Skip to content

Instantly share code, notes, and snippets.

@2200913
Last active May 1, 2023 13:46
Show Gist options
  • Save 2200913/0383699a9e6b0b9e5fdcdcf5b44c3058 to your computer and use it in GitHub Desktop.
Save 2200913/0383699a9e6b0b9e5fdcdcf5b44c3058 to your computer and use it in GitHub Desktop.
TAMAGOTCHI - Embedded Systems Project 2200913 2222947 IPLEIRIA
/**
* @file APDS-9930.cpp
* @brief Library for the SparkFun APDS-9930 breakout board
* @author Shawn Hymel (SparkFun Electronics)
*
* @copyright This code is public domain but you buy me a beer if you use
* this and we meet someday (Beerware license).
*
* This library interfaces the Avago APDS-9930 to Arduino over I2C. The library
* relies on the Arduino Wire (I2C) library. to use the library, instantiate an
* APDS9930 object, call init(), and call the appropriate functions.
*
* APDS-9930 current draw tests (default parameters):
* Off: 1mA
* Waiting for gesture: 14mA
* Gesture in progress: 35mA
*/
#include "Arduino.h"
#include "Wire.h"
#include "APDS9930.h"
/**
* @brief Constructor - Instantiates APDS9930 object
*/
APDS9930::APDS9930()
{
}
/**
* @brief Destructor
*/
APDS9930::~APDS9930()
{
}
/**
* @brief Configures I2C communications and initializes registers to defaults
*
* @return True if initialized successfully. False otherwise.
*/
#define SDA_pin 18
#define SCL_pin 19
bool APDS9930::init()
{
uint8_t id;
/* Initialize I2C */
//Wire.begin();
Wire1.begin(SDA_pin, SCL_pin);
/* Read ID register and check against known values for APDS-9930 */
if( !wireReadDataByte(APDS9930_ID, id) ) {
Serial.println(F("ID read"));
return false;
}
if( !(id == APDS9930_ID_1 || id == APDS9930_ID_2) ) {
Serial.println(F("ID check"));
Serial.println(String("ID is ") + String(id, HEX));
//return false;
}
/* Set ENABLE register to 0 (disable all features) */
if( !setMode(ALL, OFF) ) {
Serial.println(F("Regs off"));
return false;
}
/* Set default values for ambient light and proximity registers */
if( !wireWriteDataByte(APDS9930_ATIME, DEFAULT_ATIME) ) {
return false;
}
if( !wireWriteDataByte(APDS9930_WTIME, DEFAULT_WTIME) ) {
return false;
}
if( !wireWriteDataByte(APDS9930_PPULSE, DEFAULT_PPULSE) ) {
return false;
}
if( !wireWriteDataByte(APDS9930_POFFSET, DEFAULT_POFFSET) ) {
return false;
}
if( !wireWriteDataByte(APDS9930_CONFIG, DEFAULT_CONFIG) ) {
return false;
}
if( !setLEDDrive(DEFAULT_PDRIVE) ) {
return false;
}
if( !setProximityGain(DEFAULT_PGAIN) ) {
return false;
}
if( !setAmbientLightGain(DEFAULT_AGAIN) ) {
return false;
}
if( !setProximityDiode(DEFAULT_PDIODE) ) {
return false;
}
if( !setProximityIntLowThreshold(DEFAULT_PILT) ) {
return false;
}
if( !setProximityIntHighThreshold(DEFAULT_PIHT) ) {
return false;
}
if( !setLightIntLowThreshold(DEFAULT_AILT) ) {
return false;
}
if( !setLightIntHighThreshold(DEFAULT_AIHT) ) {
return false;
}
if( !wireWriteDataByte(APDS9930_PERS, DEFAULT_PERS) ) {
return false;
}
return true;
}
/*******************************************************************************
* Public methods for controlling the APDS-9930
******************************************************************************/
/**
* @brief Reads and returns the contents of the ENABLE register
*
* @return Contents of the ENABLE register. 0xFF if error.
*/
uint8_t APDS9930::getMode()
{
uint8_t enable_value;
/* Read current ENABLE register */
if( !wireReadDataByte(APDS9930_ENABLE, enable_value) ) {
return ERROR;
}
return enable_value;
}
/**
* @brief Enables or disables a feature in the APDS-9930
*
* @param[in] mode which feature to enable
* @param[in] enable ON (1) or OFF (0)
* @return True if operation success. False otherwise.
*/
bool APDS9930::setMode(uint8_t mode, uint8_t enable)
{
uint8_t reg_val;
/* Read current ENABLE register */
reg_val = getMode();
if( reg_val == ERROR ) {
return false;
}
/* Change bit(s) in ENABLE register */
enable = enable & 0x01;
if( mode >= 0 && mode <= 6 ) {
if (enable) {
reg_val |= (1 << mode);
} else {
reg_val &= ~(1 << mode);
}
} else if( mode == ALL ) {
if (enable) {
reg_val = 0x7F;
} else {
reg_val = 0x00;
}
}
/* Write value back to ENABLE register */
if( !wireWriteDataByte(APDS9930_ENABLE, reg_val) ) {
return false;
}
return true;
}
/**
* @brief Starts the light (R/G/B/Ambient) sensor on the APDS-9930
*
* @param[in] interrupts true to enable hardware interrupt on high or low light
* @return True if sensor enabled correctly. False on error.
*/
bool APDS9930::enableLightSensor(bool interrupts)
{
/* Set default gain, interrupts, enable power, and enable sensor */
if( !setAmbientLightGain(DEFAULT_AGAIN) ) {
return false;
}
if( interrupts ) {
if( !setAmbientLightIntEnable(1) ) {
return false;
}
} else {
if( !setAmbientLightIntEnable(0) ) {
return false;
}
}
if( !enablePower() ){
return false;
}
if( !setMode(AMBIENT_LIGHT, 1) ) {
return false;
}
return true;
}
/**
* @brief Ends the light sensor on the APDS-9930
*
* @return True if sensor disabled correctly. False on error.
*/
bool APDS9930::disableLightSensor()
{
if( !setAmbientLightIntEnable(0) ) {
return false;
}
if( !setMode(AMBIENT_LIGHT, 0) ) {
return false;
}
return true;
}
/**
* @brief Starts the proximity sensor on the APDS-9930
*
* @param[in] interrupts true to enable hardware external interrupt on proximity
* @return True if sensor enabled correctly. False on error.
*/
bool APDS9930::enableProximitySensor(bool interrupts)
{
/* Set default gain, LED, interrupts, enable power, and enable sensor */
if( !setProximityGain(DEFAULT_PGAIN) ) {
return false;
}
if( !setLEDDrive(DEFAULT_PDRIVE) ) {
return false;
}
if( interrupts ) {
if( !setProximityIntEnable(1) ) {
return false;
}
} else {
if( !setProximityIntEnable(0) ) {
return false;
}
}
if( !enablePower() ){
return false;
}
if( !setMode(PROXIMITY, 1) ) {
return false;
}
return true;
}
/**
* @brief Ends the proximity sensor on the APDS-9930
*
* @return True if sensor disabled correctly. False on error.
*/
bool APDS9930::disableProximitySensor()
{
if( !setProximityIntEnable(0) ) {
return false;
}
if( !setMode(PROXIMITY, 0) ) {
return false;
}
return true;
}
/**
* Turn the APDS-9930 on
*
* @return True if operation successful. False otherwise.
*/
bool APDS9930::enablePower()
{
if( !setMode(POWER, 1) ) {
return false;
}
return true;
}
/**
* Turn the APDS-9930 off
*
* @return True if operation successful. False otherwise.
*/
bool APDS9930::disablePower()
{
if( !setMode(POWER, 0) ) {
return false;
}
return true;
}
/*******************************************************************************
* Ambient light and color sensor controls
******************************************************************************/
/**
* @brief Reads the ambient (clear) light level as a 16-bit value
*
* @param[out] val value of the light sensor.
* @return True if operation successful. False otherwise.
*/
bool APDS9930::readAmbientLightLux(float &val)
{
uint16_t Ch0;
uint16_t Ch1;
uint8_t val_byte;
/* Read value from channel 0 */
if( !readCh0Light(Ch0) ) {
return false;
}
/* Read value from channel 1 */
if( !readCh1Light(Ch1) ) {
return false;
}
val = floatAmbientToLux(Ch0, Ch1);
}
bool APDS9930::readAmbientLightLux(unsigned long &val)
{
uint16_t Ch0;
uint16_t Ch1;
uint8_t val_byte;
/* Read value from channel 0 */
if( !readCh0Light(Ch0) ) {
return false;
}
/* Read value from channel 1 */
if( !readCh1Light(Ch1) ) {
return false;
}
val = ulongAmbientToLux(Ch0, Ch1);
}
float APDS9930::floatAmbientToLux(uint16_t Ch0, uint16_t Ch1)
{
float ALSIT = 2.73 * (256 - DEFAULT_ATIME);
float iac = max(Ch0 - B * Ch1, C * Ch0 - D * Ch1);
float lpc = GA * DF / (ALSIT * getAmbientLightGain());
return iac * lpc;
}
unsigned long APDS9930::ulongAmbientToLux(uint16_t Ch0, uint16_t Ch1)
{
unsigned long ALSIT = 2.73 * (256 - DEFAULT_ATIME);
unsigned long iac = max(Ch0 - B * Ch1, C * Ch0 - D * Ch1);
unsigned long lpc = GA * DF / (ALSIT * getAmbientLightGain());
return iac * lpc;
}
bool APDS9930::readCh0Light(uint16_t &val)
{
uint8_t val_byte;
val = 0;
/* Read value from channel 0 */
if( !wireReadDataByte(APDS9930_Ch0DATAL, val_byte) ) {
return false;
}
val = val_byte;
if( !wireReadDataByte(APDS9930_Ch0DATAH, val_byte) ) {
return false;
}
val += ((uint16_t)val_byte << 8);
return true;
}
bool APDS9930::readCh1Light(uint16_t &val)
{
uint8_t val_byte;
val = 0;
/* Read value from channel 0 */
if( !wireReadDataByte(APDS9930_Ch1DATAL, val_byte) ) {
return false;
}
val = val_byte;
if( !wireReadDataByte(APDS9930_Ch1DATAH, val_byte) ) {
return false;
}
val += ((uint16_t)val_byte << 8);
return true;
}
/*******************************************************************************
* Proximity sensor controls
******************************************************************************/
/**
* @brief Reads the proximity level as an 8-bit value
*
* @param[out] val value of the proximity sensor.
* @return True if operation successful. False otherwise.
*/
bool APDS9930::readProximity(uint16_t &val)
{
val = 0;
uint8_t val_byte;
/* Read value from proximity data register */
if( !wireReadDataByte(APDS9930_PDATAL, val_byte) ) {
return false;
}
val = val_byte;
if( !wireReadDataByte(APDS9930_PDATAH, val_byte) ) {
return false;
}
val += ((uint16_t)val_byte << 8);
return true;
}
/*******************************************************************************
* Getters and setters for register values
******************************************************************************/
/**
* @brief Returns the lower threshold for proximity detection
*
* @return lower threshold
*/
uint8_t APDS9930::getProximityIntLowThreshold()
{
uint16_t val;
uint8_t val_byte;
/* Read value from PILT register */
if( !wireReadDataByte(APDS9930_PILTL, val_byte) ) {
val = 0;
}
val = val_byte;
if( !wireReadDataByte(APDS9930_PILTH, val_byte) ) {
val = 0;
}
val += ((uint16_t)val_byte << 8);
return val;
}
/**
* @brief Sets the lower threshold for proximity detection
*
* @param[in] threshold the lower proximity threshold
* @return True if operation successful. False otherwise.
*/
bool APDS9930::setProximityIntLowThreshold(uint16_t threshold)
{
uint8_t lo;
uint8_t hi;
hi = threshold >> 8;
lo = threshold & 0x00FF;
if( !wireWriteDataByte(APDS9930_PILTL, lo) ) {
return false;
}
if( !wireWriteDataByte(APDS9930_PILTH, hi) ) {
return false;
}
return true;
}
/**
* @brief Returns the high threshold for proximity detection
*
* @return high threshold
*/
uint8_t APDS9930::getProximityIntHighThreshold()
{
uint16_t val;
uint8_t val_byte;
/* Read value from PILT register */
if( !wireReadDataByte(APDS9930_PIHTL, val_byte) ) {
val = 0;
}
val = val_byte;
if( !wireReadDataByte(APDS9930_PIHTH, val_byte) ) {
val = 0;
}
val += ((uint16_t)val_byte << 8);
return val;
}
/**
* @brief Sets the high threshold for proximity detection
*
* @param[in] threshold the high proximity threshold
* @return True if operation successful. False otherwise.
*/
bool APDS9930::setProximityIntHighThreshold(uint16_t threshold)
{
uint8_t lo;
uint8_t hi;
hi = threshold >> 8;
lo = threshold & 0x00FF;
if( !wireWriteDataByte(APDS9930_PIHTL, lo) ) {
return false;
}
if( !wireWriteDataByte(APDS9930_PIHTH, hi) ) {
return false;
}
return true;
}
/**
* @brief Returns LED drive strength for proximity and ALS
*
* Value LED Current
* 0 100 mA
* 1 50 mA
* 2 25 mA
* 3 12.5 mA
*
* @return the value of the LED drive strength. 0xFF on failure.
*/
uint8_t APDS9930::getLEDDrive()
{
uint8_t val;
/* Read value from CONTROL register */
if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
return ERROR;
}
/* Shift and mask out LED drive bits */
val = (val >> 6) & 0b00000011;
return val;
}
/**
* @brief Sets the LED drive strength for proximity and ALS
*
* Value LED Current
* 0 100 mA
* 1 50 mA
* 2 25 mA
* 3 12.5 mA
*
* @param[in] drive the value (0-3) for the LED drive strength
* @return True if operation successful. False otherwise.
*/
bool APDS9930::setLEDDrive(uint8_t drive)
{
uint8_t val;
/* Read value from CONTROL register */
if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
return false;
}
/* Set bits in register to given value */
drive &= 0b00000011;
drive = drive << 6;
val &= 0b00111111;
val |= drive;
/* Write register value back into CONTROL register */
if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
return false;
}
return true;
}
/**
* @brief Returns receiver gain for proximity detection
*
* Value Gain
* 0 1x
* 1 2x
* 2 4x
* 3 8x
*
* @return the value of the proximity gain. 0xFF on failure.
*/
uint8_t APDS9930::getProximityGain()
{
uint8_t val;
/* Read value from CONTROL register */
if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
return ERROR;
}
/* Shift and mask out PDRIVE bits */
val = (val >> 2) & 0b00000011;
return val;
}
/**
* @brief Sets the receiver gain for proximity detection
*
* Value Gain
* 0 1x
* 1 2x
* 2 4x
* 3 8x
*
* @param[in] drive the value (0-3) for the gain
* @return True if operation successful. False otherwise.
*/
bool APDS9930::setProximityGain(uint8_t drive)
{
uint8_t val;
/* Read value from CONTROL register */
if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
return false;
}
/* Set bits in register to given value */
drive &= 0b00000011;
drive = drive << 2;
val &= 0b11110011;
val |= drive;
/* Write register value back into CONTROL register */
if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
return false;
}
return true;
}
/**
* @brief Returns the proximity diode
*
* Value Diode selection
* 0 Reserved
* 1 Reserved
* 2 Use Ch1 diode
* 3 Reserved
*
* @return the selected diode. 0xFF on failure.
*/
uint8_t APDS9930::getProximityDiode()
{
uint8_t val;
/* Read value from CONTROL register */
if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
return ERROR;
}
/* Shift and mask out PDRIVE bits */
val = (val >> 4) & 0b00000011;
return val;
}
/**
* @brief Selects the proximity diode
*
* Value Diode selection
* 0 Reserved
* 1 Reserved
* 2 Use Ch1 diode
* 3 Reserved
*
* @param[in] drive the value (0-3) for the diode
* @return True if operation successful. False otherwise.
*/
bool APDS9930::setProximityDiode(uint8_t drive)
{
uint8_t val;
/* Read value from CONTROL register */
if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
return false;
}
/* Set bits in register to given value */
drive &= 0b00000011;
drive = drive << 4;
val &= 0b11001111;
val |= drive;
/* Write register value back into CONTROL register */
if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
return false;
}
return true;
}
/**
* @brief Returns receiver gain for the ambient light sensor (ALS)
*
* Value Gain
* 0 1x
* 1 4x
* 2 16x
* 3 64x
*
* @return the value of the ALS gain. 0xFF on failure.
*/
uint8_t APDS9930::getAmbientLightGain()
{
uint8_t val;
/* Read value from CONTROL register */
if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
return ERROR;
}
/* Shift and mask out ADRIVE bits */
val &= 0b00000011;
return val;
}
/**
* @brief Sets the receiver gain for the ambient light sensor (ALS)
*
* Value Gain
* 0 1x
* 1 4x
* 2 16x
* 3 64x
*
* @param[in] drive the value (0-3) for the gain
* @return True if operation successful. False otherwise.
*/
bool APDS9930::setAmbientLightGain(uint8_t drive)
{
uint8_t val;
/* Read value from CONTROL register */
if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
return false;
}
/* Set bits in register to given value */
drive &= 0b00000011;
val &= 0b11111100;
val |= drive;
/* Write register value back into CONTROL register */
if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
return false;
}
return true;
}
/**
* @brief Gets the low threshold for ambient light interrupts
*
* @param[out] threshold current low threshold stored on the APDS-9930
* @return True if operation successful. False otherwise.
*/
bool APDS9930::getLightIntLowThreshold(uint16_t &threshold)
{
uint8_t val_byte;
threshold = 0;
/* Read value from ambient light low threshold, low byte register */
if( !wireReadDataByte(APDS9930_AILTL, val_byte) ) {
return false;
}
threshold = val_byte;
/* Read value from ambient light low threshold, high byte register */
if( !wireReadDataByte(APDS9930_AILTH, val_byte) ) {
return false;
}
threshold = threshold + ((uint16_t)val_byte << 8);
return true;
}
/**
* @brief Sets the low threshold for ambient light interrupts
*
* @param[in] threshold low threshold value for interrupt to trigger
* @return True if operation successful. False otherwise.
*/
bool APDS9930::setLightIntLowThreshold(uint16_t threshold)
{
uint8_t val_low;
uint8_t val_high;
/* Break 16-bit threshold into 2 8-bit values */
val_low = threshold & 0x00FF;
val_high = (threshold & 0xFF00) >> 8;
/* Write low byte */
if( !wireWriteDataByte(APDS9930_AILTL, val_low) ) {
return false;
}
/* Write high byte */
if( !wireWriteDataByte(APDS9930_AILTH, val_high) ) {
return false;
}
return true;
}
/**
* @brief Gets the high threshold for ambient light interrupts
*
* @param[out] threshold current low threshold stored on the APDS-9930
* @return True if operation successful. False otherwise.
*/
bool APDS9930::getLightIntHighThreshold(uint16_t &threshold)
{
uint8_t val_byte;
threshold = 0;
/* Read value from ambient light high threshold, low byte register */
if( !wireReadDataByte(APDS9930_AIHTL, val_byte) ) {
return false;
}
threshold = val_byte;
/* Read value from ambient light high threshold, high byte register */
if( !wireReadDataByte(APDS9930_AIHTH, val_byte) ) {
return false;
}
threshold = threshold + ((uint16_t)val_byte << 8);
return true;
}
/**
* @brief Sets the high threshold for ambient light interrupts
*
* @param[in] threshold high threshold value for interrupt to trigger
* @return True if operation successful. False otherwise.
*/
bool APDS9930::setLightIntHighThreshold(uint16_t threshold)
{
uint8_t val_low;
uint8_t val_high;
/* Break 16-bit threshold into 2 8-bit values */
val_low = threshold & 0x00FF;
val_high = (threshold & 0xFF00) >> 8;
/* Write low byte */
if( !wireWriteDataByte(APDS9930_AIHTL, val_low) ) {
return false;
}
/* Write high byte */
if( !wireWriteDataByte(APDS9930_AIHTH, val_high) ) {
return false;
}
return true;
}
/**
* @brief Gets if ambient light interrupts are enabled or not
*
* @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
*/
uint8_t APDS9930::getAmbientLightIntEnable()
{
uint8_t val;
/* Read value from ENABLE register */
if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
return ERROR;
}
/* Shift and mask out AIEN bit */
val = (val >> 4) & 0b00000001;
return val;
}
/**
* @brief Turns ambient light interrupts on or off
*
* @param[in] enable 1 to enable interrupts, 0 to turn them off
* @return True if operation successful. False otherwise.
*/
bool APDS9930::setAmbientLightIntEnable(uint8_t enable)
{
uint8_t val;
/* Read value from ENABLE register */
if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
return false;
}
/* Set bits in register to given value */
enable &= 0b00000001;
enable = enable << 4;
val &= 0b11101111;
val |= enable;
/* Write register value back into ENABLE register */
if( !wireWriteDataByte(APDS9930_ENABLE, val) ) {
return false;
}
return true;
}
/**
* @brief Gets if proximity interrupts are enabled or not
*
* @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
*/
uint8_t APDS9930::getProximityIntEnable()
{
uint8_t val;
/* Read value from ENABLE register */
if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
return ERROR;
}
/* Shift and mask out PIEN bit */
val = (val >> 5) & 0b00000001;
return val;
}
/**
* @brief Turns proximity interrupts on or off
*
* @param[in] enable 1 to enable interrupts, 0 to turn them off
* @return True if operation successful. False otherwise.
*/
bool APDS9930::setProximityIntEnable(uint8_t enable)
{
uint8_t val;
/* Read value from ENABLE register */
if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
return false;
}
/* Set bits in register to given value */
enable &= 0b00000001;
enable = enable << 5;
val &= 0b11011111;
val |= enable;
/* Write register value back into ENABLE register */
if( !wireWriteDataByte(APDS9930_ENABLE, val) ) {
return false;
}
return true;
}
/**
* @brief Clears the ambient light interrupt
*
* @return True if operation completed successfully. False otherwise.
*/
bool APDS9930::clearAmbientLightInt()
{
if( !wireWriteByte(CLEAR_ALS_INT) ) {
return false;
}
return true;
}
/**
* @brief Clears the proximity interrupt
*
* @return True if operation completed successfully. False otherwise.
*/
bool APDS9930::clearProximityInt()
{
if( !wireWriteByte(CLEAR_PROX_INT) ) {
return false;
}
return true;
}
/**
* @brief Clears all interrupts
*
* @return True if operation completed successfully. False otherwise.
*/
bool APDS9930::clearAllInts()
{
if( !wireWriteByte(CLEAR_ALL_INTS) ) {
return false;
}
return true;
}
/*******************************************************************************
* Raw I2C Reads and Writes
******************************************************************************/
/**
* @brief Writes a single byte to the I2C device (no register)
*
* @param[in] val the 1-byte value to write to the I2C device
* @return True if successful write operation. False otherwise.
*/
bool APDS9930::wireWriteByte(uint8_t val)
{
Wire1.beginTransmission(APDS9930_I2C_ADDR);
Wire1.write(val);
if( Wire1.endTransmission() != 0 ) {
return false;
}
return true;
}
/**
* @brief Writes a single byte to the I2C device and specified register
*
* @param[in] reg the register in the I2C device to write to
* @param[in] val the 1-byte value to write to the I2C device
* @return True if successful write operation. False otherwise.
*/
bool APDS9930::wireWriteDataByte(uint8_t reg, uint8_t val)
{
Wire1.beginTransmission(APDS9930_I2C_ADDR);
Wire1.write(reg | AUTO_INCREMENT);
Wire1.write(val);
if( Wire1.endTransmission() != 0 ) {
return false;
}
return true;
}
/**
* @brief Writes a block (array) of bytes to the I2C device and register
*
* @param[in] reg the register in the I2C device to write to
* @param[in] val pointer to the beginning of the data byte array
* @param[in] len the length (in bytes) of the data to write
* @return True if successful write operation. False otherwise.
*/
bool APDS9930::wireWriteDataBlock( uint8_t reg,
uint8_t *val,
unsigned int len)
{
unsigned int i;
Wire1.beginTransmission(APDS9930_I2C_ADDR);
Wire1.write(reg | AUTO_INCREMENT);
for(i = 0; i < len; i++) {
Wire1.beginTransmission(APDS9930_I2C_ADDR);
Wire1.write(val[i]);
}
if( Wire1.endTransmission() != 0 ) {
return false;
}
return true;
}
/**
* @brief Reads a single byte from the I2C device and specified register
*
* @param[in] reg the register to read from
* @param[out] the value returned from the register
* @return True if successful read operation. False otherwise.
*/
bool APDS9930::wireReadDataByte(uint8_t reg, uint8_t &val)
{
/* Indicate which register we want to read from */
if (!wireWriteByte(reg | AUTO_INCREMENT)) {
return false;
}
/* Read from register */
Wire1.requestFrom(APDS9930_I2C_ADDR, 1);
while (Wire1.available()) {
val = Wire1.read();
}
return true;
}
/**
* @brief Reads a block (array) of bytes from the I2C device and register
*
* @param[in] reg the register to read from
* @param[out] val pointer to the beginning of the data
* @param[in] len number of bytes to read
* @return Number of bytes read. -1 on read error.
*/
int APDS9930::wireReadDataBlock( uint8_t reg,
uint8_t *val,
unsigned int len)
{
unsigned char i = 0;
/* Indicate which register we want to read from */
if (!wireWriteByte(reg | AUTO_INCREMENT)) {
return -1;
}
/* Read block data */
Wire1.requestFrom(APDS9930_I2C_ADDR, len);
while (Wire1.available()) {
if (i >= len) {
return -1;
}
val[i] = Wire1.read();
i++;
}
return i;
}
/**
* @file APDS-9930.h
* @brief Library for the SparkFun APDS-9930 breakout board
* @author Shawn Hymel (SparkFun Electronics)
*
* @copyright This code is public domain but you buy me a beer if you use
* this and we meet someday (Beerware license).
*
* This library interfaces the Avago APDS-9930 to Arduino over I2C. The library
* relies on the Arduino Wire (I2C) library. to use the library, instantiate an
* APDS9930 object, call init(), and call the appropriate functions.
*/
#ifndef APDS9930_H
#define APDS9930_H
#include <Arduino.h>
/* Debug */
#define DEBUG 0
/* APDS-9930 I2C address */
#define APDS9930_I2C_ADDR 0x39
/* Command register modes */
#define REPEATED_BYTE 0x80
#define AUTO_INCREMENT 0xA0
#define SPECIAL_FN 0xE0
/* Error code for returned values */
#define ERROR 0xFF
/* Acceptable device IDs */
#define APDS9930_ID_1 0x12
#define APDS9930_ID_2 0x39
/* Misc parameters */
#define FIFO_PAUSE_TIME 30 // Wait period (ms) between FIFO reads
/* APDS-9930 register addresses */
#define APDS9930_ENABLE 0x00
#define APDS9930_ATIME 0x01
#define APDS9930_WTIME 0x03
#define APDS9930_AILTL 0x04
#define APDS9930_AILTH 0x05
#define APDS9930_AIHTL 0x06
#define APDS9930_AIHTH 0x07
#define APDS9930_PILTL 0x08
#define APDS9930_PILTH 0x09
#define APDS9930_PIHTL 0x0A
#define APDS9930_PIHTH 0x0B
#define APDS9930_PERS 0x0C
#define APDS9930_CONFIG 0x0D
#define APDS9930_PPULSE 0x0E
#define APDS9930_CONTROL 0x0F
#define APDS9930_ID 0x12
#define APDS9930_STATUS 0x13
#define APDS9930_Ch0DATAL 0x14
#define APDS9930_Ch0DATAH 0x15
#define APDS9930_Ch1DATAL 0x16
#define APDS9930_Ch1DATAH 0x17
#define APDS9930_PDATAL 0x18
#define APDS9930_PDATAH 0x19
#define APDS9930_POFFSET 0x1E
/* Bit fields */
#define APDS9930_PON 0b00000001
#define APDS9930_AEN 0b00000010
#define APDS9930_PEN 0b00000100
#define APDS9930_WEN 0b00001000
#define APSD9930_AIEN 0b00010000
#define APDS9930_PIEN 0b00100000
#define APDS9930_SAI 0b01000000
/* On/Off definitions */
#define OFF 0
#define ON 1
/* Acceptable parameters for setMode */
#define POWER 0
#define AMBIENT_LIGHT 1
#define PROXIMITY 2
#define WAIT 3
#define AMBIENT_LIGHT_INT 4
#define PROXIMITY_INT 5
#define SLEEP_AFTER_INT 6
#define ALL 7
/* LED Drive values */
#define LED_DRIVE_100MA 0
#define LED_DRIVE_50MA 1
#define LED_DRIVE_25MA 2
#define LED_DRIVE_12_5MA 3
/* Proximity Gain (PGAIN) values */
#define PGAIN_1X 0
#define PGAIN_2X 1
#define PGAIN_4X 2
#define PGAIN_8X 3
/* ALS Gain (AGAIN) values */
#define AGAIN_1X 0
#define AGAIN_8X 1
#define AGAIN_16X 2
#define AGAIN_120X 3
/* Interrupt clear values */
#define CLEAR_PROX_INT 0xE5
#define CLEAR_ALS_INT 0xE6
#define CLEAR_ALL_INTS 0xE7
/* Default values */
#define DEFAULT_ATIME 0xFF
#define DEFAULT_WTIME 0xFF
#define DEFAULT_PTIME 0xFF
#define DEFAULT_PPULSE 0x08
#define DEFAULT_POFFSET 0 // 0 offset
#define DEFAULT_CONFIG 0
#define DEFAULT_PDRIVE LED_DRIVE_100MA
#define DEFAULT_PDIODE 2
#define DEFAULT_PGAIN PGAIN_8X
#define DEFAULT_AGAIN AGAIN_16X
#define DEFAULT_PILT 0 // Low proximity threshold
#define DEFAULT_PIHT 50 // High proximity threshold
#define DEFAULT_AILT 0xFFFF // Force interrupt for calibration
#define DEFAULT_AIHT 0
#define DEFAULT_PERS 0x22 // 2 consecutive prox or ALS for int.
/* ALS coefficients */
#define DF 52
#define GA 0.49
#define B 1.862
#define C 0.746
#define D 1.291
/* State definitions */
enum {
NA_STATE,
NEAR_STATE,
FAR_STATE,
ALL_STATE
};
/* APDS9930 Class */
class APDS9930 {
public:
/* Initialization methods */
APDS9930();
~APDS9930();
bool init();
uint8_t getMode();
bool setMode(uint8_t mode, uint8_t enable);
/* Turn the APDS-9930 on and off */
bool enablePower();
bool disablePower();
/* Enable or disable specific sensors */
bool enableLightSensor(bool interrupts = false);
bool disableLightSensor();
bool enableProximitySensor(bool interrupts = false);
bool disableProximitySensor();
/* LED drive strength control */
uint8_t getLEDDrive();
bool setLEDDrive(uint8_t drive);
// uint8_t getGestureLEDDrive();
// bool setGestureLEDDrive(uint8_t drive);
/* Gain control */
uint8_t getAmbientLightGain();
bool setAmbientLightGain(uint8_t gain);
uint8_t getProximityGain();
bool setProximityGain(uint8_t gain);
bool setProximityDiode(uint8_t drive);
uint8_t getProximityDiode();
/* Get and set light interrupt thresholds */
bool getLightIntLowThreshold(uint16_t &threshold);
bool setLightIntLowThreshold(uint16_t threshold);
bool getLightIntHighThreshold(uint16_t &threshold);
bool setLightIntHighThreshold(uint16_t threshold);
/* Get and set interrupt enables */
uint8_t getAmbientLightIntEnable();
bool setAmbientLightIntEnable(uint8_t enable);
uint8_t getProximityIntEnable();
bool setProximityIntEnable(uint8_t enable);
/* Clear interrupts */
bool clearAmbientLightInt();
bool clearProximityInt();
bool clearAllInts();
/* Proximity methods */
bool readProximity(uint16_t &val);
/* Ambient light methods */
bool readAmbientLightLux(float &val);
bool readAmbientLightLux(unsigned long &val);
float floatAmbientToLux(uint16_t Ch0, uint16_t Ch1);
unsigned long ulongAmbientToLux(uint16_t Ch0, uint16_t Ch1);
bool readCh0Light(uint16_t &val);
bool readCh1Light(uint16_t &val);
//private:
/* Proximity Interrupt Threshold */
uint8_t getProximityIntLowThreshold();
bool setProximityIntLowThreshold(uint16_t threshold);
uint8_t getProximityIntHighThreshold();
bool setProximityIntHighThreshold(uint16_t threshold);
/* Raw I2C Commands */
bool wireWriteByte(uint8_t val);
bool wireWriteDataByte(uint8_t reg, uint8_t val);
bool wireWriteDataBlock(uint8_t reg, uint8_t *val, unsigned int len);
bool wireReadDataByte(uint8_t reg, uint8_t &val);
int wireReadDataBlock(uint8_t reg, uint8_t *val, unsigned int len);
};
#endif
#include "Arduino.h"
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_task_wdt.h"
#include "Arduino.h"
#include <math.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <driver/i2s.h>
#include <exception>
#define I2S_WS 32
#define I2S_SD 33
#define I2S_SCK 26
#define ADC_1_0 4
#define ADC_RESOLUTION 10
#define ADC_RESOLUTION_2 4096.0
#define VREF_PLUS 3.3
#define VREF_MINUS 0.0
#define LED_PIN 5
#define I2S_PORT I2S_NUM_0
#define bufferLen 512
#define PIN_LM35 32 // ESP32 pin GIOP36 (ADC0) connected to LM35
#define ADC_VREF_mV 3300.0 // in millivolt
int freq = 5000;
int ledChannel = 5;
int resolution = 8;
//--------------PROXIMITY SENSOR------------------------
#include <Wire.h>
#include "APDS9930.h"
// Pins
#define APDS9930_INT 4 // Needs to be an interrupt pin
// Constants
#define PROX_INT_HIGH 600 // Proximity level for interrupt
#define PROX_INT_LOW 0 // No far interrupt
// Global variables
APDS9930 apds = APDS9930();
float ambient_light = 0; // can also be an unsigned long
uint16_t ch0 = 0;
uint16_t ch1 = 1;
uint16_t proximity_data = 0;
volatile bool isr_flag = false;
//------------------------------------------------------
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define NUMFLAKES 10 // Number of snowflakes in the animation example
#define LOGO_HEIGHT 64
#define LOGO_WIDTH 128
#include <WiFi.h>
#include <NTPClient.h>
const char *ssid = "BuenosDias";
const char *password = "NaoSeiAPass";
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
static const unsigned char PROGMEM logo_bmp[] = { B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };
static const uint8_t image_data_Hamster_v11[1024] = {
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ████████████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙███∙
// █████████████████████████████████████████████∙∙∙∙∙∙∙∙∙██████████████████████∙∙∙∙∙∙∙∙∙███████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████
// █████████████████████████████████████████████∙∙∙∙∙∙∙∙███████████████████████∙∙∙∙∙∙∙∙∙███████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████████
// ███████████████████████████████████████████∙█∙∙█∙█∙█∙∙█████████████∙█████∙██∙█∙█∙█∙█∙███████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████████
// ████████████████████████████████████████∙∙∙∙∙██∙█∙█∙██∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙∙██∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙██████████████████
// ████████████████████████████████████████∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙███∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████████████████
// ████████████████████████████████████████∙∙█∙∙█∙█∙█∙██∙█∙█∙█∙█∙█∙█∙████∙█∙██∙█∙█∙█∙█∙█∙∙∙∙███∙∙∙∙∙∙∙∙████████████████████████████
// █████████████████████████████████████████∙∙∙∙█∙█∙█∙█∙█∙█∙█████████∙█∙███∙█∙█∙█∙█∙█∙█∙∙∙█∙∙██∙∙∙∙∙∙∙∙████████████████████████████
// ████████████████████████████████████████∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙███∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙███████████████████████████████████████
// █████████████████████████████████████████████∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙∙∙∙███████████████████████████████████████████
// █████████████████████████████████████████████∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙██∙█∙█∙█∙█∙█∙█∙∙∙∙∙████████████████████████████████████████████
// ███████████████████████████████████████████∙█∙█∙∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙██∙█∙∙███∙███████████████████████████████████████
// ████████████████████████████████████████∙∙∙∙∙█∙██∙█∙█∙∙∙∙∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙█∙█∙█∙██∙∙∙∙∙███████████████████████████████████████
// ████████████████████████████████████████∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙█∙█∙█∙∙█∙∙∙∙∙∙██████████████████████████████████████
// ████████████████████████████████████∙∙∙∙█████∙██∙██∙██████∙██∙█∙█∙█∙██∙█████∙███∙████████∙∙∙∙∙██████████████████████████████████
// ████████████████████████████████████∙∙∙∙█∙█∙███∙██∙██∙█∙█∙██∙██∙█∙∙█████∙██∙██∙███∙█∙█∙██∙█∙∙∙██████████████████████████████████
// ███████████████████████████████████∙∙█∙∙████∙█∙██∙████∙████∙██∙█∙██∙█∙█∙██∙████∙█∙█████∙█∙∙∙█∙██████████████████████████████████
// ███████████████████████████████∙∙∙∙∙█∙██∙█∙████∙███∙█∙██∙█∙███████████∙██∙██∙█∙███∙█∙█∙████∙██∙∙∙∙∙█████████████████████████████
// ███████████████████████████████∙∙∙∙█∙█∙██∙██∙█∙██∙██∙████∙██∙█∙████∙█∙█████∙███∙████∙███∙█∙█∙∙∙∙∙∙██████████████████████████████
// ████████████████████████████████∙∙∙∙█∙█∙██∙█████∙██∙██∙█∙████∙███∙████∙█∙█∙██∙██∙█∙███∙██∙█∙██∙∙█∙██████████████████████████████
// ███████████████████████████████∙∙█∙∙█∙█∙███∙█∙█∙██∙████∙██∙█∙██∙██∙█∙████∙████∙████∙█∙██∙█∙█∙█∙∙∙∙∙█████████████████████████████
// ███████████████████████████████∙∙∙∙∙█∙█∙█∙████∙█████∙█∙████∙████∙████∙█∙███∙█∙██∙█∙███∙███∙█∙█∙∙∙∙██████████████████████████████
// ████████████████████████████████∙∙█∙█∙█∙█∙█∙∙███∙█∙██∙██∙█∙██∙█∙██∙█∙███∙█∙███∙████∙█∙█∙∙█∙█∙█∙∙█∙██████████████████████████████
// ███████████████████████████████∙∙∙∙∙█∙█∙█∙█∙██∙██∙██∙████∙██████∙████∙█████∙███∙█∙███∙██∙█∙█∙█∙∙∙∙∙█████████████████████████████
// ███████████████████████████████∙∙█∙∙█∙█∙█∙█∙█∙█∙██∙██∙█∙██∙█∙∙█∙██∙█∙█∙█∙∙██∙█∙██∙█∙█∙█∙█∙█∙█∙∙∙∙∙██████████████████████████████
// ████████████████████████████████∙∙∙∙∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙∙∙█∙∙██████████████████████████████
// ███████████████████████████████∙∙∙∙█∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙██∙∙∙∙∙∙∙∙██████████████████████████████
// ███████████████████████████████∙∙█∙∙█∙█∙∙∙∙∙██∙██∙█∙█∙████∙███∙██∙██∙███∙██∙█∙█∙██∙██∙∙∙∙∙█∙██∙∙█∙∙█████████████████████████████
// ████████████████████████████████∙∙∙∙█∙██∙∙█∙∙██∙█∙█∙█∙█∙█∙██∙██∙██∙██∙█∙██∙██∙█∙█∙██∙∙█∙∙█∙█∙█∙∙∙∙██████████████████████████████
// ███████████████████████████████∙∙∙∙∙█∙█∙∙∙∙∙∙████∙█∙██████∙██∙███∙██████∙███∙█∙█∙██∙█∙∙∙∙∙█∙█∙∙∙█∙██████████████████████████████
// ███████████████████████████████∙∙█∙∙█∙██████∙█∙∙█∙█∙█∙∙∙∙██∙███∙███∙█∙█∙█∙∙█∙█∙█∙█∙██∙███∙█∙██∙∙∙∙∙█████████████████████████████
// ████████████████████████████████∙∙∙∙█∙█∙∙∙∙█∙█∙█∙█∙█∙███∙∙███∙██∙█∙███∙█∙██∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙██████████████████████████████
// ███████████████████████████████∙█∙██∙█∙∙██∙█∙█∙█∙█∙∙█∙∙█∙█∙█∙█∙██∙██∙██∙█∙█∙∙█∙∙█∙█∙█∙█∙█∙█∙∙████∙██████████████████████████████
// ████████████████████████████████████∙∙∙∙█∙█∙█∙█∙█∙∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙██████████████████████████████████
// ████████████████████████████████████∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙∙∙∙█∙█∙█∙█∙█∙∙∙∙∙██████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0e, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf8, 0x03, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xf0, 0x07, 0xff,
0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x53, 0xff,
0xef, 0xb5, 0x57, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x06, 0xac, 0x00, 0x00, 0x0a, 0xa8, 0x30, 0x00, 0x03, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0x50, 0x00, 0x00, 0x0a, 0xa8, 0x70,
0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x25, 0x5a, 0xaa,
0xbd, 0x6a, 0xa8, 0x70, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x85, 0x55, 0x7f, 0xd7, 0x55, 0x51, 0x30, 0x0f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xaa, 0xaa, 0xba, 0xaa, 0xa8, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x55, 0x55,
0x4a, 0xaa, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf8, 0x55, 0x55, 0x6a, 0xaa, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0x54, 0xaa, 0xaa, 0x95, 0xa7, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0xa8, 0x2a,
0xaa, 0x0a, 0xb0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x05, 0x54, 0x2a, 0xaa, 0x0a, 0x90, 0x3f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0xfb, 0x6f, 0xda, 0xad, 0xf7, 0x7f, 0x83,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xae, 0xda, 0xb6,
0x9f, 0x6d, 0xd5, 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe4, 0xf5, 0xbd, 0xed, 0x6a, 0xde, 0xbe, 0x8b, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x0b, 0x5e, 0xeb, 0x5f, 0xfd, 0xb5, 0xd5, 0xec,
0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x15, 0xb5, 0xb7, 0xb5,
0xeb, 0xee, 0xf7, 0x50, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x0a, 0xdf, 0x6d, 0x7b, 0xbd, 0x5b, 0x5d, 0xac, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x4a, 0xea, 0xde, 0xd6, 0xd7, 0xbd, 0xeb, 0x54,
0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0a, 0xbd, 0xf5, 0xef,
0x7a, 0xeb, 0x5d, 0xd4, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x2a, 0xa7, 0x5b, 0x5a, 0xd7, 0x5d, 0xea, 0x54, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x0a, 0xad, 0xb7, 0xbf, 0x7b, 0xee, 0xbb, 0x54,
0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x4a, 0xaa, 0xda, 0xd2,
0xd5, 0x35, 0xaa, 0xa8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0x01, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xc0,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x4a, 0x0d, 0xab, 0xdd,
0xb7, 0x6a, 0xd8, 0x2c, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x0b, 0x26, 0xaa, 0xb6, 0xda, 0xda, 0xb2, 0x54, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x0a, 0x07, 0xaf, 0xdb, 0xbf, 0x75, 0x68, 0x28,
0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x4b, 0xf4, 0xa8, 0x6e,
0xea, 0x95, 0x5b, 0xac, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x0a, 0x15, 0x57, 0x3b, 0x5d, 0x6a, 0xaa, 0xa8, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0xb4, 0xd5, 0x49, 0x55, 0xb6, 0xa4, 0xaa, 0xa7,
0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xaa, 0x82, 0xaa,
0xa9, 0x50, 0x55, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x55, 0x02, 0xaa, 0xa5, 0x50, 0xaa, 0x83, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff };
static const uint8_t image_data_Hamster_v12[1024] = {
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ████████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙███∙████
// ████████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████
// ████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████████████
// ████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙██████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙████████████████████████████████
// █████████████████████████████████████████████∙∙∙∙∙∙∙∙∙██████████████████████∙∙∙∙∙∙∙∙∙███████████████████████████████████████████
// █████████████████████████████████████████████∙∙∙∙∙∙∙∙███████████████████████∙∙∙∙∙∙∙∙∙███████████████████████████████████████████
// ███████████████████████████████████████████∙█∙∙█∙█∙█∙∙█████████████∙█████∙██∙█∙█∙█∙█∙███████████████████████████████████████████
// ████████████████████████████████████████∙∙∙∙∙██∙█∙█∙██∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙∙██████████████████████████████████████
// ████████████████████████████████████████∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙███████████████████████████████████████
// ████████████████████████████████████████∙∙█∙∙█∙█∙█∙██∙█∙█∙███∙███∙██████∙██∙█∙█∙█∙█∙█∙∙∙∙███████████████████████████████████████
// ████████████████████████████████∙∙███████∙∙∙∙█∙█∙█∙█∙█∙█∙██∙██∙█∙██∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙███████████████████████████████████████
// █████████████████████████████████∙███████████∙∙∙∙█∙█∙█∙██∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙█████████████∙∙████████████████████████████
// █████████████████████████████████████████████∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙█∙∙████████████∙∙█████████████████████████████
// █████████████████████████████████████████∙██∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙█∙███∙███████████████████████████████████████
// ████████████████████████████████████████∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙███████████████████████████████████████
// ████████████████████████████████████∙∙∙∙████∙██∙██∙██████████∙█∙█∙█████∙██∙████████∙████∙█∙∙∙∙██████████████████████████████████
// ████████████████████████████████████∙∙∙∙█∙█∙██∙██∙██∙██∙█∙█∙███∙█∙∙█∙█∙██∙██∙█∙█∙█∙██∙█∙█∙∙∙∙∙██████████████████████████████████
// ███████████████████████████████████∙∙█∙∙████∙███∙████∙████∙██∙█∙█∙███∙██∙████∙██∙███∙████∙█∙█∙██████████████████████████████████
// ███████████████████████████████∙∙∙∙∙█∙██∙█∙███∙███∙█∙██∙█∙██∙██████∙███∙██∙█∙██∙██∙███∙██∙█∙█∙∙∙∙∙∙█████████████████████████████
// ███████████████████████████████∙∙∙∙█∙█∙█∙██∙█∙██∙██∙██∙███∙███∙█████∙█∙████∙████∙██∙█∙█∙██∙█∙█∙∙∙∙██████████████████████████████
// ████████████████████████████████∙∙∙∙█∙█∙██████∙██∙███∙██∙███∙██∙█∙█∙████∙█∙██∙█∙████████∙█∙█∙█∙∙█∙██████████████████████████████
// ███████████████████████████████∙∙█∙∙█∙█∙█∙█∙█∙██∙██∙███∙██∙██∙████∙██∙█∙███∙█████∙█∙█∙███∙█∙█∙∙∙∙∙∙█████████████████████████████
// ███████████████████████████████∙∙∙∙∙█∙█∙█∙█∙███∙██∙██∙██∙██∙██∙█∙███∙███∙███∙█∙█∙██∙█∙█∙∙█∙█∙█∙█∙∙██████████████████████████████
// ████████████████████████████████∙∙█∙█∙█∙█∙█∙█∙███∙██∙██∙██∙██████∙███∙███∙█∙█████∙███∙█∙█∙█∙█∙∙∙∙∙██████████████████████████████
// ███████████████████████████████∙∙∙∙∙∙∙∙∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙∙∙∙█∙∙∙█∙█∙∙█∙█∙∙∙∙█∙█∙█∙█∙█∙∙∙∙█∙∙█∙∙█████████████████████████████
// ███████████████████████████████∙∙█∙∙∙∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙██∙█∙██∙█∙█∙█∙████∙█∙█∙█∙█∙█∙∙█∙∙∙∙∙∙██████████████████████████████
// ████████████████████████████████∙∙∙██∙∙█∙∙█∙∙██∙██∙█∙██∙███∙██∙███∙██∙███∙█∙∙∙█∙██∙██∙∙∙∙█∙∙█∙∙█∙∙██████████████████████████████
// ███████████████████████████████∙∙∙∙∙∙██∙█∙∙∙█∙███∙█∙█∙██∙█∙██∙██∙██∙██∙█∙████∙█∙█∙██∙∙∙█∙∙██∙█∙∙∙∙██████████████████████████████
// ███████████████████████████████∙∙█∙∙█∙█∙∙∙∙∙∙██∙█∙█∙█∙█████∙███∙██∙███████∙█∙█∙█∙██∙█∙∙∙∙█∙█∙█∙∙∙∙██████████████████████████████
// ████████████████████████████████∙∙∙∙█∙██∙███∙█∙█∙█∙█∙█∙∙∙∙███∙██∙███∙█∙█∙∙█∙█∙█∙█∙██∙███∙█∙█∙█∙∙∙∙██████████████████████████████
// ███████████████████████████████∙█∙██∙█∙∙█∙∙█∙█∙█∙█∙█∙█∙███∙█∙█∙██∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙∙█∙███∙██████████████████████████████
// ████████████████████████████████████∙∙∙∙█∙█∙█∙█∙█∙∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙∙█∙█∙██∙█∙∙∙∙∙██████████████████████████████████
// ████████████████████████████████████∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙█∙█∙∙█∙█∙∙∙∙∙██████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xef, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 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, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xf0, 0x07, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff,
0xff, 0xf0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xe9, 0x53, 0xff, 0xef, 0xb5, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0xac, 0x00, 0x00, 0x0a, 0xa8, 0x3f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0x50, 0x00,
0x00, 0x0a, 0xa8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x25, 0x5a, 0xbb, 0xbf, 0x6a, 0xa8, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x3f, 0x85, 0x55, 0x6d, 0x6a, 0xaa, 0xa8, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xf8, 0x55, 0x95,
0x55, 0x55, 0x07, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf8, 0x55, 0x55, 0x55, 0x55, 0x27, 0xff, 0x9f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xb5, 0x54, 0xaa, 0xaa, 0xaa, 0x97, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0x50, 0x15,
0x55, 0x05, 0x50, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xf6, 0xdf, 0xfa, 0xbe, 0xdf, 0xef, 0x43, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0xad, 0xb6, 0xae, 0x95, 0xb5, 0x5a, 0x83,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0xf7, 0x7b, 0xda,
0xbb, 0x7b, 0x77, 0xab, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x0b, 0x5d, 0xd6, 0xb7, 0xee, 0xd6, 0xdd, 0xa8, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x15, 0x6b, 0x6d, 0xdd, 0xf5, 0xef, 0x6a, 0xd4,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xfd, 0xbb, 0x76,
0xaf, 0x5a, 0xff, 0x54, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x4a, 0xab, 0x6e, 0xdb, 0xda, 0xef, 0xab, 0xa8, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x0a, 0xae, 0xdb, 0x6d, 0x77, 0x75, 0x6a, 0x55,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2a, 0xab, 0xb6, 0xdf,
0xbb, 0xaf, 0xba, 0xa8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x00, 0xaa, 0x55, 0x50, 0x8a, 0x50, 0xaa, 0x84, 0x9f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x42, 0x55, 0x55, 0x56, 0xb5, 0x5e, 0xaa, 0x90,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x26, 0xd6, 0xed,
0xdb, 0xa2, 0xd8, 0x49, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x06, 0x8b, 0xab, 0x5b, 0x6d, 0x7a, 0xb1, 0x34, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x4a, 0x06, 0xab, 0xee, 0xdf, 0xd5, 0x68, 0x54,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x75, 0x54, 0x3b,
0x75, 0x2a, 0xb7, 0x54, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xb4, 0x95, 0x55, 0xd5, 0xaa, 0xaa, 0xa9, 0x4b, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0xaa, 0x82, 0xaa, 0xaa, 0xa0, 0x56, 0x83,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x55, 0x02, 0x95,
0x55, 0x50, 0x52, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff };
static const uint8_t image_data_Hamster_v13[1024] = {
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// █████████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙███∙███
// █████████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙███████
// ████████████████████████████████████████∙∙∙∙∙∙∙∙∙██████████████████████∙∙∙∙∙∙∙∙∙█████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙███████████████
// ████████████████████████████████████████∙∙∙∙∙∙∙∙███████████████████████∙∙∙∙∙∙∙∙∙█████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙███████████████
// ██████████████████████████████████████∙█∙∙█∙█∙█∙∙█████████████∙█████∙██∙█∙█∙█∙█∙█████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙█████████████████████
// ███████████████████████████████████∙∙∙∙∙█∙█∙█∙██∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙∙████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙███████████████████████
// ███████████████████████████████████∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙█████∙∙∙∙∙∙∙∙███████████████████████████████
// ███████████████████████████████████∙∙█∙∙██∙█∙█∙█∙█∙█∙█∙█∙█∙█∙████∙█∙██∙█∙█∙█∙█∙█∙∙∙∙█████∙∙∙∙∙∙∙∙███████████████████████████████
// ████████████∙███████████████████████∙∙∙∙█∙█∙█∙█∙█∙█∙█████████∙█∙███∙█∙█∙█∙█∙█∙█∙∙∙█∙∙███████████████████████████████████████████
// ██████████∙████████████████████████∙∙∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙███∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙████████████████████████████████████████████
// ██████████████∙█████████████████████████∙∙∙∙█∙█∙█∙██∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙∙∙∙∙████████████████████████████████████████████████
// ██████████∙█████████████████████████████∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙██∙█∙█∙█∙█∙█∙█∙∙█∙████████████████████████████████████████████████
// ████████████∙█∙██████████████████████∙█∙∙█∙∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙∙∙███∙███████████████████████████∙███∙████████████
// ██████████∙████████████████████████∙∙∙∙∙█∙██∙█∙█∙∙∙∙∙∙█∙█∙█∙█∙█∙█∙█∙∙∙∙█∙█∙█∙███∙∙∙∙████████████████████████∙∙∙█∙█∙∙████████████
// ███████████∙∙█∙∙███████████████████∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙█∙█∙█∙∙∙█∙∙∙∙█████████████████████∙∙∙∙∙∙█∙█∙∙∙∙∙∙████████
// ██████████∙█∙██∙∙██████████████∙∙∙∙███████∙██∙██∙██████∙██∙█∙██∙██∙████∙███∙███∙███∙∙∙∙∙∙███████████████∙∙█∙█∙█∙█∙∙█∙∙∙∙∙∙██████
// ███████████∙██∙████████████████∙∙∙∙█∙█∙█∙██∙███∙██∙█∙█∙██∙█∙█∙██∙███∙███∙█∙███∙██∙███∙∙∙∙██████████████∙∙█∙█∙█∙█∙██∙████∙███████
// ██████████∙█∙█████████████████∙∙█∙∙██████∙███∙███∙██████∙█∙█∙█∙██∙███∙█∙████∙███∙██∙∙∙█∙██████████████∙∙███∙██∙██∙█∙█∙∙█∙∙∙█████
// ███████████∙∙█∙███████████∙∙∙∙∙█∙██∙█∙█∙██∙█∙██∙███∙█∙█∙███████∙██∙█∙███∙█∙██∙█∙██∙███∙█∙∙∙∙∙████████∙███∙∙█∙∙██∙∙██∙∙██∙█∙∙████
// ██████████∙█∙█████████████∙∙∙∙█∙█∙████∙██∙███∙██∙█∙███∙█████████∙████∙█████∙████∙███∙█∙█∙∙∙∙∙████████∙█∙∙███████∙████████∙█∙████
// ███████████∙██∙████████████∙∙∙∙█∙█∙∙█∙██∙██∙██∙████∙████∙█∙██∙█∙██∙█∙██∙█∙██∙█∙███∙██∙█∙█∙∙█∙████████∙██∙█∙█████∙∙█████∙█∙█∙████
// ██████████∙█∙█████████████∙∙█∙∙█∙█∙████∙████∙███∙█∙██∙█∙███∙████∙████∙██∙██∙███∙█∙██∙█∙█∙∙∙∙∙████████∙∙█∙█∙██████∙█████∙∙█∙∙████
// ██████████∙█∙█∙███████████∙∙∙∙∙█∙█∙█∙████∙█∙██∙████∙██∙██∙██∙█∙██∙█∙██∙██∙███∙█████∙█∙█∙█∙█∙∙████████∙██∙███████∙∙███████∙█∙████
// ███████████∙∙███∙██████████∙∙█∙█∙█∙██∙∙∙████∙██∙█∙██∙███∙██∙███∙████∙██∙███∙██∙█∙∙█∙█∙█∙█∙∙∙∙████████∙∙█∙███████∙∙██████∙█∙∙████
// ██████████∙█∙█∙███████████∙∙∙∙∙█∙██∙∙██∙█∙█∙██████∙███∙██∙███∙██∙█∙██∙███∙██∙███∙█∙█∙█∙█∙∙∙█∙████████∙∙█∙█∙█∙∙∙∙█∙███∙█∙█∙█∙████
// ██████████∙█∙█████████████∙∙█∙∙█∙∙∙██∙█∙██∙██∙█∙∙██∙█∙█∙██∙█∙█∙███∙███∙█∙█∙██∙█∙█∙█∙█∙█∙█∙∙∙∙████████∙∙█∙█∙██∙∙∙∙██████∙█∙█∙████
// ███████████∙██∙∙∙██████████∙∙∙∙∙∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙█∙∙████████∙█∙█∙██████████████∙█∙∙████
// █████████∙∙█∙█████████████∙∙∙∙█∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙∙∙∙∙████████∙∙█∙████████████████∙█∙████
// ██████████∙█∙∙█∙██████████∙∙█∙∙█∙█∙∙∙∙∙█∙██∙█∙█∙█∙██∙██∙██∙██∙███∙██∙██∙█∙█∙██∙█∙∙█∙∙█∙██∙∙█∙████████∙∙█∙█∙████████∙██∙∙█∙∙∙████
// ████████∙█∙█∙█∙████████████∙∙∙∙█∙██∙∙█∙∙██∙██∙█∙██∙██∙███∙████∙███∙███∙█∙█∙██∙██∙∙∙∙█∙█∙█∙∙∙∙████████∙∙█∙█∙██∙█████████∙██∙∙████
// █████████∙█∙∙█∙███████████∙∙∙∙∙█∙█∙∙∙∙∙█∙███∙█∙█∙███∙██∙███∙█∙██∙██∙█∙██∙█∙████∙∙█∙∙∙█∙█∙∙∙∙∙████████∙█∙█∙██████████████∙█∙∙████
// ████████∙█∙█∙∙████████████∙∙█∙∙█∙█∙███∙█∙█∙∙█∙█∙█∙∙█∙███∙█∙███∙██∙█∙█∙█∙█∙█∙∙∙██∙█∙██∙█∙█∙█∙∙████████∙∙█∙█∙█∙∙██∙∙██∙∙█∙█∙█∙████
// ████████∙█∙∙█∙∙████████████∙∙∙∙█∙██∙∙█∙█∙█∙█∙█∙█∙██∙█∙█████∙███∙███∙█∙█∙█∙██∙█∙█∙█∙█∙█∙█∙∙∙∙∙█████████∙∙█∙███∙█∙█∙█∙█∙██∙█∙█████
// ██████████∙█∙██∙██████████∙█∙██∙█∙∙██∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙∙██∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙∙█∙███∙█████████∙█∙█∙∙█∙█∙█∙█∙█∙█∙∙∙██████
// ██████████∙██∙█████████████████∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙██∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙██████████████∙∙█∙█∙█∙█∙█∙█∙█∙█∙███████
// ███████████████████████████████∙∙∙∙█∙█∙█∙█∙█∙∙∙∙∙∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x80, 0x00, 0x00, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0xff, 0xf8, 0x00, 0x00, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xfe, 0x00, 0xff, 0xf8,
0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x2a, 0x7f, 0xfd,
0xf6, 0xaa, 0xff, 0x80, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe0, 0xab, 0x00, 0x00, 0x01, 0x55, 0x07, 0x80, 0x00, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0xaa, 0x80, 0x00, 0x01, 0x55, 0x0f, 0x80,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0xd5, 0x55, 0x57,
0xad, 0x55, 0x0f, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff,
0xf0, 0xaa, 0xaf, 0xfa, 0xea, 0xaa, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xdf, 0xff, 0xff, 0xe2, 0xaa, 0xa5, 0x57, 0x55, 0x55, 0x0f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x0a, 0xb5, 0x54,
0xaa, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff,
0xff, 0x0a, 0xaa, 0xab, 0x55, 0x52, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf5, 0xff, 0xff, 0xfa, 0x4a, 0x95, 0x55, 0x52, 0xa8, 0xef, 0xff,
0xff, 0xfe, 0xef, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xe0, 0xb5, 0x02, 0xaa,
0xa1, 0x57, 0x0f, 0xff, 0xff, 0xf1, 0x4f, 0xff, 0xff, 0xe4, 0xff, 0xff,
0xe0, 0xaa, 0x85, 0x55, 0x41, 0x51, 0x0f, 0xff, 0xff, 0x81, 0x40, 0xff,
0xff, 0xd6, 0x7f, 0xfe, 0x1f, 0xdb, 0x7e, 0xd6, 0xde, 0xee, 0xe0, 0x7f,
0xff, 0x2a, 0x90, 0x3f, 0xff, 0xed, 0xff, 0xfe, 0x15, 0x6e, 0xd5, 0xab,
0x77, 0x5d, 0xb8, 0x7f, 0xfe, 0x55, 0x6f, 0x7f, 0xff, 0xd7, 0xff, 0xfc,
0x9f, 0xbb, 0xbf, 0x55, 0xba, 0xf7, 0x62, 0xff, 0xfc, 0xed, 0xa9, 0x1f,
0xff, 0xe5, 0xff, 0xc1, 0x6a, 0xd6, 0xea, 0xfe, 0xd7, 0x5a, 0xdd, 0x07,
0xfb, 0x93, 0x33, 0x4f, 0xff, 0xd7, 0xff, 0xc2, 0xbd, 0xbb, 0x5d, 0xff,
0x7b, 0xef, 0x75, 0x07, 0xfa, 0x7f, 0x7f, 0xaf, 0xff, 0xed, 0xff, 0xe1,
0x4b, 0x6d, 0xef, 0x5a, 0xd6, 0xb5, 0xda, 0x97, 0xfb, 0x5f, 0x3e, 0xaf,
0xff, 0xd7, 0xff, 0xc9, 0x5e, 0xf7, 0x5a, 0xef, 0x7b, 0x6e, 0xb5, 0x07,
0xf9, 0x5f, 0xbe, 0x4f, 0xff, 0xd5, 0xff, 0xc1, 0x57, 0xad, 0xed, 0xb5,
0xad, 0xbb, 0xea, 0xa7, 0xfb, 0x7f, 0x3f, 0xaf, 0xff, 0xe7, 0x7f, 0xe5,
0x58, 0xf6, 0xb7, 0x6e, 0xf6, 0xed, 0x2a, 0x87, 0xf9, 0x7f, 0x3f, 0x4f,
0xff, 0xd5, 0xff, 0xc1, 0x66, 0xaf, 0xdd, 0xbb, 0x5b, 0xb7, 0x55, 0x17,
0xf9, 0x50, 0xba, 0xaf, 0xff, 0xd7, 0xff, 0xc9, 0x1a, 0xda, 0x6a, 0xd5,
0xdd, 0x5a, 0xaa, 0x87, 0xf9, 0x58, 0x7e, 0xaf, 0xff, 0xec, 0x7f, 0xe0,
0x4a, 0xaa, 0xaa, 0xaa, 0x52, 0xaa, 0xa8, 0x27, 0xfa, 0xbf, 0xff, 0x4f,
0xff, 0x97, 0xff, 0xc2, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x07,
0xf9, 0x7f, 0xff, 0xaf, 0xff, 0xd2, 0xff, 0xc9, 0x41, 0x6a, 0xb6, 0xdb,
0xb6, 0xad, 0x25, 0x97, 0xf9, 0x5f, 0xec, 0x8f, 0xff, 0x55, 0xff, 0xe1,
0x64, 0xda, 0xdb, 0xbd, 0xdd, 0x5b, 0x0a, 0x87, 0xf9, 0x5b, 0xfe, 0xcf,
0xff, 0xa5, 0xff, 0xc1, 0x41, 0x75, 0x76, 0xeb, 0x6b, 0x5e, 0x45, 0x07,
0xfa, 0xbf, 0xff, 0x4f, 0xff, 0x53, 0xff, 0xc9, 0x5d, 0x4a, 0x97, 0x5d,
0xaa, 0xa3, 0x5a, 0xa7, 0xf9, 0x53, 0x32, 0xaf, 0xff, 0x49, 0xff, 0xe1,
0x65, 0x55, 0x6b, 0xee, 0xea, 0xb5, 0x55, 0x07, 0xfc, 0xba, 0xab, 0x5f,
0xff, 0xd6, 0xff, 0xd6, 0x9a, 0xaa, 0x95, 0x35, 0x55, 0x4a, 0xa9, 0x77,
0xfd, 0x4a, 0xaa, 0x3f, 0xff, 0xdb, 0xff, 0xfe, 0x0a, 0xa0, 0x6a, 0xaa,
0xaa, 0x0a, 0xa0, 0x7f, 0xfe, 0x55, 0x55, 0x7f, 0xff, 0xff, 0xff, 0xfe,
0x15, 0x50, 0x2a, 0xa5, 0x54, 0x0a, 0xa8, 0x7f, 0xff, 0x80, 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 };
static const uint8_t image_data_Hamster_v15[1024] = {
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
// ████████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙███∙████
// ████████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████
// ████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████████████
// ████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙██████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████∙∙∙∙∙∙∙∙████████████████████████████████
// █████████████████████████████████████████████∙∙∙∙∙∙∙∙∙██████████████████████∙∙∙∙∙∙∙∙∙███████████████████████████████████████████
// █████████████████████████████████████████████∙∙∙∙∙∙∙∙███████████████████████∙∙∙∙∙∙∙∙∙███████████████████████████████████████████
// ███████████████████████████████████████████∙█∙∙█∙█∙█∙∙█████████████∙█████∙██∙█∙█∙█∙█∙███████████████████████████████████████████
// ████████████████████████████████████████∙∙∙∙∙██∙█∙█∙██∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙∙████████████████████████████∙∙████████
// █████████████∙██████████████████████████∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙█████████████████████████████∙∙∙███████
// ███████████∙∙∙██████████████████████████∙∙█∙∙█∙█∙█∙██∙█∙█∙███∙███∙██████∙██∙█∙█∙█∙█∙█∙∙∙∙█████████████████████████████████∙█████
// █████████∙██████████████████████∙∙███████∙∙∙∙█∙█∙█∙█∙█∙█∙██∙██∙█∙██∙█∙∙█∙█∙█∙∙█∙█∙█∙█∙∙∙∙█████████████████████████████████∙█████
// █████████∙███████████████████████∙███████████∙∙∙∙█∙█∙∙█∙█∙█∙∙█∙█∙█∙█∙█∙∙█∙█∙∙█∙█∙∙∙∙∙█████████████∙∙████████████████∙∙████∙█████
// █████████∙████∙∙█████████████████████████████∙∙∙∙█∙█∙∙█∙█∙∙∙█∙█∙█∙█∙█∙█∙∙█∙∙█∙█∙█∙∙∙∙████████████∙∙████████████████∙██∙████∙████
// ████████∙███████∙████████████████████████∙██∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙█∙█∙█∙█∙████∙██████████████████████████∙███████∙████
// ████████∙███████∙███████████████████████∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙∙█∙█∙█∙█∙█∙█∙█∙∙∙∙█∙█∙█∙█∙█∙∙∙∙███████████████████████████∙██∙██∙∙████
// ████████∙∙██∙██∙████████████████████∙∙∙∙████∙██∙██∙████∙█∙████∙█∙█∙████∙█∙∙█∙██∙██∙█∙█∙██∙∙∙∙∙██████████████████████∙∙∙∙∙∙██████
// ██████████∙∙∙∙∙∙████████████████████∙∙∙∙█∙█∙██∙██∙██∙█∙∙██∙∙█∙█∙█∙█∙█∙██∙∙█∙█∙██∙██████∙█∙∙∙∙∙█████████████████████████∙████████
// ████████████∙██████████████████████∙∙█∙∙████∙███∙████∙██∙█∙∙███∙█∙████∙∙██∙█∙██∙██∙█∙█∙███∙█∙█████████████████████∙∙███∙████████
// ████████████∙███∙∙█████████████∙∙∙∙∙█∙██∙█∙███∙███∙█∙█∙█████∙██████∙█∙██∙███∙∙███∙███∙██∙█∙█∙█∙∙∙∙∙███████████████∙█∙█∙█████████
// █████████████∙█∙█∙█████████████∙∙∙∙█∙█∙██∙██∙██∙█∙██∙██∙█∙█∙█∙██∙█████∙██∙█∙██∙█∙██∙███∙██∙█∙∙∙∙∙∙████████████████∙∙∙∙██████████
// ██████████████∙∙∙███████████████∙∙∙∙█∙█∙██∙██∙████∙███∙███∙███∙███∙█∙██∙█████∙████∙██∙███∙█∙██∙∙∙∙██████████████████∙███████████
// ███████████████∙███████████████∙∙█∙∙█∙█∙███∙██∙█∙██∙███∙████∙██∙█∙███∙███∙█∙███∙█∙██∙██∙██∙█∙█∙∙█∙█████████████████∙████████████
// ████████████████∙██████████████∙∙∙∙∙█∙█∙∙∙█∙█████∙██∙█∙██∙█∙██████∙█∙██∙██∙██∙██∙████∙█∙█∙█∙█∙∙∙∙∙∙█████████████∙∙∙∙████████████
// ████████████████∙∙∙∙████████████∙∙█∙█∙███∙█∙█∙█∙██∙████∙██∙██∙█∙█∙████∙██∙██∙██∙██∙█∙█∙█∙█∙█∙█∙∙∙∙██████████████████████████████
// ███████████████████████████████∙∙∙∙∙∙∙∙∙∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙∙∙█∙∙██████████████████████████████
// ███████████████████████████████∙█∙∙∙∙∙∙∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙█∙██∙∙∙█∙∙∙∙██████████████████████████████
// ███████████████████████████████∙∙∙█∙███∙∙█∙∙█∙██∙█∙█∙██∙██∙██∙██∙███∙██∙██∙█∙█∙█∙██∙█∙∙█∙∙█∙█∙∙∙█∙∙█████████████████████████████
// ████████████████████████████████∙∙∙∙█∙∙█∙∙∙∙∙██∙██∙█∙█∙██∙██∙██∙██∙██∙██∙███∙█∙██∙███∙∙∙∙∙█∙█∙█∙∙∙██████████████████████████████
// ███████████████████████████████∙∙∙∙∙█∙██∙∙∙█∙███∙█∙█∙███∙████∙███∙██∙████∙██∙█∙█∙██∙█∙∙∙∙█∙█∙█∙∙∙∙██████████████████████████████
// ███████████████████████████████∙∙█∙∙██∙∙██∙█∙█∙∙█∙█∙█∙∙█∙█∙█∙██∙██∙███∙█∙█∙█∙█∙█∙█∙█∙███∙█∙█∙█∙∙∙∙██████████████████████████████
// ████████████████████████████████∙█∙█∙∙█∙█∙█∙█∙██∙█∙∙█∙█∙█∙███∙██∙██∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙∙█∙█∙█∙█∙█∙██████████████████████████████
// ████████████████████████████████████∙∙∙∙∙█∙█∙█∙∙█∙∙∙∙∙█∙█∙█∙∙█∙█∙█∙█∙█∙█∙█∙█∙∙∙∙∙█∙█∙█∙█∙█∙∙∙∙██████████████████████████████████
// ████████████████████████████████████∙∙∙∙█∙█∙█∙█∙█∙∙∙∙∙█∙█∙█∙█∙█∙█∙∙█∙█∙█∙█∙∙∙∙∙∙∙█∙█∙█∙█∙∙∙∙∙∙██████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
// ████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xef, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 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, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xf0, 0x07, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff,
0xff, 0xf0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xe9, 0x53, 0xff, 0xef, 0xb5, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0xac, 0x00, 0x00, 0x0a, 0xa8, 0x3f,
0xff, 0xff, 0xfc, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0x05, 0x50, 0x00,
0x00, 0x0a, 0xa8, 0x7f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xe3, 0xff, 0xff,
0xff, 0x25, 0x5a, 0xbb, 0xbf, 0x6a, 0xa8, 0x7f, 0xff, 0xff, 0xff, 0xdf,
0xff, 0xbf, 0xff, 0xff, 0x3f, 0x85, 0x55, 0x6d, 0x69, 0x52, 0xa8, 0x7f,
0xff, 0xff, 0xff, 0xdf, 0xff, 0xbf, 0xff, 0xff, 0xbf, 0xf8, 0x52, 0xa5,
0x54, 0xa5, 0x07, 0xff, 0xcf, 0xff, 0xf3, 0xdf, 0xff, 0xbc, 0xff, 0xff,
0xff, 0xf8, 0x52, 0x8a, 0xaa, 0x4a, 0x87, 0xff, 0x9f, 0xff, 0xed, 0xef,
0xff, 0x7f, 0x7f, 0xff, 0xff, 0xb5, 0x54, 0xaa, 0xaa, 0x8a, 0xaf, 0x7f,
0xff, 0xff, 0xef, 0xef, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0x05, 0x50, 0x15,
0x55, 0x0a, 0xa8, 0x7f, 0xff, 0xff, 0xf6, 0xcf, 0xff, 0x36, 0xff, 0xff,
0xf0, 0xf6, 0xde, 0xbd, 0x5e, 0x96, 0xd5, 0x83, 0xff, 0xff, 0xf0, 0x3f,
0xff, 0xc0, 0xff, 0xff, 0xf0, 0xad, 0xb4, 0xca, 0xab, 0x2b, 0x7e, 0x83,
0xff, 0xff, 0xfe, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xe4, 0xf7, 0x7b, 0x4e,
0xbc, 0xd6, 0xd5, 0xd7, 0xff, 0xff, 0xce, 0xff, 0xff, 0xf7, 0x3f, 0xfe,
0x0b, 0x5d, 0xd5, 0xf7, 0xeb, 0x73, 0xbb, 0x54, 0x1f, 0xff, 0xd5, 0xff,
0xff, 0xfa, 0xbf, 0xfe, 0x15, 0xb6, 0xb6, 0xab, 0x7d, 0xad, 0x6e, 0xd0,
0x3f, 0xff, 0xc3, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0x0a, 0xdb, 0xdd, 0xdd,
0xd6, 0xfb, 0xdb, 0xac, 0x3f, 0xff, 0xf7, 0xff, 0xff, 0xfe, 0xff, 0xfe,
0x4a, 0xed, 0x6e, 0xf6, 0xbb, 0xae, 0xb6, 0xd4, 0xbf, 0xff, 0xef, 0xff,
0xff, 0xff, 0x7f, 0xfe, 0x0a, 0x2f, 0xb5, 0xaf, 0xd6, 0xdb, 0x7a, 0xa8,
0x1f, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x2b, 0xaa, 0xde, 0xda,
0xbd, 0xb6, 0xd5, 0x54, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x00, 0x55, 0x52, 0xaa, 0xa5, 0x55, 0x55, 0x01, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xc4,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x2e, 0x4b, 0x56, 0xdb,
0x76, 0xd5, 0x69, 0x28, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x09, 0x06, 0xd5, 0xb6, 0xdb, 0x75, 0xb8, 0x2a, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x0b, 0x17, 0x57, 0x7b, 0xb7, 0xb5, 0x68, 0x54,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x4c, 0xd4, 0xa9, 0x56,
0xdd, 0x55, 0x57, 0x54, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x52, 0xab, 0x4a, 0xbb, 0x6a, 0xa9, 0x54, 0xaa, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x54, 0x82, 0xa5, 0x55, 0x50, 0x55, 0x43,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xaa, 0x82, 0xaa,
0x95, 0x40, 0x55, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff };
const unsigned char *bitmaps[] = { image_data_Hamster_v12,
image_data_Hamster_v11 };
void vTaskADC(void *pvParameters);
void vTaskPWM(void *pvParameters);
void vTaskHamList(void *pvParameters);
void vTaskHamShow(void *pvParameters);
void vTaskHamPassedOut(void *pvParameters);
void vTaskTime(void *pvParameters);
static void vHandlerTask(void *pvParameters);
/* The service routine for the interrupt. This is the interrupt that the task
will be synchronized with. */
static void IRAM_ATTR vButtonInterruptHandler(void);
static void IRAM_ATTR vProximityInterruptHandler(void);
const char *pcTextForADC = "ADC is running\r\n";
const char *pcTextForPWM = "PWM is running\t\n";
const char *pcTextForBrain = "Brain is running\t\n";
const char *pcTextForHamList = "Hamster is listening\t\n";
const char *pcTextForHamShow = "Hamster is showing\t\n";
const char *pcTextTime = "Time is adquiring\t\n";
QueueHandle_t xQueueSETPOINT_TEMP;
QueueHandle_t xQueueSETPOINT_TIME;
SemaphoreHandle_t xBinarySemaphore_ToListen;
SemaphoreHandle_t xBinarySemaphore_ToShowProx;
SemaphoreHandle_t xCountingSemaphore;
const uint8_t interruptPin = 2;
int16_t sBuffer[bufferLen];
TaskHandle_t taskListHandle;
TaskHandle_t taskShowHandle;
// Tempo da última interruption (Debounce Circuit)
TickType_t xLastIntTime;
void setup(void) {
Serial.begin(115200);
//-----------------------WI-FI-------------------
Serial.println("\nEU vou configurar a net");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
vTaskDelay(1000);
Serial.println("Connecting to WiFi...");
}
timeClient.begin();
vTaskDelay(100);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;)
; // Don't proceed, loop forever
}
timeClient.update();
Serial.println(timeClient.getFormattedTime());
//--------------------DISPLAY---------------------
display.clearDisplay();
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
//display.display();
//delay(2000); // Pause for 2 seconds
vTaskDelay(10);
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE);
// Display static text
display.println("Waiting for action");
vTaskDelay(10);
display.setCursor(0, 10);
vTaskDelay(10);
display.drawBitmap(0, 20, image_data_Hamster_v11, 128, 64, 1);
vTaskDelay(10);
display.display();
//--------------------PROXIMITY SENSOR-----------------------
pinMode(APDS9930_INT, INPUT);
// Initialize Serial port
Serial.println();
Serial.println(F("------------------------------"));
Serial.println(F("APDS-9930 - ProximityInterrupt"));
Serial.println(F("------------------------------"));
// Initialize interrupt service routine
attachInterrupt(digitalPinToInterrupt(APDS9930_INT),
&vProximityInterruptHandler, FALLING);
// Initialize APDS-9930 (configure I2C and initial values)
if (apds.init()) {
Serial.println(F("APDS-9930 initialization complete"));
} else {
Serial.println(F("Something went wrong during APDS-9930 init!"));
}
// Adjust the Proximity sensor gain
if (!apds.setProximityGain(PGAIN_2X)) {
Serial.println(F("Something went wrong trying to set PGAIN"));
}
// Set proximity interrupt thresholds
if (!apds.setProximityIntLowThreshold(PROX_INT_LOW)) {
Serial.println(F("Error writing low threshold"));
}
if (!apds.setProximityIntHighThreshold(PROX_INT_HIGH)) {
Serial.println(F("Error writing high threshold"));
}
// Start running the APDS-9930 proximity sensor (interrupts)
if (apds.enableProximitySensor(true)) {
Serial.println(F("Proximity sensor is now running"));
} else {
Serial.println(F("Something went wrong during sensor init!"));
}
// Start running the APDS-9930 light sensor (no interrupts)
if (apds.enableLightSensor(false)) {
Serial.println(F("Light sensor is now running"));
} else {
Serial.println(F("Something went wrong during light sensor init!"));
}
#ifdef DUMP_REGS
/* Register dump */
uint8_t reg;
uint8_t val;
for (reg = 0x00; reg <= 0x19; reg++) {
if ((reg != 0x10) &&
(reg != 0x11))
{
apds.wireReadDataByte(reg, val);
Serial.print(reg, HEX);
Serial.print(": 0x");
Serial.println(val, HEX);
}
}
apds.wireReadDataByte(0x1E, val);
Serial.print(0x1E, HEX);
Serial.print(": 0x");
Serial.println(val, HEX);
#endif
//-------------------FREE RTOS START-----------------------------
//TASKS
//QUEUES
//INTERRUPTS
vTaskPrioritySet(NULL, configMAX_PRIORITIES - 1);
vSemaphoreCreateBinary(xBinarySemaphore_ToListen);
vSemaphoreCreateBinary(xBinarySemaphore_ToShowProx);
xCountingSemaphore = xSemaphoreCreateCounting(5, 0);
pinMode(digitalPinToInterrupt(interruptPin), INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin),
&vProximityInterruptHandler, FALLING);
xTaskCreatePinnedToCore(vTaskADC, "ADC", 1024, (void*) pcTextForADC, 4,
NULL, 0);
xTaskCreatePinnedToCore(vTaskPWM, "PWM", 1024, (void*) pcTextForPWM, 1,
NULL, 1);
xTaskCreatePinnedToCore(vTaskHamList, "HamstList", 2 * 1024,
(void*) pcTextForHamList, 3, &taskListHandle, 1);
xTaskCreatePinnedToCore(vTaskHamShow, "HamstShow", 4 * 1024,
(void*) pcTextForHamShow, 4, &taskShowHandle, 1);
xTaskCreatePinnedToCore(vTaskHamPassedOut, "HamstPassedOut", 2 * 1024,
(void*) pcTextForHamShow, 5, NULL, 1);
xTaskCreatePinnedToCore(vTaskTime, "Time", 2 * 1024, (void*) pcTextTime, 2,
NULL, 0);
xQueueSETPOINT_TEMP = xQueueCreate(1, sizeof(float));
xQueueSETPOINT_TIME = xQueueCreate(1, sizeof(String));
xLastIntTime = xTaskGetTickCount();
//--------------------PWM START-----------------------------
ledcSetup(ledChannel, freq, resolution);
ledcAttachPin(LED_PIN, ledChannel);
//-------------------SEMAPHORE INITIAL TAKE-----------------
xSemaphoreTake(xBinarySemaphore_ToListen, portMAX_DELAY);
xSemaphoreTake(xBinarySemaphore_ToShowProx, portMAX_DELAY);
ledcSetup(ledChannel, freq, resolution);
ledcAttachPin(LED_PIN, ledChannel);
}
void vTaskADC(void *pvParameters) {
char *pcTaskName;
TickType_t xLastWakeTime;
int analog_value = 0;
float analog_voltage = 0;
int lValueToSend;
float milliVolt = 0;
float tempC = 0;
pcTaskName = (char*) pvParameters;
analogReadResolution(ADC_RESOLUTION);
xLastWakeTime = xTaskGetTickCount();
for (;;) {
Serial.print(pcTaskName);
analog_value = analogRead(PIN_LM35);
Serial.print("ADC value: ");
Serial.println(analog_value);
// convert the ADC value to voltage in millivolt
milliVolt = analog_value * (ADC_VREF_mV / ADC_RESOLUTION_2);
// convert the voltage to the temperature in °C
tempC = milliVolt;
//tempC = milliVolt /10;
Serial.print("Temperatura:");
Serial.println(tempC);
xQueueOverwrite(xQueueSETPOINT_TEMP, &tempC);
vTaskDelayUntil(&xLastWakeTime, (500 / portTICK_PERIOD_MS));
}
}
void vTaskTime(void *pvParameters) {
char *pcTaskName;
TickType_t xLastWakeTime;
int lValueToSend;
pcTaskName = (char*) pvParameters;
analogReadResolution(ADC_RESOLUTION);
xLastWakeTime = xTaskGetTickCount();
for (;;) {
Serial.print(pcTaskName);
timeClient.update();
String time = timeClient.getFormattedTime();
Serial.println(time);
xQueueOverwrite(xQueueSETPOINT_TIME, &time);
vTaskDelayUntil(&xLastWakeTime, (500 / portTICK_PERIOD_MS));
}
}
void vTaskPWM(void *pvParameters) {
char *pcTaskName;
TickType_t xLastWakeTime;
int freq = 5000;
int ledChannel = 5;
int resolution = 10;
int dutyCycle = 0;
int lReceivedValue;
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
pcTaskName = (char*) pvParameters;
ledcSetup(ledChannel, freq, resolution);
ledcAttachPin(LED_PIN, ledChannel);
xLastWakeTime = xTaskGetTickCount();
for (;;) {
Serial.print(pcTaskName);
for (int dutyCycle = 0; dutyCycle <= pow(2, resolution); dutyCycle++) {
ledcWrite(ledChannel, dutyCycle);
vTaskDelay(1024 / pow(2, resolution));
}
for (int dutyCycle = pow(2, resolution); dutyCycle >= 0; dutyCycle--) {
ledcWrite(ledChannel, dutyCycle);
vTaskDelay(1024 / pow(2, resolution));
}
vTaskDelayUntil(&xLastWakeTime, (2000 / portTICK_PERIOD_MS));
}
}
static void IRAM_ATTR vProximityInterruptHandler(void) {
static signed portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
/* Serial.println("\n\nHouve interrupcao no proximity\n\n");*/
/* 'Give' the semaphore to unblock the task. */
xSemaphoreGiveFromISR(xBinarySemaphore_ToShowProx,
(signed portBASE_TYPE*)&xHigherPriorityTaskWoken);
/*Give to a counting semaphore */
xSemaphoreGiveFromISR(xCountingSemaphore,
(BaseType_t* )&xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken == pdTRUE) {
/* Giving the semaphore unblocked a task, and the priority of the
unblocked task is higher than the currently running task - force
a context switch to ensure that the interrupt returns directly to
the unblocked (higher priority) task.
NOTE: The syntax for forcing a context switch is different depending
on the port being used. Refer to the examples for the port you are
using for the correct method to use! */
portYIELD_FROM_ISR();
// vPortYield();
}
}
void vTaskHamList(void *pvParameters) {
char *pcTaskName;
TickType_t xLastWakeTime;
long lReceivedValue;
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
int ADC_received = 0;
pcTaskName = (char*) pvParameters;
static portBASE_TYPE run;
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
int i = 0;
int j = 0;
for (;;) {
Serial.print(pcTaskName);
run = xSemaphoreTake(xBinarySemaphore_ToListen,
(5000 / portTICK_PERIOD_MS));
//Serial.print("Brain vai correr ");
if (run == pdPASS) {
vTaskDelay((5000 / portTICK_PERIOD_MS));
//Two frames for the image
for (int i = 0; i < 2; i++) {
display.clearDisplay();
vTaskDelay(10);
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE);
vTaskDelay(10);
// Display static text
display.println("Waiting action");
vTaskDelay(10);
display.setCursor(0, 10);
vTaskDelay(10);
//for (int i = 0; i < 2; i++) {
//display.clearDisplay();
//Critical sections on the display sections so the image doesnt get corrupted
vTaskEnterCritical(&mux);
display.drawBitmap(0, 20, bitmaps[i], 128, 64, 1);
vTaskExitCritical(&mux);
//}
vTaskDelay(10);
display.display();
vTaskDelay((500 / portTICK_PERIOD_MS));
}
} else {
for (int i = 0; i < 2; i++) {
display.clearDisplay();
vTaskDelay(10);
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE);
vTaskDelay(10);
// Display static text
display.println("Waiting action");
vTaskDelay(10);
display.setCursor(0, 10);
vTaskDelay(10);
//for (int i = 0; i < 2; i++) {
//display.clearDisplay();
//Critical sections on the display sections so the image doesnt get corrupted
vTaskEnterCritical(&mux);
display.drawBitmap(0, 20, bitmaps[i], 128, 64, 1);
vTaskExitCritical(&mux);
//}
vTaskDelay(10);
display.display();
vTaskDelay((500 / portTICK_PERIOD_MS));
}
}
}
}
void vTaskHamShow(void *pvParameters) {
char *pcTaskName;
TickType_t xLastWakeTime;
float lReceivedValue;
String time;
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
int ADC_received = 0;
pcTaskName = (char*) pvParameters;
static portBASE_TYPE run;
static signed portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
for (;;) {
Serial.print(pcTaskName);
xQueueReceive(xQueueSETPOINT_TEMP, &lReceivedValue, 0);
xQueueReceive(xQueueSETPOINT_TIME, &time, 0);
//SEMAPHORE FOR BUTTON AND PROXIMITY SENSOR
run = xSemaphoreTake(xBinarySemaphore_ToShowProx, pdMS_TO_TICKS( 500 ));
//Serial.print("Brain vai correr ");
if (run == pdPASS) {
//PROXIMITY SENSOR
if (!apds.readProximity(proximity_data)) {
Serial.println("Error reading proximity value");
} else {
Serial.print("Proximity detected! Level: ");
Serial.print(proximity_data);
Serial.print(" ");
}
apds.readAmbientLightLux(ambient_light);
// Read the light levels (ambient, red, green, blue)
if (!apds.readAmbientLightLux(ambient_light)
|| !apds.readCh0Light(ch0) || !apds.readCh1Light(ch1)) {
Serial.println(F("Error reading light values"));
} else {
Serial.print(F("Ambient: "));
Serial.print(ambient_light);
Serial.print(F(" Ch0: "));
Serial.print(ch0);
Serial.print(F(" Ch1: "));
Serial.println(ch1);
}
// Reset flag and clear APDS-9930 interrupt (IMPORTANT!)
if (!apds.clearProximityInt()) {
Serial.println("Error clearing interrupt");
}
//DISPLAY INFO
Serial.println(lReceivedValue);
Serial.println(time);
display.clearDisplay();
vTaskDelay(10);
Serial.println("------INTERRUPT ON HAMSTER");
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE);
vTaskDelay(10);
// Display static text
display.print("Temperature :");
display.print(lReceivedValue);
display.println(" C");
vTaskDelay(10);
display.setCursor(0, 10);
display.print("Time :");
display.println(time);
vTaskDelay(10);
//Critical sections on the display sections so the image doesnt get corrupted
vTaskEnterCritical(&mux);
display.drawBitmap(0, 20, image_data_Hamster_v13, 128, 64, 1);
vTaskExitCritical(&mux);
vTaskDelay(10);
display.display();
vTaskDelay((3000 / portTICK_PERIOD_MS));
xSemaphoreGiveFromISR(xBinarySemaphore_ToListen,
(signed portBASE_TYPE*)&xHigherPriorityTaskWoken);
}
vTaskDelayUntil(&xLastWakeTime, (3000 / portTICK_PERIOD_MS));
}
}
void vTaskHamPassedOut(void *pvParameters) {
char *pcTaskName;
TickType_t xLastWakeTime;
float lReceivedValue;
String time;
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
int ADC_received = 0;
pcTaskName = (char*) pvParameters;
static portBASE_TYPE run;
static signed portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
for (;;) {
Serial.print(pcTaskName);
if (uxSemaphoreGetCount(xCountingSemaphore) == 5) {
Serial.print("The counting semaphore has this many counts:");
Serial.println(uxSemaphoreGetCount(xCountingSemaphore));
run = xSemaphoreTake(xCountingSemaphore, portMAX_DELAY);
if (run == pdPASS) {
display.clearDisplay();
vTaskDelay(10);
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE);
vTaskDelay(10);
display.print("I passed out...");
//Critical sections on the display sections so the image doesnt get corrupted
vTaskEnterCritical(&mux);
display.drawBitmap(0, 20, image_data_Hamster_v15, 128, 64, 1);
vTaskExitCritical(&mux);
vTaskDelay(10);
display.display();
//Counting semaphore reset
vSemaphoreDelete(xCountingSemaphore);
xCountingSemaphore = xSemaphoreCreateCounting(5, 0);
/*
* The hamster passed out, so i only want the other 2 tasks that access the oled and show images,
* to only show images after a couple of seconds.
*/
vTaskSuspend(taskShowHandle);
vTaskSuspend(taskListHandle);
vTaskDelay((3000 / portTICK_PERIOD_MS));
vTaskResume(taskShowHandle);
vTaskResume(taskListHandle);
}
}
vTaskDelayUntil(&xLastWakeTime, (3000 / portTICK_PERIOD_MS));
}
}
void loop() {
vTaskDelete( NULL);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment