mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 05:06:39 +01:00
add support for lilygo t-panel (#370)
* add support for lilygo t-panel add support for lilygo t-panel (the rs485 version with an ESP32-S3 and ESP32-G2) https://www.lilygo.cc/products/t-panel-s3 * refactor * moved gfx library to lib2 folder and removed examples * removed lib2\Arduino_GFX-1.3.7 and switch to moononournation/GFX Library for Arduino@^1.4.9 * added lilygo lib2\Arduino_GFX-1.3.7 back and removed all unused files. went from 166 files to 15 files!
This commit is contained in:
42
ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/compile.ps1
Normal file
42
ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/compile.ps1
Normal file
@@ -0,0 +1,42 @@
|
||||
&(Join-Path $env:USERPROFILE '\esp\esp-idf\export.ps1')
|
||||
|
||||
idf.py fullclean
|
||||
|
||||
idf.py build
|
||||
|
||||
#python -m esptool -p COM8 -b 460800 --before default_reset --after hard_reset --chip esp32c6 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 build\bootloader\bootloader.bin 0x8000 build\partition_table\partition-table.bin 0x10000 build\OpenEPaperLink_esp32_C6.bin
|
||||
|
||||
|
||||
#idf.py -p COM8 flash
|
||||
|
||||
|
||||
#esptool.py v4.7.0
|
||||
#Serial port COM8
|
||||
#Connecting...
|
||||
#Chip is ESP32-C6 (QFN40) (revision v0.0)
|
||||
#Features: WiFi 6, BT 5, IEEE802.15.4
|
||||
#Crystal is 40MHz
|
||||
#MAC: 40:4c:ca:ff:fe:47:b4:f0
|
||||
#BASE MAC: 40:4c:ca:47:b4:f0
|
||||
#MAC_EXT: ff:fe
|
||||
#Uploading stub...
|
||||
#Running stub...
|
||||
#Stub running...
|
||||
#Changing baud rate to 460800
|
||||
#Changed.
|
||||
#Configuring flash size...
|
||||
#Auto-detected Flash size: 4MB
|
||||
#Flash will be erased from 0x00000000 to 0x00005fff...
|
||||
#Flash will be erased from 0x00008000 to 0x00008fff...
|
||||
#Flash will be erased from 0x00010000 to 0x00051fff...
|
||||
#Compressed 22336 bytes to 13474...
|
||||
#Wrote 22336 bytes (13474 compressed) at 0x00000000 in 0.3 seconds (effective 624.9 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 3072 bytes to 104...
|
||||
#Wrote 3072 bytes (104 compressed) at 0x00008000 in 0.1 seconds (effective 361.3 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 268624 bytes to 140956...
|
||||
#Wrote 268624 bytes (140956 compressed) at 0x00010000 in 1.2 seconds (effective 1725.6 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Leaving...
|
||||
#Hard resetting via RTS pin...
|
||||
8
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/.gitignore
vendored
Normal file
8
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
build
|
||||
*.axf
|
||||
# Allow
|
||||
!*.bin
|
||||
|
||||
.vscode
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
6
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/CMakeLists.txt
Normal file
6
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(OpenEPaperLink_esp32_C6)
|
||||
45
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/compile.ps1
Normal file
45
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/compile.ps1
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
#| Function | ESP32H2 Pin | ESP32S3 Pin
|
||||
#| :--------------------------------: | :-------------------: | :------------------
|
||||
#| Activate The BOOT Mode Of ESP32H2 | ESP32H2_IO9 | ESP32S3_IO33
|
||||
#| Reset ESP32H2 | ESP32H2_Pin Number 8 | ESP32S3_IO34
|
||||
#| Uart | ESP32H2_TX_IO24 | ESP32S3_RX_IO48
|
||||
#| Uart | ESP32H2_RX_IO23 | ESP32S3_TX_IO47
|
||||
|
||||
&(Join-Path $env:USERPROFILE '\esp\esp-idf\export.ps1')
|
||||
|
||||
idf.py fullclean
|
||||
|
||||
idf.py build
|
||||
|
||||
#python -m esptool -p COM11 -b 460800 --before default_reset --after hard_reset --chip esp32h2 write_flash --flash_mode dio --flash_size detect --flash_freq 48m 0x0 build\bootloader\bootloader.bin 0x8000 build\partition_table\partition-table.bin 0x10000 build\OpenEPaperLink_esp32_H2.bin
|
||||
|
||||
|
||||
#idf.py -p COM8 flash
|
||||
|
||||
|
||||
#Chip is ESP32-H2 (revision v0.1)
|
||||
#Features: BLE, IEEE802.15.4
|
||||
#Crystal is 32MHz
|
||||
#MAC: 74:4d:bd:ff:fe:63:84:e8
|
||||
#BASE MAC: 74:4d:bd:63:84:e8
|
||||
#MAC_EXT: ff:fe
|
||||
#Uploading stub...
|
||||
#Running stub...
|
||||
#Stub running...
|
||||
#Changing baud rate to 460800
|
||||
#Changed.
|
||||
#Configuring flash size...
|
||||
#Auto-detected Flash size: 4MB
|
||||
#Flash will be erased from 0x00000000 to 0x00005fff...
|
||||
#Flash will be erased from 0x00008000 to 0x00008fff...
|
||||
#Flash will be erased from 0x00010000 to 0x0004dfff...
|
||||
#Compressed 22080 bytes to 13385...
|
||||
#Wrote 22080 bytes (13385 compressed) at 0x00000000 in 0.3 seconds (effective 511.5 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 3072 bytes to 104...
|
||||
#Wrote 3072 bytes (104 compressed) at 0x00008000 in 0.1 seconds (effective 309.1 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 253952 bytes to 133359...
|
||||
#Wrote 253952 bytes (133359 compressed) at 0x00010000 in 1.9 seconds (effective 1098.1 kbit/s)...
|
||||
#Hash of data verified.
|
||||
@@ -0,0 +1,9 @@
|
||||
idf_component_register( SRCS
|
||||
SRCS "utils.c"
|
||||
SRCS "second_uart.c"
|
||||
SRCS "radio.c"
|
||||
SRCS "SubGigRadio.c"
|
||||
SRCS "cc1101_radio.c"
|
||||
SRCS "led.c"
|
||||
SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
104
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/Kconfig.projbuild
Normal file
104
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/Kconfig.projbuild
Normal file
@@ -0,0 +1,104 @@
|
||||
menu "OEPL Hardware config"
|
||||
|
||||
choice OEPL_HARDWARE_PROFILE
|
||||
prompt "Hardware profile"
|
||||
default OEPL_HARDWARE_PROFILE_DEFAULT
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_DEFAULT
|
||||
bool "Default"
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_POE_AP
|
||||
bool "PoE-AP"
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_CUSTOM
|
||||
bool "Custom"
|
||||
|
||||
endchoice
|
||||
|
||||
config OEPL_HARDWARE_UART_TX
|
||||
depends on OEPL_HARDWARE_PROFILE_CUSTOM
|
||||
int "GPIO - UART TX"
|
||||
default 3
|
||||
|
||||
config OEPL_HARDWARE_UART_RX
|
||||
depends on OEPL_HARDWARE_PROFILE_CUSTOM
|
||||
int "GPIO - UART RX"
|
||||
default 2
|
||||
|
||||
config OEPL_SUBGIG_SUPPORT
|
||||
bool "Enable SubGhz Support"
|
||||
default "n"
|
||||
|
||||
menu "CC1101 Configuration"
|
||||
depends on OEPL_SUBGIG_SUPPORT
|
||||
|
||||
config GPIO_RANGE_MAX
|
||||
int
|
||||
default 33 if IDF_TARGET_ESP32
|
||||
default 46 if IDF_TARGET_ESP32S2
|
||||
default 48 if IDF_TARGET_ESP32S3
|
||||
default 18 if IDF_TARGET_ESP32C2
|
||||
default 19 if IDF_TARGET_ESP32C3
|
||||
default 30 if IDF_TARGET_ESP32C6
|
||||
default 30 if IDF_TARGET_ESP32H2
|
||||
|
||||
config MISO_GPIO
|
||||
int "CC1101 MISO GPIO"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 7
|
||||
help
|
||||
Pin Number to be used as the MISO SPI signal.
|
||||
|
||||
config SCK_GPIO
|
||||
int "CC1101 SCK GPIO"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 0
|
||||
help
|
||||
Pin Number to be used as the SCK SPI signal.
|
||||
|
||||
config MOSI_GPIO
|
||||
int "CC1101 MOSI GPIO"
|
||||
default 1
|
||||
help
|
||||
Pin Number to be used as the MOSI SPI signal.
|
||||
|
||||
config CSN_GPIO
|
||||
int "CC1101 CSN GPIO"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 4
|
||||
help
|
||||
Pin Number to be used as the CSN SPI signal.
|
||||
|
||||
config GDO0_GPIO
|
||||
int "CC1101 GDO0 GPIO"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 5
|
||||
help
|
||||
Pin Number to be used as the GDO0 signal.
|
||||
|
||||
config GDO2_GPIO
|
||||
int "CC1101 GDO2 GPIO"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 6
|
||||
help
|
||||
Pin Number to be used as the GDO2 signal.
|
||||
|
||||
choice SPI_HOST
|
||||
prompt "SPI peripheral that controls this bus"
|
||||
default SPI2_HOST
|
||||
help
|
||||
Select SPI peripheral that controls this bus.
|
||||
config SPI2_HOST
|
||||
bool "SPI2_HOST"
|
||||
help
|
||||
Use SPI2_HOST. This is also called HSPI_HOST.
|
||||
config SPI3_HOST
|
||||
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
bool "SPI3_HOST"
|
||||
help
|
||||
USE SPI3_HOST. This is also called VSPI_HOST
|
||||
endchoice
|
||||
endmenu
|
||||
endmenu
|
||||
|
||||
|
||||
562
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/SubGigRadio.c
Normal file
562
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/SubGigRadio.c
Normal file
@@ -0,0 +1,562 @@
|
||||
#include "sdkconfig.h"
|
||||
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include <driver/spi_master.h>
|
||||
#include <driver/gpio.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "radio.h"
|
||||
#include "proto.h"
|
||||
#include "cc1101_radio.h"
|
||||
#include "SubGigRadio.h"
|
||||
|
||||
void DumpHex(void *AdrIn,int Len);
|
||||
|
||||
#define LOGE(format, ... ) \
|
||||
printf("%s#%d: " format,__FUNCTION__,__LINE__,## __VA_ARGS__)
|
||||
|
||||
#if 0
|
||||
#define LOG(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOG_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
#define LOG_HEX(x,y) DumpHex(x,y)
|
||||
#else
|
||||
#define LOG(format, ... )
|
||||
#define LOG_RAW(format, ... )
|
||||
#define LOG_HEX(x,y)
|
||||
#endif
|
||||
|
||||
|
||||
// SPI Stuff
|
||||
#if CONFIG_SPI2_HOST
|
||||
#define HOST_ID SPI2_HOST
|
||||
#elif CONFIG_SPI3_HOST
|
||||
#define HOST_ID SPI3_HOST
|
||||
#endif
|
||||
|
||||
// Address Config = No address check
|
||||
// Base Frequency = xxx.xxx
|
||||
// CRC Enable = false
|
||||
// Carrier Frequency = 915.000000
|
||||
// Channel Number = 0
|
||||
// Channel Spacing = 199.951172
|
||||
// Data Rate = 1.19948
|
||||
// Deviation = 5.157471
|
||||
// Device Address = 0
|
||||
// Manchester Enable = false
|
||||
// Modulated = false
|
||||
// Modulation Format = ASK/OOK
|
||||
// PA Ramping = false
|
||||
// Packet Length = 255
|
||||
// Packet Length Mode = Reserved
|
||||
// Preamble Count = 4
|
||||
// RX Filter BW = 58.035714
|
||||
// Sync Word Qualifier Mode = No preamble/sync
|
||||
// TX Power = 10
|
||||
// Whitening = false
|
||||
// Rf settings for CC1110
|
||||
const RfSetting gCW[] = {
|
||||
{CC1101_PKTCTRL0,0x22}, // PKTCTRL0: Packet Automation Control
|
||||
{CC1101_FSCTRL1,0x06}, // FSCTRL1: Frequency Synthesizer Control
|
||||
{CC1101_MDMCFG4,0xF5}, // MDMCFG4: Modem configuration
|
||||
{CC1101_MDMCFG3,0x83}, // MDMCFG3: Modem Configuration
|
||||
{CC1101_MDMCFG2,0xb0}, // MDMCFG2: Modem Configuration
|
||||
{CC1101_DEVIATN,0x15}, // DEVIATN: Modem Deviation Setting
|
||||
{CC1101_MCSM0,0x18}, // MCSM0: Main Radio Control State Machine Configuration
|
||||
{CC1101_FOCCFG,0x17}, // FOCCFG: Frequency Offset Compensation Configuration
|
||||
{CC1101_FSCAL3,0xE9}, // FSCAL3: Frequency Synthesizer Calibration
|
||||
{CC1101_FSCAL2,0x2A}, // FSCAL2: Frequency Synthesizer Calibration
|
||||
{CC1101_FSCAL1,0x00}, // FSCAL1: Frequency Synthesizer Calibration
|
||||
{CC1101_FSCAL0,0x1F}, // FSCAL0: Frequency Synthesizer Calibration
|
||||
{CC1101_TEST1,0x31}, // TEST1: Various Test Settings
|
||||
{CC1101_TEST0,0x09}, // TEST0: Various Test Settings
|
||||
{0xff,0} // end of table
|
||||
};
|
||||
|
||||
|
||||
// Set Base Frequency to 865.999634
|
||||
const RfSetting g866Mhz[] = {
|
||||
{CC1101_FREQ2,0x21}, // FREQ2: Frequency Control Word, High Byte
|
||||
{CC1101_FREQ1,0x4e}, // FREQ1: Frequency Control Word, Middle Byte
|
||||
{CC1101_FREQ0,0xc4}, // FREQ0: Frequency Control Word, Low Byte
|
||||
{0xff,0} // end of table
|
||||
};
|
||||
|
||||
// Set Base Frequency to 863.999756
|
||||
const RfSetting g864Mhz[] = {
|
||||
{CC1101_FREQ2,0x21}, // FREQ2: Frequency Control Word, High Byte
|
||||
{CC1101_FREQ1,0x3b}, // FREQ1: Frequency Control Word, Middle Byte
|
||||
{CC1101_FREQ0,0x13}, // FREQ0: Frequency Control Word, Low Byte
|
||||
{0xff,0} // end of table
|
||||
};
|
||||
|
||||
// Set Base Frequency to 902.999756
|
||||
const RfSetting g903Mhz[] = {
|
||||
{CC1101_FREQ2,0x22}, // FREQ2: Frequency Control Word, High Byte
|
||||
{CC1101_FREQ1,0xbb}, // FREQ1: Frequency Control Word, Middle Byte
|
||||
{CC1101_FREQ0,0x13}, // FREQ0: Frequency Control Word, Low Byte
|
||||
{0xff,0} // end of table
|
||||
};
|
||||
|
||||
|
||||
// Seet Base Frequency to 915.000000
|
||||
const RfSetting g915Mhz[] = {
|
||||
{CC1101_FREQ2,0x23}, // FREQ2: Frequency Control Word, High Byte
|
||||
{CC1101_FREQ1,0x31}, // FREQ1: Frequency Control Word, Middle Byte
|
||||
{CC1101_FREQ0,0x3B}, // FREQ0: Frequency Control Word, Low Byte
|
||||
{0xff,0} // end of table
|
||||
};
|
||||
|
||||
// Address Config = No address check
|
||||
// Base Frequency = 901.934937 (adjusted to compensate for the crappy crystal on the CC1101 board)
|
||||
// CRC Enable = true
|
||||
// Carrier Frequency = 901.934937
|
||||
// Channel Number = 0
|
||||
// Channel Spacing = 199.951172
|
||||
// Data Rate = 38.3835
|
||||
// Deviation = 20.629883
|
||||
// Device Address = ff
|
||||
// Manchester Enable = false
|
||||
// Modulated = true
|
||||
// Modulation Format = GFSK
|
||||
// PA Ramping = false
|
||||
// Packet Length = 61
|
||||
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word
|
||||
// Preamble Count = 4
|
||||
// RX Filter BW = 101.562500
|
||||
// Sync Word Qualifier Mode = 30/32 sync word bits detected
|
||||
// TX Power = 10
|
||||
// Whitening = false
|
||||
// The following was generated by setting the spec for Register to "{CC1101_@RN@,0x@VH@},"
|
||||
const RfSetting gIDF_Basic[] = {
|
||||
{CC1101_SYNC1,0xC7},
|
||||
{CC1101_SYNC0,0x0A},
|
||||
{CC1101_PKTLEN,0x3D},
|
||||
{CC1101_PKTCTRL0,0x05},
|
||||
{CC1101_ADDR,0xFF},
|
||||
{CC1101_FSCTRL1,0x08},
|
||||
{CC1101_FREQ2,0x22},
|
||||
{CC1101_FREQ1,0xB1},
|
||||
{CC1101_FREQ0,0x3B},
|
||||
{CC1101_MDMCFG4,0xCA},
|
||||
{CC1101_MDMCFG3,0x83},
|
||||
{CC1101_MDMCFG2,0x93},
|
||||
{CC1101_DEVIATN,0x35},
|
||||
// {CC1101_MCSM0,0x18}, FS_AUTOCAL = 1, PO_TIMEOUT = 2
|
||||
{CC1101_MCSM0,0x18},
|
||||
{CC1101_FOCCFG,0x16},
|
||||
{CC1101_AGCCTRL2,0x43},
|
||||
{CC1101_FSCAL3,0xEF},
|
||||
{CC1101_FSCAL2,0x2D},
|
||||
{CC1101_FSCAL1,0x25},
|
||||
{CC1101_FSCAL0,0x1F},
|
||||
{CC1101_TEST2,0x81},
|
||||
{CC1101_TEST1,0x35},
|
||||
{CC1101_TEST0,0x09},
|
||||
{0xff,0} // end of table
|
||||
};
|
||||
|
||||
// RF configuration from Dimitry's orginal code
|
||||
// Address Config = No address check
|
||||
// Base Frequency = 902.999756
|
||||
// CRC Autoflush = false
|
||||
// CRC Enable = true
|
||||
// Carrier Frequency = 902.999756
|
||||
// Channel Number = 0
|
||||
// Channel Spacing = 335.632324
|
||||
// Data Format = Normal mode
|
||||
// Data Rate = 249.939
|
||||
// Deviation = 165.039063
|
||||
// Device Address = 22
|
||||
// Manchester Enable = false
|
||||
// Modulated = true
|
||||
// Modulation Format = GFSK
|
||||
// PA Ramping = false
|
||||
// Packet Length = 255
|
||||
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word
|
||||
// Preamble Count = 24
|
||||
// RX Filter BW = 650.000000
|
||||
// Sync Word Qualifier Mode = 30/32 sync word bits detected
|
||||
// TX Power = 0
|
||||
// Whitening = true
|
||||
// Rf settings for CC1101
|
||||
// The following was generated by setting the spec for Register to "{CC1101_@RN@,0x@VH@},"
|
||||
const RfSetting gDmitry915[] = {
|
||||
{CC1101_FREQ2,0x22},
|
||||
{CC1101_FREQ1,0xBB},
|
||||
{CC1101_FREQ0,0x13},
|
||||
{CC1101_MDMCFG4,0x1D},
|
||||
{CC1101_MDMCFG3,0x3B},
|
||||
{CC1101_MDMCFG2,0x13},
|
||||
{CC1101_MDMCFG1,0x73},
|
||||
{CC1101_MDMCFG0,0xA7},
|
||||
{CC1101_DEVIATN,0x65},
|
||||
{CC1101_MCSM0,0x18},
|
||||
{CC1101_FOCCFG,0x1E},
|
||||
{CC1101_BSCFG,0x1C},
|
||||
{CC1101_AGCCTRL2,0xC7},
|
||||
{CC1101_AGCCTRL1,0x00},
|
||||
{CC1101_AGCCTRL0,0xB0},
|
||||
{CC1101_FREND1,0xB6},
|
||||
{CC1101_FSCAL3,0xEA},
|
||||
{CC1101_FSCAL2,0x2A},
|
||||
{CC1101_FSCAL1,0x00},
|
||||
{CC1101_FSCAL0,0x1F},
|
||||
{CC1101_TEST0,0x09},
|
||||
{0xff,0} // end of table
|
||||
};
|
||||
|
||||
SubGigData gSubGigData;
|
||||
|
||||
int CheckSubGigState(void);
|
||||
void SubGig_CC1101_reset(void);
|
||||
void SubGig_CC1101_SetConfig(const RfSetting *pConfig);
|
||||
|
||||
static void IRAM_ATTR gpio_isr_handler(void *arg)
|
||||
{
|
||||
gSubGigData.RxAvailable = true;
|
||||
}
|
||||
|
||||
// return SUBGIG_ERR_NONE aka ESP_OK aka 0 if CC1101 is detected and all is good
|
||||
SubGigErr SubGig_radio_init(uint8_t ch)
|
||||
{
|
||||
esp_err_t Err;
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.clock_speed_hz = 5000000, // SPI clock is 5 MHz!
|
||||
.queue_size = 7,
|
||||
.mode = 0, // SPI mode 0
|
||||
.spics_io_num = -1, // we will use manual CS control
|
||||
.flags = SPI_DEVICE_NO_DUMMY
|
||||
};
|
||||
gpio_config_t io_conf = {
|
||||
.intr_type = GPIO_INTR_NEGEDGE, // GPIO interrupt type : falling edge
|
||||
//bit mask of the pins
|
||||
.pin_bit_mask = 1ULL<<CONFIG_GDO0_GPIO,
|
||||
//set as input mode
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
//enable pull-up mode
|
||||
.pull_up_en = 1,
|
||||
.pull_down_en = 0
|
||||
};
|
||||
int ErrLine = 0;
|
||||
SubGigErr Ret = SUBGIG_ERR_NONE;
|
||||
|
||||
do {
|
||||
gpio_reset_pin(CONFIG_CSN_GPIO);
|
||||
gpio_set_direction(CONFIG_CSN_GPIO, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(CONFIG_CSN_GPIO, 1);
|
||||
|
||||
spi_bus_config_t buscfg = {
|
||||
.sclk_io_num = CONFIG_SCK_GPIO,
|
||||
.mosi_io_num = CONFIG_MOSI_GPIO,
|
||||
.miso_io_num = CONFIG_MISO_GPIO,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1
|
||||
};
|
||||
|
||||
if((Err = spi_bus_initialize(HOST_ID,&buscfg,SPI_DMA_CH_AUTO)) != 0) {
|
||||
ErrLine = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
if((Err = spi_bus_add_device(HOST_ID,&devcfg,&gSpiHndl)) != 0) {
|
||||
ErrLine = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
// Configure GDO0, interrupt on falling edge
|
||||
if((Err = gpio_config(&io_conf)) != 0) {
|
||||
ErrLine = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
// Configure GDO2, interrupts disabled
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.pin_bit_mask = 1ULL<<CONFIG_GDO2_GPIO;
|
||||
if((Err = gpio_config(&io_conf)) != 0) {
|
||||
ErrLine = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
// install gpio isr service
|
||||
if((Err = gpio_install_isr_service(0)) != 0) {
|
||||
ErrLine = __LINE__;
|
||||
break;
|
||||
}
|
||||
//hook isr handler for specific gpio pin
|
||||
Err = gpio_isr_handler_add(CONFIG_GDO0_GPIO,gpio_isr_handler,
|
||||
(void*) CONFIG_GDO0_GPIO);
|
||||
if(Err != 0) {
|
||||
ErrLine = __LINE__;
|
||||
break;
|
||||
}
|
||||
// Check Chip ID
|
||||
if(!CC1101_Present()) {
|
||||
Ret = SUBGIG_CC1101_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
gSubGigData.Present = true;
|
||||
SubGig_CC1101_reset();
|
||||
CC1101_SetConfig(NULL);
|
||||
SubGig_CC1101_SetConfig(gDmitry915);
|
||||
#if 0
|
||||
CC1101_DumpRegs();
|
||||
#endif
|
||||
if(ch != 0) {
|
||||
SubGig_radioSetChannel(ch);
|
||||
}
|
||||
// good to go!
|
||||
} while(false);
|
||||
|
||||
if(ErrLine != 0) {
|
||||
LOG("%s#%d: failed %d\n",__FUNCTION__,ErrLine,Err);
|
||||
if(Err == 0) {
|
||||
Ret = ESP_FAIL;
|
||||
}
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
||||
SubGigErr SubGig_radioSetChannel(uint8_t ch)
|
||||
{
|
||||
SubGigErr Ret = SUBGIG_ERR_NONE;
|
||||
|
||||
RfSetting SetChannr[2] = {
|
||||
{CC1101_CHANNR,0},
|
||||
{0xff,0} // end of table
|
||||
};
|
||||
|
||||
do {
|
||||
if(!gSubGigData.Enabled && gSubGigData.Present && ch != 0) {
|
||||
gSubGigData.Enabled = true;
|
||||
LOG("SubGhz enabled\n");
|
||||
}
|
||||
if((Ret = CheckSubGigState()) != SUBGIG_ERR_NONE) {
|
||||
break;
|
||||
}
|
||||
if(ch == 0) {
|
||||
// Disable SubGhz
|
||||
LOG("SubGhz disabled\n");
|
||||
gSubGigData.Enabled = false;
|
||||
break;
|
||||
}
|
||||
LOG("Set channel %d\n",ch);
|
||||
|
||||
if(ch >= FIRST_866_CHAN && ch < FIRST_866_CHAN + NUM_866_CHANNELS) {
|
||||
// Base Frequency = 863.999756
|
||||
// total channels 6 (0 -> 5) (CHANNR 0 -> 15)
|
||||
// Channel 100 / CHANNR 0: 863.999756
|
||||
// Channel 101 / CHANNR 3: 865.006 Mhz
|
||||
// Channel 102 / CHANNR 6: 866.014 Mhz
|
||||
// Channel 103 / CHANNR 9: 867.020 Mhz
|
||||
// Channel 104 / CHANNR 12: 868.027 Mhz
|
||||
// Channel 105 / CHANNR 15: 869.034 Mhz
|
||||
SubGig_CC1101_SetConfig(g864Mhz);
|
||||
SetChannr[0].Value = (ch - FIRST_866_CHAN) * 3;
|
||||
}
|
||||
else {
|
||||
// Base Frequency = 902.999756
|
||||
// Dmitry's orginal code used 25 channels in 915 Mhz
|
||||
// We don't want to have to scan that many so for OEPL we'll just use 6
|
||||
// to match 866.
|
||||
// Channel 200 / CHANNR 0: 903.000 Mhz
|
||||
// Channel 201 / CHANNR 12: 907.027 Mhz
|
||||
// Channel 202 / CHANNR 24: 911.054 Mhz
|
||||
// Channel 203 / CHANNR 24: 915.083 Mhz
|
||||
// Channel 204 / CHANNR 48: 919.110 Mhz
|
||||
// Channel 205 / CHANNR 60: 923.138 Mhz
|
||||
SubGig_CC1101_SetConfig(g903Mhz);
|
||||
|
||||
if(ch >= FIRST_915_CHAN && ch < FIRST_915_CHAN + NUM_915_CHANNELS) {
|
||||
SetChannr[0].Value = (ch - FIRST_915_CHAN) * 12;
|
||||
}
|
||||
else {
|
||||
Ret = SUBGIG_INVALID_CHANNEL;
|
||||
SetChannr[0].Value = 0; // default to the first channel on 915
|
||||
}
|
||||
}
|
||||
SubGig_CC1101_SetConfig(SetChannr);
|
||||
CC1101_setRxState();
|
||||
} while(false);
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
SubGigErr SubGig_radioTx(uint8_t *packet)
|
||||
{
|
||||
SubGigErr Ret = SUBGIG_ERR_NONE;
|
||||
|
||||
do {
|
||||
if(gSubGigData.FreqTest) {
|
||||
break;
|
||||
}
|
||||
if((Ret = CheckSubGigState()) != SUBGIG_ERR_NONE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(packet[0] < 3 || packet[0] > RADIO_MAX_PACKET_LEN + RAW_PKT_PADDING) {
|
||||
Ret = SUBGIG_TX_BAD_LEN;
|
||||
break;
|
||||
}
|
||||
|
||||
// All packets seem to be padded by RAW_PKT_PADDING (2 bytes)
|
||||
// Remove the padding before sending so the length is correct when received
|
||||
packet[0] -= RAW_PKT_PADDING;
|
||||
LOG("Sending %d byte subgig frame:\n",packet[0]);
|
||||
LOG_HEX(&packet[1],packet[0]);
|
||||
if(CC1101_Tx(packet)) {
|
||||
Ret = SUBGIG_TX_FAILED;
|
||||
}
|
||||
// Clear RxAvailable, in TX GDO0 deasserts on TX FIFO underflows
|
||||
gSubGigData.RxAvailable = false;
|
||||
// restore original len just in case anyone cares
|
||||
packet[0] += RAW_PKT_PADDING;
|
||||
} while(false);
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
// returns packet size in bytes data in data
|
||||
int8_t SubGig_commsRxUnencrypted(uint8_t *data)
|
||||
{
|
||||
int RxBytes;
|
||||
int8_t Ret = 0;
|
||||
|
||||
do {
|
||||
if(CheckSubGigState() != SUBGIG_ERR_NONE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(gSubGigData.FreqTest) {
|
||||
break;
|
||||
}
|
||||
CC1101_logState();
|
||||
|
||||
if(!gSubGigData.RxAvailable && gpio_get_level(CONFIG_GDO0_GPIO) == 1) {
|
||||
// Did we miss an interrupt?
|
||||
if(gpio_get_level(CONFIG_GDO0_GPIO) == 1) {
|
||||
// Yup!
|
||||
LOGE("SubGhz lost interrupt\n");
|
||||
gSubGigData.RxAvailable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(gSubGigData.RxAvailable){
|
||||
gSubGigData.RxAvailable = false;
|
||||
RxBytes = CC1101_Rx(data,128,NULL,NULL);
|
||||
|
||||
if(RxBytes >= 2) {
|
||||
// NB: RxBytes includes the CRC, deduct it
|
||||
Ret = (uint8_t) RxBytes - 2;
|
||||
LOG("Received %d byte subgig frame:\n",Ret);
|
||||
LOG_HEX(data,Ret);
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
int CheckSubGigState()
|
||||
{
|
||||
int Err = SUBGIG_ERR_NONE;
|
||||
|
||||
if(!gSubGigData.Present) {
|
||||
Err = SUBGIG_CC1101_NOT_FOUND;
|
||||
}
|
||||
else if(!gSubGigData.Initialized) {
|
||||
Err = SUBGIG_NOT_INITIALIZED;
|
||||
}
|
||||
else if(!gSubGigData.Enabled) {
|
||||
Err = SUBGIG_NOT_ENABLED;
|
||||
}
|
||||
|
||||
if(Err != SUBGIG_ERR_NONE) {
|
||||
LOG("CheckSubGigState: returing %d\n",Err);
|
||||
}
|
||||
|
||||
return Err;
|
||||
}
|
||||
|
||||
SubGigErr SubGig_FreqTest(bool b866Mhz,bool bStart)
|
||||
{
|
||||
SubGigErr Err = SUBGIG_ERR_NONE;
|
||||
#if 0
|
||||
uint8_t TxData = 0; // len = 0
|
||||
|
||||
do {
|
||||
if((Err = CheckSubGigState()) != SUBGIG_ERR_NONE) {
|
||||
break;
|
||||
}
|
||||
if(bStart) {
|
||||
LOG_RAW("Starting %sMhz Freq test\n",b866Mhz ? "866" : "915");
|
||||
SubGig_CC1101_reset();
|
||||
SubGig_CC1101_SetConfig(gCW);
|
||||
SubGig_CC1101_SetConfig(b866Mhz ? g866Mhz : g915Mhz);
|
||||
CC1101_cmdStrobe(CC1101_SIDLE);
|
||||
CC1101_cmdStrobe(CC1101_SFTX); // flush Tx Fifo
|
||||
CC1101_cmdStrobe(CC1101_STX);
|
||||
gRfState = RFSTATE_TX;
|
||||
gSubGigData.FreqTest = true;
|
||||
}
|
||||
else {
|
||||
LOG_RAW("Ending Freq test\n");
|
||||
gSubGigData.FreqTest = false;
|
||||
SubGig_CC1101_reset();
|
||||
SubGig_CC1101_SetConfig(gSubGigData.pConfig);
|
||||
}
|
||||
} while(false);
|
||||
#endif
|
||||
return Err;
|
||||
}
|
||||
|
||||
void SubGig_CC1101_reset()
|
||||
{
|
||||
gSubGigData.Initialized = false;
|
||||
gSubGigData.FixedRegsSet = false;
|
||||
CC1101_reset();
|
||||
}
|
||||
|
||||
void SubGig_CC1101_SetConfig(const RfSetting *pConfig)
|
||||
{
|
||||
CC1101_SetConfig(pConfig);
|
||||
gSubGigData.Initialized = true;
|
||||
}
|
||||
|
||||
void DumpHex(void *AdrIn,int Len)
|
||||
{
|
||||
unsigned char *Adr = (unsigned char *) AdrIn;
|
||||
int i = 0;
|
||||
int j;
|
||||
|
||||
while(i < Len) {
|
||||
for(j = 0; j < 16; j++) {
|
||||
if((i + j) == Len) {
|
||||
break;
|
||||
}
|
||||
LOG_RAW("%02x ",Adr[i+j]);
|
||||
}
|
||||
|
||||
LOG_RAW(" ");
|
||||
for(j = 0; j < 16; j++) {
|
||||
if((i + j) == Len) {
|
||||
break;
|
||||
}
|
||||
if(isprint(Adr[i+j])) {
|
||||
LOG_RAW("%c",Adr[i+j]);
|
||||
}
|
||||
else {
|
||||
LOG_RAW(".");
|
||||
}
|
||||
}
|
||||
i += 16;
|
||||
LOG_RAW("\n");
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
|
||||
40
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/SubGigRadio.h
Normal file
40
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/SubGigRadio.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef _SUBGIG_RADIO_H_
|
||||
#define _SUBGIG_RADIO_H_
|
||||
|
||||
//sub-GHz 866 Mhz channels start at 100
|
||||
#define FIRST_866_CHAN (100)
|
||||
#define NUM_866_CHANNELS (6)
|
||||
|
||||
//sub-GHz 915 Mhz channels start at 200
|
||||
#define FIRST_915_CHAN (200)
|
||||
#define NUM_915_CHANNELS (6)
|
||||
|
||||
typedef enum {
|
||||
SUBGIG_ERR_NONE,
|
||||
SUBGIG_CC1101_NOT_FOUND,
|
||||
SUBGIG_NOT_INITIALIZED,
|
||||
SUBGIG_NOT_ENABLED,
|
||||
SUBGIG_TX_FAILED,
|
||||
SUBGIG_TX_BAD_LEN,
|
||||
SUBGIG_INVALID_CHANNEL,
|
||||
} SubGigErr;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Present:1;
|
||||
uint8_t Enabled:1;
|
||||
uint8_t FreqTest:1;
|
||||
uint8_t RxAvailable:1;
|
||||
uint8_t Initialized:1;
|
||||
uint8_t FixedRegsSet:1;
|
||||
} SubGigData;
|
||||
|
||||
extern SubGigData gSubGigData;
|
||||
|
||||
SubGigErr SubGig_radio_init(uint8_t ch);
|
||||
SubGigErr SubGig_radioTx(uint8_t *packet);
|
||||
SubGigErr SubGig_radioSetChannel(uint8_t ch);
|
||||
int8_t SubGig_commsRxUnencrypted(uint8_t *data);
|
||||
SubGigErr SubGig_FreqTest(bool b866Mhz,bool bStart);
|
||||
|
||||
#endif // _SUBGIG_RADIO_H_
|
||||
|
||||
790
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/cc1101_radio.c
Normal file
790
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/cc1101_radio.c
Normal file
@@ -0,0 +1,790 @@
|
||||
// Large portions of this code was copied from:
|
||||
// https://github.com/nopnop2002/esp-idf-cc1101 with the following copyright
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011 panStamp <contact@panstamp.com>
|
||||
* Copyright (c) 2016 Tyler Sommer <contact@tylersommer.pro>
|
||||
*
|
||||
* This file is part of the CC1101 project.
|
||||
*
|
||||
* CC1101 is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* CC1101 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with CC1101; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*
|
||||
* Author: Daniel Berenguer
|
||||
* Creation date: 03/03/2011
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <driver/spi_master.h>
|
||||
#include "proto.h"
|
||||
#include "cc1101_radio.h"
|
||||
#include "radio.h"
|
||||
|
||||
#define ENABLE_LOGGING 0
|
||||
|
||||
// LOGA - generic logging, always enabled
|
||||
#define LOGA(format, ... ) printf(format,## __VA_ARGS__)
|
||||
// LOGE - error logging, always enabled
|
||||
#define LOGE(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
|
||||
#if ENABLE_LOGGING
|
||||
#define LOG(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOG_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
#else
|
||||
#define LOG(format, ... )
|
||||
#define LOG_RAW(format, ... )
|
||||
#endif
|
||||
|
||||
#define ENABLE_VERBOSE_LOGGING 0
|
||||
|
||||
#if ENABLE_VERBOSE_LOGGING
|
||||
#define LOGV(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOGV_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
#else
|
||||
#define LOGV(format, ... )
|
||||
#define LOGB_RAW(format, ... )
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include <driver/spi_master.h>
|
||||
#include <driver/gpio.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/**
|
||||
* RF STATES
|
||||
*/
|
||||
enum RFSTATE {
|
||||
RFSTATE_IDLE = 0,
|
||||
RFSTATE_RX,
|
||||
RFSTATE_TX
|
||||
};
|
||||
|
||||
/**
|
||||
* Type of transfers
|
||||
*/
|
||||
#define WRITE_BURST 0x40
|
||||
#define READ_SINGLE 0x80
|
||||
#define READ_BURST 0xC0
|
||||
|
||||
/**
|
||||
* Type of register
|
||||
*/
|
||||
#define CC1101_CONFIG_REGISTER READ_SINGLE
|
||||
#define CC1101_STATUS_REGISTER READ_BURST
|
||||
|
||||
/**
|
||||
* PATABLE & FIFO's
|
||||
*/
|
||||
#define CC1101_PATABLE 0x3E // PATABLE address
|
||||
#define CC1101_TXFIFO 0x3F // TX FIFO address
|
||||
#define CC1101_RXFIFO 0x3F // RX FIFO address
|
||||
|
||||
/**
|
||||
* Command strobes
|
||||
*/
|
||||
#define CC1101_SRES 0x30 // Reset CC1101 chip
|
||||
#define CC1101_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). If in RX (with CCA):
|
||||
// Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround).
|
||||
#define CC1101_SXOFF 0x32 // Turn off crystal oscillator
|
||||
#define CC1101_SCAL 0x33 // Calibrate frequency synthesizer and turn it off. SCAL can be strobed from IDLE mode without
|
||||
// setting manual calibration mode (MCSM0.FS_AUTOCAL=0)
|
||||
#define CC1101_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1
|
||||
#define CC1101_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1.
|
||||
// If in RX state and CCA is enabled: Only go to TX if channel is clear
|
||||
#define CC1101_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable
|
||||
#define CC1101_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio) as described in Section 19.5 if
|
||||
// WORCTRL.RC_PD=0
|
||||
#define CC1101_SPWD 0x39 // Enter power down mode when CSn goes high
|
||||
#define CC1101_SFRX 0x3A // Flush the RX FIFO buffer. Only issue SFRX in IDLE or RXFIFO_OVERFLOW states
|
||||
#define CC1101_SFTX 0x3B // Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states
|
||||
#define CC1101_SWORRST 0x3C // Reset real time clock to Event1 value
|
||||
#define CC1101_SNOP 0x3D // No operation. May be used to get access to the chip status byte
|
||||
|
||||
#define CC1101_STATE_SLEEP 0x00
|
||||
#define CC1101_STATE_IDLE 0x01
|
||||
#define CC1101_STATE_XOFF 0x02
|
||||
#define CC1101_STATE_VCOON_MC 0x03
|
||||
#define CC1101_STATE_REGON_MC 0x04
|
||||
#define CC1101_STATE_MANCAL 0x05
|
||||
#define CC1101_STATE_VCOON 0x06
|
||||
#define CC1101_STATE_REGON 0x07
|
||||
#define CC1101_STATE_STARTCAL 0x08
|
||||
#define CC1101_STATE_BWBOOST 0x09
|
||||
#define CC1101_STATE_FS_LOCK 0x0A
|
||||
#define CC1101_STATE_IFADCON 0x0B
|
||||
#define CC1101_STATE_ENDCAL 0x0C
|
||||
#define CC1101_STATE_RX 0x0D
|
||||
#define CC1101_STATE_RX_END 0x0E
|
||||
#define CC1101_STATE_RX_RST 0x0F
|
||||
#define CC1101_STATE_TXRX_SWITCH 0x10
|
||||
#define CC1101_STATE_RXFIFO_OVERFLOW 0x11
|
||||
#define CC1101_STATE_FSTXON 0x12
|
||||
#define CC1101_STATE_TX 0x13
|
||||
#define CC1101_STATE_TX_END 0x14
|
||||
#define CC1101_STATE_RXTX_SWITCH 0x15
|
||||
#define CC1101_STATE_TXFIFO_UNDERFLOW 0x16
|
||||
|
||||
// Masks for first byte read from RXFIFO
|
||||
#define CC1101_NUM_RXBYTES_MASK 0x7f
|
||||
#define CC1101_RXFIFO_OVERFLOW_MASK 0x80
|
||||
|
||||
// Masks for last byte read from RXFIFO
|
||||
#define CC1101_LQI_MASK 0x7f
|
||||
#define CC1101_CRC_OK_MASK 0x80
|
||||
|
||||
// IOCFG2 GDO2: high when TX FIFO at or above the TX FIFO threshold
|
||||
#define CC1101_DEFVAL_IOCFG2 0x02
|
||||
|
||||
// IOCFG1 GDO1: High impedance (3-state)
|
||||
#define CC1101_DEFVAL_IOCFG1 0x2E
|
||||
|
||||
// GDO0 goes high when sync word has been sent / received, and
|
||||
// goes low at the end of the packet.
|
||||
// In TX mode the pin will go low if the TX FIFO underflows.
|
||||
#define CC1101_DEFVAL_IOCFG0 0x06
|
||||
|
||||
// Threshold = 32 bytes (1/2 of FIFO len)
|
||||
#define CC1101_DEFVAL_FIFOTHR 0x07
|
||||
#define CC1101_DEFVAL_RCCTRL1 0x41
|
||||
#define CC1101_DEFVAL_RCCTRL0 0x00
|
||||
#define CC1101_DEFVAL_AGCTEST 0x3F
|
||||
#define CC1101_DEFVAL_MCSM1 0x20
|
||||
#define CC1101_DEFVAL_WORCTRL 0xFB
|
||||
#define CC1101_DEFVAL_FSCTRL0 0
|
||||
|
||||
#define CC1101_DEFVAL_PATABLE 0xc0 // full power
|
||||
|
||||
RfSetting gFixedConfig[] = {
|
||||
{CC1101_IOCFG2,CC1101_DEFVAL_IOCFG2},
|
||||
{CC1101_IOCFG1,CC1101_DEFVAL_IOCFG1},
|
||||
{CC1101_IOCFG0,CC1101_DEFVAL_IOCFG0},
|
||||
{CC1101_FIFOTHR,CC1101_DEFVAL_FIFOTHR},
|
||||
{CC1101_FSCTRL0,CC1101_DEFVAL_FSCTRL0},
|
||||
{CC1101_RCCTRL1,CC1101_DEFVAL_RCCTRL1},
|
||||
{CC1101_RCCTRL0,CC1101_DEFVAL_RCCTRL0},
|
||||
{CC1101_MCSM1,CC1101_DEFVAL_MCSM1},
|
||||
{CC1101_WORCTRL,CC1101_DEFVAL_WORCTRL},
|
||||
{0xff,0},
|
||||
};
|
||||
|
||||
void CC1101_readBurstReg(uint8_t *buffer,uint8_t regAddr,uint8_t len);
|
||||
void CC1101_cmdStrobe(uint8_t cmd);
|
||||
void CC1101_wakeUp(void);
|
||||
uint8_t CC1101_readReg(uint8_t regAddr, uint8_t regType);
|
||||
void CC1101_writeReg(uint8_t regAddr, uint8_t value);
|
||||
void CC1101_setTxState(void);
|
||||
|
||||
void setIdleState(void);
|
||||
|
||||
spi_device_handle_t gSpiHndl;
|
||||
|
||||
#define readConfigReg(regAddr) CC1101_readReg(regAddr, CC1101_CONFIG_REGISTER)
|
||||
#define readStatusReg(regAddr) CC1101_readReg(regAddr, CC1101_STATUS_REGISTER)
|
||||
#define flushRxFifo() CC1101_cmdStrobe(CC1101_SFRX)
|
||||
#define flushTxFifo() CC1101_cmdStrobe(CC1101_SFTX)
|
||||
|
||||
const char *RegNamesCC1101[] = {
|
||||
"IOCFG2", // 0x00 GDO2 output pin configuration
|
||||
"IOCFG1", // 0x01 GDO1 output pin configuration
|
||||
"IOCFG0", // 0x02 GDO0 output pin configuration
|
||||
"FIFOTHR", // 0x03 RX FIFO and TX FIFO thresholds
|
||||
"SYNC1", // 0x04 Sync word, high INT8U
|
||||
"SYNC0", // 0x05 Sync word, low INT8U
|
||||
"PKTLEN", // 0x06 Packet length
|
||||
"PKTCTRL1", // 0x07 Packet automation control
|
||||
"PKTCTRL0", // 0x08 Packet automation control
|
||||
"ADDR", // 0x09 Device address
|
||||
"CHANNR", // 0x0A Channel number
|
||||
"FSCTRL1", // 0x0B Frequency synthesizer control
|
||||
"FSCTRL0", // 0x0C Frequency synthesizer control
|
||||
"FREQ2", // 0x0D Frequency control word, high INT8U
|
||||
"FREQ1", // 0x0E Frequency control word, middle INT8U
|
||||
"FREQ0", // 0x0F Frequency control word, low INT8U
|
||||
"MDMCFG4", // 0x10 Modem configuration
|
||||
"MDMCFG3", // 0x11 Modem configuration
|
||||
"MDMCFG2", // 0x12 Modem configuration
|
||||
"MDMCFG1", // 0x13 Modem configuration
|
||||
"MDMCFG0", // 0x14 Modem configuration
|
||||
"DEVIATN", // 0x15 Modem deviation setting
|
||||
"MCSM2", // 0x16 Main Radio Control State Machine configuration
|
||||
"MCSM1", // 0x17 Main Radio Control State Machine configuration
|
||||
"MCSM0", // 0x18 Main Radio Control State Machine configuration
|
||||
"FOCCFG", // 0x19 Frequency Offset Compensation configuration
|
||||
"BSCFG", // 0x1A Bit Synchronization configuration
|
||||
"AGCCTRL2", // 0x1B AGC control
|
||||
"AGCCTRL1", // 0x1C AGC control
|
||||
"AGCCTRL0", // 0x1D AGC control
|
||||
"WOREVT1", // 0x1E High INT8U Event 0 timeout
|
||||
"WOREVT0", // 0x1F Low INT8U Event 0 timeout
|
||||
"WORCTRL", // 0x20 Wake On Radio control
|
||||
"FREND1", // 0x21 Front end RX configuration
|
||||
"FREND0", // 0x22 Front end TX configuration
|
||||
"FSCAL3", // 0x23 Frequency synthesizer calibration
|
||||
"FSCAL2", // 0x24 Frequency synthesizer calibration
|
||||
"FSCAL1", // 0x25 Frequency synthesizer calibration
|
||||
"FSCAL0", // 0x26 Frequency synthesizer calibration
|
||||
"RCCTRL1", // 0x27 RC oscillator configuration
|
||||
"RCCTRL0", // 0x28 RC oscillator configuration
|
||||
"FSTEST", // 0x29 Frequency synthesizer calibration control
|
||||
"PTEST", // 0x2A Production test
|
||||
"AGCTEST", // 0x2B AGC test
|
||||
"TEST2", // 0x2C Various test settings
|
||||
"TEST1", // 0x2D Various test settings
|
||||
"TEST0", // 0x2E Various test settings
|
||||
"0x2f", // 0x2f
|
||||
//CC1101 Strobe commands
|
||||
"SRES", // 0x30 Reset chip.
|
||||
"SFSTXON", // 0x31 Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
|
||||
"SXOFF", // 0x32 Turn off crystal oscillator.
|
||||
"SCAL", // 0x33 Calibrate frequency synthesizer and turn it off
|
||||
"SRX", // 0x34 Enable RX. Perform calibration first if coming from IDLE and
|
||||
"STX", // 0x35 In IDLE state: Enable TX. Perform calibration first if
|
||||
"SIDLE", // 0x36 Exit RX / TX, turn off frequency synthesizer and exit
|
||||
"SAFC", // 0x37 Perform AFC adjustment of the frequency synthesizer
|
||||
"SWOR", // 0x38 Start automatic RX polling sequence (Wake-on-Radio)
|
||||
"SPWD", // 0x39 Enter power down mode when CSn goes high.
|
||||
"SFRX", // 0x3A Flush the RX FIFO buffer.
|
||||
"SFTX", // 0x3B Flush the TX FIFO buffer.
|
||||
"SWORRST", // 0x3C Reset real time clock.
|
||||
"SNOP", // 0x3D No operation. May be used to pad strobe commands to two
|
||||
"PATABLE" // 0x3E
|
||||
};
|
||||
|
||||
|
||||
// SPI Stuff
|
||||
#if CONFIG_SPI2_HOST
|
||||
#define HOST_ID SPI2_HOST
|
||||
#elif CONFIG_SPI3_HOST
|
||||
#define HOST_ID SPI3_HOST
|
||||
#endif
|
||||
|
||||
/*
|
||||
* RF state
|
||||
*/
|
||||
static uint8_t gRfState;
|
||||
|
||||
#define cc1101_Select() gpio_set_level(CONFIG_CSN_GPIO, LOW)
|
||||
#define cc1101_Deselect() gpio_set_level(CONFIG_CSN_GPIO, HIGH)
|
||||
#define wait_Miso() while(gpio_get_level(CONFIG_MISO_GPIO)>0)
|
||||
#define getGDO0state() gpio_get_level(CONFIG_GDO0_GPIO)
|
||||
#define wait_GDO0_high() while(!getGDO0state())
|
||||
#define wait_GDO0_low() while(getGDO0state())
|
||||
#define getGDO2state() gpio_get_level(CONFIG_GDO2_GPIO)
|
||||
#define wait_GDO2_low() while(getGDO2state())
|
||||
|
||||
/**
|
||||
* Arduino Macros
|
||||
*/
|
||||
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
|
||||
#define delayMicroseconds(us) esp_rom_delay_us(us)
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
|
||||
int32_t gFreqErrSum;
|
||||
uint8_t gFreqErrSumCount;
|
||||
int8_t gFreqCorrection;
|
||||
|
||||
bool spi_write_byte(uint8_t* Dataout,size_t DataLength)
|
||||
{
|
||||
spi_transaction_t SPITransaction;
|
||||
|
||||
if(DataLength > 0) {
|
||||
memset(&SPITransaction,0,sizeof(spi_transaction_t));
|
||||
SPITransaction.length = DataLength * 8;
|
||||
SPITransaction.tx_buffer = Dataout;
|
||||
SPITransaction.rx_buffer = NULL;
|
||||
spi_device_transmit(gSpiHndl,&SPITransaction);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spi_read_byte(uint8_t* Datain,uint8_t* Dataout,size_t DataLength)
|
||||
{
|
||||
spi_transaction_t SPITransaction;
|
||||
|
||||
if(DataLength > 0) {
|
||||
memset(&SPITransaction,0,sizeof(spi_transaction_t));
|
||||
SPITransaction.length = DataLength * 8;
|
||||
SPITransaction.tx_buffer = Dataout;
|
||||
SPITransaction.rx_buffer = Datain;
|
||||
spi_device_transmit(gSpiHndl,&SPITransaction);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t spi_transfer(uint8_t address)
|
||||
{
|
||||
uint8_t datain[1];
|
||||
uint8_t dataout[1];
|
||||
dataout[0] = address;
|
||||
//spi_write_byte(dev, dataout, 1 );
|
||||
//spi_read_byte(datain, dataout, 1 );
|
||||
|
||||
spi_transaction_t SPITransaction;
|
||||
memset(&SPITransaction,0,sizeof(spi_transaction_t));
|
||||
SPITransaction.length = 8;
|
||||
SPITransaction.tx_buffer = dataout;
|
||||
SPITransaction.rx_buffer = datain;
|
||||
spi_device_transmit(gSpiHndl,&SPITransaction);
|
||||
|
||||
return datain[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* CC1101_wakeUp
|
||||
*
|
||||
* Wake up CC1101 from Power Down state
|
||||
*/
|
||||
void CC1101_wakeUp(void)
|
||||
{
|
||||
cc1101_Select();
|
||||
wait_Miso();
|
||||
cc1101_Deselect();
|
||||
}
|
||||
|
||||
/**
|
||||
* CC1101_writeReg
|
||||
*
|
||||
* Write single register into the CC1101 IC via SPI
|
||||
*
|
||||
* @param regAddr Register address
|
||||
* @param value Value to be writen
|
||||
*/
|
||||
void CC1101_writeReg(uint8_t regAddr, uint8_t value)
|
||||
{
|
||||
if(regAddr < 0x3f) {
|
||||
LOGV("0x%x -> %s(0x%x)\n",value,RegNamesCC1101[regAddr],regAddr);
|
||||
}
|
||||
else {
|
||||
LOGV("0x%x -> 0x%x\n",value,regAddr);
|
||||
}
|
||||
cc1101_Select(); // Select CC1101
|
||||
wait_Miso(); // Wait until MISO goes low
|
||||
spi_transfer(regAddr); // Send register address
|
||||
spi_transfer(value); // Send value
|
||||
cc1101_Deselect(); // Deselect CC1101
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CC1101_cmdStrobe
|
||||
*
|
||||
* Send command strobe to the CC1101 IC via SPI
|
||||
*
|
||||
* @param cmd Command strobe
|
||||
*/
|
||||
void CC1101_cmdStrobe(uint8_t cmd)
|
||||
{
|
||||
cc1101_Select();
|
||||
wait_Miso();
|
||||
spi_transfer(cmd);
|
||||
cc1101_Deselect();
|
||||
}
|
||||
|
||||
/**
|
||||
* CC1101_readReg
|
||||
*
|
||||
* Read CC1101 register via SPI
|
||||
*
|
||||
* @param regAddr Register address
|
||||
* @param regType Type of register: CONFIG_REGISTER or STATUS_REGISTER
|
||||
*
|
||||
* Return:
|
||||
* Data uint8_t returned by the CC1101 IC
|
||||
*/
|
||||
uint8_t CC1101_readReg(uint8_t regAddr,uint8_t regType)
|
||||
{
|
||||
uint8_t addr, val;
|
||||
|
||||
addr = regAddr | regType;
|
||||
cc1101_Select();
|
||||
wait_Miso();
|
||||
spi_transfer(addr);
|
||||
val = spi_transfer(0x00); // Read result
|
||||
cc1101_Deselect();
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* CC1101_readBurstReg
|
||||
*
|
||||
* Read burst data from CC1101 via SPI
|
||||
*
|
||||
* @param buffer Buffer where to copy the result to
|
||||
* @param regAddr Register address
|
||||
* @param len Data length
|
||||
*/
|
||||
void CC1101_readBurstReg(uint8_t *buffer,uint8_t regAddr,uint8_t len)
|
||||
{
|
||||
uint8_t addr, i;
|
||||
|
||||
addr = regAddr | READ_BURST;
|
||||
cc1101_Select();
|
||||
wait_Miso();
|
||||
spi_transfer(addr); // Send register address
|
||||
for(i = 0; i < len; i++) {
|
||||
buffer[i] = spi_transfer(0x00); // Read result uint8_t by uint8_t
|
||||
}
|
||||
cc1101_Deselect();
|
||||
}
|
||||
|
||||
/**
|
||||
* reset
|
||||
*
|
||||
* Reset CC1101
|
||||
*/
|
||||
void CC1101_reset(void)
|
||||
{
|
||||
// See sectin 19.1.2 of the CC1101 spec sheet for reasons for the following
|
||||
cc1101_Deselect();
|
||||
delayMicroseconds(5);
|
||||
cc1101_Select();
|
||||
delayMicroseconds(10);
|
||||
cc1101_Deselect();
|
||||
delayMicroseconds(41);
|
||||
cc1101_Select();
|
||||
|
||||
// Wait until MISO goes low indicating XOSC stable
|
||||
wait_Miso();
|
||||
spi_transfer(CC1101_SRES); // Send reset command strobe
|
||||
wait_Miso();
|
||||
cc1101_Deselect();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CC1101_setRxState
|
||||
*
|
||||
* Enter Rx state
|
||||
*/
|
||||
void CC1101_setRxState(void)
|
||||
{
|
||||
CC1101_cmdStrobe(CC1101_SRX);
|
||||
gRfState = RFSTATE_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* CC1101_setTxState
|
||||
*
|
||||
* Enter Tx state
|
||||
*/
|
||||
void CC1101_setTxState(void)
|
||||
{
|
||||
CC1101_cmdStrobe(CC1101_STX);
|
||||
gRfState = RFSTATE_TX;
|
||||
}
|
||||
|
||||
|
||||
void CC1101_DumpRegs()
|
||||
{
|
||||
#if ENABLE_LOGGING
|
||||
uint8_t regAddr;
|
||||
uint8_t value;
|
||||
|
||||
LOG("\n");
|
||||
for(regAddr = 0; regAddr < 0x2f; regAddr++) {
|
||||
value = CC1101_readReg(regAddr,READ_SINGLE);
|
||||
LOG("%02x %s: 0x%02X\n",regAddr,RegNamesCC1101[regAddr],value);
|
||||
}
|
||||
|
||||
#if 0
|
||||
for(regAddr = 0; regAddr < 0x2f; regAddr++) {
|
||||
value = CC1101_readReg(regAddr,READ_SINGLE);
|
||||
LOG("<Register><Name>%s</Name><Value>0x%02X</Value></Register>\n",RegNamesCC1101[regAddr],value);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CC1101_Tx(uint8_t *TxData)
|
||||
{
|
||||
bool Ret = false;
|
||||
int ErrLine = 0;
|
||||
spi_transaction_t SPITransaction;
|
||||
uint8_t BytesSent = 0;
|
||||
uint8_t Bytes2Send;
|
||||
uint8_t len;
|
||||
uint8_t CanSend;
|
||||
esp_err_t Err;
|
||||
|
||||
do {
|
||||
// The first byte in the buffer is the number of data bytes to send,
|
||||
// we also need to send the first byte
|
||||
len = 1 + *TxData;
|
||||
memset(&SPITransaction,0,sizeof(spi_transaction_t));
|
||||
SPITransaction.tx_buffer = TxData;
|
||||
|
||||
setIdleState();
|
||||
flushTxFifo();
|
||||
|
||||
while(BytesSent < len) {
|
||||
Bytes2Send = len - BytesSent;
|
||||
if(BytesSent == 0) {
|
||||
// First chunk, the FIFO is empty and can take 64 bytes
|
||||
if(Bytes2Send > 64) {
|
||||
Bytes2Send = 64;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Not the first chunk, we can only send FIFO_THRESHOLD bytes
|
||||
// and only when GDO2 says we can
|
||||
if(getGDO2state()) {
|
||||
wait_GDO2_low();
|
||||
}
|
||||
CanSend = readStatusReg(CC1101_TXBYTES);
|
||||
if(CanSend & 0x80) {
|
||||
LOGE("TX FIFO underflow, BytesSent %d\n",BytesSent);
|
||||
ErrLine = __LINE__;
|
||||
break;
|
||||
}
|
||||
CanSend = 64 - CanSend;
|
||||
if(CanSend == 0) {
|
||||
LOGE("CanSend == 0, GDO2 problem\n");
|
||||
ErrLine = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
if(Bytes2Send > CanSend) {
|
||||
Bytes2Send = CanSend;
|
||||
}
|
||||
}
|
||||
SPITransaction.length = Bytes2Send * 8;
|
||||
SPITransaction.rxlength = 0;
|
||||
cc1101_Select();
|
||||
wait_Miso();
|
||||
spi_transfer(CC1101_TXFIFO | WRITE_BURST);
|
||||
if((Err = spi_device_transmit(gSpiHndl,&SPITransaction)) != ESP_OK) {
|
||||
ErrLine = __LINE__;
|
||||
LOGE("spi_device_transmit failed %d\n",Err);
|
||||
break;
|
||||
}
|
||||
cc1101_Deselect();
|
||||
// LOG("Sending %d bytes\n",Bytes2Send);
|
||||
if(BytesSent == 0) {
|
||||
// some or all of the tx data has been written to the FIFO,
|
||||
// start transmitting
|
||||
// LOG("Start tx\n");
|
||||
CC1101_setTxState();
|
||||
// Wait for the sync word to be transmitted
|
||||
wait_GDO0_high();
|
||||
}
|
||||
SPITransaction.tx_buffer += Bytes2Send;
|
||||
BytesSent += Bytes2Send;
|
||||
}
|
||||
|
||||
// Wait until the end of the TxData transmission
|
||||
wait_GDO0_low();
|
||||
Ret = true;
|
||||
} while(false);
|
||||
|
||||
setIdleState();
|
||||
CC1101_setRxState();
|
||||
|
||||
if(ErrLine != 0) {
|
||||
LOGE("%s#%d: failure\n",__FUNCTION__,ErrLine);
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
// Called when GDO0 goes low, i.e. end of packet.
|
||||
// Everything has been received.
|
||||
// NB: this means the entire packet must fit in the FIFO so maximum
|
||||
// message length is 64 bytes.
|
||||
int CC1101_Rx(uint8_t *RxBuf,size_t RxBufLen,uint8_t *pRssi,uint8_t *pLqi)
|
||||
{
|
||||
uint8_t rxBytes = readStatusReg(CC1101_RXBYTES);
|
||||
uint8_t Rssi;
|
||||
uint8_t Lqi;
|
||||
int Ret;
|
||||
int8_t FreqErr;
|
||||
int8_t FreqCorrection;
|
||||
|
||||
// Any data waiting to be read and no overflow?
|
||||
do {
|
||||
if(rxBytes & CC1101_RXFIFO_OVERFLOW_MASK) {
|
||||
LOGE("RxFifo overflow\n");
|
||||
Ret = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
if(rxBytes < 2) {
|
||||
// should have at least 2 bytes, packet len and one byte of data
|
||||
LOGE("Internal error, rxBytes = %d\n",rxBytes);
|
||||
Ret = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Get packet length
|
||||
Ret = readConfigReg(CC1101_RXFIFO);
|
||||
if(Ret > RxBufLen) {
|
||||
// Toss the data
|
||||
LOGE("RxBuf too small %d < %d\n",RxBufLen,Ret);
|
||||
Ret = -1;
|
||||
break;
|
||||
}
|
||||
// Read the data
|
||||
CC1101_readBurstReg(RxBuf,CC1101_RXFIFO,Ret);
|
||||
// Read RSSI
|
||||
Rssi = readConfigReg(CC1101_RXFIFO);
|
||||
// Read LQI and CRC_OK
|
||||
Lqi = readConfigReg(CC1101_RXFIFO);
|
||||
if(!(Lqi & CC1101_CRC_OK_MASK)) {
|
||||
// Crc error, ignore the packet
|
||||
LOG("Ignoring %d byte packet, CRC error\n",Ret);
|
||||
Ret = 0;
|
||||
break;
|
||||
}
|
||||
// CRC is valid
|
||||
if(pRssi != NULL) {
|
||||
*pRssi = Rssi;
|
||||
}
|
||||
if(pLqi != NULL) {
|
||||
*pLqi = Lqi & CC1101_LQI_MASK;
|
||||
}
|
||||
FreqErr = (int8_t) CC1101_readReg(CC1101_FREQEST,CC1101_STATUS_REGISTER);
|
||||
if(FreqErr != 0 && gFreqErrSumCount < 255) {
|
||||
gFreqErrSum += FreqErr + gFreqCorrection;
|
||||
gFreqErrSumCount++;
|
||||
FreqCorrection = (int8_t) (gFreqErrSum / gFreqErrSumCount);
|
||||
if(gFreqCorrection != FreqCorrection) {
|
||||
LOGA("FreqCorrection %d -> %d\n",gFreqCorrection,FreqCorrection);
|
||||
gFreqCorrection = FreqCorrection;
|
||||
CC1101_writeReg(CC1101_FSCTRL0,gFreqCorrection);
|
||||
}
|
||||
if(gFreqErrSumCount == 255) {
|
||||
LOGA("Final FreqCorrection %d\n",gFreqCorrection);
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
setIdleState();
|
||||
flushRxFifo();
|
||||
CC1101_setRxState();
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
bool CC1101_Present()
|
||||
{
|
||||
bool Ret = false;
|
||||
uint8_t PartNum = CC1101_readReg(CC1101_PARTNUM, CC1101_STATUS_REGISTER);
|
||||
uint8_t ChipVersion = CC1101_readReg(CC1101_VERSION, CC1101_STATUS_REGISTER);
|
||||
|
||||
if(PartNum == 0 && (ChipVersion == 20 || ChipVersion == 4)) {
|
||||
LOGA("CC1101 detected\n");
|
||||
Ret = true;
|
||||
}
|
||||
else {
|
||||
if(PartNum != 0) {
|
||||
LOGA("Invalid PartNum 0x%x\n",PartNum);
|
||||
}
|
||||
else {
|
||||
LOGA("Invalid or unsupported ChipVersion 0x%x\n",ChipVersion);
|
||||
}
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void CC1101_SetConfig(const RfSetting *pConfig)
|
||||
{
|
||||
int i;
|
||||
uint8_t RegWasSet[CC1101_TEST0 + 1];
|
||||
uint8_t Reg;
|
||||
|
||||
memset(RegWasSet,0,sizeof(RegWasSet));
|
||||
setIdleState();
|
||||
|
||||
if(pConfig == NULL) {
|
||||
// Just set the fixed registers
|
||||
LOG("Setting fixed registers\n");
|
||||
for(i = 0; (Reg = gFixedConfig[i].Reg) != 0xff; i++) {
|
||||
CC1101_writeReg(Reg,gFixedConfig[i].Value);
|
||||
}
|
||||
// Set TX power
|
||||
CC1101_writeReg(CC1101_PATABLE,CC1101_DEFVAL_PATABLE);
|
||||
}
|
||||
else {
|
||||
for(i = 0; (Reg = gFixedConfig[i].Reg) != 0xff; i++) {
|
||||
RegWasSet[Reg] = 1;
|
||||
}
|
||||
|
||||
while((Reg = pConfig->Reg) != 0xff) {
|
||||
if(RegWasSet[Reg] == 1) {
|
||||
LOG("%s value ignored\n",RegNamesCC1101[Reg]);
|
||||
}
|
||||
else {
|
||||
if(RegWasSet[Reg] == 2) {
|
||||
LOG("%s value set before\n",RegNamesCC1101[Reg]);
|
||||
}
|
||||
CC1101_writeReg(pConfig->Reg,pConfig->Value);
|
||||
RegWasSet[Reg] = 2;
|
||||
}
|
||||
pConfig++;
|
||||
}
|
||||
#if 0
|
||||
for(Reg = 0; Reg <= CC1101_TEST0; Reg++) {
|
||||
if(RegWasSet[Reg] == 0) {
|
||||
LOG("%s value not set\n",RegNamesCC1101[Reg]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void setIdleState()
|
||||
{
|
||||
uint8_t MarcState;
|
||||
CC1101_cmdStrobe(CC1101_SIDLE);
|
||||
// Wait for it
|
||||
do {
|
||||
MarcState = readStatusReg(CC1101_MARCSTATE);
|
||||
} while(MarcState != CC1101_STATE_IDLE);
|
||||
}
|
||||
|
||||
|
||||
void CC1101_logState()
|
||||
{
|
||||
static uint8_t LastMarcState = 0xff;
|
||||
uint8_t MarcState;
|
||||
|
||||
MarcState = readStatusReg(CC1101_MARCSTATE);
|
||||
if(LastMarcState != MarcState) {
|
||||
LOG("MarcState 0x%x -> 0x%x\n",LastMarcState,MarcState);
|
||||
LastMarcState = MarcState;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
|
||||
118
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/cc1101_radio.h
Normal file
118
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/cc1101_radio.h
Normal file
@@ -0,0 +1,118 @@
|
||||
// Large portions of this code was copied from:
|
||||
// https://github.com/nopnop2002/esp-idf-cc1101 with the following copyright
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011 panStamp <contact@panstamp.com>
|
||||
* Copyright (c) 2016 Tyler Sommer <contact@tylersommer.pro>
|
||||
*
|
||||
* This file is part of the CC1101 project.
|
||||
*
|
||||
* CC1101 is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* CC1101 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with CC1101; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*
|
||||
* Author: Daniel Berenguer
|
||||
* Creation date: 03/03/2011
|
||||
*/
|
||||
|
||||
#ifndef __CC1101_RADIO_H_
|
||||
#define __CC1101_RADIO_H_
|
||||
|
||||
/**
|
||||
* CC1101 configuration registers
|
||||
*/
|
||||
#define CC1101_IOCFG2 0x00 // GDO2 Output Pin Configuration
|
||||
#define CC1101_IOCFG1 0x01 // GDO1 Output Pin Configuration
|
||||
#define CC1101_IOCFG0 0x02 // GDO0 Output Pin Configuration
|
||||
#define CC1101_FIFOTHR 0x03 // RX FIFO and TX FIFO Thresholds
|
||||
#define CC1101_SYNC1 0x04 // Sync Word, High Byte
|
||||
#define CC1101_SYNC0 0x05 // Sync Word, Low Byte
|
||||
#define CC1101_PKTLEN 0x06 // Packet Length
|
||||
#define CC1101_PKTCTRL1 0x07 // Packet Automation Control
|
||||
#define CC1101_PKTCTRL0 0x08 // Packet Automation Control
|
||||
#define CC1101_ADDR 0x09 // Device Address
|
||||
#define CC1101_CHANNR 0x0A // Channel Number
|
||||
#define CC1101_FSCTRL1 0x0B // Frequency Synthesizer Control
|
||||
#define CC1101_FSCTRL0 0x0C // Frequency Synthesizer Control
|
||||
#define CC1101_FREQ2 0x0D // Frequency Control Word, High Byte
|
||||
#define CC1101_FREQ1 0x0E // Frequency Control Word, Middle Byte
|
||||
#define CC1101_FREQ0 0x0F // Frequency Control Word, Low Byte
|
||||
#define CC1101_MDMCFG4 0x10 // Modem Configuration
|
||||
#define CC1101_MDMCFG3 0x11 // Modem Configuration
|
||||
#define CC1101_MDMCFG2 0x12 // Modem Configuration
|
||||
#define CC1101_MDMCFG1 0x13 // Modem Configuration
|
||||
#define CC1101_MDMCFG0 0x14 // Modem Configuration
|
||||
#define CC1101_DEVIATN 0x15 // Modem Deviation Setting
|
||||
#define CC1101_MCSM2 0x16 // Main Radio Control State Machine Configuration
|
||||
#define CC1101_MCSM1 0x17 // Main Radio Control State Machine Configuration
|
||||
#define CC1101_MCSM0 0x18 // Main Radio Control State Machine Configuration
|
||||
#define CC1101_FOCCFG 0x19 // Frequency Offset Compensation Configuration
|
||||
#define CC1101_BSCFG 0x1A // Bit Synchronization Configuration
|
||||
#define CC1101_AGCCTRL2 0x1B // AGC Control
|
||||
#define CC1101_AGCCTRL1 0x1C // AGC Control
|
||||
#define CC1101_AGCCTRL0 0x1D // AGC Control
|
||||
#define CC1101_WOREVT1 0x1E // High Byte Event0 Timeout
|
||||
#define CC1101_WOREVT0 0x1F // Low Byte Event0 Timeout
|
||||
#define CC1101_WORCTRL 0x20 // Wake On Radio Control
|
||||
#define CC1101_FREND1 0x21 // Front End RX Configuration
|
||||
#define CC1101_FREND0 0x22 // Front End TX Configuration
|
||||
#define CC1101_FSCAL3 0x23 // Frequency Synthesizer Calibration
|
||||
#define CC1101_FSCAL2 0x24 // Frequency Synthesizer Calibration
|
||||
#define CC1101_FSCAL1 0x25 // Frequency Synthesizer Calibration
|
||||
#define CC1101_FSCAL0 0x26 // Frequency Synthesizer Calibration
|
||||
#define CC1101_RCCTRL1 0x27 // RC Oscillator Configuration
|
||||
#define CC1101_RCCTRL0 0x28 // RC Oscillator Configuration
|
||||
#define CC1101_FSTEST 0x29 // Frequency Synthesizer Calibration Control
|
||||
#define CC1101_PTEST 0x2A // Production Test
|
||||
#define CC1101_AGCTEST 0x2B // AGC Test
|
||||
#define CC1101_TEST2 0x2C // Various Test Settings
|
||||
#define CC1101_TEST1 0x2D // Various Test Settings
|
||||
#define CC1101_TEST0 0x2E // Various Test Settings
|
||||
|
||||
/**
|
||||
* Status registers
|
||||
*/
|
||||
#define CC1101_PARTNUM 0x30 // Chip ID
|
||||
#define CC1101_VERSION 0x31 // Chip ID
|
||||
#define CC1101_FREQEST 0x32 // Frequency Offset Estimate from Demodulator
|
||||
#define CC1101_LQI 0x33 // Demodulator Estimate for Link Quality
|
||||
#define CC1101_RSSI 0x34 // Received Signal Strength Indication
|
||||
#define CC1101_MARCSTATE 0x35 // Main Radio Control State Machine State
|
||||
#define CC1101_WORTIME1 0x36 // High Byte of WOR Time
|
||||
#define CC1101_WORTIME0 0x37 // Low Byte of WOR Time
|
||||
#define CC1101_PKTSTATUS 0x38 // Current GDOx Status and Packet Status
|
||||
#define CC1101_VCO_VC_DAC 0x39 // Current Setting from PLL Calibration Module
|
||||
#define CC1101_TXBYTES 0x3A // Underflow and Number of Bytes
|
||||
#define CC1101_RXBYTES 0x3B // Overflow and Number of Bytes
|
||||
#define CC1101_RCCTRL1_STATUS 0x3C // Last RC Oscillator Calibration Result
|
||||
#define CC1101_RCCTRL0_STATUS 0x3D // Last RC Oscillator Calibration Result
|
||||
|
||||
typedef struct {
|
||||
uint16_t Reg;
|
||||
uint8_t Value;
|
||||
} RfSetting;
|
||||
|
||||
extern spi_device_handle_t gSpiHndl;
|
||||
|
||||
void CC1101_SetConfig(const RfSetting *pConfig);
|
||||
int CC1101_Rx(uint8_t *RxBuf,size_t RxBufLen,uint8_t *pRssi,uint8_t *pLqi);
|
||||
bool CC1101_Tx(uint8_t *TxData);
|
||||
bool CC1101_Present(void);
|
||||
void CC1101_DumpRegs(void);
|
||||
void CC1101_reset(void);
|
||||
void CC1101_logState(void);
|
||||
void CC1101_setRxState(void);
|
||||
|
||||
#endif // __CC1101_RADIO_H_
|
||||
|
||||
48
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/led.c
Normal file
48
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/led.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "led.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "proto.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NUM_LEDS 2
|
||||
|
||||
const gpio_num_t led_pins[NUM_LEDS] = {LED1, LED2};
|
||||
TimerHandle_t led_timers[NUM_LEDS] = {0};
|
||||
|
||||
void led_timer_callback(TimerHandle_t xTimer) {
|
||||
int led_index = (int)pvTimerGetTimerID(xTimer);
|
||||
if (led_index >= 0 && led_index < NUM_LEDS) {
|
||||
gpio_set_level(led_pins[led_index], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void init_led() {
|
||||
gpio_config_t led1 = {};
|
||||
led1.intr_type = GPIO_INTR_DISABLE;
|
||||
led1.mode = GPIO_MODE_OUTPUT;
|
||||
led1.pin_bit_mask = ((1ULL << LED1) | (1ULL << LED2));
|
||||
led1.pull_down_en = 0;
|
||||
led1.pull_up_en = 0;
|
||||
gpio_config(&led1);
|
||||
|
||||
for (int i = 0; i < NUM_LEDS; i++) {
|
||||
led_timers[i] = xTimerCreate("led_timer", pdMS_TO_TICKS(50), pdFALSE, (void *)i, led_timer_callback);
|
||||
}
|
||||
}
|
||||
|
||||
void led_flash(int nr) {
|
||||
gpio_set_level(led_pins[nr], 1);
|
||||
if (nr >= 0 && nr < NUM_LEDS) {
|
||||
xTimerStart(led_timers[nr], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void led_set(int nr, bool state) {
|
||||
gpio_set_level(nr, state);
|
||||
}
|
||||
6
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/led.h
Normal file
6
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/led.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
void init_led();
|
||||
void led_set(int nr, bool state);
|
||||
void led_flash(int nr);
|
||||
833
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/main.c
Normal file
833
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/main.c
Normal file
@@ -0,0 +1,833 @@
|
||||
// Ported to ESP32-H2 By ATC1441(ATCnetz.de) for OpenEPaperLink at ~08.2023
|
||||
|
||||
#include "main.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_ieee802154.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_phy_init.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "led.h"
|
||||
#include "proto.h"
|
||||
#include "radio.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "second_uart.h"
|
||||
//#include "soc/lp_uart_reg.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include "utils.h"
|
||||
#include <esp_mac.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "SubGigRadio.h"
|
||||
|
||||
|
||||
static const char *TAG = "MAIN";
|
||||
|
||||
const uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
|
||||
|
||||
#define DATATYPE_NOUPDATE 0
|
||||
#define HW_TYPE 0xC6
|
||||
|
||||
#define MAX_PENDING_MACS 250
|
||||
#define HOUSEKEEPING_INTERVAL 60UL
|
||||
|
||||
struct pendingData pendingDataArr[MAX_PENDING_MACS];
|
||||
|
||||
// VERSION GOES HERE!
|
||||
uint16_t version = 0x001d;
|
||||
|
||||
#define RAW_PKT_PADDING 2
|
||||
|
||||
uint8_t radiotxbuffer[128];
|
||||
uint8_t radiorxbuffer[128];
|
||||
|
||||
static uint32_t housekeepingTimer;
|
||||
|
||||
struct blockRequest requestedData = {0}; // holds which data was requested by the tag
|
||||
|
||||
uint8_t dstMac[8]; // target for the block transfer
|
||||
uint16_t dstPan; //
|
||||
|
||||
static uint32_t blockStartTimer = 0; // reference that holds when the AP sends the next block
|
||||
uint32_t nextBlockAttempt = 0; // reference time for when the AP can request a new block from the ESP32
|
||||
uint8_t seq = 0; // holds current sequence number for transmission
|
||||
uint8_t blockbuffer[BLOCK_XFER_BUFFER_SIZE + 5]; // block transfer buffer
|
||||
uint8_t lastAckMac[8] = {0};
|
||||
|
||||
// these variables hold the current mac were talking to
|
||||
#define CONCURRENT_REQUEST_DELAY 1200UL
|
||||
uint32_t lastBlockRequest = 0;
|
||||
uint8_t lastBlockMac[8];
|
||||
uint8_t lastTagReturn[8];
|
||||
|
||||
#define NO_SUBGHZ_CHANNEL 255
|
||||
uint8_t curSubGhzChannel;
|
||||
uint8_t curChannel = 25;
|
||||
uint8_t curPower = 10;
|
||||
|
||||
uint8_t curPendingData = 0;
|
||||
uint8_t curNoUpdate = 0;
|
||||
|
||||
bool highspeedSerial = false;
|
||||
|
||||
void sendXferCompleteAck(uint8_t *dst);
|
||||
void sendCancelXfer(uint8_t *dst);
|
||||
void espNotifyAPInfo();
|
||||
|
||||
// tools
|
||||
void addCRC(void *p, uint8_t len) {
|
||||
uint8_t total = 0;
|
||||
for (uint8_t c = 1; c < len; c++) {
|
||||
total += ((uint8_t *) p)[c];
|
||||
}
|
||||
((uint8_t *) p)[0] = total;
|
||||
}
|
||||
bool checkCRC(void *p, uint8_t len) {
|
||||
uint8_t total = 0;
|
||||
for (uint8_t c = 1; c < len; c++) {
|
||||
total += ((uint8_t *) p)[c];
|
||||
}
|
||||
return ((uint8_t *) p)[0] == total;
|
||||
}
|
||||
|
||||
uint8_t getPacketType(void *buffer) {
|
||||
struct MacFcs *fcs = buffer;
|
||||
if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) {
|
||||
// broadcast frame
|
||||
uint8_t type = ((uint8_t *) buffer)[sizeof(struct MacFrameBcast)];
|
||||
return type;
|
||||
} else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) {
|
||||
// normal frame
|
||||
uint8_t type = ((uint8_t *) buffer)[sizeof(struct MacFrameNormal)];
|
||||
return type;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
uint8_t getBlockDataLength() {
|
||||
uint8_t partNo = 0;
|
||||
for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) {
|
||||
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
|
||||
partNo++;
|
||||
}
|
||||
}
|
||||
return partNo;
|
||||
}
|
||||
|
||||
// pendingdata slot stuff
|
||||
int8_t findSlotForMac(const uint8_t *mac) {
|
||||
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
|
||||
if (memcmp(mac, ((uint8_t *) &(pendingDataArr[c].targetMac)), 8) == 0) {
|
||||
if (pendingDataArr[c].attemptsLeft != 0) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int8_t findFreeSlot() {
|
||||
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
|
||||
if (pendingDataArr[c].attemptsLeft == 0) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int8_t findSlotForVer(const uint8_t *ver) {
|
||||
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
|
||||
if (memcmp(ver, ((uint8_t *) &(pendingDataArr[c].availdatainfo.dataVer)), 8) == 0) {
|
||||
if (pendingDataArr[c].attemptsLeft != 0) return c;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void deleteAllPendingDataForVer(const uint8_t *ver) {
|
||||
int8_t slot = -1;
|
||||
do {
|
||||
slot = findSlotForVer(ver);
|
||||
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
|
||||
} while (slot != -1);
|
||||
}
|
||||
void deleteAllPendingDataForMac(const uint8_t *mac) {
|
||||
int8_t slot = -1;
|
||||
do {
|
||||
slot = findSlotForMac(mac);
|
||||
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
|
||||
} while (slot != -1);
|
||||
}
|
||||
|
||||
void countSlots() {
|
||||
curPendingData = 0;
|
||||
curNoUpdate = 0;
|
||||
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
|
||||
if (pendingDataArr[c].attemptsLeft != 0) {
|
||||
if (pendingDataArr[c].availdatainfo.dataType != 0) {
|
||||
curPendingData++;
|
||||
} else {
|
||||
curNoUpdate++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// processing serial data
|
||||
#define ZBS_RX_WAIT_HEADER 0
|
||||
#define ZBS_RX_WAIT_SDA 1 // send data avail
|
||||
#define ZBS_RX_WAIT_CANCEL 2 // cancel traffic for mac
|
||||
#define ZBS_RX_WAIT_SCP 3 // set channel power
|
||||
#define ZBS_RX_WAIT_BLOCKDATA 4
|
||||
|
||||
bool isSame(uint8_t *in1, char *in2, int len) {
|
||||
bool flag = 1;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (in1[i] != in2[i]) flag = 0;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
int blockPosition = 0;
|
||||
void processSerial(uint8_t lastchar) {
|
||||
static uint8_t cmdbuffer[4];
|
||||
static uint8_t RXState = 0;
|
||||
static uint8_t serialbuffer[48];
|
||||
static uint8_t *serialbufferp;
|
||||
static uint8_t bytesRemain = 0;
|
||||
static uint32_t lastSerial = 0;
|
||||
static uint32_t blockStartTime = 0;
|
||||
if ((RXState != ZBS_RX_WAIT_HEADER) && ((getMillis() - lastSerial) > 1000)) {
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
ESP_LOGI(TAG, "UART Timeout");
|
||||
}
|
||||
lastSerial = getMillis();
|
||||
switch (RXState) {
|
||||
case ZBS_RX_WAIT_HEADER:
|
||||
// shift characters in
|
||||
for (uint8_t c = 0; c < 3; c++) {
|
||||
cmdbuffer[c] = cmdbuffer[c + 1];
|
||||
}
|
||||
cmdbuffer[3] = lastchar;
|
||||
|
||||
if (isSame(cmdbuffer + 1, ">D>", 3)) {
|
||||
pr("ACK>");
|
||||
blockStartTime = getMillis();
|
||||
ESP_LOGI(TAG, "Starting BlkData, %lu ms after request", blockStartTime - nextBlockAttempt );
|
||||
blockPosition = 0;
|
||||
RXState = ZBS_RX_WAIT_BLOCKDATA;
|
||||
}
|
||||
|
||||
if (isSame(cmdbuffer, "SDA>", 4)) {
|
||||
ESP_LOGI(TAG, "SDA In");
|
||||
RXState = ZBS_RX_WAIT_SDA;
|
||||
bytesRemain = sizeof(struct pendingData);
|
||||
serialbufferp = serialbuffer;
|
||||
break;
|
||||
}
|
||||
if (isSame(cmdbuffer, "CXD>", 4)) {
|
||||
ESP_LOGI(TAG, "CXD In");
|
||||
RXState = ZBS_RX_WAIT_CANCEL;
|
||||
bytesRemain = sizeof(struct pendingData);
|
||||
serialbufferp = serialbuffer;
|
||||
break;
|
||||
}
|
||||
if (isSame(cmdbuffer, "SCP>", 4)) {
|
||||
ESP_LOGI(TAG, "SCP In");
|
||||
RXState = ZBS_RX_WAIT_SCP;
|
||||
bytesRemain = sizeof(struct espSetChannelPower);
|
||||
serialbufferp = serialbuffer;
|
||||
break;
|
||||
}
|
||||
if (isSame(cmdbuffer, "NFO?", 4)) {
|
||||
pr("ACK>");
|
||||
ESP_LOGI(TAG, "NFO? In");
|
||||
espNotifyAPInfo();
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
if (isSame(cmdbuffer, "RDY?", 4)) {
|
||||
pr("ACK>");
|
||||
ESP_LOGI(TAG, "RDY? In");
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
if (isSame(cmdbuffer, "RSET", 4)) {
|
||||
pr("ACK>");
|
||||
ESP_LOGI(TAG, "RSET In");
|
||||
delay(100);
|
||||
// TODO RESET US HERE
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
if (isSame(cmdbuffer, "HSPD", 4)) {
|
||||
pr("ACK>");
|
||||
ESP_LOGI(TAG, "HSPD In, switching to 2000000");
|
||||
delay(100);
|
||||
uart_switch_speed(2000000);
|
||||
delay(100);
|
||||
highspeedSerial = true;
|
||||
pr("ACK>");
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
break;
|
||||
case ZBS_RX_WAIT_BLOCKDATA:
|
||||
blockbuffer[blockPosition++] = 0xAA ^ lastchar;
|
||||
if (blockPosition >= 4100) {
|
||||
ESP_LOGI(TAG, "Blockdata fully received in %lu ms, %lu ms after the request", getMillis() - blockStartTime, getMillis() - nextBlockAttempt);
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZBS_RX_WAIT_SDA:
|
||||
*serialbufferp = lastchar;
|
||||
serialbufferp++;
|
||||
bytesRemain--;
|
||||
if (bytesRemain == 0) {
|
||||
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
|
||||
struct pendingData *pd = (struct pendingData *) serialbuffer;
|
||||
int8_t slot = findSlotForMac(pd->targetMac);
|
||||
if (slot == -1) slot = findFreeSlot();
|
||||
if (slot != -1) {
|
||||
memcpy(&(pendingDataArr[slot]), serialbuffer, sizeof(struct pendingData));
|
||||
pr("ACK>");
|
||||
} else {
|
||||
pr("NOQ>");
|
||||
}
|
||||
} else {
|
||||
pr("NOK>");
|
||||
}
|
||||
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
break;
|
||||
case ZBS_RX_WAIT_CANCEL:
|
||||
*serialbufferp = lastchar;
|
||||
serialbufferp++;
|
||||
bytesRemain--;
|
||||
if (bytesRemain == 0) {
|
||||
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
|
||||
struct pendingData *pd = (struct pendingData *) serialbuffer;
|
||||
deleteAllPendingDataForMac((uint8_t *) &pd->targetMac);
|
||||
pr("ACK>");
|
||||
} else {
|
||||
pr("NOK>");
|
||||
}
|
||||
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
break;
|
||||
case ZBS_RX_WAIT_SCP:
|
||||
*serialbufferp = lastchar;
|
||||
serialbufferp++;
|
||||
bytesRemain--;
|
||||
if (bytesRemain == 0) {
|
||||
if (checkCRC(serialbuffer, sizeof(struct espSetChannelPower))) {
|
||||
struct espSetChannelPower *scp = (struct espSetChannelPower *) serialbuffer;
|
||||
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
if(curSubGhzChannel != scp->subghzchannel
|
||||
&& curSubGhzChannel != NO_SUBGHZ_CHANNEL)
|
||||
{
|
||||
curSubGhzChannel = scp->subghzchannel;
|
||||
ESP_LOGI(TAG,"Set SubGhz channel: %d",curSubGhzChannel);
|
||||
SubGig_radioSetChannel(scp->subghzchannel);
|
||||
if(scp->channel == 0) {
|
||||
// Not setting 802.15.4 channel
|
||||
goto SCPchannelFound;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (uint8_t c = 0; c < sizeof(channelList); c++) {
|
||||
if (channelList[c] == scp->channel) goto SCPchannelFound;
|
||||
}
|
||||
goto SCPfailed;
|
||||
SCPchannelFound:
|
||||
pr("ACK>");
|
||||
if (curChannel != scp->channel) {
|
||||
radioSetChannel(scp->channel);
|
||||
curChannel = scp->channel;
|
||||
}
|
||||
curPower = scp->power;
|
||||
radioSetTxPower(scp->power);
|
||||
ESP_LOGI(TAG, "Set channel: %d power: %d", curChannel, curPower);
|
||||
} else {
|
||||
SCPfailed:
|
||||
pr("NOK>");
|
||||
}
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// sending data to the ESP
|
||||
void espBlockRequest(const struct blockRequest *br, uint8_t *src) {
|
||||
struct espBlockRequest *ebr = (struct espBlockRequest *) blockbuffer;
|
||||
uartTx('R');
|
||||
uartTx('Q');
|
||||
uartTx('B');
|
||||
uartTx('>');
|
||||
memcpy(&(ebr->ver), &(br->ver), 8);
|
||||
memcpy(&(ebr->src), src, 8);
|
||||
ebr->blockId = br->blockId;
|
||||
addCRC(ebr, sizeof(struct espBlockRequest));
|
||||
for (uint8_t c = 0; c < sizeof(struct espBlockRequest); c++) {
|
||||
uartTx(((uint8_t *) ebr)[c]);
|
||||
}
|
||||
}
|
||||
void espNotifyAvailDataReq(const struct AvailDataReq *adr, const uint8_t *src) {
|
||||
uartTx('A');
|
||||
uartTx('D');
|
||||
uartTx('R');
|
||||
uartTx('>');
|
||||
|
||||
struct espAvailDataReq eadr = {0};
|
||||
memcpy((void *) eadr.src, (void *) src, 8);
|
||||
memcpy((void *) &eadr.adr, (void *) adr, sizeof(struct AvailDataReq));
|
||||
addCRC(&eadr, sizeof(struct espAvailDataReq));
|
||||
for (uint8_t c = 0; c < sizeof(struct espAvailDataReq); c++) {
|
||||
uartTx(((uint8_t *) &eadr)[c]);
|
||||
}
|
||||
}
|
||||
void espNotifyXferComplete(const uint8_t *src) {
|
||||
struct espXferComplete exfc;
|
||||
memcpy(&exfc.src, src, 8);
|
||||
uartTx('X');
|
||||
uartTx('F');
|
||||
uartTx('C');
|
||||
uartTx('>');
|
||||
addCRC(&exfc, sizeof(exfc));
|
||||
for (uint8_t c = 0; c < sizeof(exfc); c++) {
|
||||
uartTx(((uint8_t *) &exfc)[c]);
|
||||
}
|
||||
}
|
||||
void espNotifyTimeOut(const uint8_t *src) {
|
||||
struct espXferComplete exfc;
|
||||
memcpy(&exfc.src, src, 8);
|
||||
uartTx('X');
|
||||
uartTx('T');
|
||||
uartTx('O');
|
||||
uartTx('>');
|
||||
addCRC(&exfc, sizeof(exfc));
|
||||
for (uint8_t c = 0; c < sizeof(exfc); c++) {
|
||||
uartTx(((uint8_t *) &exfc)[c]);
|
||||
}
|
||||
}
|
||||
void espNotifyAPInfo() {
|
||||
pr("TYP>%02X", HW_TYPE);
|
||||
pr("VER>%04X", version);
|
||||
pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]);
|
||||
pr("%02X%02X", mSelfMac[2], mSelfMac[3]);
|
||||
pr("%02X%02X", mSelfMac[4], mSelfMac[5]);
|
||||
pr("%02X%02X", mSelfMac[6], mSelfMac[7]);
|
||||
pr("ZCH>%02X", curChannel);
|
||||
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
pr("SCH>%03d",curSubGhzChannel);
|
||||
#endif
|
||||
pr("ZPW>%02X", curPower);
|
||||
countSlots();
|
||||
pr("PEN>%02X", curPendingData);
|
||||
pr("NOP>%02X", curNoUpdate);
|
||||
}
|
||||
|
||||
void espNotifyTagReturnData(uint8_t *src, uint8_t len) {
|
||||
struct tagReturnData *trd = (struct tagReturnData *)(radiorxbuffer + sizeof(struct MacFrameBcast) + 1); // oh how I'd love to pass this as an argument, but sdcc won't let me
|
||||
struct espTagReturnData *etrd = (struct espTagReturnData *)radiotxbuffer;
|
||||
|
||||
if (memcmp((void *) & trd->dataVer, lastTagReturn, 8) == 0) {
|
||||
return;
|
||||
} else {
|
||||
memcpy(lastTagReturn, &trd->dataVer, 8);
|
||||
}
|
||||
|
||||
memcpy(etrd->src, src, 8);
|
||||
etrd->len = len;
|
||||
memcpy(&etrd->returnData, trd, len);
|
||||
addCRC(etrd, len + 10);
|
||||
|
||||
uartTx('T');
|
||||
uartTx('R');
|
||||
uartTx('D');
|
||||
uartTx('>');
|
||||
for (uint8_t c = 0; c < len + 10; c++) {
|
||||
uartTx(((uint8_t *)etrd)[c]);
|
||||
}
|
||||
}
|
||||
|
||||
// process data from tag
|
||||
void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) {
|
||||
struct MacFrameNormal *rxHeader = (struct MacFrameNormal *) buffer;
|
||||
struct blockRequest *blockReq = (struct blockRequest *) (buffer + sizeof(struct MacFrameNormal) + 1);
|
||||
if (!checkCRC(blockReq, sizeof(struct blockRequest))) return;
|
||||
|
||||
// check if we're already talking to this mac
|
||||
if (memcmp(rxHeader->src, lastBlockMac, 8) == 0) {
|
||||
lastBlockRequest = getMillis();
|
||||
} else {
|
||||
// we weren't talking to this mac, see if there was a transfer in progress from another mac, recently
|
||||
if ((getMillis() - lastBlockRequest) > CONCURRENT_REQUEST_DELAY) {
|
||||
// mark this mac as the new current mac we're talking to
|
||||
memcpy((void *) lastBlockMac, (void *) rxHeader->src, 8);
|
||||
lastBlockRequest = getMillis();
|
||||
} else {
|
||||
// we're talking to another mac, let this mac know we can't accomodate another request right now
|
||||
pr("BUSY!\n");
|
||||
sendCancelXfer(rxHeader->src);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// check if we have data for this mac
|
||||
if (findSlotForMac(rxHeader->src) == -1) {
|
||||
// no data for this mac, politely tell it to fuck off
|
||||
sendCancelXfer(rxHeader->src);
|
||||
return;
|
||||
}
|
||||
|
||||
bool requestDataDownload = false;
|
||||
if ((blockReq->blockId != requestedData.blockId) || (blockReq->ver != requestedData.ver)) {
|
||||
// requested block isn't already in the buffer
|
||||
requestDataDownload = true;
|
||||
} else {
|
||||
// requested block is already in the buffer
|
||||
if (forceBlockDownload) {
|
||||
if ((getMillis() - nextBlockAttempt) > 380) {
|
||||
requestDataDownload = true;
|
||||
pr("FORCED\n");
|
||||
} else {
|
||||
pr("IGNORED\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy blockrequest into requested data
|
||||
memcpy(&requestedData, blockReq, sizeof(struct blockRequest));
|
||||
|
||||
struct MacFrameNormal *txHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
|
||||
struct blockRequestAck *blockRequestAck = (struct blockRequestAck *) (radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
|
||||
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct blockRequestAck) + RAW_PKT_PADDING;
|
||||
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_REQUEST_ACK;
|
||||
|
||||
if (blockStartTimer == 0) {
|
||||
if (requestDataDownload) {
|
||||
if (highspeedSerial == true) {
|
||||
blockRequestAck->pleaseWaitMs = 140;
|
||||
} else {
|
||||
blockRequestAck->pleaseWaitMs = 550;
|
||||
}
|
||||
} else {
|
||||
// block is already in buffer
|
||||
blockRequestAck->pleaseWaitMs = 30;
|
||||
}
|
||||
} else {
|
||||
blockRequestAck->pleaseWaitMs = 30;
|
||||
}
|
||||
blockStartTimer = getMillis() + blockRequestAck->pleaseWaitMs;
|
||||
|
||||
memcpy(txHeader->src, mSelfMac, 8);
|
||||
memcpy(txHeader->dst, rxHeader->src, 8);
|
||||
|
||||
txHeader->pan = rxHeader->pan;
|
||||
txHeader->fcs.frameType = 1;
|
||||
txHeader->fcs.panIdCompressed = 1;
|
||||
txHeader->fcs.destAddrType = 3;
|
||||
txHeader->fcs.srcAddrType = 3;
|
||||
txHeader->seq = seq++;
|
||||
|
||||
addCRC((void *) blockRequestAck, sizeof(struct blockRequestAck));
|
||||
|
||||
radioTx(radiotxbuffer);
|
||||
|
||||
// save the target for the blockdata
|
||||
memcpy(dstMac, rxHeader->src, 8);
|
||||
dstPan = rxHeader->pan;
|
||||
|
||||
if (requestDataDownload) {
|
||||
blockPosition = 0;
|
||||
espBlockRequest(&requestedData, rxHeader->src);
|
||||
nextBlockAttempt = getMillis();
|
||||
}
|
||||
}
|
||||
|
||||
void processAvailDataReq(uint8_t *buffer) {
|
||||
struct MacFrameBcast *rxHeader = (struct MacFrameBcast *) buffer;
|
||||
struct AvailDataReq *availDataReq = (struct AvailDataReq *) (buffer + sizeof(struct MacFrameBcast) + 1);
|
||||
|
||||
if (!checkCRC(availDataReq, sizeof(struct AvailDataReq))) return;
|
||||
|
||||
// prepare tx buffer to send a response
|
||||
memset(radiotxbuffer, 0, sizeof(struct MacFrameNormal) + sizeof(struct AvailDataInfo) + 2); // 120);
|
||||
struct MacFrameNormal *txHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
|
||||
struct AvailDataInfo *availDataInfo = (struct AvailDataInfo *) (radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
|
||||
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct AvailDataInfo) + RAW_PKT_PADDING;
|
||||
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_AVAIL_DATA_INFO;
|
||||
|
||||
// check to see if we have data available for this mac
|
||||
bool haveData = false;
|
||||
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
|
||||
if (pendingDataArr[c].attemptsLeft) {
|
||||
if (memcmp(pendingDataArr[c].targetMac, rxHeader->src, 8) == 0) {
|
||||
haveData = true;
|
||||
memcpy((void *) availDataInfo, &(pendingDataArr[c].availdatainfo), sizeof(struct AvailDataInfo));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// couldn't find data for this mac
|
||||
if (!haveData) availDataInfo->dataType = DATATYPE_NOUPDATE;
|
||||
|
||||
memcpy(txHeader->src, mSelfMac, 8);
|
||||
memcpy(txHeader->dst, rxHeader->src, 8);
|
||||
txHeader->pan = rxHeader->dstPan;
|
||||
txHeader->fcs.frameType = 1;
|
||||
txHeader->fcs.panIdCompressed = 1;
|
||||
txHeader->fcs.destAddrType = 3;
|
||||
txHeader->fcs.srcAddrType = 3;
|
||||
txHeader->seq = seq++;
|
||||
addCRC(availDataInfo, sizeof(struct AvailDataInfo));
|
||||
radioTx(radiotxbuffer);
|
||||
memset(lastAckMac, 0, 8); // reset lastAckMac, so we can record if we've received exactly one ack packet
|
||||
espNotifyAvailDataReq(availDataReq, rxHeader->src);
|
||||
}
|
||||
void processXferComplete(uint8_t *buffer) {
|
||||
struct MacFrameNormal *rxHeader = (struct MacFrameNormal *) buffer;
|
||||
sendXferCompleteAck(rxHeader->src);
|
||||
if (memcmp(lastAckMac, rxHeader->src, 8) != 0) {
|
||||
memcpy((void *) lastAckMac, (void *) rxHeader->src, 8);
|
||||
espNotifyXferComplete(rxHeader->src);
|
||||
int8_t slot = findSlotForMac(rxHeader->src);
|
||||
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void processTagReturnData(uint8_t *buffer, uint8_t len) {
|
||||
struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buffer;
|
||||
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
|
||||
|
||||
if (!checkCRC((buffer + sizeof(struct MacFrameBcast) + 1), len - (sizeof(struct MacFrameBcast) + 1))) {
|
||||
return;
|
||||
}
|
||||
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_TAG_RETURN_DATA_ACK;
|
||||
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
|
||||
memcpy(frameHeader->src, mSelfMac, 8);
|
||||
memcpy(frameHeader->dst, rxframe->src, 8);
|
||||
radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits
|
||||
radiotxbuffer[2] = 0xCC; // normal frame
|
||||
frameHeader->seq = seq++;
|
||||
frameHeader->pan = rxframe->srcPan;
|
||||
radioTx(radiotxbuffer);
|
||||
|
||||
espNotifyTagReturnData(rxframe->src, len - (sizeof(struct MacFrameBcast) + 1));
|
||||
}
|
||||
|
||||
// send block data to the tag
|
||||
void sendPart(uint8_t partNo) {
|
||||
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
|
||||
struct blockPart *blockPart = (struct blockPart *) (radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
|
||||
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
|
||||
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_PART;
|
||||
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE + 1 + RAW_PKT_PADDING;
|
||||
memcpy(frameHeader->src, mSelfMac, 8);
|
||||
memcpy(frameHeader->dst, dstMac, 8);
|
||||
blockPart->blockId = requestedData.blockId;
|
||||
blockPart->blockPart = partNo;
|
||||
memcpy(&(blockPart->data), blockbuffer + (partNo * BLOCK_PART_DATA_SIZE), BLOCK_PART_DATA_SIZE);
|
||||
addCRC(blockPart, sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE);
|
||||
frameHeader->fcs.frameType = 1;
|
||||
frameHeader->fcs.panIdCompressed = 1;
|
||||
frameHeader->fcs.destAddrType = 3;
|
||||
frameHeader->fcs.srcAddrType = 3;
|
||||
frameHeader->seq = seq++;
|
||||
frameHeader->pan = dstPan;
|
||||
radioTx(radiotxbuffer);
|
||||
}
|
||||
void sendBlockData() {
|
||||
if (getBlockDataLength() == 0) {
|
||||
pr("Invalid block request received, 0 parts..\n");
|
||||
requestedData.requestedParts[0] |= 0x01;
|
||||
}
|
||||
|
||||
pr("Sending parts:");
|
||||
for (uint8_t c = 0; (c < BLOCK_MAX_PARTS); c++) {
|
||||
if (c % 10 == 0) pr(" ");
|
||||
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
|
||||
pr("X");
|
||||
} else {
|
||||
pr(".");
|
||||
}
|
||||
}
|
||||
pr("\n");
|
||||
|
||||
uint8_t partNo = 0;
|
||||
while (partNo < BLOCK_MAX_PARTS) {
|
||||
for (uint8_t c = 0; (c < BLOCK_MAX_PARTS) && (partNo < BLOCK_MAX_PARTS); c++) {
|
||||
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
|
||||
sendPart(c);
|
||||
partNo++;
|
||||
}
|
||||
}
|
||||
if(dstPan == PROTO_PAN_ID_SUBGHZ) {
|
||||
// Don't send BLOCK_MAX_PARTS for subgig, it requests what it
|
||||
// can handle with its limited RAM
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void sendXferCompleteAck(uint8_t *dst) {
|
||||
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
|
||||
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
|
||||
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_XFER_COMPLETE_ACK;
|
||||
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
|
||||
memcpy(frameHeader->src, mSelfMac, 8);
|
||||
memcpy(frameHeader->dst, dst, 8);
|
||||
frameHeader->fcs.frameType = 1;
|
||||
frameHeader->fcs.panIdCompressed = 1;
|
||||
frameHeader->fcs.destAddrType = 3;
|
||||
frameHeader->fcs.srcAddrType = 3;
|
||||
frameHeader->seq = seq++;
|
||||
frameHeader->pan = dstPan;
|
||||
radioTx(radiotxbuffer);
|
||||
}
|
||||
void sendCancelXfer(uint8_t *dst) {
|
||||
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
|
||||
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
|
||||
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_CANCEL_XFER;
|
||||
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
|
||||
memcpy(frameHeader->src, mSelfMac, 8);
|
||||
memcpy(frameHeader->dst, dst, 8);
|
||||
frameHeader->fcs.frameType = 1;
|
||||
frameHeader->fcs.panIdCompressed = 1;
|
||||
frameHeader->fcs.destAddrType = 3;
|
||||
frameHeader->fcs.srcAddrType = 3;
|
||||
frameHeader->seq = seq++;
|
||||
frameHeader->pan = dstPan;
|
||||
radioTx(radiotxbuffer);
|
||||
}
|
||||
void sendPong(void *buf) {
|
||||
struct MacFrameBcast *rxframe = (struct MacFrameBcast *) buf;
|
||||
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
|
||||
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_PONG;
|
||||
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
if(rxframe->srcPan == PROTO_PAN_ID_SUBGHZ) {
|
||||
radiotxbuffer[sizeof(struct MacFrameNormal) + 2] = curSubGhzChannel;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
radiotxbuffer[sizeof(struct MacFrameNormal) + 2] = curChannel;
|
||||
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + 1 + RAW_PKT_PADDING;
|
||||
memcpy(frameHeader->src, mSelfMac, 8);
|
||||
memcpy(frameHeader->dst, rxframe->src, 8);
|
||||
radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits
|
||||
radiotxbuffer[2] = 0xCC; // normal frame
|
||||
frameHeader->seq = seq++;
|
||||
frameHeader->pan = rxframe->srcPan;
|
||||
radioTx(radiotxbuffer);
|
||||
}
|
||||
|
||||
void app_main(void) {
|
||||
esp_event_loop_create_default();
|
||||
|
||||
init_nvs();
|
||||
init_led();
|
||||
init_second_uart();
|
||||
|
||||
requestedData.blockId = 0xFF;
|
||||
// clear the array with pending information
|
||||
memset(pendingDataArr, 0, sizeof(pendingDataArr));
|
||||
|
||||
radio_init(curChannel);
|
||||
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
if(SubGig_radio_init(curSubGhzChannel)) {
|
||||
// Ether we don't have a cc1101 or it's not working
|
||||
curSubGhzChannel = NO_SUBGHZ_CHANNEL;
|
||||
ESP_LOGI(TAG,"CC1101 NOT detected.");
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(TAG,"CC1101 detected.");
|
||||
}
|
||||
#endif
|
||||
radioSetTxPower(10);
|
||||
|
||||
pr("RES>");
|
||||
pr("RDY>");
|
||||
ESP_LOGI(TAG, "H2 ready!");
|
||||
|
||||
housekeepingTimer = getMillis();
|
||||
while (1) {
|
||||
while ((getMillis() - housekeepingTimer) < ((1000 * HOUSEKEEPING_INTERVAL) - 100)) {
|
||||
int8_t ret = commsRxUnencrypted(radiorxbuffer);
|
||||
if (ret > 1) {
|
||||
led_flash(0);
|
||||
// received a packet, lets see what it is
|
||||
switch (getPacketType(radiorxbuffer)) {
|
||||
case PKT_AVAIL_DATA_REQ:
|
||||
if (ret == 28) {
|
||||
// old version of the AvailDataReq struct, set all the new fields to zero, so it will pass the CRC
|
||||
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast) + sizeof(struct oldAvailDataReq), 0,
|
||||
sizeof(struct AvailDataReq) - sizeof(struct oldAvailDataReq) + 2);
|
||||
processAvailDataReq(radiorxbuffer);
|
||||
} else if (ret == 40) {
|
||||
// new version of the AvailDataReq struct
|
||||
processAvailDataReq(radiorxbuffer);
|
||||
}
|
||||
break;
|
||||
case PKT_BLOCK_REQUEST:
|
||||
processBlockRequest(radiorxbuffer, 1);
|
||||
break;
|
||||
case PKT_BLOCK_PARTIAL_REQUEST:
|
||||
processBlockRequest(radiorxbuffer, 0);
|
||||
break;
|
||||
case PKT_XFER_COMPLETE:
|
||||
processXferComplete(radiorxbuffer);
|
||||
break;
|
||||
case PKT_PING:
|
||||
sendPong(radiorxbuffer);
|
||||
break;
|
||||
case PKT_AVAIL_DATA_SHORTREQ:
|
||||
// a short AvailDataReq is basically a very short (1 byte payload) packet that requires little preparation on the tx side, for optimal
|
||||
// battery use bytes of the struct are set 0, so it passes the checksum test, and the ESP32 can detect that no interesting payload is
|
||||
// sent
|
||||
if (ret == 18) {
|
||||
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast), 0, sizeof(struct AvailDataReq) + 2);
|
||||
processAvailDataReq(radiorxbuffer);
|
||||
}
|
||||
break;
|
||||
case PKT_TAG_RETURN_DATA:
|
||||
processTagReturnData(radiorxbuffer, ret);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "t=%02X" , getPacketType(radiorxbuffer));
|
||||
break;
|
||||
}
|
||||
} else if (blockStartTimer == 0) {
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
uint8_t curr_char;
|
||||
while (getRxCharSecond(&curr_char)) processSerial(curr_char);
|
||||
|
||||
if (blockStartTimer) {
|
||||
if (getMillis() > blockStartTimer) {
|
||||
sendBlockData();
|
||||
blockStartTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memset(&lastTagReturn, 0, 8);
|
||||
for (uint8_t cCount = 0; cCount < MAX_PENDING_MACS; cCount++) {
|
||||
if (pendingDataArr[cCount].attemptsLeft == 1) {
|
||||
if (pendingDataArr[cCount].availdatainfo.dataType != DATATYPE_NOUPDATE) {
|
||||
espNotifyTimeOut(pendingDataArr[cCount].targetMac);
|
||||
}
|
||||
pendingDataArr[cCount].attemptsLeft = 0;
|
||||
} else if (pendingDataArr[cCount].attemptsLeft > 1) {
|
||||
pendingDataArr[cCount].attemptsLeft--;
|
||||
if (pendingDataArr[cCount].availdatainfo.nextCheckIn) pendingDataArr[cCount].availdatainfo.nextCheckIn--;
|
||||
}
|
||||
}
|
||||
housekeepingTimer = getMillis();
|
||||
}
|
||||
}
|
||||
1
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/main.h
Normal file
1
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/main.h
Normal file
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
194
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/proto.h
Normal file
194
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/proto.h
Normal file
@@ -0,0 +1,194 @@
|
||||
#ifndef _PROTO_H_
|
||||
#define _PROTO_H_
|
||||
#include <stdint.h>
|
||||
|
||||
#define LED1 22
|
||||
#define LED2 25
|
||||
|
||||
#define PROTO_PAN_ID (0x4447) // PAN ID compression shall be used
|
||||
#define PROTO_PAN_ID_SUBGHZ (0x1337) // PAN ID compression shall be used
|
||||
|
||||
#define RADIO_MAX_PACKET_LEN (125) // useful payload, not including the crc
|
||||
|
||||
#define ADDR_MODE_NONE (0)
|
||||
#define ADDR_MODE_SHORT (2)
|
||||
#define ADDR_MODE_LONG (3)
|
||||
|
||||
#define FRAME_TYPE_BEACON (0)
|
||||
#define FRAME_TYPE_DATA (1)
|
||||
#define FRAME_TYPE_ACK (2)
|
||||
#define FRAME_TYPE_MAC_CMD (3)
|
||||
|
||||
#define SHORT_MAC_UNUSED (0x10000000UL) // for radioRxFilterCfg's myShortMac
|
||||
|
||||
struct MacFcs {
|
||||
uint8_t frameType : 3;
|
||||
uint8_t secure : 1;
|
||||
uint8_t framePending : 1;
|
||||
uint8_t ackReqd : 1;
|
||||
uint8_t panIdCompressed : 1;
|
||||
uint8_t rfu1 : 1;
|
||||
uint8_t rfu2 : 2;
|
||||
uint8_t destAddrType : 2;
|
||||
uint8_t frameVer : 2;
|
||||
uint8_t srcAddrType : 2;
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct MacFrameFromMaster {
|
||||
struct MacFcs fcs;
|
||||
uint8_t seq;
|
||||
uint16_t pan;
|
||||
uint8_t dst[8];
|
||||
uint16_t from;
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct MacFrameNormal {
|
||||
struct MacFcs fcs;
|
||||
uint8_t seq;
|
||||
uint16_t pan;
|
||||
uint8_t dst[8];
|
||||
uint8_t src[8];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct MacFrameBcast {
|
||||
struct MacFcs fcs;
|
||||
uint8_t seq;
|
||||
uint16_t dstPan;
|
||||
uint16_t dstAddr;
|
||||
uint16_t srcPan;
|
||||
uint8_t src[8];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
#define PKT_TAG_RETURN_DATA 0xE1
|
||||
#define PKT_TAG_RETURN_DATA_ACK 0xE2
|
||||
#define PKT_AVAIL_DATA_SHORTREQ 0xE3
|
||||
#define PKT_AVAIL_DATA_REQ 0xE5
|
||||
#define PKT_AVAIL_DATA_INFO 0xE6
|
||||
#define PKT_BLOCK_PARTIAL_REQUEST 0xE7
|
||||
#define PKT_BLOCK_REQUEST_ACK 0xE9
|
||||
#define PKT_BLOCK_REQUEST 0xE4
|
||||
#define PKT_BLOCK_PART 0xE8
|
||||
#define PKT_XFER_COMPLETE 0xEA
|
||||
#define PKT_XFER_COMPLETE_ACK 0xEB
|
||||
#define PKT_CANCEL_XFER 0xEC
|
||||
#define PKT_PING 0xED
|
||||
#define PKT_PONG 0xEE
|
||||
|
||||
struct AvailDataReq {
|
||||
uint8_t checksum;
|
||||
uint8_t lastPacketLQI;
|
||||
int8_t lastPacketRSSI;
|
||||
int8_t temperature;
|
||||
uint16_t batteryMv;
|
||||
uint8_t hwType;
|
||||
uint8_t wakeupReason;
|
||||
uint8_t capabilities;
|
||||
uint16_t tagSoftwareVersion;
|
||||
uint8_t currentChannel;
|
||||
uint8_t customMode;
|
||||
uint8_t reserved[8];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct oldAvailDataReq {
|
||||
uint8_t checksum;
|
||||
uint8_t lastPacketLQI;
|
||||
int8_t lastPacketRSSI;
|
||||
int8_t temperature;
|
||||
uint16_t batteryMv;
|
||||
uint8_t hwType;
|
||||
uint8_t wakeupReason;
|
||||
uint8_t capabilities;
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct AvailDataInfo {
|
||||
uint8_t checksum;
|
||||
uint64_t dataVer; // MD5 of potential traffic
|
||||
uint32_t dataSize;
|
||||
uint8_t dataType;
|
||||
uint8_t dataTypeArgument; // extra specification or instruction for the tag (LUT to be used for drawing image)
|
||||
uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct pendingData {
|
||||
struct AvailDataInfo availdatainfo;
|
||||
uint16_t attemptsLeft;
|
||||
uint8_t targetMac[8];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct blockPart {
|
||||
uint8_t checksum;
|
||||
uint8_t blockId;
|
||||
uint8_t blockPart;
|
||||
uint8_t data[];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct blockData {
|
||||
uint16_t size;
|
||||
uint16_t checksum;
|
||||
uint8_t data[];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
#define TAG_RETURN_DATA_SIZE 90
|
||||
|
||||
struct tagReturnData {
|
||||
uint8_t checksum;
|
||||
uint8_t partId;
|
||||
uint64_t dataVer;
|
||||
uint8_t dataType;
|
||||
uint8_t data[TAG_RETURN_DATA_SIZE];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
#define BLOCK_PART_DATA_SIZE 99
|
||||
#define BLOCK_MAX_PARTS 42
|
||||
#define BLOCK_DATA_SIZE 4096UL
|
||||
#define BLOCK_XFER_BUFFER_SIZE BLOCK_DATA_SIZE + sizeof(struct blockData)
|
||||
#define BLOCK_REQ_PARTS_BYTES 6
|
||||
|
||||
struct blockRequest {
|
||||
uint8_t checksum;
|
||||
uint64_t ver;
|
||||
uint8_t blockId;
|
||||
uint8_t type;
|
||||
uint8_t requestedParts[BLOCK_REQ_PARTS_BYTES];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct blockRequestAck {
|
||||
uint8_t checksum;
|
||||
uint16_t pleaseWaitMs;
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct espBlockRequest {
|
||||
uint8_t checksum;
|
||||
uint64_t ver;
|
||||
uint8_t blockId;
|
||||
uint8_t src[8];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct espXferComplete {
|
||||
uint8_t checksum;
|
||||
uint8_t src[8];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct espAvailDataReq {
|
||||
uint8_t checksum;
|
||||
uint8_t src[8];
|
||||
struct AvailDataReq adr;
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct espSetChannelPower {
|
||||
uint8_t checksum;
|
||||
uint8_t channel;
|
||||
uint8_t power;
|
||||
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
uint8_t subghzchannel;
|
||||
#endif
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
struct espTagReturnData {
|
||||
uint8_t checksum;
|
||||
uint8_t src[8];
|
||||
uint8_t len;
|
||||
struct tagReturnData returnData;
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
#endif
|
||||
150
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/radio.c
Normal file
150
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/radio.c
Normal file
@@ -0,0 +1,150 @@
|
||||
#include <stddef.h>
|
||||
#include "radio.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_ieee802154.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_phy_init.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "led.h"
|
||||
#include "main.h"
|
||||
#include "proto.h"
|
||||
#include "sdkconfig.h"
|
||||
// if you get an error about soc/lp_uart_reg.h not being found,
|
||||
// you didn't choose the right build target. :-)
|
||||
//#include "soc/lp_uart_reg.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include "utils.h"
|
||||
#include <esp_mac.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "SubGigRadio.h"
|
||||
|
||||
|
||||
static const char *TAG = "RADIO";
|
||||
|
||||
uint8_t mSelfMac[8];
|
||||
volatile uint8_t isInTransmit = 0;
|
||||
QueueHandle_t packet_buffer = NULL;
|
||||
void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info) {
|
||||
ESP_EARLY_LOGI(TAG, "RX %d", frame[0]);
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
static uint8_t inner_rxPKT[130];
|
||||
memcpy(inner_rxPKT, &frame[0], frame[0] + 1);
|
||||
xQueueSendFromISR(packet_buffer, (void *)&inner_rxPKT, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken);
|
||||
esp_ieee802154_receive_sfd_done();
|
||||
}
|
||||
|
||||
void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_error_t error) {
|
||||
isInTransmit = 0;
|
||||
ESP_EARLY_LOGE(TAG, "TX Err: %d", error);
|
||||
}
|
||||
|
||||
void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) {
|
||||
isInTransmit = 0;
|
||||
ESP_EARLY_LOGI(TAG, "TX %d", frame[0]);
|
||||
esp_ieee802154_receive_sfd_done();
|
||||
}
|
||||
static bool zigbee_is_enabled = false;
|
||||
void radio_init(uint8_t ch) {
|
||||
if (packet_buffer == NULL) packet_buffer = xQueueCreate(32, 130);
|
||||
|
||||
// this will trigger a "IEEE802154 MAC sleep init failed" when called a second time, but it works
|
||||
if(zigbee_is_enabled)
|
||||
{
|
||||
zigbee_is_enabled = false;
|
||||
esp_ieee802154_disable();
|
||||
}
|
||||
zigbee_is_enabled = true;
|
||||
esp_ieee802154_enable();
|
||||
esp_ieee802154_set_channel(ch);
|
||||
// esp_ieee802154_set_txpower(int8_t power);
|
||||
esp_ieee802154_set_panid(PROTO_PAN_ID);
|
||||
esp_ieee802154_set_promiscuous(false);
|
||||
esp_ieee802154_set_coordinator(false);
|
||||
esp_ieee802154_set_pending_mode(ESP_IEEE802154_AUTO_PENDING_ZIGBEE);
|
||||
|
||||
// esp_ieee802154_set_extended_address needs the MAC in reversed byte order
|
||||
esp_read_mac(mSelfMac, ESP_MAC_IEEE802154);
|
||||
uint8_t eui64_rev[8] = {0};
|
||||
for (int i = 0; i < 8; i++) {
|
||||
eui64_rev[7 - i] = mSelfMac[i];
|
||||
}
|
||||
esp_ieee802154_set_extended_address(eui64_rev);
|
||||
esp_ieee802154_get_extended_address(mSelfMac);
|
||||
|
||||
esp_ieee802154_set_short_address(0xFFFE);
|
||||
esp_ieee802154_set_rx_when_idle(true);
|
||||
esp_ieee802154_receive();
|
||||
|
||||
led_flash(1);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
led_flash(0);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
led_flash(1);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
led_flash(0);
|
||||
|
||||
ESP_LOGI(TAG, "Receiver ready, panId=0x%04x, channel=%d, long=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, short=%04x",
|
||||
esp_ieee802154_get_panid(), esp_ieee802154_get_channel(),
|
||||
mSelfMac[0], mSelfMac[1], mSelfMac[2], mSelfMac[3],
|
||||
mSelfMac[4], mSelfMac[5], mSelfMac[6], mSelfMac[7],
|
||||
esp_ieee802154_get_short_address());
|
||||
}
|
||||
|
||||
// uint32_t lastZbTx = 0;
|
||||
bool radioTx(uint8_t *packet) {
|
||||
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
// The subghz driver uses DMA
|
||||
static DMA_ATTR uint8_t txPKT[130];
|
||||
#else
|
||||
static uint8_t txPKT[130];
|
||||
#endif
|
||||
led_flash(1);
|
||||
// while (getMillis() - lastZbTx < 6) {
|
||||
// }
|
||||
// lastZbTx = getMillis();
|
||||
memcpy(txPKT, packet, packet[0]);
|
||||
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
struct MacFrameNormal *txHeader = (struct MacFrameNormal *) (packet + 1);
|
||||
|
||||
if(txHeader->pan == PROTO_PAN_ID_SUBGHZ) {
|
||||
return SubGig_radioTx(packet);
|
||||
}
|
||||
#endif
|
||||
while (isInTransmit) {
|
||||
}
|
||||
isInTransmit = 1;
|
||||
esp_ieee802154_transmit(txPKT, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void radioSetChannel(uint8_t ch) {
|
||||
radio_init(ch);
|
||||
}
|
||||
|
||||
void radioSetTxPower(uint8_t power) {}
|
||||
|
||||
int8_t commsRxUnencrypted(uint8_t *data) {
|
||||
static uint8_t inner_rxPKT_out[130];
|
||||
if (xQueueReceive(packet_buffer, (void *)&inner_rxPKT_out, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||
memcpy(data, &inner_rxPKT_out[1], inner_rxPKT_out[0] + 1);
|
||||
return inner_rxPKT_out[0] - 2;
|
||||
}
|
||||
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
if(gSubGigData.Enabled) {
|
||||
int8_t Ret = SubGig_commsRxUnencrypted(data);
|
||||
if(Ret > 0) {
|
||||
return Ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
20
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/radio.h
Normal file
20
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/radio.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define RAW_PKT_PADDING 2
|
||||
extern uint8_t mSelfMac[8];
|
||||
|
||||
void radio_init(uint8_t ch);
|
||||
bool radioTx(uint8_t *packet);
|
||||
void radioSetChannel(uint8_t ch);
|
||||
void radioSetTxPower(uint8_t power);
|
||||
int8_t commsRxUnencrypted(uint8_t *data);
|
||||
|
||||
#ifdef SUBGIG_SUPPORT
|
||||
void SubGig_radio_init(uint8_t ch);
|
||||
bool SubGig_radioTx(uint8_t *packet);
|
||||
void SubGig_radioSetChannel(uint8_t ch);
|
||||
void SubGig_radioSetTxPower(uint8_t power);
|
||||
int8_t SubGig_commsRxUnencrypted(uint8_t *data);
|
||||
#endif
|
||||
116
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/second_uart.c
Normal file
116
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/second_uart.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <esp_mac.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_ieee802154.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_phy_init.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "main.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "proto.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/uart_struct.h"
|
||||
//#include "soc/lp_uart_reg.h"
|
||||
#include "second_uart.h"
|
||||
|
||||
//static const char *TAG = "SECOND_UART";
|
||||
|
||||
#define BUF_SIZE (1024)
|
||||
#define RD_BUF_SIZE (BUF_SIZE)
|
||||
static QueueHandle_t uart0_queue;
|
||||
|
||||
#define MAX_BUFF_POS 8000
|
||||
volatile int curr_buff_pos = 0;
|
||||
volatile int worked_buff_pos = 0;
|
||||
volatile uint8_t buff_pos[MAX_BUFF_POS + 5];
|
||||
|
||||
static void uart_event_task(void *pvParameters);
|
||||
void init_second_uart() {
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = 115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
ESP_ERROR_CHECK(uart_driver_install(1, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0));
|
||||
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
|
||||
ESP_ERROR_CHECK(uart_set_pin(1, CONFIG_OEPL_HARDWARE_UART_TX, CONFIG_OEPL_HARDWARE_UART_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
xTaskCreate(uart_event_task, "uart_event_task", 16384, NULL, 12, NULL);
|
||||
}
|
||||
|
||||
void uart_switch_speed(int baudrate) {
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = baudrate,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
|
||||
}
|
||||
|
||||
void uartTx(uint8_t data) { uart_write_bytes(1, (const char *) &data, 1); }
|
||||
|
||||
|
||||
bool getRxCharSecond(uint8_t *newChar) {
|
||||
if (curr_buff_pos != worked_buff_pos) {
|
||||
*newChar = buff_pos[worked_buff_pos];
|
||||
worked_buff_pos++;
|
||||
worked_buff_pos %= MAX_BUFF_POS;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void uart_event_task(void *pvParameters) {
|
||||
uart_event_t event;
|
||||
uint8_t *dtmp = (uint8_t *) malloc(RD_BUF_SIZE);
|
||||
for (;;) {
|
||||
if (xQueueReceive(uart0_queue, (void *) &event, (TickType_t) portMAX_DELAY)) {
|
||||
bzero(dtmp, RD_BUF_SIZE);
|
||||
switch (event.type) {
|
||||
case UART_DATA:
|
||||
uart_read_bytes(1, dtmp, event.size, portMAX_DELAY);
|
||||
for (int i = 0; i < event.size; i++) {
|
||||
buff_pos[curr_buff_pos] = dtmp[i];
|
||||
curr_buff_pos++;
|
||||
curr_buff_pos %= MAX_BUFF_POS;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// ESP_LOGI(TAG, "uart event type: %d", event.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(dtmp);
|
||||
dtmp = NULL;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void uart_printf(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
char buffer[128];
|
||||
int len = vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
if (len > 0) {
|
||||
uart_write_bytes(1, buffer, len);
|
||||
}
|
||||
}
|
||||
18
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/second_uart.h
Normal file
18
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/second_uart.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
void init_second_uart();
|
||||
void uart_switch_speed(int baudrate);
|
||||
|
||||
void uartTx(uint8_t data);
|
||||
bool getRxCharSecond(uint8_t *newChar);
|
||||
|
||||
void uart_printf(const char *format, ...);
|
||||
|
||||
#define pr uart_printf
|
||||
|
||||
|
||||
|
||||
#define CONFIG_OEPL_HARDWARE_UART_TX 24
|
||||
#define CONFIG_OEPL_HARDWARE_UART_RX 23
|
||||
36
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/utils.c
Normal file
36
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/utils.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <esp_mac.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_ieee802154.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_phy_init.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "main.h"
|
||||
#include "proto.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/uart_struct.h"
|
||||
//#include "soc/lp_uart_reg.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
void delay(int ms) { vTaskDelay(pdMS_TO_TICKS(ms)); }
|
||||
|
||||
uint32_t getMillis() { return (uint32_t) (esp_timer_get_time() / 1000); }
|
||||
|
||||
void init_nvs()
|
||||
{
|
||||
// Initialize NVS
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK( ret );
|
||||
}
|
||||
5
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/utils.h
Normal file
5
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/utils.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
void delay(int ms);
|
||||
uint32_t getMillis();
|
||||
void init_nvs();
|
||||
5
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/partitions.csv
Normal file
5
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/partitions.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
# ESP-IDF Partition Table
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs,data,nvs,0x9000,0x6000,,
|
||||
factory,app,factory,0x10000,1M,,
|
||||
littlefs,data,spiffs,,3008K,,
|
||||
|
8
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/sdkconfig.defaults
Normal file
8
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/sdkconfig.defaults
Normal file
@@ -0,0 +1,8 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32h2"
|
||||
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
76
ESP32_AP-Flasher/compile.ps1
Normal file
76
ESP32_AP-Flasher/compile.ps1
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
#| Function | ESP32H2 Pin | ESP32S3 Pin
|
||||
#| :--------------------------------: | :-------------------: | :------------------
|
||||
#| Activate The BOOT Mode Of ESP32H2 | ESP32H2_IO9 | ESP32S3_IO33
|
||||
#| Reset ESP32H2 | ESP32H2_Pin Number 8 | ESP32S3_IO34
|
||||
#| Uart | ESP32H2_TX_IO24 | ESP32S3_RX_IO48
|
||||
#| Uart | ESP32H2_RX_IO23 | ESP32S3_TX_IO47
|
||||
|
||||
# cd ESP32_AP-Flasher
|
||||
|
||||
# export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
|
||||
python gzip_wwwfiles.py
|
||||
|
||||
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --environment ESP32_S3_16_8_LILYGO_AP
|
||||
|
||||
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --target buildfs --environment ESP32_S3_16_8_LILYGO_AP
|
||||
|
||||
# mkdir ESP32_S3_16_8_LILYGO_AP
|
||||
|
||||
copy "$env:USERPROFILE\.platformio\packages\framework-arduinoespressif32\tools\partitions\boot_app0.bin" ESP32_S3_16_8_LILYGO_AP\boot_app0.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\firmware.bin ESP32_S3_16_8_LILYGO_AP\firmware.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\bootloader.bin ESP32_S3_16_8_LILYGO_AP\bootloader.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\partitions.bin ESP32_S3_16_8_LILYGO_AP\partitions.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\littlefs.bin ESP32_S3_16_8_LILYGO_AP\littlefs.bin
|
||||
|
||||
copy ESP32_S3_16_8_LILYGO_AP\firmware.bin espbinaries\ESP32_S3_16_8_LILYGO_AP.bin
|
||||
|
||||
copy ESP32_S3_16_8_LILYGO_AP\merged-firmware.bin espbinaries\ESP32_S3_16_8_LILYGO_AP_full.bin
|
||||
|
||||
cd ESP32_S3_16_8_LILYGO_AP
|
||||
|
||||
#python -m esptool --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
|
||||
#python -m esptool -p COM12 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
|
||||
cd ..
|
||||
|
||||
#esptool.py v4.7.0
|
||||
#Serial port COM12
|
||||
#Connecting...
|
||||
#Chip is ESP32-S3 (QFN56) (revision v0.2)
|
||||
#Features: WiFi, BLE
|
||||
#Crystal is 40MHz
|
||||
#MAC: f4:12:fa:af:5b:9c
|
||||
#Uploading stub...
|
||||
#Running stub...
|
||||
#Stub running...
|
||||
#Changing baud rate to 460800
|
||||
#Changed.
|
||||
#Configuring flash size...
|
||||
#Auto-detected Flash size: 16MB
|
||||
#Flash will be erased from 0x00000000 to 0x00003fff...
|
||||
#Flash will be erased from 0x00008000 to 0x00008fff...
|
||||
#Flash will be erased from 0x0000e000 to 0x0000ffff...
|
||||
#Flash will be erased from 0x00010000 to 0x00203fff...
|
||||
#Flash will be erased from 0x00910000 to 0x00feffff...
|
||||
#Compressed 15104 bytes to 10401...
|
||||
#Wrote 15104 bytes (10401 compressed) at 0x00000000 in 0.3 seconds (effective 375.1 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 3072 bytes to 146...
|
||||
#Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (effective 272.1 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 8192 bytes to 47...
|
||||
#Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 447.3 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 2047040 bytes to 1259376...
|
||||
#Wrote 2047040 bytes (1259376 compressed) at 0x00010000 in 18.7 seconds (effective 876.9 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 7208960 bytes to 302805...
|
||||
#Wrote 7208960 bytes (302805 compressed) at 0x00910000 in 47.0 seconds (effective 1227.2 kbit/s)...
|
||||
#Hash of data verified.
|
||||
69
ESP32_AP-Flasher/compileyellow.ps1
Normal file
69
ESP32_AP-Flasher/compileyellow.ps1
Normal file
@@ -0,0 +1,69 @@
|
||||
# cd ESP32_AP-Flasher
|
||||
|
||||
# export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
|
||||
python gzip_wwwfiles.py
|
||||
|
||||
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --environment ESP32_S3_16_8_YELLOW_AP
|
||||
|
||||
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --target buildfs --environment ESP32_S3_16_8_YELLOW_AP
|
||||
|
||||
# mkdir ESP32_S3_16_8_YELLOW_AP
|
||||
|
||||
copy "$env:USERPROFILE\.platformio\packages\framework-arduinoespressif32\tools\partitions\boot_app0.bin" ESP32_S3_16_8_YELLOW_AP\boot_app0.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\firmware.bin ESP32_S3_16_8_YELLOW_AP\firmware.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\bootloader.bin ESP32_S3_16_8_YELLOW_AP\bootloader.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\partitions.bin ESP32_S3_16_8_YELLOW_AP\partitions.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\littlefs.bin ESP32_S3_16_8_YELLOW_AP\littlefs.bin
|
||||
|
||||
copy ESP32_S3_16_8_YELLOW_AP\firmware.bin espbinaries\ESP32_S3_16_8_YELLOW_AP.bin
|
||||
|
||||
copy ESP32_S3_16_8_YELLOW_AP\merged-firmware.bin espbinaries\ESP32_S3_16_8_YELLOW_AP_full.bin
|
||||
|
||||
cd ESP32_S3_16_8_YELLOW_AP
|
||||
|
||||
#python -m esptool --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
|
||||
#python -m esptool -p COM4 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
|
||||
cd ..
|
||||
|
||||
#esptool.py v4.7.0
|
||||
#Serial port COM4
|
||||
#Connecting...
|
||||
#Chip is ESP32-S3 (QFN56) (revision v0.2)
|
||||
#Features: WiFi, BLE, Embedded PSRAM 8MB (AP_3v3)
|
||||
#Crystal is 40MHz
|
||||
#MAC: dc:da:0c:16:cf:4c
|
||||
#Uploading stub...
|
||||
#Running stub...
|
||||
#Stub running...
|
||||
#Changing baud rate to 460800
|
||||
#Changed.
|
||||
#Configuring flash size...
|
||||
#Auto-detected Flash size: 16MB
|
||||
#Flash will be erased from 0x00000000 to 0x00003fff...
|
||||
#Flash will be erased from 0x00008000 to 0x00008fff...
|
||||
#Flash will be erased from 0x0000e000 to 0x0000ffff...
|
||||
#Flash will be erased from 0x00010000 to 0x001dbfff...
|
||||
#Flash will be erased from 0x00910000 to 0x00feffff...
|
||||
#Compressed 15104 bytes to 10401...
|
||||
#Wrote 15104 bytes (10401 compressed) at 0x00000000 in 0.4 seconds (effective 277.3 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 3072 bytes to 146...
|
||||
#Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (effective 425.0 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 8192 bytes to 47...
|
||||
#Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 632.5 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 1881424 bytes to 1196500...
|
||||
#Wrote 1881424 bytes (1196500 compressed) at 0x00010000 in 27.6 seconds (effective 544.8 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 7208960 bytes to 302804...
|
||||
#Wrote 7208960 bytes (302804 compressed) at 0x00910000 in 35.0 seconds (effective 1648.8 kbit/s)...
|
||||
#Hash of data verified.
|
||||
|
||||
64
ESP32_AP-Flasher/data/tagtypes/E2.json
Normal file
64
ESP32_AP-Flasher/data/tagtypes/E2.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"version": 1,
|
||||
"name": "LILYGO TPANEL 4\"",
|
||||
"width": 480,
|
||||
"height": 480,
|
||||
"rotatebuffer": 0,
|
||||
"bpp": 16,
|
||||
"colortable": {
|
||||
"white": [ 255, 255, 255 ],
|
||||
"black": [ 0, 0, 0 ],
|
||||
"red": [ 255, 0, 0 ]
|
||||
},
|
||||
"shortlut": 0,
|
||||
"options": [ ],
|
||||
"contentids": [ 22, 1, 2, 3, 4, 8, 7, 19, 10, 11, 21 ],
|
||||
"template": {
|
||||
"21": [
|
||||
{ "box": [ 0, 0, 480, 480, 1 ] },
|
||||
{ "text": [ 10, 15, "OpenEpaperLink AP", "calibrib30", 2, 0, 0, 1 ] },
|
||||
{ "text": [ 10, 70, "IP address:", "bahnschrift30", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 180, 70, "{ap_ip}", "bahnschrift30", 0, 0, 0, 1 ] },
|
||||
{ "text": [ 10, 110, "Channel:", "bahnschrift30", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 180, 110, "{ap_ch}", "bahnschrift30", 0, 0, 0, "1" ] },
|
||||
{ "text": [ 10, 150, "Tag count:", "bahnschrift30", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 180, 150, "{ap_tagcount}", "bahnschrift30", 0, 0, 0, "1" ] }
|
||||
],
|
||||
"1": {
|
||||
"weekday": [ 240, 30, "Signika-SB.ttf", 90 ],
|
||||
"month": [ 240, 330, "Signika-SB.ttf", 90 ],
|
||||
"day": [ 240, 80, "Signika-SB.ttf", 250 ]
|
||||
},
|
||||
"4": {
|
||||
"location": [ 20, 20, "fonts/calibrib30" ],
|
||||
"wind": [ 90, 95, "fonts/calibrib50" ],
|
||||
"temp": [ 20, 200, "fonts/calibrib100" ],
|
||||
"icon": [ 400, 30, 150, 2 ],
|
||||
"dir": [ 40, 70, 80 ],
|
||||
"umbrella": [ 325, 250, 150 ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": [ "Signika-SB.ttf", 150, 150, 110, 80, 60, 50 ],
|
||||
"xy": [ 240, 240 ]
|
||||
},
|
||||
"8": {
|
||||
"location": [ 10, 20, "fonts/calibrib50" ],
|
||||
"column": [ 6, 80 ],
|
||||
"day": [ 40, 100, "fonts/bahnschrift30", 144, 270 ],
|
||||
"rain": [ 40, 320 ],
|
||||
"icon": [ 40, 180, 50 ],
|
||||
"wind": [ 17, 120 ],
|
||||
"line": [ 100, 340 ]
|
||||
},
|
||||
"10": {
|
||||
"title": [ 240, 10, "fonts/bahnschrift20" ],
|
||||
"pos": [ 240, 35 ]
|
||||
},
|
||||
"11": {
|
||||
"rotate": 0,
|
||||
"mode": 1,
|
||||
"days": 4,
|
||||
"gridparam": [ 5, 17, 20, "calibrib16.vlw", "tahoma9.vlw", 14 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
|
||||
#define LV_ATTRIBUTE_TICK_INC IRAM_ATTR
|
||||
#define TOUCH_MODULES_CST_MUTUAL
|
||||
|
||||
// SD
|
||||
#define SD_CS 38
|
||||
#define SD_SCLK 36
|
||||
#define SD_MOSI 35
|
||||
#define SD_MISO 37
|
||||
|
||||
// IIC
|
||||
#define IIC_SDA 17
|
||||
#define IIC_SCL 18
|
||||
|
||||
// ESP32H2
|
||||
#define ESP32H2_TX 48
|
||||
#define ESP32H2_RX 47
|
||||
|
||||
// #define T_Panel_V1_0_RS485
|
||||
#define T_Panel_V1_2_RS485
|
||||
// #define T_Panel_V1_2_CAN
|
||||
|
||||
#if defined T_Panel_V1_0_RS485
|
||||
#define RS485_TX 15
|
||||
#define RS485_RX 16
|
||||
#endif
|
||||
|
||||
#if defined T_Panel_V1_2_RS485
|
||||
#define RS485_TX 16
|
||||
#define RS485_RX 15
|
||||
#endif
|
||||
|
||||
#if defined T_Panel_V1_2_CAN
|
||||
#define CAN_TX 16
|
||||
#define CAN_RX 15
|
||||
#endif
|
||||
|
||||
// YDP395BT001-V2
|
||||
#define LCD_WIDTH 480
|
||||
#define LCD_HEIGHT 480
|
||||
#define LCD_VSYNC 40
|
||||
#define LCD_HSYNC 39
|
||||
#define LCD_PCLK 41
|
||||
#define LCD_B0 1
|
||||
#define LCD_B1 2
|
||||
#define LCD_B2 3
|
||||
#define LCD_B3 4
|
||||
#define LCD_B4 5
|
||||
#define LCD_G0 6
|
||||
#define LCD_G1 7
|
||||
#define LCD_G2 8
|
||||
#define LCD_G3 9
|
||||
#define LCD_G4 10
|
||||
#define LCD_G5 11
|
||||
#define LCD_R0 12
|
||||
#define LCD_R1 13
|
||||
#define LCD_R2 42
|
||||
#define LCD_R3 46
|
||||
#define LCD_R4 45
|
||||
#define LCD_BL 14
|
||||
|
||||
// CST3240
|
||||
#define CST3240_ADDRESS 0x5A
|
||||
#define TOUCH_SDA 17
|
||||
#define TOUCH_SCL 18
|
||||
#define TOUCH_INT 21
|
||||
#define TOUCH_RST 4
|
||||
|
||||
// XL95x5
|
||||
#define XL95X5_CS 17
|
||||
#define XL95X5_SCLK 15
|
||||
#define XL95X5_MOSI 16
|
||||
#define XL95X5_TOUCH_RST 4
|
||||
#define XL95X5_RS485_CON 7
|
||||
#define XL95X5_LCD_RST 5
|
||||
#define XL95X5_ESP32H2_IO12 1
|
||||
#define XL95X5_ESP32H2_IO4 2
|
||||
#define XL95X5_ESP32H2_IO5 3
|
||||
|
||||
// ESP32H2
|
||||
#define ESP32H2_EN 34
|
||||
#define ESP32H2_BOOT 33
|
||||
|
||||
#include "Arduino_GFX_Library.h"
|
||||
|
||||
extern Arduino_RGB_Display *gfx;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TFT
|
||||
|
||||
extern TFT_eSPI tft2;
|
||||
@@ -10,4 +102,4 @@ extern bool tftOverride;
|
||||
void TFTLog(String text);
|
||||
void sendAvail(uint8_t wakeupReason);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
167
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_DataBus.cpp
Normal file
167
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_DataBus.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
Arduino_DataBus::Arduino_DataBus() {}
|
||||
|
||||
void Arduino_DataBus::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
writeCommand(c);
|
||||
write(d);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
writeCommand(c);
|
||||
write16(d);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC16D16(uint16_t c, uint16_t d)
|
||||
{
|
||||
writeCommand16(c);
|
||||
write16(d);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
writeCommand(c);
|
||||
write16(d1);
|
||||
write16(d2);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
writeCommand(c);
|
||||
_data16.value = d1;
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
_data16.value = d2;
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendCommand(uint8_t c)
|
||||
{
|
||||
beginWrite();
|
||||
writeCommand(c);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendCommand16(uint16_t c)
|
||||
{
|
||||
beginWrite();
|
||||
writeCommand16(c);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendData(uint8_t d)
|
||||
{
|
||||
beginWrite();
|
||||
write(d);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendData16(uint16_t d)
|
||||
{
|
||||
beginWrite();
|
||||
write16(d);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::batchOperation(const uint8_t *operations, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
uint8_t l = 0;
|
||||
switch (operations[i])
|
||||
{
|
||||
case BEGIN_WRITE:
|
||||
beginWrite();
|
||||
break;
|
||||
case WRITE_C8_D16:
|
||||
writeCommand(operations[++i]);
|
||||
l = 2;
|
||||
break;
|
||||
case WRITE_C8_D8:
|
||||
writeC8D8(operations[++i], operations[++i]);
|
||||
break;
|
||||
case WRITE_COMMAND_8:
|
||||
writeCommand(operations[++i]);
|
||||
break;
|
||||
case WRITE_C16_D16:
|
||||
|
||||
break;
|
||||
case WRITE_COMMAND_16:
|
||||
|
||||
break;
|
||||
case WRITE_DATA_8:
|
||||
l = 1;
|
||||
break;
|
||||
case WRITE_DATA_16:
|
||||
l = 2;
|
||||
break;
|
||||
case WRITE_BYTES:
|
||||
l = operations[++i];
|
||||
break;
|
||||
case END_WRITE:
|
||||
endWrite();
|
||||
break;
|
||||
case DELAY:
|
||||
delay(operations[++i]);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown operation id at %d: %d", i, operations[i]);
|
||||
break;
|
||||
}
|
||||
while (l--)
|
||||
{
|
||||
write(operations[++i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void Arduino_DataBus::writePattern(uint8_t *data, uint8_t len, uint32_t repeat)
|
||||
{
|
||||
while (repeat--)
|
||||
{
|
||||
writeBytes(data, len);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
write16(idx[*(data++)]);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
uint8_t *d = data;
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*(d++)];
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
}
|
||||
}
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
void Arduino_DataBus::pinMode(uint8_t pin, uint8_t mode)
|
||||
{
|
||||
}
|
||||
|
||||
void Arduino_DataBus::digitalWrite(uint8_t pin, uint8_t val)
|
||||
{
|
||||
}
|
||||
|
||||
int Arduino_DataBus::digitalRead(uint8_t pin)
|
||||
{
|
||||
}
|
||||
|
||||
293
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_DataBus.h
Normal file
293
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_DataBus.h
Normal file
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_DATABUS_H_
|
||||
#define _ARDUINO_DATABUS_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define GFX_SKIP_OUTPUT_BEGIN -2
|
||||
#define GFX_NOT_DEFINED -1
|
||||
#define GFX_STR_HELPER(x) #x
|
||||
#define GFX_STR(x) GFX_STR_HELPER(x)
|
||||
|
||||
#if defined(__AVR__)
|
||||
#define LITTLE_FOOT_PRINT // reduce program size for limited flash MCU
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint8_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ARDUINO_ARCH_NRF52840)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(TARGET_RP2040)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ESP32)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ESP8266)
|
||||
#define ESP8266SAFEBATCHBITSIZE (2048 * 8 * 9)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ARDUINO_ARCH_STM32)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(__arm__)
|
||||
#if defined(ARDUINO_ARCH_SAMD)
|
||||
// Adafruit M0, M4
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(CONFIG_ARCH_CHIP_CXD56XX) // Sony Spresense
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint8_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(RTL8722DM)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(CORE_TEENSY)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
// PJRC Teensy 4.x
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#else
|
||||
// PJRC Teensy 3.x
|
||||
typedef uint8_t ARDUINOGFX_PORT_t;
|
||||
#endif
|
||||
#else
|
||||
// Arduino Due?
|
||||
// USE_FAST_PINIO not available here (yet)...Due has a totally different
|
||||
// GPIO register set and will require some changes elsewhere (e.g. in
|
||||
// constructors especially).
|
||||
#endif
|
||||
#else // !ARM
|
||||
// Unknow architecture, USE_FAST_PINIO is not available here (yet)
|
||||
// but don't worry about it too much...the digitalWrite() implementation
|
||||
// on these platforms is reasonably efficient and already RAM-resident,
|
||||
// only gotcha then is no parallel connection support for now.
|
||||
#endif // !ARM
|
||||
|
||||
#ifdef USE_FAST_PINIO
|
||||
typedef volatile ARDUINOGFX_PORT_t *PORTreg_t;
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ARC32) || defined(ARDUINO_MAXIM)
|
||||
#define SPI_DEFAULT_FREQ 16000000
|
||||
// Teensy 3.0, 3.1/3.2, 3.5, 3.6
|
||||
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
#define SPI_DEFAULT_FREQ 40000000
|
||||
// Teensy 4.x
|
||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
#define SPI_DEFAULT_FREQ 40000000
|
||||
#elif defined(__AVR__) || defined(TEENSYDUINO)
|
||||
#define SPI_DEFAULT_FREQ 8000000
|
||||
#elif defined(ARDUINO_ARCH_NRF52840)
|
||||
#define SPI_DEFAULT_FREQ 8000000
|
||||
#elif defined(ESP8266) || defined(ESP32)
|
||||
#define SPI_DEFAULT_FREQ 40000000
|
||||
#elif defined(RTL8722DM)
|
||||
#define SPI_DEFAULT_FREQ 20000000
|
||||
#elif defined(RASPI)
|
||||
#define SPI_DEFAULT_FREQ 80000000
|
||||
#elif defined(ARDUINO_ARCH_STM32F1)
|
||||
#define SPI_DEFAULT_FREQ 36000000
|
||||
#elif defined(ARDUINO_BLACKPILL_F411CE)
|
||||
#define SPI_DEFAULT_FREQ 50000000
|
||||
#elif defined(F_CPU)
|
||||
#define SPI_DEFAULT_FREQ (F_CPU / 4)
|
||||
#else
|
||||
#define SPI_DEFAULT_FREQ 24000000 ///< Default SPI data clock frequency
|
||||
#endif
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) (void)(x)
|
||||
#endif
|
||||
#define ATTR_UNUSED __attribute__((unused))
|
||||
|
||||
#define MSB_16(val) (((val)&0xFF00) >> 8) | (((val)&0xFF) << 8)
|
||||
#define MSB_16_SET(var, val) \
|
||||
{ \
|
||||
(var) = MSB_16(val); \
|
||||
}
|
||||
#define MSB_32_SET(var, val) \
|
||||
{ \
|
||||
uint8_t *v = (uint8_t *)&(val); \
|
||||
(var) = v[3] | (v[2] << 8) | (v[1] << 16) | (v[0] << 24); \
|
||||
}
|
||||
#define MSB_32_16_16_SET(var, v1, v2) \
|
||||
{ \
|
||||
(var) = (((uint32_t)v2 & 0xff00) << 8) | (((uint32_t)v2 & 0xff) << 24) | ((v1 & 0xff00) >> 8) | ((v1 & 0xff) << 8); \
|
||||
}
|
||||
#define MSB_32_8_ARRAY_SET(var, a) \
|
||||
{ \
|
||||
(var) = ((uint32_t)a[0] << 8 | a[1] | a[2] << 24 | a[3] << 16); \
|
||||
}
|
||||
|
||||
#if defined(ESP32)
|
||||
#define INLINE __attribute__((always_inline)) inline
|
||||
#else
|
||||
#define INLINE inline
|
||||
#endif
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
#include <esp_lcd_panel_io.h>
|
||||
#include <esp_lcd_panel_io_interface.h>
|
||||
#include <esp_pm.h>
|
||||
#include <esp_private/gdma.h>
|
||||
#include <hal/dma_types.h>
|
||||
#include <hal/lcd_hal.h>
|
||||
#include <soc/dport_reg.h>
|
||||
#include <soc/gpio_sig_map.h>
|
||||
#include <soc/lcd_cam_reg.h>
|
||||
#include <soc/lcd_cam_struct.h>
|
||||
|
||||
typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t;
|
||||
typedef struct lcd_panel_io_i80_t lcd_panel_io_i80_t;
|
||||
typedef struct lcd_i80_trans_descriptor_t lcd_i80_trans_descriptor_t;
|
||||
|
||||
struct esp_lcd_i80_bus_t
|
||||
{
|
||||
int bus_id; // Bus ID, index from 0
|
||||
portMUX_TYPE spinlock; // spinlock used to protect i80 bus members(hal, device_list, cur_trans)
|
||||
lcd_hal_context_t hal; // Hal object
|
||||
size_t bus_width; // Number of data lines
|
||||
intr_handle_t intr; // LCD peripheral interrupt handle
|
||||
esp_pm_lock_handle_t pm_lock; // Power management lock
|
||||
size_t num_dma_nodes; // Number of DMA descriptors
|
||||
uint8_t *format_buffer; // The driver allocates an internal buffer for DMA to do data format transformer
|
||||
size_t resolution_hz; // LCD_CLK resolution, determined by selected clock source
|
||||
gdma_channel_handle_t dma_chan; // DMA channel handle
|
||||
size_t psram_trans_align; // DMA transfer alignment for data allocated from PSRAM
|
||||
size_t sram_trans_align; // DMA transfer alignment for data allocated from SRAM
|
||||
lcd_i80_trans_descriptor_t *cur_trans; // Current transaction
|
||||
lcd_panel_io_i80_t *cur_device; // Current working device
|
||||
LIST_HEAD(i80_device_list, lcd_panel_io_i80_t)
|
||||
device_list; // Head of i80 device list
|
||||
struct
|
||||
{
|
||||
unsigned int exclusive : 1; // Indicate whether the I80 bus is owned by one device (whose CS GPIO is not assigned) exclusively
|
||||
} flags;
|
||||
dma_descriptor_t dma_nodes[]; // DMA descriptor pool, the descriptors are shared by all i80 devices
|
||||
};
|
||||
|
||||
struct lcd_i80_trans_descriptor_t
|
||||
{
|
||||
lcd_panel_io_i80_t *i80_device; // i80 device issuing this transaction
|
||||
int cmd_value; // Command value
|
||||
uint32_t cmd_cycles; // Command cycles
|
||||
const void *data; // Data buffer
|
||||
uint32_t data_length; // Data buffer size
|
||||
void *user_ctx; // private data used by trans_done_cb
|
||||
esp_lcd_panel_io_color_trans_done_cb_t trans_done_cb; // transaction done callback
|
||||
};
|
||||
|
||||
struct lcd_panel_io_i80_t
|
||||
{
|
||||
esp_lcd_panel_io_t base; // Base class of generic lcd panel io
|
||||
esp_lcd_i80_bus_t *bus; // Which bus the device is attached to
|
||||
int cs_gpio_num; // GPIO used for CS line
|
||||
unsigned int pclk_hz; // PCLK clock frequency
|
||||
size_t clock_prescale; // Prescaler coefficient, determined by user's configured PCLK frequency
|
||||
QueueHandle_t trans_queue; // Transaction queue, transactions in this queue are pending for scheduler to dispatch
|
||||
QueueHandle_t done_queue; // Transaction done queue, transactions in this queue are finished but not recycled by the caller
|
||||
size_t queue_size; // Size of transaction queue
|
||||
size_t num_trans_inflight; // Number of transactions that are undergoing (the descriptor not recycled yet)
|
||||
int lcd_cmd_bits; // Bit width of LCD command
|
||||
int lcd_param_bits; // Bit width of LCD parameter
|
||||
void *user_ctx; // private data used when transfer color data
|
||||
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; // color data trans done callback
|
||||
LIST_ENTRY(lcd_panel_io_i80_t)
|
||||
device_list_entry; // Entry of i80 device list
|
||||
struct
|
||||
{
|
||||
unsigned int dc_idle_level : 1; // Level of DC line in IDLE phase
|
||||
unsigned int dc_cmd_level : 1; // Level of DC line in CMD phase
|
||||
unsigned int dc_dummy_level : 1; // Level of DC line in DUMMY phase
|
||||
unsigned int dc_data_level : 1; // Level of DC line in DATA phase
|
||||
} dc_levels;
|
||||
struct
|
||||
{
|
||||
unsigned int cs_active_high : 1; // Whether the CS line is active on high level
|
||||
unsigned int reverse_color_bits : 1; // Reverse the data bits, D[N:0] -> D[0:N]
|
||||
unsigned int swap_color_bytes : 1; // Swap adjacent two data bytes before sending out
|
||||
unsigned int pclk_active_neg : 1; // The display will write data lines when there's a falling edge on WR line
|
||||
unsigned int pclk_idle_low : 1; // The WR line keeps at low level in IDLE phase
|
||||
} flags;
|
||||
lcd_i80_trans_descriptor_t trans_pool[]; // Transaction pool
|
||||
};
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BEGIN_WRITE,
|
||||
WRITE_COMMAND_8,
|
||||
WRITE_COMMAND_16,
|
||||
WRITE_DATA_8,
|
||||
WRITE_DATA_16,
|
||||
WRITE_BYTES,
|
||||
WRITE_C8_D8,
|
||||
WRITE_C8_D16,
|
||||
WRITE_C16_D16,
|
||||
END_WRITE,
|
||||
DELAY,
|
||||
} spi_operation_type_t;
|
||||
|
||||
union
|
||||
{
|
||||
uint16_t value;
|
||||
struct
|
||||
{
|
||||
uint8_t lsb;
|
||||
uint8_t msb;
|
||||
};
|
||||
} _data16;
|
||||
|
||||
class Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_DataBus();
|
||||
|
||||
void unused() { UNUSED(_data16); } // avoid compiler warning
|
||||
|
||||
virtual bool begin(int32_t speed = SPI_DEFAULT_FREQ, int8_t dataMode = GFX_NOT_DEFINED) = 0;
|
||||
virtual void beginWrite() = 0;
|
||||
virtual void endWrite() = 0;
|
||||
virtual void writeCommand(uint8_t c) = 0;
|
||||
virtual void writeCommand16(uint16_t c) = 0;
|
||||
virtual void write(uint8_t) = 0;
|
||||
virtual void write16(uint16_t) = 0;
|
||||
virtual void writeC8D8(uint8_t c, uint8_t d);
|
||||
virtual void writeC16D16(uint16_t c, uint16_t d);
|
||||
virtual void writeC8D16(uint8_t c, uint16_t d);
|
||||
virtual void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2);
|
||||
virtual void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2);
|
||||
virtual void writeRepeat(uint16_t p, uint32_t len) = 0;
|
||||
virtual void writePixels(uint16_t *data, uint32_t len) = 0;
|
||||
|
||||
void sendCommand(uint8_t c);
|
||||
void sendCommand16(uint16_t c);
|
||||
void sendData(uint8_t d);
|
||||
void sendData16(uint16_t d);
|
||||
|
||||
void batchOperation(const uint8_t *operations, size_t len);
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
virtual void writeBytes(uint8_t *data, uint32_t len) = 0;
|
||||
virtual void writePattern(uint8_t *data, uint8_t len, uint32_t repeat);
|
||||
virtual void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len);
|
||||
virtual void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len);
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
virtual void pinMode(uint8_t pin, uint8_t mode);
|
||||
virtual void digitalWrite(uint8_t pin, uint8_t val);
|
||||
virtual int digitalRead(uint8_t pin);
|
||||
|
||||
protected:
|
||||
int32_t _speed;
|
||||
int8_t _dataMode;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_DATABUS_H_
|
||||
279
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_G.cpp
Normal file
279
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_G.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "Arduino_G.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Instatiate a GFX context for graphics! Can only be done by a superclass
|
||||
@param w Display width, in pixels
|
||||
@param h Display height, in pixels
|
||||
*/
|
||||
/**************************************************************************/
|
||||
Arduino_G::Arduino_G(int16_t w, int16_t h) : WIDTH(w), HEIGHT(h)
|
||||
{
|
||||
}
|
||||
|
||||
// utility functions
|
||||
bool gfx_draw_bitmap_to_framebuffer(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t xskip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
xskip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= xskip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
xskip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *row = framebuffer;
|
||||
row += y * framebuffer_w; // shift framebuffer to y offset
|
||||
row += x; // shift framebuffer to x offset
|
||||
if (((framebuffer_w & 1) == 0) && ((xskip & 1) == 0) && ((bitmap_w & 1) == 0))
|
||||
{
|
||||
uint32_t *row2 = (uint32_t *)row;
|
||||
uint32_t *from_bitmap2 = (uint32_t *)from_bitmap;
|
||||
int16_t framebuffer_w2 = framebuffer_w >> 1;
|
||||
int16_t xskip2 = xskip >> 1;
|
||||
int16_t w2 = bitmap_w >> 1;
|
||||
|
||||
int16_t j = bitmap_h;
|
||||
while (j--)
|
||||
{
|
||||
for (int16_t i = 0; i < w2; ++i)
|
||||
{
|
||||
row2[i] = *from_bitmap2++;
|
||||
}
|
||||
from_bitmap2 += xskip2;
|
||||
row2 += framebuffer_w2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t j = bitmap_h;
|
||||
while (j--)
|
||||
{
|
||||
for (int i = 0; i < bitmap_w; ++i)
|
||||
{
|
||||
row[i] = *from_bitmap++;
|
||||
}
|
||||
from_bitmap += xskip;
|
||||
row += framebuffer_w;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_1(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t xskip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
xskip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= xskip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
xskip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *p;
|
||||
int16_t i;
|
||||
for (int16_t j = 0; j < bitmap_h; j++)
|
||||
{
|
||||
p = framebuffer;
|
||||
p += (x * framebuffer_h); // shift framebuffer to y offset
|
||||
p += (framebuffer_h - y - j); // shift framebuffer to x offset
|
||||
|
||||
i = bitmap_w;
|
||||
while (i--)
|
||||
{
|
||||
*p = *from_bitmap++;
|
||||
p += framebuffer_h;
|
||||
}
|
||||
from_bitmap += xskip;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_2(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t xskip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
xskip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= xskip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
xskip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *row = framebuffer;
|
||||
row += (max_Y - y) * framebuffer_w; // shift framebuffer to y offset
|
||||
row += framebuffer_w - x - bitmap_w; // shift framebuffer to x offset
|
||||
int16_t i;
|
||||
int16_t j = bitmap_h;
|
||||
while (j--)
|
||||
{
|
||||
i = bitmap_w;
|
||||
while (i--)
|
||||
{
|
||||
row[i] = *from_bitmap++;
|
||||
}
|
||||
from_bitmap += xskip;
|
||||
row -= framebuffer_w;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_3(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t xskip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
xskip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= xskip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
xskip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *p;
|
||||
int16_t i;
|
||||
for (int16_t j = 0; j < bitmap_h; j++)
|
||||
{
|
||||
p = framebuffer;
|
||||
p += ((max_X - x) * framebuffer_h); // shift framebuffer to y offset
|
||||
p += y + j; // shift framebuffer to x offset
|
||||
|
||||
i = bitmap_w;
|
||||
while (i--)
|
||||
{
|
||||
*p = *from_bitmap++;
|
||||
p -= framebuffer_h;
|
||||
}
|
||||
from_bitmap += xskip;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
50
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_G.h
Normal file
50
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_G.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#ifndef _ARDUINO_G_H_
|
||||
#define _ARDUINO_G_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
/// A generic graphics superclass that can handle all sorts of drawing. At a minimum you can subclass and provide drawPixel(). At a maximum you can do a ton of overriding to optimize. Used for any/all Adafruit displays!
|
||||
class Arduino_G
|
||||
{
|
||||
public:
|
||||
Arduino_G(int16_t w, int16_t h); // Constructor
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
virtual bool begin(int32_t speed = GFX_NOT_DEFINED) = 0;
|
||||
|
||||
virtual void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) = 0;
|
||||
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) = 0;
|
||||
virtual void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) = 0;
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) = 0;
|
||||
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) = 0;
|
||||
|
||||
protected:
|
||||
int16_t
|
||||
WIDTH, ///< This is the 'raw' display width - never changes
|
||||
HEIGHT; ///< This is the 'raw' display height - never changes
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_G_H_
|
||||
|
||||
// utility functions
|
||||
bool gfx_draw_bitmap_to_framebuffer(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_1(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_2(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_3(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
2898
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_GFX.cpp
Normal file
2898
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_GFX.cpp
Normal file
File diff suppressed because it is too large
Load Diff
447
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_GFX.h
Normal file
447
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_GFX.h
Normal file
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_GFX_H_
|
||||
#define _ARDUINO_GFX_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Print.h>
|
||||
#include "Arduino_G.h"
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if !defined(ATTINY_CORE)
|
||||
#include "gfxfont.h"
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
#ifndef DEGTORAD
|
||||
#define DEGTORAD 0.017453292519943295769236907684886F
|
||||
#endif
|
||||
|
||||
|
||||
#define RGB565(r, g, b) ((((r)&0xF8) << 8) | (((g)&0xFC) << 3) | ((b) >> 3))
|
||||
#define RGB16TO24(c) ((((uint32_t)c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x1F) << 3))
|
||||
|
||||
#define RGB565_BLACK RGB565(0, 0, 0)
|
||||
#define RGB565_NAVY RGB565(0, 0, 123)
|
||||
#define RGB565_DARKGREEN RGB565(0, 125, 0)
|
||||
#define RGB565_DARKCYAN RGB565(0, 125, 123)
|
||||
#define RGB565_MAROON RGB565(123, 0, 0)
|
||||
#define RGB565_PURPLE RGB565(123, 0, 123)
|
||||
#define RGB565_OLIVE RGB565(123, 125, 0)
|
||||
#define RGB565_LIGHTGREY RGB565(198, 195, 198)
|
||||
#define RGB565_DARKGREY RGB565(123, 125, 123)
|
||||
#define RGB565_BLUE RGB565(0, 0, 255)
|
||||
#define RGB565_GREEN RGB565(0, 255, 0)
|
||||
#define RGB565_CYAN RGB565(0, 255, 255)
|
||||
#define RGB565_RED RGB565(255, 0, 0)
|
||||
#define RGB565_MAGENTA RGB565(255, 0, 255)
|
||||
#define RGB565_YELLOW RGB565(255, 255, 0)
|
||||
#define RGB565_WHITE RGB565(255, 255, 255)
|
||||
#define RGB565_ORANGE RGB565(255, 165, 0)
|
||||
#define RGB565_GREENYELLOW RGB565(173, 255, 41)
|
||||
#define RGB565_PINK RGB565(255, 130, 198)
|
||||
|
||||
// Color definitions
|
||||
#ifndef DISABLE_COLOR_DEFINES
|
||||
#define BLACK RGB565_BLACK
|
||||
#define NAVY RGB565_NAVY
|
||||
#define DARKGREEN RGB565_DARKGREEN
|
||||
#define DARKCYAN RGB565_DARKCYAN
|
||||
#define MAROON RGB565_MAROON
|
||||
#define PURPLE RGB565_PURPLE
|
||||
#define OLIVE RGB565_OLIVE
|
||||
#define LIGHTGREY RGB565_LIGHTGREY
|
||||
#define DARKGREY RGB565_DARKGREY
|
||||
#define BLUE RGB565_BLUE
|
||||
#define GREEN RGB565_GREEN
|
||||
#define CYAN RGB565_CYAN
|
||||
#define RED RGB565_RED
|
||||
#define MAGENTA RGB565_MAGENTA
|
||||
#define YELLOW RGB565_YELLOW
|
||||
#define WHITE RGB565_WHITE
|
||||
#define ORANGE RGB565_ORANGE
|
||||
#define GREENYELLOW RGB565_GREENYELLOW
|
||||
#define PINK RGB565_PINK
|
||||
#endif
|
||||
|
||||
// Many (but maybe not all) non-AVR board installs define macros
|
||||
// for compatibility with existing PROGMEM-reading AVR code.
|
||||
// Do our own checks and defines here for good measure...
|
||||
|
||||
#ifndef pgm_read_byte
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#endif
|
||||
#ifndef pgm_read_word
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#endif
|
||||
#ifndef pgm_read_dword
|
||||
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
|
||||
#endif
|
||||
// workaround of a15 asm compile error
|
||||
#ifdef ESP8266
|
||||
#undef pgm_read_word
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#endif
|
||||
|
||||
// Pointers are a peculiar case...typically 16-bit on AVR boards,
|
||||
// 32 bits elsewhere. Try to accommodate both...
|
||||
|
||||
#if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF)
|
||||
#define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr))
|
||||
#else
|
||||
#define pgm_read_pointer(addr) ((void *)pgm_read_word(addr))
|
||||
#endif
|
||||
|
||||
#ifndef _swap_uint8_t
|
||||
#define _swap_uint8_t(a, b) \
|
||||
{ \
|
||||
uint8_t t = a; \
|
||||
a = b; \
|
||||
b = t; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _swap_int16_t
|
||||
#define _swap_int16_t(a, b) \
|
||||
{ \
|
||||
int16_t t = a; \
|
||||
a = b; \
|
||||
b = t; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _diff
|
||||
#define _diff(a, b) ((a > b) ? (a - b) : (b - a))
|
||||
#endif
|
||||
|
||||
#ifndef _ordered_in_range
|
||||
#define _ordered_in_range(v, a, b) ((a <= v) && (v <= b))
|
||||
#endif
|
||||
|
||||
#ifndef _in_range
|
||||
#define _in_range(v, a, b) ((a > b) ? _ordered_in_range(v, b, a) : _ordered_in_range(v, a, b))
|
||||
#endif
|
||||
|
||||
#if !defined(ATTINY_CORE)
|
||||
INLINE GFXglyph *pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c)
|
||||
{
|
||||
#ifdef __AVR__
|
||||
return &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
|
||||
#else
|
||||
// expression in __AVR__ section may generate "dereferencing type-punned pointer will break strict-aliasing rules" warning
|
||||
// In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way
|
||||
// So expression may be simplified
|
||||
return gfxFont->glyph + c;
|
||||
#endif //__AVR__
|
||||
}
|
||||
|
||||
INLINE uint8_t *pgm_read_bitmap_ptr(const GFXfont *gfxFont)
|
||||
{
|
||||
#ifdef __AVR__
|
||||
return (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);
|
||||
#else
|
||||
// expression in __AVR__ section generates "dereferencing type-punned pointer will break strict-aliasing rules" warning
|
||||
// In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way
|
||||
// So expression may be simplified
|
||||
return gfxFont->bitmap;
|
||||
#endif //__AVR__
|
||||
}
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
/// A generic graphics superclass that can handle all sorts of drawing. At a minimum you can subclass and provide drawPixel(). At a maximum you can do a ton of overriding to optimize. Used for any/all Adafruit displays!
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
class Arduino_GFX : public Print
|
||||
#else
|
||||
class Arduino_GFX : public Print, public Arduino_G
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
{
|
||||
public:
|
||||
Arduino_GFX(int16_t w, int16_t h); // Constructor
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
virtual bool begin(int32_t speed = GFX_NOT_DEFINED) = 0;
|
||||
virtual void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) = 0;
|
||||
|
||||
// TRANSACTION API / CORE DRAW API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void startWrite();
|
||||
virtual void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
virtual void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
virtual void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
virtual void endWrite(void);
|
||||
|
||||
// CONTROL API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void setRotation(uint8_t r);
|
||||
virtual void invertDisplay(bool i);
|
||||
virtual void displayOn();
|
||||
virtual void displayOff();
|
||||
|
||||
// BASIC DRAW API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
// It's good to implement those, even if using transaction API
|
||||
void writePixel(int16_t x, int16_t y, uint16_t color);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void fillScreen(uint16_t color);
|
||||
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
|
||||
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
|
||||
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
|
||||
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
|
||||
void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
|
||||
void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
|
||||
void drawXBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void setTextSize(uint8_t s);
|
||||
void setTextSize(uint8_t sx, uint8_t sy);
|
||||
void setTextSize(uint8_t sx, uint8_t sy, uint8_t pixel_margin);
|
||||
|
||||
#if !defined(ATTINY_CORE)
|
||||
void setFont(const GFXfont *f = NULL);
|
||||
#if defined(U8G2_FONT_SUPPORT)
|
||||
void setFont(const uint8_t *font);
|
||||
void setUTF8Print(bool isEnable);
|
||||
uint16_t u8g2_font_get_word(const uint8_t *font, uint8_t offset);
|
||||
uint8_t u8g2_font_decode_get_unsigned_bits(uint8_t cnt);
|
||||
int8_t u8g2_font_decode_get_signed_bits(uint8_t cnt);
|
||||
void u8g2_font_decode_len(uint8_t len, uint8_t is_foreground, uint16_t color, uint16_t bg);
|
||||
#endif // defined(U8G2_FONT_SUPPORT)
|
||||
virtual void flush(void);
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
// adopt from LovyanGFX
|
||||
void drawEllipse(int16_t x, int16_t y, int16_t rx, int16_t ry, uint16_t color);
|
||||
void drawEllipseHelper(int32_t x, int32_t y, int32_t rx, int32_t ry, uint8_t cornername, uint16_t color);
|
||||
void fillEllipse(int16_t x, int16_t y, int16_t rx, int16_t ry, uint16_t color);
|
||||
void fillEllipseHelper(int32_t x, int32_t y, int32_t rx, int32_t ry, uint8_t cornername, int16_t delta, uint16_t color);
|
||||
void drawArc(int16_t x, int16_t y, int16_t r1, int16_t r2, float start, float end, uint16_t color);
|
||||
void fillArc(int16_t x, int16_t y, int16_t r1, int16_t r2, float start, float end, uint16_t color);
|
||||
void fillArcHelper(int16_t cx, int16_t cy, int16_t oradius, int16_t iradius, float start, float end, uint16_t color);
|
||||
|
||||
// TFT optimization code, too big for ATMEL family
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
void writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h);
|
||||
void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg);
|
||||
#else // !defined(LITTLE_FOOT_PRINT)
|
||||
virtual void writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
virtual void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
virtual void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
virtual void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
virtual void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
virtual void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h);
|
||||
virtual void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg);
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text cursor location
|
||||
@param x X coordinate in pixels
|
||||
@param y Y coordinate in pixels
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setCursor(int16_t x, int16_t y)
|
||||
{
|
||||
cursor_x = x;
|
||||
cursor_y = y;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text font color with transparant background
|
||||
@param c 16-bit 5-6-5 Color to draw text with
|
||||
@note For 'transparent' background, background and foreground
|
||||
are set to same color rather than using a separate flag.
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setTextColor(uint16_t c) { textcolor = textbgcolor = c; }
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text font color with custom background color
|
||||
@param c 16-bit 5-6-5 Color to draw text with
|
||||
@param bg 16-bit 5-6-5 Color to draw background/fill with
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setTextColor(uint16_t c, uint16_t bg)
|
||||
{
|
||||
textcolor = c;
|
||||
textbgcolor = bg;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set whether text that is too long for the screen width should
|
||||
automatically wrap around to the next line (else clip right).
|
||||
@param w true for wrapping, false for clipping
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setTextWrap(bool w) { wrap = w; }
|
||||
|
||||
virtual size_t write(uint8_t);
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get width of the display, accounting for current rotation
|
||||
@returns Width in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t width(void) const { return _width; };
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get height of the display, accounting for current rotation
|
||||
@returns Height in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t height(void) const { return _height; }
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get rotation setting for display
|
||||
@returns 0 thru 3 corresponding to 4 cardinal rotations
|
||||
*/
|
||||
/************************************************************************/
|
||||
uint8_t getRotation(void) const { return _rotation; }
|
||||
|
||||
// get current cursor position (get rotation safe maximum values,
|
||||
// using: width() for x, height() for y)
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get text cursor X location
|
||||
@returns X coordinate in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t getCursorX(void) const { return cursor_x; }
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get text cursor Y location
|
||||
@returns Y coordinate in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t getCursorY(void) const { return cursor_y; };
|
||||
|
||||
/*!
|
||||
@brief Given 8-bit red, green and blue values, return a 'packed'
|
||||
16-bit color value in '565' RGB format (5 bits red, 6 bits
|
||||
green, 5 bits blue). This is just a mathematical operation,
|
||||
no hardware is touched.
|
||||
@param red 8-bit red brightnesss (0 = off, 255 = max).
|
||||
@param green 8-bit green brightnesss (0 = off, 255 = max).
|
||||
@param blue 8-bit blue brightnesss (0 = off, 255 = max).
|
||||
@return 'Packed' 16-bit color value (565 format).
|
||||
*/
|
||||
uint16_t color565(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
|
||||
}
|
||||
|
||||
protected:
|
||||
void charBounds(char c, int16_t *x, int16_t *y, int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy);
|
||||
int16_t
|
||||
_width, ///< Display width as modified by current rotation
|
||||
_height, ///< Display height as modified by current rotation
|
||||
_max_x, ///< x zero base bound (_width - 1)
|
||||
_max_y, ///< y zero base bound (_height - 1)
|
||||
cursor_x, ///< x location to start print()ing text
|
||||
cursor_y; ///< y location to start print()ing text
|
||||
uint16_t
|
||||
textcolor, ///< 16-bit background color for print()
|
||||
textbgcolor; ///< 16-bit text color for print()
|
||||
uint8_t
|
||||
textsize_x, ///< Desired magnification in X-axis of text to print()
|
||||
textsize_y, ///< Desired magnification in Y-axis of text to print()
|
||||
text_pixel_margin, ///< Margin for each text pixel
|
||||
_rotation; ///< Display rotation (0 thru 3)
|
||||
bool
|
||||
wrap; ///< If set, 'wrap' text at right edge of display
|
||||
#if !defined(ATTINY_CORE)
|
||||
GFXfont *gfxFont; ///< Pointer to special font
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
#if defined(U8G2_FONT_SUPPORT)
|
||||
uint8_t *u8g2Font;
|
||||
bool _enableUTF8Print = false;
|
||||
uint8_t _utf8_state = 0;
|
||||
uint16_t _encoding;
|
||||
|
||||
uint8_t _u8g2_glyph_cnt;
|
||||
uint8_t _u8g2_bits_per_0;
|
||||
uint8_t _u8g2_bits_per_1;
|
||||
uint8_t _u8g2_bits_per_char_width;
|
||||
uint8_t _u8g2_bits_per_char_height;
|
||||
uint8_t _u8g2_bits_per_char_x;
|
||||
uint8_t _u8g2_bits_per_char_y;
|
||||
uint8_t _u8g2_bits_per_delta_x;
|
||||
int8_t _u8g2_max_char_width;
|
||||
int8_t _u8g2_max_char_height;
|
||||
uint16_t _u8g2_start_pos_upper_A;
|
||||
uint16_t _u8g2_start_pos_lower_a;
|
||||
uint16_t _u8g2_start_pos_unicode;
|
||||
uint8_t _u8g2_first_char;
|
||||
|
||||
uint8_t _u8g2_char_width;
|
||||
uint8_t _u8g2_char_height;
|
||||
int8_t _u8g2_char_x;
|
||||
int8_t _u8g2_char_y;
|
||||
int8_t _u8g2_delta_x;
|
||||
|
||||
int8_t _u8g2_dx;
|
||||
int8_t _u8g2_dy;
|
||||
uint16_t _u8g2_target_x;
|
||||
uint16_t _u8g2_target_y;
|
||||
|
||||
const uint8_t *_u8g2_decode_ptr;
|
||||
uint8_t _u8g2_decode_bit_pos;
|
||||
#endif // defined(U8G2_FONT_SUPPORT)
|
||||
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
int16_t
|
||||
WIDTH, ///< This is the 'raw' display width - never changes
|
||||
HEIGHT; ///< This is the 'raw' display height - never changes
|
||||
#endif // defined(LITTLE_FOOT_PRINT)
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_GFX_H_
|
||||
@@ -0,0 +1,208 @@
|
||||
#ifndef _ARDUINO_GFX_LIBRARIES_H_
|
||||
#define _ARDUINO_GFX_LIBRARIES_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
#include "databus/Arduino_ESP32RGBPanel.h"
|
||||
#include "databus/Arduino_XL9535SWSPI.h"
|
||||
|
||||
#include "Arduino_GFX.h" // Core graphics library
|
||||
|
||||
#include "display/Arduino_RGB_Display.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_SAMD) && defined(SEEED_GROVE_UI_WIRELESS)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define WIO_TERMINAL
|
||||
#define DF_GFX_CS LCD_SS_PIN
|
||||
#define DF_GFX_DC LCD_DC
|
||||
#define DF_GFX_RST GFX_NOT_DEFINED
|
||||
#define DF_GFX_BL LCD_BACKLIGHT
|
||||
#elif defined(ARDUINO_ESP32_S3_BOX)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define ESP32_S3_BOX
|
||||
#define DF_GFX_SCK TFT_CLK
|
||||
#define DF_GFX_MOSI TFT_MOSI
|
||||
#define DF_GFX_MISO TFT_MISO
|
||||
#define DF_GFX_CS TFT_CS
|
||||
#define DF_GFX_DC TFT_DC
|
||||
#define DF_GFX_RST TFT_RST
|
||||
#define DF_GFX_BL TFT_BL
|
||||
#elif defined(ARDUINO_M5Stack_Core_ESP32) || defined(ARDUINO_M5STACK_FIRE)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define M5STACK_CORE
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 23
|
||||
#define DF_GFX_MISO 19
|
||||
#define DF_GFX_CS 14
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST 33
|
||||
#define DF_GFX_BL 32
|
||||
#elif defined(ARDUINO_M5Stack_ATOMS3)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define M5STACK_ATOMS3
|
||||
#define DF_GFX_SCK 17
|
||||
#define DF_GFX_MOSI 21
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 15
|
||||
#define DF_GFX_DC 33
|
||||
#define DF_GFX_RST 34
|
||||
#define DF_GFX_BL 16
|
||||
#elif defined(ARDUINO_ODROID_ESP32)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define ODROID_GO
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 23
|
||||
#define DF_GFX_MISO 19
|
||||
#define DF_GFX_CS 5
|
||||
#define DF_GFX_DC 21
|
||||
#define DF_GFX_RST GFX_NOT_DEFINED
|
||||
#define DF_GFX_BL 14
|
||||
/* TTGO T-Watch */
|
||||
#elif defined(ARDUINO_T) || defined(ARDUINO_TWATCH_BASE) || defined(ARDUINO_TWATCH_2020_V1) || defined(ARDUINO_TWATCH_2020_V2)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define TTGO_T_WATCH
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 19
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 5
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST GFX_NOT_DEFINED
|
||||
#define DF_GFX_BL 12
|
||||
/* Waveshare RP2040-LCD-1.28 */
|
||||
#elif defined(ARDUINO_WAVESHARE_RP2040_LCD_1_28)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define WAVESHARE_RP2040_LCD_1_28
|
||||
#define DF_GFX_SCK 10
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 12
|
||||
#define DF_GFX_BL 25
|
||||
#define DF_GFX_SPI spi1
|
||||
#elif defined(ARDUINO_ARCH_NRF52840)
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 7
|
||||
#define DF_GFX_BL 6
|
||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
// PJRC Teensy 4.x
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 39 // GFX_NOT_DEFINED for display without CS pin
|
||||
#define DF_GFX_DC 41
|
||||
#define DF_GFX_RST 40
|
||||
#define DF_GFX_BL 22
|
||||
#elif defined(ARDUINO_BLACKPILL_F411CE)
|
||||
#define DF_GFX_SCK 5
|
||||
#define DF_GFX_MOSI 7
|
||||
#define DF_GFX_MISO 6
|
||||
#define DF_GFX_CS 4
|
||||
#define DF_GFX_DC 3
|
||||
#define DF_GFX_RST 2
|
||||
#define DF_GFX_BL 1
|
||||
#elif defined(TARGET_RP2040)
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 19
|
||||
#define DF_GFX_MISO 16
|
||||
#define DF_GFX_CS 17
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST 26
|
||||
#define DF_GFX_BL 28
|
||||
#define DF_GFX_SPI spi0
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32)
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 23
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 5
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST 33
|
||||
#define DF_GFX_BL 22
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2)
|
||||
#define DF_GFX_SCK 36
|
||||
#define DF_GFX_MOSI 35
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 34
|
||||
#define DF_GFX_DC 38
|
||||
#define DF_GFX_RST 33
|
||||
#define DF_GFX_BL 21
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
#define DF_GFX_SCK 36
|
||||
#define DF_GFX_MOSI 35
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 40
|
||||
#define DF_GFX_DC 41
|
||||
#define DF_GFX_RST 42
|
||||
#define DF_GFX_BL 48
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32C3)
|
||||
#define DF_GFX_SCK 4
|
||||
#define DF_GFX_MOSI 6
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 7
|
||||
#define DF_GFX_DC 2
|
||||
#define DF_GFX_RST 1
|
||||
#define DF_GFX_BL 3
|
||||
#elif defined(ESP8266)
|
||||
#define DF_GFX_SCK 14
|
||||
#define DF_GFX_MOSI 13
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 15
|
||||
#define DF_GFX_DC 4
|
||||
#define DF_GFX_RST 2
|
||||
#define DF_GFX_BL 5
|
||||
#elif defined(RTL8722DM)
|
||||
#if defined(BOARD_RTL8720DN_BW16)
|
||||
#define DF_GFX_SCK 10
|
||||
#define DF_GFX_MOSI 12
|
||||
#define DF_GFX_MISO 11
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 6
|
||||
#define DF_GFX_BL 3
|
||||
#elif defined(BOARD_RTL8722DM)
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 18
|
||||
#define DF_GFX_DC 17
|
||||
#define DF_GFX_RST 22
|
||||
#define DF_GFX_BL 23
|
||||
#elif defined(BOARD_RTL8722DM_MINI)
|
||||
#define DF_GFX_SCK 11
|
||||
#define DF_GFX_MOSI 9
|
||||
#define DF_GFX_MISO 10
|
||||
#define DF_GFX_CS 12
|
||||
#define DF_GFX_DC 14
|
||||
#define DF_GFX_RST 15
|
||||
#define DF_GFX_BL 13
|
||||
#else // old version
|
||||
#define DF_GFX_SCK 19
|
||||
#define DF_GFX_MOSI 21
|
||||
#define DF_GFX_MISO 20
|
||||
#define DF_GFX_CS 18 // GFX_NOT_DEFINED for display without CS pin
|
||||
#define DF_GFX_DC 17
|
||||
#define DF_GFX_RST 2
|
||||
#define DF_GFX_BL 23
|
||||
#endif
|
||||
#elif defined(SEEED_XIAO_M0)
|
||||
#define DF_GFX_SCK 8
|
||||
#define DF_GFX_MOSI 10
|
||||
#define DF_GFX_MISO 9
|
||||
#define DF_GFX_CS 3 // GFX_NOT_DEFINED for display without CS pin
|
||||
#define DF_GFX_DC 2
|
||||
#define DF_GFX_RST 1
|
||||
#define DF_GFX_BL 0
|
||||
#else // default pins for Arduino Nano, Mini, Micro and more
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 7
|
||||
#define DF_GFX_BL 6
|
||||
#endif
|
||||
|
||||
#endif // _ARDUINO_GFX_LIBRARIES_H_
|
||||
@@ -0,0 +1,129 @@
|
||||
#include "Arduino_ESP32RGBPanel.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32RGBPanel::Arduino_ESP32RGBPanel(
|
||||
int8_t de, int8_t vsync, int8_t hsync, int8_t pclk,
|
||||
int8_t r0, int8_t r1, int8_t r2, int8_t r3, int8_t r4,
|
||||
int8_t g0, int8_t g1, int8_t g2, int8_t g3, int8_t g4, int8_t g5,
|
||||
int8_t b0, int8_t b1, int8_t b2, int8_t b3, int8_t b4,
|
||||
uint16_t hsync_polarity, uint16_t hsync_front_porch, uint16_t hsync_pulse_width, uint16_t hsync_back_porch,
|
||||
uint16_t vsync_polarity, uint16_t vsync_front_porch, uint16_t vsync_pulse_width, uint16_t vsync_back_porch,
|
||||
uint16_t pclk_active_neg, int32_t prefer_speed, bool useBigEndian,
|
||||
uint16_t de_idle_high, uint16_t pclk_idle_high)
|
||||
: _de(de), _vsync(vsync), _hsync(hsync), _pclk(pclk),
|
||||
_r0(r0), _r1(r1), _r2(r2), _r3(r3), _r4(r4),
|
||||
_g0(g0), _g1(g1), _g2(g2), _g3(g3), _g4(g4), _g5(g5),
|
||||
_b0(b0), _b1(b1), _b2(b2), _b3(b3), _b4(b4),
|
||||
_hsync_polarity(hsync_polarity), _hsync_front_porch(hsync_front_porch), _hsync_pulse_width(hsync_pulse_width), _hsync_back_porch(hsync_back_porch),
|
||||
_vsync_polarity(vsync_polarity), _vsync_front_porch(vsync_front_porch), _vsync_pulse_width(vsync_pulse_width), _vsync_back_porch(vsync_back_porch),
|
||||
_pclk_active_neg(pclk_active_neg), _prefer_speed(prefer_speed), _useBigEndian(useBigEndian),
|
||||
_de_idle_high(de_idle_high), _pclk_idle_high(pclk_idle_high)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32RGBPanel::begin(int32_t speed)
|
||||
{
|
||||
if (speed == GFX_NOT_DEFINED)
|
||||
{
|
||||
#ifdef CONFIG_SPIRAM_MODE_QUAD
|
||||
_speed = 6000000L;
|
||||
#else
|
||||
_speed = 12000000L;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
_speed = speed;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t *Arduino_ESP32RGBPanel::getFrameBuffer(int16_t w, int16_t h)
|
||||
{
|
||||
esp_lcd_rgb_panel_config_t *_panel_config = (esp_lcd_rgb_panel_config_t *)heap_caps_calloc(1, sizeof(esp_lcd_rgb_panel_config_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
|
||||
_panel_config->clk_src = LCD_CLK_SRC_PLL160M;
|
||||
|
||||
_panel_config->timings.pclk_hz = (_prefer_speed == GFX_NOT_DEFINED) ? _speed : _prefer_speed;
|
||||
_panel_config->timings.h_res = w;
|
||||
_panel_config->timings.v_res = h;
|
||||
// The following parameters should refer to LCD spec
|
||||
_panel_config->timings.hsync_pulse_width = _hsync_pulse_width;
|
||||
_panel_config->timings.hsync_back_porch = _hsync_back_porch;
|
||||
_panel_config->timings.hsync_front_porch = _hsync_front_porch;
|
||||
_panel_config->timings.vsync_pulse_width = _vsync_pulse_width;
|
||||
_panel_config->timings.vsync_back_porch = _vsync_back_porch;
|
||||
_panel_config->timings.vsync_front_porch = _vsync_front_porch;
|
||||
_panel_config->timings.flags.hsync_idle_low = (_hsync_polarity == 0) ? 1 : 0;
|
||||
_panel_config->timings.flags.vsync_idle_low = (_vsync_polarity == 0) ? 1 : 0;
|
||||
_panel_config->timings.flags.de_idle_high = _de_idle_high;
|
||||
_panel_config->timings.flags.pclk_active_neg = _pclk_active_neg;
|
||||
_panel_config->timings.flags.pclk_idle_high = _pclk_idle_high;
|
||||
|
||||
_panel_config->data_width = 16; // RGB565 in parallel mode, thus 16bit in width
|
||||
_panel_config->sram_trans_align = 8;
|
||||
_panel_config->psram_trans_align = 64;
|
||||
_panel_config->hsync_gpio_num = _hsync;
|
||||
_panel_config->vsync_gpio_num = _vsync;
|
||||
_panel_config->de_gpio_num = _de;
|
||||
_panel_config->pclk_gpio_num = _pclk;
|
||||
|
||||
if (_useBigEndian)
|
||||
{
|
||||
_panel_config->data_gpio_nums[0] = _g3;
|
||||
_panel_config->data_gpio_nums[1] = _g4;
|
||||
_panel_config->data_gpio_nums[2] = _g5;
|
||||
_panel_config->data_gpio_nums[3] = _r0;
|
||||
_panel_config->data_gpio_nums[4] = _r1;
|
||||
_panel_config->data_gpio_nums[5] = _r2;
|
||||
_panel_config->data_gpio_nums[6] = _r3;
|
||||
_panel_config->data_gpio_nums[7] = _r4;
|
||||
_panel_config->data_gpio_nums[8] = _b0;
|
||||
_panel_config->data_gpio_nums[9] = _b1;
|
||||
_panel_config->data_gpio_nums[10] = _b2;
|
||||
_panel_config->data_gpio_nums[11] = _b3;
|
||||
_panel_config->data_gpio_nums[12] = _b4;
|
||||
_panel_config->data_gpio_nums[13] = _g0;
|
||||
_panel_config->data_gpio_nums[14] = _g1;
|
||||
_panel_config->data_gpio_nums[15] = _g2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_panel_config->data_gpio_nums[0] = _b0;
|
||||
_panel_config->data_gpio_nums[1] = _b1;
|
||||
_panel_config->data_gpio_nums[2] = _b2;
|
||||
_panel_config->data_gpio_nums[3] = _b3;
|
||||
_panel_config->data_gpio_nums[4] = _b4;
|
||||
_panel_config->data_gpio_nums[5] = _g0;
|
||||
_panel_config->data_gpio_nums[6] = _g1;
|
||||
_panel_config->data_gpio_nums[7] = _g2;
|
||||
_panel_config->data_gpio_nums[8] = _g3;
|
||||
_panel_config->data_gpio_nums[9] = _g4;
|
||||
_panel_config->data_gpio_nums[10] = _g5;
|
||||
_panel_config->data_gpio_nums[11] = _r0;
|
||||
_panel_config->data_gpio_nums[12] = _r1;
|
||||
_panel_config->data_gpio_nums[13] = _r2;
|
||||
_panel_config->data_gpio_nums[14] = _r3;
|
||||
_panel_config->data_gpio_nums[15] = _r4;
|
||||
}
|
||||
|
||||
_panel_config->disp_gpio_num = GPIO_NUM_NC;
|
||||
|
||||
_panel_config->flags.disp_active_low = 0;
|
||||
_panel_config->flags.relax_on_idle = 0;
|
||||
_panel_config->flags.fb_in_psram = 1; // allocate frame buffer in PSRAM
|
||||
|
||||
ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(_panel_config, &_panel_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_reset(_panel_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_init(_panel_handle));
|
||||
|
||||
uint16_t color = random(0xffff);
|
||||
ESP_ERROR_CHECK(_panel_handle->draw_bitmap(_panel_handle, 0, 0, 1, 1, &color));
|
||||
|
||||
_rgb_panel = __containerof(_panel_handle, esp_rgb_panel_t, base);
|
||||
|
||||
return (uint16_t *)_rgb_panel->fb;
|
||||
}
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32RGBPANEL_H_
|
||||
#define _ARDUINO_ESP32RGBPANEL_H_
|
||||
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_private/gdma.h"
|
||||
#include "esp_pm.h"
|
||||
#include "hal/dma_types.h"
|
||||
|
||||
#include "hal/lcd_hal.h"
|
||||
#include "hal/lcd_ll.h"
|
||||
|
||||
#include "esp32s3/rom/cache.h"
|
||||
// This function is located in ROM (also see esp_rom/${target}/ld/${target}.rom.ld)
|
||||
extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size);
|
||||
|
||||
// extract from esp-idf esp_lcd_rgb_panel.c
|
||||
struct esp_rgb_panel_t
|
||||
{
|
||||
esp_lcd_panel_t base; // Base class of generic lcd panel
|
||||
int panel_id; // LCD panel ID
|
||||
lcd_hal_context_t hal; // Hal layer object
|
||||
size_t data_width; // Number of data lines (e.g. for RGB565, the data width is 16)
|
||||
size_t sram_trans_align; // Alignment for framebuffer that allocated in SRAM
|
||||
size_t psram_trans_align; // Alignment for framebuffer that allocated in PSRAM
|
||||
int disp_gpio_num; // Display control GPIO, which is used to perform action like "disp_off"
|
||||
intr_handle_t intr; // LCD peripheral interrupt handle
|
||||
esp_pm_lock_handle_t pm_lock; // Power management lock
|
||||
size_t num_dma_nodes; // Number of DMA descriptors that used to carry the frame buffer
|
||||
uint8_t *fb; // Frame buffer
|
||||
size_t fb_size; // Size of frame buffer
|
||||
int data_gpio_nums[SOC_LCD_RGB_DATA_WIDTH]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color"
|
||||
size_t resolution_hz; // Peripheral clock resolution
|
||||
esp_lcd_rgb_timing_t timings; // RGB timing parameters (e.g. pclk, sync pulse, porch width)
|
||||
gdma_channel_handle_t dma_chan; // DMA channel handle
|
||||
esp_lcd_rgb_panel_frame_trans_done_cb_t on_frame_trans_done; // Callback, invoked after frame trans done
|
||||
void *user_ctx; // Reserved user's data of callback functions
|
||||
int x_gap; // Extra gap in x coordinate, it's used when calculate the flush window
|
||||
int y_gap; // Extra gap in y coordinate, it's used when calculate the flush window
|
||||
struct
|
||||
{
|
||||
unsigned int disp_en_level : 1; // The level which can turn on the screen by `disp_gpio_num`
|
||||
unsigned int stream_mode : 1; // If set, the LCD transfers data continuously, otherwise, it stops refreshing the LCD when transaction done
|
||||
unsigned int fb_in_psram : 1; // Whether the frame buffer is in PSRAM
|
||||
} flags;
|
||||
dma_descriptor_t dma_nodes[]; // DMA descriptor pool of size `num_dma_nodes`
|
||||
};
|
||||
|
||||
class Arduino_ESP32RGBPanel
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32RGBPanel(
|
||||
int8_t de, int8_t vsync, int8_t hsync, int8_t pclk,
|
||||
int8_t r0, int8_t r1, int8_t r2, int8_t r3, int8_t r4,
|
||||
int8_t g0, int8_t g1, int8_t g2, int8_t g3, int8_t g4, int8_t g5,
|
||||
int8_t b0, int8_t b1, int8_t b2, int8_t b3, int8_t b4,
|
||||
uint16_t hsync_polarity, uint16_t hsync_front_porch, uint16_t hsync_pulse_width, uint16_t hsync_back_porch,
|
||||
uint16_t vsync_polarity, uint16_t vsync_front_porch, uint16_t vsync_pulse_width, uint16_t vsync_back_porch,
|
||||
uint16_t pclk_active_neg = 0, int32_t prefer_speed = GFX_NOT_DEFINED, bool useBigEndian = false,
|
||||
uint16_t de_idle_high = 0, uint16_t pclk_idle_high = 0);
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED);
|
||||
|
||||
uint16_t *getFrameBuffer(int16_t w, int16_t h);
|
||||
|
||||
protected:
|
||||
private:
|
||||
int32_t _speed;
|
||||
int8_t _de, _vsync, _hsync, _pclk;
|
||||
int8_t _r0, _r1, _r2, _r3, _r4;
|
||||
int8_t _g0, _g1, _g2, _g3, _g4, _g5;
|
||||
int8_t _b0, _b1, _b2, _b3, _b4;
|
||||
uint16_t _hsync_polarity;
|
||||
uint16_t _hsync_front_porch;
|
||||
uint16_t _hsync_pulse_width;
|
||||
uint16_t _hsync_back_porch;
|
||||
uint16_t _vsync_polarity;
|
||||
uint16_t _vsync_front_porch;
|
||||
uint16_t _vsync_pulse_width;
|
||||
uint16_t _vsync_back_porch;
|
||||
uint16_t _pclk_active_neg;
|
||||
int32_t _prefer_speed;
|
||||
bool _useBigEndian;
|
||||
uint16_t _de_idle_high;
|
||||
uint16_t _pclk_idle_high;
|
||||
|
||||
esp_lcd_panel_handle_t _panel_handle = NULL;
|
||||
esp_rgb_panel_t *_rgb_panel;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32RGBPANEL_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,276 @@
|
||||
#include "Arduino_XL9535SWSPI.h"
|
||||
|
||||
Arduino_XL9535SWSPI::Arduino_XL9535SWSPI(int8_t sda, int8_t scl, int8_t pwd, int8_t cs, int8_t sck, int8_t mosi, TwoWire *wire)
|
||||
: _sda(sda), _scl(scl), _pwd(pwd), _cs(cs), _sck(sck), _mosi(mosi), _wire(wire)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_XL9535SWSPI::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
UNUSED(speed);
|
||||
UNUSED(dataMode);
|
||||
|
||||
_address = XL9535_IIC_ADDRESS;
|
||||
_wire->beginTransmission(_address);
|
||||
if (!_wire->endTransmission())
|
||||
{
|
||||
Serial.println("Found xl9535");
|
||||
is_found = true;
|
||||
|
||||
if (_pwd != GFX_NOT_DEFINED)
|
||||
{
|
||||
this->pinMode(_pwd, OUTPUT);
|
||||
}
|
||||
this->pinMode(_cs, OUTPUT);
|
||||
this->pinMode(_sck, OUTPUT);
|
||||
this->pinMode(_mosi, OUTPUT);
|
||||
|
||||
if (_pwd != GFX_NOT_DEFINED)
|
||||
{
|
||||
this->digitalWrite(_pwd, 1);
|
||||
}
|
||||
this->digitalWrite(_cs, 1);
|
||||
this->digitalWrite(_sck, 1);
|
||||
this->digitalWrite(_mosi, 1);
|
||||
|
||||
// while(1)
|
||||
// {
|
||||
// this->digitalWrite(4, 0);
|
||||
// delay(1000);
|
||||
// this->digitalWrite(4, 1);
|
||||
// delay(1000);
|
||||
// }
|
||||
|
||||
// this->digitalWrite(_cs, 0);
|
||||
// this->digitalWrite(5, 1);
|
||||
// delay(100);
|
||||
// this->digitalWrite(5, 0);
|
||||
// delay(800);
|
||||
// this->digitalWrite(5, 1);
|
||||
// delay(800);
|
||||
// this->digitalWrite(_cs, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("xl9535 not found");
|
||||
is_found = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::beginWrite()
|
||||
{
|
||||
this->digitalWrite(_cs, 0);
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::endWrite()
|
||||
{
|
||||
this->digitalWrite(_cs, 1);
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::writeCommand(uint8_t c)
|
||||
{
|
||||
// D/C bit, command
|
||||
this->digitalWrite(_mosi, 0);
|
||||
this->digitalWrite(_sck, 0);
|
||||
this->digitalWrite(_sck, 1);
|
||||
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (c & bit)
|
||||
{
|
||||
this->digitalWrite(_mosi, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->digitalWrite(_mosi, 0);
|
||||
}
|
||||
this->digitalWrite(_sck, 0);
|
||||
bit >>= 1;
|
||||
this->digitalWrite(_sck, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::writeCommand16(uint16_t)
|
||||
{
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::write(uint8_t d)
|
||||
{
|
||||
// D/C bit, data
|
||||
this->digitalWrite(_mosi, 1);
|
||||
this->digitalWrite(_sck, 0);
|
||||
this->digitalWrite(_sck, 1);
|
||||
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (d & bit)
|
||||
{
|
||||
this->digitalWrite(_mosi, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->digitalWrite(_mosi, 0);
|
||||
}
|
||||
this->digitalWrite(_sck, 0);
|
||||
bit >>= 1;
|
||||
this->digitalWrite(_sck, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::write16(uint16_t)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void Arduino_XL9535SWSPI::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
void Arduino_XL9535SWSPI::writeRegister(uint8_t reg, uint8_t *data, size_t len)
|
||||
{
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(reg);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
_wire->write(data[i]);
|
||||
}
|
||||
_wire->endTransmission();
|
||||
}
|
||||
|
||||
uint8_t Arduino_XL9535SWSPI::readRegister(uint8_t reg, uint8_t *data, size_t len)
|
||||
{
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(reg);
|
||||
_wire->endTransmission();
|
||||
_wire->requestFrom(_address, len);
|
||||
size_t index = 0;
|
||||
while (index < len)
|
||||
data[index++] = _wire->read();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::pinMode(uint8_t pin, uint8_t mode)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
uint8_t port = 0;
|
||||
if (pin > 7)
|
||||
{
|
||||
this->readRegister(XL9535_CONFIG_PORT_1_REG, &port, 1);
|
||||
if (mode == OUTPUT)
|
||||
{
|
||||
port = port & (~(1 << (pin - 10)));
|
||||
}
|
||||
else
|
||||
{
|
||||
port = port | (1 << (pin - 10));
|
||||
}
|
||||
this->writeRegister(XL9535_CONFIG_PORT_1_REG, &port, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->readRegister(XL9535_CONFIG_PORT_0_REG, &port, 1);
|
||||
if (mode == OUTPUT)
|
||||
{
|
||||
port = port & (~(1 << pin));
|
||||
}
|
||||
else
|
||||
{
|
||||
port = port | (1 << pin);
|
||||
}
|
||||
this->writeRegister(XL9535_CONFIG_PORT_0_REG, &port, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("xl9535 not found");
|
||||
}
|
||||
}
|
||||
void Arduino_XL9535SWSPI::pinMode8(uint8_t port, uint8_t pin, uint8_t mode)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
uint8_t _pin = (mode != OUTPUT) ? pin : ~pin;
|
||||
if (port)
|
||||
{
|
||||
this->writeRegister(XL9535_CONFIG_PORT_1_REG, &_pin, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->writeRegister(XL9535_CONFIG_PORT_0_REG, &_pin, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("xl9535 not found");
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::digitalWrite(uint8_t pin, uint8_t val)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
uint8_t port = 0;
|
||||
uint8_t reg_data = 0;
|
||||
if (pin > 7)
|
||||
{
|
||||
this->readRegister(XL9535_OUTPUT_PORT_1_REG, ®_data, 1);
|
||||
reg_data = reg_data & (~(1 << (pin - 10)));
|
||||
port = reg_data | val << (pin - 10);
|
||||
this->writeRegister(XL9535_OUTPUT_PORT_1_REG, &port, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->readRegister(XL9535_OUTPUT_PORT_0_REG, ®_data, 1);
|
||||
reg_data = reg_data & (~(1 << pin));
|
||||
port = reg_data | val << pin;
|
||||
this->writeRegister(XL9535_OUTPUT_PORT_0_REG, &port, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("xl9535 not found");
|
||||
}
|
||||
}
|
||||
|
||||
int Arduino_XL9535SWSPI::digitalRead(uint8_t pin)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
int state = 0;
|
||||
uint8_t port = 0;
|
||||
if (pin > 7)
|
||||
{
|
||||
this->readRegister(XL9535_INPUT_PORT_1_REG, &port, 1);
|
||||
state = port >> (pin - 10) & 0x01 ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->readRegister(XL9535_INPUT_PORT_0_REG, &port, 1);
|
||||
state = port >> pin & 0x01 ? 1 : 0;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("xl9535 not found");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef _ARDUINO_XL9535SWSPI_H_
|
||||
#define _ARDUINO_XL9535SWSPI_H_
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#define XL9535_IIC_ADDRESS 0X20
|
||||
|
||||
#define XL9535_INPUT_PORT_0_REG 0X00
|
||||
#define XL9535_INPUT_PORT_1_REG 0X01
|
||||
#define XL9535_OUTPUT_PORT_0_REG 0X02
|
||||
#define XL9535_OUTPUT_PORT_1_REG 0X03
|
||||
#define XL9535_INVERSION_PORT_0_REG 0X04
|
||||
#define XL9535_INVERSION_PORT_1_REG 0X05
|
||||
#define XL9535_CONFIG_PORT_0_REG 0X06
|
||||
#define XL9535_CONFIG_PORT_1_REG 0X07
|
||||
|
||||
class Arduino_XL9535SWSPI : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_XL9535SWSPI(int8_t sda, int8_t scl, int8_t pwd, int8_t cs, int8_t sck, int8_t mosi, TwoWire *wire = &Wire);
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
void pinMode(uint8_t pin, uint8_t mode)override;
|
||||
void pinMode8(uint8_t port, uint8_t pin, uint8_t mode);
|
||||
|
||||
void digitalWrite(uint8_t pin, uint8_t val) override;
|
||||
int digitalRead(uint8_t pin) override;
|
||||
|
||||
protected:
|
||||
void writeRegister(uint8_t reg, uint8_t *data, size_t len);
|
||||
uint8_t readRegister(uint8_t reg, uint8_t *data, size_t len);
|
||||
|
||||
uint8_t _address;
|
||||
bool is_found;
|
||||
|
||||
int8_t _sda, _scl, _pwd, _cs, _sck, _mosi;
|
||||
TwoWire *_wire;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_XL9535SWSPI_H_
|
||||
@@ -0,0 +1,498 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "Arduino_RGB_Display.h"
|
||||
|
||||
Arduino_RGB_Display::Arduino_RGB_Display(
|
||||
int16_t w, int16_t h, Arduino_ESP32RGBPanel *rgbpanel, uint8_t r, bool auto_flush,
|
||||
Arduino_DataBus *bus, int8_t rst, const uint8_t *init_operations, size_t init_operations_len)
|
||||
: Arduino_GFX(w, h), _rgbpanel(rgbpanel), _auto_flush(auto_flush),
|
||||
_bus(bus), _rst(rst), _init_operations(init_operations), _init_operations_len(init_operations_len)
|
||||
{
|
||||
_framebuffer_size = w * h * 2;
|
||||
MAX_X = WIDTH - 1;
|
||||
MAX_Y = HEIGHT - 1;
|
||||
setRotation(r);
|
||||
}
|
||||
|
||||
bool Arduino_RGB_Display::begin(int32_t speed)
|
||||
{
|
||||
if (_bus)
|
||||
{
|
||||
if (!_bus->begin())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_rst != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rst, OUTPUT);
|
||||
digitalWrite(_rst, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(_rst, LOW);
|
||||
delay(120);
|
||||
digitalWrite(_rst, HIGH);
|
||||
delay(120);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_bus)
|
||||
{
|
||||
// Software Rest
|
||||
_bus->sendCommand(0x01);
|
||||
delay(120);
|
||||
}
|
||||
}
|
||||
|
||||
if (_bus)
|
||||
{
|
||||
if (_init_operations_len > 0)
|
||||
{
|
||||
_bus->batchOperation((uint8_t *)_init_operations, _init_operations_len);
|
||||
}
|
||||
}
|
||||
|
||||
_rgbpanel->begin(speed);
|
||||
_framebuffer = _rgbpanel->getFrameBuffer(WIDTH, HEIGHT);
|
||||
|
||||
if (!_framebuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
uint16_t *fb = _framebuffer;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
fb += (int32_t)x * _height;
|
||||
fb += _max_y - y;
|
||||
*fb = color;
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr((uint32_t)fb, 2);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
fb += (int32_t)(_max_y - y) * _width;
|
||||
fb += _max_x - x;
|
||||
*fb = color;
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr((uint32_t)fb, 2);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
fb += (int32_t)(_max_x - x) * _height;
|
||||
fb += y;
|
||||
*fb = color;
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr((uint32_t)fb, 2);
|
||||
}
|
||||
break;
|
||||
default: // case 0:
|
||||
fb += (int32_t)y * _width;
|
||||
fb += x;
|
||||
*fb = color;
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr((uint32_t)fb, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writeFastVLine(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastVLine(x: %d, y: %d, h: %d)", x, y, h);
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastHLineCore(_height - y - h, x, h, color);
|
||||
break;
|
||||
case 2:
|
||||
writeFastVLineCore(_max_x - x, _height - y - h, h, color);
|
||||
break;
|
||||
case 3:
|
||||
writeFastHLineCore(y, _max_x - x, h, color);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastVLineCore(x, y, h, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writeFastVLineCore(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastVLineCore(x: %d, y: %d, h: %d)", x, y, h);
|
||||
if (_ordered_in_range(x, 0, MAX_X) && h)
|
||||
{ // X on screen, nonzero height
|
||||
if (h < 0)
|
||||
{ // If negative height...
|
||||
y += h + 1; // Move Y to top edge
|
||||
h = -h; // Use positive height
|
||||
}
|
||||
if (y <= MAX_Y)
|
||||
{ // Not off bottom
|
||||
int16_t y2 = y + h - 1;
|
||||
if (y2 >= 0)
|
||||
{ // Not off top
|
||||
// Line partly or fully overlaps screen
|
||||
if (y < 0)
|
||||
{
|
||||
y = 0;
|
||||
h = y2 + 1;
|
||||
} // Clip top
|
||||
if (y2 > MAX_Y)
|
||||
{
|
||||
h = MAX_Y - y + 1;
|
||||
} // Clip bottom
|
||||
|
||||
uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
if (_auto_flush)
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
*fb = color;
|
||||
Cache_WriteBack_Addr((uint32_t)fb, 2);
|
||||
fb += WIDTH;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
*fb = color;
|
||||
fb += WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writeFastHLine(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastHLine(x: %d, y: %d, w: %d)", x, y, w);
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastVLineCore(_max_y - y, x, w, color);
|
||||
break;
|
||||
case 2:
|
||||
writeFastHLineCore(_width - x - w, _max_y - y, w, color);
|
||||
break;
|
||||
case 3:
|
||||
writeFastVLineCore(y, _width - x - w, w, color);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastHLineCore(x, y, w, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writeFastHLineCore(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastHLineCore(x: %d, y: %d, w: %d)", x, y, w);
|
||||
if (_ordered_in_range(y, 0, MAX_Y) && w)
|
||||
{ // Y on screen, nonzero width
|
||||
if (w < 0)
|
||||
{ // If negative width...
|
||||
x += w + 1; // Move X to left edge
|
||||
w = -w; // Use positive width
|
||||
}
|
||||
if (x <= MAX_X)
|
||||
{ // Not off right
|
||||
int16_t x2 = x + w - 1;
|
||||
if (x2 >= 0)
|
||||
{ // Not off left
|
||||
// Line partly or fully overlaps screen
|
||||
if (x < 0)
|
||||
{
|
||||
x = 0;
|
||||
w = x2 + 1;
|
||||
} // Clip left
|
||||
if (x2 > MAX_X)
|
||||
{
|
||||
w = MAX_X - x + 1;
|
||||
} // Clip right
|
||||
|
||||
uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
uint32_t cachePos = (uint32_t)fb;
|
||||
int16_t writeSize = w * 2;
|
||||
while (w--)
|
||||
{
|
||||
*(fb++) = color;
|
||||
}
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr(cachePos, writeSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writeFillRectPreclipped(int16_t x, int16_t y,
|
||||
int16_t w, int16_t h, uint16_t color)
|
||||
{
|
||||
// log_i("writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
|
||||
if (_rotation > 0)
|
||||
{
|
||||
int16_t t = x;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
x = WIDTH - y - h;
|
||||
y = t;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - x - w;
|
||||
y = HEIGHT - y - h;
|
||||
break;
|
||||
case 3:
|
||||
x = y;
|
||||
y = HEIGHT - t - w;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// log_i("adjusted writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * WIDTH;
|
||||
uint32_t cachePos = (uint32_t)row;
|
||||
row += x;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] = color;
|
||||
}
|
||||
row += WIDTH;
|
||||
}
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr(cachePos, WIDTH * h * 2);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * w;
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip += (x + w - 1) - _max_x;
|
||||
w -= (x + w - 1) - _max_x;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
uint32_t cachePos = (uint32_t)row;
|
||||
row += x;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] = color_index[*bitmap++];
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr(cachePos, _width * h * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::draw16bitRGBBitmap(int16_t x, int16_t y,
|
||||
uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
bool result;
|
||||
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
result = gfx_draw_bitmap_to_framebuffer_rotate_1(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
case 2:
|
||||
result = gfx_draw_bitmap_to_framebuffer_rotate_2(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
case 3:
|
||||
result = gfx_draw_bitmap_to_framebuffer_rotate_3(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
default: // case 0:
|
||||
result = gfx_draw_bitmap_to_framebuffer(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (_auto_flush)
|
||||
{
|
||||
uint32_t cachePos;
|
||||
size_t cache_size;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
cachePos = (uint32_t)(_framebuffer + (x * WIDTH));
|
||||
cache_size = HEIGHT * w * 2;
|
||||
break;
|
||||
case 2:
|
||||
cachePos = (uint32_t)(_framebuffer + ((MAX_Y - y) * WIDTH));
|
||||
cache_size = HEIGHT * h * 2;
|
||||
break;
|
||||
case 3:
|
||||
cachePos = (uint32_t)(_framebuffer + ((MAX_Y - x) * WIDTH));
|
||||
cache_size = HEIGHT * w * 2;
|
||||
break;
|
||||
default: // case 0:
|
||||
cachePos = (uint32_t)(_framebuffer + (y * WIDTH) + x);
|
||||
cache_size = (WIDTH * (h - 1) + w) * 2;
|
||||
}
|
||||
Cache_WriteBack_Addr(cachePos, cache_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::draw16bitBeRGBBitmap(int16_t x, int16_t y,
|
||||
uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::draw16bitBeRGBBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t xskip = 0;
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * w;
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
xskip = (x + w - 1) - _max_x;
|
||||
w -= xskip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
xskip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
uint32_t cachePos = (uint32_t)row;
|
||||
row += x;
|
||||
uint16_t color;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
color = *bitmap++;
|
||||
MSB_16_SET(row[i], color);
|
||||
}
|
||||
bitmap += xskip;
|
||||
row += _width;
|
||||
}
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr(cachePos, _width * h * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::flush(void)
|
||||
{
|
||||
if (!_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr((uint32_t)_framebuffer, _framebuffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t *Arduino_RGB_Display::getFramebuffer()
|
||||
{
|
||||
return _framebuffer;
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
void Arduino_RGB_Display::XL_pinMode(uint8_t pin, uint8_t mode)
|
||||
{
|
||||
_bus->pinMode(pin, mode);
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::XL_digitalWrite(uint8_t pin, uint8_t val)
|
||||
{
|
||||
_bus->digitalWrite(pin, val);
|
||||
}
|
||||
|
||||
int Arduino_RGB_Display::XL_digitalRead(uint8_t pin)
|
||||
{
|
||||
return _bus->digitalRead(pin);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
280
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/font/glcdfont.h
Normal file
280
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/font/glcdfont.h
Normal file
@@ -0,0 +1,280 @@
|
||||
// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0.
|
||||
// See gfxfont.h for newer custom bitmap font info.
|
||||
|
||||
#ifndef FONT5X7_H
|
||||
#define FONT5X7_H
|
||||
|
||||
#ifdef __AVR__
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <pgmspace.h>
|
||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
// PROGMEM is defefind for T4 to place data in specific memory section
|
||||
#undef PROGMEM
|
||||
#define PROGMEM
|
||||
#else
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
// Standard ASCII 5x7 font
|
||||
|
||||
static const unsigned char font[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
|
||||
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
|
||||
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
|
||||
0x18, 0x3C, 0x7E, 0x3C, 0x18,
|
||||
0x1C, 0x57, 0x7D, 0x57, 0x1C,
|
||||
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
|
||||
0x00, 0x18, 0x3C, 0x18, 0x00,
|
||||
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
|
||||
0x00, 0x18, 0x24, 0x18, 0x00,
|
||||
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
|
||||
0x30, 0x48, 0x3A, 0x06, 0x0E,
|
||||
0x26, 0x29, 0x79, 0x29, 0x26,
|
||||
0x40, 0x7F, 0x05, 0x05, 0x07,
|
||||
0x40, 0x7F, 0x05, 0x25, 0x3F,
|
||||
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
|
||||
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
|
||||
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
|
||||
0x14, 0x22, 0x7F, 0x22, 0x14,
|
||||
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
|
||||
0x06, 0x09, 0x7F, 0x01, 0x7F,
|
||||
0x00, 0x66, 0x89, 0x95, 0x6A,
|
||||
0x60, 0x60, 0x60, 0x60, 0x60,
|
||||
0x94, 0xA2, 0xFF, 0xA2, 0x94,
|
||||
0x08, 0x04, 0x7E, 0x04, 0x08,
|
||||
0x10, 0x20, 0x7E, 0x20, 0x10,
|
||||
0x08, 0x08, 0x2A, 0x1C, 0x08,
|
||||
0x08, 0x1C, 0x2A, 0x08, 0x08,
|
||||
0x1E, 0x10, 0x10, 0x10, 0x10,
|
||||
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
|
||||
0x30, 0x38, 0x3E, 0x38, 0x30,
|
||||
0x06, 0x0E, 0x3E, 0x0E, 0x06,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5F, 0x00, 0x00,
|
||||
0x00, 0x07, 0x00, 0x07, 0x00,
|
||||
0x14, 0x7F, 0x14, 0x7F, 0x14,
|
||||
0x24, 0x2A, 0x7F, 0x2A, 0x12,
|
||||
0x23, 0x13, 0x08, 0x64, 0x62,
|
||||
0x36, 0x49, 0x56, 0x20, 0x50,
|
||||
0x00, 0x08, 0x07, 0x03, 0x00,
|
||||
0x00, 0x1C, 0x22, 0x41, 0x00,
|
||||
0x00, 0x41, 0x22, 0x1C, 0x00,
|
||||
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
|
||||
0x08, 0x08, 0x3E, 0x08, 0x08,
|
||||
0x00, 0x80, 0x70, 0x30, 0x00,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x00, 0x00, 0x60, 0x60, 0x00,
|
||||
0x20, 0x10, 0x08, 0x04, 0x02,
|
||||
0x3E, 0x51, 0x49, 0x45, 0x3E,
|
||||
0x00, 0x42, 0x7F, 0x40, 0x00,
|
||||
0x72, 0x49, 0x49, 0x49, 0x46,
|
||||
0x21, 0x41, 0x49, 0x4D, 0x33,
|
||||
0x18, 0x14, 0x12, 0x7F, 0x10,
|
||||
0x27, 0x45, 0x45, 0x45, 0x39,
|
||||
0x3C, 0x4A, 0x49, 0x49, 0x31,
|
||||
0x41, 0x21, 0x11, 0x09, 0x07,
|
||||
0x36, 0x49, 0x49, 0x49, 0x36,
|
||||
0x46, 0x49, 0x49, 0x29, 0x1E,
|
||||
0x00, 0x00, 0x14, 0x00, 0x00,
|
||||
0x00, 0x40, 0x34, 0x00, 0x00,
|
||||
0x00, 0x08, 0x14, 0x22, 0x41,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x00, 0x41, 0x22, 0x14, 0x08,
|
||||
0x02, 0x01, 0x59, 0x09, 0x06,
|
||||
0x3E, 0x41, 0x5D, 0x59, 0x4E,
|
||||
0x7C, 0x12, 0x11, 0x12, 0x7C,
|
||||
0x7F, 0x49, 0x49, 0x49, 0x36,
|
||||
0x3E, 0x41, 0x41, 0x41, 0x22,
|
||||
0x7F, 0x41, 0x41, 0x41, 0x3E,
|
||||
0x7F, 0x49, 0x49, 0x49, 0x41,
|
||||
0x7F, 0x09, 0x09, 0x09, 0x01,
|
||||
0x3E, 0x41, 0x41, 0x51, 0x73,
|
||||
0x7F, 0x08, 0x08, 0x08, 0x7F,
|
||||
0x00, 0x41, 0x7F, 0x41, 0x00,
|
||||
0x20, 0x40, 0x41, 0x3F, 0x01,
|
||||
0x7F, 0x08, 0x14, 0x22, 0x41,
|
||||
0x7F, 0x40, 0x40, 0x40, 0x40,
|
||||
0x7F, 0x02, 0x1C, 0x02, 0x7F,
|
||||
0x7F, 0x04, 0x08, 0x10, 0x7F,
|
||||
0x3E, 0x41, 0x41, 0x41, 0x3E,
|
||||
0x7F, 0x09, 0x09, 0x09, 0x06,
|
||||
0x3E, 0x41, 0x51, 0x21, 0x5E,
|
||||
0x7F, 0x09, 0x19, 0x29, 0x46,
|
||||
0x26, 0x49, 0x49, 0x49, 0x32,
|
||||
0x03, 0x01, 0x7F, 0x01, 0x03,
|
||||
0x3F, 0x40, 0x40, 0x40, 0x3F,
|
||||
0x1F, 0x20, 0x40, 0x20, 0x1F,
|
||||
0x3F, 0x40, 0x38, 0x40, 0x3F,
|
||||
0x63, 0x14, 0x08, 0x14, 0x63,
|
||||
0x03, 0x04, 0x78, 0x04, 0x03,
|
||||
0x61, 0x59, 0x49, 0x4D, 0x43,
|
||||
0x00, 0x7F, 0x41, 0x41, 0x41,
|
||||
0x02, 0x04, 0x08, 0x10, 0x20,
|
||||
0x00, 0x41, 0x41, 0x41, 0x7F,
|
||||
0x04, 0x02, 0x01, 0x02, 0x04,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40,
|
||||
0x00, 0x03, 0x07, 0x08, 0x00,
|
||||
0x20, 0x54, 0x54, 0x78, 0x40,
|
||||
0x7F, 0x28, 0x44, 0x44, 0x38,
|
||||
0x38, 0x44, 0x44, 0x44, 0x28,
|
||||
0x38, 0x44, 0x44, 0x28, 0x7F,
|
||||
0x38, 0x54, 0x54, 0x54, 0x18,
|
||||
0x00, 0x08, 0x7E, 0x09, 0x02,
|
||||
0x18, 0xA4, 0xA4, 0x9C, 0x78,
|
||||
0x7F, 0x08, 0x04, 0x04, 0x78,
|
||||
0x00, 0x44, 0x7D, 0x40, 0x00,
|
||||
0x20, 0x40, 0x40, 0x3D, 0x00,
|
||||
0x7F, 0x10, 0x28, 0x44, 0x00,
|
||||
0x00, 0x41, 0x7F, 0x40, 0x00,
|
||||
0x7C, 0x04, 0x78, 0x04, 0x78,
|
||||
0x7C, 0x08, 0x04, 0x04, 0x78,
|
||||
0x38, 0x44, 0x44, 0x44, 0x38,
|
||||
0xFC, 0x18, 0x24, 0x24, 0x18,
|
||||
0x18, 0x24, 0x24, 0x18, 0xFC,
|
||||
0x7C, 0x08, 0x04, 0x04, 0x08,
|
||||
0x48, 0x54, 0x54, 0x54, 0x24,
|
||||
0x04, 0x04, 0x3F, 0x44, 0x24,
|
||||
0x3C, 0x40, 0x40, 0x20, 0x7C,
|
||||
0x1C, 0x20, 0x40, 0x20, 0x1C,
|
||||
0x3C, 0x40, 0x30, 0x40, 0x3C,
|
||||
0x44, 0x28, 0x10, 0x28, 0x44,
|
||||
0x4C, 0x90, 0x90, 0x90, 0x7C,
|
||||
0x44, 0x64, 0x54, 0x4C, 0x44,
|
||||
0x00, 0x08, 0x36, 0x41, 0x00,
|
||||
0x00, 0x00, 0x77, 0x00, 0x00,
|
||||
0x00, 0x41, 0x36, 0x08, 0x00,
|
||||
0x02, 0x01, 0x02, 0x04, 0x02,
|
||||
0x3C, 0x26, 0x23, 0x26, 0x3C,
|
||||
0x1E, 0xA1, 0xA1, 0x61, 0x12,
|
||||
0x3A, 0x40, 0x40, 0x20, 0x7A,
|
||||
0x38, 0x54, 0x54, 0x55, 0x59,
|
||||
0x21, 0x55, 0x55, 0x79, 0x41,
|
||||
0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
|
||||
0x21, 0x55, 0x54, 0x78, 0x40,
|
||||
0x20, 0x54, 0x55, 0x79, 0x40,
|
||||
0x0C, 0x1E, 0x52, 0x72, 0x12,
|
||||
0x39, 0x55, 0x55, 0x55, 0x59,
|
||||
0x39, 0x54, 0x54, 0x54, 0x59,
|
||||
0x39, 0x55, 0x54, 0x54, 0x58,
|
||||
0x00, 0x00, 0x45, 0x7C, 0x41,
|
||||
0x00, 0x02, 0x45, 0x7D, 0x42,
|
||||
0x00, 0x01, 0x45, 0x7C, 0x40,
|
||||
0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
|
||||
0xF0, 0x28, 0x25, 0x28, 0xF0,
|
||||
0x7C, 0x54, 0x55, 0x45, 0x00,
|
||||
0x20, 0x54, 0x54, 0x7C, 0x54,
|
||||
0x7C, 0x0A, 0x09, 0x7F, 0x49,
|
||||
0x32, 0x49, 0x49, 0x49, 0x32,
|
||||
0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
|
||||
0x32, 0x4A, 0x48, 0x48, 0x30,
|
||||
0x3A, 0x41, 0x41, 0x21, 0x7A,
|
||||
0x3A, 0x42, 0x40, 0x20, 0x78,
|
||||
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
|
||||
0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
|
||||
0x3D, 0x40, 0x40, 0x40, 0x3D,
|
||||
0x3C, 0x24, 0xFF, 0x24, 0x24,
|
||||
0x48, 0x7E, 0x49, 0x43, 0x66,
|
||||
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
|
||||
0xFF, 0x09, 0x29, 0xF6, 0x20,
|
||||
0xC0, 0x88, 0x7E, 0x09, 0x03,
|
||||
0x20, 0x54, 0x54, 0x79, 0x41,
|
||||
0x00, 0x00, 0x44, 0x7D, 0x41,
|
||||
0x30, 0x48, 0x48, 0x4A, 0x32,
|
||||
0x38, 0x40, 0x40, 0x22, 0x7A,
|
||||
0x00, 0x7A, 0x0A, 0x0A, 0x72,
|
||||
0x7D, 0x0D, 0x19, 0x31, 0x7D,
|
||||
0x26, 0x29, 0x29, 0x2F, 0x28,
|
||||
0x26, 0x29, 0x29, 0x29, 0x26,
|
||||
0x30, 0x48, 0x4D, 0x40, 0x20,
|
||||
0x38, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x38,
|
||||
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
|
||||
0x2F, 0x10, 0x28, 0x34, 0xFA,
|
||||
0x00, 0x00, 0x7B, 0x00, 0x00,
|
||||
0x08, 0x14, 0x2A, 0x14, 0x22,
|
||||
0x22, 0x14, 0x2A, 0x14, 0x08,
|
||||
0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
|
||||
0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
|
||||
0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
|
||||
0x00, 0x00, 0x00, 0xFF, 0x00,
|
||||
0x10, 0x10, 0x10, 0xFF, 0x00,
|
||||
0x14, 0x14, 0x14, 0xFF, 0x00,
|
||||
0x10, 0x10, 0xFF, 0x00, 0xFF,
|
||||
0x10, 0x10, 0xF0, 0x10, 0xF0,
|
||||
0x14, 0x14, 0x14, 0xFC, 0x00,
|
||||
0x14, 0x14, 0xF7, 0x00, 0xFF,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x14, 0x14, 0xF4, 0x04, 0xFC,
|
||||
0x14, 0x14, 0x17, 0x10, 0x1F,
|
||||
0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0x1F, 0x00,
|
||||
0x10, 0x10, 0x10, 0xF0, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1F, 0x10,
|
||||
0x10, 0x10, 0x10, 0x1F, 0x10,
|
||||
0x10, 0x10, 0x10, 0xF0, 0x10,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0xFF, 0x10,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x14,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x00, 0x00, 0x1F, 0x10, 0x17,
|
||||
0x00, 0x00, 0xFC, 0x04, 0xF4,
|
||||
0x14, 0x14, 0x17, 0x10, 0x17,
|
||||
0x14, 0x14, 0xF4, 0x04, 0xF4,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xF7,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0xF7, 0x00, 0xF7,
|
||||
0x14, 0x14, 0x14, 0x17, 0x14,
|
||||
0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0xF4, 0x14,
|
||||
0x10, 0x10, 0xF0, 0x10, 0xF0,
|
||||
0x00, 0x00, 0x1F, 0x10, 0x1F,
|
||||
0x00, 0x00, 0x00, 0x1F, 0x14,
|
||||
0x00, 0x00, 0x00, 0xFC, 0x14,
|
||||
0x00, 0x00, 0xF0, 0x10, 0xF0,
|
||||
0x10, 0x10, 0xFF, 0x10, 0xFF,
|
||||
0x14, 0x14, 0x14, 0xFF, 0x14,
|
||||
0x10, 0x10, 0x10, 0x1F, 0x00,
|
||||
0x00, 0x00, 0x00, 0xF0, 0x10,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||
0x38, 0x44, 0x44, 0x38, 0x44,
|
||||
0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
|
||||
0x7E, 0x02, 0x02, 0x06, 0x06,
|
||||
0x02, 0x7E, 0x02, 0x7E, 0x02,
|
||||
0x63, 0x55, 0x49, 0x41, 0x63,
|
||||
0x38, 0x44, 0x44, 0x3C, 0x04,
|
||||
0x40, 0x7E, 0x20, 0x1E, 0x20,
|
||||
0x06, 0x02, 0x7E, 0x02, 0x02,
|
||||
0x99, 0xA5, 0xE7, 0xA5, 0x99,
|
||||
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
|
||||
0x4C, 0x72, 0x01, 0x72, 0x4C,
|
||||
0x30, 0x4A, 0x4D, 0x4D, 0x30,
|
||||
0x30, 0x48, 0x78, 0x48, 0x30,
|
||||
0xBC, 0x62, 0x5A, 0x46, 0x3D,
|
||||
0x3E, 0x49, 0x49, 0x49, 0x00,
|
||||
0x7E, 0x01, 0x01, 0x01, 0x7E,
|
||||
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
|
||||
0x44, 0x44, 0x5F, 0x44, 0x44,
|
||||
0x40, 0x51, 0x4A, 0x44, 0x40,
|
||||
0x40, 0x44, 0x4A, 0x51, 0x40,
|
||||
0x00, 0x00, 0xFF, 0x01, 0x03,
|
||||
0xE0, 0x80, 0xFF, 0x00, 0x00,
|
||||
0x08, 0x08, 0x6B, 0x6B, 0x08,
|
||||
0x36, 0x12, 0x36, 0x24, 0x36,
|
||||
0x00, 0x06, 0x09, 0x09, 0x06,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00,
|
||||
0x00, 0x00, 0x10, 0x10, 0x00,
|
||||
0x30, 0x40, 0xFF, 0x01, 0x01,
|
||||
0x00, 0x1F, 0x01, 0x01, 0x1E,
|
||||
0x00, 0x19, 0x1D, 0x17, 0x12,
|
||||
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
|
||||
};
|
||||
#endif // FONT5X7_H
|
||||
31
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/gfxfont.h
Normal file
31
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/gfxfont.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// Font structures for newer Adafruit_GFX (1.1 and later).
|
||||
// Example fonts are included in 'Fonts' directory.
|
||||
// To use a font in your Arduino sketch, #include the corresponding .h
|
||||
// file and pass address of GFXfont struct to setFont(). Pass NULL to
|
||||
// revert to 'classic' fixed-space bitmap font.
|
||||
|
||||
#ifndef _GFXFONT_H_
|
||||
#define _GFXFONT_H_
|
||||
|
||||
/// Font data stored PER GLYPH
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap
|
||||
uint8_t width; ///< Bitmap dimensions in pixels
|
||||
uint8_t height; ///< Bitmap dimensions in pixels
|
||||
uint8_t xAdvance; ///< Distance to advance cursor (x axis)
|
||||
int8_t xOffset; ///< X dist from cursor pos to UL corner
|
||||
int8_t yOffset; ///< Y dist from cursor pos to UL corner
|
||||
} GFXglyph;
|
||||
|
||||
/// Data stored for FONT AS A WHOLE
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *bitmap; ///< Glyph bitmaps, concatenated
|
||||
GFXglyph *glyph; ///< Glyph array
|
||||
uint8_t first; ///< ASCII extents (first char)
|
||||
uint8_t last; ///< ASCII extents (last char)
|
||||
uint8_t yAdvance; ///< Newline distance (y axis)
|
||||
} GFXfont;
|
||||
|
||||
#endif // _GFXFONT_H_
|
||||
@@ -260,6 +260,73 @@ board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 16777216
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 16MB
|
||||
[env:ESP32_S3_16_8_LILYGO_AP]
|
||||
board = esp32-s3-devkitc-1
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
build_unflags =
|
||||
-std=gnu++11
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
;-D ILI9341_DRIVER
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
lib2\Arduino_GFX-1.3.7
|
||||
build_flags =
|
||||
-std=gnu++17
|
||||
${env.build_flags}
|
||||
-D HAS_TFT
|
||||
-D HAS_LILYGO_TPANEL
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D HAS_BLE_WRITER
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=34
|
||||
-D FLASHER_AP_POWER={-1}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
|
||||
-D FLASHER_AP_TXD=48
|
||||
-D FLASHER_AP_RXD=47
|
||||
|
||||
-D FLASHER_DEBUG_TXD=43
|
||||
-D FLASHER_DEBUG_RXD=44
|
||||
-D FLASHER_DEBUG_PROG=33
|
||||
-D FLASHER_LED=-1
|
||||
;-D HAS_RGB_LED
|
||||
;-D FLASHER_RGB_LED=48
|
||||
;-D ST7789_DRIVER
|
||||
-D TFT_WIDTH=480
|
||||
-D TFT_HEIGHT=480
|
||||
;-D TFT_MISO=-1
|
||||
;-D TFT_MOSI=13
|
||||
;-D TFT_SCLK=12
|
||||
;-D TFT_CS=10
|
||||
;-D TFT_DC=11
|
||||
;-D TFT_RST=1
|
||||
;-D TFT_RGB_ORDER=TFT_BGR
|
||||
-D USE_HSPI_PORT
|
||||
-D LOAD_FONT2
|
||||
-D MD5_ENABLED=1
|
||||
-D SERIAL_FLASHER_INTERFACE_UART=1
|
||||
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
|
||||
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
|
||||
;-D C6_OTA_FLASHING
|
||||
;-D HAS_SUBGHZ
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_qspi ;Enable external PSRAM
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 16777216
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 16MB
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an ESP32-S3 16MB Flash 8MB RAM
|
||||
; ----------------------------------------------------------------------------------------
|
||||
|
||||
@@ -19,7 +19,191 @@ uint8_t YellowSense = 0;
|
||||
bool tftLogscreen = true;
|
||||
bool tftOverride = false;
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
|
||||
|
||||
static const uint8_t st7701_type9_init_operations_lilygo[] = {
|
||||
|
||||
BEGIN_WRITE,
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x13,
|
||||
|
||||
WRITE_C8_D8, 0xEF, 0x08,
|
||||
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x10,
|
||||
|
||||
WRITE_C8_D16, 0xC0, 0x3B, 0x00,
|
||||
WRITE_C8_D16, 0xC1, 0x0B, 0x02,
|
||||
|
||||
WRITE_COMMAND_8, 0xC2,
|
||||
WRITE_BYTES, 3, 0x30, 0x02, 0x37,
|
||||
|
||||
WRITE_C8_D8, 0xCC, 0x10,
|
||||
|
||||
WRITE_COMMAND_8, 0xB0, // Positive Voltage Gamma Control
|
||||
WRITE_BYTES, 16,
|
||||
0x00, 0x0F, 0x16, 0x0E,
|
||||
0x11, 0x07, 0x09, 0x09,
|
||||
0x08, 0x23, 0x05, 0x11,
|
||||
0x0F, 0x28, 0x2D, 0x18,
|
||||
|
||||
WRITE_COMMAND_8, 0xB1, // Negative Voltage Gamma Control
|
||||
WRITE_BYTES, 16,
|
||||
0x00, 0x0F, 0x16, 0x0E,
|
||||
0x11, 0x07, 0x09, 0x08,
|
||||
0x09, 0x23, 0x05, 0x11,
|
||||
0x0F, 0x28, 0x2D, 0x18,
|
||||
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x11,
|
||||
|
||||
WRITE_C8_D8, 0xB0, 0x4D,
|
||||
WRITE_C8_D8, 0xB1, 0x33,
|
||||
WRITE_C8_D8, 0xB2, 0x87,
|
||||
WRITE_C8_D8, 0xB5, 0x4B,
|
||||
WRITE_C8_D8, 0xB7, 0x8C,
|
||||
WRITE_C8_D8, 0xB8, 0x20,
|
||||
WRITE_C8_D8, 0xC1, 0x78,
|
||||
WRITE_C8_D8, 0xC2, 0x78,
|
||||
WRITE_C8_D8, 0xD0, 0x88,
|
||||
|
||||
WRITE_COMMAND_8, 0xE0,
|
||||
WRITE_BYTES, 3, 0x00, 0x00, 0x02,
|
||||
|
||||
WRITE_COMMAND_8, 0xE1,
|
||||
WRITE_BYTES, 11,
|
||||
0x02, 0xF0, 0x00, 0x00,
|
||||
0x03, 0xF0, 0x00, 0x00,
|
||||
0x00, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE2,
|
||||
WRITE_BYTES, 12,
|
||||
0x10, 0x10, 0x40, 0x40,
|
||||
0xF2, 0xF0, 0x00, 0x00,
|
||||
0xF2, 0xF0, 0x00, 0x00,
|
||||
|
||||
WRITE_COMMAND_8, 0xE3,
|
||||
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
|
||||
|
||||
WRITE_C8_D16, 0xE4, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE5,
|
||||
WRITE_BYTES, 16,
|
||||
0x07, 0xEF, 0xF0, 0xF0,
|
||||
0x09, 0xF1, 0xF0, 0xF0,
|
||||
0x03, 0xF3, 0xF0, 0xF0,
|
||||
0x05, 0xED, 0xF0, 0xF0,
|
||||
|
||||
WRITE_COMMAND_8, 0xE6,
|
||||
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
|
||||
|
||||
WRITE_C8_D16, 0xE7, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE8,
|
||||
WRITE_BYTES, 16,
|
||||
0x08, 0xF0, 0xF0, 0xF0,
|
||||
0x0A, 0xF2, 0xF0, 0xF0,
|
||||
0x04, 0xF4, 0xF0, 0xF0,
|
||||
0x06, 0xEE, 0xF0, 0xF0,
|
||||
|
||||
WRITE_COMMAND_8, 0xEB,
|
||||
WRITE_BYTES, 7,
|
||||
0x00, 0x00, 0xE4, 0xE4,
|
||||
0x44, 0x88, 0x40,
|
||||
|
||||
WRITE_C8_D16, 0xEC, 0x78, 0x00,
|
||||
|
||||
WRITE_COMMAND_8, 0xED,
|
||||
WRITE_BYTES, 16,
|
||||
0x20, 0xF9, 0x87, 0x76,
|
||||
0x65, 0x54, 0x4F, 0xFF,
|
||||
0xFF, 0xF4, 0x45, 0x56,
|
||||
0x67, 0x78, 0x9F, 0x02,
|
||||
|
||||
WRITE_COMMAND_8, 0xEF,
|
||||
WRITE_BYTES, 6,
|
||||
0x10, 0x0D, 0x04, 0x08,
|
||||
0x3F, 0x1F,
|
||||
|
||||
// WRITE_C8_D8, 0xCD, 0x05,//Test
|
||||
|
||||
WRITE_C8_D8, 0x3A, 0x55,
|
||||
|
||||
WRITE_C8_D8, 0x36, 0x08,
|
||||
|
||||
WRITE_COMMAND_8, 0x11,
|
||||
|
||||
// WRITE_COMMAND_8, 0xFF,//Test
|
||||
// WRITE_BYTES, 5,
|
||||
// 0x77, 0x01, 0x00, 0x00,
|
||||
// 0x12,
|
||||
|
||||
// WRITE_C8_D8, 0xD1, 0x81,//Test
|
||||
// WRITE_C8_D8, 0xD2, 0x08,//Test
|
||||
|
||||
WRITE_COMMAND_8, 0x29, // Display On
|
||||
|
||||
// WRITE_C8_D8, 0x35, 0x00,//Test
|
||||
// WRITE_C8_D8, 0xCE, 0x04,//Test
|
||||
|
||||
// WRITE_COMMAND_8, 0xF2,//Test
|
||||
// WRITE_BYTES, 4,
|
||||
// 0xF0, 0xA3, 0xA3, 0x71,
|
||||
|
||||
END_WRITE};
|
||||
|
||||
Arduino_DataBus *bus = new Arduino_XL9535SWSPI(IIC_SDA /* SDA */, IIC_SCL /* SCL */, -1 /* XL PWD */,
|
||||
XL95X5_CS /* XL CS */, XL95X5_SCLK /* XL SCK */, XL95X5_MOSI /* XL MOSI */);
|
||||
Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel(
|
||||
-1 /* DE */, LCD_VSYNC /* VSYNC */, LCD_HSYNC /* HSYNC */, LCD_PCLK /* PCLK */,
|
||||
LCD_B0 /* B0 */, LCD_B1 /* B1 */, LCD_B2 /* B2 */, LCD_B3 /* B3 */, LCD_B4 /* B4 */,
|
||||
LCD_G0 /* G0 */, LCD_G1 /* G1 */, LCD_G2 /* G2 */, LCD_G3 /* G3 */, LCD_G4 /* G4 */, LCD_G5 /* G5 */,
|
||||
LCD_R0 /* R0 */, LCD_R1 /* R1 */, LCD_R2 /* R2 */, LCD_R3 /* R3 */, LCD_R4 /* R4 */,
|
||||
1 /* hsync_polarity */, 20 /* hsync_front_porch */, 2 /* hsync_pulse_width */, 0 /* hsync_back_porch */,
|
||||
1 /* vsync_polarity */, 30 /* vsync_front_porch */, 8 /* vsync_pulse_width */, 1 /* vsync_back_porch */,
|
||||
10 /* pclk_active_neg */, 6000000L /* prefer_speed */, false /* useBigEndian */,
|
||||
0 /* de_idle_high*/, 0 /* pclk_idle_high */);
|
||||
Arduino_RGB_Display *gfx = new Arduino_RGB_Display(
|
||||
LCD_WIDTH /* width */, LCD_HEIGHT /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
|
||||
bus, -1 /* RST */, st7701_type9_init_operations_lilygo, sizeof(st7701_type9_init_operations_lilygo));
|
||||
|
||||
#endif
|
||||
|
||||
void TFTLog(String text) {
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
|
||||
gfx->setTextSize(2);
|
||||
|
||||
if (tftLogscreen == false) {
|
||||
gfx->fillScreen(BLACK);
|
||||
gfx->setCursor(0, 0);
|
||||
tftLogscreen = true;
|
||||
}
|
||||
if (text.isEmpty()) return;
|
||||
gfx->setTextColor(LIGHTGREY);
|
||||
if (text.startsWith("!")) {
|
||||
gfx->setTextColor(RED);
|
||||
text = text.substring(1);
|
||||
} else if (text.indexOf("http") != -1) {
|
||||
int httpIndex = text.indexOf("http");
|
||||
gfx->print(text.substring(0, httpIndex));
|
||||
gfx->setTextColor(YELLOW);
|
||||
text = text.substring(httpIndex);
|
||||
} else if (text.indexOf(":") != -1) {
|
||||
int colonIndex = text.indexOf(":");
|
||||
gfx->setTextColor(LIGHTGREY);
|
||||
gfx->print(text.substring(0, colonIndex + 1));
|
||||
gfx->setTextColor(WHITE);
|
||||
text = text.substring(colonIndex + 1);
|
||||
} else if (text.endsWith("!")) {
|
||||
gfx->setTextColor(GREEN);
|
||||
}
|
||||
gfx->println(text);
|
||||
|
||||
#else
|
||||
|
||||
if (tftLogscreen == false) {
|
||||
tft2.fillScreen(TFT_BLACK);
|
||||
tft2.setCursor(0, 0, (tft2.width() == 160 ? 1 : 2));
|
||||
@@ -53,6 +237,7 @@ void TFTLog(String text) {
|
||||
tft2.setTextColor(TFT_GREEN);
|
||||
}
|
||||
tft2.println(text);
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t findId(uint8_t mac[8]) {
|
||||
@@ -72,7 +257,11 @@ void sendAvail(uint8_t wakeupReason) {
|
||||
memcpy(&eadr.src, mac, 6);
|
||||
eadr.adr.lastPacketRSSI = WiFi.RSSI();
|
||||
eadr.adr.currentChannel = config.channel;
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
eadr.adr.hwType = 0xE2;
|
||||
#else
|
||||
eadr.adr.hwType = (tft2.width() == 160 ? 0xE1 : 0xE0);
|
||||
#endif
|
||||
eadr.adr.wakeupReason = wakeupReason;
|
||||
eadr.adr.capabilities = 0;
|
||||
eadr.adr.tagSoftwareVersion = 0;
|
||||
@@ -81,6 +270,20 @@ void sendAvail(uint8_t wakeupReason) {
|
||||
}
|
||||
|
||||
void yellow_ap_display_init(void) {
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
|
||||
tftLogscreen = true;
|
||||
|
||||
pinMode(LCD_BL, OUTPUT);
|
||||
digitalWrite(LCD_BL, HIGH);
|
||||
|
||||
Wire.begin(IIC_SDA, IIC_SCL);
|
||||
|
||||
gfx->begin();
|
||||
gfx->fillScreen(BLACK);
|
||||
|
||||
#else
|
||||
pinMode(YELLOW_SENSE, INPUT_PULLDOWN);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
if (digitalRead(YELLOW_SENSE) == HIGH) YellowSense = 1;
|
||||
@@ -105,6 +308,7 @@ void yellow_ap_display_init(void) {
|
||||
GPIO.func_out_sel_cfg[TFT_BACKLIGHT].inv_sel = 1;
|
||||
}
|
||||
ledcWrite(6, config.tft);
|
||||
#endif
|
||||
}
|
||||
|
||||
void yellow_ap_display_loop(void) {
|
||||
@@ -146,7 +350,28 @@ void yellow_ap_display_loop(void) {
|
||||
void* spriteData = spr.getPointer();
|
||||
size_t bytesRead = file.readBytes((char*)spriteData, spr.width() * spr.height() * 2);
|
||||
file.close();
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
long dy = spr.height();
|
||||
long dx = spr.width();
|
||||
|
||||
uint16_t* data = static_cast<uint16_t*>(const_cast<void*>(spriteData));
|
||||
|
||||
for (int16_t j = 0; j < dy; j++)
|
||||
{
|
||||
for (int16_t i = 0; i < dx; i++)
|
||||
{
|
||||
uint16_t color = *data;
|
||||
color = color<<8 | color>>8;
|
||||
*data = color;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
gfx->draw16bitRGBBitmap(0, 0, (uint16_t *)spriteData, dx, dy);
|
||||
#else
|
||||
spr.pushSprite(0, 0);
|
||||
#endif
|
||||
|
||||
tftLogscreen = false;
|
||||
|
||||
struct espXferComplete xfc = {0};
|
||||
|
||||
@@ -80,6 +80,7 @@ uint32_t colorDistance(Color &c1, Color &c2, Error &e1) {
|
||||
}
|
||||
|
||||
void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t buffer_size, bool is_red) {
|
||||
|
||||
uint8_t rotate = imageParams.rotate;
|
||||
long bufw = spr.width(), bufh = spr.height();
|
||||
|
||||
@@ -286,7 +287,29 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
size_t dataSize = spr.width() * spr.height() * (spr.getColorDepth() / 8);
|
||||
memcpy(spriteData2, spriteData, dataSize);
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
if (spr.getColorDepth() == 16)
|
||||
{
|
||||
long dy = spr.height();
|
||||
long dx = spr.width();
|
||||
|
||||
uint16_t* data = static_cast<uint16_t*>(const_cast<void*>(spriteData2));
|
||||
|
||||
for (int16_t j = 0; j < dy; j++)
|
||||
{
|
||||
for (int16_t i = 0; i < dx; i++)
|
||||
{
|
||||
uint16_t color = *data;
|
||||
color = color<<8 | color>>8;
|
||||
*data = color;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
gfx->draw16bitRGBBitmap(0, 0, (uint16_t *)spriteData2, dx, dy);
|
||||
}
|
||||
#else
|
||||
spr2.pushSprite(0, 0);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
64
resources/tagtypes/E2.json
Normal file
64
resources/tagtypes/E2.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"version": 1,
|
||||
"name": "LILYGO TPANEL 4\"",
|
||||
"width": 480,
|
||||
"height": 480,
|
||||
"rotatebuffer": 0,
|
||||
"bpp": 16,
|
||||
"colortable": {
|
||||
"white": [ 255, 255, 255 ],
|
||||
"black": [ 0, 0, 0 ],
|
||||
"red": [ 255, 0, 0 ]
|
||||
},
|
||||
"shortlut": 0,
|
||||
"options": [ ],
|
||||
"contentids": [ 22, 1, 2, 3, 4, 8, 7, 19, 10, 11, 21 ],
|
||||
"template": {
|
||||
"21": [
|
||||
{ "box": [ 0, 0, 480, 480, 1 ] },
|
||||
{ "text": [ 10, 15, "OpenEpaperLink AP", "calibrib30", 2, 0, 0, 1 ] },
|
||||
{ "text": [ 10, 70, "IP address:", "bahnschrift30", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 180, 70, "{ap_ip}", "bahnschrift30", 0, 0, 0, 1 ] },
|
||||
{ "text": [ 10, 110, "Channel:", "bahnschrift30", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 180, 110, "{ap_ch}", "bahnschrift30", 0, 0, 0, "1" ] },
|
||||
{ "text": [ 10, 150, "Tag count:", "bahnschrift30", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 180, 150, "{ap_tagcount}", "bahnschrift30", 0, 0, 0, "1" ] }
|
||||
],
|
||||
"1": {
|
||||
"weekday": [ 240, 30, "Signika-SB.ttf", 90 ],
|
||||
"month": [ 240, 330, "Signika-SB.ttf", 90 ],
|
||||
"day": [ 240, 80, "Signika-SB.ttf", 250 ]
|
||||
},
|
||||
"4": {
|
||||
"location": [ 20, 20, "fonts/calibrib30" ],
|
||||
"wind": [ 90, 95, "fonts/calibrib50" ],
|
||||
"temp": [ 20, 200, "fonts/calibrib100" ],
|
||||
"icon": [ 400, 30, 150, 2 ],
|
||||
"dir": [ 40, 70, 80 ],
|
||||
"umbrella": [ 325, 250, 150 ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": [ "Signika-SB.ttf", 150, 150, 110, 80, 60, 50 ],
|
||||
"xy": [ 240, 240 ]
|
||||
},
|
||||
"8": {
|
||||
"location": [ 10, 20, "fonts/calibrib50" ],
|
||||
"column": [ 6, 80 ],
|
||||
"day": [ 40, 100, "fonts/bahnschrift30", 144, 270 ],
|
||||
"rain": [ 40, 320 ],
|
||||
"icon": [ 40, 180, 50 ],
|
||||
"wind": [ 17, 120 ],
|
||||
"line": [ 100, 340 ]
|
||||
},
|
||||
"10": {
|
||||
"title": [ 240, 10, "fonts/bahnschrift20" ],
|
||||
"pos": [ 240, 35 ]
|
||||
},
|
||||
"11": {
|
||||
"rotate": 0,
|
||||
"mode": 1,
|
||||
"days": 4,
|
||||
"gridparam": [ 5, 17, 20, "calibrib16.vlw", "tahoma9.vlw", 14 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user