42 Commits
Author SHA1 Message Date
mitchell 10648045a3 start wlvgl 2025-04-04 23:52:48 -05:00
mitchell bff0bb30dd led playback 2025-04-04 23:52:48 -05:00
mitchell 6508358ddf playback for char lcd 2025-04-04 23:52:48 -05:00
mitchell 361a14aa09 start to replay 2025-04-04 23:52:48 -05:00
mitchell 232c9ddce1 enable psram 2025-04-04 23:52:48 -05:00
mitchell 6a798e96e9 preliminary tft state tracking 2025-04-04 23:52:48 -05:00
mitchell a198ae4225 state tracking for LEDs 2025-04-04 23:52:48 -05:00
mitchell c359ecb544 state tracking for sseg 2025-04-04 23:52:48 -05:00
mitchell 4f2f0fccda impl state tracking for speaker driver 2025-04-04 23:52:48 -05:00
mitchell 579a7559c1 Add state tracking to bottom half 2025-04-04 23:52:48 -05:00
mitchell 758b16aa0d state tracking on char_lcd 2025-04-04 23:52:48 -05:00
mitchell 54ff226694 setup state tracking 2025-04-04 23:52:48 -05:00
mitchell 8cd5d09933 update game results 2025-04-04 23:52:48 -05:00
mitchell 00fa493943 rename purple to pink 2025-04-04 23:52:48 -05:00
mitchell 12eedf9722 fix LVGL screen cleaning code 2025-04-04 23:52:48 -05:00
mitchell 43b01f0b2b Clean Up calls to the leds driver 2025-04-04 23:52:48 -05:00
mitchell 295b764d40 update LED driver 2025-04-04 23:52:48 -05:00
mitchell 6530ed56c6 move other drivers 2025-04-04 23:52:48 -05:00
mitchell 83915efc33 Move tetris images to flash 2025-04-04 23:52:38 -05:00
mitchell 41113ccafe more speaker driver updates 2025-03-26 04:56:57 -05:00
mitchell cc8dcfacb3 WE HAVE A GOOD SPEAKER DRIVER!!!! 2025-03-26 03:47:06 -05:00
mitchell 62b82eba2b sort of working.... 2025-03-26 01:52:42 -05:00
mitchell babe2f828e Preliminary speaker driver changes 2025-03-25 23:49:46 -05:00
mitchell 42aa5fa315 small tweaks to drivers, starting speaker refactor 2025-03-25 21:42:10 -05:00
mitchell ab7148be42 rename functions 2025-03-25 21:20:19 -05:00
mitchell 3806fd7ee8 Support switch touching 2025-03-25 19:44:19 -05:00
mitchell 5bb6b05002 updates to bottom half code and "debug switches" helper 2025-03-25 19:27:20 -05:00
mitchell b594d6fcb3 refactor and doc for bottom_half.cpp and others 2025-03-25 18:11:33 -05:00
mitchell af93abb8cb Refactor char_lcd functions 2025-03-25 17:16:54 -05:00
mitchell 7e00a6d950 update sd card code 2025-03-25 16:26:31 -05:00
mitchell beb7f0bfb9 Directly pull in the i2c_lcd driver 2025-03-18 12:32:35 -05:00
drake 1343618729 step 5 fixes 2024-12-28 17:56:04 -06:00
drake a6f435216a power screen star code 2024-12-28 17:44:54 -06:00
mitchell a4cf115bd6 Update Wires and Tetris time 2024-12-28 17:18:02 -06:00
mitchell 06dbb8155e Add constants 2024-09-22 22:05:08 -05:00
mitchell 7d2ddcbbdd remove debugging logs 2024-09-22 21:08:40 -05:00
mitchell 14d40633f2 add power guage support 2024-09-20 23:55:01 -05:00
mitchell 3561117a56 integrate the tft driver into the code 2024-09-18 17:14:24 -05:00
mitchell fd351d0934 fix warnings 2024-08-28 17:59:29 -05:00
mitchell e54f3b469d suppress unused warning on TAG 2024-08-28 17:56:43 -05:00
mitchell 0b816aca68 fix warnings 2024-08-28 17:50:26 -05:00
mitchell afdbbeb233 change set_game_time 2024-08-28 17:27:43 -05:00
83 changed files with 6777 additions and 1198 deletions
+12 -46
View File
@@ -1,53 +1,19 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | Linux |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | ----- |
# BLK_BOX_TC
# Hello World Example
ESP-IDF version `v5.3.2`
Starts a FreeRTOS task to print "Hello World".
Firmware for the BLK_BOX Top control board for the puzzle `PDE001`.
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## Resources
## How to use example
All the files in the `resources/` folder should be loaded onto a micro SD card placed in the BLK_BOX.
Follow detailed instructions provided specifically for this example.
Developer Note: You can convert mp3 files to 44100Hz mono signed 16 uncompressed .wav files with the following command:
```ffmpeg -i input.mp3 -ac 1 -ar 44100 -sample_fmt s16 output.wav```
Select the instructions depending on Espressif chip installed on your development board:
File names must be no longer than `8` characters not including the extention
File extentions must be no longer than `3` characters.
- [ESP32 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/index.html)
- [ESP32-S2 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html)
## Example folder contents
The project **hello_world** contains one source file in C language [hello_world_main.c](main/hello_world_main.c). The file is located in folder [main](main).
ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt` files that provide set of directives and instructions describing the project's source files and targets (executable, library, or both).
Below is short explanation of remaining files in the project folder.
```
├── CMakeLists.txt
├── pytest_hello_world.py Python script used for automated testing
├── main
│ ├── CMakeLists.txt
│ └── hello_world_main.c
└── README.md This is the file you are currently reading
```
For more information on structure and contents of ESP-IDF projects, please refer to Section [Build System](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html) of the ESP-IDF Programming Guide.
## Troubleshooting
* Program upload failure
* Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs.
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
## Technical support and feedback
Please use the following feedback channels:
* For technical queries, go to the [esp32.com](https://esp32.com/) forum
* For a feature request or bug report, create a [GitHub issue](https://github.com/espressif/esp-idf/issues)
We will get back to you as soon as possible.
To build images, use the lvgl image converter [`https://lvgl.io/tools/imageconverter`].
Use v8.
I have had the best luck with `CF_RGB565A8`.
+8
View File
@@ -0,0 +1,8 @@
menu "BLK_BOX Config"
config USE_NEW_DISPLAY
bool "use new TFT display"
default y
help
Whether or not you have a new TFT display.
Incorrectly selecting may result in wrong colors.
endmenu
+7
View File
@@ -1,15 +1,22 @@
set(SOURCES
"all.cpp"
"TM1640/TM16xx.cpp"
"TM1640/TM1640.cpp"
"SparkFunBQ27441/SparkFunBQ27441.cpp"
"esp_lcd_ili9488/esp_lcd_ili9488.c"
"bottom_half.cpp"
"char_lcd.cpp"
"game_timer.cpp"
"i2c_lcd_pcf8574.c"
"leds.cpp"
"power.cpp"
"sd.cpp"
"speaker.cpp"
"sseg.cpp"
"state_tracking.cpp"
"tft.cpp"
"wires.cpp"
"wlvgl.cpp"
)
target_sources(${COMPONENT_LIB} PRIVATE ${SOURCES})
@@ -0,0 +1,186 @@
// Modified or adapted from https://github.com/sparkfun/SparkFun_BQ27441_Arduino_Library
//
// Originally Licensed under the MIT
/*
The MIT License (MIT)
Copyright (c) 2016 SparkFun Electronics, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/******************************************************************************
BQ27441_Definitions.h
BQ27441 LiPo Fuel Gauge Definitions
Jim Lindblom @ SparkFun Electronics
May 9, 2016
https://github.com/sparkfun/SparkFun_BQ27441_Arduino_Library
BQ27441 hardware constants, register addresses, and bit positions.
Hardware Resources:
- Arduino Development Board
- SparkFun Battery Babysitter
Development environment specifics:
Arduino 1.6.7
SparkFun Battery Babysitter v1.0
Arduino Uno (any 'duino should do)
******************************************************************************/
#define BQ72441_I2C_ADDRESS 0x55 // Default I2C address of the BQ27441-G1A
///////////////////////
// General Constants //
///////////////////////
#define BQ27441_UNSEAL_KEY 0x8000 // Secret code to unseal the BQ27441-G1A
#define BQ27441_DEVICE_ID 0x0421 // Default device ID
///////////////////////
// Standard Commands //
///////////////////////
// The fuel gauge uses a series of 2-byte standard commands to enable system
// reading and writing of battery information. Each command has an associated
// sequential command-code pair.
#define BQ27441_COMMAND_CONTROL 0x00 // Control()
#define BQ27441_COMMAND_TEMP 0x02 // Temperature()
#define BQ27441_COMMAND_VOLTAGE 0x04 // Voltage()
#define BQ27441_COMMAND_FLAGS 0x06 // Flags()
#define BQ27441_COMMAND_NOM_CAPACITY 0x08 // NominalAvailableCapacity()
#define BQ27441_COMMAND_AVAIL_CAPACITY 0x0A // FullAvailableCapacity()
#define BQ27441_COMMAND_REM_CAPACITY 0x0C // RemainingCapacity()
#define BQ27441_COMMAND_FULL_CAPACITY 0x0E // FullChargeCapacity()
#define BQ27441_COMMAND_AVG_CURRENT 0x10 // AverageCurrent()
#define BQ27441_COMMAND_STDBY_CURRENT 0x12 // StandbyCurrent()
#define BQ27441_COMMAND_MAX_CURRENT 0x14 // MaxLoadCurrent()
#define BQ27441_COMMAND_AVG_POWER 0x18 // AveragePower()
#define BQ27441_COMMAND_SOC 0x1C // StateOfCharge()
#define BQ27441_COMMAND_INT_TEMP 0x1E // InternalTemperature()
#define BQ27441_COMMAND_SOH 0x20 // StateOfHealth()
#define BQ27441_COMMAND_REM_CAP_UNFL 0x28 // RemainingCapacityUnfiltered()
#define BQ27441_COMMAND_REM_CAP_FIL 0x2A // RemainingCapacityFiltered()
#define BQ27441_COMMAND_FULL_CAP_UNFL 0x2C // FullChargeCapacityUnfiltered()
#define BQ27441_COMMAND_FULL_CAP_FIL 0x2E // FullChargeCapacityFiltered()
#define BQ27441_COMMAND_SOC_UNFL 0x30 // StateOfChargeUnfiltered()
//////////////////////////
// Control Sub-commands //
//////////////////////////
// Issuing a Control() command requires a subsequent 2-byte subcommand. These
// additional bytes specify the particular control function desired. The
// Control() command allows the system to control specific features of the fuel
// gauge during normal operation and additional features when the device is in
// different access modes.
#define BQ27441_CONTROL_STATUS 0x00
#define BQ27441_CONTROL_DEVICE_TYPE 0x01
#define BQ27441_CONTROL_FW_VERSION 0x02
#define BQ27441_CONTROL_DM_CODE 0x04
#define BQ27441_CONTROL_PREV_MACWRITE 0x07
#define BQ27441_CONTROL_CHEM_ID 0x08
#define BQ27441_CONTROL_BAT_INSERT 0x0C
#define BQ27441_CONTROL_BAT_REMOVE 0x0D
#define BQ27441_CONTROL_SET_HIBERNATE 0x11
#define BQ27441_CONTROL_CLEAR_HIBERNATE 0x12
#define BQ27441_CONTROL_SET_CFGUPDATE 0x13
#define BQ27441_CONTROL_SHUTDOWN_ENABLE 0x1B
#define BQ27441_CONTROL_SHUTDOWN 0x1C
#define BQ27441_CONTROL_SEALED 0x20
#define BQ27441_CONTROL_PULSE_SOC_INT 0x23
#define BQ27441_CONTROL_RESET 0x41
#define BQ27441_CONTROL_SOFT_RESET 0x42
#define BQ27441_CONTROL_EXIT_CFGUPDATE 0x43
#define BQ27441_CONTROL_EXIT_RESIM 0x44
///////////////////////////////////////////
// Control Status Word - Bit Definitions //
///////////////////////////////////////////
// Bit positions for the 16-bit data of CONTROL_STATUS.
// CONTROL_STATUS instructs the fuel gauge to return status information to
// Control() addresses 0x00 and 0x01. The read-only status word contains status
// bits that are set or cleared either automatically as conditions warrant or
// through using specified subcommands.
#define BQ27441_STATUS_SHUTDOWNEN (1<<15)
#define BQ27441_STATUS_WDRESET (1<<14)
#define BQ27441_STATUS_SS (1<<13)
#define BQ27441_STATUS_CALMODE (1<<12)
#define BQ27441_STATUS_CCA (1<<11)
#define BQ27441_STATUS_BCA (1<<10)
#define BQ27441_STATUS_QMAX_UP (1<<9)
#define BQ27441_STATUS_RES_UP (1<<8)
#define BQ27441_STATUS_INITCOMP (1<<7)
#define BQ27441_STATUS_HIBERNATE (1<<6)
#define BQ27441_STATUS_SLEEP (1<<4)
#define BQ27441_STATUS_LDMD (1<<3)
#define BQ27441_STATUS_RUP_DIS (1<<2)
#define BQ27441_STATUS_VOK (1<<1)
////////////////////////////////////
// Flag Command - Bit Definitions //
////////////////////////////////////
// Bit positions for the 16-bit data of Flags()
// This read-word function returns the contents of the fuel gauging status
// register, depicting the current operating status.
#define BQ27441_FLAG_OT (1<<15)
#define BQ27441_FLAG_UT (1<<14)
#define BQ27441_FLAG_FC (1<<9)
#define BQ27441_FLAG_CHG (1<<8)
#define BQ27441_FLAG_OCVTAKEN (1<<7)
#define BQ27441_FLAG_ITPOR (1<<5)
#define BQ27441_FLAG_CFGUPMODE (1<<4)
#define BQ27441_FLAG_BAT_DET (1<<3)
#define BQ27441_FLAG_SOC1 (1<<2)
#define BQ27441_FLAG_SOCF (1<<1)
#define BQ27441_FLAG_DSG (1<<0)
////////////////////////////
// Extended Data Commands //
////////////////////////////
// Extended data commands offer additional functionality beyond the standard
// set of commands. They are used in the same manner; however, unlike standard
// commands, extended commands are not limited to 2-byte words.
#define BQ27441_EXTENDED_OPCONFIG 0x3A // OpConfig()
#define BQ27441_EXTENDED_CAPACITY 0x3C // DesignCapacity()
#define BQ27441_EXTENDED_DATACLASS 0x3E // DataClass()
#define BQ27441_EXTENDED_DATABLOCK 0x3F // DataBlock()
#define BQ27441_EXTENDED_BLOCKDATA 0x40 // BlockData()
#define BQ27441_EXTENDED_CHECKSUM 0x60 // BlockDataCheckSum()
#define BQ27441_EXTENDED_CONTROL 0x61 // BlockDataControl()
////////////////////////////////////////
// Configuration Class, Subclass ID's //
////////////////////////////////////////
// To access a subclass of the extended data, set the DataClass() function
// with one of these values.
// Configuration Classes
#define BQ27441_ID_SAFETY 2 // Safety
#define BQ27441_ID_CHG_TERMINATION 36 // Charge Termination
#define BQ27441_ID_CONFIG_DATA 48 // Data
#define BQ27441_ID_DISCHARGE 49 // Discharge
#define BQ27441_ID_REGISTERS 64 // Registers
#define BQ27441_ID_POWER 68 // Power
// Gas Gauging Classes
#define BQ27441_ID_IT_CFG 80 // IT Cfg
#define BQ27441_ID_CURRENT_THRESH 81 // Current Thresholds
#define BQ27441_ID_STATE 82 // State
// Ra Tables Classes
#define BQ27441_ID_R_A_RAM 89 // R_a RAM
// Calibration Classes
#define BQ27441_ID_CALIB_DATA 104 // Data
#define BQ27441_ID_CC_CAL 105 // CC Cal
#define BQ27441_ID_CURRENT 107 // Current
// Security Classes
#define BQ27441_ID_CODES 112 // Codes
/////////////////////////////////////////
// OpConfig Register - Bit Definitions //
/////////////////////////////////////////
// Bit positions of the OpConfig Register
#define BQ27441_OPCONFIG_BIE (1<<13)
#define BQ27441_OPCONFIG_BI_PU_EN (1<<12)
#define BQ27441_OPCONFIG_GPIOPOL (1<<11)
#define BQ27441_OPCONFIG_SLEEP (1<<5)
#define BQ27441_OPCONFIG_RMFCC (1<<4)
#define BQ27441_OPCONFIG_BATLOWEN (1<<2)
#define BQ27441_OPCONFIG_TEMPS (1<<0)
@@ -0,0 +1,734 @@
// Modified or adapted from https://github.com/sparkfun/SparkFun_BQ27441_Arduino_Library
//
// Originally Licensed under the MIT
/*
The MIT License (MIT)
Copyright (c) 2016 SparkFun Electronics, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/******************************************************************************
SparkFunBQ27441.cpp
BQ27441 Arduino Library Main Source File
Jim Lindblom @ SparkFun Electronics
May 9, 2016
https://github.com/sparkfun/SparkFun_BQ27441_Arduino_Library
Implementation of all features of the BQ27441 LiPo Fuel Gauge.
Hardware Resources:
- Arduino Development Board
- SparkFun Battery Babysitter
Development environment specifics:
Arduino 1.6.7
SparkFun Battery Babysitter v1.0
Arduino Uno (any 'duino should do)
******************************************************************************/
#include "SparkFunBQ27441.h"
/*****************************************************************************
************************** Initialization Functions *************************
*****************************************************************************/
// Initializes class variables
BQ27441::BQ27441() : _deviceAddress(BQ72441_I2C_ADDRESS), _sealFlag(false), _userConfigControl(false)
{
}
static uint8_t constrain(uint8_t x, uint8_t min, uint8_t max) {
if (x < min) return min;
if (x > max) return max;
return x;
}
// Initializes I2C and verifies communication with the BQ27441.
bool BQ27441::begin(void)
{
uint16_t deviceID = 0;
// Assume the I2C is already initialized from other things
deviceID = deviceType(); // Read deviceType from BQ27441
if (deviceID == BQ27441_DEVICE_ID)
{
return true; // If device ID is valid, return true
}
return false; // Otherwise return false
}
// Configures the design capacity of the connected battery.
bool BQ27441::setCapacity(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
// Unit: mAh
uint8_t capMSB = capacity >> 8;
uint8_t capLSB = capacity & 0x00FF;
uint8_t capacityData[2] = {capMSB, capLSB};
return writeExtendedData(BQ27441_ID_STATE, 10, capacityData, 2);
}
// Configures the design energy of the connected battery.
bool BQ27441::setDesignEnergy(uint16_t energy)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0C (12)
// Design energy is a 2-byte piece of data - MSB first
// Unit: mWh
uint8_t enMSB = energy >> 8;
uint8_t enLSB = energy & 0x00FF;
uint8_t energyData[2] = {enMSB, enLSB};
return writeExtendedData(BQ27441_ID_STATE, 12, energyData, 2);
}
// Configures the terminate voltage.
bool BQ27441::setTerminateVoltage(uint16_t voltage)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0F (16)
// Termiante voltage is a 2-byte piece of data - MSB first
// Unit: mV
// Min 2500, Max 3700
if(voltage<2500) voltage=2500;
if(voltage>3700) voltage=3700;
uint8_t tvMSB = voltage >> 8;
uint8_t tvLSB = voltage & 0x00FF;
uint8_t tvData[2] = {tvMSB, tvLSB};
return writeExtendedData(BQ27441_ID_STATE, 16, tvData, 2);
}
// Configures taper rate of connected battery.
bool BQ27441::setTaperRate(uint16_t rate)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x1B (27)
// Termiante voltage is a 2-byte piece of data - MSB first
// Unit: 0.1h
// Max 2000
if(rate>2000) rate=2000;
uint8_t trMSB = rate >> 8;
uint8_t trLSB = rate & 0x00FF;
uint8_t trData[2] = {trMSB, trLSB};
return writeExtendedData(BQ27441_ID_STATE, 27, trData, 2);
}
/*****************************************************************************
********************** Battery Characteristics Functions ********************
*****************************************************************************/
// Reads and returns the battery voltage
uint16_t BQ27441::voltage(void)
{
return readWord(BQ27441_COMMAND_VOLTAGE);
}
// Reads and returns the specified current measurement
int16_t BQ27441::current(current_measure type)
{
int16_t current = 0;
switch (type)
{
case AVG:
current = (int16_t) readWord(BQ27441_COMMAND_AVG_CURRENT);
break;
case STBY:
current = (int16_t) readWord(BQ27441_COMMAND_STDBY_CURRENT);
break;
case MAX:
current = (int16_t) readWord(BQ27441_COMMAND_MAX_CURRENT);
break;
}
return current;
}
// Reads and returns the specified capacity measurement
uint16_t BQ27441::capacity(capacity_measure type)
{
uint16_t capacity = 0;
switch (type)
{
case REMAIN:
return readWord(BQ27441_COMMAND_REM_CAPACITY);
break;
case FULL:
return readWord(BQ27441_COMMAND_FULL_CAPACITY);
break;
case AVAIL:
capacity = readWord(BQ27441_COMMAND_NOM_CAPACITY);
break;
case AVAIL_FULL:
capacity = readWord(BQ27441_COMMAND_AVAIL_CAPACITY);
break;
case REMAIN_F:
capacity = readWord(BQ27441_COMMAND_REM_CAP_FIL);
break;
case REMAIN_UF:
capacity = readWord(BQ27441_COMMAND_REM_CAP_UNFL);
break;
case FULL_F:
capacity = readWord(BQ27441_COMMAND_FULL_CAP_FIL);
break;
case FULL_UF:
capacity = readWord(BQ27441_COMMAND_FULL_CAP_UNFL);
break;
case DESIGN:
capacity = readWord(BQ27441_EXTENDED_CAPACITY);
}
return capacity;
}
// Reads and returns measured average power
int16_t BQ27441::power(void)
{
return (int16_t) readWord(BQ27441_COMMAND_AVG_POWER);
}
// Reads and returns specified state of charge measurement
uint16_t BQ27441::soc(soc_measure type)
{
uint16_t socRet = 0;
switch (type)
{
case FILTERED:
socRet = readWord(BQ27441_COMMAND_SOC);
break;
case UNFILTERED:
socRet = readWord(BQ27441_COMMAND_SOC_UNFL);
break;
}
return socRet;
}
// Reads and returns specified state of health measurement
uint8_t BQ27441::soh(soh_measure type)
{
uint16_t sohRaw = readWord(BQ27441_COMMAND_SOH);
uint8_t sohStatus = sohRaw >> 8;
uint8_t sohPercent = sohRaw & 0x00FF;
if (type == PERCENT)
return sohPercent;
else
return sohStatus;
}
// Reads and returns specified temperature measurement
uint16_t BQ27441::temperature(temp_measure type)
{
uint16_t temp = 0;
switch (type)
{
case BATTERY:
temp = readWord(BQ27441_COMMAND_TEMP);
break;
case INTERNAL_TEMP:
temp = readWord(BQ27441_COMMAND_INT_TEMP);
break;
}
return temp;
}
/*****************************************************************************
************************** GPOUT Control Functions **************************
*****************************************************************************/
// Get GPOUT polarity setting (active-high or active-low)
bool BQ27441::GPOUTPolarity(void)
{
uint16_t opConfigRegister = opConfig();
return (opConfigRegister & BQ27441_OPCONFIG_GPIOPOL);
}
// Set GPOUT polarity to active-high or active-low
bool BQ27441::setGPOUTPolarity(bool activeHigh)
{
uint16_t oldOpConfig = opConfig();
// Check to see if we need to update opConfig:
if ((activeHigh && (oldOpConfig & BQ27441_OPCONFIG_GPIOPOL)) ||
(!activeHigh && !(oldOpConfig & BQ27441_OPCONFIG_GPIOPOL)))
return true;
uint16_t newOpConfig = oldOpConfig;
if (activeHigh)
newOpConfig |= BQ27441_OPCONFIG_GPIOPOL;
else
newOpConfig &= ~(BQ27441_OPCONFIG_GPIOPOL);
return writeOpConfig(newOpConfig);
}
// Get GPOUT function (BAT_LOW or SOC_INT)
bool BQ27441::GPOUTFunction(void)
{
uint16_t opConfigRegister = opConfig();
return (opConfigRegister & BQ27441_OPCONFIG_BATLOWEN);
}
// Set GPOUT function to BAT_LOW or SOC_INT
bool BQ27441::setGPOUTFunction(gpout_function function)
{
uint16_t oldOpConfig = opConfig();
// Check to see if we need to update opConfig:
if ((function && (oldOpConfig & BQ27441_OPCONFIG_BATLOWEN)) ||
(!function && !(oldOpConfig & BQ27441_OPCONFIG_BATLOWEN)))
return true;
// Modify BATLOWN_EN bit of opConfig:
uint16_t newOpConfig = oldOpConfig;
if (function)
newOpConfig |= BQ27441_OPCONFIG_BATLOWEN;
else
newOpConfig &= ~(BQ27441_OPCONFIG_BATLOWEN);
// Write new opConfig
return writeOpConfig(newOpConfig);
}
// Get SOC1_Set Threshold - threshold to set the alert flag
uint8_t BQ27441::SOC1SetThreshold(void)
{
return readExtendedData(BQ27441_ID_DISCHARGE, 0);
}
// Get SOC1_Clear Threshold - threshold to clear the alert flag
uint8_t BQ27441::SOC1ClearThreshold(void)
{
return readExtendedData(BQ27441_ID_DISCHARGE, 1);
}
// Set the SOC1 set and clear thresholds to a percentage
bool BQ27441::setSOC1Thresholds(uint8_t set, uint8_t clear)
{
uint8_t thresholds[2];
thresholds[0] = constrain(set, 0, 100);
thresholds[1] = constrain(clear, 0, 100);
return writeExtendedData(BQ27441_ID_DISCHARGE, 0, thresholds, 2);
}
// Get SOCF_Set Threshold - threshold to set the alert flag
uint8_t BQ27441::SOCFSetThreshold(void)
{
return readExtendedData(BQ27441_ID_DISCHARGE, 2);
}
// Get SOCF_Clear Threshold - threshold to clear the alert flag
uint8_t BQ27441::SOCFClearThreshold(void)
{
return readExtendedData(BQ27441_ID_DISCHARGE, 3);
}
// Set the SOCF set and clear thresholds to a percentage
bool BQ27441::setSOCFThresholds(uint8_t set, uint8_t clear)
{
uint8_t thresholds[2];
thresholds[0] = constrain(set, 0, 100);
thresholds[1] = constrain(clear, 0, 100);
return writeExtendedData(BQ27441_ID_DISCHARGE, 2, thresholds, 2);
}
// Check if the SOC1 flag is set
bool BQ27441::socFlag(void)
{
uint16_t flagState = flags();
return flagState & BQ27441_FLAG_SOC1;
}
// Check if the SOCF flag is set
bool BQ27441::socfFlag(void)
{
uint16_t flagState = flags();
return flagState & BQ27441_FLAG_SOCF;
}
// Check if the ITPOR flag is set
bool BQ27441::itporFlag(void)
{
uint16_t flagState = flags();
return flagState & BQ27441_FLAG_ITPOR;
}
// Check if the FC flag is set
bool BQ27441::fcFlag(void)
{
uint16_t flagState = flags();
return flagState & BQ27441_FLAG_FC;
}
// Check if the CHG flag is set
bool BQ27441::chgFlag(void)
{
uint16_t flagState = flags();
return flagState & BQ27441_FLAG_CHG;
}
// Check if the DSG flag is set
bool BQ27441::dsgFlag(void)
{
uint16_t flagState = flags();
return flagState & BQ27441_FLAG_DSG;
}
// Get the SOC_INT interval delta
uint8_t BQ27441::sociDelta(void)
{
return readExtendedData(BQ27441_ID_STATE, 26);
}
// Set the SOC_INT interval delta to a value between 1 and 100
bool BQ27441::setSOCIDelta(uint8_t delta)
{
uint8_t soci = constrain(delta, 0, 100);
return writeExtendedData(BQ27441_ID_STATE, 26, &soci, 1);
}
// Pulse the GPOUT pin - must be in SOC_INT mode
bool BQ27441::pulseGPOUT(void)
{
return executeControlWord(BQ27441_CONTROL_PULSE_SOC_INT);
}
/*****************************************************************************
*************************** Control Sub-Commands ****************************
*****************************************************************************/
// Read the device type - should be 0x0421
uint16_t BQ27441::deviceType(void)
{
return readControlWord(BQ27441_CONTROL_DEVICE_TYPE);
}
// Enter configuration mode - set userControl if calling from an Arduino sketch
// and you want control over when to exitConfig
bool BQ27441::enterConfig(bool userControl)
{
if (userControl) _userConfigControl = true;
if (sealed())
{
_sealFlag = true;
unseal(); // Must be unsealed before making changes
}
if (executeControlWord(BQ27441_CONTROL_SET_CFGUPDATE))
{
int16_t timeout = BQ72441_I2C_TIMEOUT;
while ((timeout--) && (!(flags() & BQ27441_FLAG_CFGUPMODE)))
vTaskDelay(pdMS_TO_TICKS(1));
if (timeout > 0)
return true;
}
return false;
}
// Exit configuration mode with the option to perform a resimulation
bool BQ27441::exitConfig(bool resim)
{
// There are two methods for exiting config mode:
// 1. Execute the EXIT_CFGUPDATE command
// 2. Execute the SOFT_RESET command
// EXIT_CFGUPDATE exits config mode _without_ an OCV (open-circuit voltage)
// measurement, and without resimulating to update unfiltered-SoC and SoC.
// If a new OCV measurement or resimulation is desired, SOFT_RESET or
// EXIT_RESIM should be used to exit config mode.
if (resim)
{
if (softReset())
{
int16_t timeout = BQ72441_I2C_TIMEOUT;
while ((timeout--) && ((flags() & BQ27441_FLAG_CFGUPMODE)))
vTaskDelay(pdMS_TO_TICKS(1));
if (timeout > 0)
{
if (_sealFlag) seal(); // Seal back up if we IC was sealed coming in
return true;
}
}
return false;
}
else
{
return executeControlWord(BQ27441_CONTROL_EXIT_CFGUPDATE);
}
}
// Read the flags() command
uint16_t BQ27441::flags(void)
{
return readWord(BQ27441_COMMAND_FLAGS);
}
// Read the CONTROL_STATUS subcommand of control()
uint16_t BQ27441::status(void)
{
return readControlWord(BQ27441_CONTROL_STATUS);
}
/***************************** Private Functions *****************************/
// Check if the BQ27441-G1A is sealed or not.
bool BQ27441::sealed(void)
{
uint16_t stat = status();
return stat & BQ27441_STATUS_SS;
}
// Seal the BQ27441-G1A
bool BQ27441::seal(void)
{
return readControlWord(BQ27441_CONTROL_SEALED);
}
// UNseal the BQ27441-G1A
bool BQ27441::unseal(void)
{
// To unseal the BQ27441, write the key to the control
// command. Then immediately write the same key to control again.
if (readControlWord(BQ27441_UNSEAL_KEY))
{
return readControlWord(BQ27441_UNSEAL_KEY);
}
return false;
}
// Read the 16-bit opConfig register from extended data
uint16_t BQ27441::opConfig(void)
{
return readWord(BQ27441_EXTENDED_OPCONFIG);
}
// Write the 16-bit opConfig register in extended data
bool BQ27441::writeOpConfig(uint16_t value)
{
uint8_t opConfigMSB = value >> 8;
uint8_t opConfigLSB = value & 0x00FF;
uint8_t opConfigData[2] = {opConfigMSB, opConfigLSB};
// OpConfig register location: BQ27441_ID_REGISTERS id, offset 0
return writeExtendedData(BQ27441_ID_REGISTERS, 0, opConfigData, 2);
}
// Issue a soft-reset to the BQ27441-G1A
bool BQ27441::softReset(void)
{
return executeControlWord(BQ27441_CONTROL_SOFT_RESET);
}
// Read a 16-bit command word from the BQ27441-G1A
uint16_t BQ27441::readWord(uint16_t subAddress)
{
uint8_t data[2];
i2cReadBytes(subAddress, data, 2);
return ((uint16_t) data[1] << 8) | data[0];
}
// Read a 16-bit subcommand() from the BQ27441-G1A's control()
uint16_t BQ27441::readControlWord(uint16_t function)
{
uint8_t subCommandMSB = (function >> 8);
uint8_t subCommandLSB = (function & 0x00FF);
uint8_t command[3] = {0, subCommandLSB, subCommandMSB};
uint8_t data[2] = {0, 0};
i2cWriteBytes((uint8_t) 0, command, 2);
if (i2cReadBytes((uint8_t) 0, data, 2))
{
return ((uint16_t)data[1] << 8) | data[0];
}
return false;
}
// Execute a subcommand() from the BQ27441-G1A's control()
bool BQ27441::executeControlWord(uint16_t function)
{
uint8_t subCommandMSB = (function >> 8);
uint8_t subCommandLSB = (function & 0x00FF);
uint8_t command[2] = {subCommandLSB, subCommandMSB};
if (i2cWriteBytes((uint8_t) 0, command, 2))
return true;
return false;
}
/*****************************************************************************
************************** Extended Data Commands ***************************
*****************************************************************************/
// Issue a BlockDataControl() command to enable BlockData access
bool BQ27441::blockDataControl(void)
{
uint8_t enableByte = 0x00;
return i2cWriteBytes(BQ27441_EXTENDED_CONTROL, &enableByte, 1);
}
// Issue a DataClass() command to set the data class to be accessed
bool BQ27441::blockDataClass(uint8_t id)
{
return i2cWriteBytes(BQ27441_EXTENDED_DATACLASS, &id, 1);
}
// Issue a DataBlock() command to set the data block to be accessed
bool BQ27441::blockDataOffset(uint8_t offset)
{
return i2cWriteBytes(BQ27441_EXTENDED_DATABLOCK, &offset, 1);
}
// Read the current checksum using BlockDataCheckSum()
uint8_t BQ27441::blockDataChecksum(void)
{
uint8_t csum;
i2cReadBytes(BQ27441_EXTENDED_CHECKSUM, &csum, 1);
return csum;
}
// Use BlockData() to read a byte from the loaded extended data
uint8_t BQ27441::readBlockData(uint8_t offset)
{
uint8_t ret;
uint8_t address = offset + BQ27441_EXTENDED_BLOCKDATA;
i2cReadBytes(address, &ret, 1);
return ret;
}
// Use BlockData() to write a byte to an offset of the loaded data
bool BQ27441::writeBlockData(uint8_t offset, uint8_t data)
{
uint8_t address = offset + BQ27441_EXTENDED_BLOCKDATA;
return i2cWriteBytes(address, &data, 1);
}
// Read all 32 bytes of the loaded extended data and compute a
// checksum based on the values.
uint8_t BQ27441::computeBlockChecksum(void)
{
uint8_t data[32];
i2cReadBytes(BQ27441_EXTENDED_BLOCKDATA, data, 32);
uint8_t csum = 0;
for (int i=0; i<32; i++)
{
csum += data[i];
}
csum = 255 - csum;
return csum;
}
// Use the BlockDataCheckSum() command to write a checksum value
bool BQ27441::writeBlockChecksum(uint8_t csum)
{
return i2cWriteBytes(BQ27441_EXTENDED_CHECKSUM, &csum, 1);
}
// Read a byte from extended data specifying a class ID and position offset
uint8_t BQ27441::readExtendedData(uint8_t classID, uint8_t offset)
{
uint8_t retData = 0;
if (!_userConfigControl) enterConfig(false);
if (!blockDataControl()) // // enable block data memory control
return false; // Return false if enable fails
if (!blockDataClass(classID)) // Write class ID using DataBlockClass()
return false;
blockDataOffset(offset / 32); // Write 32-bit block offset (usually 0)
computeBlockChecksum(); // Compute checksum going in
retData = readBlockData(offset % 32); // Read from offset (limit to 0-31)
if (!_userConfigControl) exitConfig();
return retData;
}
// Write a specified number of bytes to extended data specifying a
// class ID, position offset.
bool BQ27441::writeExtendedData(uint8_t classID, uint8_t offset, uint8_t * data, uint8_t len)
{
if (len > 32)
return false;
if (!_userConfigControl) enterConfig(false);
if (!blockDataControl()) // // enable block data memory control
return false; // Return false if enable fails
if (!blockDataClass(classID)) // Write class ID using DataBlockClass()
return false;
blockDataOffset(offset / 32); // Write 32-bit block offset (usually 0)
computeBlockChecksum(); // Compute checksum going in
// Write data bytes:
for (int i = 0; i < len; i++)
{
// Write to offset, mod 32 if offset is greater than 32
// The blockDataOffset above sets the 32-bit block
writeBlockData((offset % 32) + i, data[i]);
}
// Write new checksum using BlockDataChecksum (0x60)
uint8_t newCsum = computeBlockChecksum(); // Compute the new checksum
writeBlockChecksum(newCsum);
if (!_userConfigControl) exitConfig();
return true;
}
/*****************************************************************************
************************ I2C Read and Write Routines ************************
*****************************************************************************/
// Read a specified number of bytes over I2C at a given subAddress
int16_t BQ27441::i2cReadBytes(uint8_t subAddress, uint8_t * dest, uint8_t count)
{
int16_t timeout = BQ72441_I2C_TIMEOUT;
i2c_master_write_read_device(BQ72441_I2C_NUM, _deviceAddress, &subAddress, 1, dest, count, timeout);
return timeout;
}
// Write a specified number of bytes over I2C to a given subAddress
uint16_t BQ27441::i2cWriteBytes(uint8_t subAddress, uint8_t * src, uint8_t count)
{
int16_t timeout = BQ72441_I2C_TIMEOUT;
// prepend the subAddress to the data.
uint8_t w_buff[count+1] = {0};
w_buff[0] = subAddress;
for (int i = 0; i < count; i ++) {
w_buff[i+1] = src[i];
}
esp_err_t ret = i2c_master_write_to_device(BQ72441_I2C_NUM, _deviceAddress, src, count+1, timeout);
return ret == ESP_OK;
}
BQ27441 lipo;
@@ -0,0 +1,564 @@
// Modified or adapted from https://github.com/sparkfun/SparkFun_BQ27441_Arduino_Library
//
// Originally Licensed under the MIT
/*
The MIT License (MIT)
Copyright (c) 2016 SparkFun Electronics, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/******************************************************************************
SparkFunBQ27441.h
BQ27441 Arduino Library Main Header File
Jim Lindblom @ SparkFun Electronics
May 9, 2016
https://github.com/sparkfun/SparkFun_BQ27441_Arduino_Library
Definition of the BQ27441 library, which implements all features of the
BQ27441 LiPo Fuel Gauge.
Hardware Resources:
- Arduino Development Board
- SparkFun Battery Babysitter
Development environment specifics:
Arduino 1.6.7
SparkFun Battery Babysitter v1.0
Arduino Uno (any 'duino should do)
******************************************************************************/
#ifndef SparkFunBQ27441_h
#define SparkFunBQ27441_h
#include "BQ27441_Definitions.h"
#include <stdint.h>
#include "driver/i2c.h"
#define BQ72441_I2C_NUM I2C_NUM_0
#define BQ72441_I2C_TIMEOUT 2000
// Parameters for the current() function, to specify which current to read
typedef enum {
AVG, // Average Current (DEFAULT)
STBY, // Standby Current
MAX // Max Current
} current_measure;
// Parameters for the capacity() function, to specify which capacity to read
typedef enum {
REMAIN, // Remaining Capacity (DEFAULT)
FULL, // Full Capacity
AVAIL, // Available Capacity
AVAIL_FULL, // Full Available Capacity
REMAIN_F, // Remaining Capacity Filtered
REMAIN_UF, // Remaining Capacity Unfiltered
FULL_F, // Full Capacity Filtered
FULL_UF, // Full Capacity Unfiltered
DESIGN // Design Capacity
} capacity_measure;
// Parameters for the soc() function
typedef enum {
FILTERED, // State of Charge Filtered (DEFAULT)
UNFILTERED // State of Charge Unfiltered
} soc_measure;
// Parameters for the soh() function
typedef enum {
PERCENT, // State of Health Percentage (DEFAULT)
SOH_STAT // State of Health Status Bits
} soh_measure;
// Parameters for the temperature() function
typedef enum {
BATTERY, // Battery Temperature (DEFAULT)
INTERNAL_TEMP // Internal IC Temperature
} temp_measure;
// Parameters for the setGPOUTFunction() funciton
typedef enum {
SOC_INT, // Set GPOUT to SOC_INT functionality
BAT_LOW // Set GPOUT to BAT_LOW functionality
} gpout_function;
class BQ27441 {
public:
//////////////////////////////
// Initialization Functions //
//////////////////////////////
/**
Initializes class variables
*/
BQ27441();
/**
Initializes I2C and verifies communication with the BQ27441.
Must be called before using any other functions.
@return true if communication was successful.
*/
bool begin(void);
/**
Configures the design capacity of the connected battery.
@param capacity of battery (unsigned 16-bit value)
@return true if capacity successfully set.
*/
bool setCapacity(uint16_t capacity);
/**
Configures the design energy of the connected battery.
@param energy of battery (unsigned 16-bit value)
@return true if energy successfully set.
*/
bool setDesignEnergy(uint16_t energy);
/**
Configures terminate voltage (lowest operational voltage of battery powered circuit)
@param voltage of battery (unsigned 16-bit value)
@return true if energy successfully set.
*/
bool setTerminateVoltage(uint16_t voltage);
bool setTaperRate(uint16_t rate);
/////////////////////////////
// Battery Characteristics //
/////////////////////////////
/**
Reads and returns the battery voltage
@return battery voltage in mV
*/
uint16_t voltage(void);
/**
Reads and returns the specified current measurement
@param current_measure enum specifying current value to be read
@return specified current measurement in mA. >0 indicates charging.
*/
int16_t current(current_measure type = AVG);
/**
Reads and returns the specified capacity measurement
@param capacity_measure enum specifying capacity value to be read
@return specified capacity measurement in mAh.
*/
uint16_t capacity(capacity_measure type = REMAIN);
/**
Reads and returns measured average power
@return average power in mAh. >0 indicates charging.
*/
int16_t power(void);
/**
Reads and returns specified state of charge measurement
@param soc_measure enum specifying filtered or unfiltered measurement
@return specified state of charge measurement in %
*/
uint16_t soc(soc_measure type = FILTERED);
/**
Reads and returns specified state of health measurement
@param soh_measure enum specifying filtered or unfiltered measurement
@return specified state of health measurement in %, or status bits
*/
uint8_t soh(soh_measure type = PERCENT);
/**
Reads and returns specified temperature measurement
@param temp_measure enum specifying internal or battery measurement
@return specified temperature measurement in degrees C
*/
uint16_t temperature(temp_measure type = BATTERY);
////////////////////////////
// GPOUT Control Commands //
////////////////////////////
/**
Get GPOUT polarity setting (active-high or active-low)
@return true if active-high, false if active-low
*/
bool GPOUTPolarity(void);
/**
Set GPOUT polarity to active-high or active-low
@param activeHigh is true if active-high, false if active-low
@return true on success
*/
bool setGPOUTPolarity(bool activeHigh);
/**
Get GPOUT function (BAT_LOW or SOC_INT)
@return true if BAT_LOW or false if SOC_INT
*/
bool GPOUTFunction(void);
/**
Set GPOUT function to BAT_LOW or SOC_INT
@param function should be either BAT_LOW or SOC_INT
@return true on success
*/
bool setGPOUTFunction(gpout_function function);
/**
Get SOC1_Set Threshold - threshold to set the alert flag
@return state of charge value between 0 and 100%
*/
uint8_t SOC1SetThreshold(void);
/**
Get SOC1_Clear Threshold - threshold to clear the alert flag
@return state of charge value between 0 and 100%
*/
uint8_t SOC1ClearThreshold(void);
/**
Set the SOC1 set and clear thresholds to a percentage
@param set and clear percentages between 0 and 100. clear > set.
@return true on success
*/
bool setSOC1Thresholds(uint8_t set, uint8_t clear);
/**
Get SOCF_Set Threshold - threshold to set the alert flag
@return state of charge value between 0 and 100%
*/
uint8_t SOCFSetThreshold(void);
/**
Get SOCF_Clear Threshold - threshold to clear the alert flag
@return state of charge value between 0 and 100%
*/
uint8_t SOCFClearThreshold(void);
/**
Set the SOCF set and clear thresholds to a percentage
@param set and clear percentages between 0 and 100. clear > set.
@return true on success
*/
bool setSOCFThresholds(uint8_t set, uint8_t clear);
/**
Check if the SOC1 flag is set in flags()
@return true if flag is set
*/
bool socFlag(void);
/**
Check if the SOCF flag is set in flags()
@return true if flag is set
*/
bool socfFlag(void);
/**
Check if the ITPOR flag is set in flags()
@return true if flag is set
*/
bool itporFlag(void);
/**
Check if the FC flag is set in flags()
@return true if flag is set
*/
bool fcFlag(void);
/**
Check if the CHG flag is set in flags()
@return true if flag is set
*/
bool chgFlag(void);
/**
Check if the DSG flag is set in flags()
@return true if flag is set
*/
bool dsgFlag(void);
/**
Get the SOC_INT interval delta
@return interval percentage value between 1 and 100
*/
uint8_t sociDelta(void);
/**
Set the SOC_INT interval delta to a value between 1 and 100
@param interval percentage value between 1 and 100
@return true on success
*/
bool setSOCIDelta(uint8_t delta);
/**
Pulse the GPOUT pin - must be in SOC_INT mode
@return true on success
*/
bool pulseGPOUT(void);
//////////////////////////
// Control Sub-commands //
//////////////////////////
/**
Read the device type - should be 0x0421
@return 16-bit value read from DEVICE_TYPE subcommand
*/
uint16_t deviceType(void);
/**
Enter configuration mode - set userControl if calling from an Arduino
sketch and you want control over when to exitConfig.
@param userControl is true if the Arduino sketch is handling entering
and exiting config mode (should be false in library calls).
@return true on success
*/
bool enterConfig(bool userControl = true);
/**
Exit configuration mode with the option to perform a resimulation
@param resim is true if resimulation should be performed after exiting
@return true on success
*/
bool exitConfig(bool resim = true);
/**
Read the flags() command
@return 16-bit representation of flags() command register
*/
uint16_t flags(void);
/**
Read the CONTROL_STATUS subcommand of control()
@return 16-bit representation of CONTROL_STATUS subcommand
*/
uint16_t status(void);
private:
uint8_t _deviceAddress; // Stores the BQ27441-G1A's I2C address
bool _sealFlag; // Global to identify that IC was previously sealed
bool _userConfigControl; // Global to identify that user has control over
// entering/exiting config
/**
Check if the BQ27441-G1A is sealed or not.
@return true if the chip is sealed
*/
bool sealed(void);
/**
Seal the BQ27441-G1A
@return true on success
*/
bool seal(void);
/**
UNseal the BQ27441-G1A
@return true on success
*/
bool unseal(void);
/**
Read the 16-bit opConfig register from extended data
@return opConfig register contents
*/
uint16_t opConfig(void);
/**
Write the 16-bit opConfig register in extended data
@param New 16-bit value for opConfig
@return true on success
*/
bool writeOpConfig(uint16_t value);
/**
Issue a soft-reset to the BQ27441-G1A
@return true on success
*/
bool softReset(void);
/**
Read a 16-bit command word from the BQ27441-G1A
@param subAddress is the command to be read from
@return 16-bit value of the command's contents
*/
uint16_t readWord(uint16_t subAddress);
/**
Read a 16-bit subcommand() from the BQ27441-G1A's control()
@param function is the subcommand of control() to be read
@return 16-bit value of the subcommand's contents
*/
uint16_t readControlWord(uint16_t function);
/**
Execute a subcommand() from the BQ27441-G1A's control()
@param function is the subcommand of control() to be executed
@return true on success
*/
bool executeControlWord(uint16_t function);
////////////////////////////
// Extended Data Commands //
////////////////////////////
/**
Issue a BlockDataControl() command to enable BlockData access
@return true on success
*/
bool blockDataControl(void);
/**
Issue a DataClass() command to set the data class to be accessed
@param id is the id number of the class
@return true on success
*/
bool blockDataClass(uint8_t id);
/**
Issue a DataBlock() command to set the data block to be accessed
@param offset of the data block
@return true on success
*/
bool blockDataOffset(uint8_t offset);
/**
Read the current checksum using BlockDataCheckSum()
@return true on success
*/
uint8_t blockDataChecksum(void);
/**
Use BlockData() to read a byte from the loaded extended data
@param offset of data block byte to be read
@return true on success
*/
uint8_t readBlockData(uint8_t offset);
/**
Use BlockData() to write a byte to an offset of the loaded data
@param offset is the position of the byte to be written
data is the value to be written
@return true on success
*/
bool writeBlockData(uint8_t offset, uint8_t data);
/**
Read all 32 bytes of the loaded extended data and compute a
checksum based on the values.
@return 8-bit checksum value calculated based on loaded data
*/
uint8_t computeBlockChecksum(void);
/**
Use the BlockDataCheckSum() command to write a checksum value
@param csum is the 8-bit checksum to be written
@return true on success
*/
bool writeBlockChecksum(uint8_t csum);
/**
Read a byte from extended data specifying a class ID and position offset
@param classID is the id of the class to be read from
offset is the byte position of the byte to be read
@return 8-bit value of specified data
*/
uint8_t readExtendedData(uint8_t classID, uint8_t offset);
/**
Write a specified number of bytes to extended data specifying a
class ID, position offset.
@param classID is the id of the class to be read from
offset is the byte position of the byte to be read
data is the data buffer to be written
len is the number of bytes to be written
@return true on success
*/
bool writeExtendedData(uint8_t classID, uint8_t offset, uint8_t * data, uint8_t len);
/////////////////////////////////
// I2C Read and Write Routines //
/////////////////////////////////
/**
Read a specified number of bytes over I2C at a given subAddress
@param subAddress is the 8-bit address of the data to be read
dest is the data buffer to be written to
count is the number of bytes to be read
@return true on success
*/
int16_t i2cReadBytes(uint8_t subAddress, uint8_t * dest, uint8_t count);
/**
Write a specified number of bytes over I2C to a given subAddress
@param subAddress is the 8-bit address of the data to be written to
src is the data buffer to be written
count is the number of bytes to be written
@return true on success
*/
uint16_t i2cWriteBytes(uint8_t subAddress, uint8_t * src, uint8_t count);
};
extern BQ27441 lipo; // Use lipo.[] to interact with the library in an Arduino sketch
// Thanks for reading!
#endif
+51
View File
@@ -0,0 +1,51 @@
#include "all.h"
static const char *TAG = "driver_all";
static void init_i2c();
void init_drivers() {
init_i2c();
// init char_lcd so we can use it to report other initialization errors.
init_lcd();
// init the bottom half so that we can get user input.
init_bottom_half();
init_sd();
init_speaker();
init_sseg();
init_game_timers();
init_tft();
init_leds();
init_power_board();
}
/// @brief Initializes I2C_NUM_0.
///
/// This is hooked up the to:
/// - The bottom half
/// - The char lcd
/// - The power board
/// - The MPU6050
/// - The PERH port
/// - The Capacitive Touch Panel
static void init_i2c() {
ESP_LOGI(TAG, "Initializing i2c...");
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = GPIO_NUM_5,
.scl_io_num = GPIO_NUM_6,
.sda_pullup_en = GPIO_PULLUP_DISABLE,
.scl_pullup_en = GPIO_PULLUP_DISABLE,
// .sda_pullup_en = GPIO_PULLUP_ENABLE,
// .scl_pullup_en = GPIO_PULLUP_ENABLE,
.master = {
.clk_speed = 100*1000,
},
.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL
};
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &conf));
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0));
ESP_LOGI(TAG, "i2c initialized!");
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef ALL_H
#define ALL_H
#include "char_lcd.h"
#include "bottom_half.h"
#include "sd.h"
#include "speaker.h"
#include "game_timer.h"
#include "drivers/tft.h"
#include "drivers/leds.h"
#include "drivers/power.h"
void init_drivers();
#endif /* ALL_H */
+232 -143
View File
@@ -1,29 +1,219 @@
#include "bottom_half.h"
#include <esp_log.h>
#include "state_tracking.h"
static const char *TAG = "bottom_half";
static uint16_t keypad_state;
static uint16_t button_state;
static uint8_t button_state;
static uint8_t switch_state;
static uint8_t switch_touch_state;
static uint8_t touch_state;
static uint16_t keypad_pressed;
static uint16_t button_pressed;
static uint8_t button_pressed;
static uint8_t switch_flipped_up;
static uint8_t switch_touch_pressed;
static uint8_t touch_pressed;
static uint16_t keypad_released;
static uint16_t button_released;
static uint8_t button_released;
static uint8_t switch_flipped_down;
static uint8_t switch_touch_released;
static uint8_t touch_released;
/// read buffer
static uint8_t buf[8];
static void poll_bottom_task(void *arg);
static void receive_keypad();
static void receive_button_switch();
static void receive_touch();
static bool replay_handler(const char* event, char* arg) {
// no reply neccesary
return false;
}
// TODO: add intrupt on bottom half delta pin
// static void IRAM_ATTR gpio_isr_handler(void* arg)
// {
// // TODO: do somthing
// ESP_LOGI("BOTTOM_HALF", "Hit");
// }
void init_bottom_half() {
ESP_LOGI(TAG, "Initializing bottom half...");
ESP_ERROR_CHECK(gpio_set_direction(BOTTOM_PIN_INTERUPT, GPIO_MODE_INPUT));
ESP_ERROR_CHECK(gpio_set_pull_mode(BOTTOM_PIN_INTERUPT, GPIO_PULLUP_ONLY));
// TODO: do interupt stuff.
// ESP_ERROR_CHECK(gpio_intr_enable(BOTTOM_PIN_INTERUPT));
// ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG))
//install gpio isr service
// gpio_install_isr_service(0);
//hook isr handler for specific gpio pin
// gpio_isr_handler_add(BOTTOM_INTERUPT_PIN, gpio_isr_handler, NULL);
receive_keypad();
receive_button_switch();
receive_touch();
xTaskCreate(poll_bottom_task, "poll_bottom", 4096, NULL, 10, NULL);
register_replay_fn(replay_handler);
ESP_LOGI(TAG, "Bottom half initialized!");
}
static uint8_t receive_delta(void) {
uint8_t reg = 1;
buf[0] = 0;
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, &reg, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
return buf[0];
}
static void receive_keypad(void) {
uint8_t reg = 2;
buf[0] = 0;
buf[1] = 0;
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, &reg, 1, buf, 2, (100 / portTICK_PERIOD_MS)));
uint16_t new_keypad_state = buf[0] | (buf[1] << 8);
uint16_t just_pressed = new_keypad_state & ~keypad_state;
keypad_pressed |= just_pressed;
if (is_state_tracking() && just_pressed) {
char buf[6];
sprintf(buf, "%d", just_pressed);
event_occured("KP_PRESS", buf);
}
uint16_t just_released = ~new_keypad_state & keypad_state;
keypad_released |= just_released;
if (is_state_tracking() && just_released) {
char buf[6];
sprintf(buf, "%d", just_released);
event_occured("KP_RELEASE", buf);
}
keypad_state = new_keypad_state;
}
static void receive_button_switch(void) {
uint8_t reg = 3;
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, &reg, 1, buf, 2, (100 / portTICK_PERIOD_MS)));
uint8_t new_button_state = buf[1] & 0xF;
uint8_t new_switch_state = (~buf[0]) & 0xF;
uint8_t new_switch_touch_state = (buf[1] >> 4) & 0xF;
// button
uint8_t just_pressed = new_button_state & ~button_state;
button_pressed |= just_pressed;
if (is_state_tracking() && just_pressed) {
char buf[4];
sprintf(buf, "%d", just_pressed);
event_occured("BTN_PRESS", buf);
}
uint8_t just_released = ~new_button_state & button_state;
button_released |= just_released;
if (is_state_tracking() && just_released) {
char buf[4];
sprintf(buf, "%d", just_released);
event_occured("BTN_RELEASE", buf);
}
button_state = new_button_state;
// switch
uint8_t just_flipped_up = new_switch_state & ~switch_state;
switch_flipped_up |= just_flipped_up;
if (is_state_tracking() && just_flipped_up) {
char buf[4];
sprintf(buf, "%d", just_flipped_up);
event_occured("SW_UP", buf);
}
uint8_t just_flipped_down = ~new_switch_state & switch_state;
switch_flipped_down |= just_flipped_down;
if (is_state_tracking() && just_flipped_down) {
char buf[4];
sprintf(buf, "%d", just_flipped_down);
event_occured("SW_DOWN", buf);
}
switch_state = new_switch_state;
// switch touch
uint8_t touch_just_pressed = new_switch_touch_state & ~switch_touch_state;
switch_touch_pressed |= touch_just_pressed;
if (is_state_tracking() && touch_just_pressed) {
char buf[4];
sprintf(buf, "%d", touch_just_pressed);
event_occured("SW_TOUCH", buf);
}
uint8_t touch_just_released = ~new_switch_touch_state & switch_touch_state;
switch_touch_released |= touch_just_released;
if (is_state_tracking() && touch_just_released) {
char buf[4];
sprintf(buf, "%d", touch_just_released);
event_occured("SW_UNTOUCH", buf);
}
switch_touch_state = new_switch_touch_state;
}
static void receive_touch(void) {
uint8_t reg = 4;
buf[0] = 0;
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, &reg, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
bool new_touch_state = buf[0] != 0;
bool just_pressed = new_touch_state & !touch_state;
touch_pressed |= just_pressed;
if (is_state_tracking() && just_pressed) {
event_occured("FINGER_TOUCHED", NULL);
}
bool just_released = (!new_touch_state) & touch_state;
touch_released |= just_released;
if (is_state_tracking() && just_released) {
event_occured("FINGER_UNTOUCHED", NULL);
}
touch_state = new_touch_state;
}
static void poll_bottom_task(void *arg) {
// TODO: if using an interupt, switch this to use a queue
while (1) {
bool new_data = gpio_get_level(BOTTOM_PIN_INTERUPT) == 0;
if (new_data) {
uint8_t delta = receive_delta();
// ESP_LOGI(_TAG, "delta: %d", delta);
if (delta == 0) ESP_LOGW(TAG, "delta pin was low, but delta register returned 0");
if (delta & (1 << DELTA_BIT_KP)) receive_keypad();
if (delta & (1 << DELTA_BIT_BUTTON_SWITCH)) receive_button_switch();
if (delta & (1 << DELTA_BIT_TOUCH)) receive_touch();
}
vTaskDelay(pdMS_TO_TICKS(10));
}
vTaskDelete(NULL);
}
void clear_all_pressed_released(void) {
keypad_pressed = 0;
button_pressed = 0;
switch_flipped_up = 0;
touch_pressed = 0;
keypad_released = 0;
button_released = 0;
switch_flipped_down = 0;
touch_released = 0;
}
@@ -42,10 +232,10 @@ static bool _take_key(KeypadKey* kp, uint16_t* keypad_bitfield) {
return false;
}
bool get_pressed_keypad(KeypadKey* kp) {
bool get_keypad_pressed(KeypadKey* kp) {
return _take_key(kp, &keypad_pressed);
}
bool get_released_keypad(KeypadKey* kp) {
bool get_keypad_released(KeypadKey* kp) {
return _take_key(kp, &keypad_released);
}
@@ -88,9 +278,12 @@ char char_of_keypad_key(KeypadKey kp) {
}
}
static bool _take_button(ButtonKey* button, uint16_t* button_bitfield) {
static bool _take_button(ButtonKey* button, uint8_t* button_bitfield) {
if (((*button_bitfield) & 0xF) == 0) return false;
// scan the 4 button bits for one that is set
for (int i = 0; i < 4; i++) {
int bit_selector = (1 << (i+8));
int bit_selector = (1 << i);
if ((*button_bitfield) & bit_selector) {
if (button != nullptr) {
*button = (ButtonKey) i;
@@ -102,56 +295,70 @@ static bool _take_button(ButtonKey* button, uint16_t* button_bitfield) {
}
return false;
}
static bool _take_switch(SwitchKey* switch_, uint16_t* button_bitfield) {
static bool _take_switch(SwitchKey* switch_, uint8_t* switch_bitfield) {
if (((*switch_bitfield) & 0xF) == 0) return false;
// scan the 4 switch bits for one that is set
for (int i = 0; i < 4; i++) {
int bit_selector = (1 << i);
if ((*button_bitfield) & bit_selector) {
if ((*switch_bitfield) & bit_selector) {
if (switch_ != nullptr) {
*switch_ = (SwitchKey) i;
}
// clear bit
*button_bitfield &= ~bit_selector;
*switch_bitfield &= ~bit_selector;
return true;
}
}
return false;
}
bool get_pressed_button(ButtonKey* button) {
bool get_button_pressed(ButtonKey* button) {
return _take_button(button, &button_pressed);
}
bool get_released_button(ButtonKey* button) {
bool get_button_released(ButtonKey* button) {
return _take_button(button, &button_released);
}
uint8_t get_button_state() {
return (uint8_t)((button_state >> 8) & 0xF);
return button_state;
}
bool get_flipped_up_switch(SwitchKey* switch_) {
return _take_switch(switch_, &button_released);
bool get_switch_flipped_up(SwitchKey* switch_) {
return _take_switch(switch_, &switch_flipped_up);
}
bool get_flipped_down_switch(SwitchKey* switch_) {
return _take_switch(switch_, &button_released);
bool get_switch_flipped_down(SwitchKey* switch_) {
return _take_switch(switch_, &switch_flipped_down);
}
bool get_flipped_switch(SwitchKey* switch_) {
bool get_switch_flipped(SwitchKey* switch_) {
for (int i = 0; i < 4; i++) {
int bit_selector = (1 << (i+4));
if (button_pressed & bit_selector || button_released & bit_selector) {
int bit_selector = (1 << i);
if (
((switch_flipped_up & bit_selector) != 0) ||
((switch_flipped_down & bit_selector) != 0)
) {
if (switch_ != nullptr) {
*switch_ = (SwitchKey) i;
}
// clear bit
button_pressed &= ~bit_selector;
button_released &= ~bit_selector;
switch_flipped_up &= ~bit_selector;
switch_flipped_down &= ~bit_selector;
return true;
}
}
return false;
}
uint8_t get_switch_state() {
return (uint8_t)(~button_state & 0xF);
return switch_state;
}
bool get_switch_touch_pressed(SwitchKey* switch_) {
return _take_switch(switch_, &switch_touch_pressed);
}
bool get_switch_touch_released(SwitchKey* switch_) {
return _take_switch(switch_, &switch_touch_released);
}
uint8_t get_switch_touch_state(){
return switch_touch_state;
}
bool get_touch_state(void) {
@@ -167,121 +374,3 @@ bool get_touch_released(void) {
touch_released = false;
return return_;
}
static void poll_bottom_task(void *arg);
static void receive_keypad(void);
static void receive_button(void);
static void receive_touch(void);
// static void IRAM_ATTR gpio_isr_handler(void* arg)
// {
// // TODO: do somthing
// ESP_LOGI("BOTTOM_HALF", "Hit");
// }
void init_bottom_half() {
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = GPIO_NUM_5,
.scl_io_num = GPIO_NUM_6,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master = {
.clk_speed = 100000,
}
};
ESP_ERROR_CHECK(i2c_param_config(BOTTOM_I2C_NUM, &conf));
ESP_ERROR_CHECK(i2c_driver_install(BOTTOM_I2C_NUM, conf.mode, 0, 0, 0));
gpio_config_t delta_pin_conf = {};
// delta_pin_conf.intr_type = GPIO_INTR_LOW_LEVEL;
delta_pin_conf.mode = GPIO_MODE_INPUT;
// GPIO 0
delta_pin_conf.pin_bit_mask = (1ULL<<BOTTOM_PIN_INTERUPT);
delta_pin_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&delta_pin_conf);
//install gpio isr service
// gpio_install_isr_service(0);
//hook isr handler for specific gpio pin
// gpio_isr_handler_add(BOTTOM_INTERUPT_PIN, gpio_isr_handler, NULL);
receive_keypad();
receive_button();
receive_touch();
xTaskCreate(poll_bottom_task, "poll_bottom", 4096, NULL, 10, NULL);
}
static uint8_t receive_delta(void) {
uint8_t reg = 1;
buf[0] = 0;
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, &reg, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
return buf[0];
}
static void receive_keypad(void) {
uint8_t reg = 2;
buf[0] = 0;
buf[1] = 0;
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, &reg, 1, buf, 2, (100 / portTICK_PERIOD_MS)));
uint16_t new_keypad_state = buf[0] | (buf[1] << 8);
uint16_t just_pressed = new_keypad_state & ~keypad_state;
keypad_pressed |= just_pressed;
uint16_t just_released = ~new_keypad_state & keypad_state;
keypad_released |= just_released;
keypad_state = new_keypad_state;
}
static void receive_button(void) {
uint8_t reg = 3;
buf[0] = 0;
buf[1] = 0;
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, &reg, 1, buf, 2, (100 / portTICK_PERIOD_MS)));
uint16_t new_button_state = buf[0] | (buf[1] << 8);
uint16_t just_pressed = new_button_state & ~button_state;
button_pressed |= just_pressed;
uint16_t just_released = ~new_button_state & button_state;
button_released |= just_released;
button_state = new_button_state;
}
static void receive_touch(void) {
uint8_t reg = 4;
buf[0] = 0;
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, &reg, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
bool new_touch_state = buf[0] != 0;
bool just_pressed = new_touch_state & !touch_state;
touch_pressed |= just_pressed;
bool just_released = (!new_touch_state) & touch_state;
touch_released |= just_released;
touch_state = new_touch_state;
}
static void poll_bottom_task(void *arg) {
while (1) {
bool new_data = gpio_get_level(BOTTOM_PIN_INTERUPT) == 0;
if (new_data) {
uint8_t delta = receive_delta();
// ESP_LOGI(_TAG, "delta: %d", delta);
if (delta == 0) ESP_LOGW(TAG, "delta pin was low, but delta register returned 0");
if (delta & (1 << DELTA_BIT_KP)) receive_keypad();
if (delta & (1 << DELTA_BIT_BUTTON)) receive_button();
if (delta & (1 << DELTA_BIT_TOUCH)) receive_touch();
}
vTaskDelay(pdMS_TO_TICKS(10));
}
vTaskDelete(NULL);
}
+82 -21
View File
@@ -3,16 +3,16 @@
#include "driver/i2c.h"
#include "driver/gpio.h"
#include "esp_log.h"
#define BOTTOM_I2C_NUM I2C_NUM_0
#define BOTTOM_I2C_ADDR 126
#define BOTTOM_PIN_INTERUPT GPIO_NUM_0
#define DELTA_BIT_KP 0
#define DELTA_BIT_BUTTON 1
#define DELTA_BIT_BUTTON_SWITCH 1
#define DELTA_BIT_TOUCH 2
/// @brief An enum for the possible keypad buttons.
typedef enum {
k1 = 0,
k4 = 1,
@@ -32,13 +32,19 @@ typedef enum {
kd = 15,
} KeypadKey;
/// @brief An enum for the possible buttons.
typedef enum {
b1 = 0,
b2 = 1,
b3 = 2,
b4 = 3,
button_green = 0,
button_red = 1,
button_yellow = 2,
button_blue = 3,
} ButtonKey;
/// @brief An enum for the possible switches.
typedef enum {
s1 = 0,
s2 = 1,
@@ -46,25 +52,80 @@ typedef enum {
s4 = 3,
} SwitchKey;
void clear_all_pressed_released(void);
bool get_pressed_keypad(KeypadKey* kp);
bool get_released_keypad(KeypadKey* kp);
char char_of_keypad_key(KeypadKey kp);
bool get_pressed_button(ButtonKey* button);
bool get_released_button(ButtonKey* button);
uint8_t get_button_state();
bool get_flipped_up_switch(SwitchKey* switch_);
bool get_flipped_down_switch(SwitchKey* switch_);
bool get_flipped_switch(SwitchKey* switch_);
uint8_t get_switch_state();
bool get_touch_state(void);
bool get_touch_pressed(void);
bool get_touch_released(void);
/// @brief Initializes communication with the bottom half.
void init_bottom_half();
/// Clears all pending pressed/released switches/buttons/keys/touch sensors.
void clear_all_pressed_released();
/// @brief Gets the key that was just pressed (if any)
/// @param kp an OUT variable for the key that was pressed (if any)
/// @return true if there was a key that was just pressed
bool get_keypad_pressed(KeypadKey* kp);
/// @brief Gets the key that was just released (if any)
/// @param kp an OUT variable for the key that was released (if any)
/// @return true if there was a key that was just released
bool get_keypad_released(KeypadKey* kp);
/// @brief Converts a `KeypadKey` to a char
/// @param kp The value to convert
/// @return The char representing the key
char char_of_keypad_key(KeypadKey kp);
// TODO: add a get_keypad state?
/// @brief Gets the button that was just pressed (if any)
/// @param button an OUT variable for the button that was pressed (if any)
/// @return true if there was a button that was just pressed
bool get_button_pressed(ButtonKey* button);
/// @brief Gets the button that was just released (if any)
/// @param button an OUT variable for the button that was released (if any)
/// @return true if there was a button that was just released
bool get_button_released(ButtonKey* button);
/// @brief Gets the raw state of the buttons b1-b4 as bitflags.
/// B1 is MSB and B4 is LSB.
/// @return Bitflags for b1-b4.
uint8_t get_button_state();
/// @brief Gets the switch that was just flipped up (if any)
/// @param switch_ an OUT variable for the switch that was flipped up (if any)
/// @return true if there was a switch that was just flipped up
bool get_switch_flipped_up(SwitchKey* switch_);
/// @brief Gets the switch that was just flipped down (if any)
/// @param switch_ an OUT variable for the switch that was flipped down (if any)
/// @return true if there was a switch that was just flipped down
bool get_switch_flipped_down(SwitchKey* switch_);
/// @brief Gets the switch that was just flipped (if any)
/// @param switch_ an OUT variable for the switch that was flipped (if any)
/// @return true if there was a switch that was just flipped
bool get_switch_flipped(SwitchKey* switch_);
/// @brief Gets the raw state of the switches s1-s4 as bitflags.
/// S1 is MSB and S4 is LSB.
/// @return Bitflags for s1-s4.
uint8_t get_switch_state();
/// @brief Gets the switch that was just touched (if any)
/// @param switch_ an OUT variable for the switch that was touched (if any)
/// @return true if there was a switch that was just touched
bool get_switch_touch_pressed(SwitchKey* switch_);
/// @brief Gets the switch that was just un-touched (if any)
/// @param switch_ an OUT variable for the switch that was un-touched (if any)
/// @return true if there was a switch that was just un-touched
bool get_switch_touch_released(SwitchKey* switch_);
/// @brief Gets the raw state of the touched switches s1-s4 as bitflags.
/// S1 is MSB and S4 is LSB.
/// @return Bitflags for the touched state of S1-S4.
uint8_t get_switch_touch_state();
/// @brief Gets the state of the fingerprint sensor
/// @return true if the fingerprint sensor is touched
bool get_touch_state();
/// @brief Gets whether or not the touch sensor was just pressed
/// @return true if the touch sensor was just pressed
bool get_touch_pressed();
/// @brief Gets whether or not the touch sensor was just released
/// @return true if the touch sensor was just released
bool get_touch_released();
// TODO: add touch sensor for switch
#endif /* BOTTOM_HALF_HPP */
+237 -2
View File
@@ -1,14 +1,249 @@
#include "char_lcd.h"
#include "./i2c_lcd_pcf8574.h"
#include <esp_log.h>
#include "state_tracking.h"
#include <cstring>
i2c_lcd_pcf8574_handle_t lcd;
static const char *TAG = "char_lcd";
void init_char_lcd(void) {
static char buf[65];
static bool replay_handler(const char* event, char* arg) {
if (strcmp(event, "LCD_CLEAR") == 0) {
lcd_clear();
return true;
}
if (strcmp(event, "LCD_CURSOR") == 0) {
char* col_str = strtok(arg, ",");
char* row_str = strtok(NULL, ",");
uint32_t col = atoi(col_str);
uint32_t row = atoi(row_str);
lcd_set_cursor_pos(col, row);
return true;
}
if (strcmp(event, "LCD_SET_DISPLAY") == 0) {
lcd_set_display(strcmp(arg, "true") == 0);
return true;
}
if (strcmp(event, "LCD_CURSOR_VIS") == 0) {
lcd_set_cursor_vis(strcmp(arg, "true") == 0);
return true;
}
if (strcmp(event, "LCD_CURSOR_BLINK") == 0) {
lcd_set_cursor_blink(strcmp(arg, "true") == 0);
return true;
}
if (strcmp(event, "LCD_SCROLL_DISPLAY_LEFT") == 0) {
lcd_scroll_display_left();
return true;
}
if (strcmp(event, "LCD_SCROLL_DISPLAY_RIGHT") == 0) {
lcd_scroll_display_right();
return true;
}
if (strcmp(event, "LCD_LEFT_TO_RIGHT") == 0) {
lcd_left_to_right();
return true;
}
if (strcmp(event, "LCD_RIGHT_TO_LEFT") == 0) {
lcd_right_to_left();
return true;
}
if (strcmp(event, "LCD_AUTOSCROLL") == 0) {
lcd_set_autoscroll(strcmp(arg, "true") == 0);
return true;
}
if (strcmp(event, "LCD_BACKLIGHT") == 0) {
uint32_t brightness = atoi(arg);
lcd_set_backlight(brightness);
return true;
}
if (strcmp(event, "LCD_CREATE_CHAR") == 0) {
char* location_str = strtok(arg, ",");
uint8_t location = atoi(location_str);
uint8_t charmap[8];
for (int i = 0; i < 8; i++) {
char* str = strtok(NULL, ",");
charmap[i] = atoi(str);
}
lcd_create_char(location, charmap);
return true;
}
if (strcmp(event, "LCD_WRITE") == 0) {
uint8_t value = atoi(arg);
lcd_write(value);
return true;
}
if (strcmp(event, "LCD_PRINT") == 0) {
// TODO: handle \r and \n
lcd_print(arg);
return true;
}
return false;
}
void init_lcd() {
ESP_LOGI(TAG, "Initializing LCD...");
lcd_init(&lcd, LCD_ADDR, CHAR_LCD_I2C_NUM);
lcd_begin(&lcd, LCD_COLS, LCD_ROWS);
lcd_set_backlight(&lcd, 255);
ESP_LOGI(TAG, "LCD initialized");
register_replay_fn(replay_handler);
ESP_LOGI(TAG, "LCD initialized!");
}
void lcd_clear() {
lcd_clear(&lcd);
if (is_state_tracking()) {
event_occured("LCD_CLEAR", NULL);
}
}
void lcd_cursor_home() {
lcd_home(&lcd);
if (is_state_tracking()) {
event_occured("LCD_CURSOR", "0,0");
}
}
void lcd_set_cursor_pos(uint8_t col, uint8_t row) {
lcd_set_cursor(&lcd, col, row);
if (is_state_tracking()) {
sprintf(buf, "%d,%d", col, row);
event_occured("LCD_CURSOR", buf);
}
}
void lcd_set_display(bool display) {
if (display) {
lcd_display(&lcd);
} else {
lcd_no_display(&lcd);
}
if (is_state_tracking()) {
event_occured("LCD_SET_DISPLAY", display ? "true" : "false");
}
}
void lcd_set_cursor_vis(bool cursor) {
if (cursor) {
lcd_cursor(&lcd);
} else {
lcd_no_cursor(&lcd);
}
if (is_state_tracking()) {
event_occured("LCD_CURSOR_VIS", cursor ? "true" : "false");
}
}
void lcd_set_cursor_blink(bool blink) {
if (blink) {
lcd_blink(&lcd);
} else {
lcd_no_blink(&lcd);
}
if (is_state_tracking()) {
event_occured("LCD_CURSOR_BLINK", blink ? "true" : "false");
}
}
void lcd_scroll_display_left() {
lcd_scroll_display_left(&lcd);
if (is_state_tracking()) {
event_occured("LCD_SCROLL_DISPLAY_LEFT", NULL);
}
}
void lcd_scroll_display_right() {
lcd_scroll_display_right(&lcd);
if (is_state_tracking()) {
event_occured("LCD_SCROLL_DISPLAY_RIGHT", NULL);
}
}
void lcd_left_to_right() {
lcd_left_to_right(&lcd);
if (is_state_tracking()) {
event_occured("LCD_LEFT_TO_RIGHT", NULL);
}
}
void lcd_right_to_left() {
lcd_right_to_left(&lcd);
if (is_state_tracking()) {
event_occured("LCD_RIGHT_TO_LEFT", NULL);
}
}
void lcd_set_autoscroll(bool autoscroll) {
if (autoscroll) {
lcd_autoscroll(&lcd);
} else {
lcd_no_autoscroll(&lcd);
}
if (is_state_tracking()) {
event_occured("LCD_AUTOSCROLL", autoscroll ? "true" : "false");
}
}
void lcd_set_backlight(uint8_t brightness) {
lcd_set_backlight(&lcd, brightness);
if (is_state_tracking()) {
sprintf(buf, "%d", brightness);
event_occured("LCD_BACKLIGHT", buf);
}
}
void lcd_create_char(uint8_t location, uint8_t* charmap) {
lcd_create_char(&lcd, location, charmap);
if (is_state_tracking()) {
snprintf(buf, 65,
"%d,%d,%d,%d,%d,%d,%d,%d,%d", location,
charmap[0], charmap[1], charmap[2], charmap[3], charmap[4], charmap[5], charmap[6], charmap[7]
);
event_occured("LCD_CREATE_CHAR", buf);
}
}
void lcd_write(uint8_t value) {
lcd_write(&lcd, value);
if (is_state_tracking()) {
sprintf(buf, "%d", value);
event_occured("LCD_WRITE", buf);
}
}
void lcd_print(const char* str) {
lcd_print(&lcd, str);
if (is_state_tracking()) {
// TODO: handle \r and \n
event_occured("LCD_PRINT", str);
}
}
void lcd_print(uint8_t col, uint8_t row, const char* str) {
lcd_set_cursor_pos(col, row);
lcd_print(str);
}
+48 -4
View File
@@ -1,8 +1,7 @@
#ifndef CHAR_LCD_H
#define CHAR_LCD_H
#include "i2c_lcd_pcf8574.h"
#include <esp_log.h>
#include <cstdint>
#define CHAR_LCD_I2C_NUM I2C_NUM_0
@@ -10,8 +9,53 @@
#define LCD_COLS 20
#define LCD_ROWS 4
extern i2c_lcd_pcf8574_handle_t lcd;
/// Initializes the 2004 Character LCD
void init_lcd();
void init_char_lcd(void);
/// Clear the LCD
void lcd_clear();
/// Move cursor to home position
void lcd_cursor_home();
/// Set cursor position
void lcd_set_cursor_pos(uint8_t col, uint8_t row);
/// Turn the display on/off
void lcd_set_display(bool display);
/// Turn the cursor's visibility on/off
void lcd_set_cursor_vis(bool cursor);
/// Turn blinking cursor on/off
void lcd_set_cursor_blink(bool blink);
/// Scroll the display left
void lcd_scroll_display_left();
/// Scroll the display right
void lcd_scroll_display_right();
/// Set the text to flows automatically left to right
void lcd_left_to_right();
/// Set the text to flows automatically right to left
void lcd_right_to_left();
// Turn on/off autoscroll
void lcd_set_autoscroll(bool autoscroll);
// Set backlight brightness
void lcd_set_backlight(uint8_t brightness);
// Create a custom character
void lcd_create_char(uint8_t location, uint8_t charmap[]);
// Write a character to the LCD
void lcd_write(uint8_t value);
// Print a string to the LCD
void lcd_print(const char* str);
// Print a string to the LCD at a given pos
void lcd_print(uint8_t col, uint8_t row, const char* str);
#endif /* CHAR_LCD_H */
@@ -0,0 +1,467 @@
// Addapted from:
// https://github.com/atanisoft/esp_lcd_ili9488
/*
* SPDX-FileCopyrightText: 2022 atanisoft (github.com/atanisoft)
*
* SPDX-License-Identifier: MIT
*/
#include <driver/gpio.h>
#include <esp_lcd_panel_interface.h>
#include <esp_lcd_panel_io.h>
#include <esp_lcd_panel_vendor.h>
#include <esp_lcd_panel_ops.h>
#include <esp_lcd_panel_commands.h>
#include <esp_log.h>
#include <esp_rom_gpio.h>
#include <esp_check.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <memory.h>
#include <stdlib.h>
#include <sys/cdefs.h>
static const char *TAG = "ili9488";
typedef struct
{
uint8_t cmd;
uint8_t data[16];
uint8_t data_bytes;
} lcd_init_cmd_t;
typedef struct
{
esp_lcd_panel_t base;
esp_lcd_panel_io_handle_t io;
int reset_gpio_num;
bool reset_level;
int x_gap;
int y_gap;
uint8_t memory_access_control;
uint8_t color_mode;
size_t buffer_size;
uint8_t *color_buffer;
} ili9488_panel_t;
enum ili9488_constants
{
ILI9488_INTRFC_MODE_CTL = 0xB0,
ILI9488_FRAME_RATE_NORMAL_CTL = 0xB1,
ILI9488_INVERSION_CTL = 0xB4,
ILI9488_FUNCTION_CTL = 0xB6,
ILI9488_ENTRY_MODE_CTL = 0xB7,
ILI9488_POWER_CTL_ONE = 0xC0,
ILI9488_POWER_CTL_TWO = 0xC1,
ILI9488_POWER_CTL_THREE = 0xC5,
ILI9488_POSITIVE_GAMMA_CTL = 0xE0,
ILI9488_NEGATIVE_GAMMA_CTL = 0xE1,
ILI9488_ADJUST_CTL_THREE = 0xF7,
ILI9488_COLOR_MODE_16BIT = 0x55,
ILI9488_COLOR_MODE_18BIT = 0x66,
ILI9488_INTERFACE_MODE_USE_SDO = 0x00,
ILI9488_INTERFACE_MODE_IGNORE_SDO = 0x80,
ILI9488_IMAGE_FUNCTION_DISABLE_24BIT_DATA = 0x00,
ILI9488_WRITE_MODE_BCTRL_DD_ON = 0x28,
ILI9488_FRAME_RATE_60HZ = 0xA0,
ILI9488_INIT_LENGTH_MASK = 0x1F,
ILI9488_INIT_DONE_FLAG = 0xFF
};
static esp_err_t panel_ili9488_del(esp_lcd_panel_t *panel)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
if (ili9488->reset_gpio_num >= 0)
{
gpio_reset_pin(ili9488->reset_gpio_num);
}
if (ili9488->color_buffer != NULL)
{
heap_caps_free(ili9488->color_buffer);
}
ESP_LOGI(TAG, "del ili9488 panel @%p", ili9488);
free(ili9488);
return ESP_OK;
}
static esp_err_t panel_ili9488_reset(esp_lcd_panel_t *panel)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
esp_lcd_panel_io_handle_t io = ili9488->io;
if (ili9488->reset_gpio_num >= 0)
{
ESP_LOGI(TAG, "Setting GPIO:%d to %d", ili9488->reset_gpio_num,
ili9488->reset_level);
// perform hardware reset
gpio_set_level(ili9488->reset_gpio_num, ili9488->reset_level);
vTaskDelay(pdMS_TO_TICKS(10));
ESP_LOGI(TAG, "Setting GPIO:%d to %d", ili9488->reset_gpio_num,
!ili9488->reset_level);
gpio_set_level(ili9488->reset_gpio_num, !ili9488->reset_level);
vTaskDelay(pdMS_TO_TICKS(10));
}
else
{
ESP_LOGI(TAG, "Sending SW_RESET to display");
esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0);
vTaskDelay(pdMS_TO_TICKS(20));
}
return ESP_OK;
}
static esp_err_t panel_ili9488_init(esp_lcd_panel_t *panel)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
esp_lcd_panel_io_handle_t io = ili9488->io;
// ORIGINAL
lcd_init_cmd_t ili9488_init[] =
{
#if CONFIG_USE_NEW_DISPLAY
{ ILI9488_POSITIVE_GAMMA_CTL, { 0x00, 0x08, 0x0c, 0x02, 0x0e, 0x04, 0x30, 0x45, 0x47, 0x04, 0x0C, 0x0a, 0x2e, 0x34, 0x0F }, 15 },
{ ILI9488_NEGATIVE_GAMMA_CTL, { 0x00, 0x11, 0x0d, 0x01, 0x0f, 0x05, 0x39, 0x36, 0x51, 0x06, 0x0f, 0x0d, 0x33, 0x37, 0x0F }, 15 },
#else
{ ILI9488_POSITIVE_GAMMA_CTL, { 0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F }, 15 },
{ ILI9488_NEGATIVE_GAMMA_CTL, { 0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F }, 15 },
#endif /* CONFIG_USE_NEW_DISPLAY */
{ ILI9488_POWER_CTL_ONE, { 0x17, 0x15 }, 2 },
{ ILI9488_POWER_CTL_TWO, { 0x41 }, 1 },
{ ILI9488_POWER_CTL_THREE, { 0x00, 0x12, 0x80 }, 3 },
{ LCD_CMD_MADCTL, { ili9488->memory_access_control }, 1 },
{ LCD_CMD_COLMOD, { ili9488->color_mode }, 1 },
{ ILI9488_INTRFC_MODE_CTL, { ILI9488_INTERFACE_MODE_USE_SDO }, 1 },
{ ILI9488_FRAME_RATE_NORMAL_CTL, { ILI9488_FRAME_RATE_60HZ }, 1 },
{ ILI9488_INVERSION_CTL, { 0x02 }, 1 },
{ ILI9488_FUNCTION_CTL, { 0x02, 0x02, 0x3B }, 3},
{ ILI9488_ENTRY_MODE_CTL, { 0xC6 }, 1 },
{ ILI9488_ADJUST_CTL_THREE, { 0xA9, 0x51, 0x2C, 0x02 }, 4 },
{ LCD_CMD_NOP, { 0 }, ILI9488_INIT_DONE_FLAG },
};
// WITH CONSTS INLINED:
// lcd_init_cmd_t ili9488_init[] =
// {
// { 0xE0,
// { 0x00, 0x03, 0x09, 0x08, 0x16,
// 0x0A, 0x3F, 0x78, 0x4C, 0x09,
// 0x0A, 0x08, 0x16, 0x1A, 0x0F },
// 15
// },
// { 0xE1,
// { 0x00, 0x16, 0x19, 0x03, 0x0F,
// 0x05, 0x32, 0x45, 0x46, 0x04,
// 0x0E, 0x0D, 0x35, 0x37, 0x0F},
// 15
// },
// { 0xC0, { 0x17, 0x15 }, 2 },
// { 0xC1, { 0x41 }, 1 },
// { 0xC5, { 0x00, 0x12, 0x80 }, 3 },
// { 0x36, { ili9488->memory_access_control }, 1 },
// { 0x3A, { ili9488->color_mode }, 1 },
// { 0xB0, { ILI9488_INTERFACE_MODE_USE_SDO }, 1 },
// { 0xB1, { ILI9488_FRAME_RATE_60HZ }, 1 },
// { 0xB4, { 0x02 }, 1 },
// { 0xB6, { 0x02, 0x02, 0x3B }, 3},
// { 0xB7, { 0xC6 }, 1 },
// { 0xF7, { 0xA9, 0x51, 0x2C, 0x02 }, 4 },
// { 0x00, { 0 }, ILI9488_INIT_DONE_FLAG },
// };
// code from LCD manufacturer. (Not working):
// lcd_init_cmd_t ili9488_init[] = {
// { 0xF7, { 0xA9, 0x51, 0x2C, 0x82 }, 4 },
// { 0x36, { 0x48 }, 1 },
// { 0x3A, { 0x55 }, 1 },
// { 0xB4, { 0x02 }, 1 },
// { 0xB1, { 0xA0, 0x11 }, 2 },
// { 0xC0, { 0x0F, 0x0F }, 2 },
// { 0xC1, { 0x41 }, 1 },
// { 0xC2, { 0x22 }, 1 },
// { 0xB7, { 0xC6 }, 1 },
// { 0xc5, { 0x00, 0x53, 0x80 }, 3 },
// { 0xE0, { 0x00, 0x08, 0x0c, 0x02, 0x0e, 0x04, 0x30, 0x45, 0x47, 0x04, 0x0C, 0x0a, 0x2e, 0x34, 0x0F }, 15 },
// { 0xE1, { 0x00, 0x11, 0x0d, 0x01, 0x0f, 0x05, 0x39, 0x36, 0x51, 0x06, 0x0f, 0x0d, 0x33, 0x37, 0x0F }, 15 },
// { 0x21, { 0x00 }, 1 },
// { 0x3A, { 0x55 }, 1 },
// { LCD_CMD_NOP, { 0 }, ILI9488_INIT_DONE_FLAG },
// };
ESP_LOGI(TAG, "Initializing ILI9488");
int cmd = 0;
while ( ili9488_init[cmd].data_bytes != ILI9488_INIT_DONE_FLAG )
{
ESP_LOGD(TAG, "Sending CMD: %02x, len: %d", ili9488_init[cmd].cmd,
ili9488_init[cmd].data_bytes & ILI9488_INIT_LENGTH_MASK);
esp_lcd_panel_io_tx_param(
io, ili9488_init[cmd].cmd, ili9488_init[cmd].data,
ili9488_init[cmd].data_bytes & ILI9488_INIT_LENGTH_MASK);
cmd++;
}
// Take the display out of sleep mode.
esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0);
vTaskDelay(pdMS_TO_TICKS(100));
// Turn on the display.
esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON, NULL, 0);
vTaskDelay(pdMS_TO_TICKS(100));
ESP_LOGI(TAG, "Initialization complete");
return ESP_OK;
}
#define SEND_COORDS(start, end, io, cmd) \
esp_lcd_panel_io_tx_param(io, cmd, (uint8_t[]) { \
(start >> 8) & 0xFF, \
start & 0xFF, \
((end - 1) >> 8) & 0xFF, \
(end - 1) & 0xFF, \
}, 4)
static esp_err_t panel_ili9488_draw_bitmap(
esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end,
const void *color_data)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
assert((x_start < x_end) && (y_start < y_end) &&
"starting position must be smaller than end position");
esp_lcd_panel_io_handle_t io = ili9488->io;
x_start += ili9488->x_gap;
x_end += ili9488->x_gap;
y_start += ili9488->y_gap;
y_end += ili9488->y_gap;
size_t color_data_len = (x_end - x_start) * (y_end - y_start);
SEND_COORDS(x_start, x_end, io, LCD_CMD_CASET);
SEND_COORDS(y_start, y_end, io, LCD_CMD_RASET);
// When the ILI9488 is used in 18-bit color mode we need to convert the
// incoming color data from RGB565 (16-bit) to RGB666.
//
// NOTE: 16-bit color does not work via SPI interface :(
if (ili9488->color_mode == ILI9488_COLOR_MODE_18BIT)
{
uint8_t *buf = ili9488->color_buffer;
uint16_t *raw_color_data = (uint16_t *) color_data;
for (uint32_t i = 0, pixel_index = 0; i < color_data_len; i++) {
buf[pixel_index++] = (uint8_t) (((raw_color_data[i] & 0xF800) >> 8) |
((raw_color_data[i] & 0x8000) >> 13));
buf[pixel_index++] = (uint8_t) ((raw_color_data[i] & 0x07E0) >> 3);
buf[pixel_index++] = (uint8_t) (((raw_color_data[i] & 0x001F) << 3) |
((raw_color_data[i] & 0x0010) >> 2));
}
esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, buf, color_data_len * 3);
}
else
{
// 16-bit color we can transmit as-is to the display.
esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, color_data_len * 2);
}
return ESP_OK;
}
#undef SEND_COORDS
static esp_err_t panel_ili9488_invert_color(
esp_lcd_panel_t *panel, bool invert_color_data)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
esp_lcd_panel_io_handle_t io = ili9488->io;
if (invert_color_data)
{
esp_lcd_panel_io_tx_param(io, LCD_CMD_INVON, NULL, 0);
}
else
{
esp_lcd_panel_io_tx_param(io, LCD_CMD_INVOFF, NULL, 0);
}
return ESP_OK;
}
static esp_err_t panel_ili9488_mirror(
esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
esp_lcd_panel_io_handle_t io = ili9488->io;
if (mirror_x)
{
ili9488->memory_access_control &= ~LCD_CMD_MX_BIT;
}
else
{
ili9488->memory_access_control |= LCD_CMD_MX_BIT;
}
if (mirror_y)
{
ili9488->memory_access_control |= LCD_CMD_MY_BIT;
}
else
{
ili9488->memory_access_control &= ~LCD_CMD_MY_BIT;
}
esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, &ili9488->memory_access_control, 1);
return ESP_OK;
}
static esp_err_t panel_ili9488_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
esp_lcd_panel_io_handle_t io = ili9488->io;
if (swap_axes)
{
ili9488->memory_access_control |= LCD_CMD_MV_BIT;
}
else
{
ili9488->memory_access_control &= ~LCD_CMD_MV_BIT;
}
esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, &ili9488->memory_access_control, 1);
return ESP_OK;
}
static esp_err_t panel_ili9488_set_gap(
esp_lcd_panel_t *panel, int x_gap, int y_gap)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
ili9488->x_gap = x_gap;
ili9488->y_gap = y_gap;
return ESP_OK;
}
static esp_err_t panel_ili9488_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
esp_lcd_panel_io_handle_t io = ili9488->io;
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
// In ESP-IDF v4.x the API used false for "on" and true for "off"
// invert the logic to be consistent with IDF v5.x.
on_off = !on_off;
#endif
if (on_off)
{
esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON, NULL, 0);
}
else
{
esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPOFF, NULL, 0);
}
// give time for the ILI9488 to recover after an on/off command
vTaskDelay(pdMS_TO_TICKS(100));
return ESP_OK;
}
esp_err_t esp_lcd_new_panel_ili9488(
const esp_lcd_panel_io_handle_t io,
const esp_lcd_panel_dev_config_t *panel_dev_config,
const size_t buffer_size,
esp_lcd_panel_handle_t *ret_panel)
{
esp_err_t ret = ESP_OK;
ili9488_panel_t *ili9488 = NULL;
ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG,
err, TAG, "invalid argument");
ili9488 = (ili9488_panel_t *)(calloc(1, sizeof(ili9488_panel_t)));
ESP_GOTO_ON_FALSE(ili9488, ESP_ERR_NO_MEM, err, TAG, "no mem for ili9488 panel");
if (panel_dev_config->reset_gpio_num >= 0)
{
gpio_config_t cfg;
memset(&cfg, 0, sizeof(gpio_config_t));
esp_rom_gpio_pad_select_gpio(panel_dev_config->reset_gpio_num);
cfg.pin_bit_mask = BIT64(panel_dev_config->reset_gpio_num);
cfg.mode = GPIO_MODE_OUTPUT;
ESP_GOTO_ON_ERROR(gpio_config(&cfg), err, TAG,
"configure GPIO for RESET line failed");
}
if (panel_dev_config->bits_per_pixel == 16)
{
ili9488->color_mode = ILI9488_COLOR_MODE_16BIT;
}
else
{
ESP_GOTO_ON_FALSE(buffer_size > 0, ESP_ERR_INVALID_ARG, err, TAG,
"Color conversion buffer size must be specified");
ili9488->color_mode = ILI9488_COLOR_MODE_18BIT;
// Allocate DMA buffer for color conversions
ili9488->color_buffer =
(uint8_t *)heap_caps_malloc(buffer_size * 3, MALLOC_CAP_DMA);
ESP_GOTO_ON_FALSE(ili9488->color_buffer, ESP_ERR_NO_MEM, err, TAG,
"Failed to allocate DMA color conversion buffer");
}
ili9488->memory_access_control = LCD_CMD_MX_BIT | LCD_CMD_BGR_BIT;
switch (panel_dev_config->color_space)
{
case ESP_LCD_COLOR_SPACE_RGB:
ESP_LOGI(TAG, "Configuring for RGB color order");
ili9488->memory_access_control &= ~LCD_CMD_BGR_BIT;
break;
case ESP_LCD_COLOR_SPACE_BGR:
ESP_LOGI(TAG, "Configuring for BGR color order");
break;
default:
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG,
"Unsupported color mode!");
}
ili9488->io = io;
ili9488->reset_gpio_num = panel_dev_config->reset_gpio_num;
ili9488->reset_level = panel_dev_config->flags.reset_active_high;
ili9488->base.del = panel_ili9488_del;
ili9488->base.reset = panel_ili9488_reset;
ili9488->base.init = panel_ili9488_init;
ili9488->base.draw_bitmap = panel_ili9488_draw_bitmap;
ili9488->base.invert_color = panel_ili9488_invert_color;
ili9488->base.set_gap = panel_ili9488_set_gap;
ili9488->base.mirror = panel_ili9488_mirror;
ili9488->base.swap_xy = panel_ili9488_swap_xy;
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
ili9488->base.disp_off = panel_ili9488_disp_on_off;
#else
ili9488->base.disp_on_off = panel_ili9488_disp_on_off;
#endif
*ret_panel = &(ili9488->base);
ESP_LOGI(TAG, "new ili9488 panel @%p", ili9488);
return ESP_OK;
err:
if (ili9488)
{
if (panel_dev_config->reset_gpio_num >= 0)
{
gpio_reset_pin(panel_dev_config->reset_gpio_num);
}
if (ili9488->color_buffer != NULL)
{
heap_caps_free(ili9488->color_buffer);
}
free(ili9488);
}
return ret;
}
@@ -0,0 +1,45 @@
// Addapted from:
// https://github.com/atanisoft/esp_lcd_ili9488
/*
* SPDX-FileCopyrightText: 2022 atanisoft (github.com/atanisoft)
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include "esp_lcd_panel_vendor.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Create LCD panel for model ILI9488
*
* @param[in] io LCD panel IO handle
* @param[in] panel_dev_config general panel device configuration
* @param[in] buffer_size size of buffer to allocate for color conversions.
* @param[out] ret_panel Returned LCD panel handle
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_ERR_NO_MEM if out of memory
* - ESP_OK on success
*
* NOTE: If you are using the SPI interface you *MUST* 18-bit color mode
* in @param panel_dev_config field bits_per_pixel and @param buffer_size
* must be provided.
*
* NOTE: For parallel IO (Intel 8080) interface 16-bit color mode should
* be used and @param buffer_size will be ignored.
*/
esp_err_t esp_lcd_new_panel_ili9488(const esp_lcd_panel_io_handle_t io,
const esp_lcd_panel_dev_config_t *panel_dev_config,
const size_t buffer_size,
esp_lcd_panel_handle_t *ret_panel);
#ifdef __cplusplus
}
#endif
+24 -15
View File
@@ -1,4 +1,7 @@
#include "game_timer.h"
#include <esp_log.h>
static const char* TAG = "game_timer";
static bool is_module_playing;
static bool is_game_playing;
@@ -12,6 +15,14 @@ static uint32_t module_time_left;
static void game_timer_task(void *arg);
static uint32_t sat_sub(uint32_t x, uint32_t y);
void init_game_timers() {
ESP_LOGI(TAG, "Initializing game timers...");
xTaskCreate(game_timer_task, "game_timers", 4096, NULL, 10, NULL);
ESP_LOGI(TAG, "Game timers initialized!");
}
static void write_game_time(uint32_t millis) {
if (millis > 60'000) {
int disp_time = (millis / 60'000) * 100;
@@ -31,27 +42,23 @@ static void write_module_time(uint32_t millis) {
}
}
void init_game_module_timer(void) {
xTaskCreate(game_timer_task, "game_module_timer", 4096, NULL, 10, NULL);
}
void start_game_timer(void) {
void start_game_timer() {
is_game_playing = true;
}
void stop_game_timer(void) {
void stop_game_timer() {
is_game_playing = false;
}
void start_module_timer(void) {
void start_module_timer() {
is_module_playing = true;
}
void stop_module_timer(void) {
void stop_module_timer() {
is_module_playing = false;
}
void set_game_time(uint32_t new_time) {
void set_game_time(int32_t new_time) {
if (new_time > 0) {
game_time_count_up = false;
game_time_left = new_time;
@@ -62,8 +69,12 @@ void set_game_time(uint32_t new_time) {
write_game_time(game_time_left);
}
uint32_t get_game_time() {
return game_time_left;
int32_t get_game_time() {
if (game_time_count_up) {
return -((int32_t) game_time_left);
} else {
return ((int32_t) game_time_left);
}
}
void set_module_time(uint32_t new_time) {
@@ -87,8 +98,7 @@ void time_penalty(uint32_t penalty) {
}
}
static void game_timer_task(void *arg)
{
static void game_timer_task(void *arg) {
TickType_t lastWakeTime = xTaskGetTickCount();
const uint32_t frequency = 100;
@@ -114,8 +124,7 @@ static void game_timer_task(void *arg)
vTaskDelete(NULL);
}
static uint32_t sat_sub(uint32_t x, uint32_t y)
{
static uint32_t sat_sub(uint32_t x, uint32_t y) {
uint32_t res = x - y;
res &= -(res <= x);
return res;
+7 -7
View File
@@ -5,22 +5,22 @@
#include "sseg.h"
/// Initializes the game and module timers.
void init_game_module_timer(void);
void init_game_timers();
/// Starts the game timer
void start_game_timer(void);
void start_game_timer();
/// Stops the game timer
void stop_game_timer(void);
void stop_game_timer();
/// Starts the module timer
void start_module_timer(void);
void start_module_timer();
/// Stops the module timer
void stop_module_timer(void);
void stop_module_timer();
/// Sets the game time in ms
void set_game_time(uint32_t new_time);
void set_game_time(int32_t new_time);
/// Gets the current game time in ms
uint32_t get_game_time();
int32_t get_game_time();
/// Gets the current game time in ms
void time_penalty(uint32_t penalty);
+355
View File
@@ -0,0 +1,355 @@
/// \file i2c_lcd_pcf8574.c
/// \brief Liquid Crystal display driver with PCF8574 adapter for esp-idf
///
/// \author Femi Olugbon, https://iamflinks.github.io
/// \copyright Copyright (c) 2024 by Femi Olugbon
///
/// ChangeLog see: i2c_lcd_pcf8574.h
#include <stdio.h>
#include "i2c_lcd_pcf8574.h"
#include "esp_log.h"
#include "esp_check.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define TAG "I2C_LCD_PCF8574"
#define I2C_MASTER_TIMEOUT_MS 1000
// private functions
static void lcd_send(i2c_lcd_pcf8574_handle_t* lcd, uint8_t value, bool is_data);
static void lcd_write_nibble(i2c_lcd_pcf8574_handle_t* lcd, uint8_t half_byte, bool is_data, i2c_cmd_handle_t cmd);
static void lcd_write_i2c(i2c_lcd_pcf8574_handle_t* lcd, uint8_t data, bool is_data, bool enable);
void lcd_init(i2c_lcd_pcf8574_handle_t* lcd, uint8_t i2c_addr, i2c_port_t i2c_port) {
lcd->i2c_addr = i2c_addr;
lcd->i2c_port = i2c_port;
lcd->backlight = 0;
lcd->entrymode = 0x02; // Init the LCD with an internal reset
lcd->displaycontrol = 0x04;
lcd->rs_mask = 0x01;
lcd->rw_mask = 0x00;
lcd->enable_mask = 0x04;
lcd->data_mask[0] = 0x10;
lcd->data_mask[1] = 0x20;
lcd->data_mask[2] = 0x40;
lcd->data_mask[3] = 0x80;
lcd->backlight_mask = 0x08;
}
void lcd_begin(i2c_lcd_pcf8574_handle_t* lcd, uint8_t cols, uint8_t rows) {
// Ensure the cols and rows stay within max limit
lcd->cols = (cols > 80) ? 80 : cols;
lcd->lines = (rows > 4) ? 4 : rows;
lcd->row_offsets[0] = 0x00;
lcd->row_offsets[1] = 0x40;
lcd->row_offsets[2] = 0x00 + cols;
lcd->row_offsets[3] = 0x40 + cols;
// Initialize the LCD
lcd_write_i2c(lcd, 0x00, false, false);
esp_rom_delay_us(50000);
// This follows after the reset mode
lcd->displaycontrol = 0x04;
lcd->entrymode = 0x02;
// The following are the reset sequence: Please see "Initialization instruction in the PCF8574 datasheet."
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
// We left-shift the device addres and add the read/write command
i2c_master_write_byte(cmd, (lcd->i2c_addr << 1) | I2C_MASTER_WRITE, true);
lcd_write_nibble(lcd, 0x03, false, cmd);
i2c_master_stop(cmd);
i2c_master_cmd_begin(lcd->i2c_port, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
esp_rom_delay_us(4500);
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (lcd->i2c_addr << 1) | I2C_MASTER_WRITE, true);
lcd_write_nibble(lcd, 0x03, false, cmd);
i2c_master_stop(cmd);
i2c_master_cmd_begin(lcd->i2c_port, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
esp_rom_delay_us(200);
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (lcd->i2c_addr << 1) | I2C_MASTER_WRITE, true);
lcd_write_nibble(lcd, 0x03, false, cmd);
i2c_master_stop(cmd);
i2c_master_cmd_begin(lcd->i2c_port, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
esp_rom_delay_us(200);
// Set the data interface to 4-bit interface (PCF8574 uses 4-bit interface)
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (lcd->i2c_addr << 1) | I2C_MASTER_WRITE, true);
lcd_write_nibble(lcd, 0x02, false, cmd);
i2c_master_stop(cmd);
i2c_master_cmd_begin(lcd->i2c_port, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
// Instruction: function set = 0x20
lcd_send(lcd, 0x20 | (rows > 1 ? 0x08 : 0x00), false);
// Set the display parameters (turn on display, clear, and set left to right)
lcd_display(lcd);
lcd_clear(lcd);
lcd_left_to_right(lcd);
} // lcd_begin()
// Clear the display content
void lcd_clear(i2c_lcd_pcf8574_handle_t* lcd) {
// Instruction: Clear display = 0x01
lcd_send(lcd, 0x01, false);
// Clearing the display takes a while: takes approx. 1.5ms
esp_rom_delay_us(1600);
} // lcd_clear()
// Set the display to home
void lcd_home(i2c_lcd_pcf8574_handle_t* lcd) {
// Instruction: Return home = 0x02
lcd_send(lcd, 0x02, false);
// Same as clearing the display: takes approx. 1.5ms
esp_rom_delay_us(1600);
} // lcd_home()
// Set the cursor to a new position.
void lcd_set_cursor(i2c_lcd_pcf8574_handle_t* lcd, uint8_t col, uint8_t row) {
// Check the display boundaries
if (row >= lcd->lines) {
row = lcd->lines - 1;
}
if (col >= lcd->cols) {
col = lcd->cols - 1;
}
// Instruction: Set DDRAM address = 080
lcd_send(lcd, 0x80 | (lcd->row_offsets[row] + col), false);
} // lcd_set_cursor()
// Turn off the display: fast operation
void lcd_no_display(i2c_lcd_pcf8574_handle_t* lcd) {
// Display Control: Display on/off control = 0x04
lcd->displaycontrol &= ~0x04;
// Instruction: Display mode: 0x08
lcd_send(lcd, 0x08 | lcd->displaycontrol, false);
} // lcd_no_display()
// Turn on the display: fast operation
void lcd_display(i2c_lcd_pcf8574_handle_t* lcd) {
// Display Control: Display on/off control = 0x04
lcd->displaycontrol |= 0x04;
// Instruction: Display mode: 0x08
lcd_send(lcd, 0x08 | lcd->displaycontrol, false);
} // lcd_display()
// Turn on the cursor
void lcd_cursor(i2c_lcd_pcf8574_handle_t* lcd) {
// Display Control: Cursor on/off control = 0x02
lcd->displaycontrol |= 0x02;
// Instruction: Display mode: 0x08
lcd_send(lcd, 0x08 | lcd->displaycontrol, false);
} // lcd_cursor()
// Turn off the cursor
void lcd_no_cursor(i2c_lcd_pcf8574_handle_t* lcd) {
// Display Control: Cursor on/off control = 0x02
lcd->displaycontrol &= ~0x02;
// Instruction: Display mode: 0x08
lcd_send(lcd, 0x08 | lcd->displaycontrol, false);
} // lcd_no_cursor()
// Turn on the blinking
void lcd_blink(i2c_lcd_pcf8574_handle_t* lcd) {
// Display Control: Blink on/off control = 0x01
lcd->displaycontrol |= 0x01;
// Instruction: Display mode: 0x08
lcd_send(lcd, 0x08 | lcd->displaycontrol, false);
} // lcd_blink()
// Turn off the blinking
void lcd_no_blink(i2c_lcd_pcf8574_handle_t* lcd) {
// Display Control: Blink on/off control = 0x01
lcd->displaycontrol &= ~0x01;
// Instruction: Display mode: 0x08
lcd_send(lcd, 0x08 | lcd->displaycontrol, false);
} // lcd_no_blink()
// This command will scroll the display left by one step without changing the RAM
void lcd_scroll_display_left(i2c_lcd_pcf8574_handle_t* lcd) {
// Instruction: Cursor or display shift - 0x10
// Instruction: Display mode: 0x08
// Control: Left shift control = 0x00
// 0x10 | 0x08 | 0x00 = 0x18
lcd_send(lcd, 0x18, false);
} // lcd_scroll_display_left()
// This command will scroll the display right by one step without changing the RAM
void lcd_scroll_display_right(i2c_lcd_pcf8574_handle_t* lcd) {
// Instruction: Cursor or display shift - 0x10
// Instruction: Display mode: 0x08
// Control: Left shift control = 0x04
// 0x10 | 0x08 | 0x04 = 0x1C
lcd_send(lcd, 0x1C, false);
} // lcd_scroll_display_right()
// Controlling the entry mode: This is for text that flows left to right
void lcd_left_to_right(i2c_lcd_pcf8574_handle_t* lcd) {
// Instruction: Entry mode set, set increment/decrement = 0x02
lcd->entrymode |= 0x02;
lcd_send(lcd, 0x04 | lcd->entrymode, false);
} // lcd_left_to_right()
// Controlling the entry mode: This is for text that flows right to left
void lcd_right_to_left(i2c_lcd_pcf8574_handle_t* lcd) {
// Instruction: Entry mode set, clear increment/decrement = 0x02
lcd->entrymode &= ~0x02;
lcd_send(lcd, 0x04 | lcd->entrymode, false);
} // lcd_right_to_left()
// This will justify the text to the right from the cursor
void lcd_autoscroll(i2c_lcd_pcf8574_handle_t* lcd) {
// Instruction: Entry mode set, set shift = 0x01
lcd->entrymode |= 0x01;
lcd_send(lcd, 0x04 | lcd->entrymode, false);
} // lcd_autoscroll()
// This will justify the text to the left from the cursor
void lcd_no_autoscroll(i2c_lcd_pcf8574_handle_t* lcd) {
// Instruction: Entry mode set, clear shift = 0x01
lcd->entrymode &= ~0x01;
lcd_send(lcd, 0x04 | lcd->entrymode, false);
} // lcd_no_autoscroll()
// Setting the backlight: It can only be turn on or off.
// Current backlight value is saved in the i2c_lcd_pcf8574_handle_t struct for further data transfers
void lcd_set_backlight(i2c_lcd_pcf8574_handle_t* lcd, uint8_t brightness) {
// Place the backlight value in the lcd struct
lcd->backlight = brightness;
// Send no data
lcd_write_i2c(lcd, 0x00, true, false);
} // lcd_set_backlight()
// Custom character creation: allows us to create up to 8 custom characters in the CGRAM locations
void lcd_create_char(i2c_lcd_pcf8574_handle_t* lcd, uint8_t location, uint8_t charmap[]) {
location &= 0x7; // Only 8 locations are available
// Set the CGRAM address
lcd_send(lcd, 0x40 | (location << 3), false);
for (int i = 0; i < 8; i++) {
lcd_write(lcd, charmap[i]);
}
} // lcd_create_char()
// Write a byte to the LCD
void lcd_write(i2c_lcd_pcf8574_handle_t* lcd, uint8_t value) {
lcd_send(lcd, value, true);
} // lcd_write()
// Print characters to the LCD: cursor set or clear instruction must preceded this instruction, or it will write on the current text.
void lcd_print(i2c_lcd_pcf8574_handle_t* lcd, const char* str) {
while (*str) {
lcd_write(lcd, *str++);
}
} // lcd_print()
// Additional function to print numbers as formatted string
void lcd_print_number(i2c_lcd_pcf8574_handle_t* lcd, uint8_t col, uint8_t row, uint8_t buf_len, const char *str, ...) {
// Ensure the buffer length is greater than zero
if (buf_len == 0)
{
ESP_LOGE(TAG, "Buffer length must be greater than 0");
}
// Create a buffer to hold the characters
char buffer[buf_len];
va_list args;
va_start(args, str);
int chars_written = vsniprintf(buffer, buf_len, str, args);
va_end(args);
if (chars_written < 0) {
ESP_LOGE(TAG, "Encoding error in vsnprintf");
}
if ((size_t)chars_written >= buf_len) {
ESP_LOGW(TAG, "Buffer overflow: %d characters needed, but only %d available", chars_written + 1, buf_len);
}
lcd_set_cursor(lcd, col, row);
lcd_print(lcd, buffer);
} // lcd_print_number()
// Private functions: derived from the esp32 i2c_master driver
static void lcd_send(i2c_lcd_pcf8574_handle_t* lcd, uint8_t value, bool is_data) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (lcd->i2c_addr << 1) | I2C_MASTER_WRITE, true);
lcd_write_nibble(lcd, (value >> 4 & 0x0F), is_data, cmd);
lcd_write_nibble(lcd, (value & 0x0F), is_data, cmd);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(lcd->i2c_port, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to send data to LCD: %s", esp_err_to_name(ret));
}
} // lcd_send()
// Write a nibble / half byte with ACK
static void lcd_write_nibble(i2c_lcd_pcf8574_handle_t* lcd, uint8_t half_byte, bool is_data, i2c_cmd_handle_t cmd) {
// Map the data to the given pin connections
uint8_t data = is_data ? lcd->rs_mask : 0;
// Don't use rw_mask here
if (lcd->backlight > 0) {
data |= lcd->backlight_mask;
}
// Allow arbitrary pin configuration
if (half_byte & 0x01) data |= lcd->data_mask[0];
if (half_byte & 0x02) data |= lcd->data_mask[1];
if (half_byte & 0x04) data |= lcd->data_mask[2];
if (half_byte & 0x08) data |= lcd->data_mask[3];
i2c_master_write_byte(cmd, data | lcd->enable_mask, true);
i2c_master_write_byte(cmd, data, true);
} // lcd_write_nibble()
// Private function to change the PCF8574 pins to the given value.
static void lcd_write_i2c(i2c_lcd_pcf8574_handle_t* lcd, uint8_t data, bool is_data, bool enable) {
if (is_data) {
data |= lcd->rs_mask;
}
if (enable) {
data |= lcd->enable_mask;
}
if (lcd->backlight > 0) {
data |= lcd->backlight_mask;
}
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (lcd->i2c_addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, data, true);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(lcd->i2c_port, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to write to LCD: %s", esp_err_to_name(ret));
}
} // lcd_write_i2c()
+112
View File
@@ -0,0 +1,112 @@
/// \file i2c_lcd_pcf8574.h
/// \brief Liquid Crystal display driver with PCF8574 adapter for esp-idf
///
/// \author Femi Olugbon, https://iamflinks.github.io
/// \copyright Copyright (c) 2024 by Femi Olugbon
///
/// The library work is lincensed under a BSD style license.
///
/// \details
/// This library can drive a LCD based on the Hitachi's HD44790 display chip that is wired through a PCF8574 I2C converter. It uses the esp-idf i2c_driver component for communication. The library was adapted from the LiquidCrystal_PCF8574 (Mathias Hertel) and LiquidCrystal_I2C Arduino libraries.
///
///
/// ChangeLog:
/// ===========
/// * 07/22/2024 --> Created
/// * 07/23/2024 --> Added number printing functionality
///
#pragma once
#ifndef I2C_LCD_PCF8574_H
#define I2C_LCD_PCF8574_H
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "driver/i2c.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LCD_MAX_ROWS 4
typedef struct
{
uint8_t i2c_addr;
uint8_t backlight;
uint8_t cols;
uint8_t lines;
uint8_t entrymode;
uint8_t displaycontrol;
uint8_t row_offsets[LCD_MAX_ROWS];
uint8_t rs_mask;
uint8_t rw_mask;
uint8_t enable_mask;
uint8_t backlight_mask;
uint8_t data_mask[4];
i2c_port_t i2c_port;
} i2c_lcd_pcf8574_handle_t;
// Initialize the LCD
void lcd_init(i2c_lcd_pcf8574_handle_t* lcd, uint8_t i2c_addr, i2c_port_t i2c_port);
// Begin using the LCD
void lcd_begin(i2c_lcd_pcf8574_handle_t* lcd, uint8_t cols, uint8_t rows);
// Clear the LCD
void lcd_clear(i2c_lcd_pcf8574_handle_t* lcd);
// Move cursor to home position
void lcd_home(i2c_lcd_pcf8574_handle_t* lcd);
// Set cursor position
void lcd_set_cursor(i2c_lcd_pcf8574_handle_t* lcd, uint8_t col, uint8_t row);
// Turn the display on/off
void lcd_no_display(i2c_lcd_pcf8574_handle_t* lcd);
void lcd_display(i2c_lcd_pcf8574_handle_t* lcd);
// Turn the cursor on/off
void lcd_cursor(i2c_lcd_pcf8574_handle_t* lcd);
void lcd_no_cursor(i2c_lcd_pcf8574_handle_t* lcd);
// Turn blinking cursor on/off
void lcd_blink(i2c_lcd_pcf8574_handle_t* lcd);
void lcd_no_blink(i2c_lcd_pcf8574_handle_t* lcd);
// Scroll the display
void lcd_scroll_display_left(i2c_lcd_pcf8574_handle_t* lcd);
void lcd_scroll_display_right(i2c_lcd_pcf8574_handle_t* lcd);
// Set the direction for text that flows automatically
void lcd_left_to_right(i2c_lcd_pcf8574_handle_t* lcd);
void lcd_right_to_left(i2c_lcd_pcf8574_handle_t* lcd);
// Turn on/off autoscroll
void lcd_autoscroll(i2c_lcd_pcf8574_handle_t* lcd);
void lcd_no_autoscroll(i2c_lcd_pcf8574_handle_t* lcd);
// Set backlight brightness
void lcd_set_backlight(i2c_lcd_pcf8574_handle_t* lcd, uint8_t brightness);
// Create a custom character
void lcd_create_char(i2c_lcd_pcf8574_handle_t* lcd, uint8_t location, uint8_t charmap[]);
// Write a character to the LCD
void lcd_write(i2c_lcd_pcf8574_handle_t* lcd, uint8_t value);
// Print a string to the LCD
void lcd_print(i2c_lcd_pcf8574_handle_t* lcd, const char* str);
void lcd_print_number(i2c_lcd_pcf8574_handle_t* lcd, uint8_t col, uint8_t row, uint8_t buf_len, const char *str, ...);
#ifdef __cplusplus
}
#endif // C++ extern
#endif // I2C_LCD_PCF8574_H
+62 -6
View File
@@ -1,8 +1,36 @@
#include "leds.h"
#include "led_strip.h"
#include <esp_log.h>
#include "state_tracking.h"
#include <cstring>
led_strip_handle_t leds;
static const char* TAG = "leds";
static led_strip_handle_t leds;
// TODO: rename these to playback_handler
static bool replay_handler(const char* event, char* arg) {
if (strcmp(event, "LED_SET") == 0) {
uint32_t led = atoi(strtok(arg, ","));
uint32_t color = atoi(strtok(NULL, ","));
led_set(led, color);
return true;
}
if (strcmp(event, "LED_FLUSH") == 0) {
leds_flush();
return true;
}
if (strcmp(event, "LED_CLR") == 0) {
leds_clear();
return true;
}
return false;
}
void init_leds() {
ESP_LOGI(TAG, "Initializing LEDs...");
void init_leds(void) {
led_strip_config_t strip_config = {
.strip_gpio_num = NEOPIXEL_PIN,
.max_leds = LED_COUNT,
@@ -17,11 +45,39 @@ void init_leds(void) {
rmt_config.flags.with_dma = false;
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &leds));
register_replay_fn(replay_handler);
ESP_LOGI(TAG, "LEDs initialized!");
}
void example_leds(void) {
for (int i = 0; i < LED_COUNT; i++) {
ESP_ERROR_CHECK(led_strip_set_pixel(leds, i, i, LED_COUNT-i, 0));
void led_set(uint32_t led, uint8_t r, uint8_t g, uint8_t b) {
led_strip_set_pixel(leds, led, r, g, b);
if (is_state_tracking()) {
char buf[32];
uint32_t color = (r << 16) | (g << 8) | b;
sprintf(buf, "%ld,%ld", led, color);
event_occured("LED_SET", buf);
}
}
void led_set(uint32_t led, uint32_t color) {
led_set(led, (color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF);
}
void leds_flush() {
led_strip_refresh(leds);
if (is_state_tracking()) {
event_occured("LED_FLUSH", NULL);
}
}
void leds_clear() {
led_strip_clear(leds);
if (is_state_tracking()) {
event_occured("LED_CLR", NULL);
}
ESP_ERROR_CHECK(led_strip_refresh(leds));
}
+60 -27
View File
@@ -1,40 +1,73 @@
#ifndef LEDS_H
#define LEDS_H
#include "led_strip.h"
#include <stdint.h>
#define LED_COUNT 21
#define NEOPIXEL_PIN GPIO_NUM_7
// 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution)
#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000)
extern led_strip_handle_t leds;
enum LEDColor: uint32_t {
LED_COLOR_OFF = 0x00'00'00,
LED_COLOR_RED = 0x17'00'00,
LED_COLOR_RED_STRONG = 0xFF'00'00,
LED_COLOR_ORANGE = 0x17'02'00,
LED_COLOR_ORANGE_STRONG = 0xFF'20'00,
LED_COLOR_YELLOW = 0x07'07'00,
LED_COLOR_YELLOW_STRONG = 0xFF'FF'00,
LED_COLOR_GREEN = 0x00'07'00,
LED_COLOR_GREEN_STRONG = 0x00'FF'00,
LED_COLOR_BLUE = 0x00'00'17,
LED_COLOR_BLUE_STRONG = 0x00'00'FF,
LED_COLOR_PINK = 0x10'00'04,
LED_COLOR_PINK_STRONG = 0xFF'00'80,
LED_COLOR_WHITE = 0x04'04'04,
LED_COLOR_WHITE_STRONG = 0xFF'FF'FF,
};
typedef enum {
shape1 = 0,
shape2 = 1,
shape3 = 2,
shape4 = 3,
module_sseg = 4,
game_sseg = 5,
tft = 6,
mic = 7,
ir_led = 8,
speaker = 9,
rfid = 10,
keypad = 11,
char_lcd = 12,
switch4 = 13,
switch3 = 14,
switch2 = 15,
switch1 = 16,
button4 = 17,
button3 = 18,
button2 = 19,
button1 = 20,
} Led;
enum IndicatorLED {
LED_SHAPE1 = 0u,
LED_SHAPE2 = 1u,
LED_SHAPE3 = 2u,
LED_SHAPE4 = 3u,
LED_MODULE_SSEG = 4u,
LED_GAME_SSEG = 5u,
LED_TFT = 6u,
LED_MIC = 7u,
LED_IR_LED = 8u,
LED_SPEAKER = 9u,
LED_RFID = 10u,
LED_KEYPAD = 11u,
LED_LCD = 12u,
LED_S4 = 13u,
LED_S3 = 14u,
LED_S2 = 15u,
LED_S1 = 16u,
LED_B4 = 17u,
LED_B3 = 18u,
LED_B2 = 19u,
LED_B1 = 20u,
LED_MAX = 20u,
};
void init_leds(void);
void example_leds(void);
/// @brief Initializes the indicator LEDs
void init_leds();
/// Sets the color of an LED.
///
/// Call `flush_leds()` to send the data to the LEDs.
void led_set(uint32_t led, uint32_t color);
/// Sets the color of an LED with rgb.
///
/// Call `flush_leds()` to send the data to the LEDs.
void led_set(uint32_t led, uint8_t r, uint8_t g, uint8_t b);
/// Outputs the data to the leds.
void leds_flush();
/// Clears the LEDs
void leds_clear();
#endif /* LEDS_H */
+53
View File
@@ -0,0 +1,53 @@
#include "power.h"
#include "char_lcd.h"
#include <esp_log.h>
static const char* TAG = "power";
void bat_monitor_task(void* arg) {
while (1) {
char str_buf[33] = {0};
uint16_t voltage = lipo.voltage();
sprintf(str_buf, "%d.%03dV", voltage / 1000, voltage % 1000);
lcd_clear();
lcd_print(1, 0, str_buf);
int16_t current = lipo.current(current_measure::AVG);
sprintf(str_buf, "%dmA", current);
lcd_print(1, 1, str_buf);
int16_t total_cap = lipo.capacity(capacity_measure::FULL);
sprintf(str_buf, "%dmAh", total_cap);
lcd_print(1, 2, str_buf);
int16_t soc = lipo.soc(soc_measure::FILTERED);
sprintf(str_buf, "%d%%", soc);
lcd_print(1, 3, str_buf);
vTaskDelay(pdMS_TO_TICKS(250));
}
vTaskDelete(NULL);
}
void init_power_board() {
ESP_LOGI(TAG, "Initializing power board...");
if (!lipo.begin()) {
ESP_LOGE(TAG, "Failed to init communication with the battery gas guage");
return;
}
auto voltage = lipo.voltage();
ESP_LOGI(TAG, "Battery Voltage: %d", voltage);
ESP_LOGI(TAG, "Power board initialized!");
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef POWER_H
#define POWER_H
#include "SparkFunBQ27441/SparkFunBQ27441.h"
void bat_monitor_task(void* arg);
/// Initializes the battery gas guage for getting battery stats.
void init_power_board();
/// @brief Gets the battery voltage
/// @return battery voltage in mV.
uint16_t get_bat_voltage();
#endif /* POWER_H */
+56 -44
View File
@@ -1,74 +1,86 @@
#include "sd.h"
#include "char_lcd.h"
#include "bottom_half.h"
sdmmc_card_t *card;
static const char* mount_point = MOUNT_POINT;
static const char* TAG = "sd";
void init_sd() {
bool init_sd() {
ESP_LOGI(TAG, "Initializing SD card...");
esp_err_t ret;
// Options for mounting the filesystem.
// If format_if_mount_failed is set to true, SD card will be partitioned and
// formatted in case when mounting fails.
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = false,
.max_files = 5,
.max_files = 8,
.allocation_unit_size = 16 * 1024,
.disk_status_check_enable = false,
.disk_status_check_enable = true,
.use_one_fat = false,
};
ESP_LOGI(TAG, "Initializing SD card");
// Use settings defined above to initialize SD card and mount FAT filesystem.
// Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
// Please check its source code and implement error recovery when developing
// production applications.
ESP_LOGI(TAG, "Using SDMMC peripheral");
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
// This initializes the slot without card detect (CD) and write protect (WP) signals.
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
// Set bus width to use:
slot_config.width = 4;
// On chips where the GPIOs used for SD card can be configured, set them in
// the slot_config structure:
slot_config.clk = SD_PIN_CLK;
slot_config.cmd = SD_PIN_CMD;
slot_config.d0 = SD_PIN_D0;
slot_config.d1 = SD_PIN_D1;
slot_config.d2 = SD_PIN_D2;
slot_config.d3 = SD_PIN_D3;
// Enable internal pullups on enabled pins. The internal pullups
// are insufficient however, please make sure 10k external pullups are
// connected on the bus. This is for debug / example purpose only.
slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
sdmmc_slot_config_t slot_config = {
.clk = SD_PIN_CLK,
.cmd = SD_PIN_CMD,
.d0 = SD_PIN_D0,
.d1 = SD_PIN_D1,
.d2 = SD_PIN_D2,
.d3 = SD_PIN_D3,
.d4 = GPIO_NUM_NC,
.d5 = GPIO_NUM_NC,
.d6 = GPIO_NUM_NC,
.d7 = GPIO_NUM_NC,
.cd = GPIO_NUM_NC,
.wp = GPIO_NUM_NC,
.width = 4,
.flags = 0
// .flags = SDMMC_SLOT_FLAG_INTERNAL_PULLUP
};
try_mount:
ESP_LOGI(TAG, "Mounting filesystem");
ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount filesystem. "
"If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
} else {
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
}
return;
}
if (ret == ESP_OK) {
ESP_LOGI(TAG, "Filesystem mounted");
} else {
ESP_LOGE(TAG, "Failed to mount sd card: %s.", esp_err_to_name(ret));
lcd_print(0, 0, "SD: ");
lcd_print(4, 0, esp_err_to_name(ret));
lcd_print(0, 1, "Press Green to retry");
lcd_print(0, 2, "Press Yellow to skip");
lcd_print(0, 3, "Press Red to format");
ButtonKey button;
while (!( get_button_pressed(&button) && (button == ButtonKey::button_green || button == ButtonKey::button_red || button == ButtonKey::button_yellow) )) vTaskDelay(pdMS_TO_TICKS(10));
lcd_clear();
if (button == ButtonKey::button_green) {
goto try_mount;
}
if (button == ButtonKey::button_yellow) {
return false;
}
if (button == ButtonKey::button_red) {
mount_config.format_if_mount_failed = true;
goto try_mount;
}
}
// Card has been initialized, print its properties
sdmmc_card_print_info(stdout, card);
ESP_LOGI(TAG, "SD card initialized!");
return true;
}
void deinit_sd() {
esp_vfs_fat_sdcard_unmount(mount_point, card);
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_vfs_fat_sdcard_unmount(mount_point, card));
ESP_LOGI(TAG, "Card unmounted");
}
+8 -2
View File
@@ -8,7 +8,7 @@
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"
#define MOUNT_POINT "/sdcard"
#define MOUNT_POINT "/sd"
extern sdmmc_card_t *card;
@@ -19,7 +19,13 @@ extern sdmmc_card_t *card;
#define SD_PIN_D2 GPIO_NUM_39
#define SD_PIN_D3 GPIO_NUM_38
void init_sd();
/// @brief Initializes the SD card
///
/// This requires the char_lcd to have been initialized.
/// @return true if the sd card was successfully initialized
bool init_sd();
/// @brief Unmounts the sd card
void deinit_sd();
#endif /* SD_H */
+207 -82
View File
@@ -1,114 +1,224 @@
#include "speaker.h"
#include "state_tracking.h"
static const char *TAG = "speaker";
static size_t audio_block_size = 4096;
typedef struct {
/// The path to the file being played.
char* file_name;
/// The handle to the file being played.
FILE* file_handle;
/// A number that all samples will be shifted right by.
uint8_t prescaler;
/// A flag for repeating.
bool repeat;
} playing_audio_clip_t;
// It's hard to get the tx_chan's internal state, so instead, we keep track of it here.
bool channel_enabled = false;
i2s_chan_handle_t tx_chan;
static const char *TAG = "speaker_driver";
/// A queue of owned `char*` to be stopped from playing.
///
/// the speaker driver system will free the given char* when it is done with it.
QueueHandle_t stop_clip_queue;
/// A queue of `audio_clip_t`s to be played once there is nothing being played
QueueHandle_t play_clip_queue;
esp_err_t play_raw_stop_queue(const char *fp, QueueHandle_t stop_handle) {
FILE *fh = fopen(fp, "rb");
if (fh == NULL)
{
ESP_LOGE(TAG, "Failed to open file");
return ESP_ERR_INVALID_ARG;
/// The clips that are currently playing
std::vector<playing_audio_clip_t> playing_clips;
static bool replay_handler(const char* event, char* arg) {
if (strcmp(event, "PLAY_WAV") == 0) {
char* file_name = strtok(arg, ":");
char* play_immediately_str = strtok(NULL, ":");
char* repeat_str = strtok(NULL, ":");
char* prescaler_str = strtok(NULL, ":");
bool play_immediately = strcmp(play_immediately_str, "true") == 0;
bool repeat = strcmp(repeat_str, "true") == 0;
uint8_t prescaler = atoi(prescaler_str);
play_clip_wav(file_name, play_immediately, repeat, prescaler, 0);
return true;
}
if (strcmp(event, "STOP_WAV") == 0) {
stop_clip(arg, 0);
return true;
}
// create a writer buffer
uint8_t *read_buf = (uint8_t*) calloc(AUDIO_BUFFER, sizeof(uint8_t));
uint16_t *write_buf = (uint16_t*) calloc(AUDIO_BUFFER, sizeof(uint16_t));
size_t bytes_read = 0;
size_t bytes_written = 0;
esp_err_t channel_enable_result = i2s_channel_enable(tx_chan);
ESP_ERROR_CHECK_WITHOUT_ABORT(channel_enable_result);
if (channel_enable_result != ESP_OK) {
return channel_enable_result;
return false;
}
bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
for (int i = 0; i < bytes_read; i++) {
write_buf[i] = read_buf[i] << 4;
static bool push_clip(audio_clip_t clip) {
ESP_LOGD(TAG, "playing %s", clip.file_name);
FILE* fh = fopen(clip.file_name, "rb");
if (fh == NULL) {
ESP_LOGW(TAG, "failed to open %s", clip.file_name);
return false;
} else {
// skip the .wav header
fseek(fh, 44, SEEK_SET);
playing_audio_clip_t playing_clip = {
.file_name = clip.file_name,
.file_handle = fh,
.prescaler = clip.prescaler,
.repeat = clip.repeat,
};
playing_clips.push_back(playing_clip);
return true;
}
}
// i2s_channel_enable(tx_handle);
while (bytes_read > 0) {
// write the buffer to the i2s
// ESP_LOGI(TAG, "Writing: ");
// for (int i = 0; i < words_read; i++) {
// int16_t val = buf[i];
// printf("%s0x%04X ", (val < 0 ? "-" : "+"), (val < 0 ? -val : val));
// }>
i2s_channel_write(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY);
bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
for (int i = 0; i < bytes_read; i++) {
write_buf[i] = read_buf[i] << 4;
/// @brief Disables the channel if neccesary.
static void disable_channel() {
if (channel_enabled) {
ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_disable(tx_chan));
channel_enabled = false;
}
uint8_t recv = 0;
if (xQueueReceive(stop_handle, &recv, 0)) {
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
/// @brief Enables the channel if neccesary
static void enable_channel() {
if (!channel_enabled) {
ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_enable(tx_chan));
channel_enabled = true;
}
}
i2s_channel_disable(tx_chan);
free(read_buf);
free(write_buf);
fclose(fh);
static void speaker_task(void* arg) {
audio_clip_t next_clip;
char* clip_to_stop;
return ESP_OK;
int16_t* audio_buf = (int16_t*) malloc(audio_block_size * sizeof(int16_t));
int16_t* file_buf = (int16_t*) malloc(audio_block_size * sizeof(int16_t));
while (1) {
// first, take all "play immediatly" clips from the queue.
while (xQueuePeek(play_clip_queue, &next_clip, 0) == pdTRUE && next_clip.play_immediatly) {
if (xQueueReceive(play_clip_queue, &next_clip, 0) == pdTRUE) {
push_clip(next_clip);
}
}
esp_err_t play_raw(const char *fp) {
FILE *fh = fopen(fp, "rb");
if (fh == NULL)
{
ESP_LOGE(TAG, "Failed to open file");
return ESP_ERR_INVALID_ARG;
// handle any stop requests
while (xQueueReceive(stop_clip_queue, &clip_to_stop, 0) == pdTRUE) {
// delete clip from list
bool found = false;
for (int clip_idx = playing_clips.size()-1; clip_idx >= 0; clip_idx--) {
playing_audio_clip_t& clip = playing_clips.at(clip_idx);
if (strcmp(clip.file_name, clip_to_stop) == 0) {
found = true;
ESP_LOGV(TAG, "stopping %s", clip.file_name);
fclose(clip.file_handle);
free(clip.file_name);
playing_clips.erase(playing_clips.begin() + clip_idx);
}
}
if (!found) {
ESP_LOGW(TAG, "Could not find clip \"%s\" to stop", clip_to_stop);
}
// free the string that was passed into the queue
free(clip_to_stop);
}
// create a writer buffer
uint8_t *read_buf = (uint8_t*) calloc(AUDIO_BUFFER, sizeof(uint8_t));
uint16_t *write_buf = (uint16_t*) calloc(AUDIO_BUFFER, sizeof(uint16_t));
size_t bytes_read = 0;
size_t bytes_written = 0;
esp_err_t channel_enable_result = i2s_channel_enable(tx_chan);
ESP_ERROR_CHECK_WITHOUT_ABORT(channel_enable_result);
if (channel_enable_result != ESP_OK) {
return channel_enable_result;
// if we aren't playing any clips, wait for the next one.
if (playing_clips.empty()) {
if (xQueueReceive(play_clip_queue, &next_clip, 0) == pdTRUE) {
push_clip(next_clip);
} else {
// we must wait before our next clip
disable_channel();
// now wait for next clip
if (xQueueReceive(play_clip_queue, &next_clip, portMAX_DELAY) == pdTRUE) {
push_clip(next_clip);
}
}
}
bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
for (int i = 0; i < bytes_read; i++) {
write_buf[i] = read_buf[i] << 4;
// send 1 block
std::memset(audio_buf, 0, audio_block_size * sizeof(int16_t));
for (int clip_idx = playing_clips.size()-1; clip_idx >= 0; clip_idx--) {
playing_audio_clip_t& clip = playing_clips.at(clip_idx);
size_t samples_read = fread(file_buf, sizeof(uint16_t), audio_block_size, clip.file_handle);
if (samples_read == 0) {
if (clip.repeat) {
ESP_LOGV(TAG, "repeating %s", clip.file_name);
fseek(clip.file_handle, 44, SEEK_SET);
} else {
ESP_LOGV(TAG, "finishing %s", clip.file_name);
fclose(clip.file_handle);
free(clip.file_name);
playing_clips.erase(playing_clips.begin() + clip_idx);
}
continue;
}
// i2s_channel_enable(tx_handle);
while (bytes_read > 0) {
// write the buffer to the i2s
// ESP_LOGI(TAG, "Writing: ");
// for (int i = 0; i < words_read; i++) {
// int16_t val = buf[i];
// printf("%s0x%04X ", (val < 0 ? "-" : "+"), (val < 0 ? -val : val));
// }>
i2s_channel_write(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY);
bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
for (int i = 0; i < bytes_read; i++) {
write_buf[i] = read_buf[i] << 4;
for (int i = 0; i < samples_read; i++) {
audio_buf[i] += (file_buf[i] >> clip.prescaler);
}
vTaskDelay(pdMS_TO_TICKS(10));
}
i2s_channel_disable(tx_chan);
free(read_buf);
free(write_buf);
fclose(fh);
size_t bytes_to_write = audio_block_size * sizeof(int16_t);
size_t bytes_written;
if (!channel_enabled) {
ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_preload_data(tx_chan, audio_buf, bytes_to_write, &bytes_written));
enable_channel();
} else {
ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_write(tx_chan, audio_buf, bytes_to_write, &bytes_written, portMAX_DELAY));
}
if (bytes_written != bytes_to_write) {
ESP_LOGW(TAG, "only %d bytes written to the i2s channel! (expected %d)", bytes_written, bytes_to_write);
}
}
return ESP_OK;
vTaskDelete(NULL);
}
bool play_clip_wav(const char* file_name, bool play_immediately, bool repeat, uint8_t prescaler, TickType_t ticks_to_wait) {
// clone the passed in string to the heap.
size_t len = strlen(file_name);
char* dynamic_file_name = (char*) malloc(len+1);
strcpy(dynamic_file_name, file_name);
audio_clip_t clip = {
.file_name = dynamic_file_name,
.prescaler = prescaler,
.repeat = repeat,
.play_immediatly = play_immediately,
};
if (is_state_tracking()) {
char buf[64];
sprintf(buf, "%s:%d:%d:%d", file_name, play_immediately, repeat, prescaler);
event_occured("PLAY_WAV", buf);
}
if (play_immediately) {
return xQueueSendToFront(play_clip_queue, &clip, ticks_to_wait) == pdTRUE;
}
return xQueueSend(play_clip_queue, &clip, ticks_to_wait) == pdTRUE;
}
bool stop_clip(const char* file_name, TickType_t ticks_to_wait) {
// clone the passed in string to the heap.
size_t len = strlen(file_name);
char* dynamic_file_name = (char*) malloc(len+1);
strcpy(dynamic_file_name, file_name);
if (is_state_tracking()) {
event_occured("STOP_WAV", file_name);
}
return xQueueSend(stop_clip_queue, &dynamic_file_name, ticks_to_wait) == pdTRUE;
}
void init_speaker(void) {
ESP_LOGI(TAG, "Initializing speaker...");
i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&tx_chan_cfg, &tx_chan, NULL));
@@ -129,8 +239,23 @@ void init_speaker(void) {
},
};
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &tx_std_cfg));
i2s_chan_info_t info = {};
i2s_channel_get_info(tx_chan, &info);
if (info.total_dma_buf_size != 0) {
audio_block_size = info.total_dma_buf_size / sizeof(int16_t);
}
void play_example() {
ESP_ERROR_CHECK_WITHOUT_ABORT(play_raw("/sdcard/o.pcm"));
// init queues
play_clip_queue = xQueueCreate(CLIP_QUEUE_SIZE, sizeof(audio_clip_t));
stop_clip_queue = xQueueCreate(CLIP_QUEUE_SIZE, sizeof(char*));
// start task
xTaskCreate(speaker_task, "play_audio", 4096, NULL, 5, NULL);
play_clip_wav(MOUNT_POINT "/startup.wav", true, false, 4, 0);
register_replay_fn(replay_handler);
ESP_LOGI(TAG, "Speaker initialized!");
}
+39 -8
View File
@@ -3,6 +3,9 @@
#include <stdint.h>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <vector>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
@@ -16,17 +19,45 @@
#define SPEAKER_PIN_WS GPIO_NUM_9
#define SPEAKER_PIN_DOUT GPIO_NUM_3
#define SAMPLE_RATE 44100
#define AUDIO_BUFFER 2048
// The maximum number of clips that can be queued at one time.
#define CLIP_QUEUE_SIZE 64
extern i2s_chan_handle_t tx_chan;
/// Plays a audio file stopping when something is received on `stop_handle`
///
/// `stop_handle` should be of size `uint8_t`.
esp_err_t play_raw_stop_queue(const char *fp, QueueHandle_t stop_handle);
esp_err_t play_raw(const char *fp);
typedef struct {
/// A dynamically allocated string specifying the name of the
/// file to play. The speaker system will free this once it
/// is done.
char* file_name;
/// A number that all samples will be shifted right by.
uint8_t prescaler;
/// A flag for repeating.
bool repeat;
/// A flag for starting the clip immediatly,
/// even if there is another clip playing.
bool play_immediatly;
} audio_clip_t;
void init_speaker(void);
void play_example();
/// @brief Initalizes the speaker
void init_speaker();
/// @brief Plays a wav audio clip.
/// @param file_name The name of the file to play. Fully qualified with the `.wav` extention.
/// @param play_immediatly If `true`, the file will play immediatly even if there is already
/// another clip being played. The two clips will play simultaniously. If `false` the clip
/// will play once all the previous clips have finished.
/// @param repeat If `true` the clip will repeat until stopped. If `false` the clip will
/// stop when finished.
/// @param prescaler A number to shift right all samples by. This makes the music half as
/// loud. Useful for loud audio files.
/// @param ticks_to_wait The number of ticks to wait if the queue is full.
/// @return true if the clip was added to the queue.
bool play_clip_wav(const char* file_name, bool play_immediately, bool repeat, uint8_t prescaler, TickType_t ticks_to_wait);
/// @brief Stops an audio clip from playing.
/// @param file_name The file name of the audio clip that was played.
/// @param ticks_to_wait The number of ticks to wait if the queue is full.
/// @return true if the clip was added to the queue.
bool stop_clip(const char* file_name, TickType_t ticks_to_wait);
#endif /* SPEAKER_H */
+112 -13
View File
@@ -1,39 +1,138 @@
#include "sseg.h"
#include <esp_log.h>
#include "state_tracking.h"
#include <cstring>
TM1640* sseg = nullptr;
static const char *TAG = "sseg_driver";
static const char *TAG = "sseg";
static bool replay_handler(const char* event, char* arg) {
if (strcmp(event, "SSEG_G_RAW") == 0) {
uint8_t segments[4];
segments[0] = atoi(strtok(arg, ","));
for (int i = 1; i < 4; i++) {
segments[i] = atoi(strtok(NULL, ","));
}
set_game_sseg_raw(segments);
return true;
}
if (strcmp(event, "SSEG_G_CLR") == 0) {
clear_game_sseg();
return true;
}
if (strcmp(event, "SSEG_M_RAW") == 0) {
uint8_t segments[4];
segments[0] = atoi(strtok(arg, ","));
for (int i = 1; i < 4; i++) {
segments[i] = atoi(strtok(NULL, ","));
}
set_module_sseg_raw(segments);
return true;
}
if (strcmp(event, "SSEG_M_CLR") == 0) {
clear_module_sseg();
return true;
}
if (strcmp(event, "SSEG_G") == 0) {
uint32_t value = atoi(strtok(arg, ","));
uint8_t dot_pos = atoi(strtok(NULL, ","));
set_game_sseg_num(value, dot_pos);
return true;
}
if (strcmp(event, "SSEG_M") == 0) {
uint32_t value = atoi(strtok(arg, ","));
uint8_t dot_pos = atoi(strtok(NULL, ","));
set_module_sseg_num(value, dot_pos);
return true;
}
return false;
}
void init_sseg() {
ESP_LOGI(TAG, "Initializing sseg...");
sseg = new TM1640(SSEG_PIN_DATA, SSEG_PIN_CLK, 8);
register_replay_fn(replay_handler);
ESP_LOGI(TAG, "Sseg initialized!");
}
void set_game_sseg_raw(const uint8_t* digits) {
sseg->setSegments(digits[0], 0);
sseg->setSegments(digits[1], 1);
sseg->setSegments(digits[2], 2);
sseg->setSegments(digits[3], 3);
void set_game_sseg_raw(const uint8_t* segments) {
sseg->setSegments(segments[0], 0);
sseg->setSegments(segments[1], 1);
sseg->setSegments(segments[2], 2);
sseg->setSegments(segments[3], 3);
if (is_state_tracking()) {
char buf[32];
sprintf(buf, "%d,%d,%d,%d", segments[0], segments[1], segments[2], segments[3]);
event_occured("SSEG_G_RAW", buf);
}
}
void clear_game_sseg() {
sseg->setSegments(0, 0);
sseg->setSegments(0, 1);
sseg->setSegments(0, 2);
sseg->setSegments(0, 3);
if (is_state_tracking()) {
event_occured("SSEG_G_CLR", NULL);
}
}
void set_module_sseg_raw(const uint8_t* digits) {
sseg->setSegments(digits[0], 4);
sseg->setSegments(digits[1], 5);
sseg->setSegments(digits[2], 6);
sseg->setSegments(digits[3], 7);
void set_module_sseg_raw(const uint8_t* segments) {
sseg->setSegments(segments[0], 4);
sseg->setSegments(segments[1], 5);
sseg->setSegments(segments[2], 6);
sseg->setSegments(segments[3], 7);
if (is_state_tracking()) {
char buf[32];
sprintf(buf, "%d,%d,%d,%d", segments[0], segments[1], segments[2], segments[3]);
event_occured("SSEG_M_RAW", buf);
}
}
void set_game_sseg_num(unsigned int value, int dot_pos) {
void clear_module_sseg() {
sseg->setSegments(0, 4);
sseg->setSegments(0, 5);
sseg->setSegments(0, 6);
sseg->setSegments(0, 7);
if (is_state_tracking()) {
event_occured("SSEG_M_CLR", NULL);
}
}
void set_game_sseg_num(uint32_t value, uint8_t dot_pos) {
uint32_t initial_value = value;
for (int i = 0; i < 4; i++) {
auto idx = value % 10;
sseg->sendChar(3-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
value = value / 10;
}
if (is_state_tracking()) {
char buf[16];
sprintf(buf, "%ld,%d", initial_value, dot_pos);
event_occured("SSEG_G", buf);
}
}
void set_module_sseg_num(unsigned int value, int dot_pos) {
void set_module_sseg_num(uint32_t value, uint8_t dot_pos) {
uint32_t initial_value = value;
for (int i = 0; i < 4; i++) {
auto idx = value % 10;
sseg->sendChar(7-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
value = value / 10;
}
if (is_state_tracking()) {
char buf[16];
sprintf(buf, "%ld,%d", initial_value, dot_pos);
event_occured("SSEG_M", buf);
}
}
+12 -6
View File
@@ -12,24 +12,30 @@ extern TM1640* sseg;
/// Initializes the seven segment driver
void init_sseg();
/// sets the game seven segment to the value of the digits
/// @brief Sets the game seven segment to the value of `segments`.
///
/// the bits 0-6 map to segments A-G, and bit 7 is DP.
///
/// `digits` must have len >= 4.
void set_game_sseg_raw(const uint8_t* digits);
void set_game_sseg_raw(const uint8_t* segments);
/// sets the module seven segment to the value of the digits
/// @brief Clears the game seven segment display.
void clear_game_sseg();
/// @brief Sets the module seven segment to the value of the `segments`.
///
/// the bits 0-6 map to segments A-G, and bit 7 is DP.
///
/// `digits` must have len >= 4.
void set_module_sseg_raw(const uint8_t* digits);
void set_module_sseg_raw(const uint8_t* segments);
/// @brief Clears the game seven segment display.
void clear_module_sseg();
/// sets the game timer to the given number, with the dot at position `dot_pos` from the right (0 => right-most digit).
void set_game_sseg_num(unsigned int value, int dot_pos);
void set_game_sseg_num(uint32_t value, uint8_t dot_pos);
/// sets the module timer to the given number, with the dot at position `dot_pos` from the right (0 => right-most digit).
void set_module_sseg_num(unsigned int value, int dot_pos);
void set_module_sseg_num(uint32_t value, uint8_t dot_pos);
#endif /* SSEG_H */
+226
View File
@@ -0,0 +1,226 @@
#include "state_tracking.h"
#include <unistd.h>
#include <vector>
#include "wlvgl.h"
static const char* PLAYBACK_TAG = "playback";
enum state_t {
STATE_IDLE = 0,
STATE_RECORDING = 1,
STATE_PLAYBACK = 2,
};
static std::vector<bool(*)(const char*, char*)> replay_fns;
static bool should_close_recording_stream;
static FILE* recording_stream;
static uint32_t recording_start_time;
TaskHandle_t flush_file_task_handle;
static bool should_close_playback_stream;
static FILE* playback_stream;
static uint32_t playback_start_time;
TaskHandle_t playback_task_handle;
static volatile state_t state = STATE_IDLE;
/// @brief Periodically flushes and syncs (if neccesary) the output stream.
/// @param arg unused.
static void flush_file_task(void* arg) {
while (state == STATE_RECORDING && recording_stream != nullptr) {
fflush(recording_stream);
int fd = fileno(recording_stream);
if (fd != -1) {
fsync(fd);
}
vTaskDelay(pdMS_TO_TICKS(5000));
}
flush_file_task_handle = NULL;
vTaskDelete(NULL);
}
static void playback_task(void* arg) {
const size_t size = 16*1024;
char* buf = (char*) malloc(size*sizeof(char));
if (buf == nullptr) {
ESP_LOGE(PLAYBACK_TAG, "buf alloc failure");
vTaskDelete(NULL);
}
while (state == STATE_PLAYBACK && playback_stream != nullptr) {
char* ret = fgets(buf, size, playback_stream);
if (ret == nullptr) {
break;
}
if (buf[0] == '\0') {
ESP_LOGI(PLAYBACK_TAG, "playback done");
break;
}
// get rid of the '\n' and possibly '\r' in the string
for (int i = 0; i < size; i++) {
if (buf[i] == '\0') break;
if (buf[i] == '\r' || buf[i] == '\n') {
buf[i] = '\0';
break;
}
}
ESP_LOGI(PLAYBACK_TAG, "handling: %s", buf);
// look for a comma, indicating the end of the "ticks" part
// TODO: replace with strtok
size_t comma_pos = 0;
for (int i = 0; i < 11; i++) {
if (buf[i] == ',') {
comma_pos = i;
break;
}
}
if (comma_pos == 0) {
ESP_LOGE(PLAYBACK_TAG, "Failed to find comma in playback line");
continue;
}
buf[comma_pos] = '\0';
uint32_t tick = atoi(buf);
// now look for the colon to indicate the end of the event name
size_t colon_pos = 0;
int i = comma_pos + 1; // start looking right after the comma
while (i < size) {
if (buf[i] == ':') {
colon_pos = i;
break;
}
i++;
}
if (colon_pos == 0) {
ESP_LOGE(PLAYBACK_TAG, "Failed to find colon in playback line");
continue;
}
buf[colon_pos] = '\0';
char* event_name = buf + (comma_pos + 1);
char* arg = buf + (colon_pos + 1);
int32_t ticks_to_wait = ((int32_t) tick) - (int32_t)(xTaskGetTickCount() - playback_start_time);
if (ticks_to_wait < 0) {
ESP_LOGW(PLAYBACK_TAG, "Playback is behind by %ld ticks!", ticks_to_wait);
}
if (ticks_to_wait > 0) {
vTaskDelay(ticks_to_wait);
}
bool matched = false;
for (const auto& fn : replay_fns) {
matched = (fn)(event_name, arg);
if (matched) break;
}
if (!matched) {
ESP_LOGW(PLAYBACK_TAG, "Failed to match event: %s!", event_name);
}
}
free(buf);
playback_task_handle = NULL;
stop_playback();
vTaskDelete(NULL);
}
void register_replay_fn(bool (*replay_fn)(const char*, char*)) {
replay_fns.push_back(replay_fn);
}
void event_occured(const char* name, const char* arg) {
if (state != STATE_RECORDING) return;
if (name == nullptr) return;
if (recording_stream == nullptr) {
ESP_LOGE("state_tracking", "We are in state recording, but recording stream is null");
return;
}
arg = (arg == nullptr) ? "" : arg;
uint32_t ticks = xTaskGetTickCount() - recording_start_time;
fprintf(recording_stream, "%ld,%s:%s\n", ticks, name, (arg == nullptr) ? "" : arg);
}
bool set_recording_source(FILE* stream, bool should_close) {
if (state == STATE_RECORDING) return false;
recording_stream = stream;
should_close_recording_stream = should_close;
return true;
}
bool set_playback_source(FILE* stream, bool should_close) {
if (state == STATE_PLAYBACK) return false;
playback_stream = stream;
should_close_playback_stream = should_close;
return true;
}
bool start_recording() {
if (state != STATE_IDLE) return false;
if (recording_stream == nullptr) return false;
state = STATE_RECORDING;
recording_start_time = xTaskGetTickCount();
xTaskCreate(flush_file_task, "flush_recording", 2048, NULL, 2, &flush_file_task_handle);
reset_wlv_tables(); // TODO: generify this
return true;
}
bool stop_recording() {
if (state != STATE_RECORDING) return false;
state = STATE_IDLE;
fflush(recording_stream);
if (should_close_recording_stream) {
fclose(recording_stream);
recording_stream = nullptr;
}
if (flush_file_task_handle != nullptr) {
vTaskDelete(flush_file_task_handle);
flush_file_task_handle = NULL;
}
return true;
}
bool start_playback() {
if (state != STATE_IDLE) return false;
if (playback_stream == nullptr) return false;
state = STATE_PLAYBACK;
playback_start_time = xTaskGetTickCount();
xTaskCreate(playback_task, "playback", 4096, NULL, 2, &playback_task_handle);
reset_wlv_tables(); // TODO: generify this
return true;
}
bool stop_playback() {
if (state != STATE_PLAYBACK) return false;
state = STATE_IDLE;
if (should_close_playback_stream) {
fclose(playback_stream);
playback_stream = nullptr;
}
if (playback_task_handle != nullptr) {
// TODO: NO!! This leaks the malloc. Instead, use a queue to request a graceful stop
vTaskDelete(playback_task_handle);
playback_task_handle = NULL;
}
return true;
}
bool is_state_tracking() {
return state == STATE_RECORDING;
}
+53
View File
@@ -0,0 +1,53 @@
#ifndef STATE_TRACKING_H
#define STATE_TRACKING_H
#include <stdint.h>
#include "esp_vfs_fat.h"
/// @brief Registers function to be called on replay.
/// @param replay_callback A function to call to playback the event.
void register_replay_fn(bool (*replay_fn)(const char*, char*));
// TODO: add one for generically responding to all events.
/// @brief Call this to indicate that the bomb state has transitioned.
/// @param name The name of the event that has occured.
/// @param arg The serialized data associated with the event.
/// This must not contain newline characters such as '\n' or '\r'
void event_occured(const char* name, const char* arg);
/// @brief Sets the recording source.
/// @param stream The stream to record to.
/// @param should_close whether or not the stream should be closed when finished.
/// @return true if the source was updated.
bool set_recording_source(FILE* stream, bool should_close);
/// @brief Sets the playback source.
/// @param stream The stream to playback from.
/// @param should_close whether or not the stream should be closed when finished.
/// @return true if the source was updated.
bool set_playback_source(FILE* stream, bool should_close);
/// @brief Starts recording to the stream specified by `set_recording_source()`.
/// @return true if starting recording is successful.
bool start_recording();
/// @brief Stops recording the state.
/// @return true if stopping the recording is successful.
bool stop_recording();
/// @brief Starts playing back the recording specified by `set_playback_source()`.
/// @return true if starting playback is successful.
bool start_playback();
/// @brief Stops playing back the recording.
/// @return true if stopping the playback is successful.
bool stop_playback();
/// @brief Gets weather or not we are tracking the state
/// This can be helpful to conditionally do extra computation only
/// when we are tracking the state.
/// @return
bool is_state_tracking();
#endif /* STATE_TRACKING_H */
+58 -13
View File
@@ -1,4 +1,5 @@
#include "tft.h"
#include "state_tracking.h"
static const char* TAG = "tft";
@@ -16,6 +17,10 @@ static lv_style_t style_screen;
SemaphoreHandle_t xGuiSemaphore;
static bool replay_handler(const char* event, char* arg) {
return false;
}
static bool notify_lvgl_flush_ready(
esp_lcd_panel_io_handle_t panel_io,
esp_lcd_panel_io_event_data_t *edata,
@@ -26,6 +31,14 @@ static bool notify_lvgl_flush_ready(
return false;
}
const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/// Base 64 encodes a u16... sort of. This doesn't do any of the fancy padding stuff.
static void encode_base64(char* buf, size_t start_idx, uint16_t value) {
buf[start_idx+0] = base64_chars[(value >> 10) & 0x3F];
buf[start_idx+1] = base64_chars[(value >> 4) & 0x3F];
buf[start_idx+2] = base64_chars[(value << 2) & 0x3F];
}
static void lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) {
esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
@@ -33,7 +46,46 @@ static void lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t
int offsetx2 = area->x2;
int offsety1 = area->y1;
int offsety2 = area->y2;
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
// TODO: change this to be a kconfig value
#if false
if (is_state_tracking()) {
size_t size = (offsetx2 + 1 - offsetx1) * (offsety2 + 1 - offsety1) + 1;
// if (size > 1024) {
// ESP_LOGW("tft_track_state", "Write too big (%d)! truncating to 1024!", size);
// }
// size = MIN(1024, size);
// 24 bytes for the offsets
// 3 bytes per encoded color
// 1 byte for null terminator
size_t alloc_size = 24 + size * 3 + 1;
char* buf = (char*)malloc(alloc_size);
if (buf != nullptr) {
size_t initial_offset = sprintf(buf, "%d,%d,%d,%d:", offsetx1, offsety1, offsetx2 + 1, offsety2 + 1);
for (size_t i = 0; i < size; i++) {
size_t index = initial_offset + i * 3;
// we assume that the size of the color data is 16b
static_assert(sizeof(lv_color_t) == sizeof(uint16_t), "lv_color_t must be 16b wide");
encode_base64(buf, index, color_map[i].full);
}
buf[initial_offset + (size-1) * 3 + 1] = '\0';
event_occured("TFT_W", buf);
free(buf);
} else {
ESP_LOGE("tft_track_state", "buffer alloc failed!");
}
}
#endif
}
static void IRAM_ATTR lv_tick_task(void *param) {
@@ -87,7 +139,6 @@ static void initialize_display() {
}
};
const esp_lcd_panel_dev_config_t lcd_config = {
.reset_gpio_num = TFT_PIN_RESET,
.color_space = LCD_RGB_ELEMENT_ORDER_BGR,
@@ -151,10 +202,10 @@ static void guiTask(void *pvParameter) {
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &periodic_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LVGL_UPDATE_PERIOD_MS * 1000));
screen = lv_disp_get_scr_act(NULL);
screen = lv_scr_act();
lv_style_init(&style_screen);
lv_style_set_bg_color(&style_screen, lv_color_black());
lv_obj_add_style(lv_scr_act(), &style_screen, LV_STATE_DEFAULT);
lv_obj_add_style(screen, &style_screen, LV_STATE_DEFAULT);
while (1) {
/* Delay 1 tick (assumes FreeRTOS tick is 10ms */
@@ -170,20 +221,14 @@ static void guiTask(void *pvParameter) {
vTaskDelete(NULL);
}
static void tick_timer_task(void* arg) {
while (1)
{
lv_task_handler();
vTaskDelay(pdMS_TO_TICKS(10));
}
}
void init_tft() {
ESP_LOGI(TAG, "Initializing TFT...");
initialize_spi();
initialize_display();
xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 5, NULL, 1);
// xTaskCreatePinnedToCore(tick_timer_task, "tick_lvgl", 4096, NULL, 5, NULL, 1);
register_replay_fn(replay_handler);
ESP_LOGI(TAG, "TFT initialization Successful");
ESP_LOGI(TAG, "TFT initialized!");
}
+1 -1
View File
@@ -22,7 +22,7 @@
#include <esp_lcd_panel_io.h>
#include <esp_lcd_panel_vendor.h>
#include <esp_lcd_panel_ops.h>
#include <esp_lcd_ili9488.h>
#include "esp_lcd_ili9488/esp_lcd_ili9488.h"
#include <esp_timer.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
+10 -4
View File
@@ -1,10 +1,14 @@
#include "wires.h"
extern uint32_t current_step;
uint32_t total_strikes;
uint32_t step_strikes[N_STEPS] = {0};
uint32_t step_finish_times[N_STEPS] = {0};
static const char *TAG = "wires";
static const uint32_t STRIKE_TIME_PENALTY = 30'000;
const uint32_t STRIKE_TIME_PENALTY = 30'000;
static bool button_state;
static bool button_pressed;
@@ -79,12 +83,14 @@ void clear_wires_pressed_released_cut(void) {
button_released = false;
}
void strike(char* reason) {
void strike(const char* reason) {
ESP_LOGW("strike!", "%s", reason);
lcd_set_cursor(&lcd, 0, 3);
lcd_print(&lcd, reason);
lcd_print(0, 3, reason);
time_penalty(STRIKE_TIME_PENALTY);
if (current_step > 0 && current_step <= N_STEPS) {
total_strikes += 1;
step_strikes[current_step - 1] += 1;
}
uint8_t reg = 6;
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_to_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, &reg, 1, (100 / portTICK_PERIOD_MS)));
}
+6 -1
View File
@@ -7,6 +7,7 @@
#include <esp_log.h>
#include "drivers/char_lcd.h"
#include "drivers/game_timer.h"
#include "main.h"
#define WIRES_PIN_DELTA GPIO_NUM_2
#define WIRES_I2C_NUM I2C_NUM_1
@@ -15,6 +16,10 @@
#define DELTA_BIT_WIRES 0
#define DELTA_BIT_BUTTON 1
extern const uint32_t STRIKE_TIME_PENALTY;
extern uint32_t step_strikes[N_STEPS];
extern uint32_t step_finish_times[N_STEPS];
extern uint32_t total_strikes;
void init_wires(void);
@@ -29,6 +34,6 @@ void clear_wires_pressed_released_cut(void);
void set_leds(uint8_t led_states);
void strike(char* reason);
void strike(const char* reason);
#endif /* WIRES_HPP */
+55
View File
@@ -0,0 +1,55 @@
#include "wlvgl.h"
#include <vector>
/// A table that maps an incrementing integer to a style reference
static std::vector<lv_style_t*> style_table;
/// A table that maps an incrementing integer to a style reference
static std::vector<lv_obj_t*> obj_table;
void reset_wlv_tables() {
style_table.clear();
obj_table.clear();
}
lv_obj_t wlv_obj_create(lv_obj_t* parent) {
// initialize the obj
lv_obj_t value = lv_obj_create(parent);
if (is_state_tracking()) {
// add the style to the table
obj_table.push_back(value);
size_t obj_index = obj_table.size();
char buf[8];
sprintf(buf, "%d", obj_index);
event_occured("lv_obj_create", buf);
}
return value;
}
void wlv_style_init(lv_style_t* style) {
// initialize the style
lv_style_init(style);
if (is_state_tracking()) {
// add the style to the table
style_table.push_back(style);
size_t style_index = style_table.size();
char buf[8];
sprintf(buf, "%d", style_index);
event_occured("lv_style_init", buf);
}
}
void wlv_obj_set_style_bg_color(lv_obj_t* obj, lv_color_t value, lv_style_selector_t selector) {
lv_obj_set_style_bg_color(obj, value, selector);
if (is_state_tracking()) {
char buf[8];
sprintf(buf, "%d", style_index);
event_occured("lv_obj_set_style_bg_color", buf);
}
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef WLVGL_H
#define WLVGL_H
#include "lvgl.h"
#include "state_tracking.h"
void reset_wlv_tables();
void wlv_obj_create(lv_obj_t* parent);
void wlv_style_init(lv_style_t* style);
void wlv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
#endif /* WLVGL_H */
+114 -25
View File
@@ -1,13 +1,14 @@
#include "helper.h"
// TODO: move to driver
void clean_bomb(void) {
// clear pending inputs
clear_all_pressed_released();
clear_wires_pressed_released_cut();
// clear leds
led_strip_clear(leds);
led_strip_refresh(leds);
leds_clear();
leds_flush();
// clear module timer
stop_module_timer();
@@ -16,23 +17,11 @@ void clean_bomb(void) {
set_module_sseg_raw(clear);
// clear char lcd
lcd_clear(&lcd);
lcd_no_cursor(&lcd);
lcd_set_cursor(&lcd, 0, 0);
lcd_clear();
lcd_set_cursor_vis(false);
lcd_cursor_home();
}
void poster_child_task(void* arg) {
while (1) {
if (get_help_button_pressed()) {
play_raw(MOUNT_POINT "/poster.pcm");
}
vTaskDelay(pdMS_TO_TICKS(10));
}
vTaskDelete(NULL);
}
static const int STRING_MAX_LEN = 8;
void do_star_codes(StarCodeHandler* star_codes, int star_codes_len) {
KeypadKey key;
@@ -41,7 +30,7 @@ void do_star_codes(StarCodeHandler* star_codes, int star_codes_len) {
char current[STRING_MAX_LEN+1] = {0};
while (1) {
while (get_pressed_keypad(&key)) {
while (get_keypad_pressed(&key)) {
if (key == KeypadKey::star) {
current[0] = '*';
for (int i = 1; i < STRING_MAX_LEN; i++) {
@@ -59,8 +48,7 @@ void do_star_codes(StarCodeHandler* star_codes, int star_codes_len) {
StarCodeHandler sch = star_codes[i];
if (strcmp(current, sch.code) == 0) {
hit = true;
lcd_set_cursor(&lcd, 1, 2);
lcd_print(&lcd, sch.display_text);
lcd_print(1, 2, sch.display_text);
vTaskDelay(pdMS_TO_TICKS(2000));
if (sch.callback != nullptr) {
(sch.callback)();
@@ -73,8 +61,7 @@ void do_star_codes(StarCodeHandler* star_codes, int star_codes_len) {
}
if (!hit) {
lcd_set_cursor(&lcd, 1, 2);
lcd_print(&lcd, "Invalid Star Code");
lcd_print(1, 2, "Invalid Star Code");
vTaskDelay(pdMS_TO_TICKS(2000));
}
@@ -94,11 +81,113 @@ void do_star_codes(StarCodeHandler* star_codes, int star_codes_len) {
}
// ESP_LOGI(STEP0_TAG, "Pressed: %c", c);
lcd_clear(&lcd);
lcd_set_cursor(&lcd, 1, 1);
lcd_print(&lcd, current);
lcd_clear();
lcd_print(1, 1, current);
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
static lv_obj_t* old_scr;
static lv_obj_t* scr;
static lv_style_t game_results_style;
static lv_obj_t* overall_results_label;
static lv_obj_t* breakdown_results_label;
static lv_obj_t* strike_numbers_label;
static lv_obj_t* step_times_label;
static void write_time(char* buf, int32_t game_time) {
char minus[2] = "\0";
if (game_time < 0) {
minus[0] = '-';
game_time = -game_time;
}
uint8_t hours = (game_time / (1000*60*60)) % 10;
uint8_t minutes = (game_time / (1000*60)) % 60;
uint8_t seconds = (game_time / (1000)) % 60;
sprintf(buf, "%s%d:%02d:%02d", minus, hours, minutes, seconds);
}
extern uint32_t initial_game_time;
void display_game_results(void) {
while (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdFALSE) vTaskDelay(pdMS_TO_TICKS(10));
scr = lv_obj_create(NULL);
lv_obj_set_style_bg_color(scr, lv_color_black(), LV_STATE_DEFAULT);
lv_style_init(&game_results_style);
lv_style_set_text_color(&game_results_style, lv_color_white());
lv_style_set_text_align(&game_results_style, LV_TEXT_ALIGN_LEFT);
overall_results_label = lv_label_create(scr);
lv_obj_align(overall_results_label, LV_ALIGN_TOP_LEFT, 20, 20);
lv_obj_set_size(overall_results_label, 460, 140);
lv_obj_add_style(overall_results_label, &game_results_style, LV_STATE_DEFAULT);
breakdown_results_label = lv_label_create(scr);
lv_obj_align(breakdown_results_label, LV_ALIGN_BOTTOM_LEFT, 20, 0);
lv_obj_set_size(breakdown_results_label, 460, 140);
lv_obj_add_style(breakdown_results_label, &game_results_style, LV_STATE_DEFAULT);
strike_numbers_label = lv_label_create(scr);
lv_obj_align(strike_numbers_label, LV_ALIGN_BOTTOM_LEFT, 90, 0);
lv_obj_set_size(strike_numbers_label, 60, 140);
lv_obj_add_style(strike_numbers_label, &game_results_style, LV_STATE_DEFAULT);
lv_obj_set_style_text_align(strike_numbers_label, LV_TEXT_ALIGN_RIGHT, LV_STATE_DEFAULT);
step_times_label = lv_label_create(scr);
lv_obj_align(step_times_label, LV_ALIGN_BOTTOM_LEFT, 140, 0);
lv_obj_set_size(step_times_label, 80, 140);
lv_obj_add_style(step_times_label, &game_results_style, LV_STATE_DEFAULT);
lv_obj_set_style_text_align(step_times_label, LV_TEXT_ALIGN_RIGHT, LV_STATE_DEFAULT);
char buf[1024] = {0};
char time_buf_1[32] = {0};
char time_buf_2[32] = {0};
char time_buf_3[32] = {0};
char time_buf_4[32] = {0};
char time_buf_5[32] = {0};
char time_buf_6[32] = {0};
int32_t time_left = get_game_time();
int32_t time_spent = initial_game_time - time_left;
int32_t true_time_spent = time_spent - (total_strikes * STRIKE_TIME_PENALTY);
write_time(time_buf_1, time_left);
write_time(time_buf_2, time_spent);
write_time(time_buf_3, true_time_spent);
sprintf(buf,
"Finished!\n\tTotal Strikes: %ld\n\tTime Left (w/ penalties): %s\n\tTime Spent (w/ penalties): %s\n\tTrue Time Spent: %s\n\n",
total_strikes, time_buf_1, time_buf_2, time_buf_3
);
lv_label_set_text(overall_results_label, buf);
lv_label_set_text(breakdown_results_label, "Step Breakdown:\n\tStep 1: \n\tStep 2:\n\tStep 3:\n\tStep 4:\n\tStep 5:\n\tStep 6:");
sprintf(buf,
"\n%ld strikes\n%ld strikes\n%ld strikes\n%ld strikes\n%ld strikes\n%ld strikes",
step_strikes[0], step_strikes[1], step_strikes[2], step_strikes[3], step_strikes[4], step_strikes[5]
);
lv_label_set_text(strike_numbers_label, buf);
write_time(time_buf_1, initial_game_time - step_finish_times[0]);
write_time(time_buf_2, step_finish_times[0] - step_finish_times[1]);
write_time(time_buf_3, step_finish_times[1] - step_finish_times[2]);
write_time(time_buf_4, step_finish_times[2] - step_finish_times[3]);
write_time(time_buf_5, step_finish_times[3] - step_finish_times[4]);
write_time(time_buf_6, step_finish_times[4] - step_finish_times[5]);
sprintf(buf,
"\n%s\n%s\n%s\n%s\n%s\n%s",
time_buf_1, time_buf_2, time_buf_3, time_buf_4, time_buf_5, time_buf_6
);
lv_label_set_text(step_times_label, buf);
old_scr = lv_scr_act();
lv_scr_load(scr);
xSemaphoreGive(xGuiSemaphore);
}
+4 -2
View File
@@ -8,10 +8,11 @@
#include "drivers/char_lcd.h"
#include "drivers/leds.h"
#include "drivers/speaker.h"
#include "drivers/tft.h"
struct StarCodeHandler {
char* code;
char* display_text;
const char* code;
const char* display_text;
bool should_exit;
void (*callback)(void);
};
@@ -23,5 +24,6 @@ struct StarCodeHandler {
void clean_bomb(void);
void poster_child_task(void* arg);
void do_star_codes(StarCodeHandler* star_codes, int star_codes_len);
void display_game_results();
#endif /* HELPER_H */
+1 -1
View File
@@ -3,7 +3,7 @@ dependencies:
# iamflinks/i2c_lcd_pcf8574: "^1.0.1"
espressif/led_strip: "^2.5.4"
lvgl/lvgl: "^8.1"
atanisoft/esp_lcd_ili9488: "^1.0.9"
# atanisoft/esp_lcd_ili9488: "^1.0.9"
## Required IDF version
idf:
version: ">=4.1.0"
+43 -57
View File
@@ -1,18 +1,14 @@
#include "main.h"
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/i2c.h"
#include "drivers/tft.h"
#include "drivers/wires.h"
#include "drivers/bottom_half.h"
#include "drivers/sd.h"
#include "drivers/game_timer.h"
#include "drivers/speaker.h"
#include "drivers/char_lcd.h"
#include "esp_rom_gpio.h"
#include "drivers/leds.h"
#include "esp_heap_caps.h"
#include "drivers/all.h"
#include "drivers/state_tracking.h"
#include "helper.h"
@@ -25,77 +21,67 @@
#include "steps/step6.h"
static const char *TAG = "main";
uint32_t initial_game_time = 60*60*1000;
uint32_t initial_game_time = 90*60*1000 + 1000;
uint32_t skip_to_step = 0;
static void print_bin(char* out_str, uint8_t n) {
out_str[0] = ((n & 0b1000) ? '1' : '0');
out_str[1] = ((n & 0b0100) ? '1' : '0');
out_str[2] = ((n & 0b0010) ? '1' : '0');
out_str[3] = ((n & 0b0001) ? '1' : '0');
}
static void debug_switches() {
uint8_t switch_state = 0;
uint8_t button_state = 0;
char buff[5] = {0};
while (1) {
uint8_t new_button_state = get_button_state();
if (new_button_state != button_state) {
button_state = new_button_state;
print_bin(buff, button_state);
ESP_LOGI("main", "b: 0b%s", buff);
}
uint8_t new_switch_state = get_switch_state();
if (new_switch_state != switch_state) {
switch_state = new_switch_state;
print_bin(buff, switch_state);
ESP_LOGI("main", "s: 0b%s", buff);
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
uint32_t current_step = 0;
extern uint32_t total_strikes;
extern "C" void app_main(void) {
printf("app_main\n");
init_sd();
init_tft();
init_speaker();
init_sseg();
init_game_module_timer();
init_leds();
init_drivers();
// TODO: get wires out of the drivers
// TODO: generify the strike system out of wires
init_wires();
init_bottom_half();
init_char_lcd();
// debug_switches();
vTaskDelay(pdMS_TO_TICKS(1000));
clean_bomb();
step0();
set_game_time(initial_game_time + 1000);
// set_recording_source(stdout, false);
FILE* record_file = fopen(MOUNT_POINT "/record.txt", "w");
if (record_file == nullptr) {
ESP_LOGE("main", "failed to open record.txt");
}
set_recording_source(record_file, true);
start_recording();
set_game_time(initial_game_time);
start_game_timer();
total_strikes = 0;
clean_bomb();
current_step = 1;
if (skip_to_step <= 1) step1();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 2;
if (skip_to_step <= 2) step2();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 3;
if (skip_to_step <= 3) step3();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 4;
if (skip_to_step <= 4) step4();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 5;
if (skip_to_step <= 5) step5();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 6;
if (skip_to_step <= 6) step6();
start_game_timer();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
stop_game_timer();
ESP_LOGI(TAG, "Bomb has been diffused. Counter-Terrorists win.");
ESP_ERROR_CHECK_WITHOUT_ABORT(play_raw("/sdcard/diffused.pcm"));
}
play_clip_wav(MOUNT_POINT "/diffuse.wav", true, false, 3, 0);
display_game_results();
stop_recording();
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef MAIN_H
#define MAIN_H
#include <cstddef>
constexpr size_t N_STEPS = 6;
#endif /* MAIN_H */
+2
View File
@@ -10,4 +10,6 @@ set(SOURCES
"wires_puzzle.cpp"
)
add_subdirectory(tetris_resources)
target_sources(${COMPONENT_LIB} PRIVATE ${SOURCES})
+9 -12
View File
@@ -6,16 +6,13 @@ void print_wires(WireColor* wires, int editing_idx) {
bool cut[NUM_WIRES];
solve_wires(wires, cut);
lcd_set_cursor(&lcd, 1, 1);
char string_buf[NUM_WIRES+1] = {0};
wires_to_string(wires, string_buf);
lcd_print(&lcd, string_buf);
lcd_print(1, 1, string_buf);
lcd_set_cursor(&lcd, 1, 2);
cut_to_string(cut, string_buf);
lcd_print(&lcd, string_buf);
lcd_print(1, 2, string_buf);
lcd_set_cursor(&lcd, 1, 3);
wires_state = get_wires();
for (int i = 0; i < NUM_WIRES; i++) {
if (wires_state & (1<<i)) {
@@ -24,16 +21,16 @@ void print_wires(WireColor* wires, int editing_idx) {
string_buf[i] = '!';
}
}
lcd_print(&lcd, string_buf);
lcd_print(1, 3, string_buf);
lcd_set_cursor(&lcd, editing_idx+1, 1);
lcd_set_cursor_pos(editing_idx+1, 1);
}
void setup_wires(void) {
clear_all_pressed_released();
get_cut_wires();
lcd_clear(&lcd);
lcd_cursor(&lcd);
lcd_clear();
lcd_set_cursor_vis(true);
WireColor wires[NUM_WIRES];
load_wires_from_sd_card(wires);
@@ -45,18 +42,18 @@ void setup_wires(void) {
ButtonKey button;
while (1) {
while (get_pressed_keypad(&key)) {
while (get_keypad_pressed(&key)) {
if (key == KeypadKey::k1) {
generate_new_wires(wires);
save_wires_to_sd_card(wires);
print_wires(wires, editing_idx);
} else if (key == KeypadKey::pound) {
lcd_no_cursor(&lcd);
lcd_set_cursor_vis(false);
return;
}
}
while (get_pressed_button(&button)) {
while (get_button_pressed(&button)) {
if (button == ButtonKey::b1) {
// left
editing_idx = editing_idx - 1;
+228 -59
View File
@@ -1,31 +1,59 @@
#include "step0.h"
#include "drivers/state_tracking.h"
static const char* TAG = "step0";
extern uint32_t initial_game_time;
extern uint32_t skip_to_step;
static void set_game_time(void);
static void skip_to_step1(void) { skip_to_step = 1; }
static void skip_to_step2(void) { skip_to_step = 2; }
static void skip_to_step3(void) { skip_to_step = 3; }
static void skip_to_step4(void) { skip_to_step = 4; }
static void skip_to_step5(void) { skip_to_step = 5; }
static void skip_to_step6(void) { skip_to_step = 6; }
static void try_step1(void) { clean_bomb(); step1(); }
static void try_step2(void) { clean_bomb(); step2(); }
static void try_step3(void) { clean_bomb(); step3(); }
static void try_step4(void) { clean_bomb(); step4(); }
static void try_step5(void) { clean_bomb(); step5(); }
static void try_step6(void) { clean_bomb(); step6(); }
static void issue_strike(void) { strike("Strike Issued"); }
static void set_game_time();
static void skip_to_step1() { skip_to_step = 1; }
static void skip_to_step2() { skip_to_step = 2; }
static void skip_to_step3() { skip_to_step = 3; }
static void skip_to_step4() { skip_to_step = 4; }
static void skip_to_step5() { skip_to_step = 5; }
static void skip_to_step6() { skip_to_step = 6; }
static void try_step1() { clean_bomb(); step1(); }
static void try_step2() { clean_bomb(); step2(); }
static void try_step3() { clean_bomb(); step3(); }
static void try_step4() { clean_bomb(); step4(); }
static void try_step5() { clean_bomb(); step5(); }
static void try_step6() { clean_bomb(); step6(); }
static void issue_strike() { strike("Strike Issued"); }
static void flashbang();
static void debug_switches();
static void battery_stats() {
BaseType_t xReturned;
TaskHandle_t xHandle = NULL;
xReturned = xTaskCreate(bat_monitor_task, "bat_monitor", 4096, NULL, 5, &xHandle);
KeypadKey k;
while (!get_keypad_pressed(&k) || k != KeypadKey::pound) vTaskDelay(pdMS_TO_TICKS(10));
if (xReturned == pdPASS) {
vTaskDelete(xHandle);
}
}
// TODO: remove. This is temperary
static void replay_last() {
FILE* record_file = fopen(MOUNT_POINT "/record.txt", "r");
if (record_file == nullptr) {
ESP_LOGE("main", "failed to open record.txt");
}
set_playback_source(record_file, true);
start_playback();
}
/// Wait for "*9819"
void step0(void) {
void step0() {
led_set(IndicatorLED::LED_SPEAKER, LEDColor::LED_COLOR_BLUE);
leds_flush();
StarCodeHandler star_codes[] = {
{
.code = "*9819",
.display_text = "Diffusal Initiated",
.display_text = "Defusal Initiated",
.should_exit = true,
.callback = nullptr,
},
@@ -41,6 +69,18 @@ void step0(void) {
.should_exit = false,
.callback = set_game_time,
},
{
.code = "*59863",
.display_text = "Debug Switches",
.should_exit = false,
.callback = debug_switches,
},
{
.code = "*59864",
.display_text = "Battery Stats",
.should_exit = false,
.callback = battery_stats,
},
{
.code = "*59871",
.display_text = "Try Step 1",
@@ -119,59 +159,76 @@ void step0(void) {
.should_exit = false,
.callback = issue_strike,
},
{
.code = "*1112",
.display_text = "????",
.should_exit = false,
.callback = flashbang,
},
{
.code = "*1113",
.display_text = "replay_last",
.should_exit = false,
.callback = replay_last,
},
};
int len = sizeof(star_codes)/sizeof(StarCodeHandler);
do_star_codes(star_codes, len);
}
static const char* SECONDS_OR_MINUTES[] = {
"Minutes",
"Seconds",
};
static const int STRING_MAX_LEN = 8;
static void set_game_time(void) {
static const int CURSOR_POS_MAP[5] = {1, 3, 4, 6, 7};
static char str_buf[18] = {0};
static void _update_display(uint8_t* digits, uint8_t cursor_pos) {
sprintf(str_buf, "%d:%d%d:%d%d", digits[0], digits[1], digits[2], digits[3], digits[4]);
lcd_clear();
lcd_print(1, 1, str_buf);
cursor_pos = MAX(0, MIN(4, cursor_pos));
int mapped_cursor_pos = CURSOR_POS_MAP[cursor_pos];
lcd_set_cursor_pos(mapped_cursor_pos, 1);
}
static void set_game_time() {
uint8_t hours = (initial_game_time / (1000*60*60)) % 10;
uint8_t minutes = (initial_game_time / (1000*60)) % 60;
uint8_t seconds = (initial_game_time / (1000)) % 60;
uint8_t digits[5] = {hours, (uint8_t)(minutes / 10), (uint8_t)(minutes % 10), (uint8_t)(seconds / 10), (uint8_t)(seconds % 10)};
uint8_t cursor_pos = 0;
lcd_set_cursor_vis(true);
_update_display(digits, cursor_pos);
KeypadKey key;
bool seconds = true;
int current = initial_game_time / 1000;
char str_buf[21] = {0};
lcd_clear(&lcd);
lcd_set_cursor(&lcd, 1, 1);
sprintf(str_buf, "%d", current);
lcd_print(&lcd, str_buf);
lcd_set_cursor(&lcd, 1, 2);
lcd_print(&lcd, SECONDS_OR_MINUTES[seconds]);
ButtonKey button;
while (1) {
while (get_pressed_keypad(&key)) {
while (get_keypad_pressed(&key)) {
if (key == KeypadKey::star) {
current = 0;
digits[0] = 0;
digits[1] = 0;
digits[2] = 0;
digits[3] = 0;
digits[4] = 0;
cursor_pos = 0;
} else if (key == KeypadKey::pound) {
// submit
if (current == 0) {
clean_bomb();
return;
if (digits[0] != 0 || digits[1] != 0 || digits[2] != 0 || digits[3] != 0 || digits[4] != 0) {
uint32_t new_game_time = 0;
new_game_time += digits[0] * (1000*60*60);
new_game_time += (digits[1] * 10 + digits[2]) * (1000*60);
new_game_time += (digits[3] * 10 + digits[4]) * (1000);
initial_game_time = new_game_time;
}
if (seconds) {
initial_game_time = current * 1000;
} else {
initial_game_time = current * 60*1000;
}
clean_bomb();
led_set(IndicatorLED::LED_SPEAKER, LEDColor::LED_COLOR_BLUE);
leds_flush();
return;
} else if (key == KeypadKey::ka) {
if (seconds) {
current = current / 60;
} else {
current = current * 60;
}
seconds = !seconds;
} else {
int just_pressed = 0;
int just_pressed = -1;
switch (key) {
case KeypadKey::k0:
just_pressed = 0;
break;
case KeypadKey::k1:
just_pressed = 1;
break;
@@ -203,17 +260,129 @@ static void set_game_time(void) {
break;
}
current = (current * 10) + just_pressed;
if (just_pressed != -1) {
digits[cursor_pos] = just_pressed;
cursor_pos = MIN(4, cursor_pos+1);
}
}
lcd_clear(&lcd);
lcd_set_cursor(&lcd, 1, 1);
sprintf(str_buf, "%d", current);
lcd_print(&lcd, str_buf);
lcd_set_cursor(&lcd, 1, 2);
lcd_print(&lcd, SECONDS_OR_MINUTES[seconds]);
_update_display(digits, cursor_pos);
}
while (get_button_pressed(&button)) {
if (button == ButtonKey::b1) {
cursor_pos = MAX(0, cursor_pos-1);
} else if (button == ButtonKey::b2) {
cursor_pos = MIN(4, cursor_pos+1);
}
_update_display(digits, cursor_pos);
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
static void print_4bin_rev(char* out_str, uint8_t n) {
out_str[0] = ((n & 0b0001) ? '1' : '0');
out_str[1] = ((n & 0b0010) ? '1' : '0');
out_str[2] = ((n & 0b0100) ? '1' : '0');
out_str[3] = ((n & 0b1000) ? '1' : '0');
out_str[4] = '\0';
}
static void debug_switches() {
clean_bomb();
uint8_t switch_state = 0xFF;
uint8_t switch_touch_state = 0xFF;
uint8_t button_state = 0xFF;
char bin_buf[5] = {0};
char buf[21] = {0};
KeypadKey key;
ButtonKey button;
SwitchKey switch_;
while (1) {
if (get_button_pressed(&button)) {
sprintf(buf, "Button Pressed: %d ", button);
lcd_print(0, 3, buf);
ESP_LOGI(TAG, "%s", buf);
}
if (get_button_released(&button)) {
sprintf(buf, "Button Released: %d", button);
lcd_print(0, 3, buf);
ESP_LOGI(TAG, "%s", buf);
}
if (get_switch_flipped_down(&switch_)) {
sprintf(buf, "Switch Down: %d ", switch_);
lcd_print(0, 3, buf);
ESP_LOGI(TAG, "%s", buf);
}
if (get_switch_flipped_up(&switch_)) {
sprintf(buf, "Switch Up: %d ", switch_);
lcd_print(0, 3, buf);
ESP_LOGI(TAG, "%s", buf);
}
if (get_switch_touch_pressed(&switch_)) {
sprintf(buf, "Switch Touch: %d ", switch_);
lcd_print(0, 3, buf);
ESP_LOGI(TAG, "%s", buf);
}
if (get_switch_touch_released(&switch_)) {
sprintf(buf, "Switch Un-touch: %d", switch_);
lcd_print(0, 3, buf);
ESP_LOGI(TAG, "%s", buf);
}
uint8_t new_switch_touch_state = get_switch_touch_state();
if (new_switch_touch_state != switch_touch_state) {
switch_touch_state = new_switch_touch_state;
print_4bin_rev(bin_buf, switch_touch_state);
sprintf(buf, "t: %s", bin_buf);
lcd_print(1, 0, buf);
ESP_LOGI(TAG, "%s", buf);
}
uint8_t new_switch_state = get_switch_state();
if (new_switch_state != switch_state) {
switch_state = new_switch_state;
print_4bin_rev(bin_buf, switch_state);
sprintf(buf, "s: %s", bin_buf);
lcd_print(1, 1, buf);
ESP_LOGI(TAG, "%s", buf);
}
uint8_t new_button_state = get_button_state();
if (new_button_state != button_state) {
button_state = new_button_state;
print_4bin_rev(bin_buf, button_state);
sprintf(buf, "b: %s", bin_buf);
lcd_print(1, 2, buf);
ESP_LOGI(TAG, "%s", buf);
}
if (get_keypad_pressed(&key) && key == KeypadKey::pound) {
return;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
static void flashbang() {
play_clip_wav(MOUNT_POINT "/flash.wav", true, false, 1, 0);
vTaskDelay(pdMS_TO_TICKS(4000));
for (int bright = 255; bright >= 0; bright -= 2) {
for (int led_idx = 0; led_idx < IndicatorLED::LED_MAX; led_idx++) {
led_set(led_idx, bright, bright, bright);
}
leds_flush();
vTaskDelay(pdMS_TO_TICKS(10));
}
leds_clear();
leds_flush();
}
+1
View File
@@ -4,6 +4,7 @@
#include "../drivers/bottom_half.h"
#include "../drivers/char_lcd.h"
#include "../drivers/wires.h"
#include "../drivers/power.h"
#include "setup_wires.h"
#include "../helper.h"
+47 -46
View File
@@ -1,26 +1,27 @@
#include "step1.h"
__attribute__((unused))
static const char *TAG = "step1";
static char* COLOR_NAMES[] = {
static const char* COLOR_NAMES[] = {
"green",
"red",
"yellow",
"blue"
};
static char* NUM_NAMES[] = {
static const char* NUM_NAMES[] = {
"one",
"two",
"three",
"four"
};
static uint8_t NEOPIXEL_COLORS[4][3] = {
{0, 20, 0},
{20, 0, 0},
{20, 20, 0},
{0, 0, 20},
static uint32_t NEOPIXEL_COLORS[4] = {
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_YELLOW,
LEDColor::LED_COLOR_BLUE,
};
static std::random_device my_rd;
@@ -29,6 +30,7 @@ static std::uniform_int_distribution<> zero_to_one(0, 1);
static std::uniform_int_distribution<> zero_to_two(0, 2);
static std::uniform_int_distribution<> zero_to_three(0, 3);
static lv_obj_t *old_scr;
static lv_obj_t *scr;
static lv_obj_t *text = NULL;
@@ -57,18 +59,18 @@ static int part = 0;
static void init_step(void) {
if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdTRUE) {
scr = lv_disp_get_scr_act(NULL);
scr = lv_obj_create(NULL);
// Set the background color of the display to black.
lv_style_init(&style_screen);
lv_style_set_bg_color(&style_screen, lv_color_black());
lv_style_set_text_font(&style_screen, &lv_font_montserrat_32);
lv_obj_add_style(lv_scr_act(), &style_screen, LV_STATE_DEFAULT);
lv_obj_add_style(scr, &style_screen, LV_STATE_DEFAULT);
// rgb565
lv_color_t green = { .full = 0x0640 };
lv_color_t green = { .full = 0x0560 };
lv_color_t red = { .full = 0xf800 };
lv_color_t yellow = { .full = 0xfe80 };
lv_color_t yellow = { .full = 0xfce0 };
lv_color_t blue = { .full = 0x045f };
lv_style_init(&green_text);
@@ -84,16 +86,19 @@ static void init_step(void) {
lv_style_set_text_color(&blue_text, blue);
text = lv_label_create(scr);
old_scr = lv_scr_act();
lv_scr_load(scr);
xSemaphoreGive(xGuiSemaphore);
}
}
static void clean_up_step(void) {
if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdTRUE) {
lv_obj_clean(scr);
while (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdFALSE) vTaskDelay(pdMS_TO_TICKS(10));
lv_scr_load(old_scr);
lv_obj_del(scr);
xSemaphoreGive(xGuiSemaphore);
}
}
static void generate_switch_leds(void) {
int colors[4] = {0, 1, 2, 3};
@@ -113,29 +118,21 @@ static void generate_switch_leds(void) {
switch_leds[3] = colors[0];
for (int i = 0; i < 4; i++) {
uint8_t* rgb = NEOPIXEL_COLORS[switch_leds[i]];
led_strip_set_pixel(leds, Led::switch1 - i, rgb[0], rgb[1], rgb[2]);
led_set(IndicatorLED::LED_S1 - i, NEOPIXEL_COLORS[switch_leds[i]]);
}
led_strip_refresh(leds);
leds_flush();
}
static void set_text_and_color(char* text_str, int color) {
static void set_text_and_color(const char* text_str, int color) {
if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdTRUE) {
ESP_LOGI(TAG, "set_text_and_color: setting text: %s", text_str);
lv_label_set_text(text, text_str);
ESP_LOGI(TAG, "set_text_and_color: set text");
lv_obj_center(text);
ESP_LOGI(TAG, "set_text_and_color: setting %d", color);
if (last_style != nullptr) {
ESP_LOGI(TAG, "set_text_and_color: removing %d", color);
lv_obj_remove_style(text, last_style, LV_STATE_DEFAULT);
}
ESP_LOGI(TAG, "set_text_and_color: adding %d", color);
lv_obj_add_style(text, color_styles[color], LV_STATE_DEFAULT);
last_style = color_styles[color];
ESP_LOGI(TAG, "set_text_and_color: style");
xSemaphoreGive(xGuiSemaphore);
ESP_LOGI(TAG, "set_text_and_color: give");
}
}
@@ -143,7 +140,7 @@ static int generate_part_a(void) {
int text_color = zero_to_three(my_gen);
int text_idx = zero_to_three(my_gen);
char* text_string = COLOR_NAMES[text_idx];
const char* text_string = COLOR_NAMES[text_idx];
set_text_and_color(text_string, text_color);
generate_switch_leds();
@@ -161,7 +158,7 @@ static int generate_part_b(void) {
int text_color = zero_to_three(my_gen);
int text_number = zero_to_three(my_gen);
char* text_string = NUM_NAMES[text_number];
const char* text_string = NUM_NAMES[text_number];
set_text_and_color(text_string, text_color);
generate_switch_leds();
@@ -177,7 +174,7 @@ static int generate_part_c(void) {
}
int text_color = zero_to_three(my_gen);
char* text_string = "switch";
const char* text_string = "switch";
set_text_and_color(text_string, text_color);
generate_switch_leds();
@@ -200,33 +197,31 @@ static int generate_part(void) {
}
static void update_lcd_count(int times) {
char buf[6] = {0};
char buf[16] = {0};
sprintf(buf, "%d/15", times);
lcd_set_cursor(&lcd, 14, 1);
lcd_print(&lcd, buf);
lcd_print(14, 1, buf);
}
static bool play_part(uint32_t time) {
stop_module_timer();
set_module_time(time);
lcd_clear(&lcd);
lcd_set_cursor(&lcd, 1, 1);
lcd_clear();
lcd_set_cursor_pos(1, 1);
switch (part) {
case 0:
lcd_print(&lcd, "COLOR");
led_strip_set_pixel(leds, Led::char_lcd, 20, 0, 20);
lcd_print("COLOR");
led_set(IndicatorLED::LED_LCD, LEDColor::LED_COLOR_PINK);
break;
case 1:
lcd_print(&lcd, "NUMBER");
led_strip_set_pixel(leds, Led::char_lcd, 0, 0, 30);
lcd_print("NUMBER");
led_set(IndicatorLED::LED_LCD, LEDColor::LED_COLOR_BLUE);
break;
case 2:
lcd_print(&lcd, "SWITCH");
led_strip_set_pixel(leds, Led::char_lcd, 20, 20, 0);
lcd_print("SWITCH");
led_set(IndicatorLED::LED_LCD, LEDColor::LED_COLOR_YELLOW);
break;
}
led_strip_refresh(leds);
leds_flush();
int times = 0;
int correct = generate_part();
@@ -236,7 +231,7 @@ static bool play_part(uint32_t time) {
SwitchKey switch_;
while (times < 15) {
while (get_pressed_button(&button)) {
while (get_button_pressed(&button)) {
start_module_timer();
if ((int)(button) == correct) {
times++;
@@ -247,7 +242,7 @@ static bool play_part(uint32_t time) {
strike("Incorrect action");
}
}
while (get_flipped_switch(&switch_)) {
while (get_switch_flipped(&switch_)) {
start_module_timer();
if (switch_leds[(int)(switch_)] + 4 == correct) {
times++;
@@ -260,23 +255,29 @@ static bool play_part(uint32_t time) {
}
if (get_module_time() <= 0) {
strike("Out of time");
vTaskDelay(pdMS_TO_TICKS(2000));
return false;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
stop_module_timer();
if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdTRUE) {
lv_label_set_text(text, "");
xSemaphoreGive(xGuiSemaphore);
}
vTaskDelay(pdMS_TO_TICKS(80));
play_raw(MOUNT_POINT "/correct.pcm");
if (part < 2) {
play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0);
vTaskDelay(pdMS_TO_TICKS(2000));
} else {
play_clip_wav(MOUNT_POINT "/stepdone.wav", true, false, 1, 0);
}
return true;
}
void step1(void) {
while (get_flipped_switch(nullptr));
while (get_switch_flipped(nullptr));
init_step();
while (!play_part(40*1000));
+26 -21
View File
@@ -1,7 +1,10 @@
#include "step2.h"
__attribute__((unused))
static const char *TAG = "step2";
static const int NUM_SOLVES = 4;
// one: 0b00000110
// seven: 0b00000111
static const uint8_t SSEG_NUMS[8] = {0b00111111, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b01111111, 0b01101111};
@@ -13,9 +16,13 @@ static const uint8_t SSEG_MAPS[5][4] = {
{0b01000111, 0b00011001, 0b01111000, 0b00111110}
};
static const int INDICATOR_RED[5] = {15, 0, 0, 10, 5};
static const int INDICATOR_GREEN[5] = {0, 0, 10, 5, 7};
static const int INDICATOR_BLUE[5] = {0, 10, 0, 0, 5};
static const uint32_t INDICATOR_COLORS[5] = {
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_BLUE,
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_YELLOW,
LEDColor::LED_COLOR_WHITE,
};
// random number generators
static std::random_device rd;
@@ -45,8 +52,8 @@ std::map<int, int> number_map = {
static void new_puzzle(void) {
// scramble lights
for (int i = 0; i < 5; i++) {
led_strip_set_pixel(leds, 9, INDICATOR_RED[map_dist(gen)], INDICATOR_GREEN[map_dist(gen)], INDICATOR_BLUE[map_dist(gen)]);
led_strip_refresh(leds);
led_set(IndicatorLED::LED_SPEAKER, INDICATOR_COLORS[map_dist(gen)]);
leds_flush();
uint8_t random_segments[4] = {0, 0, 0, 0};
for (int i = 0; i < 4; i++) {
@@ -69,8 +76,8 @@ static void new_puzzle(void) {
}
// ESP_LOGI(TAG, "Chosen Map: %i", chosen_map);
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 9, INDICATOR_RED[chosen_map], INDICATOR_GREEN[chosen_map], INDICATOR_BLUE[chosen_map]));
ESP_ERROR_CHECK(led_strip_refresh(leds));
led_set(IndicatorLED::LED_SPEAKER, INDICATOR_COLORS[chosen_map]);
leds_flush();
for (int i = 0; i < 8; i++) {
bool bit = (answer_sseg >> i) & 1;
@@ -81,6 +88,7 @@ static void new_puzzle(void) {
// ESP_LOGI(TAG, "Flipping bit %i on display %i", i, display);
}
}
set_module_sseg_raw(display_map);
}
void step2(void) {
@@ -88,35 +96,32 @@ void step2(void) {
int solved_times = 0;
new_puzzle();
int strike_time = xTaskGetTickCount();
bool striked = false;
while(solved_times < 4) {
int strike_time = 0;
while(solved_times < NUM_SOLVES) {
// for every bit in the answer-
set_module_sseg_raw(display_map);
if (get_pressed_keypad(&key)) {
lcd_clear(&lcd);
if (get_keypad_pressed(&key)) {
lcd_clear();
char c = char_of_keypad_key(key);
// ESP_LOGI(TAG, "Pressed: %c", c);
if (c == answer_char) {
play_raw(MOUNT_POINT "/correct.pcm");
solved_times++;
if (solved_times < 3) {
if (solved_times < NUM_SOLVES) {
play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0);
clean_bomb();
new_puzzle();
} else {
uint8_t display_tmp[4] = {0b00000000, 0b00000000, 0b00000000, 0b00000000};
set_module_sseg_raw(display_tmp);
play_clip_wav(MOUNT_POINT "/stepdone.wav", true, false, 1, 0);
clear_module_sseg();
}
} else {
strike_time = xTaskGetTickCount();
striked = true;
strike("Incorrect Character!");
}
}
if (xTaskGetTickCount() - strike_time > pdMS_TO_TICKS(5000)) {
striked = false;
lcd_clear(&lcd);
if (strike_time != 0 && xTaskGetTickCount() - strike_time > pdMS_TO_TICKS(5000)) {
strike_time = 0;
lcd_clear();
}
vTaskDelay(pdMS_TO_TICKS(10));
}
+50 -46
View File
@@ -4,18 +4,21 @@
#define THREE_SECOND_TIME 90'000
#define SIX_SECOND_TIME 75'000
#define TIMES_TO_COMPLETE 4
__attribute__((unused))
static const char *TAG = "step3";
static int tone = 0;
static int times = 0;
static const char* TONE_FILES[] = {
MOUNT_POINT "/low-1.pcm",
MOUNT_POINT "/low-3.pcm",
MOUNT_POINT "/low-6.pcm",
MOUNT_POINT "/high-1.pcm",
MOUNT_POINT "/high-3.pcm",
MOUNT_POINT "/high-6.pcm",
MOUNT_POINT "/low-1.wav",
MOUNT_POINT "/low-3.wav",
MOUNT_POINT "/low-6.wav",
MOUNT_POINT "/high-1.wav",
MOUNT_POINT "/high-3.wav",
MOUNT_POINT "/high-6.wav",
};
static const char* LCD_STRINGS[] = {
@@ -32,7 +35,7 @@ static const char* LCD_STRINGS[] = {
static int indicator_led_idxs[LED_COUNT] = {0};
static bool contains_coconut = false;
static char* COCONUT = "coconut";
static const char* COCONUT = "coconut";
static char lcd_random_char_set[] = "aeiou tnsrhldm";
static char random_lcd_text[21] = {0};
@@ -46,14 +49,14 @@ static std::uniform_int_distribution<> lcd_rand_char_dist(0, sizeof(lcd_random_c
static std::uniform_int_distribution<> has_coconut_dist(0, 2);
static std::uniform_int_distribution<> coconut_position_dist(0, 13);
static uint8_t NEOPIXEL_COLORS[7][3] = {
{20, 0, 0}, // red
{20, 10, 0}, // orange
{20, 20, 0}, // yellow
{0, 20, 0}, // green
{0, 0, 20}, // blue
{20, 0, 20}, // purple
{0, 0, 0}, // off
static uint32_t NEOPIXEL_COLORS[7] = {
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_ORANGE,
LEDColor::LED_COLOR_YELLOW,
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_BLUE,
LEDColor::LED_COLOR_PINK,
LEDColor::LED_COLOR_OFF,
};
static bool one_second();
@@ -72,13 +75,14 @@ void step3(void) {
int len = sizeof(star_codes)/sizeof(StarCodeHandler);
do_star_codes(star_codes, len);
while (times < 4) {
while (times < TIMES_TO_COMPLETE) {
tone = tone_dist(gen);
// tone = 2;
while (get_pressed_button(nullptr)) vTaskDelay(pdMS_TO_TICKS(10));
while (get_button_pressed(nullptr)) vTaskDelay(pdMS_TO_TICKS(10));
play_raw(MOUNT_POINT "/que.pcm");
play_raw(TONE_FILES[tone]);
play_clip_wav(MOUNT_POINT "/ready.wav", true, false, 3, 0);
// The high pitched tones need to be scaled down by 3 more
play_clip_wav(TONE_FILES[tone], false, false, 2 + (tone/3) * 3, 0);
bool correct = false;
switch (tone % 3) {
@@ -95,7 +99,11 @@ void step3(void) {
if (correct) {
times++;
clean_bomb();
play_raw(MOUNT_POINT "/correct.pcm");
if (times < TIMES_TO_COMPLETE) {
play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0);
} else {
play_clip_wav(MOUNT_POINT "/stepdone.wav", true, false, 1, 0);
}
} else {
vTaskDelay(pdMS_TO_TICKS(1500));
}
@@ -131,10 +139,9 @@ static void rng_leds() {
static void write_leds() {
// update all the leds
for (int i = 0; i < LED_COUNT; i++) {
auto colors = NEOPIXEL_COLORS[indicator_led_idxs[i]];
led_strip_set_pixel(leds, i, colors[0], colors[1], colors[2]);
led_set(i, NEOPIXEL_COLORS[indicator_led_idxs[i]]);
}
led_strip_refresh(leds);
leds_flush();
}
static uint8_t four_bit_flag(bool b0, bool b1, bool b2, bool b3) {
@@ -146,7 +153,7 @@ static uint8_t four_bit_flag(bool b0, bool b1, bool b2, bool b3) {
;
}
static void print_bin(char* out_str, uint8_t n) {
static void print_4bin(char* out_str, uint8_t n) {
out_str[0] = ((n & 0b1000) ? '1' : '0');
out_str[1] = ((n & 0b0100) ? '1' : '0');
out_str[2] = ((n & 0b0010) ? '1' : '0');
@@ -170,19 +177,19 @@ static void print_bin(char* out_str, uint8_t n) {
static void debug_correct_values(uint8_t correct_buttons, uint8_t button_mask, uint8_t correct_switches) {
char buf[20] = {0};
print_bin(buf, correct_switches);
print_4bin(buf, correct_switches);
ESP_LOGI(TAG, "Expected Switch State: 0b%s", buf);
print_bin(buf, correct_buttons);
print_4bin(buf, correct_buttons);
ESP_LOGI(TAG, "Expected Button State: 0b%s", buf);
print_bin(buf, button_mask);
print_4bin(buf, button_mask);
ESP_LOGI(TAG, "Button Mask: 0b%s", buf);
}
static void debug_actual_values(uint8_t buttons, uint8_t switch_) {
char buf[20] = {0};
print_bin(buf, switch_);
print_4bin(buf, switch_);
ESP_LOGI(TAG, "Actual Switch State: 0b%s", buf);
print_bin(buf, buttons);
print_4bin(buf, buttons);
ESP_LOGI(TAG, "Actual Button State: 0b%s", buf);
ESP_LOGI(TAG, "");
}
@@ -190,7 +197,7 @@ static void debug_actual_values(uint8_t buttons, uint8_t switch_) {
static void wait_for_timer(void) {
KeypadKey key;
while (get_module_time() > 0) {
if (get_pressed_keypad(&key) && key == KeypadKey::kd) {
if (get_keypad_pressed(&key) && key == KeypadKey::kd) {
set_module_time(0);
return;
}
@@ -204,13 +211,12 @@ static bool one_second() {
start_module_timer();
rng_leds();
int speaker_color = indicator_led_idxs[Led::speaker];
int speaker_color = indicator_led_idxs[IndicatorLED::LED_SPEAKER];
int lcd_string_idx = lcd_string_dist(gen);
bool was_high = (tone / 3) == 1;
write_leds();
lcd_clear(&lcd);
lcd_set_cursor(&lcd, 1, 1);
lcd_print(&lcd, LCD_STRINGS[lcd_string_idx]);
lcd_clear();
lcd_print(1, 1, LCD_STRINGS[lcd_string_idx]);
int red_led_count = 0;
int blue_led_count = 0;
@@ -231,10 +237,10 @@ static bool one_second() {
uint8_t correct_button_mask = 0b1011;
uint8_t correct_buttons = four_bit_flag(
indicator_led_idxs[Led::char_lcd] != 6, // green
indicator_led_idxs[IndicatorLED::LED_LCD] != 6, // green
red_led_count > blue_led_count, // red
0, // yellow UNCHECKED
indicator_led_idxs[Led::rfid] == 4 || indicator_led_idxs[Led::rfid] == 6 // blue
indicator_led_idxs[IndicatorLED::LED_RFID] == 4 || indicator_led_idxs[IndicatorLED::LED_RFID] == 6 // blue
);
debug_correct_values(correct_buttons, correct_button_mask, correct_switches);
@@ -265,8 +271,7 @@ static bool three_second() {
int lcd_number = lcd_number_dist(gen);
char lcd_number_string[9] = {0};
sprintf(lcd_number_string, "%d", lcd_number);
lcd_set_cursor(&lcd, 1, 1);
lcd_print(&lcd, lcd_number_string);
lcd_print(1, 1, lcd_number_string);
bool was_high = (tone / 3) == 1;
@@ -328,8 +333,7 @@ static bool six_second() {
generate_random_lcd_text();
vTaskDelay(pdMS_TO_TICKS(10));
lcd_set_cursor(&lcd, 0, 0);
lcd_print(&lcd, random_lcd_text);
lcd_print(0, 0, random_lcd_text);
int vowels = 0;
for (int i = 0; i < 20; i++) {
@@ -341,7 +345,7 @@ static bool six_second() {
bool was_high = (tone / 3) == 1;
bool second_switch_correct_state = (indicator_led_idxs[Led::switch2] == 0) || (indicator_led_idxs[Led::switch2] == 6);
bool second_switch_correct_state = (indicator_led_idxs[IndicatorLED::LED_S2] == 0) || (indicator_led_idxs[IndicatorLED::LED_S2] == 6);
second_switch_correct_state = second_switch_correct_state || was_high;
rng_leds();
@@ -357,10 +361,10 @@ static bool six_second() {
}
}
int purple_led_on_bottom_count = 0;
for (int i = Led::rfid; i < LED_COUNT; i++) {
int pink_led_on_bottom_count = 0;
for (int i = IndicatorLED::LED_RFID; i < LED_COUNT; i++) {
if (indicator_led_idxs[i] == 5) {
purple_led_on_bottom_count++;
pink_led_on_bottom_count++;
}
}
@@ -368,12 +372,12 @@ static bool six_second() {
vowels > 7,
second_switch_correct_state,
true,
!(purple_led_on_bottom_count > 1)
!(pink_led_on_bottom_count > 1)
);
uint8_t correct_button_mask = 0b1101;
uint8_t correct_buttons = four_bit_flag(
(!was_high) || (green_led_count >= 2) || indicator_led_idxs[Led::keypad] == 4, // green
(!was_high) || (green_led_count >= 2) || indicator_led_idxs[IndicatorLED::LED_KEYPAD] == 4, // green
0, // red UNCHECKED
blue_led_count >= 3, // yellow
contains_coconut // blue
+149 -109
View File
@@ -1,14 +1,12 @@
#include "step4.h"
__attribute__((unused))
static const char *TAG = "step4";
static lv_obj_t *old_scr;
static lv_obj_t* scr;
static lv_style_t scr_style;
static lv_obj_t* img;
static bool invisible_blocks = false;
static bool text_output = false;
static const int height = 22;
static const int width = 10;
@@ -19,24 +17,51 @@ static lv_obj_t* line_clear_img;
static lv_style_t game_over_style;
static lv_obj_t* game_over_label;
static const void* LINE_CLEAR_SRC = (void*)"A:/sdcard/clear.bin";
static const void* BACKGROUND_SRC = (void*)"A:/sdcard/bg.bin";
// LV_IMG_DECLARE(background);
// static const void* BACKGROUND_SRC = (void*)&background;
#define MUSIC_FILE MOUNT_POINT "/piano.wav"
static QueueHandle_t stop_music;
static bool playing_music = true;
#ifdef TETRIS_USE_FLASH_BG_IMG
LV_IMG_DECLARE(bg);
static const void* BACKGROUND_SRC = (void*) &bg;
#else
static const void* BACKGROUND_SRC = (void*)"A:" MOUNT_POINT "/bg.bin";
#endif
static const char* PIECE_IMG_SRC[] = {
#ifdef TETRIS_USE_FLASH_IMG
LV_IMG_DECLARE(clear);
LV_IMG_DECLARE(db);
LV_IMG_DECLARE(green);
LV_IMG_DECLARE(lb);
LV_IMG_DECLARE(orange);
LV_IMG_DECLARE(purple);
LV_IMG_DECLARE(red);
LV_IMG_DECLARE(yellow);
static const void* LINE_CLEAR_SRC = (void*) &clear;
static const void* PIECE_IMG_SRC[] = {
NULL,
"A:/sdcard/lb.bin",
"A:/sdcard/db.bin",
"A:/sdcard/orange.bin",
"A:/sdcard/yellow.bin",
"A:/sdcard/green.bin",
"A:/sdcard/purple.bin",
"A:/sdcard/red.bin",
&lb,
&db,
&orange,
&yellow,
&green,
&purple,
&red,
};
#else
static const void* LINE_CLEAR_SRC = (void*)"A:" MOUNT_POINT "/clear.bin";
static const void* PIECE_IMG_SRC[] = {
NULL,
"A:" MOUNT_POINT "/lb.bin",
"A:" MOUNT_POINT "/db.bin",
"A:" MOUNT_POINT "/orange.bin",
"A:" MOUNT_POINT "/yellow.bin",
"A:" MOUNT_POINT "/green.bin",
"A:" MOUNT_POINT "/purple.bin",
"A:" MOUNT_POINT "/red.bin",
};
#endif
static bool game = true;
@@ -55,27 +80,27 @@ static int piece_nodes[4][2] = {
lv_obj_t* piece_imgs[4] = {};
TaskHandle_t music_handle;
static bool music_playing;
static std::random_device rd;
static std::mt19937 gen(rd());
static std::uniform_int_distribution<> piece_dist(2, 7);
static void generate_block(void);
static void show_board(void);
static void get_node_locations(void);
static bool check_overlap(void);
static void generate_block();
static void show_board();
static void get_node_locations();
static bool check_overlap();
static void line_clear(int hi);
static void check_line_clears(void);
static void place_piece(void);
static void check_line_clears();
static void place_piece();
static void move_left(void);
static void move_right(void);
static void drop(void);
static void rotate_block(void);
static void update_score(void);
static void clear_board(void);
static void move_left();
static void move_right();
static void drop();
static void rotate_block();
static void update_score();
static void clear_board();
static int bbcc(int i) { // [0,1,2,3] -> [ 0, 0,+1,+1]
@@ -86,10 +111,6 @@ static int bccb(int i) { // [0,1,2,3] -> [ 0,+1,+1, 0]
const int map[] = {0, 1, 1, 0};
return map[i];
}
static int cbbc(int i) { // [0,1,2,3] -> [+1, 0, 0,+1]
const int map[] = {1, 0, 0, 1};
return map[i];
}
static int ccbb(int i) { // [0,1,2,3] -> [+1,+1, 0, 0]
const int map[] = {1, 1, 0, 0};
return map[i];
@@ -129,28 +150,15 @@ static int bdca(int i) { // [0,1,2,3] -> [ 0,+2,+1,-1]
return map[i];
}
static void music_task(void* arg) {
stop_music = xQueueCreate(2, sizeof (uint8_t));
if (stop_music == 0) {
ESP_LOGW(TAG, "Could not create stop_music queue!");
vTaskDelete(NULL);
}
while (playing_music) {
play_raw_stop_queue(MOUNT_POINT "/tetris.pcm", stop_music);
}
vTaskDelete(NULL);
}
static void init_screen(void) {
static void init_screen() {
while (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdFALSE) vTaskDelay(pdMS_TO_TICKS(10));
scr = lv_obj_create(NULL);
img = lv_img_create(lv_scr_act());
img = lv_img_create(scr);
lv_img_set_src(img, BACKGROUND_SRC);
lv_obj_align(img, LV_ALIGN_CENTER, 0, 0);
line_clear_img = lv_img_create(lv_scr_act());
line_clear_img = lv_img_create(scr);
lv_obj_add_flag(line_clear_img, LV_OBJ_FLAG_HIDDEN);
lv_img_set_src(line_clear_img, LINE_CLEAR_SRC);
lv_obj_align(line_clear_img, LV_ALIGN_BOTTOM_LEFT, 159, -(height*16));
@@ -161,39 +169,62 @@ static void init_screen(void) {
lv_style_set_bg_opa(&game_over_style, LV_OPA_100);
lv_style_set_text_align(&game_over_style, LV_TEXT_ALIGN_CENTER);
game_over_label = lv_label_create(lv_scr_act());
game_over_label = lv_label_create(scr);
lv_obj_add_flag(game_over_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_align(game_over_label, LV_ALIGN_CENTER, 0, 0);
lv_obj_align(game_over_label, LV_ALIGN_LEFT_MID, 0, 0);
lv_obj_set_width(game_over_label, 160);
lv_obj_add_style(game_over_label, &game_over_style, LV_STATE_DEFAULT);
// for (int h = 0; h < height; h++) {
// for (int w = 0; w < width; w++) {
// visual_board[h][w] = lv_img_create(lv_scr_act());
// lv_obj_align(visual_board[h][w], LV_ALIGN_BOTTOM_LEFT, 159 + w*16, -(h*16));
// lv_img_set_src(visual_board[h][w], PIECE_IMG_SRC[((w+h)%7)+1]);
// }
// }
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
visual_board[h][w] = lv_img_create(scr);
lv_obj_align(visual_board[h][w], LV_ALIGN_BOTTOM_LEFT, 159 + w*16, -(h*16));
lv_obj_add_flag(visual_board[h][w], LV_OBJ_FLAG_HIDDEN);
}
}
for (int i = 0; i < 4; i++) {
piece_imgs[i] = lv_img_create(lv_scr_act());
piece_imgs[i] = lv_img_create(scr);
lv_obj_align(piece_imgs[i], LV_ALIGN_BOTTOM_LEFT, 159, -320);
}
old_scr = lv_scr_act();
lv_scr_load(scr);
xSemaphoreGive(xGuiSemaphore);
xTaskCreate(music_task, "music", 4096, NULL, 5, NULL);
play_clip_wav(MUSIC_FILE, true, true, 4, 0);
music_playing = true;
}
static void deinit_screen(void) {
static void deinit_screen() {
while (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdFALSE) vTaskDelay(pdMS_TO_TICKS(10));
lv_obj_clean(lv_scr_act());
lv_scr_load(old_scr);
lv_obj_del(scr);
xSemaphoreGive(xGuiSemaphore);
playing_music = false;
uint8_t value = 0;
if (!xQueueSend(stop_music, &value, pdMS_TO_TICKS(1000))) {
ESP_LOGE(TAG, "Faild to send stop queue");
if (!stop_clip(MUSIC_FILE, pdMS_TO_TICKS(1000))) {
ESP_LOGW(TAG, "Can't stop, addicted to the shindig.");
}
music_playing = false;
}
static void reveal_board() {
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
if (PIECE_IMG_SRC[board[h][w]]) {
lv_img_set_src(visual_board[h][w], PIECE_IMG_SRC[board[h][w]]);
lv_obj_clear_flag(visual_board[h][w], LV_OBJ_FLAG_HIDDEN);
}
}
}
}
static void hide_board() {
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
lv_obj_add_flag(visual_board[h][w], LV_OBJ_FLAG_HIDDEN);
lv_img_set_src(visual_board[h][w], NULL);
}
}
}
@@ -211,7 +242,7 @@ bool play_game(int time, int required_score) {
show_board();
ButtonKey button;
while (get_pressed_button(&button));
while (get_button_pressed(&button));
// SwitchKey switch_;
const TickType_t first_repeat_time = pdMS_TO_TICKS(700);
@@ -220,7 +251,7 @@ bool play_game(int time, int required_score) {
TickType_t last_repeat = 0;
while(game) {
if (get_pressed_button(&button)) {
while (get_button_pressed(&button)) {
switch (button) {
case ButtonKey::b1:
move_left();
@@ -245,12 +276,26 @@ bool play_game(int time, int required_score) {
return true;
}
}
if (get_released_button(&button)) {
while (get_button_released(&button)) {
if (button == ButtonKey::b3) {
down_held = 0;
}
}
// Toggle music with switch4
SwitchKey switch_;
while (get_switch_flipped(&switch_)) {
if (switch_ == SwitchKey::s4) {
if (music_playing) {
stop_clip(MUSIC_FILE, 0);
music_playing = false;
} else {
play_clip_wav(MUSIC_FILE, true, true, 4, 0);
music_playing = true;
}
}
}
if (down_held != 0) {
// check repeat
TickType_t now = xTaskGetTickCount();
@@ -274,7 +319,7 @@ bool play_game(int time, int required_score) {
strike("Out of time");
return false;
}
// if (get_flipped_switch(&switch_)) {
// if (get_switch_flipped(&switch_)) {
// printf("%d\n", piece);
// for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) {
// int* p = piece_nodes[i];
@@ -293,43 +338,48 @@ bool play_game(int time, int required_score) {
return false;
}
static void complete(void) {
static void complete() {
if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdTRUE) {
reveal_board();
lv_label_set_text(game_over_label, "Winner!\nPress any button to continue");
lv_obj_clear_flag(game_over_label, LV_OBJ_FLAG_HIDDEN);
xSemaphoreGive(xGuiSemaphore);
}
vTaskDelay(pdMS_TO_TICKS(500));
while (get_pressed_button(nullptr));
while (get_button_pressed(nullptr));
while (1) {
if (get_pressed_button(nullptr)) break;
if (get_button_pressed(nullptr)) break;
vTaskDelay(pdMS_TO_TICKS(10));
}
if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdTRUE) {
lv_obj_add_flag(game_over_label, LV_OBJ_FLAG_HIDDEN);
hide_board();
xSemaphoreGive(xGuiSemaphore);
}
}
static void fail(void) {
static void fail() {
if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdTRUE) {
lv_label_set_text(game_over_label, "Game Over\nPress any button to continue");
lv_obj_clear_flag(game_over_label, LV_OBJ_FLAG_HIDDEN);
reveal_board();
xSemaphoreGive(xGuiSemaphore);
}
vTaskDelay(pdMS_TO_TICKS(500));
while (get_pressed_button(nullptr));
vTaskDelay(pdMS_TO_TICKS(2000));
while (get_button_pressed(nullptr));
while (1) {
if (get_pressed_button(nullptr)) break;
if (get_button_pressed(nullptr)) break;
vTaskDelay(pdMS_TO_TICKS(10));
}
if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdTRUE) {
lv_obj_add_flag(game_over_label, LV_OBJ_FLAG_HIDDEN);
hide_board();
xSemaphoreGive(xGuiSemaphore);
}
}
void step4(void) {
void step4() {
StarCodeHandler star_code = {
.code = "*3850",
.display_text = "Starting...",
@@ -340,17 +390,19 @@ void step4(void) {
init_screen();
while (!play_game(4*60*1000, 2)) fail();
play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0);
complete();
while (!play_game(4*60*1000, 4)) fail();
play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0);
complete();
while (!play_game(6*60*1000, 8)) fail();
while (!play_game(7*60*1000, 8)) fail();
play_clip_wav(MOUNT_POINT "/stepdone.wav", true, false, 1, 0);
complete();
// vTaskDelay(pdMS_TO_TICKS(3000));
deinit_screen();
}
static void show_board(void) {
static void show_board() {
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
if (board[h][w] == 9) {
@@ -364,16 +416,6 @@ static void show_board(void) {
board[p[0]][p[1]] = 9;
}
if (text_output) {
for (int h = height-1; h >= 0; h--) {
for (int w = 0; w < width; w++) {
printf("|%c", board[h][w] == 9 ? 'X' : (invisible_blocks ? '0' : ('0' + board[h][w])));
}
printf("|\n");
}
printf("\n");
}
if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdTRUE) {
for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) {
int* p = piece_nodes[i];
@@ -384,7 +426,7 @@ static void show_board(void) {
}
}
static void generate_block(void) {
static void generate_block() {
int new_piece = piece_dist(gen);
if (new_piece == piece) {
new_piece = 1;
@@ -419,7 +461,7 @@ static void generate_block(void) {
}
}
static void rotate_block(void) {
static void rotate_block() {
piece_rotation++;
if (piece_rotation > 3) {
piece_rotation = 0;
@@ -497,7 +539,7 @@ static void rotate_block(void) {
}
// Check if nodes are outside of map or interposed onto placed nodes
static bool check_overlap(void) {
static bool check_overlap() {
for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) {
int* p = piece_nodes[i];
if (p[0] < 0 || p[1] < 0 || p[1] >= width) {
@@ -509,7 +551,7 @@ static bool check_overlap(void) {
return false;
}
static void move_left(void) {
static void move_left() {
for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) {
int* p = piece_nodes[i];
if (p[1] == 0) {
@@ -523,7 +565,7 @@ static void move_left(void) {
get_node_locations();
}
static void move_right(void) {
static void move_right() {
for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) {
int* p = piece_nodes[i];
if (p[1] == width-1) {
@@ -536,7 +578,7 @@ static void move_right(void) {
get_node_locations();
}
static void drop(void) {
static void drop() {
for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) {
int* p = piece_nodes[i];
if (p[0] == 0) {
@@ -556,7 +598,7 @@ static void drop(void) {
get_node_locations();
}
static void place_piece(void) {
static void place_piece() {
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
if (board[h][w] == 9) {
@@ -566,7 +608,6 @@ static void place_piece(void) {
}
if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdTRUE) {
for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) {
int* p = piece_nodes[i];
lv_obj_align(piece_imgs[i], LV_ALIGN_BOTTOM_LEFT, 159, -(height*16));
}
xSemaphoreGive(xGuiSemaphore);
@@ -646,7 +687,7 @@ static void get_node_locations() {
}
}
static void check_line_clears(void) {
static void check_line_clears() {
for (int h = height-2; h >= 0; h--) {
for (int w = 0; w < width; w++) {
if (board[h][w] != 0 && board[h][w] != 9) {
@@ -660,12 +701,11 @@ static void check_line_clears(void) {
}
}
static void update_score(void) {
static void update_score() {
char buff[16] = {};
sprintf(buff, "%d/%d", score, target_score);
lcd_clear(&lcd);
lcd_set_cursor(&lcd, 1, 1);
lcd_print(&lcd, buff);
lcd_clear();
lcd_print(1, 1, buff);
}
static void line_clear(int hi) {
@@ -698,7 +738,7 @@ static void line_clear(int hi) {
}
}
void clear_board(void) {
void clear_board() {
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
board[h][w] = 0;
+2 -7
View File
@@ -10,13 +10,8 @@
#include "../drivers/char_lcd.h"
#include "../helper.h"
// TODO:
// - [ ] set up real game loop
// - [ ] stop music
// - [ ] set up strike on falure
// - [ ] set up module timer
#define TETRIS_USE_FLASH_IMG
#define TETRIS_USE_FLASH_BG_IMG
void step4(void);
+147 -127
View File
@@ -1,5 +1,16 @@
#include "step5.h"
#define TIME_CLEAR 30'000
#define TIME_PLANK 40'000
#define TIME_EMPTY 40'000
#define TIME_NOTHING 25'000
#define TIME_BLINK 35'000
#define TIME_UMMM 35'000
#define TIME_BLANK 40'000
#define TIME_WHAT 60'000
#define TIME_PLINK 40'000
__attribute__((unused))
static const char *TAG = "step5";
static const int TIMES_TO_SOLVE = 9;
@@ -10,23 +21,23 @@ static std::uniform_int_distribution<> puzzle_dist(0, 7);
static std::uniform_int_distribution<> led_picker_dist(0, 20);
static std::uniform_int_distribution<> led_color_dist(0, 5);
void set_unique_leds(std::vector<int>& input_options, const int num, const int r, const int g, const int b) {
void set_unique_leds(std::vector<int>& input_options, const int num, const uint32_t color) {
for (int i = 0; i < num; i++) {
std::uniform_int_distribution<> led_option_dist(0, input_options.size() - 1);
int led = led_option_dist(gen);
ESP_ERROR_CHECK(led_strip_set_pixel(leds, input_options[led], r, g, b));
led_set(input_options[led], color);
input_options.erase(input_options.begin() + led);
}
}
void set_unique_leds_random_color(std::vector<int>& input_options, const int num, const int* r, const int* g, const int* b) {
void set_unique_leds_random_color(std::vector<int>& input_options, const int num, const uint32_t* COLORS, size_t COLORS_len) {
for (int i = 0; i < num; i++) {
std::uniform_int_distribution<> led_option_dist(0, input_options.size() - 1);
int led = led_option_dist(gen);
std::uniform_int_distribution<> led_color_dist(0, sizeof(r) - 1);
std::uniform_int_distribution<> led_color_dist(0, COLORS_len - 1);
int color = led_color_dist(gen);
ESP_ERROR_CHECK(led_strip_set_pixel(leds, input_options[led], r[color], g[color], b[color]));
led_set(input_options[led], COLORS[color]);
input_options.erase(input_options.begin() + led);
}
}
@@ -185,9 +196,14 @@ void step5(void) {
all_leds.push_back(i);
}
const int INDICATOR_RED[6] = {20, 0, 0, 10, 10, 5};
const int INDICATOR_GREEN[6] = {0, 0, 10, 5, 0, 7};
const int INDICATOR_BLUE[6] = {0, 10, 0, 0, 5, 5};
const uint32_t COLORS[] = {
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_BLUE,
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_YELLOW,
LEDColor::LED_COLOR_PINK,
LEDColor::LED_COLOR_WHITE,
};
static std::uniform_int_distribution<> led_number_dist(0, 21);
int last_cycle_tick = xTaskGetTickCount();
@@ -196,8 +212,8 @@ void step5(void) {
if ((xTaskGetTickCount() - last_cycle_tick) > pdMS_TO_TICKS(100)) {
clean_bomb();
std::vector<int> led_options = all_leds;
set_unique_leds_random_color(led_options, led_number_dist(gen), INDICATOR_RED, INDICATOR_GREEN, INDICATOR_BLUE);
ESP_ERROR_CHECK(led_strip_refresh(leds));
set_unique_leds_random_color(led_options, led_number_dist(gen), COLORS, sizeof(COLORS)/sizeof(COLORS[0]));
leds_flush();
last_cycle_tick = xTaskGetTickCount();
scrambled_times++;
}
@@ -206,7 +222,7 @@ void step5(void) {
clean_bomb();
int solved_puzzles = 0;
while (solved_puzzles < TIMES_TO_SOLVE) {
lcd_set_cursor(&lcd, 1, 1);
lcd_set_cursor_pos(1, 1);
bool solved_correctly = false;
int puzzle = puzzle_dist(gen);
@@ -214,8 +230,8 @@ void step5(void) {
switch (puzzle) {
case 0: {
lcd_print(&lcd, "Clear");
set_module_time(30000);
lcd_print("Clear");
set_module_time(TIME_CLEAR);
start_module_timer();
std::vector<int> indicator_options = all_leds;
@@ -223,21 +239,23 @@ void step5(void) {
// set green
std::uniform_int_distribution<> green_indicators_dist(1, 15);
uint8_t green_indicators = green_indicators_dist(gen);
set_unique_leds(indicator_options, green_indicators, 0, 10, 0);
set_unique_leds(indicator_options, green_indicators, LEDColor::LED_COLOR_GREEN);
// set non-green
const int NON_GREEN_INDICATOR_RED[3] = {20, 0, 10};
const int NON_GREEN_INDICATOR_GREEN[3] = {0, 0, 0};
const int NON_GREEN_INDICATOR_BLUE[3] = {0, 10, 5};
const uint32_t NON_GREEN_COLORS[] = {
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_BLUE,
LEDColor::LED_COLOR_PINK,
};
std::uniform_int_distribution<> non_green_indicators_dist(0, (20 - green_indicators));
set_unique_leds_random_color(indicator_options, non_green_indicators_dist(gen), NON_GREEN_INDICATOR_RED, NON_GREEN_INDICATOR_GREEN, NON_GREEN_INDICATOR_BLUE);
set_unique_leds_random_color(indicator_options, non_green_indicators_dist(gen), NON_GREEN_COLORS, sizeof(NON_GREEN_COLORS)/sizeof(NON_GREEN_COLORS[0]));
ESP_ERROR_CHECK(led_strip_refresh(leds));
leds_flush();
// wait for submit
KeypadKey key;
while (1) {
if (get_module_time() <= 0 || (get_pressed_keypad(&key) && (char_of_keypad_key(key) == '#'))) {
if (get_module_time() <= 0 || (get_keypad_pressed(&key) && (char_of_keypad_key(key) == '#'))) {
solved_correctly = submit_0(green_indicators);
break;
}
@@ -247,27 +265,24 @@ void step5(void) {
break;
}
case 1: {
lcd_print(&lcd, "Blank");
set_module_time(40000);
lcd_print("Blank");
set_module_time(TIME_BLANK);
start_module_timer();
std::uniform_int_distribution<> on_indicators_dist(16, 21);
uint8_t indicators_num = on_indicators_dist(gen);
std::vector<int> indicator_options = all_leds;
const int INDICATOR_RED[6] = {20, 0, 0, 10, 10, 5};
const int INDICATOR_GREEN[6] = {0, 0, 10, 5, 0, 7};
const int INDICATOR_BLUE[6] = {0, 10, 0, 0, 5, 5};
set_unique_leds_random_color(indicator_options, indicators_num, INDICATOR_RED, INDICATOR_BLUE, INDICATOR_GREEN);
ESP_ERROR_CHECK(led_strip_refresh(leds));
set_unique_leds_random_color(indicator_options, indicators_num, COLORS, sizeof(COLORS)/sizeof(COLORS[0]));
leds_flush();
uint8_t starting_switch_state = get_switch_state();
std::string pressed_keys;
KeypadKey key;
while (1) {
if (get_pressed_keypad(&key)) {
if (get_keypad_pressed(&key)) {
char keypad_char = char_of_keypad_key(key);
if (keypad_char == '#') {
solved_correctly = submit_1(indicators_num, pressed_keys, starting_switch_state);
@@ -285,7 +300,7 @@ void step5(void) {
break;
}
case 2: {
set_module_time(40000);
set_module_time(TIME_EMPTY);
start_module_timer();
std::map<int, int> idx_to_led_map = {
@@ -304,10 +319,10 @@ void step5(void) {
for (int i = 0; i < 5; i++) {
if (lit_leds[i]) {
int color = led_color_dist(gen);
ESP_ERROR_CHECK(led_strip_set_pixel(leds, idx_to_led_map[i], INDICATOR_RED[color], INDICATOR_GREEN[color], INDICATOR_BLUE[color]));
led_set(idx_to_led_map[i], COLORS[color]);
}
}
ESP_ERROR_CHECK(led_strip_refresh(leds));
leds_flush();
int green_button_pressed = 0;
int blue_button_pressed = 0;
@@ -318,7 +333,7 @@ void step5(void) {
ButtonKey button;
while (1) {
if (get_pressed_button(&button)) {
if (get_button_pressed(&button)) {
uint8_t button_state = get_button_state();
if ((button_state & 0b1) == 0b1) {
@@ -344,7 +359,7 @@ void step5(void) {
break;
}
}
if (get_pressed_keypad(&key)) {
if (get_keypad_pressed(&key)) {
char keypad_char = char_of_keypad_key(key);
if (keypad_char == '#') {
solved_correctly = submit_2(lit_leds, green_button_pressed, blue_button_pressed, fingerprint_sensor_pressed, keypad_string);
@@ -364,13 +379,16 @@ void step5(void) {
break;
}
case 3: {
lcd_print(&lcd, "Nothing");
set_module_time(25000);
lcd_print("Nothing");
set_module_time(TIME_NOTHING);
start_module_timer();
const int COLOR_RED[5] = {0, 20, 10, 0};
const int COLOR_GREEN[5] = {20, 0, 10, 0};
const int COLOR_BLUE[5] = {0, 0, 0, 20};
const uint32_t COLORS[] = {
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_YELLOW,
LEDColor::LED_COLOR_BLUE,
};
static std::uniform_int_distribution<> color_dist(0, 3);
@@ -378,18 +396,16 @@ void step5(void) {
int speaker_color = color_dist(gen);
int s3_color = color_dist(gen);
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 6, COLOR_RED[tft_color], COLOR_GREEN[tft_color], COLOR_BLUE[tft_color]));
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 9, COLOR_RED[speaker_color], COLOR_GREEN[speaker_color], COLOR_BLUE[speaker_color]));
ESP_ERROR_CHECK(led_strip_set_pixel(leds, 14, COLOR_RED[s3_color], COLOR_GREEN[s3_color], COLOR_BLUE[s3_color]));
ESP_ERROR_CHECK(led_strip_refresh(leds));
led_set(IndicatorLED::LED_TFT, COLORS[tft_color]);
led_set(IndicatorLED::LED_SPEAKER, COLORS[speaker_color]);
led_set(IndicatorLED::LED_S3, COLORS[s3_color]);
leds_flush();
int buttons_pressed = 0;
ButtonKey button;
KeypadKey key;
while (1) {
if (get_pressed_button(&button)) {
if (get_button_pressed(&button)) {
buttons_pressed++;
uint8_t button_state = get_button_state();
@@ -422,42 +438,48 @@ void step5(void) {
break;
}
case 4: {
lcd_print(&lcd, "Blink");
set_module_time(35000);
lcd_print("Blink");
set_module_time(TIME_BLINK);
start_module_timer();
// buttons
const int BUTTON_COLOR_RED[4] = {0, 20, 10, 0};
const int BUTTON_COLOR_GREEN[4] = {10, 0, 5, 0};
const int BUTTON_COLOR_BLUE[4] = {0, 0, 0, 10};
const uint32_t BUTTON_COLORS[] = {
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_YELLOW,
LEDColor::LED_COLOR_BLUE,
};
static std::uniform_int_distribution<> button_color_dist(0, 3);
int button_colors[4] = {button_color_dist(gen), button_color_dist(gen), button_color_dist(gen), button_color_dist(gen)};
for (int i = 0; i < 4; i++) {
ESP_ERROR_CHECK(led_strip_set_pixel(leds, (20 - i), BUTTON_COLOR_RED[button_colors[i]], BUTTON_COLOR_GREEN[button_colors[i]], BUTTON_COLOR_BLUE[button_colors[i]]));
led_set(IndicatorLED::LED_B1 - i, BUTTON_COLORS[button_colors[i]]);
}
// switches
const int SWITCH_COLOR_RED[3] = {20, 0, 10};
const int SWITCH_COLOR_GREEN[3] = {0, 10, 5};
const uint32_t SWITCH_COLOR[] = {
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_YELLOW,
};
static std::uniform_int_distribution<> switch_color_dist(0, 2);
int switch_colors[4] = {switch_color_dist(gen), switch_color_dist(gen), switch_color_dist(gen), switch_color_dist(gen)};
for (int i = 0; i < 4; i++) {
ESP_ERROR_CHECK(led_strip_set_pixel(leds, (16 - i), SWITCH_COLOR_RED[switch_colors[i]], SWITCH_COLOR_GREEN[switch_colors[i]], 0));
led_set(IndicatorLED::LED_S1 - i, SWITCH_COLOR[switch_colors[i]]);
}
ESP_ERROR_CHECK(led_strip_refresh(leds));
leds_flush();
ButtonKey button;
KeypadKey key;
uint8_t starting_switch_state = get_switch_state();
while (1) {
if (get_pressed_button(&button)) {
if (get_button_pressed(&button)) {
uint8_t button_state = get_button_state();
for (int i = 0; i < 4; i++) {
@@ -466,13 +488,12 @@ void step5(void) {
if (button_colors[i] > 3) {
button_colors[i] = 0;
}
ESP_ERROR_CHECK(led_strip_set_pixel(leds, (20 - i), BUTTON_COLOR_RED[button_colors[i]], BUTTON_COLOR_GREEN[button_colors[i]], BUTTON_COLOR_BLUE[button_colors[i]]));
led_set(IndicatorLED::LED_B1 - i, BUTTON_COLORS[button_colors[i]]);
}
}
ESP_ERROR_CHECK(led_strip_refresh(leds));
leds_flush();
}
if (get_module_time() <= 0 || (get_pressed_keypad(&key) && (char_of_keypad_key(key) == '#'))) {
if (get_module_time() <= 0 || (get_keypad_pressed(&key) && (char_of_keypad_key(key) == '#'))) {
solved_correctly = submit_4(button_colors, switch_colors, starting_switch_state);
break;
}
@@ -481,31 +502,34 @@ void step5(void) {
break;
}
case 5: {
lcd_print(&lcd, "Ummm");
set_module_time(35000);
lcd_print("Ummm");
set_module_time(TIME_UMMM);
start_module_timer();
std::uniform_int_distribution<> indicator_number_dist(0, 5);
const int INDICATOR_RED[4] = {0, 20, 10, 0};
const int INDICATOR_GREEN[4] = {10, 0, 5, 0};
const int INDICATOR_BLUE[4] = {0, 0, 0, 10};
const uint32_t COLORS[] = {
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_YELLOW,
LEDColor::LED_COLOR_BLUE,
};
// green, red, yellow, blue
std::array<int, 4> indicator_numbers = {indicator_number_dist(gen), indicator_number_dist(gen), indicator_number_dist(gen), indicator_number_dist(gen)};
std::vector<int> indicator_options = all_leds;
for (int i = 0; i < 4; i++) {
set_unique_leds(indicator_options, indicator_numbers[i], INDICATOR_RED[i], INDICATOR_GREEN[i], INDICATOR_BLUE[i]);
set_unique_leds(indicator_options, indicator_numbers[i], COLORS[i]);
}
ESP_ERROR_CHECK(led_strip_refresh(leds));
leds_flush();
std::array<int, 4> buttons_pressed = {0, 0, 0, 0};
ButtonKey button;
KeypadKey key;
while (1) {
if (get_pressed_button(&button)) {
if (get_button_pressed(&button)) {
uint8_t button_state = get_button_state();
bool failed = false;
@@ -523,7 +547,7 @@ void step5(void) {
break;
}
}
if (get_module_time() <= 0 || (get_pressed_keypad(&key) && (char_of_keypad_key(key) == '#'))) {
if (get_module_time() <= 0 || (get_keypad_pressed(&key) && (char_of_keypad_key(key) == '#'))) {
ESP_LOGI(TAG, "Keypad Char: %c, time: %lu", char_of_keypad_key(key), get_module_time());
solved_correctly = submit_5(indicator_numbers, buttons_pressed);
break;
@@ -534,17 +558,21 @@ void step5(void) {
break;
}
case 6: {
lcd_print(&lcd, "Plank");
set_module_time(40000);
lcd_print("Plank");
set_module_time(TIME_PLANK);
start_module_timer();
std::uniform_int_distribution<> led_color_dist(0, 5);
std::uniform_int_distribution<> led_off_dist(-1, 3);
// red, purple, blue, white, green, yellow
const uint8_t COLORS_RED[6] = {20, 10, 0, 5, 0, 10};
const uint8_t COLORS_GREEN[6] = {0, 0, 0, 7, 10, 5};
const uint8_t COLORS_BLUE[6] = {0, 10, 10, 5, 0, 0};
const uint32_t COLORS[] = {
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_PINK,
LEDColor::LED_COLOR_BLUE,
LEDColor::LED_COLOR_WHITE,
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_YELLOW,
};
int button_colors[4];
bool buttons_cycling[4];
@@ -553,14 +581,14 @@ void step5(void) {
for (int i = 0; i < 4; i++) {
if (led_off != i) {
button_colors[i] = led_color_dist(gen);
ESP_ERROR_CHECK(led_strip_set_pixel(leds, (20 - i), COLORS_RED[button_colors[i]], COLORS_GREEN[button_colors[i]], COLORS_BLUE[button_colors[i]]));
led_set(IndicatorLED::LED_B1 - i, COLORS[button_colors[i]]);
buttons_cycling[i] = true;
} else {
button_colors[i] = -1;
buttons_cycling[i] = false;
}
}
ESP_ERROR_CHECK(led_strip_refresh(leds));
leds_flush();
const uint8_t CORRECT_COLORS[4] = {4, 0, 5, 2};
TickType_t lastCycleTime = xTaskGetTickCount();
@@ -571,7 +599,7 @@ void step5(void) {
std::uniform_int_distribution<> led_turn_on_dist(0, 3);
while (1) {
if (get_pressed_button(&button)) {
if (get_button_pressed(&button)) {
uint8_t button_state = get_button_state();
bool failed = false;
@@ -584,8 +612,8 @@ void step5(void) {
break;
} else if (led_turn_on_dist(gen) == 0) {
button_turned_on = true;
led_strip_set_pixel(leds, (20 - i), COLORS_RED[CORRECT_COLORS[i]], COLORS_GREEN[CORRECT_COLORS[i]], COLORS_BLUE[CORRECT_COLORS[i]]);
led_strip_refresh(leds);
led_set(IndicatorLED::LED_B1 - i, COLORS[CORRECT_COLORS[i]]);
leds_flush();
}
} else if (button_colors[i] != CORRECT_COLORS[i]) {
strike("Wrong time!");
@@ -601,21 +629,20 @@ void step5(void) {
}
}
if ((xTaskGetTickCount() - lastCycleTime) >= pdMS_TO_TICKS(500)) {
for (int i = 0; i < 4; i++) {
for (uint32_t i = 0; i < 4; i++) {
if (buttons_cycling[i]) {
button_colors[i]++;
if (button_colors[i] > 5) {
button_colors[i] = 0;
}
ESP_ERROR_CHECK(led_strip_set_pixel(leds, (20 - i), COLORS_RED[button_colors[i]], COLORS_GREEN[button_colors[i]], COLORS_BLUE[button_colors[i]]));
led_set(IndicatorLED::LED_B1 - i, COLORS[button_colors[i]]);
}
}
ESP_ERROR_CHECK(led_strip_refresh(leds));
leds_flush();
lastCycleTime = xTaskGetTickCount();
}
get_pressed_keypad(&key);
if (get_module_time() <= 0 || (get_pressed_keypad(&key) && (char_of_keypad_key(key) == '#'))) {
if (get_module_time() <= 0 || (get_keypad_pressed(&key) && (char_of_keypad_key(key) == '#'))) {
solved_correctly = submit_6(buttons_cycling, button_turned_on, led_off);
break;
}
@@ -624,8 +651,8 @@ void step5(void) {
break;
}
case 7: {
lcd_print(&lcd, "What");
set_module_time(55000);
lcd_print("What");
set_module_time(TIME_WHAT);
start_module_timer();
std::uniform_int_distribution<> math_number_dist(1, 9);
@@ -697,15 +724,15 @@ void step5(void) {
}
// display expression
lcd_set_cursor(&lcd, 1, 2);
lcd_print(&lcd, display_expression.c_str());
lcd_print(1, 2, display_expression.c_str());
// set LEDs
// blue, red, green, yellow
const int INDICATOR_RED[4] = {0, 20, 0, 10};
const int INDICATOR_GREEN[4] = {0, 0, 10, 5};
const int INDICATOR_BLUE[4] = {10, 0, 0, 0};
const uint32_t COLORS[] = {
LEDColor::LED_COLOR_BLUE,
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_YELLOW,
};
std::uniform_int_distribution<> add_sub_indicator_dist(1, 6);
std::uniform_int_distribution<> mult_div_indicator_dist(1, 3);
@@ -727,10 +754,10 @@ void step5(void) {
std::vector<int> led_options = all_leds;
for (int i = 0; i < 4; i++) {
set_unique_leds(led_options, modifier_indicators[i], INDICATOR_RED[i], INDICATOR_GREEN[i], INDICATOR_BLUE[i]);
set_unique_leds(led_options, modifier_indicators[i], COLORS[i]);
}
ESP_ERROR_CHECK(led_strip_refresh(leds));
leds_flush();
std::string answer_string = std::to_string(expression_answer);
std::string entered_string = "";
@@ -740,7 +767,7 @@ void step5(void) {
KeypadKey key;
while (1) {
if (get_pressed_keypad(&key)) {
if (get_keypad_pressed(&key)) {
if (key == KeypadKey::star) {
// clear
entered_string = "";
@@ -748,7 +775,6 @@ void step5(void) {
// submit
if (entered_string != answer_string) {
strike("Incorrect answer!");
break;
} else {
solved_correctly = true;
}
@@ -757,38 +783,37 @@ void step5(void) {
entered_string += char_of_keypad_key(key);
}
lcd_clear(&lcd);
lcd_set_cursor(&lcd, 1, 1);
lcd_print(&lcd, "What");
lcd_set_cursor(&lcd, 1, 2);
lcd_print(&lcd, display_expression.c_str());
lcd_set_cursor(&lcd, 1, 3);
lcd_print(&lcd, entered_string.c_str());
lcd_clear();
lcd_print(1, 1, "What");
lcd_print(1, 2, display_expression.c_str());
lcd_print(1, 3, entered_string.c_str());
}
if (get_module_time() <= 0) {
strike("Ran out of time!");
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
break;
}
case 8: {
lcd_print(&lcd, "Plink");
set_module_time(40000);
lcd_print("Plink");
set_module_time(TIME_PLINK);
start_module_timer();
std::uniform_int_distribution<> indicator_number_dist(0, 4);
// ESP_LOGI(TAG, "Green: %i, Red: %i, Yellow: %i, Blue: %i", green_indicators, red_indicators, yellow_indicators, blue_indicators);
// green, red, yellow, blue, purple
const int INDICATOR_RED[5] = {0, 20, 10, 0, 10};
const int INDICATOR_GREEN[5] = {10, 0, 5, 0, 0};
const int INDICATOR_BLUE[5] = {0, 0, 0, 10, 5};
const uint32_t COLORS[] = {
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_YELLOW,
LEDColor::LED_COLOR_BLUE,
LEDColor::LED_COLOR_PINK,
};
int solved_times = 0;
bool failed = false;
@@ -797,11 +822,10 @@ void step5(void) {
std::vector<int> led_options = all_leds;
for (int i = 0; i < 5; i++) {
set_unique_leds(led_options, indicator_numbers[i], INDICATOR_RED[i], INDICATOR_GREEN[i], INDICATOR_BLUE[i]);
set_unique_leds(led_options, indicator_numbers[i], COLORS[i]);
}
ESP_ERROR_CHECK(led_strip_refresh(leds));
leds_flush();
std::uniform_int_distribution<> answer_color_dist(0, 4);
@@ -810,7 +834,7 @@ void step5(void) {
{1, "Red"},
{2, "Yellow"},
{3, "Blue"},
{4, "Purple"},
{4, "Pink"},
};
int answer_color = answer_color_dist(gen);
@@ -820,14 +844,13 @@ void step5(void) {
// ESP_LOGI(TAG, "color string: %s", color_string.c_str());
lcd_set_cursor(&lcd, 1, 2);
lcd_print(&lcd, color_string.c_str());
lcd_print(1, 2, color_string.c_str());
std::string entered_string;
KeypadKey key;
while (1) {
if (get_pressed_keypad(&key)) {
if (get_keypad_pressed(&key)) {
bool failed = false;
if (key == KeypadKey::star) {
@@ -850,13 +873,10 @@ void step5(void) {
break;
}
lcd_clear(&lcd);
lcd_set_cursor(&lcd, 1, 1);
lcd_print(&lcd, "Plink");
lcd_set_cursor(&lcd, 1, 2);
lcd_print(&lcd, color_string.c_str());
lcd_set_cursor(&lcd, 1, 3);
lcd_print(&lcd, entered_string.c_str());
lcd_clear();
lcd_print(1, 1, "Plink");
lcd_print(1, 2, color_string.c_str());
lcd_print(1, 3, entered_string.c_str());
}
if (get_module_time() <= 0) {
strike("Ran out of time!");
@@ -880,7 +900,7 @@ void step5(void) {
stop_module_timer();
if (solved_correctly) {
solved_puzzles++;
play_raw(MOUNT_POINT "/correct.pcm");
play_clip_wav(MOUNT_POINT "/correct.wav", true, false, 3, 0);
vTaskDelay(pdMS_TO_TICKS(500));
solved_correctly = false;
} else {
+2 -2
View File
@@ -1,5 +1,6 @@
#include "step6.h"
__attribute__((unused))
static const char *TAG = "step6";
static uint8_t cut_wires = 0;
@@ -14,7 +15,6 @@ void step6(void) {
solve_wires(wires, solution);
while (1) {
uint8_t new_cut_wires = get_cut_wires();
uint8_t just_cut_wires = new_cut_wires & ~cut_wires;
cut_wires |= new_cut_wires;
@@ -22,7 +22,7 @@ void step6(void) {
for (int i = 0; i < NUM_WIRES; i++) {
if (just_cut_wires & (1<<i)) {
if (solution[i]) {
play_raw(MOUNT_POINT "/correct.pcm");
play_clip_wav(MOUNT_POINT "/correct.wav", true, false, 3, 0);
} else {
strike("Cut wrong wire");
}
@@ -0,0 +1,13 @@
set(SOURCES
"bg.c"
"clear.c"
"db.c"
"green.c"
"lb.c"
"orange.c"
"purple.c"
"red.c"
"yellow.c"
)
target_sources(${COMPONENT_LIB} PRIVATE ${SOURCES})
File diff suppressed because one or more lines are too long
+69
View File
@@ -0,0 +1,69 @@
#ifdef __has_include
#if __has_include("lvgl.h")
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
#define LV_LVGL_H_INCLUDE_SIMPLE
#endif
#endif
#endif
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_CLEAR
#define LV_ATTRIBUTE_IMG_CLEAR
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_CLEAR uint8_t clear_map[] = {
0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00,
0xbb, 0xde, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde,
0xbb, 0xde, 0x75, 0xad, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0xdb, 0xde, 0x75, 0xad, 0xbb, 0xde,
0xbb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0x5d, 0xef, 0x7d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7e, 0xf7, 0x7e, 0xf7, 0x5d, 0xef, 0xba, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0x5d, 0xef, 0x7d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7e, 0xf7, 0x7e, 0xf7, 0x5d, 0xef, 0xba, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0x5d, 0xef, 0x7d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7e, 0xf7, 0x7e, 0xf7, 0x5d, 0xef, 0xba, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0x5d, 0xef, 0x7d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7e, 0xf7, 0x7e, 0xf7, 0x5d, 0xef, 0xba, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0x5d, 0xef, 0x7d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7e, 0xf7, 0x7e, 0xf7, 0x5d, 0xef, 0xba, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0x5d, 0xef, 0x7d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7e, 0xf7, 0x7e, 0xf7, 0x5d, 0xef, 0xba, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0x5d, 0xef, 0x7d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7e, 0xf7, 0x7e, 0xf7, 0x5d, 0xef, 0xba, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0x5d, 0xef, 0x7d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7e, 0xf7, 0x7e, 0xf7, 0x5d, 0xef, 0xba, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0x5d, 0xef, 0x7d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7e, 0xf7, 0x7e, 0xf7, 0x5d, 0xef, 0xba, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xbb, 0xde, 0x5d, 0xef, 0x7d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x9e, 0xf7, 0x7e, 0xf7, 0x7e, 0xf7, 0x5d, 0xef, 0xba, 0xd6, 0x75, 0xad, 0xbb, 0xde,
0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xb7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xb7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xb7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xb7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xb7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xb7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xb7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xb7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xb7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xb7, 0xbd, 0x75, 0xad, 0xbb, 0xde,
0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0xf8, 0xc5, 0x38, 0xc6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x18, 0xc6, 0xd7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0xf8, 0xc5, 0x38, 0xc6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x18, 0xc6, 0xd7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0xf8, 0xc5, 0x38, 0xc6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x18, 0xc6, 0xd7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0xf8, 0xc5, 0x38, 0xc6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x18, 0xc6, 0xd7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0xf8, 0xc5, 0x38, 0xc6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x18, 0xc6, 0xd7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0xf8, 0xc5, 0x38, 0xc6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x18, 0xc6, 0xd7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0xf8, 0xc5, 0x38, 0xc6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x18, 0xc6, 0xd7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0xf8, 0xc5, 0x38, 0xc6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x18, 0xc6, 0xd7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0xf8, 0xc5, 0x38, 0xc6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x18, 0xc6, 0xd7, 0xbd, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xb7, 0xbd, 0xf8, 0xc5, 0x38, 0xc6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x18, 0xc6, 0xd7, 0xbd, 0x75, 0xad, 0xbb, 0xde,
0xbb, 0xde, 0x75, 0xad, 0xf7, 0xbd, 0x38, 0xc6, 0x79, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0x9a, 0xd6, 0x9a, 0xd6, 0x7a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf7, 0xbd, 0x38, 0xc6, 0x79, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0x9a, 0xd6, 0x9a, 0xd6, 0x7a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf7, 0xbd, 0x38, 0xc6, 0x79, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0x9a, 0xd6, 0x9a, 0xd6, 0x7a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf7, 0xbd, 0x38, 0xc6, 0x79, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0x9a, 0xd6, 0x9a, 0xd6, 0x7a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf7, 0xbd, 0x38, 0xc6, 0x79, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0x9a, 0xd6, 0x9a, 0xd6, 0x7a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf7, 0xbd, 0x38, 0xc6, 0x79, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0x9a, 0xd6, 0x9a, 0xd6, 0x7a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf7, 0xbd, 0x38, 0xc6, 0x79, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0x9a, 0xd6, 0x9a, 0xd6, 0x7a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf7, 0xbd, 0x38, 0xc6, 0x79, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0x9a, 0xd6, 0x9a, 0xd6, 0x7a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf7, 0xbd, 0x38, 0xc6, 0x79, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0x9a, 0xd6, 0x9a, 0xd6, 0x7a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf7, 0xbd, 0x38, 0xc6, 0x79, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xba, 0xd6, 0xba, 0xd6, 0x9a, 0xd6, 0x9a, 0xd6, 0x7a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde,
0xbb, 0xde, 0x75, 0xad, 0xf8, 0xc5, 0x59, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x9a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf8, 0xc5, 0x59, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x9a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf8, 0xc5, 0x59, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x9a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf8, 0xc5, 0x59, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x9a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf8, 0xc5, 0x59, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x9a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf8, 0xc5, 0x59, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x9a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf8, 0xc5, 0x59, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x9a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf8, 0xc5, 0x59, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x9a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf8, 0xc5, 0x59, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x9a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0xf8, 0xc5, 0x59, 0xce, 0x7a, 0xd6, 0x9a, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0x9a, 0xd6, 0x59, 0xce, 0x18, 0xc6, 0x75, 0xad, 0xbb, 0xde,
0xbb, 0xde, 0x75, 0xad, 0x18, 0xc6, 0x79, 0xce, 0x9a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xdb, 0xde, 0xbb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x18, 0xc6, 0x79, 0xce, 0x9a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xdb, 0xde, 0xbb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x18, 0xc6, 0x79, 0xce, 0x9a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xdb, 0xde, 0xbb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x18, 0xc6, 0x79, 0xce, 0x9a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xdb, 0xde, 0xbb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x18, 0xc6, 0x79, 0xce, 0x9a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xdb, 0xde, 0xbb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x18, 0xc6, 0x79, 0xce, 0x9a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xdb, 0xde, 0xbb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x18, 0xc6, 0x79, 0xce, 0x9a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xdb, 0xde, 0xbb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x18, 0xc6, 0x79, 0xce, 0x9a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xdb, 0xde, 0xbb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x18, 0xc6, 0x79, 0xce, 0x9a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xdb, 0xde, 0xbb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x18, 0xc6, 0x79, 0xce, 0x9a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xfb, 0xde, 0xdb, 0xde, 0xbb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xbb, 0xde,
0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x7a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0xfc, 0xe6, 0xdb, 0xde, 0xdb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x7a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0xfc, 0xe6, 0xdb, 0xde, 0xdb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x7a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0xfc, 0xe6, 0xdb, 0xde, 0xdb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x7a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0xfc, 0xe6, 0xdb, 0xde, 0xdb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x7a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0xfc, 0xe6, 0xdb, 0xde, 0xdb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x7a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0xfc, 0xe6, 0xdb, 0xde, 0xdb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x7a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0xfc, 0xe6, 0xdb, 0xde, 0xdb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x7a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0xfc, 0xe6, 0xdb, 0xde, 0xdb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x7a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0xfc, 0xe6, 0xdb, 0xde, 0xdb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x7a, 0xd6, 0xbb, 0xde, 0xdb, 0xde, 0xfb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0xfc, 0xe6, 0xdb, 0xde, 0xdb, 0xde, 0x9a, 0xd6, 0x59, 0xce, 0x75, 0xad, 0xba, 0xd6,
0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x9a, 0xd6, 0xdb, 0xde, 0xfb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x3c, 0xe7, 0x1c, 0xe7, 0xfc, 0xe6, 0xfb, 0xde, 0xba, 0xd6, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x9a, 0xd6, 0xdb, 0xde, 0xfb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x3c, 0xe7, 0x1c, 0xe7, 0xfc, 0xe6, 0xfb, 0xde, 0xba, 0xd6, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x9a, 0xd6, 0xdb, 0xde, 0xfb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x3c, 0xe7, 0x1c, 0xe7, 0xfc, 0xe6, 0xfb, 0xde, 0xba, 0xd6, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x9a, 0xd6, 0xdb, 0xde, 0xfb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x3c, 0xe7, 0x1c, 0xe7, 0xfc, 0xe6, 0xfb, 0xde, 0xba, 0xd6, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x9a, 0xd6, 0xdb, 0xde, 0xfb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x3c, 0xe7, 0x1c, 0xe7, 0xfc, 0xe6, 0xfb, 0xde, 0xba, 0xd6, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x9a, 0xd6, 0xdb, 0xde, 0xfb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x3c, 0xe7, 0x1c, 0xe7, 0xfc, 0xe6, 0xfb, 0xde, 0xba, 0xd6, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x9a, 0xd6, 0xdb, 0xde, 0xfb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x3c, 0xe7, 0x1c, 0xe7, 0xfc, 0xe6, 0xfb, 0xde, 0xba, 0xd6, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x9a, 0xd6, 0xdb, 0xde, 0xfb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x3c, 0xe7, 0x1c, 0xe7, 0xfc, 0xe6, 0xfb, 0xde, 0xba, 0xd6, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x9a, 0xd6, 0xdb, 0xde, 0xfb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x3c, 0xe7, 0x1c, 0xe7, 0xfc, 0xe6, 0xfb, 0xde, 0xba, 0xd6, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x39, 0xce, 0x9a, 0xd6, 0xdb, 0xde, 0xfb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x3c, 0xe7, 0x1c, 0xe7, 0xfc, 0xe6, 0xfb, 0xde, 0xba, 0xd6, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6,
0xbb, 0xde, 0x75, 0xad, 0x59, 0xce, 0x9a, 0xd6, 0xfb, 0xde, 0xfc, 0xe6, 0x3c, 0xe7, 0x3d, 0xef, 0x3d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xfc, 0xe6, 0xbb, 0xde, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x59, 0xce, 0x9a, 0xd6, 0xfb, 0xde, 0xfc, 0xe6, 0x3c, 0xe7, 0x3d, 0xef, 0x3d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xfc, 0xe6, 0xbb, 0xde, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x59, 0xce, 0x9a, 0xd6, 0xfb, 0xde, 0xfc, 0xe6, 0x3c, 0xe7, 0x3d, 0xef, 0x3d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xfc, 0xe6, 0xbb, 0xde, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x59, 0xce, 0x9a, 0xd6, 0xfb, 0xde, 0xfc, 0xe6, 0x3c, 0xe7, 0x3d, 0xef, 0x3d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xfc, 0xe6, 0xbb, 0xde, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x59, 0xce, 0x9a, 0xd6, 0xfb, 0xde, 0xfc, 0xe6, 0x3c, 0xe7, 0x3d, 0xef, 0x3d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xfc, 0xe6, 0xbb, 0xde, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x59, 0xce, 0x9a, 0xd6, 0xfb, 0xde, 0xfc, 0xe6, 0x3c, 0xe7, 0x3d, 0xef, 0x3d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xfc, 0xe6, 0xbb, 0xde, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x59, 0xce, 0x9a, 0xd6, 0xfb, 0xde, 0xfc, 0xe6, 0x3c, 0xe7, 0x3d, 0xef, 0x3d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xfc, 0xe6, 0xbb, 0xde, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x59, 0xce, 0x9a, 0xd6, 0xfb, 0xde, 0xfc, 0xe6, 0x3c, 0xe7, 0x3d, 0xef, 0x3d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xfc, 0xe6, 0xbb, 0xde, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x59, 0xce, 0x9a, 0xd6, 0xfb, 0xde, 0xfc, 0xe6, 0x3c, 0xe7, 0x3d, 0xef, 0x3d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xfc, 0xe6, 0xbb, 0xde, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6, 0xbb, 0xde, 0x75, 0xad, 0x59, 0xce, 0x9a, 0xd6, 0xfb, 0xde, 0xfc, 0xe6, 0x3c, 0xe7, 0x3d, 0xef, 0x3d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xfc, 0xe6, 0xbb, 0xde, 0x7a, 0xd6, 0x75, 0xad, 0xba, 0xd6,
0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0x5d, 0xef, 0x5d, 0xef, 0x7d, 0xef, 0x5d, 0xef, 0x3c, 0xe7, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0x5d, 0xef, 0x5d, 0xef, 0x7d, 0xef, 0x5d, 0xef, 0x3c, 0xe7, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0x5d, 0xef, 0x5d, 0xef, 0x7d, 0xef, 0x5d, 0xef, 0x3c, 0xe7, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0x5d, 0xef, 0x5d, 0xef, 0x7d, 0xef, 0x5d, 0xef, 0x3c, 0xe7, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0x5d, 0xef, 0x5d, 0xef, 0x7d, 0xef, 0x5d, 0xef, 0x3c, 0xe7, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0x5d, 0xef, 0x5d, 0xef, 0x7d, 0xef, 0x5d, 0xef, 0x3c, 0xe7, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0x5d, 0xef, 0x5d, 0xef, 0x7d, 0xef, 0x5d, 0xef, 0x3c, 0xe7, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0x5d, 0xef, 0x5d, 0xef, 0x7d, 0xef, 0x5d, 0xef, 0x3c, 0xe7, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0x5d, 0xef, 0x5d, 0xef, 0x7d, 0xef, 0x5d, 0xef, 0x3c, 0xe7, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0xfc, 0xe6, 0x1c, 0xe7, 0x5d, 0xef, 0x5d, 0xef, 0x7d, 0xef, 0x5d, 0xef, 0x3c, 0xe7, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde,
0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x5d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x7d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x5d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x7d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x5d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x7d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x5d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x7d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x5d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x7d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x5d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x7d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x5d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x7d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x5d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x7d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x5d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x7d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde, 0xbb, 0xde, 0x75, 0xad, 0x79, 0xce, 0xbb, 0xde, 0x1c, 0xe7, 0x1c, 0xe7, 0x5d, 0xef, 0x7e, 0xf7, 0x9e, 0xf7, 0x7d, 0xef, 0x3d, 0xef, 0x1c, 0xe7, 0xdb, 0xde, 0x9a, 0xd6, 0x75, 0xad, 0xbb, 0xde,
0xba, 0xd6, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xba, 0xd6, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xba, 0xd6, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xba, 0xd6, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xba, 0xd6, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xba, 0xd6, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xba, 0xd6, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xba, 0xd6, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xba, 0xd6, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde, 0xba, 0xd6, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0x75, 0xad, 0xbb, 0xde,
0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xbb, 0xde, 0xba, 0xd6, 0xbb, 0xde, 0xba, 0xd6, 0x00, 0x00,
/*alpha channel*/
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
};
const lv_img_dsc_t clear = {
.header.cf = LV_IMG_CF_RGB565A8,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 160,
.header.h = 16,
.data_size = 7680,
.data = clear_map,
};
+69
View File
@@ -0,0 +1,69 @@
#ifdef __has_include
#if __has_include("lvgl.h")
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
#define LV_LVGL_H_INCLUDE_SIMPLE
#endif
#endif
#endif
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_DB
#define LV_ATTRIBUTE_IMG_DB
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_DB uint8_t db_map[] = {
0x00, 0x00, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x00, 0x00,
0x13, 0x33, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x34, 0x33, 0x54, 0x33, 0x54, 0x33, 0x54, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0x13, 0x33, 0xb5, 0x4b, 0xd5, 0x4b, 0xf6, 0x4b, 0xf7, 0x4b, 0x17, 0x4c, 0x17, 0x4c, 0x17, 0x4c, 0xf6, 0x4b, 0xf6, 0x4b, 0xb5, 0x4b, 0x13, 0x33, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0xf1, 0x01, 0xd5, 0x4b, 0xdd, 0xce, 0xbb, 0x9d, 0xb9, 0x64, 0xb9, 0x64, 0xb9, 0x64, 0xb9, 0x64, 0xb9, 0x64, 0x98, 0x64, 0xf6, 0x4b, 0xf1, 0x01, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0xf1, 0x01, 0x53, 0x02, 0x95, 0x02, 0x58, 0x54, 0x7b, 0x85, 0x1a, 0x6d, 0x1a, 0x6d, 0x1a, 0x6d, 0x79, 0x54, 0xb5, 0x02, 0x74, 0x02, 0x32, 0x02, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0x32, 0x02, 0x95, 0x02, 0xd6, 0x02, 0xf7, 0x02, 0x38, 0x03, 0x38, 0x03, 0x59, 0x03, 0x38, 0x03, 0x18, 0x03, 0xf7, 0x02, 0xb5, 0x02, 0x53, 0x02, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0x53, 0x02, 0xb5, 0x02, 0xf7, 0x02, 0x18, 0x03, 0x59, 0x03, 0x59, 0x03, 0x59, 0x03, 0x59, 0x03, 0x38, 0x03, 0x18, 0x03, 0xd6, 0x02, 0x74, 0x02, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0x74, 0x02, 0xd6, 0x02, 0x38, 0x03, 0x59, 0x03, 0x7a, 0x03, 0x9a, 0x03, 0xbb, 0x03, 0x9a, 0x03, 0x7a, 0x03, 0x59, 0x03, 0x17, 0x03, 0xb5, 0x02, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0x95, 0x02, 0xf7, 0x02, 0x59, 0x03, 0x5a, 0x03, 0xbb, 0x03, 0xbb, 0x03, 0xbb, 0x03, 0xbb, 0x03, 0x9a, 0x03, 0x59, 0x03, 0x38, 0x03, 0xb6, 0x02, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0xb5, 0x02, 0x18, 0x03, 0x7a, 0x03, 0xbb, 0x03, 0xfc, 0x03, 0xfc, 0x03, 0x1d, 0x04, 0xfc, 0x03, 0xbb, 0x03, 0x9b, 0x03, 0x59, 0x03, 0xd7, 0x02, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0xb6, 0x02, 0x38, 0x03, 0x9a, 0x03, 0xbb, 0x03, 0xfc, 0x03, 0x1d, 0x04, 0x1d, 0x04, 0x1d, 0x04, 0xfc, 0x03, 0xbb, 0x03, 0x59, 0x03, 0xf7, 0x02, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0xd6, 0x02, 0x59, 0x03, 0xbb, 0x03, 0xfc, 0x03, 0x3d, 0x04, 0x5e, 0x04, 0x7e, 0x04, 0x5e, 0x04, 0x1d, 0x04, 0xfc, 0x03, 0x7a, 0x03, 0x18, 0x03, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0xd7, 0x02, 0x59, 0x03, 0xbb, 0x03, 0xfc, 0x03, 0x5e, 0x04, 0x9f, 0x04, 0xbf, 0x04, 0x7f, 0x04, 0x1d, 0x04, 0xfc, 0x03, 0x9a, 0x03, 0x18, 0x03, 0xaf, 0x01, 0x13, 0x33,
0x13, 0x33, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0xaf, 0x01, 0x13, 0x33,
0x00, 0x00, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x13, 0x33, 0x00, 0x00,
/*alpha channel*/
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
};
const lv_img_dsc_t db = {
.header.cf = LV_IMG_CF_RGB565A8,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 16,
.header.h = 16,
.data_size = 768,
.data = db_map,
};
+69
View File
@@ -0,0 +1,69 @@
#ifdef __has_include
#if __has_include("lvgl.h")
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
#define LV_LVGL_H_INCLUDE_SIMPLE
#endif
#endif
#endif
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_GREEN
#define LV_ATTRIBUTE_IMG_GREEN
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_GREEN uint8_t green_map[] = {
0x00, 0x00, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0x00, 0x00,
0xa9, 0x34, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0xe9, 0x34, 0xe9, 0x34, 0xe9, 0x34, 0xe9, 0x34, 0x09, 0x35, 0x09, 0x35, 0x09, 0x35, 0x09, 0x35, 0xe9, 0x34, 0xe9, 0x34, 0xe9, 0x34, 0xe9, 0x34, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0xe9, 0x34, 0x2c, 0x4d, 0x6c, 0x4d, 0x8c, 0x4d, 0xac, 0x4d, 0xcc, 0x4d, 0xcc, 0x4d, 0xcc, 0x4d, 0x8c, 0x4d, 0x8c, 0x4d, 0x2c, 0x4d, 0xc9, 0x34, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0x44, 0x04, 0x6c, 0x4d, 0x7a, 0xcf, 0xb5, 0x9e, 0x4f, 0x66, 0x4f, 0x66, 0x4f, 0x66, 0x4f, 0x66, 0x2f, 0x66, 0x0f, 0x66, 0x8c, 0x4d, 0x44, 0x04, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0x44, 0x04, 0xc4, 0x04, 0x25, 0x05, 0x0e, 0x56, 0xd3, 0x86, 0x91, 0x6e, 0x91, 0x6e, 0x91, 0x6e, 0x2e, 0x56, 0x65, 0x05, 0x05, 0x05, 0x84, 0x04, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0xa4, 0x04, 0x25, 0x05, 0xa5, 0x05, 0xc6, 0x05, 0x06, 0x06, 0x26, 0x06, 0x26, 0x06, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x05, 0x65, 0x05, 0xe5, 0x04, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0xc4, 0x04, 0x65, 0x05, 0xc6, 0x05, 0xe6, 0x05, 0x46, 0x06, 0x47, 0x06, 0x47, 0x06, 0x47, 0x06, 0x26, 0x06, 0x06, 0x06, 0x85, 0x05, 0x05, 0x05, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0x05, 0x05, 0xa5, 0x05, 0x06, 0x06, 0x47, 0x06, 0x87, 0x06, 0xa7, 0x06, 0xa7, 0x06, 0xa7, 0x06, 0x67, 0x06, 0x46, 0x06, 0xe6, 0x05, 0x65, 0x05, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0x45, 0x05, 0xc6, 0x05, 0x46, 0x06, 0x67, 0x06, 0xa7, 0x06, 0xc8, 0x06, 0xe8, 0x06, 0xc8, 0x06, 0x87, 0x06, 0x67, 0x06, 0x06, 0x06, 0x85, 0x05, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0x65, 0x05, 0x06, 0x06, 0x87, 0x06, 0xa7, 0x06, 0x08, 0x07, 0x08, 0x07, 0x28, 0x07, 0x28, 0x07, 0xe8, 0x06, 0xa7, 0x06, 0x46, 0x06, 0xc6, 0x05, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0x65, 0x05, 0x06, 0x06, 0xa7, 0x06, 0xc7, 0x06, 0x28, 0x07, 0x48, 0x07, 0x48, 0x07, 0x48, 0x07, 0x08, 0x07, 0xc7, 0x06, 0x47, 0x06, 0xc6, 0x05, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0xa5, 0x05, 0x46, 0x06, 0xc7, 0x06, 0x08, 0x07, 0x69, 0x07, 0x89, 0x07, 0xa9, 0x07, 0x89, 0x07, 0x28, 0x07, 0x08, 0x07, 0x87, 0x06, 0xe6, 0x05, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0xa5, 0x05, 0x47, 0x06, 0xe8, 0x06, 0x08, 0x07, 0x89, 0x07, 0xc9, 0x07, 0xea, 0x07, 0xa9, 0x07, 0x48, 0x07, 0x08, 0x07, 0x87, 0x06, 0x06, 0x06, 0xa3, 0x03, 0xa9, 0x34,
0xa9, 0x34, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa3, 0x03, 0xa9, 0x34,
0x00, 0x00, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0xa9, 0x34, 0x00, 0x00,
/*alpha channel*/
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
};
const lv_img_dsc_t green = {
.header.cf = LV_IMG_CF_RGB565A8,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 16,
.header.h = 16,
.data_size = 768,
.data = green_map,
};
+69
View File
@@ -0,0 +1,69 @@
#ifdef __has_include
#if __has_include("lvgl.h")
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
#define LV_LVGL_H_INCLUDE_SIMPLE
#endif
#endif
#endif
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_LB
#define LV_ATTRIBUTE_IMG_LB
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_LB uint8_t lb_map[] = {
0x00, 0x00, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x00, 0x00,
0x53, 0x34, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0x73, 0x34, 0x73, 0x34, 0x73, 0x34, 0x73, 0x34, 0x94, 0x34, 0x94, 0x34, 0x94, 0x34, 0x94, 0x34, 0x73, 0x34, 0x73, 0x34, 0x73, 0x34, 0x73, 0x34, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0x73, 0x34, 0xd5, 0x4c, 0x15, 0x4d, 0x36, 0x4d, 0x37, 0x4d, 0x57, 0x4d, 0x57, 0x4d, 0x57, 0x4d, 0x36, 0x4d, 0x16, 0x4d, 0xf5, 0x4c, 0x53, 0x34, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0xb1, 0x03, 0x15, 0x4d, 0x3d, 0xcf, 0x7b, 0x9e, 0xd9, 0x65, 0xd9, 0x65, 0xf9, 0x65, 0xf9, 0x65, 0xd9, 0x65, 0xd8, 0x65, 0x36, 0x4d, 0xb1, 0x03, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0xb1, 0x03, 0x33, 0x04, 0x95, 0x04, 0xb8, 0x55, 0x7b, 0x86, 0x3a, 0x6e, 0x3a, 0x6e, 0x3a, 0x6e, 0xd9, 0x55, 0xd5, 0x04, 0x54, 0x04, 0xf2, 0x03, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0x12, 0x04, 0x95, 0x04, 0x16, 0x05, 0x37, 0x05, 0x78, 0x05, 0x78, 0x05, 0x99, 0x05, 0x78, 0x05, 0x58, 0x05, 0x37, 0x05, 0xd5, 0x04, 0x53, 0x04, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0x33, 0x04, 0xb5, 0x04, 0x37, 0x05, 0x58, 0x05, 0x99, 0x05, 0xb9, 0x05, 0xb9, 0x05, 0xb9, 0x05, 0x78, 0x05, 0x58, 0x05, 0xf6, 0x04, 0x74, 0x04, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0x74, 0x04, 0x16, 0x05, 0x78, 0x05, 0xb9, 0x05, 0xda, 0x05, 0xfa, 0x05, 0x1b, 0x06, 0xfa, 0x05, 0xda, 0x05, 0x99, 0x05, 0x37, 0x05, 0xb5, 0x04, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0xb5, 0x04, 0x37, 0x05, 0x99, 0x05, 0xda, 0x05, 0x1b, 0x06, 0x3b, 0x06, 0x3b, 0x06, 0x3b, 0x06, 0xfa, 0x05, 0xd9, 0x05, 0x78, 0x05, 0xd6, 0x04, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0xb5, 0x04, 0x58, 0x05, 0xda, 0x05, 0x1b, 0x06, 0x5c, 0x06, 0x7c, 0x06, 0x7d, 0x06, 0x7c, 0x06, 0x3b, 0x06, 0xfb, 0x05, 0x99, 0x05, 0x17, 0x05, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0xd6, 0x04, 0x78, 0x05, 0xfa, 0x05, 0x1b, 0x06, 0x7c, 0x06, 0x9d, 0x06, 0x9d, 0x06, 0x9d, 0x06, 0x5c, 0x06, 0x1b, 0x06, 0xb9, 0x05, 0x37, 0x05, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0x16, 0x05, 0x99, 0x05, 0x1b, 0x06, 0x5c, 0x06, 0xbd, 0x06, 0xde, 0x06, 0xfe, 0x06, 0xde, 0x06, 0x9d, 0x06, 0x5c, 0x06, 0xda, 0x05, 0x58, 0x05, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0x17, 0x05, 0xb9, 0x05, 0x3b, 0x06, 0x7c, 0x06, 0xde, 0x06, 0x1f, 0x07, 0x3f, 0x07, 0x1f, 0x07, 0x9d, 0x06, 0x7c, 0x06, 0xfa, 0x05, 0x58, 0x05, 0x2f, 0x03, 0x53, 0x34,
0x53, 0x34, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x2f, 0x03, 0x53, 0x34,
0x00, 0x00, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x53, 0x34, 0x00, 0x00,
/*alpha channel*/
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
};
const lv_img_dsc_t lb = {
.header.cf = LV_IMG_CF_RGB565A8,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 16,
.header.h = 16,
.data_size = 768,
.data = lb_map,
};
+69
View File
@@ -0,0 +1,69 @@
#ifdef __has_include
#if __has_include("lvgl.h")
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
#define LV_LVGL_H_INCLUDE_SIMPLE
#endif
#endif
#endif
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_ORANGE
#define LV_ATTRIBUTE_IMG_ORANGE
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ORANGE uint8_t orange_map[] = {
0x00, 0x00, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x00, 0x00,
0x66, 0x9b, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0x86, 0x9b, 0x86, 0x9b, 0x86, 0x9b, 0x86, 0x9b, 0xa6, 0xa3, 0xa6, 0xa3, 0xa6, 0xa3, 0xa6, 0xa3, 0x86, 0x9b, 0x86, 0x9b, 0x86, 0x9b, 0x86, 0x9b, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0x86, 0x9b, 0x09, 0xac, 0x49, 0xac, 0x49, 0xb4, 0x69, 0xbc, 0x69, 0xbc, 0x89, 0xbc, 0x69, 0xbc, 0x49, 0xb4, 0x49, 0xb4, 0x09, 0xac, 0x86, 0x9b, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0x80, 0x8a, 0x29, 0xac, 0xf9, 0xee, 0xf3, 0xdd, 0x0c, 0xcd, 0x0c, 0xcd, 0x2c, 0xcd, 0x0c, 0xcd, 0x0c, 0xcd, 0xec, 0xc4, 0x49, 0xb4, 0x80, 0x8a, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0x80, 0x8a, 0xe0, 0x9a, 0x40, 0xab, 0xca, 0xc4, 0xd0, 0xdd, 0x6d, 0xd5, 0x6d, 0xd5, 0x6d, 0xd5, 0xea, 0xcc, 0x60, 0xab, 0x00, 0xa3, 0xc0, 0x92, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0xc0, 0x92, 0x40, 0xab, 0x80, 0xb3, 0xa0, 0xbb, 0xe0, 0xc3, 0xe0, 0xc3, 0x00, 0xcc, 0xe0, 0xc3, 0xe0, 0xc3, 0xa0, 0xbb, 0x60, 0xab, 0xe0, 0x9a, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0xe0, 0x9a, 0x40, 0xab, 0xa0, 0xbb, 0xe0, 0xc3, 0x00, 0xcc, 0x20, 0xcc, 0x20, 0xcc, 0x20, 0xcc, 0xe0, 0xc3, 0xe0, 0xc3, 0x80, 0xb3, 0x20, 0xa3, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0x20, 0xa3, 0x80, 0xb3, 0xe0, 0xc3, 0x20, 0xcc, 0x40, 0xd4, 0x60, 0xd4, 0x80, 0xdc, 0x60, 0xd4, 0x40, 0xd4, 0x20, 0xcc, 0xc0, 0xbb, 0x40, 0xab, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0x40, 0xab, 0xa0, 0xbb, 0x00, 0xcc, 0x40, 0xd4, 0x80, 0xdc, 0xa0, 0xdc, 0xa0, 0xdc, 0xa0, 0xdc, 0x60, 0xd4, 0x40, 0xcc, 0xe0, 0xc3, 0x60, 0xb3, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0x40, 0xab, 0xe0, 0xc3, 0x40, 0xd4, 0x80, 0xdc, 0xc0, 0xe4, 0xe0, 0xe4, 0xe0, 0xec, 0xe0, 0xe4, 0xa0, 0xdc, 0x80, 0xdc, 0x00, 0xcc, 0xa0, 0xbb, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0x60, 0xb3, 0xe0, 0xc3, 0x60, 0xd4, 0x80, 0xdc, 0xe0, 0xe4, 0x00, 0xed, 0x00, 0xed, 0x00, 0xed, 0xc0, 0xe4, 0x80, 0xdc, 0x20, 0xcc, 0xa0, 0xbb, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0x80, 0xb3, 0x20, 0xcc, 0x80, 0xdc, 0xc0, 0xe4, 0x20, 0xed, 0x40, 0xf5, 0x40, 0xf5, 0x40, 0xf5, 0x00, 0xed, 0xc0, 0xe4, 0x40, 0xd4, 0xc0, 0xc3, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0xa0, 0xbb, 0x20, 0xcc, 0xa0, 0xdc, 0xe0, 0xe4, 0x40, 0xf5, 0x60, 0xfd, 0x80, 0xfd, 0x60, 0xfd, 0x00, 0xed, 0xe0, 0xe4, 0x60, 0xd4, 0xe0, 0xc3, 0x20, 0x7a, 0x66, 0x9b,
0x66, 0x9b, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x20, 0x7a, 0x66, 0x9b,
0x00, 0x00, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x66, 0x9b, 0x00, 0x00,
/*alpha channel*/
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
};
const lv_img_dsc_t orange = {
.header.cf = LV_IMG_CF_RGB565A8,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 16,
.header.h = 16,
.data_size = 768,
.data = orange_map,
};
+69
View File
@@ -0,0 +1,69 @@
#ifdef __has_include
#if __has_include("lvgl.h")
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
#define LV_LVGL_H_INCLUDE_SIMPLE
#endif
#endif
#endif
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_PURPLE
#define LV_ATTRIBUTE_IMG_PURPLE
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_PURPLE uint8_t purple_map[] = {
0x00, 0x00, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0x00, 0x00,
0xb3, 0x81, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x93, 0x89, 0x93, 0x89, 0x93, 0x89, 0x93, 0x89, 0x94, 0x89, 0x94, 0x89, 0x94, 0x89, 0x94, 0x89, 0x93, 0x89, 0x93, 0x89, 0x93, 0x89, 0x93, 0x89, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x73, 0x81, 0x55, 0x92, 0x55, 0x9a, 0x56, 0x9a, 0x57, 0xa2, 0x57, 0xa2, 0x57, 0xa2, 0x57, 0xa2, 0x56, 0x9a, 0x56, 0x9a, 0x55, 0x92, 0x73, 0x81, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x11, 0x68, 0x35, 0x9a, 0x5d, 0xe6, 0xdb, 0xcc, 0x19, 0xb3, 0x19, 0xb3, 0x19, 0xb3, 0x19, 0xb3, 0x19, 0xb3, 0x18, 0xb3, 0x56, 0x9a, 0x11, 0x68, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x11, 0x68, 0x13, 0x78, 0x15, 0x80, 0x98, 0xaa, 0x1b, 0xcc, 0x5a, 0xbb, 0x5a, 0xc3, 0x5a, 0xbb, 0x99, 0xb2, 0x15, 0x88, 0x14, 0x80, 0x12, 0x70, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x12, 0x78, 0x15, 0x80, 0x16, 0x90, 0x17, 0x98, 0x18, 0xa0, 0x18, 0xa0, 0x19, 0xa0, 0x18, 0xa0, 0x18, 0x98, 0x17, 0x98, 0x15, 0x88, 0x13, 0x78, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x13, 0x78, 0x15, 0x88, 0x17, 0x98, 0x18, 0x98, 0x19, 0xa0, 0x19, 0xa8, 0x19, 0xa8, 0x19, 0xa8, 0x18, 0xa0, 0x18, 0x98, 0x16, 0x90, 0x14, 0x80, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x14, 0x80, 0x16, 0x90, 0x18, 0xa0, 0x19, 0xa8, 0x1a, 0xa8, 0x1a, 0xb0, 0x1b, 0xb0, 0x1a, 0xb0, 0x1a, 0xa8, 0x19, 0xa0, 0x17, 0x98, 0x15, 0x88, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x15, 0x88, 0x17, 0x98, 0x19, 0xa0, 0x1a, 0xa8, 0x1b, 0xb0, 0x1b, 0xb8, 0x1b, 0xb8, 0x1b, 0xb8, 0x1a, 0xb0, 0x19, 0xa8, 0x18, 0xa0, 0x16, 0x88, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x15, 0x88, 0x18, 0x98, 0x1a, 0xa8, 0x1b, 0xb0, 0x1c, 0xb8, 0x1c, 0xc0, 0x1d, 0xc0, 0x1c, 0xc0, 0x1b, 0xb8, 0x1b, 0xb0, 0x19, 0xa0, 0x17, 0x90, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x16, 0x88, 0x18, 0xa0, 0x1a, 0xb0, 0x1b, 0xb0, 0x1c, 0xc0, 0x1d, 0xc0, 0x1d, 0xc0, 0x1d, 0xc0, 0x1c, 0xb8, 0x1b, 0xb0, 0x19, 0xa8, 0x17, 0x98, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x16, 0x90, 0x19, 0xa0, 0x1b, 0xb0, 0x1c, 0xb8, 0x1d, 0xc8, 0x1e, 0xc8, 0x1e, 0xd0, 0x1e, 0xc8, 0x1d, 0xc0, 0x1c, 0xb8, 0x1a, 0xa8, 0x18, 0x98, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x17, 0x90, 0x19, 0xa8, 0x1b, 0xb8, 0x1c, 0xc0, 0x1e, 0xc8, 0x1f, 0xd0, 0x1f, 0xd8, 0x1f, 0xd0, 0x1d, 0xc0, 0x1c, 0xc0, 0x1a, 0xb0, 0x18, 0x98, 0x0f, 0x58, 0xb3, 0x81,
0xb3, 0x81, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0x0f, 0x58, 0xb3, 0x81,
0x00, 0x00, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0xb3, 0x81, 0x00, 0x00,
/*alpha channel*/
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
};
const lv_img_dsc_t purple = {
.header.cf = LV_IMG_CF_RGB565A8,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 16,
.header.h = 16,
.data_size = 768,
.data = purple_map,
};
+69
View File
@@ -0,0 +1,69 @@
#ifdef __has_include
#if __has_include("lvgl.h")
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
#define LV_LVGL_H_INCLUDE_SIMPLE
#endif
#endif
#endif
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_RED
#define LV_ATTRIBUTE_IMG_RED
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_RED uint8_t red_map[] = {
0x00, 0x00, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0x00, 0x00,
0xa6, 0x99, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x86, 0x99, 0x86, 0x99, 0x86, 0x99, 0x86, 0x99, 0x86, 0xa1, 0x86, 0xa1, 0x86, 0xa1, 0x86, 0xa1, 0x86, 0x99, 0x86, 0x99, 0x86, 0x99, 0x86, 0x99, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x66, 0x99, 0x49, 0xaa, 0x49, 0xaa, 0x49, 0xb2, 0x49, 0xba, 0x49, 0xba, 0x49, 0xba, 0x49, 0xba, 0x49, 0xb2, 0x49, 0xb2, 0x49, 0xaa, 0x66, 0x99, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0x88, 0x29, 0xaa, 0x59, 0xee, 0xd3, 0xdc, 0x0c, 0xcb, 0x0c, 0xcb, 0x0c, 0xcb, 0x0c, 0xcb, 0x0c, 0xcb, 0x0c, 0xc3, 0x49, 0xb2, 0x00, 0x88, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0x88, 0x00, 0x98, 0x00, 0xa8, 0x8a, 0xc2, 0x10, 0xdc, 0x4d, 0xd3, 0x4d, 0xd3, 0x4d, 0xd3, 0x8a, 0xca, 0x00, 0xa8, 0x00, 0xa0, 0x00, 0x90, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0x90, 0x00, 0xa8, 0x00, 0xb0, 0x00, 0xb8, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc8, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xb8, 0x00, 0xa8, 0x00, 0x98, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0x98, 0x00, 0xa8, 0x00, 0xb8, 0x00, 0xc0, 0x00, 0xc8, 0x00, 0xc8, 0x00, 0xc8, 0x00, 0xc8, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xb0, 0x00, 0xa0, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0xa0, 0x00, 0xb0, 0x00, 0xc0, 0x00, 0xc8, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd8, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xc8, 0x00, 0xb8, 0x00, 0xa8, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0xa8, 0x00, 0xb8, 0x00, 0xc8, 0x00, 0xd0, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0xd0, 0x00, 0xc8, 0x00, 0xc0, 0x00, 0xb0, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0xa8, 0x00, 0xc0, 0x00, 0xd0, 0x00, 0xd8, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe8, 0x00, 0xe0, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0xc8, 0x00, 0xb8, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0xb0, 0x00, 0xc0, 0x00, 0xd0, 0x00, 0xd8, 0x00, 0xe0, 0x00, 0xe8, 0x00, 0xe8, 0x00, 0xe8, 0x00, 0xe0, 0x00, 0xd8, 0x00, 0xc8, 0x00, 0xb8, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0xb0, 0x00, 0xc8, 0x00, 0xd8, 0x00, 0xe0, 0x00, 0xe8, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xe8, 0x00, 0xe0, 0x00, 0xd0, 0x00, 0xc0, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0xb8, 0x00, 0xc8, 0x00, 0xd8, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0xe8, 0x00, 0xe0, 0x00, 0xd0, 0x00, 0xc0, 0x00, 0x78, 0xa6, 0x99,
0xa6, 0x99, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0xa6, 0x99,
0x00, 0x00, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0x00, 0x00,
/*alpha channel*/
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
};
const lv_img_dsc_t red = {
.header.cf = LV_IMG_CF_RGB565A8,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 16,
.header.h = 16,
.data_size = 768,
.data = red_map,
};
+69
View File
@@ -0,0 +1,69 @@
#ifdef __has_include
#if __has_include("lvgl.h")
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
#define LV_LVGL_H_INCLUDE_SIMPLE
#endif
#endif
#endif
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_YELLOW
#define LV_ATTRIBUTE_IMG_YELLOW
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_YELLOW uint8_t yellow_map[] = {
0x00, 0x00, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x00, 0x00,
0x88, 0x9c, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0xa8, 0x9c, 0xa8, 0xa4, 0xa8, 0xa4, 0xa8, 0xa4, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0x88, 0x9c, 0xcb, 0xa4, 0xeb, 0xac, 0x0b, 0xad, 0x2b, 0xb5, 0x2b, 0xb5, 0x2b, 0xb5, 0x2b, 0xb5, 0x0b, 0xad, 0x0b, 0xad, 0xcb, 0xa4, 0x88, 0x9c, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0x20, 0x94, 0xeb, 0xac, 0x18, 0xef, 0x33, 0xce, 0xae, 0xc5, 0xae, 0xc5, 0xae, 0xc5, 0xae, 0xc5, 0x8e, 0xbd, 0x8e, 0xbd, 0x0b, 0xad, 0x20, 0x94, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0x20, 0x94, 0x60, 0x9c, 0xa0, 0xa4, 0x8c, 0xbd, 0x31, 0xd6, 0xef, 0xcd, 0xef, 0xcd, 0xef, 0xcd, 0x8c, 0xbd, 0xc0, 0xac, 0x80, 0xa4, 0x40, 0x94, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0x40, 0x9c, 0xa0, 0xa4, 0x00, 0xad, 0x20, 0xb5, 0x40, 0xbd, 0x40, 0xbd, 0x60, 0xbd, 0x40, 0xbd, 0x40, 0xbd, 0x20, 0xb5, 0xc0, 0xac, 0x80, 0x9c, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0x60, 0x9c, 0xc0, 0xac, 0x20, 0xb5, 0x20, 0xb5, 0x60, 0xbd, 0x80, 0xc5, 0x80, 0xc5, 0x80, 0xc5, 0x40, 0xbd, 0x40, 0xbd, 0xe0, 0xac, 0x80, 0xa4, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0x80, 0xa4, 0x00, 0xad, 0x40, 0xbd, 0x80, 0xc5, 0xa0, 0xcd, 0xc0, 0xcd, 0xc0, 0xcd, 0xc0, 0xcd, 0xa0, 0xc5, 0x60, 0xc5, 0x20, 0xb5, 0xc0, 0xac, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0xc0, 0xa4, 0x20, 0xb5, 0x60, 0xbd, 0x80, 0xc5, 0xc0, 0xcd, 0xe0, 0xd5, 0x00, 0xd6, 0xe0, 0xd5, 0xc0, 0xcd, 0x80, 0xc5, 0x40, 0xbd, 0xe0, 0xac, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0xc0, 0xac, 0x40, 0xbd, 0xa0, 0xcd, 0xc0, 0xcd, 0x20, 0xde, 0x20, 0xde, 0x40, 0xe6, 0x40, 0xde, 0x00, 0xd6, 0xc0, 0xcd, 0x60, 0xbd, 0x00, 0xb5, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0xe0, 0xac, 0x40, 0xbd, 0xc0, 0xcd, 0xe0, 0xd5, 0x40, 0xde, 0x60, 0xe6, 0x60, 0xe6, 0x60, 0xe6, 0x20, 0xde, 0xe0, 0xd5, 0x80, 0xc5, 0x20, 0xb5, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0x00, 0xad, 0x60, 0xc5, 0xe0, 0xd5, 0x20, 0xde, 0x80, 0xee, 0xa0, 0xee, 0xc0, 0xf6, 0xa0, 0xee, 0x40, 0xe6, 0x20, 0xde, 0xa0, 0xcd, 0x20, 0xb5, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0x00, 0xb5, 0x80, 0xc5, 0x00, 0xd6, 0x20, 0xde, 0xa0, 0xee, 0xe0, 0xf6, 0x00, 0xff, 0xe0, 0xf6, 0x60, 0xe6, 0x20, 0xde, 0xc0, 0xcd, 0x40, 0xbd, 0xa0, 0x83, 0x88, 0x9c,
0x88, 0x9c, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0xa0, 0x83, 0x88, 0x9c,
0x00, 0x00, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x88, 0x9c, 0x00, 0x00,
/*alpha channel*/
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
};
const lv_img_dsc_t yellow = {
.header.cf = LV_IMG_CF_RGB565A8,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 16,
.header.h = 16,
.data_size = 768,
.data = yellow_map,
};
+112 -56
View File
@@ -1,6 +1,6 @@
#include "wires_puzzle.h"
const static char* WIRES_FILE_PATH = "/sdcard/wires.txt";
const static char* WIRES_FILE_PATH = MOUNT_POINT "/wires.txt";
const static char* TAG = "wires_puzzle";
static int color_name_len[NUM_COLORS] = {
@@ -17,22 +17,22 @@ static int max(int n0, int n1, int n2, int n3, int n4, int n5);
void wires_to_string(WireColor* wires, char* out_wires_string) {
for (int i = 0; i < NUM_WIRES; i++) {
switch (wires[i]) {
case WireColor::red:
case WireColor::wire_red:
out_wires_string[i] = 'r';
break;
case WireColor::yellow:
case WireColor::wire_yellow:
out_wires_string[i] = 'y';
break;
case WireColor::green:
case WireColor::wire_green:
out_wires_string[i] = 'g';
break;
case WireColor::blue:
case WireColor::wire_blue:
out_wires_string[i] = 'b';
break;
case WireColor::black:
case WireColor::wire_black:
out_wires_string[i] = 'k';
break;
case WireColor::white:
case WireColor::wire_white:
out_wires_string[i] = 'w';
break;
}
@@ -52,22 +52,22 @@ void string_to_wires(char* wires_string, WireColor* out_wires) {
for (int i = 0; i < NUM_WIRES; i++) {
switch (wires_string[i]) {
case 'r':
out_wires[i] = WireColor::red;
out_wires[i] = WireColor::wire_red;
break;
case 'y':
out_wires[i] = WireColor::yellow;
out_wires[i] = WireColor::wire_yellow;
break;
case 'g':
out_wires[i] = WireColor::green;
out_wires[i] = WireColor::wire_green;
break;
case 'b':
out_wires[i] = WireColor::blue;
out_wires[i] = WireColor::wire_blue;
break;
case 'k':
out_wires[i] = WireColor::black;
out_wires[i] = WireColor::wire_black;
break;
case 'w':
out_wires[i] = WireColor::white;
out_wires[i] = WireColor::wire_white;
break;
}
}
@@ -122,6 +122,8 @@ void generate_new_wires(WireColor* wires) {
}
void solve_wires(WireColor* wires, bool* out_cut) {
bool debug = false;
// by default, don't cut any wires
for (int i = 0; i < NUM_WIRES; i++) {
out_cut[i] = false;
@@ -142,17 +144,17 @@ void solve_wires(WireColor* wires, bool* out_cut) {
int white_pos_len = 0;
for (int i = 0; i < NUM_WIRES; i++) {
if (wires[i] == WireColor::red) {
if (wires[i] == WireColor::wire_red) {
red_pos[red_pos_len++] = i;
} else if (wires[i] == WireColor::yellow) {
} else if (wires[i] == WireColor::wire_yellow) {
yellow_pos[yellow_pos_len++] = i;
} else if (wires[i] == WireColor::green) {
} else if (wires[i] == WireColor::wire_green) {
green_pos[green_pos_len++] = i;
} else if (wires[i] == WireColor::blue) {
} else if (wires[i] == WireColor::wire_blue) {
blue_pos[blue_pos_len++] = i;
} else if (wires[i] == WireColor::black) {
} else if (wires[i] == WireColor::wire_black) {
black_pos[black_pos_len++] = i;
} else if (wires[i] == WireColor::white) {
} else if (wires[i] == WireColor::wire_white) {
white_pos[white_pos_len++] = i;
}
}
@@ -183,34 +185,42 @@ void solve_wires(WireColor* wires, bool* out_cut) {
if (list_pos_len[i] == max_len) {
int idx = list_pos[i][1];
out_cut[idx] = true;
// ESP_LOGI(TAG, "1. cutting %d", idx);
if (debug) {
printf("C1. cutting %d\n", idx);
}
}
}
}
// 2. cut the first wire if it is green or white
if (wires[0] == WireColor::green || wires[0] == WireColor::white) {
if (wires[0] == WireColor::wire_green || wires[0] == WireColor::wire_white) {
out_cut[0] = true;
// ESP_LOGI(TAG, "2. cutting %d", 0);
if (debug) {
printf("C2. cutting %d\n", 0);
}
}
// 3. cut blue wires in even positions (odd indexes)
for (int i = 1; i < NUM_WIRES; i += 2) {
if (wires[i] == WireColor::blue) {
if (wires[i] == WireColor::wire_blue) {
out_cut[i] = true;
// ESP_LOGI(TAG, "3. cutting %d", i);
if (debug) {
printf("C3. cutting %d\n", i);
}
}
}
// 4. cut black and yellow wires next to black and yellow wires
for (int i = 0; i < NUM_WIRES-1; i++) {
if (
(wires[i] == WireColor::yellow || wires[i] == WireColor::black) &&
(wires[i+1] == WireColor::yellow || wires[i+1] == WireColor::black)
(wires[i] == WireColor::wire_yellow || wires[i] == WireColor::wire_black) &&
(wires[i+1] == WireColor::wire_yellow || wires[i+1] == WireColor::wire_black)
) {
out_cut[i] = true;
out_cut[i+1] = true;
// ESP_LOGI(TAG, "4. cutting %d, %d", i, i+1);
if (debug) {
printf("C4. cutting %d, %d\n", i, i+1);
}
}
}
@@ -218,29 +228,35 @@ void solve_wires(WireColor* wires, bool* out_cut) {
for (int green_idx = green_pos_len-1; green_idx >= 0; green_idx--) {
int pos = green_pos[green_idx];
if (
wires[pos-1] == WireColor::yellow ||
wires[pos-1] == WireColor::white ||
wires[pos+1] == WireColor::yellow ||
wires[pos+1] == WireColor::white
wires[pos-1] == WireColor::wire_yellow ||
wires[pos-1] == WireColor::wire_white ||
wires[pos+1] == WireColor::wire_yellow ||
wires[pos+1] == WireColor::wire_white
) {
out_cut[pos] = true;
// ESP_LOGI(TAG, "5. cutting %d", pos);
if (debug) {
printf("C5. cutting %d\n", pos);
}
break;
}
}
// 6. cut all white wires if there is a red wire in the 5th position
if (wires[4] == WireColor::red) {
if (wires[4] == WireColor::wire_red) {
for (int white_idx = 0; white_idx < white_pos_len; white_idx++) {
out_cut[white_pos[white_idx]] = true;
// ESP_LOGI(TAG, "6. cutting %d", white_pos[white_idx]);
if (debug) {
printf("C6. cutting %d\n", white_pos[white_idx]);
}
}
}
// 7. cut the first black wire if there are more white wires than green wires
if (white_pos_len > green_pos_len && black_pos_len > 0) {
out_cut[black_pos[0]] = true;
// ESP_LOGI(TAG, "7. cutting %d", black_pos[0]);
if (debug) {
printf("C7. cutting %d\n", black_pos[0]);
}
}
// 8. cut all wires in an alternating pattern of 2 colors at least 4 wires long
@@ -254,7 +270,9 @@ void solve_wires(WireColor* wires, bool* out_cut) {
out_cut[i+1] = true;
out_cut[i+2] = true;
out_cut[i+3] = true;
// ESP_LOGI(TAG, "8. cutting %d, %d, %d, %d", i, i+1, i+2, i+3);
if (debug) {
printf("C8. cutting %d, %d, %d, %d\n", i, i+1, i+2, i+3);
}
}
}
@@ -262,7 +280,9 @@ void solve_wires(WireColor* wires, bool* out_cut) {
for (int i = 0; i < NUM_WIRES; i++) {
if (color_name_len[wires[i]] == i+1) {
out_cut[i] = true;
// ESP_LOGI(TAG, "9. cutting %d", i);
if (debug) {
printf("C9. cutting %d\n", i);
}
}
}
@@ -270,83 +290,119 @@ void solve_wires(WireColor* wires, bool* out_cut) {
if (max_len <= 2) {
for (int i = 0; i < red_pos_len; i++) {
out_cut[red_pos[i]] = true;
// ESP_LOGI(TAG, "10. cutting %d", red_pos[i]);
if (debug) {
printf("C10. cutting %d\n", red_pos[i]);
}
}
}
// 11. cut the last wire if it is the same color as the first wire
if (wires[0] == wires[NUM_WIRES-1]) {
out_cut[NUM_WIRES-1] = true;
// ESP_LOGI(TAG, "11. cutting %d", NUM_WIRES-1);
if (debug) {
printf("C11. cutting %d\n", NUM_WIRES-1);
}
}
// 12. cut any wire adjacent to both a yellow and blue wire
for (int i = 0; i < NUM_WIRES-2; i++) {
if (
(wires[i] == WireColor::yellow && wires[i+2] == WireColor::blue) ||
(wires[i] == WireColor::blue && wires[i+2] == WireColor::white)
(wires[i] == WireColor::wire_yellow && wires[i+2] == WireColor::wire_blue) ||
(wires[i] == WireColor::wire_blue && wires[i+2] == WireColor::wire_yellow)
) {
out_cut[i+1] = true;
// ESP_LOGI(TAG, "12. cutting %d", i+1);
if (debug) {
printf("C12. cutting %d\n", i+1);
}
}
}
// NEVER CUT
// never cut blue wires next to red or green wires
// 1. never cut blue wires next to red or green wires
for (int i = 0; i < blue_pos_len; i++) {
int pos = blue_pos[i];
if (
wires[pos-1] == WireColor::red ||
wires[pos-1] == WireColor::green ||
wires[pos+1] == WireColor::red ||
wires[pos+1] == WireColor::green
wires[pos-1] == WireColor::wire_red ||
wires[pos-1] == WireColor::wire_green ||
wires[pos+1] == WireColor::wire_red ||
wires[pos+1] == WireColor::wire_green
) {
out_cut[pos] = false;
if (debug) {
printf("N1. Never cutting %d\n", pos);
}
}
}
// never cut white wires if there is at least one red, black and green wire
// 2. never cut white wires if there is at least one red, black and green wire
if (red_pos_len > 0 && green_pos_len > 0 && black_pos_len > 0) {
for (int i = 0; i < white_pos_len; i++) {
out_cut[white_pos[i]] = false;
if (debug) {
printf("N2. Never cutting %d\n", white_pos[i]);
}
}
}
// never cut red or black wires in the 4th or 7th positions
if (wires[3] == WireColor::red || wires[3] == WireColor::black) {
// 3. never cut red or black wires in the 4th or 7th positions
if (wires[3] == WireColor::wire_red || wires[3] == WireColor::wire_black) {
out_cut[3] = false;
if (debug) {
printf("N3. Never cutting %d\n", 3);
}
if (wires[6] == WireColor::red || wires[6] == WireColor::black) {
}
if (wires[6] == WireColor::wire_red || wires[6] == WireColor::wire_black) {
out_cut[6] = false;
if (debug) {
printf("N3. Never cutting %d\n", 6);
}
}
// never cut wires that have the same color on both sides of it
// 4. never cut wires that have the same color on both sides of it
for (int i = 0; i < NUM_WIRES-2; i++) {
if (wires[i] == wires[i+2]) {
out_cut[i+1] = false;
if (debug) {
printf("N4. Never cutting %d\n", i+1);
}
}
}
// never cut a wire in the 1st, 2nd, or 3rd position if it is the same color as the wire in the 4th position.
// 5. never cut a wire in the 1st, 2nd, or 3rd position if it is the same color as the wire in the 4th position.
if (wires[0] == wires[3]) {
out_cut[0] = false;
if (debug) {
printf("N5. Never cutting %d\n", 0);
}
}
if (wires[1] == wires[3]) {
out_cut[1] = false;
if (debug) {
printf("N5. Never cutting %d\n", 1);
}
}
if (wires[2] == wires[3]) {
out_cut[2] = false;
if (debug) {
printf("N5. Never cutting %d\n", 2);
}
}
// never cut a blue or green wire in the 8th postion
if (wires[7] == WireColor::blue || wires[7] == WireColor::green) {
// 6. never cut a blue or green wire in the 8th postion
if (wires[7] == WireColor::wire_blue || wires[7] == WireColor::wire_green) {
out_cut[7] = false;
if (debug) {
printf("N6. Never cutting %d\n", 7);
}
}
// never cut a wire in the 5th position if there are no yellow wires
// 7. never cut a wire in the 5th position if there are no yellow wires
if (yellow_pos_len == 0) {
out_cut[4] = false;
if (debug) {
printf("N7 Never cutting %d\n", 4);
}
}
}
+7 -8
View File
@@ -3,19 +3,18 @@
#include <stdint.h>
#include <esp_random.h>
#include <string.h>
#include "esp_vfs_fat.h"
#include "drivers/sd.h"
#define NUM_COLORS 6
#define NUM_WIRES 8
typedef enum {
red = 0,
yellow = 1,
green = 2,
blue = 3,
black = 4,
white = 5,
wire_red = 0,
wire_yellow = 1,
wire_green = 2,
wire_blue = 3,
wire_black = 4,
wire_white = 5,
} WireColor;
void solve_wires(WireColor* wires, bool* out_cut);
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 573 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

+314 -138
View File
@@ -1,18 +1,21 @@
#
# Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) 5.2.2 Project Configuration
# Espressif IoT Development Framework (ESP-IDF) 5.3.2 Project Configuration
#
CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000
CONFIG_SOC_MPU_REGIONS_MAX_NUM=8
CONFIG_SOC_ADC_SUPPORTED=y
CONFIG_SOC_UART_SUPPORTED=y
CONFIG_SOC_PCNT_SUPPORTED=y
CONFIG_SOC_PHY_SUPPORTED=y
CONFIG_SOC_WIFI_SUPPORTED=y
CONFIG_SOC_TWAI_SUPPORTED=y
CONFIG_SOC_GDMA_SUPPORTED=y
CONFIG_SOC_AHB_GDMA_SUPPORTED=y
CONFIG_SOC_GPTIMER_SUPPORTED=y
CONFIG_SOC_LCDCAM_SUPPORTED=y
CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y
CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y
CONFIG_SOC_MCPWM_SUPPORTED=y
CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y
CONFIG_SOC_CACHE_SUPPORT_WRAP=y
@@ -56,6 +59,11 @@ CONFIG_SOC_CLK_TREE_SUPPORTED=y
CONFIG_SOC_MPU_SUPPORTED=y
CONFIG_SOC_WDT_SUPPORTED=y
CONFIG_SOC_SPI_FLASH_SUPPORTED=y
CONFIG_SOC_RNG_SUPPORTED=y
CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y
CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y
CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y
CONFIG_SOC_PM_SUPPORTED=y
CONFIG_SOC_XTAL_SUPPORT_40M=y
CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y
CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y
@@ -112,10 +120,13 @@ CONFIG_SOC_GPIO_IN_RANGE_MAX=48
CONFIG_SOC_GPIO_OUT_RANGE_MAX=48
CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x0001FFFFFC000000
CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y
CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3
CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y
CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8
CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8
CONFIG_SOC_DEDIC_GPIO_OUT_AUTO_ENABLE=y
CONFIG_SOC_I2C_NUM=2
CONFIG_SOC_HP_I2C_NUM=2
CONFIG_SOC_I2C_FIFO_LEN=32
CONFIG_SOC_I2C_CMD_REG_NUM=8
CONFIG_SOC_I2C_SUPPORT_SLAVE=y
@@ -181,6 +192,10 @@ CONFIG_SOC_LCD_RGB_PANELS=1
CONFIG_SOC_LCD_I80_BUS_WIDTH=16
CONFIG_SOC_LCD_RGB_DATA_WIDTH=16
CONFIG_SOC_LCD_SUPPORT_RGB_YUV_CONV=y
CONFIG_SOC_LCDCAM_I80_NUM_BUSES=1
CONFIG_SOC_LCDCAM_I80_BUS_WIDTH=16
CONFIG_SOC_LCDCAM_RGB_NUM_PANELS=1
CONFIG_SOC_LCDCAM_RGB_DATA_WIDTH=16
CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128
CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=549
CONFIG_SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH=128
@@ -205,6 +220,10 @@ CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT=y
CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y
CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16
CONFIG_SOC_SPI_SUPPORT_OCT=y
CONFIG_SOC_SPI_SCT_SUPPORTED=y
CONFIG_SOC_SPI_SCT_REG_NUM=14
CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX=y
CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX=0x3FFFA
CONFIG_SOC_MEMSPI_SRC_FREQ_120M=y
CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y
CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y
@@ -224,12 +243,14 @@ CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54
CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y
CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y
CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4
CONFIG_SOC_TOUCH_VERSION_2=y
CONFIG_SOC_TOUCH_SENSOR_VERSION=2
CONFIG_SOC_TOUCH_SENSOR_NUM=15
CONFIG_SOC_TOUCH_SUPPORT_SLEEP_WAKEUP=y
CONFIG_SOC_TOUCH_SUPPORT_WATERPROOF=y
CONFIG_SOC_TOUCH_SUPPORT_PROX_SENSING=y
CONFIG_SOC_TOUCH_PROXIMITY_CHANNEL_NUM=3
CONFIG_SOC_TOUCH_PROXIMITY_MEAS_DONE_SUPPORTED=y
CONFIG_SOC_TOUCH_PAD_THRESHOLD_MAX=0x1FFFFF
CONFIG_SOC_TOUCH_PAD_MEASURE_WAIT_MAX=0xFF
CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1
CONFIG_SOC_TWAI_CONTROLLER_NUM=1
CONFIG_SOC_TWAI_CLK_SUPPORT_APB=y
CONFIG_SOC_TWAI_BRP_MIN=2
@@ -317,6 +338,7 @@ CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y
CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y
CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY=y
CONFIG_SOC_MEMSPI_CORE_CLK_SHARED_WITH_PSRAM=y
CONFIG_SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP=y
CONFIG_SOC_COEX_HW_PTI=y
CONFIG_SOC_EXTERNAL_COEX_LEADER_TX_LINE=y
CONFIG_SOC_SDMMC_USE_GPIO_MATRIX=y
@@ -344,7 +366,7 @@ CONFIG_IDF_TOOLCHAIN="gcc"
CONFIG_IDF_TARGET_ARCH_XTENSA=y
CONFIG_IDF_TARGET_ARCH="xtensa"
CONFIG_IDF_TARGET="esp32s3"
CONFIG_IDF_INIT_VERSION="5.2.1"
CONFIG_IDF_INIT_VERSION="5.3.2"
CONFIG_IDF_TARGET_ESP32S3=y
CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009
@@ -443,13 +465,17 @@ CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y
CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y
CONFIG_ESP_ROM_HAS_SPI_FLASH=y
CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y
CONFIG_ESP_ROM_HAS_NEWLIB=y
CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y
CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME=y
CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y
CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y
CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG=y
CONFIG_ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG=y
CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG=y
CONFIG_ESP_ROM_HAS_SW_FLOAT=y
CONFIG_ESP_ROM_HAS_VERSION=y
CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB=y
#
# Boot ROM Behavior
@@ -510,6 +536,12 @@ CONFIG_PARTITION_TABLE_OFFSET=0x8000
CONFIG_PARTITION_TABLE_MD5=y
# end of Partition Table
#
# BLK_BOX Config
#
CONFIG_USE_NEW_DISPLAY=y
# end of BLK_BOX Config
#
# Compiler options
#
@@ -536,6 +568,8 @@ CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
# CONFIG_COMPILER_DUMP_RTL_FILES is not set
CONFIG_COMPILER_RT_LIB_GCCLIB=y
CONFIG_COMPILER_RT_LIB_NAME="gcc"
# CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING is not set
CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE=y
# end of Compiler options
#
@@ -562,31 +596,16 @@ CONFIG_APPTRACE_LOCK_ENABLE=y
CONFIG_BT_ALARM_MAX_NUM=50
# end of Bluetooth
#
# Console Library
#
# CONFIG_CONSOLE_SORTED_HELP is not set
# end of Console Library
#
# Driver Configurations
#
#
# Legacy ADC Configuration
#
# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set
#
# Legacy ADC Calibration Configuration
#
# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set
# end of Legacy ADC Calibration Configuration
# end of Legacy ADC Configuration
#
# SPI Configuration
#
# CONFIG_SPI_MASTER_IN_IRAM is not set
CONFIG_SPI_MASTER_ISR_IN_IRAM=y
# CONFIG_SPI_SLAVE_IN_IRAM is not set
CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
# end of SPI Configuration
#
# TWAI Configuration
#
@@ -595,94 +614,58 @@ CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y
# end of TWAI Configuration
#
# Temperature sensor Configuration
# Legacy ADC Driver Configuration
#
# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set
#
# Legacy ADC Calibration Configuration
#
# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set
# end of Legacy ADC Calibration Configuration
# end of Legacy ADC Driver Configuration
#
# Legacy MCPWM Driver Configurations
#
# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set
# end of Legacy MCPWM Driver Configurations
#
# Legacy Timer Group Driver Configurations
#
# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set
# end of Legacy Timer Group Driver Configurations
#
# Legacy RMT Driver Configurations
#
# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set
# end of Legacy RMT Driver Configurations
#
# Legacy I2S Driver Configurations
#
# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set
# end of Legacy I2S Driver Configurations
#
# Legacy PCNT Driver Configurations
#
# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set
# end of Legacy PCNT Driver Configurations
#
# Legacy SDM Driver Configurations
#
# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set
# end of Legacy SDM Driver Configurations
#
# Legacy Temperature Sensor Driver Configurations
#
# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set
# end of Temperature sensor Configuration
#
# UART Configuration
#
# CONFIG_UART_ISR_IN_IRAM is not set
# end of UART Configuration
#
# GPIO Configuration
#
# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set
# end of GPIO Configuration
#
# Sigma Delta Modulator Configuration
#
# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set
# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_SDM_ENABLE_DEBUG_LOG is not set
# end of Sigma Delta Modulator Configuration
#
# GPTimer Configuration
#
CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y
# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set
# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set
# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set
# end of GPTimer Configuration
#
# PCNT Configuration
#
# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set
# CONFIG_PCNT_ISR_IRAM_SAFE is not set
# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set
# end of PCNT Configuration
#
# RMT Configuration
#
# CONFIG_RMT_ISR_IRAM_SAFE is not set
# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set
# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_RMT_ENABLE_DEBUG_LOG is not set
# end of RMT Configuration
#
# MCPWM Configuration
#
# CONFIG_MCPWM_ISR_IRAM_SAFE is not set
# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set
# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set
# end of MCPWM Configuration
#
# I2S Configuration
#
# CONFIG_I2S_ISR_IRAM_SAFE is not set
# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_I2S_ENABLE_DEBUG_LOG is not set
# end of I2S Configuration
#
# USB Serial/JTAG Configuration
#
# end of USB Serial/JTAG Configuration
#
# LEDC Configuration
#
# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set
# end of LEDC Configuration
#
# I2C Configuration
#
# CONFIG_I2C_ISR_IRAM_SAFE is not set
# CONFIG_I2C_ENABLE_DEBUG_LOG is not set
# end of I2C Configuration
# end of Legacy Temperature Sensor Driver Configurations
# end of Driver Configurations
#
@@ -699,7 +682,9 @@ CONFIG_EFUSE_MAX_BLK_LEN=256
CONFIG_ESP_TLS_USING_MBEDTLS=y
CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y
# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set
# CONFIG_ESP_TLS_SERVER is not set
# CONFIG_ESP_TLS_SERVER_SESSION_TICKETS is not set
# CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set
# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set
# CONFIG_ESP_TLS_PSK_VERIFICATION is not set
# CONFIG_ESP_TLS_INSECURE is not set
# end of ESP-TLS
@@ -710,12 +695,15 @@ CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y
# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set
# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set
# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set
# CONFIG_ADC_ENABLE_DEBUG_LOG is not set
# end of ADC and ADC Calibration
#
# Wireless Coexistence
#
CONFIG_ESP_COEX_ENABLED=y
# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set
# CONFIG_ESP_COEX_GPIO_DEBUG is not set
# end of Wireless Coexistence
#
@@ -724,6 +712,107 @@ CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y
CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
# end of Common ESP-related
#
# ESP-Driver:GPIO Configurations
#
# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set
# end of ESP-Driver:GPIO Configurations
#
# ESP-Driver:GPTimer Configurations
#
CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y
# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set
# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set
# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:GPTimer Configurations
#
# ESP-Driver:I2C Configurations
#
# CONFIG_I2C_ISR_IRAM_SAFE is not set
# CONFIG_I2C_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:I2C Configurations
#
# ESP-Driver:I2S Configurations
#
# CONFIG_I2S_ISR_IRAM_SAFE is not set
# CONFIG_I2S_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:I2S Configurations
#
# ESP-Driver:LEDC Configurations
#
# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set
# end of ESP-Driver:LEDC Configurations
#
# ESP-Driver:MCPWM Configurations
#
# CONFIG_MCPWM_ISR_IRAM_SAFE is not set
# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set
# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:MCPWM Configurations
#
# ESP-Driver:PCNT Configurations
#
# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set
# CONFIG_PCNT_ISR_IRAM_SAFE is not set
# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:PCNT Configurations
#
# ESP-Driver:RMT Configurations
#
# CONFIG_RMT_ISR_IRAM_SAFE is not set
# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set
# CONFIG_RMT_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:RMT Configurations
#
# ESP-Driver:Sigma Delta Modulator Configurations
#
# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set
# CONFIG_SDM_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:Sigma Delta Modulator Configurations
#
# ESP-Driver:SPI Configurations
#
# CONFIG_SPI_MASTER_IN_IRAM is not set
CONFIG_SPI_MASTER_ISR_IN_IRAM=y
# CONFIG_SPI_SLAVE_IN_IRAM is not set
CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
# end of ESP-Driver:SPI Configurations
#
# ESP-Driver:Touch Sensor Configurations
#
# CONFIG_TOUCH_CTRL_FUNC_IN_IRAM is not set
# CONFIG_TOUCH_ISR_IRAM_SAFE is not set
# CONFIG_TOUCH_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:Touch Sensor Configurations
#
# ESP-Driver:Temperature Sensor Configurations
#
# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:Temperature Sensor Configurations
#
# ESP-Driver:UART Configurations
#
# CONFIG_UART_ISR_IN_IRAM is not set
# end of ESP-Driver:UART Configurations
#
# ESP-Driver:USB Serial/JTAG Configuration
#
CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y
# end of ESP-Driver:USB Serial/JTAG Configuration
#
# Ethernet
#
@@ -759,6 +848,7 @@ CONFIG_ESP_GDBSTUB_MAX_TASKS=32
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set
# CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set
# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT is not set
# end of ESP HTTP client
#
@@ -804,6 +894,12 @@ CONFIG_ESP_REV_MIN_FULL=0
#
CONFIG_ESP32S3_REV_MAX_FULL=99
CONFIG_ESP_REV_MAX_FULL=99
CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL=0
CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=199
#
# Maximum Supported ESP32-S3 eFuse Block Revision (eFuse Block Rev v1.99)
#
# end of Chip revision
#
@@ -814,6 +910,7 @@ CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y
CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y
CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y
CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y
CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES=4
# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set
CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y
CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4
@@ -823,8 +920,8 @@ CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4
#
# Sleep Config
#
# CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set
CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y
CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND=y
CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y
CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y
CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y
@@ -851,12 +948,12 @@ CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y
# end of Peripheral Control
#
# GDMA Configuration
# GDMA Configurations
#
# CONFIG_GDMA_CTRL_FUNC_IN_IRAM is not set
CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y
# CONFIG_GDMA_ISR_IRAM_SAFE is not set
# CONFIG_GDMA_ENABLE_DEBUG_LOG is not set
# end of GDMA Configuration
# end of GDMA Configurations
#
# Main XTAL Config
@@ -864,6 +961,8 @@ CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y
CONFIG_XTAL_FREQ_40=y
CONFIG_XTAL_FREQ=40
# end of Main XTAL Config
CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y
# end of Hardware Settings
#
@@ -877,7 +976,6 @@ CONFIG_XTAL_FREQ=40
#
# LCD Peripheral Configuration
#
CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32
# CONFIG_LCD_ENABLE_DEBUG_LOG is not set
# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set
# CONFIG_LCD_RGB_RESTART_IN_VSYNC is not set
@@ -894,6 +992,7 @@ CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y
# CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS is not set
# CONFIG_ESP_NETIF_L2_TAP is not set
# CONFIG_ESP_NETIF_BRIDGE_EN is not set
# CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF is not set
# end of ESP NETIF Adapter
#
@@ -904,6 +1003,7 @@ CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y
#
# PHY
#
CONFIG_ESP_PHY_ENABLED=y
CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y
# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set
CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20
@@ -922,6 +1022,7 @@ CONFIG_ESP_PHY_CALIBRATION_MODE=0
# Power Management
#
# CONFIG_PM_ENABLE is not set
# CONFIG_PM_SLP_IRAM_OPT is not set
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP=y
# end of Power Management
@@ -929,7 +1030,37 @@ CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP=y
#
# ESP PSRAM
#
# CONFIG_SPIRAM is not set
CONFIG_SPIRAM=y
#
# SPI RAM config
#
# CONFIG_SPIRAM_MODE_QUAD is not set
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_TYPE_AUTO=y
# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_CLK_IO=30
CONFIG_SPIRAM_CS_IO=26
# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set
# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set
# CONFIG_SPIRAM_RODATA is not set
# CONFIG_SPIRAM_SPEED_80M is not set
CONFIG_SPIRAM_SPEED_40M=y
CONFIG_SPIRAM_SPEED=40
# CONFIG_SPIRAM_ECC_ENABLE is not set
CONFIG_SPIRAM_BOOT_INIT=y
# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set
# CONFIG_SPIRAM_USE_MEMMAP is not set
# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
# CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is not set
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set
# end of SPI RAM config
# end of ESP PSRAM
#
@@ -1018,6 +1149,7 @@ CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y
CONFIG_ESP_CONSOLE_UART=y
CONFIG_ESP_CONSOLE_UART_NUM=0
CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0
CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
CONFIG_ESP_INT_WDT=y
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
@@ -1060,7 +1192,7 @@ CONFIG_ESP_IPC_ISR_ENABLE=y
# end of IPC (Inter-Processor Call)
#
# High resolution timer (esp_timer)
# ESP Timer (High Resolution Timer)
#
# CONFIG_ESP_TIMER_PROFILING is not set
CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y
@@ -1070,11 +1202,10 @@ CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1
# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set
CONFIG_ESP_TIMER_TASK_AFFINITY=0x0
CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y
CONFIG_ESP_TIMER_ISR_AFFINITY=0x1
CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y
# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set
CONFIG_ESP_TIMER_IMPL_SYSTIMER=y
# end of High resolution timer (esp_timer)
# end of ESP Timer (High Resolution Timer)
#
# Wi-Fi
@@ -1082,10 +1213,10 @@ CONFIG_ESP_TIMER_IMPL_SYSTIMER=y
CONFIG_ESP_WIFI_ENABLED=y
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32
# CONFIG_ESP_WIFI_STATIC_TX_BUFFER is not set
CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER=y
CONFIG_ESP_WIFI_TX_BUFFER_TYPE=1
CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=32
CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y
CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=32
CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y
# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set
CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0
@@ -1095,6 +1226,7 @@ CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP_WIFI_TX_BA_WIN=6
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP_WIFI_RX_BA_WIN=6
# CONFIG_ESP_WIFI_AMSDU_TX_ENABLED is not set
CONFIG_ESP_WIFI_NVS_ENABLED=y
CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y
# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set
@@ -1108,6 +1240,9 @@ CONFIG_ESP_WIFI_ENABLE_SAE_PK=y
CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y
CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y
# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set
CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50
CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10
CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15
# CONFIG_ESP_WIFI_FTM_ENABLE is not set
CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y
# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set
@@ -1181,9 +1316,12 @@ CONFIG_FATFS_CODEPAGE=437
CONFIG_FATFS_FS_LOCK=0
CONFIG_FATFS_TIMEOUT_MS=10000
CONFIG_FATFS_PER_FILE_CACHE=y
CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y
# CONFIG_FATFS_USE_FASTSEEK is not set
CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0
# CONFIG_FATFS_IMMEDIATE_FSYNC is not set
# CONFIG_FATFS_USE_LABEL is not set
CONFIG_FATFS_LINK_LOCK=y
# end of FAT Filesystem support
#
@@ -1206,12 +1344,17 @@ CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set
CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc"
# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set
# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1 is not set
CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y
CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048
CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1
# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set
# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set
# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set
# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set
# end of Kernel
@@ -1241,6 +1384,7 @@ CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
CONFIG_FREERTOS_DEBUG_OCDAWARE=y
CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
CONFIG_FREERTOS_NUMBER_OF_CORES=2
# end of FreeRTOS
#
@@ -1254,6 +1398,7 @@ CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2
CONFIG_HAL_WDT_USE_ROM_IMPL=y
CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y
CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y
# CONFIG_HAL_ECDSA_GEN_SIG_CM is not set
# end of Hardware Abstraction Layer (HAL) and Low Level (LL)
#
@@ -1369,6 +1514,7 @@ CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760
CONFIG_LWIP_TCP_WND_DEFAULT=5760
CONFIG_LWIP_TCP_RECVMBOX_SIZE=6
CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6
CONFIG_LWIP_TCP_QUEUE_OOSEQ=y
CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6
CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4
@@ -1399,6 +1545,9 @@ CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set
# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set
CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF
CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5
CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3
CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10
# CONFIG_LWIP_PPP_SUPPORT is not set
CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3
CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5
@@ -1424,13 +1573,17 @@ CONFIG_LWIP_MAX_RAW_PCBS=16
CONFIG_LWIP_SNTP_MAX_SERVERS=1
# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set
CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000
CONFIG_LWIP_SNTP_STARTUP_DELAY=y
CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY=5000
# end of SNTP
#
# DNS
#
CONFIG_LWIP_DNS_MAX_HOST_IP=1
CONFIG_LWIP_DNS_MAX_SERVERS=3
# CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set
# CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF is not set
# end of DNS
CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7
@@ -1454,6 +1607,8 @@ CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE=y
CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y
# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set
# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set
CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y
# CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set
CONFIG_LWIP_HOOK_IP6_INPUT_NONE=y
# CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT is not set
# CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set
@@ -1466,6 +1621,7 @@ CONFIG_LWIP_HOOK_IP6_INPUT_NONE=y
# mbedTLS
#
CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
# CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC is not set
# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set
# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
@@ -1493,6 +1649,7 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y
# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set
# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set
# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set
# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200
# end of Certificate Bundle
@@ -1515,6 +1672,7 @@ CONFIG_MBEDTLS_HAVE_TIME=y
# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set
CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y
CONFIG_MBEDTLS_SHA512_C=y
# CONFIG_MBEDTLS_SHA3_C is not set
CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y
# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set
# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set
@@ -1591,6 +1749,7 @@ CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM=y
# CONFIG_MBEDTLS_HKDF_C is not set
# CONFIG_MBEDTLS_THREADING_C is not set
CONFIG_MBEDTLS_ERROR_STRINGS=y
CONFIG_MBEDTLS_FS_IO=y
# end of mbedTLS
#
@@ -1625,6 +1784,8 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y
# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set
# end of Newlib
CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND=y
#
# NVS
#
@@ -1715,6 +1876,8 @@ CONFIG_SPI_FLASH_HPM_DC_AUTO=y
# CONFIG_SPI_FLASH_HPM_DC_DISABLE is not set
CONFIG_SPI_FLASH_SUSPEND_QVL_SUPPORTED=y
# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set
CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50
# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set
# end of Optional and Experimental Features (READ DOCS FIRST)
# end of Main Flash configuration
@@ -1812,6 +1975,11 @@ CONFIG_WS_BUFFER_SIZE=1024
# Ultra Low Power (ULP) Co-processor
#
# CONFIG_ULP_COPROC_ENABLED is not set
#
# ULP Debugging Options
#
# end of ULP Debugging Options
# end of Ultra Low Power (ULP) Co-processor
#
@@ -1835,16 +2003,23 @@ CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y
# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set
#
# Root Hub configuration
# Hub Driver Configuration
#
#
# Root Port configuration
#
CONFIG_USB_HOST_DEBOUNCE_DELAY_MS=250
CONFIG_USB_HOST_RESET_HOLD_MS=30
CONFIG_USB_HOST_RESET_RECOVERY_MS=30
CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS=10
# end of Root Hub configuration
# end of Root Port configuration
# CONFIG_USB_HOST_HUBS_SUPPORTED is not set
# end of Hub Driver Configuration
CONFIG_USB_OTG_SUPPORTED=y
# CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK is not set
CONFIG_USB_OTG_SUPPORTED=y
# end of USB-OTG
#
@@ -1878,7 +2053,6 @@ CONFIG_WL_SECTOR_SIZE=4096
#
CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16
CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30
# CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION is not set
CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y
# CONFIG_WIFI_PROV_STA_FAST_SCAN is not set
# end of Wi-Fi Provisioning Manager
@@ -1907,7 +2081,7 @@ CONFIG_LV_COLOR_CHROMA_KEY_HEX=0x00FF00
# Memory settings
#
# CONFIG_LV_MEM_CUSTOM is not set
CONFIG_LV_MEM_SIZE_KILOBYTES=32
CONFIG_LV_MEM_SIZE_KILOBYTES=64
CONFIG_LV_MEM_ADDR=0x0
CONFIG_LV_MEM_BUF_MAX_NUM=16
# CONFIG_LV_MEMCPY_MEMSET_STD is not set
@@ -2229,16 +2403,15 @@ CONFIG_STACK_CHECK_NONE=y
# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set
CONFIG_ESP32_APPTRACE_DEST_NONE=y
CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
# CONFIG_MCPWM_ISR_IN_IRAM is not set
# CONFIG_EXTERNAL_COEX_ENABLE is not set
# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set
# CONFIG_MCPWM_ISR_IN_IRAM is not set
# CONFIG_EVENT_LOOP_PROFILING is not set
CONFIG_POST_EVENTS_FROM_ISR=y
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
CONFIG_GDBSTUB_SUPPORT_TASKS=y
CONFIG_GDBSTUB_MAX_TASKS=32
# CONFIG_OTA_ALLOW_HTTP is not set
# CONFIG_ESP_SYSTEM_PD_FLASH is not set
CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y
@@ -2254,7 +2427,9 @@ CONFIG_ESP32_PHY_MAX_TX_POWER=20
# CONFIG_ESP32_REDUCE_PHY_TX_POWER is not set
CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y
CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y
# CONFIG_ESP32S3_SPIRAM_SUPPORT is not set
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
CONFIG_DEFAULT_PSRAM_CLK_IO=30
CONFIG_DEFAULT_PSRAM_CS_IO=26
# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160=y
# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240 is not set
@@ -2304,10 +2479,10 @@ CONFIG_TIMER_TASK_STACK_SIZE=3584
CONFIG_ESP32_WIFI_ENABLED=y
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32
# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set
CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1
CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32
# CONFIG_ESP32_WIFI_CSI_ENABLED is not set
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP32_WIFI_TX_BA_WIN=6
@@ -2315,6 +2490,7 @@ CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_RX_BA_WIN=6
CONFIG_ESP32_WIFI_RX_BA_WIN=6
# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set
CONFIG_ESP32_WIFI_NVS_ENABLED=y
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set