Merge remote-tracking branch 'origin/master' into httpd

Conflicts:
	components/services/monitor.c
	components/telnet/telnet.c
	components/telnet/telnet.h
This commit is contained in:
Sebastien
2020-02-12 18:03:22 -05:00
81 changed files with 2376 additions and 7661 deletions

View File

@@ -18,9 +18,9 @@ GND - GND
FLT - GND FLT - GND
DMP - GND DMP - GND
SCL - GND SCL - GND
BCK - (see below) BCK - (BCK - see below)
DIN - (see below) DIN - (DO - see below)
LCK - (see below) LCK - (WS - see below)
FMT - GND FMT - GND
XMT - 3.3V XMT - 3.3V
@@ -30,32 +30,41 @@ Use the `squeezelite-esp32-I2S-4MFlash-sdkconfig.defaults` configuration file.
To access NVS, in the webUI, go to credits and select "shows nvs editor". Go into the NVS editor tab to change NFS parameters. In syntax description below \<\> means a value while \[\] describe optional parameters. To access NVS, in the webUI, go to credits and select "shows nvs editor". Go into the NVS editor tab to change NFS parameters. In syntax description below \<\> means a value while \[\] describe optional parameters.
### I2C ### I2C
The NVS parameter "i2c_config" set the i2c's gpio used for generic purpose (e.g. display). Leave it blank to disable I2C usage. Note that on SqueezeAMP, port must be 1. Syntax is The NVS parameter "i2c_config" set the i2c's gpio used for generic purpose (e.g. display). Leave it blank to disable I2C usage. Note that on SqueezeAMP, port must be 1. Default speed is 400000. Syntax is
``` ```
bck=<gpio>,ws=<gpio>,do=<gpio> sda=<gpio>,scl=<gpio>[,port=0|1][,speed=<speed>]
```
### SPI
The NVS parameter "spi_config" set the spi's gpio used for generic purpose (e.g. display). Leave it blank to disable SPI usage. The DC parameter is needed for displays. Syntax is
```
data=<gpio>,clk=<gpio>[,dc=<gpio>][,host=1|2]
``` ```
### DAC/I2S ### DAC/I2S
The NVS parameter "dac_config" set the gpio used for i2s communication with your DAC. You can also define these at compile time but nvs parameter takes precedence. Note that on SqueezeAMP and A1S, these are forced at runtime, so this parameter does not matter. If your DAC also requires i2c, then you must go the re-compile route. Syntax is The NVS parameter "dac_config" set the gpio used for i2s communication with your DAC. You can define the defaults at compile time but nvs parameter takes precedence except for SqueezeAMP and A1S where these are forced at runtime. If your DAC also requires i2c, then you must go the re-compile route. Syntax is
``` ```
sda=<gpio>,scl=<gpio>,port=0|1 bck=<gpio>,ws=<gpio>,do=<gpio>
``` ```
### SPDIF ### SPDIF
The NVS parameter "spdif_config" sets the i2s's gpio needed for SPDIF. The NVS parameter "spdif_config" sets the i2s's gpio needed for SPDIF.
SPDIF is made available by re-using i2s interface in a non-standard way, so although only one pin (DO) is needed, the controller must be fully initialized, so the bit clock (bck) and word clock (ws) must be set as well. As i2s and SPDIF are mutually exclusive, you can reuse the same IO if your hardware allows so. SPDIF is made available by re-using i2s interface in a non-standard way, so although only one pin (DO) is needed, the controller must be fully initialized, so the bit clock (bck) and word clock (ws) must be set as well. As i2s and SPDIF are mutually exclusive, you can reuse the same IO if your hardware allows so.
Note that on SqueezeAMP, these are automatically defined, so this parameter does not matter. You can define the defaults at compile time but nvs parameter takes precedence except for SqueezeAMP where these are forced at runtime.
Leave it blank to disable SPDIF usage, you can also define them at compile time using "make menuconfig". Syntax is Leave it blank to disable SPDIF usage, you can also define them at compile time using "make menuconfig". Syntax is
``` ```
bck=<gpio>,ws=<gpio>,do=<gpio> bck=<gpio>,ws=<gpio>,do=<gpio>
``` ```
## Display ### Display
The NVS parameter "display_config" sets the parameters for an optional display. Syntax is The NVS parameter "display_config" sets the parameters for an optional display. Syntax is
``` ```
I2C|SPI,width=<pixels>,height=<pixels>[,address=<i2c_address>][,HFlip][,VFlip] I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,HFlip][,VFlip][driver=SSD1306|SSD1326|SH1106]
SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,speed=<speed>][,HFlip][,VFlip][driver=SSD1306|SSD1326|SH1106]
``` ```
- VFlip and HFlip are optional can be used to change display orientation - VFlip and HFlip are optional can be used to change display orientation
- Default speed is 8000000 (8MHz)
Currently 128x32/64 I2C display like [this](https://www.buydisplay.com/i2c-blue-0-91-inch-oled-display-module-128x32-arduino-raspberry-pi) and [this](https://www.waveshare.com/wiki/1.3inch_OLED_HAT) are supported
The NVS parameter "metadata_config" sets how metadata is displayed for AirPlay and Bluetooth. Syntax is The NVS parameter "metadata_config" sets how metadata is displayed for AirPlay and Bluetooth. Syntax is
``` ```
@@ -65,22 +74,23 @@ The NVS parameter "metadata_config" sets how metadata is displayed for AirPlay a
- 'format' can contain free text and any of the 3 keywords %artist%, %album%, %title%. Using that format string, the keywords are replaced by their value to build the string to be displayed. Note that the plain text following a keyword that happens to be empty during playback of a track will be removed. For example, if you have set format=%artist% - %title% and there is no artist in the metadata then only <title> will be displayed not " - <title>". - 'format' can contain free text and any of the 3 keywords %artist%, %album%, %title%. Using that format string, the keywords are replaced by their value to build the string to be displayed. Note that the plain text following a keyword that happens to be empty during playback of a track will be removed. For example, if you have set format=%artist% - %title% and there is no artist in the metadata then only <title> will be displayed not " - <title>".
Currently only 128x32 I2C display like [this](https://www.buydisplay.com/i2c-blue-0-91-inch-oled-display-module-128x32-arduino-raspberry-pi) are supported
### Set GPIO ### Set GPIO
The parameter "set_GPIO" is use to set assign GPIO to various functions. The parameter "set_GPIO" is use to assign GPIO to various functions.
GPIO can be set to GND provide or Vcc at boot. This is convenient to power devices that consume less than 40mA from the side connector. Be careful because there is no conflict checks being made wrt which GPIO you're changing, so you might damage your board or create a conflict here. GPIO can be set to GND provide or Vcc at boot. This is convenient to power devices that consume less than 40mA from the side connector. Be careful because there is no conflict checks being made wrt which GPIO you're changing, so you might damage your board or create a conflict here.
This parameter can use used as well to assign a GPIO that will be set to 1 when playback starts and wil be reset to 0 when squeezelite becomes idle. The idle timeout is set on the squeezelite command line through -C \<timeout\> The \<amp\> parameter can use used to assign a GPIO that will be set to 1 when playback starts. It will be reset to 0 when squeezelite becomes idle. The idle timeout is set on the squeezelite command line through -C \<timeout\>
Finally, if you have an audio jack that supports insertion (set to GND when inserted), you can specify whch GPIO it's connected to. Using the parameter jack_mutes_amp allows to mute the amp when headset (e.g.) is inserted. If you have an audio jack that supports insertion (use :0 or :1 to set the level when inserted), you can specify which GPIO it's connected to. Using the parameter jack_mutes_amp allows to mute the amp when headset (e.g.) is inserted.
You can set the Green and Red status led as well with their respective active state (:0 or :1)
Syntax is: Syntax is:
``` ```
<gpio_1>=Vcc|GND|amp|jack[,<gpio_n>=Vcc|GND|amp|jack] <gpio>=Vcc|GND|amp|jack[:0|1]|green[:0|1]|red[:0|1]|spkfault[:0|1][,<repeated sequence for next GPIO>]
``` ```
You can define the defaults for jack, spkfault leds at compile time but nvs parameter takes precedence except for SqueezeAMP where these are forced at runtime.
### Rotary Encoder ### Rotary Encoder
One rotary encoder is supported, quadrature shift with press. Such encoders usually have 2 pins for encoders (A and B), and common C that must be set to ground and an optional SW pin for press. A, B and SW must be pulled up, so automatic pull-up is provided by ESP32, but you can add your own resistors. A bit of filtering on A and B (~470nF) helps for debouncing which is not made by software. One rotary encoder is supported, quadrature shift with press. Such encoders usually have 2 pins for encoders (A and B), and common C that must be set to ground and an optional SW pin for press. A, B and SW must be pulled up, so automatic pull-up is provided by ESP32, but you can add your own resistors. A bit of filtering on A and B (~470nF) helps for debouncing which is not made by software.
@@ -175,6 +185,12 @@ Below is a difficult but functional 2-buttons interface for your decoding pleasu
"longshifted":{"pressed":"BCTRLS_LEFT"}} "longshifted":{"pressed":"BCTRLS_LEFT"}}
] ]
``` ```
### Battery / ADC
The NVS parameter "bat_config" sets the ADC1 channel used to measure battery/DC voltage. Scale is a float ratio applied to every sample of the 12 bits ADC. A measure is taken every 10s and an average is made every 5 minutes (not a sliding window). Syntax is
```
channel=0..7,scale=<scale>
```
NB: Set parameter to empty to disable battery reading
## Setting up ESP-IDF ## Setting up ESP-IDF
### Docker ### Docker
You can use docker to build squeezelite-esp32 You can use docker to build squeezelite-esp32

View File

@@ -1,147 +0,0 @@
CONFIG_ESPTOOLPY_BAUD_2MB=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHFREQ="80m"
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_ESPTOOLPY_FLASHSIZE="16MB"
CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_WIFI_FAST_SCAN=y
CONFIG_WIFI_CONNECT_AP_BY_SIGNAL=y
CONFIG_FAST_SCAN_THRESHOLD=y
CONFIG_FAST_SCAN_MINIMUM_SIGNAL=-127
CONFIG_EXAMPLE_OPEN=y
CONFIG_INCLUDE_FLAC=y
CONFIG_INCLUDE_FAAD=y
CONFIG_INCLUDE_MAD=y
CONFIG_INCLUDE_VORBIS=y
CONFIG_INCLUDE_ALAC=y
CONFIG_OTA_ALLOW_HTTP=y
CONFIG_WL_SECTOR_SIZE_512=y
#CONFIG_WL_SECTOR_SIZE_4096 is not defined
CONFIG_WL_SECTOR_SIZE=512
CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16
CONFIG_BTAUDIO=y
CONFIG_OUTPUT_NAME=""
CONFIG_OUTPUT_RATES="44100"
CONFIG_I2S_NUM=0
CONFIG_I2S_BCK_IO=26
CONFIG_I2S_WS_IO=25
CONFIG_I2S_DO_IO=22
CONFIG_I2S_BITS_PER_CHANNEL_16=y
CONFIG_I2S_BITS_PER_CHANNEL=16
CONFIG_A2DP_DEV_NAME="Squeezelite"
CONFIG_A2DP_CONTROL_DELAY_MS=500
CONFIG_A2DP_CONNECT_TIMEOUT_MS=1000
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000
CONFIG_PARTITION_TABLE_MD5=y
CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y
CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN=2
CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN=0
CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_PCM=y
CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=1
CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=0
CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=2
CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0
CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y
CONFIG_BTDM_CTRL_PINNED_TO_CORE=0
CONFIG_BTDM_CTRL_HCI_MODE_VHCI=y
CONFIG_BTDM_MODEM_SLEEP=y
CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG=y
CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL=y
CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1
CONFIG_BT_BLUEDROID_ENABLED=y
CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y
CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0
CONFIG_BT_BTC_TASK_STACK_SIZE=3072
CONFIG_BT_BTU_TASK_STACK_SIZE=4096
CONFIG_BT_CLASSIC_ENABLED=y
CONFIG_BT_A2DP_ENABLE=y
CONFIG_BT_A2DP_SINK_TASK_STACK_SIZE=2048
CONFIG_BT_A2DP_SOURCE_TASK_STACK_SIZE=2048
CONFIG_BT_SSP_ENABLED=y
CONFIG_BT_ACL_CONNECTIONS=4
CONFIG_BT_SMP_ENABLE=y
CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30
CONFIG_BT_RESERVE_DRAM=0xdb5c
CONFIG_SPI_MASTER_ISR_IN_IRAM=y
CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
CONFIG_ESP32_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_TYPE_AUTO=y
CONFIG_SPIRAM_SIZE=-1
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_CACHE_WORKAROUND=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=256
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65536
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_OCCUPY_VSPI_HOST=y
CONFIG_SPIRAM_BANKSWITCH_ENABLE=n
CONFIG_D0WD_PSRAM_CLK_IO=17
CONFIG_D0WD_PSRAM_CS_IO=16
CONFIG_D2WD_PSRAM_CLK_IO=9
CONFIG_D2WD_PSRAM_CS_IO=10
CONFIG_PICO_PSRAM_CS_IO=10
CONFIG_ESP32_PANIC_PRINT_REBOOT=y
CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP32_XTAL_FREQ_40=y
CONFIG_ESP32_XTAL_FREQ=40
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y
CONFIG_ESP32_WIFI_SW_COEXIST_PREFERENCE_BALANCE=y
CONFIG_ESP32_WIFI_SW_COEXIST_PREFERENCE_VALUE=2
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=12
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=40
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=12
CONFIG_ESP32_WIFI_NVS_ENABLED=y
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752
CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32
CONFIG_ESP32_WIFI_IRAM_OPT=y
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=n
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=n
CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y
CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
CONFIG_ESP32_PHY_MAX_TX_POWER=20
CONFIG_FREERTOS_HZ=100
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32
CONFIG_LWIP_MAX_SOCKETS=16
CONFIG_LWIP_NETIF_LOOPBACK=y
CONFIG_LWIP_TCP_MSL=60000
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=8192
CONFIG_LWIP_TCP_WND_DEFAULT=32768
CONFIG_LWIP_TCP_RECVMBOX_SIZE=32
CONFIG_LWIP_MAX_RAW_PCBS=16
CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
CONFIG_ESP32_PTHREAD_STACK_MIN=768
CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1=y
CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=1
CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread"
CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# wifi-manager
CONFIG_DEFAULT_AP_SSID="squeezelite"
CONFIG_DEFAULT_AP_PASSWORD="squeezelite"
CONFIG_DEFAULT_AP_IP="192.168.4.1"
CONFIG_DEFAULT_AP_GATEWAY="192.168.4.1"
CONFIG_DEFAULT_AP_NETMASK="255.255.255.0"
CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30"

View File

@@ -2,6 +2,34 @@
# Automatically generated file. DO NOT EDIT. # Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) Project Configuration # Espressif IoT Development Framework (ESP-IDF) Project Configuration
# #
# ESP32-A1S defaults (with AC101 codec)
CONFIG_I2S_NUM=0
CONFIG_I2C_LOCKED=y
CONFIG_DISPLAY_CONFIG=""
CONFIG_I2C_CONFIG=""
CONFIG_SPI_CONFIG=""
CONFIG_SET_GPIO=""
CONFIG_ROTARY_ENCODER=""
CONFIG_LED_GREEN_GPIO=-1
CONFIG_LED_GREEN_GPIO_LEVEL=1
CONFIG_LED_RED_GPIO=-1
CONFIG_LED_RED_GPIO_LEVEL=1
CONFIG_JACK_GPIO=-1
CONFIG_JACK_GPIO_LEVEL=0
CONFIG_SPKFAULT_GPIO=-1
CONFIG_SPKFAULT_GPIO_LEVEL=0
CONFIG_BAT_CHANNEL=-1
CONFIG_BAT_SCALE="0"
CONFIG_I2S_BCK_IO=27
CONFIG_I2S_WS_IO=26
CONFIG_I2S_DO_IO=25
CONFIG_I2S_DI_IO=35
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=27
CONFIG_SPDIF_WS_IO=26
CONFIG_SPDIF_DO_IO=-1
CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_TARGET_ESP32=y
CONFIG_IDF_TARGET="esp32" CONFIG_IDF_TARGET="esp32"
@@ -29,10 +57,12 @@ CONFIG_BOOTLOADER_WDT_ENABLE=y
CONFIG_BOOTLOADER_WDT_TIME_MS=9000 CONFIG_BOOTLOADER_WDT_TIME_MS=9000
CONFIG_ESPTOOLPY_BAUD_2MB=y
CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
CONFIG_ESPTOOLPY_BAUD=2000000
CONFIG_ESPTOOLPY_COMPRESSED=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHMODE_QIO=y

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,32 @@
# Automatically generated file. DO NOT EDIT. # Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) Project Configuration # Espressif IoT Development Framework (ESP-IDF) Project Configuration
# #
CONFIG_DISPLAY_CONFIG=""
CONFIG_I2C_CONFIG=""
CONFIG_SPI_CONFIG=""
CONFIG_SET_GPIO=""
CONFIG_ROTARY_ENCODER=""
CONFIG_LED_GREEN_GPIO=-1
CONFIG_LED_GREEN_GPIO_LEVEL=1
CONFIG_LED_RED_GPIO=-1
CONFIG_LED_RED_GPIO_LEVEL=1
CONFIG_JACK_GPIO=-1
CONFIG_JACK_GPIO_LEVEL=0
CONFIG_SPKFAULT_GPIO=-1
CONFIG_SPKFAULT_GPIO_LEVEL=0
CONFIG_BAT_CHANNEL=-1
CONFIG_BAT_SCALE="0"
CONFIG_I2S_NUM=0
CONFIG_I2S_BCK_IO=33
CONFIG_I2S_WS_IO=25
CONFIG_I2S_DO_IO=32
CONFIG_I2S_DI_IO=-1
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=33
CONFIG_SPDIF_WS_IO=25
CONFIG_SPDIF_DO_IO=-1
CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_TARGET_ESP32=y
CONFIG_IDF_TARGET="esp32" CONFIG_IDF_TARGET="esp32"
@@ -29,10 +55,12 @@ CONFIG_BOOTLOADER_WDT_ENABLE=y
CONFIG_BOOTLOADER_WDT_TIME_MS=9000 CONFIG_BOOTLOADER_WDT_TIME_MS=9000
CONFIG_ESPTOOLPY_BAUD_2MB=y
CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
CONFIG_ESPTOOLPY_BAUD=2000000
CONFIG_ESPTOOLPY_COMPRESSED=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
@@ -84,18 +112,12 @@ CONFIG_INCLUDE_ALAC=y
CONFIG_BASIC_I2C_BT=y CONFIG_BASIC_I2C_BT=y
CONFIG_I2S_NUM=0
CONFIG_I2S_BCK_IO=26
CONFIG_I2S_WS_IO=25
CONFIG_I2S_DO_IO=22
CONFIG_I2S_BITS_PER_CHANNEL_16=y
CONFIG_I2S_BITS_PER_CHANNEL=16
CONFIG_SDIF_NUM=0 CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=26 CONFIG_SPDIF_BCK_IO=-1
CONFIG_SPDIF_WS_IO=25 CONFIG_SPDIF_WS_IO=-1
CONFIG_SPDIF_DO_IO=15 CONFIG_SPDIF_DO_IO=-1
CONFIG_A2DP_SINK_NAME="SMSL BT4.2" CONFIG_A2DP_SINK_NAME="SMSL BT4.2"
CONFIG_A2DP_DEV_NAME="Squeezelite" CONFIG_A2DP_DEV_NAME="Squeezelite"
CONFIG_A2DP_CONTROL_DELAY_MS=500 CONFIG_A2DP_CONTROL_DELAY_MS=500

View File

@@ -1,143 +0,0 @@
CONFIG_ESPTOOLPY_BAUD_2MB=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHFREQ="80m"
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_ESPTOOLPY_FLASHSIZE="16MB"
CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_WIFI_FAST_SCAN=y
CONFIG_WIFI_CONNECT_AP_BY_SIGNAL=y
CONFIG_FAST_SCAN_THRESHOLD=y
CONFIG_FAST_SCAN_MINIMUM_SIGNAL=-127
CONFIG_EXAMPLE_OPEN=y
CONFIG_INCLUDE_FLAC=y
CONFIG_INCLUDE_FAAD=y
CONFIG_INCLUDE_MAD=y
CONFIG_INCLUDE_VORBIS=y
CONFIG_INCLUDE_ALAC=y
CONFIG_OTA_ALLOW_HTTP=y
CONFIG_BTAUDIO=y
CONFIG_OUTPUT_NAME=""
CONFIG_OUTPUT_RATES="44100"
CONFIG_I2S_NUM=0
CONFIG_I2S_BCK_IO=26
CONFIG_I2S_WS_IO=25
CONFIG_I2S_DO_IO=22
CONFIG_I2S_BITS_PER_CHANNEL_16=y
CONFIG_I2S_BITS_PER_CHANNEL=16
CONFIG_A2DP_DEV_NAME="Squeezelite"
CONFIG_A2DP_CONTROL_DELAY_MS=500
CONFIG_A2DP_CONNECT_TIMEOUT_MS=1000
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="non-ota-partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="non-ota-partitions.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000
CONFIG_PARTITION_TABLE_MD5=y
CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y
CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN=2
CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN=0
CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_PCM=y
CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=1
CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=0
CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=2
CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0
CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y
CONFIG_BTDM_CTRL_PINNED_TO_CORE=0
CONFIG_BTDM_CTRL_HCI_MODE_VHCI=y
CONFIG_BTDM_MODEM_SLEEP=y
CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG=y
CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL=y
CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1
CONFIG_BT_BLUEDROID_ENABLED=y
CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y
CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0
CONFIG_BT_BTC_TASK_STACK_SIZE=3072
CONFIG_BT_BTU_TASK_STACK_SIZE=4096
CONFIG_BT_CLASSIC_ENABLED=y
CONFIG_BT_A2DP_ENABLE=y
CONFIG_BT_A2DP_SINK_TASK_STACK_SIZE=2048
CONFIG_BT_A2DP_SOURCE_TASK_STACK_SIZE=2048
CONFIG_BT_SSP_ENABLED=y
CONFIG_BT_ACL_CONNECTIONS=4
CONFIG_BT_SMP_ENABLE=y
CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30
CONFIG_BT_RESERVE_DRAM=0xdb5c
CONFIG_SPI_MASTER_ISR_IN_IRAM=y
CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
CONFIG_ESP32_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_TYPE_AUTO=y
CONFIG_SPIRAM_SIZE=-1
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_CACHE_WORKAROUND=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=256
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65536
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_OCCUPY_VSPI_HOST=y
CONFIG_SPIRAM_BANKSWITCH_ENABLE=n
CONFIG_D0WD_PSRAM_CLK_IO=17
CONFIG_D0WD_PSRAM_CS_IO=16
CONFIG_D2WD_PSRAM_CLK_IO=9
CONFIG_D2WD_PSRAM_CS_IO=10
CONFIG_PICO_PSRAM_CS_IO=10
CONFIG_ESP32_PANIC_PRINT_REBOOT=y
CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP32_XTAL_FREQ_40=y
CONFIG_ESP32_XTAL_FREQ=40
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y
CONFIG_ESP32_WIFI_SW_COEXIST_PREFERENCE_BALANCE=y
CONFIG_ESP32_WIFI_SW_COEXIST_PREFERENCE_VALUE=2
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=12
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=40
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=12
CONFIG_ESP32_WIFI_NVS_ENABLED=y
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752
CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32
CONFIG_ESP32_WIFI_IRAM_OPT=y
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=n
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=n
CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y
CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
CONFIG_ESP32_PHY_MAX_TX_POWER=20
CONFIG_FREERTOS_HZ=100
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32
CONFIG_LWIP_MAX_SOCKETS=16
CONFIG_LWIP_NETIF_LOOPBACK=y
CONFIG_LWIP_TCP_MSL=60000
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=8192
CONFIG_LWIP_TCP_WND_DEFAULT=32768
CONFIG_LWIP_TCP_RECVMBOX_SIZE=32
CONFIG_LWIP_MAX_RAW_PCBS=16
CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
CONFIG_ESP32_PTHREAD_STACK_MIN=768
CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1=y
CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=1
CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread"
CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# wifi-manager
CONFIG_DEFAULT_AP_SSID="squeezelite"
CONFIG_DEFAULT_AP_PASSWORD="squeezelite"
CONFIG_DEFAULT_AP_IP="192.168.4.1"
CONFIG_DEFAULT_AP_GATEWAY="192.168.4.1"
CONFIG_DEFAULT_AP_NETMASK="255.255.255.0"
CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30"

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,32 @@
# Automatically generated file. DO NOT EDIT. # Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) Project Configuration # Espressif IoT Development Framework (ESP-IDF) Project Configuration
# #
CONFIG_DISPLAY_CONFIG=""
CONFIG_I2C_CONFIG=""
CONFIG_SPI_CONFIG=""
CONFIG_SET_GPIO=""
CONFIG_ROTARY_ENCODER=""
CONFIG_LED_GREEN_GPIO=-1
CONFIG_LED_GREEN_GPIO_LEVEL=1
CONFIG_LED_RED_GPIO=-1
CONFIG_LED_RED_GPIO_LEVEL=1
CONFIG_JACK_GPIO=-1
CONFIG_JACK_GPIO_LEVEL=0
CONFIG_SPKFAULT_GPIO=-1
CONFIG_SPKFAULT_GPIO_LEVEL=0
CONFIG_BAT_CHANNEL=-1
CONFIG_BAT_SCALE="0"
CONFIG_I2S_NUM=0
CONFIG_I2S_BCK_IO=33
CONFIG_I2S_WS_IO=25
CONFIG_I2S_DO_IO=32
CONFIG_I2S_DI_IO=-1
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=33
CONFIG_SPDIF_WS_IO=25
CONFIG_SPDIF_DO_IO=-1
CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_TARGET_ESP32=y
CONFIG_IDF_TARGET="esp32" CONFIG_IDF_TARGET="esp32"
@@ -29,10 +55,12 @@ CONFIG_BOOTLOADER_WDT_ENABLE=y
CONFIG_BOOTLOADER_WDT_TIME_MS=9000 CONFIG_BOOTLOADER_WDT_TIME_MS=9000
CONFIG_ESPTOOLPY_BAUD_2MB=y
CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
CONFIG_ESPTOOLPY_BAUD=2000000
CONFIG_ESPTOOLPY_COMPRESSED=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
@@ -84,18 +112,12 @@ CONFIG_INCLUDE_ALAC=y
CONFIG_BASIC_I2C_BT=y CONFIG_BASIC_I2C_BT=y
CONFIG_I2S_NUM=0
CONFIG_I2S_BCK_IO=26
CONFIG_I2S_WS_IO=25
CONFIG_I2S_DO_IO=22
CONFIG_I2S_BITS_PER_CHANNEL_16=y
CONFIG_I2S_BITS_PER_CHANNEL=16
CONFIG_SDIF_NUM=0 CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=26 CONFIG_SPDIF_BCK_IO=-1
CONFIG_SPDIF_WS_IO=25 CONFIG_SPDIF_WS_IO=-1
CONFIG_SPDIF_DO_IO=15 CONFIG_SPDIF_DO_IO=-1
CONFIG_A2DP_SINK_NAME="SMSL BT4.2" CONFIG_A2DP_SINK_NAME="SMSL BT4.2"
CONFIG_A2DP_DEV_NAME="Squeezelite" CONFIG_A2DP_DEV_NAME="Squeezelite"
CONFIG_A2DP_CONTROL_DELAY_MS=500 CONFIG_A2DP_CONTROL_DELAY_MS=500
@@ -387,6 +409,7 @@ CONFIG_SPIRAM_SIZE=-1
CONFIG_SPIRAM_SPEED_80M=y CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_MEMTEST=y CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_CACHE_WORKAROUND=y CONFIG_SPIRAM_CACHE_WORKAROUND=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=256 CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=256
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65536 CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65536
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
@@ -792,8 +815,9 @@ CONFIG_VFS_SUPPORT_TERMIOS=y
CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
CONFIG_WL_SECTOR_SIZE_4096=y CONFIG_WL_SECTOR_SIZE_512=y
CONFIG_WL_SECTOR_SIZE=4096 #CONFIG_WL_SECTOR_SIZE_4096 is not defined
CONFIG_WL_SECTOR_SIZE=512
CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16

View File

@@ -2,6 +2,38 @@
# Automatically generated file. DO NOT EDIT. # Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) Project Configuration # Espressif IoT Development Framework (ESP-IDF) Project Configuration
# #
# SqueezeAMP defaults
CONFIG_JACK_LOCKED=y
CONFIG_BAT_LOCKED=y
CONFIG_I2C_LOCKED=y
CONFIG_SPDIF_LOCKED=y
CONFIG_LED_LOCKED=y
CONFIG_DISPLAY_CONFIG=""
CONFIG_I2C_CONFIG=""
CONFIG_SPI_CONFIG=""
CONFIG_SET_GPIO=""
CONFIG_ROTARY_ENCODER=""
CONFIG_LED_GREEN_GPIO=12
CONFIG_LED_GREEN_GPIO_LEVEL=0
CONFIG_LED_RED_GPIO=13
CONFIG_LED_RED_GPIO_LEVEL=0
CONFIG_JACK_GPIO=34
CONFIG_JACK_GPIO_LEVEL=0
CONFIG_SPKFAULT_GPIO=2
CONFIG_SPKFAULT_GPIO_LEVEL=0
CONFIG_BAT_CHANNEL=7
CONFIG_BAT_SCALE="20.24"
CONFIG_I2S_NUM=0
CONFIG_I2S_BCK_IO=33
CONFIG_I2S_WS_IO=25
CONFIG_I2S_DO_IO=32
CONFIG_I2S_DI_IO=-1
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=33
CONFIG_SPDIF_WS_IO=25
CONFIG_SPDIF_DO_IO=15
CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_TARGET_ESP32=y
CONFIG_IDF_TARGET="esp32" CONFIG_IDF_TARGET="esp32"
@@ -29,10 +61,12 @@ CONFIG_BOOTLOADER_WDT_ENABLE=y
CONFIG_BOOTLOADER_WDT_TIME_MS=9000 CONFIG_BOOTLOADER_WDT_TIME_MS=9000
CONFIG_ESPTOOLPY_BAUD_2MB=y
CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
CONFIG_ESPTOOLPY_BAUD=2000000
CONFIG_ESPTOOLPY_COMPRESSED=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
@@ -781,8 +815,9 @@ CONFIG_VFS_SUPPORT_TERMIOS=y
CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
CONFIG_WL_SECTOR_SIZE_4096=y CONFIG_WL_SECTOR_SIZE_512=y
CONFIG_WL_SECTOR_SIZE=4096 #CONFIG_WL_SECTOR_SIZE_4096 is not defined
CONFIG_WL_SECTOR_SIZE=512
CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16

View File

@@ -2,6 +2,38 @@
# Automatically generated file. DO NOT EDIT. # Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) Project Configuration # Espressif IoT Development Framework (ESP-IDF) Project Configuration
# #
# SqueezeAMP defaults
CONFIG_JACK_LOCKED=y
CONFIG_BAT_LOCKED=y
CONFIG_I2C_LOCKED=y
CONFIG_SPDIF_LOCKED=y
CONFIG_LED_LOCKED=y
CONFIG_DISPLAY_CONFIG=""
CONFIG_I2C_CONFIG=""
CONFIG_SPI_CONFIG=""
CONFIG_SET_GPIO=""
CONFIG_ROTARY_ENCODER=""
CONFIG_LED_GREEN_GPIO=12
CONFIG_LED_GREEN_GPIO_LEVEL=0
CONFIG_LED_RED_GPIO=13
CONFIG_LED_RED_GPIO_LEVEL=0
CONFIG_JACK_GPIO=34
CONFIG_JACK_GPIO_LEVEL=0
CONFIG_SPKFAULT_GPIO=2
CONFIG_SPKFAULT_GPIO_LEVEL=0
CONFIG_BAT_CHANNEL=7
CONFIG_BAT_SCALE="20.24"
CONFIG_I2S_NUM=0
CONFIG_I2S_BCK_IO=33
CONFIG_I2S_WS_IO=25
CONFIG_I2S_DO_IO=32
CONFIG_I2S_DI_IO=-1
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=33
CONFIG_SPDIF_WS_IO=25
CONFIG_SPDIF_DO_IO=15
CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_TARGET_ESP32=y
CONFIG_IDF_TARGET="esp32" CONFIG_IDF_TARGET="esp32"
@@ -29,10 +61,12 @@ CONFIG_BOOTLOADER_WDT_ENABLE=y
CONFIG_BOOTLOADER_WDT_TIME_MS=9000 CONFIG_BOOTLOADER_WDT_TIME_MS=9000
CONFIG_ESPTOOLPY_BAUD_2MB=y
CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
CONFIG_ESPTOOLPY_BAUD=2000000
CONFIG_ESPTOOLPY_COMPRESSED=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHMODE_QIO=y

File diff suppressed because it is too large Load Diff

View File

@@ -1,141 +0,0 @@
CONFIG_ESPTOOLPY_BAUD_2MB=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHFREQ="80m"
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_ESPTOOLPY_FLASHSIZE="16MB"
CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_WIFI_FAST_SCAN=y
CONFIG_WIFI_CONNECT_AP_BY_SIGNAL=y
CONFIG_FAST_SCAN_THRESHOLD=y
CONFIG_FAST_SCAN_MINIMUM_SIGNAL=-127
CONFIG_EXAMPLE_OPEN=y
CONFIG_INCLUDE_FLAC=y
CONFIG_INCLUDE_FAAD=y
CONFIG_INCLUDE_MAD=y
CONFIG_INCLUDE_VORBIS=y
CONFIG_INCLUDE_ALAC=y
CONFIG_BTAUDIO=y
CONFIG_OUTPUT_NAME=""
CONFIG_OUTPUT_RATES="44100"
CONFIG_I2S_NUM=0
CONFIG_I2S_BCK_IO=26
CONFIG_I2S_WS_IO=25
CONFIG_I2S_DO_IO=22
CONFIG_I2S_BITS_PER_CHANNEL_16=y
CONFIG_I2S_BITS_PER_CHANNEL=16
CONFIG_A2DP_DEV_NAME="Squeezelite"
CONFIG_A2DP_CONTROL_DELAY_MS=500
CONFIG_A2DP_CONNECT_TIMEOUT_MS=1000
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000
CONFIG_PARTITION_TABLE_MD5=y
CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y
CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN=2
CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN=0
CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_PCM=y
CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=1
CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=0
CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=2
CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0
CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y
CONFIG_BTDM_CTRL_PINNED_TO_CORE=0
CONFIG_BTDM_CTRL_HCI_MODE_VHCI=y
CONFIG_BTDM_MODEM_SLEEP=y
CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG=y
CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL=y
CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1
CONFIG_BT_BLUEDROID_ENABLED=y
CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y
CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0
CONFIG_BT_BTC_TASK_STACK_SIZE=3072
CONFIG_BT_BTU_TASK_STACK_SIZE=4096
CONFIG_BT_CLASSIC_ENABLED=y
CONFIG_BT_A2DP_ENABLE=y
CONFIG_BT_A2DP_SINK_TASK_STACK_SIZE=2048
CONFIG_BT_A2DP_SOURCE_TASK_STACK_SIZE=2048
CONFIG_BT_SSP_ENABLED=y
CONFIG_BT_ACL_CONNECTIONS=4
CONFIG_BT_SMP_ENABLE=y
CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30
CONFIG_BT_RESERVE_DRAM=0xdb5c
CONFIG_SPI_MASTER_ISR_IN_IRAM=y
CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
CONFIG_ESP32_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_TYPE_AUTO=y
CONFIG_SPIRAM_SIZE=-1
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_CACHE_WORKAROUND=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=256
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65536
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_OCCUPY_VSPI_HOST=y
CONFIG_SPIRAM_BANKSWITCH_ENABLE=n
CONFIG_D0WD_PSRAM_CLK_IO=17
CONFIG_D0WD_PSRAM_CS_IO=16
CONFIG_D2WD_PSRAM_CLK_IO=9
CONFIG_D2WD_PSRAM_CS_IO=10
CONFIG_PICO_PSRAM_CS_IO=10
CONFIG_ESP32_PANIC_PRINT_REBOOT=y
CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
CONFIG_ESP32_XTAL_FREQ_40=y
CONFIG_ESP32_XTAL_FREQ=40
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y
CONFIG_ESP32_WIFI_SW_COEXIST_PREFERENCE_BALANCE=y
CONFIG_ESP32_WIFI_SW_COEXIST_PREFERENCE_VALUE=2
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=12
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=40
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=12
CONFIG_ESP32_WIFI_NVS_ENABLED=y
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752
CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32
CONFIG_ESP32_WIFI_IRAM_OPT=y
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=n
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=n
CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y
CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
CONFIG_ESP32_PHY_MAX_TX_POWER=20
CONFIG_FREERTOS_HZ=100
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32
CONFIG_LWIP_MAX_SOCKETS=16
CONFIG_LWIP_NETIF_LOOPBACK=y
CONFIG_LWIP_TCP_MSL=60000
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=8192
CONFIG_LWIP_TCP_WND_DEFAULT=32768
CONFIG_LWIP_TCP_RECVMBOX_SIZE=32
CONFIG_LWIP_MAX_RAW_PCBS=16
CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
CONFIG_ESP32_PTHREAD_STACK_MIN=768
CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1=y
CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=1
CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread"
CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# wifi-manager
CONFIG_DEFAULT_AP_SSID="squeezelite"
CONFIG_DEFAULT_AP_PASSWORD="squeezelite"
CONFIG_DEFAULT_AP_IP="192.168.4.1"
CONFIG_DEFAULT_AP_GATEWAY="192.168.4.1"
CONFIG_DEFAULT_AP_NETMASK="255.255.255.0"
CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -32,7 +32,7 @@ static const char *TAG = "cmd_i2ctools";
static gpio_num_t i2c_gpio_sda = 19; static gpio_num_t i2c_gpio_sda = 19;
static gpio_num_t i2c_gpio_scl = 18; static gpio_num_t i2c_gpio_scl = 18;
static uint32_t i2c_frequency = 100000; static uint32_t i2c_frequency = 100000;
#ifdef CONFIG_SQUEEZEAMP #ifdef CONFIG_I2C_LOCKED
static i2c_port_t i2c_port = I2C_NUM_1; static i2c_port_t i2c_port = I2C_NUM_1;
#else #else
static i2c_port_t i2c_port = I2C_NUM_0; static i2c_port_t i2c_port = I2C_NUM_0;

View File

@@ -0,0 +1,6 @@
idf_component_register(SRCS "led.c" "audio_controls.c" "buttons.c" "services.c" "monitor.c"INCLUDE_DIRS
INCLUDE_DIRS . ../tools/
)

View File

@@ -0,0 +1,12 @@
#
# Component Makefile
#
# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
# this will take the sources in the src/ directory, compile them and link them into
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
# please read the SDK documents if you need to do this.
#
COMPONENT_SRCDIRS := . tarablessd13x6 tarablessd13x6/fonts tarablessd13x6/ifaces
COMPONENT_ADD_INCLUDEDIRS := .
COMPONENT_ADD_INCLUDEDIRS += ./tarablessd13x6

View File

@@ -27,7 +27,7 @@
#include "display.h" #include "display.h"
// here we should include all possible drivers // here we should include all possible drivers
extern struct display_s SSD1306_display; extern struct display_s SSD13x6_display;
struct display_s *display = NULL; struct display_s *display = NULL;
@@ -36,7 +36,7 @@ static const char *TAG = "display";
#define min(a,b) (((a) < (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b))
#define DISPLAYER_STACK_SIZE 2048 #define DISPLAYER_STACK_SIZE (3*1024)
#define SCROLLABLE_SIZE 384 #define SCROLLABLE_SIZE 384
#define HEADER_SIZE 64 #define HEADER_SIZE 64
#define DEFAULT_SLEEP 3600 #define DEFAULT_SLEEP 3600
@@ -66,20 +66,20 @@ void display_init(char *welcome) {
if (item && *item) { if (item && *item) {
char * drivername=strstr(item,"driver"); char * drivername=strstr(item,"driver");
if (!drivername || (drivername && strcasestr(drivername,"SSD1306"))) { if (!drivername || (drivername && (strcasestr(drivername,"SSD1306") || strcasestr(drivername,"SSD1326") || strcasestr(drivername,"SH1106")))) {
display = &SSD1306_display; display = &SSD13x6_display;
if (display->init(item, welcome)) { if (display->init(item, welcome)) {
init = true; init = true;
ESP_LOGI(TAG, "Display initialization successful"); ESP_LOGI(TAG, "Display initialization successful");
} else { } else {
display = NULL; display = NULL;
ESP_LOGE(TAG, "Display initialization failed"); ESP_LOGW(TAG, "Display initialization failed");
} }
} else { } else {
ESP_LOGE(TAG,"Unknown display driver name in display config: %s",item); ESP_LOGE(TAG,"Unknown display driver name in display config: %s",item);
} }
} else { } else {
ESP_LOGW(TAG, "no display"); ESP_LOGI(TAG, "no display");
} }
if (init) { if (init) {

View File

@@ -25,10 +25,10 @@
#include "display.h" #include "display.h"
#include "globdefs.h" #include "globdefs.h"
#include "ssd1306.h" #include "ssd13x6.h"
#include "ssd1306_draw.h" #include "ssd13x6_draw.h"
#include "ssd1306_font.h" #include "ssd13x6_font.h"
#include "ssd1306_default_if.h" #include "ssd13x6_default_if.h"
#define I2C_ADDRESS 0x3C #define I2C_ADDRESS 0x3C
@@ -50,13 +50,13 @@ static void on(bool state);
static void update(void); static void update(void);
// display structure for others to use // display structure for others to use
struct display_s SSD1306_display = { 0, 0, struct display_s SSD13x6_display = { 0, 0,
init, clear, set_font, on, brightness, init, clear, set_font, on, brightness,
text, line, stretch, update, draw, draw_cbr, NULL }; text, line, stretch, update, draw, draw_cbr, NULL };
// SSD1306 specific function // SSD13x6 specific function
static struct SSD1306_Device Display; static struct SSD13x6_Device Display;
static SSD1306_AddressMode AddressMode = AddressMode_Invalid; static SSD13x6_AddressMode AddressMode = AddressMode_Invalid;
static const unsigned char BitReverseTable256[] = static const unsigned char BitReverseTable256[] =
{ {
@@ -82,40 +82,66 @@ static const unsigned char BitReverseTable256[] =
static struct { static struct {
int y, space; int y, space;
const struct SSD1306_FontDef *font; const struct SSD13x6_FontDef *font;
} lines[MAX_LINES]; } lines[MAX_LINES];
/**************************************************************************************** /****************************************************************************************
* *
*/ */
static bool init(char *config, char *welcome) { static bool init(char *config, char *welcome) {
bool res = false; bool res = true;
int width = -1, height = -1, model = SSD1306;
char *p;
ESP_LOGI(TAG, "Initializing display with config: %s",config);
// no time for smart parsing - this is for tinkerers
if ((p = strcasestr(config, "width")) != NULL) width = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "height")) != NULL) height = atoi(strchr(p, '=') + 1);
if (strcasestr(config, "ssd1326")) model = SSD1326;
else if (strcasestr(config, "sh1106")) model = SH1106;
if (width == -1 || height == -1) {
ESP_LOGW(TAG, "No display configured %s [%d x %d]", config, width, height);
return false;
}
if (strstr(config, "I2C") && i2c_system_port != -1) {
int address = I2C_ADDRESS;
if (strstr(config, "I2C")) {
int width = -1, height = -1, address = I2C_ADDRESS;
char *p;
ESP_LOGI(TAG, "Initializing I2C display with config: %s",config);
// no time for smart parsing - this is for tinkerers
if ((p = strcasestr(config, "width")) != NULL) width = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "height")) != NULL) height = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1); if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1);
if (width != -1 && height != -1) { SSD13x6_I2CMasterInitDefault( i2c_system_port, -1, -1 ) ;
SSD1306_I2CMasterInitDefault( i2c_system_port, -1, -1 ) ; SSD13x6_I2CMasterAttachDisplayDefault( &Display, model, width, height, address, -1 );
SSD1306_I2CMasterAttachDisplayDefault( &Display, width, height, address, -1 ); SSD13x6_SetHFlip( &Display, strcasestr(config, "HFlip") ? true : false);
SSD1306_SetHFlip( &Display, strcasestr(config, "HFlip") ? true : false); SSD13x6_SetVFlip( &Display, strcasestr(config, "VFlip") ? true : false);
SSD1306_SetVFlip( &Display, strcasestr(config, "VFlip") ? true : false); SSD13x6_SetFont( &Display, &Font_droid_sans_fallback_15x17 );
SSD1306_SetFont( &Display, &Font_droid_sans_fallback_15x17 ); SSD13x6_display.width = width;
SSD1306_display.width = width; SSD13x6_display.height = height;
SSD1306_display.height = height;
text(DISPLAY_FONT_MEDIUM, DISPLAY_CENTERED, DISPLAY_CLEAR | DISPLAY_UPDATE, welcome); text(DISPLAY_FONT_MEDIUM, DISPLAY_CENTERED, DISPLAY_CLEAR | DISPLAY_UPDATE, welcome);
ESP_LOGI(TAG, "Initialized I2C display %dx%d", width, height);
res = true; ESP_LOGI(TAG, "Display is I2C on port %u", address);
} else { } else if (strstr(config, "SPI") && spi_system_host != -1) {
ESP_LOGI(TAG, "Cannot initialized I2C display %s [%dx%d]", config, width, height); int CS_pin = -1, speed = 0;
}
if ((p = strcasestr(config, "cs")) != NULL) CS_pin = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "speed")) != NULL) speed = atoi(strchr(p, '=') + 1);
SSD13x6_SPIMasterInitDefault( spi_system_host, spi_system_dc_gpio );
SSD13x6_SPIMasterAttachDisplayDefault( &Display, model, width, height, CS_pin, -1, speed );
SSD13x6_SetFont( &Display, &Font_droid_sans_fallback_15x17 );
SSD13x6_display.width = width;
SSD13x6_display.height = height;
text(DISPLAY_FONT_MEDIUM, DISPLAY_CENTERED, DISPLAY_CLEAR | DISPLAY_UPDATE, welcome);
ESP_LOGI(TAG, "Display is SPI host %u with cs:%d", spi_system_host, CS_pin);
} else { } else {
ESP_LOGE(TAG, "Non-I2C display not supported. Display config %s", config); res = false;
ESP_LOGW(TAG, "Unknown display type or no serial interface configured");
} }
return res; return res;
@@ -125,8 +151,8 @@ static bool init(char *config, char *welcome) {
* *
*/ */
static void clear(void) { static void clear(void) {
SSD1306_Clear( &Display, SSD_COLOR_BLACK ); SSD13x6_Clear( &Display, SSD_COLOR_BLACK );
SSD1306_Update( &Display ); SSD13x6_Update( &Display );
} }
/**************************************************************************************** /****************************************************************************************
@@ -186,13 +212,13 @@ static bool line(int num, int x, int attribute, char *text) {
// always horizontal mode for text display // always horizontal mode for text display
if (AddressMode != AddressMode_Horizontal) { if (AddressMode != AddressMode_Horizontal) {
AddressMode = AddressMode_Horizontal; AddressMode = AddressMode_Horizontal;
SSD1306_SetDisplayAddressMode( &Display, AddressMode ); SSD13x6_SetDisplayAddressMode( &Display, AddressMode );
} }
SSD1306_SetFont( &Display, lines[num].font ); SSD13x6_SetFont( &Display, lines[num].font );
if (attribute & DISPLAY_MONOSPACE) SSD1306_FontForceMonospace( &Display, true ); if (attribute & DISPLAY_MONOSPACE) SSD13x6_FontForceMonospace( &Display, true );
width = SSD1306_FontMeasureString( &Display, text ); width = SSD13x6_FontMeasureString( &Display, text );
// adjusting position, erase only EoL for rigth-justified // adjusting position, erase only EoL for rigth-justified
if (x == DISPLAY_RIGHT) x = Display.Width - width - 1; if (x == DISPLAY_RIGHT) x = Display.Width - width - 1;
@@ -200,17 +226,18 @@ static bool line(int num, int x, int attribute, char *text) {
// erase if requested // erase if requested
if (attribute & DISPLAY_CLEAR) { if (attribute & DISPLAY_CLEAR) {
int y_min = max(0, lines[num].y), y_max = max(0, lines[num].y + lines[num].font->Height);
for (int c = (attribute & DISPLAY_ONLY_EOL) ? x : 0; c < Display.Width; c++) for (int c = (attribute & DISPLAY_ONLY_EOL) ? x : 0; c < Display.Width; c++)
for (int y = lines[num].y; y < lines[num].y + lines[num].font->Height; y++) for (int y = y_min; y < y_max; y++)
SSD1306_DrawPixelFast( &Display, c, y, SSD_COLOR_BLACK ); SSD13x6_DrawPixelFast( &Display, c, y, SSD_COLOR_BLACK );
} }
SSD1306_FontDrawString( &Display, x, lines[num].y, text, SSD_COLOR_WHITE ); SSD13x6_FontDrawString( &Display, x, lines[num].y, text, SSD_COLOR_WHITE );
ESP_LOGD(TAG, "displaying %s line %u (x:%d, attr:%u)", text, num+1, x, attribute); ESP_LOGD(TAG, "displaying %s line %u (x:%d, attr:%u)", text, num+1, x, attribute);
// update whole display if requested // update whole display if requested
if (attribute & DISPLAY_UPDATE) SSD1306_Update( &Display ); if (attribute & DISPLAY_UPDATE) SSD13x6_Update( &Display );
return width + x < Display.Width; return width + x < Display.Width;
} }
@@ -225,8 +252,8 @@ static int stretch(int num, char *string, int max) {
num--; num--;
// we might already fit // we might already fit
SSD1306_SetFont( &Display, lines[num].font ); SSD13x6_SetFont( &Display, lines[num].font );
if (SSD1306_FontMeasureString( &Display, string ) <= Display.Width) return 0; if (SSD13x6_FontMeasureString( &Display, string ) <= Display.Width) return 0;
// add some space for better visual // add some space for better visual
strncat(string, space, max-len); strncat(string, space, max-len);
@@ -234,10 +261,10 @@ static int stretch(int num, char *string, int max) {
len = strlen(string); len = strlen(string);
// mark the end of the extended string // mark the end of the extended string
boundary = SSD1306_FontMeasureString( &Display, string ); boundary = SSD13x6_FontMeasureString( &Display, string );
// add a full display width // add a full display width
while (len < max && SSD1306_FontMeasureString( &Display, string ) - boundary < Display.Width) { while (len < max && SSD13x6_FontMeasureString( &Display, string ) - boundary < Display.Width) {
string[len++] = string[extra++]; string[len++] = string[extra++];
string[len] = '\0'; string[len] = '\0';
} }
@@ -254,31 +281,31 @@ static void text(enum display_font_e font, enum display_pos_e pos, int attribute
va_start(args, text); va_start(args, text);
TextAnchor Anchor = TextAnchor_Center; TextAnchor Anchor = TextAnchor_Center;
if (attribute & DISPLAY_CLEAR) SSD1306_Clear( &Display, SSD_COLOR_BLACK ); if (attribute & DISPLAY_CLEAR) SSD13x6_Clear( &Display, SSD_COLOR_BLACK );
if (!text) return; if (!text) return;
switch(font) { switch(font) {
case DISPLAY_FONT_LINE_1: case DISPLAY_FONT_LINE_1:
SSD1306_SetFont( &Display, &Font_line_1 ); SSD13x6_SetFont( &Display, &Font_line_1 );
break; break;
case DISPLAY_FONT_LINE_2: case DISPLAY_FONT_LINE_2:
SSD1306_SetFont( &Display, &Font_line_2 ); SSD13x6_SetFont( &Display, &Font_line_2 );
break; break;
case DISPLAY_FONT_SMALL: case DISPLAY_FONT_SMALL:
SSD1306_SetFont( &Display, &Font_droid_sans_fallback_11x13 ); SSD13x6_SetFont( &Display, &Font_droid_sans_fallback_11x13 );
break; break;
case DISPLAY_FONT_MEDIUM: case DISPLAY_FONT_MEDIUM:
case DISPLAY_FONT_DEFAULT: case DISPLAY_FONT_DEFAULT:
default: default:
SSD1306_SetFont( &Display, &Font_droid_sans_fallback_15x17 ); SSD13x6_SetFont( &Display, &Font_droid_sans_fallback_15x17 );
break; break;
case DISPLAY_FONT_LARGE: case DISPLAY_FONT_LARGE:
SSD1306_SetFont( &Display, &Font_droid_sans_fallback_24x28 ); SSD13x6_SetFont( &Display, &Font_droid_sans_fallback_24x28 );
break; break;
case DISPLAY_FONT_SEGMENT: case DISPLAY_FONT_SEGMENT:
if (Display.Height == 32) SSD1306_SetFont( &Display, &Font_Tarable7Seg_16x32 ); if (Display.Height == 32) SSD13x6_SetFont( &Display, &Font_Tarable7Seg_16x32 );
else SSD1306_SetFont( &Display, &Font_Tarable7Seg_32x64 ); else SSD13x6_SetFont( &Display, &Font_Tarable7Seg_32x64 );
break; break;
} }
@@ -298,15 +325,15 @@ static void text(enum display_font_e font, enum display_pos_e pos, int attribute
break; break;
} }
ESP_LOGD(TAG, "SSDD1306 displaying %s at %u with attribute %u", text, Anchor, attribute); ESP_LOGD(TAG, "SSDD13x6 displaying %s at %u with attribute %u", text, Anchor, attribute);
if (AddressMode != AddressMode_Horizontal) { if (AddressMode != AddressMode_Horizontal) {
AddressMode = AddressMode_Horizontal; AddressMode = AddressMode_Horizontal;
SSD1306_SetDisplayAddressMode( &Display, AddressMode ); SSD13x6_SetDisplayAddressMode( &Display, AddressMode );
} }
SSD1306_FontDrawAnchoredString( &Display, Anchor, text, SSD_COLOR_WHITE ); SSD13x6_FontDrawAnchoredString( &Display, Anchor, text, SSD_COLOR_WHITE );
if (attribute & DISPLAY_UPDATE) SSD1306_Update( &Display ); if (attribute & DISPLAY_UPDATE) SSD13x6_Update( &Display );
va_end(args); va_end(args);
} }
@@ -319,7 +346,7 @@ static void draw_cbr(u8_t *data, int height) {
// force addressing mode by rows // force addressing mode by rows
if (AddressMode != AddressMode_Horizontal) { if (AddressMode != AddressMode_Horizontal) {
AddressMode = AddressMode_Horizontal; AddressMode = AddressMode_Horizontal;
SSD1306_SetDisplayAddressMode( &Display, AddressMode ); SSD13x6_SetDisplayAddressMode( &Display, AddressMode );
} }
// try to minimize I2C traffic which is very slow // try to minimize I2C traffic which is very slow
@@ -341,28 +368,41 @@ static void draw_cbr(u8_t *data, int height) {
// now update the display by "byte rows" // now update the display by "byte rows"
if (first--) { if (first--) {
SSD1306_SetColumnAddress( &Display, first, last ); SSD13x6_SetColumnAddress( &Display, first, last );
SSD1306_SetPageAddress( &Display, r, r); SSD13x6_SetPageAddress( &Display, r, r);
SSD1306_WriteRawData( &Display, Display.Framebuffer + r*Display.Width + first, last - first + 1); SSD13x6_WriteRawData( &Display, Display.Framebuffer + r*Display.Width + first, last - first + 1);
} }
} }
#else #else
if (!height) height = Display->Height; if (!height) height = Display->Height;
// copy data in frame buffer SSD13x6_SetPageAddress( &Display, 0, height / 8 - 1);
for (int c = 0; c < Display.Width; c++)
for (int r = 0; r < height / 8; r++)
Display.Framebuffer[c*Display.Height/8 + r] = BitReverseTable256[data[c*height/8 +r]];
SSD1306_SetPageAddress( &Display, 0, height / 8 - 1); // force addressing mode by columns (if we can)
if (SSD13x6_GetCaps( &Display ) & CAPS_ADDRESS_VERTICAL) {
// just copy data in frame buffer with bit-reverse
for (int c = 0; c < Display.Width; c++)
for (int r = 0; r < height / 8; r++)
Display.Framebuffer[c*Display.Height/8 + r] = BitReverseTable256[data[c*height/8 +r]];
// force addressing mode by columns if (AddressMode != AddressMode_Vertical) {
if (AddressMode != AddressMode_Vertical) { AddressMode = AddressMode_Vertical;
AddressMode = AddressMode_Vertical; SSD13x6_SetDisplayAddressMode( &Display, AddressMode );
SSD1306_SetDisplayAddressMode( &Display, AddressMode ); }
} else {
// need to do rwo/col swap and bit-reverse
int rows = (height ? height : Display.Height) / 8;
for (int r = 0; r < rows; r++) {
uint8_t *optr = Display.Framebuffer + r*Display.Width, *iptr = data + r;
for (int c = 0; c < Display.Width; c++) {
*optr++ = BitReverseTable256[*iptr];;
iptr += rows;
}
}
ESP_LOGW(TAG, "Can't set addressing mode to vertical, swapping");
} }
SSD1306_WriteRawData(&Display, Display.Framebuffer, Display.Width * Display.Height/8); SSD13x6_WriteRawData(&Display, Display.Framebuffer, Display.Width * Display.Height/8);
#endif #endif
} }
@@ -386,7 +426,7 @@ static void draw(int x1, int y1, int x2, int y2, bool by_column, u8_t *data) {
if (AddressMode != AddressMode_Vertical) { if (AddressMode != AddressMode_Vertical) {
AddressMode = AddressMode_Vertical; AddressMode = AddressMode_Vertical;
SSD1306_SetDisplayAddressMode( &Display, AddressMode ); SSD13x6_SetDisplayAddressMode( &Display, AddressMode );
} }
// copy the window and do row/col exchange // copy the window and do row/col exchange
@@ -405,32 +445,32 @@ static void draw(int x1, int y1, int x2, int y2, bool by_column, u8_t *data) {
} }
} }
SSD1306_SetColumnAddress( &Display, x1, x2); SSD13x6_SetColumnAddress( &Display, x1, x2);
SSD1306_SetPageAddress( &Display, y1/8, y2/8); SSD13x6_SetPageAddress( &Display, y1/8, y2/8);
SSD1306_WriteRawData( &Display, data, (x2-x1 + 1) * ((y2-y1)/8 + 1)); SSD13x6_WriteRawData( &Display, data, (x2-x1 + 1) * ((y2-y1)/8 + 1));
} }
/**************************************************************************************** /****************************************************************************************
* Brightness * Brightness
*/ */
static void brightness(u8_t level) { static void brightness(u8_t level) {
SSD1306_DisplayOn( &Display ); SSD13x6_DisplayOn( &Display );
SSD1306_SetContrast( &Display, (uint8_t) level); SSD13x6_SetContrast( &Display, (uint8_t) level);
} }
/**************************************************************************************** /****************************************************************************************
* Display On/Off * Display On/Off
*/ */
static void on(bool state) { static void on(bool state) {
if (state) SSD1306_DisplayOn( &Display ); if (state) SSD13x6_DisplayOn( &Display );
else SSD1306_DisplayOff( &Display ); else SSD13x6_DisplayOff( &Display );
} }
/**************************************************************************************** /****************************************************************************************
* Update * Update
*/ */
static void update(void) { static void update(void) {
SSD1306_Update( &Display ); SSD13x6_Update( &Display );
} }

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Fallback11x13[ ] = {
0x05, 0x00, 0x10, 0xE4, 0x11, 0x00, 0x0E, 0x00, 0x02, 0xE4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ 0x05, 0x00, 0x10, 0xE4, 0x11, 0x00, 0x0E, 0x00, 0x02, 0xE4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ
}; };
const struct SSD1306_FontDef Font_droid_sans_fallback_11x13 = { const struct SSD13x6_FontDef Font_droid_sans_fallback_11x13 = {
Droid_Sans_Fallback11x13, Droid_Sans_Fallback11x13,
11, 11,
13, 13,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Fallback15x17[ ] = {
0x07, 0xC0, 0x00, 0x01, 0x00, 0x03, 0x01, 0x10, 0x8C, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ 0x07, 0xC0, 0x00, 0x01, 0x00, 0x03, 0x01, 0x10, 0x8C, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ
}; };
const struct SSD1306_FontDef Font_droid_sans_fallback_15x17 = { const struct SSD13x6_FontDef Font_droid_sans_fallback_15x17 = {
Droid_Sans_Fallback15x17, Droid_Sans_Fallback15x17,
15, 15,
17, 17,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Fallback24x28[ ] = {
0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x0C, 0xE0, 0xF0, 0x03, 0x0C, 0xE0, 0x80, 0x0F, 0x0E, 0x00, 0x00, 0xFE, 0x07, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x7E, 0x00, 0xE0, 0x80, 0x0F, 0x00, 0xE0, 0xF0, 0x03, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x0C, 0xE0, 0xF0, 0x03, 0x0C, 0xE0, 0x80, 0x0F, 0x0E, 0x00, 0x00, 0xFE, 0x07, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x7E, 0x00, 0xE0, 0x80, 0x0F, 0x00, 0xE0, 0xF0, 0x03, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ
}; };
const struct SSD1306_FontDef Font_droid_sans_fallback_24x28 = { const struct SSD13x6_FontDef Font_droid_sans_fallback_24x28 = {
Droid_Sans_Fallback24x28, Droid_Sans_Fallback24x28,
24, 24,
28, 28,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Mono13x24[ ] = {
0x0C, 0x00, 0x00, 0x00, 0x80, 0x00, 0xC0, 0x80, 0x07, 0xC0, 0x00, 0x1E, 0xC0, 0x18, 0xF8, 0xC0, 0x18, 0xC0, 0x7F, 0x00, 0x00, 0x1E, 0x00, 0xC0, 0x07, 0x18, 0xF8, 0x00, 0x18, 0x3E, 0x00, 0x80, 0x07, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ 0x0C, 0x00, 0x00, 0x00, 0x80, 0x00, 0xC0, 0x80, 0x07, 0xC0, 0x00, 0x1E, 0xC0, 0x18, 0xF8, 0xC0, 0x18, 0xC0, 0x7F, 0x00, 0x00, 0x1E, 0x00, 0xC0, 0x07, 0x18, 0xF8, 0x00, 0x18, 0x3E, 0x00, 0x80, 0x07, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ
}; };
const struct SSD1306_FontDef Font_droid_sans_mono_13x24 = { const struct SSD13x6_FontDef Font_droid_sans_mono_13x24 = {
Droid_Sans_Mono13x24, Droid_Sans_Mono13x24,
13, 13,
24, 24,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Mono16x31[ ] = {
0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x60, 0x00, 0x78, 0x00, 0x60, 0x00, 0xF8, 0x01, 0x60, 0x00, 0xE0, 0x07, 0x60, 0xE0, 0x00, 0x3F, 0x70, 0xE0, 0x00, 0xFC, 0x3C, 0x40, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0xE0, 0x07, 0x40, 0x00, 0xF8, 0x01, 0xE0, 0x00, 0x3F, 0x00, 0xE0, 0xC0, 0x0F, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x60, 0x00, 0x78, 0x00, 0x60, 0x00, 0xF8, 0x01, 0x60, 0x00, 0xE0, 0x07, 0x60, 0xE0, 0x00, 0x3F, 0x70, 0xE0, 0x00, 0xFC, 0x3C, 0x40, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0xE0, 0x07, 0x40, 0x00, 0xF8, 0x01, 0xE0, 0x00, 0x3F, 0x00, 0xE0, 0xC0, 0x0F, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ
}; };
const struct SSD1306_FontDef Font_droid_sans_mono_16x31 = { const struct SSD13x6_FontDef Font_droid_sans_mono_16x31 = {
Droid_Sans_Mono16x31, Droid_Sans_Mono16x31,
16, 16,
31, 31,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Mono7x13[ ] = {
0x06, 0x00, 0x00, 0x30, 0x10, 0xC4, 0x10, 0x00, 0x0F, 0xC4, 0x01, 0x30, 0x00, 0x00, 0x00 // Code for char ÿ 0x06, 0x00, 0x00, 0x30, 0x10, 0xC4, 0x10, 0x00, 0x0F, 0xC4, 0x01, 0x30, 0x00, 0x00, 0x00 // Code for char ÿ
}; };
const struct SSD1306_FontDef Font_droid_sans_mono_7x13 = { const struct SSD13x6_FontDef Font_droid_sans_mono_7x13 = {
Droid_Sans_Mono7x13, Droid_Sans_Mono7x13,
7, 7,
13, 13,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -237,7 +237,7 @@ static const uint8_t Liberation_Mono13x21[ ] = {
0x0C, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x03, 0x10, 0x00, 0x0F, 0x10, 0x0C, 0x3C, 0x18, 0x00, 0xE0, 0x0D, 0x00, 0x80, 0x07, 0x00, 0xE0, 0x01, 0x0C, 0x3C, 0x00, 0x00, 0x0F, 0x00, 0xC0, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ 0x0C, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x03, 0x10, 0x00, 0x0F, 0x10, 0x0C, 0x3C, 0x18, 0x00, 0xE0, 0x0D, 0x00, 0x80, 0x07, 0x00, 0xE0, 0x01, 0x0C, 0x3C, 0x00, 0x00, 0x0F, 0x00, 0xC0, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ
}; };
const struct SSD1306_FontDef Font_liberation_mono_13x21 = { const struct SSD13x6_FontDef Font_liberation_mono_13x21 = {
Liberation_Mono13x21, Liberation_Mono13x21,
13, 13,
21, 21,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -237,7 +237,7 @@ static const uint8_t Liberation_Mono17x30[] = {
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x30, 0x00, 0x3F, 0x00, 0x30, 0x00, 0xFC, 0x01, 0x30, 0x38, 0xE0, 0x07, 0x38, 0x38, 0x00, 0x3F, 0x1C, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xF8, 0x01, 0x38, 0x00, 0x3F, 0x00, 0x38, 0xE0, 0x07, 0x00, 0x38, 0xFC, 0x01, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x30, 0x00, 0x3F, 0x00, 0x30, 0x00, 0xFC, 0x01, 0x30, 0x38, 0xE0, 0x07, 0x38, 0x38, 0x00, 0x3F, 0x1C, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xF8, 0x01, 0x38, 0x00, 0x3F, 0x00, 0x38, 0xE0, 0x07, 0x00, 0x38, 0xFC, 0x01, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ
}; };
const struct SSD1306_FontDef Font_liberation_mono_17x30 = { const struct SSD13x6_FontDef Font_liberation_mono_17x30 = {
Liberation_Mono17x30, Liberation_Mono17x30,
17, 17,
30, 30,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -237,7 +237,7 @@ static const uint8_t Liberation_Mono9x15[ ] = {
0x08, 0x00, 0x00, 0x30, 0x40, 0xC6, 0x41, 0x06, 0x67, 0x00, 0x18, 0x06, 0x07, 0xC6, 0x01, 0x30, 0x00, 0x00, 0x00 // Code for char ÿ 0x08, 0x00, 0x00, 0x30, 0x40, 0xC6, 0x41, 0x06, 0x67, 0x00, 0x18, 0x06, 0x07, 0xC6, 0x01, 0x30, 0x00, 0x00, 0x00 // Code for char ÿ
}; };
const struct SSD1306_FontDef Font_liberation_mono_9x15 = { const struct SSD13x6_FontDef Font_liberation_mono_9x15 = {
Liberation_Mono9x15, Liberation_Mono9x15,
9, 9,
15, 15,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -214,7 +214,7 @@ static const uint8_t Square721_BT11x14[] = {
0x06, 0x00, 0x00, 0xE8, 0x03, 0xB0, 0x04, 0xA0, 0x04, 0xA0, 0x04, 0xE0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char è 0x06, 0x00, 0x00, 0xE8, 0x03, 0xB0, 0x04, 0xA0, 0x04, 0xA0, 0x04, 0xE0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char è
}; };
const struct SSD1306_FontDef Font_line_1 = { const struct SSD13x6_FontDef Font_line_1 = {
Square721_BT11x14, Square721_BT11x14,
11, 11,
14, 14,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -237,7 +237,7 @@ static const uint8_t Archivo_Narrow18x24[] = {
0x0A, 0x00, 0x01, 0x00, 0x00, 0x1F, 0xE0, 0x38, 0xFF, 0xE0, 0x38, 0xFC, 0xF7, 0x00, 0xE0, 0x7F, 0x00, 0x00, 0x3F, 0x38, 0xF0, 0x0F, 0x38, 0xFF, 0x01, 0x00, 0x1F, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ 0x0A, 0x00, 0x01, 0x00, 0x00, 0x1F, 0xE0, 0x38, 0xFF, 0xE0, 0x38, 0xFC, 0xF7, 0x00, 0xE0, 0x7F, 0x00, 0x00, 0x3F, 0x38, 0xF0, 0x0F, 0x38, 0xFF, 0x01, 0x00, 0x1F, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ
}; };
const struct SSD1306_FontDef Font_line_2 = { const struct SSD13x6_FontDef Font_line_2 = {
Archivo_Narrow18x24, Archivo_Narrow18x24,
18, 18,
24, 24,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -109,7 +109,7 @@ static const uint8_t Tarable7Seg_16x32[ ] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char 
}; };
const struct SSD1306_FontDef Font_Tarable7Seg_16x32 = { const struct SSD13x6_FontDef Font_Tarable7Seg_16x32 = {
Tarable7Seg_16x32, Tarable7Seg_16x32,
16, 16,
32, 32,

View File

@@ -1,4 +1,4 @@
#include <ssd1306_font.h> #include <ssd13x6_font.h>
//WARNING: This Font Require X-GLCD Lib. //WARNING: This Font Require X-GLCD Lib.
// You can not use it with MikroE GLCD Lib. // You can not use it with MikroE GLCD Lib.
@@ -109,7 +109,7 @@ static const uint8_t Tarable7Seg_32x64[ ] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char 
}; };
const struct SSD1306_FontDef Font_Tarable7Seg_32x64 = { const struct SSD13x6_FontDef Font_Tarable7Seg_32x64 = {
Tarable7Seg_32x64, Tarable7Seg_32x64,
32, 32,
64, 64,

View File

@@ -11,19 +11,18 @@
#include <string.h> #include <string.h>
#include <driver/i2c.h> #include <driver/i2c.h>
#include <driver/gpio.h> #include <driver/gpio.h>
#include "ssd1306.h" #include "ssd13x6.h"
#include "ssd1306_default_if.h" #include "ssd13x6_default_if.h"
static const int I2CDisplaySpeed = CONFIG_DISPLAY_I2C_SPEED;
static int I2CPortNumber; static int I2CPortNumber;
static const int SSD1306_I2C_COMMAND_MODE = 0x80; static const int SSD13x6_I2C_COMMAND_MODE = 0x80;
static const int SSD1306_I2C_DATA_MODE = 0x40; static const int SSD13x6_I2C_DATA_MODE = 0x40;
static bool I2CDefaultWriteBytes( int Address, bool IsCommand, const uint8_t* Data, size_t DataLength ); static bool I2CDefaultWriteBytes( int Address, bool IsCommand, const uint8_t* Data, size_t DataLength );
static bool I2CDefaultWriteCommand( struct SSD1306_Device* Display, SSDCmd Command ); static bool I2CDefaultWriteCommand( struct SSD13x6_Device* Display, SSDCmd Command );
static bool I2CDefaultWriteData( struct SSD1306_Device* Display, const uint8_t* Data, size_t DataLength ); static bool I2CDefaultWriteData( struct SSD13x6_Device* Display, const uint8_t* Data, size_t DataLength );
static bool I2CDefaultReset( struct SSD1306_Device* Display ); static bool I2CDefaultReset( struct SSD13x6_Device* Display );
/* /*
* Initializes the i2c master with the parameters specified * Initializes the i2c master with the parameters specified
@@ -31,7 +30,7 @@ static bool I2CDefaultReset( struct SSD1306_Device* Display );
* *
* Returns true on successful init of the i2c bus. * Returns true on successful init of the i2c bus.
*/ */
bool SSD1306_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ) { bool SSD13x6_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ) {
I2CPortNumber = PortNumber; I2CPortNumber = PortNumber;
if (SDA != -1 && SCL != -1) { if (SDA != -1 && SCL != -1) {
@@ -42,7 +41,7 @@ bool SSD1306_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ) {
Config.sda_pullup_en = GPIO_PULLUP_ENABLE; Config.sda_pullup_en = GPIO_PULLUP_ENABLE;
Config.scl_io_num = SCL; Config.scl_io_num = SCL;
Config.scl_pullup_en = GPIO_PULLUP_ENABLE; Config.scl_pullup_en = GPIO_PULLUP_ENABLE;
Config.master.clk_speed = I2CDisplaySpeed; Config.master.clk_speed = 250000;
ESP_ERROR_CHECK_NONFATAL( i2c_param_config( I2CPortNumber, &Config ), return false ); ESP_ERROR_CHECK_NONFATAL( i2c_param_config( I2CPortNumber, &Config ), return false );
ESP_ERROR_CHECK_NONFATAL( i2c_driver_install( I2CPortNumber, Config.mode, 0, 0, 0 ), return false ); ESP_ERROR_CHECK_NONFATAL( i2c_driver_install( I2CPortNumber, Config.mode, 0, 0, 0 ), return false );
@@ -55,7 +54,7 @@ bool SSD1306_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ) {
* Attaches a display to the I2C bus using default communication functions. * Attaches a display to the I2C bus using default communication functions.
* *
* Params: * Params:
* DisplayHandle: Pointer to your SSD1306_Device object * DisplayHandle: Pointer to your SSD13x6_Device object
* Width: Width of display * Width: Width of display
* Height: Height of display * Height: Height of display
* I2CAddress: Address of your display * I2CAddress: Address of your display
@@ -63,15 +62,18 @@ bool SSD1306_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ) {
* *
* Returns true on successful init of display. * Returns true on successful init of display.
*/ */
bool SSD1306_I2CMasterAttachDisplayDefault( struct SSD1306_Device* DisplayHandle, int Width, int Height, int I2CAddress, int RSTPin ) { bool SSD13x6_I2CMasterAttachDisplayDefault( struct SSD13x6_Device* DeviceHandle, int Model, int Width, int Height, int I2CAddress, int RSTPin ) {
NullCheck( DisplayHandle, return false ); NullCheck( DeviceHandle, return false );
if ( RSTPin >= 0 ) { if ( RSTPin >= 0 ) {
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTPin, GPIO_MODE_OUTPUT ), return false ); ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTPin, GPIO_MODE_OUTPUT ), return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTPin, 1 ), return false ); ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTPin, 1 ), return false );
} }
return SSD1306_Init_I2C( DisplayHandle, memset( DeviceHandle, 0, sizeof( struct SSD13x6_Device ) );
DeviceHandle->Model = Model;
return SSD13x6_Init_I2C( DeviceHandle,
Width, Width,
Height, Height,
I2CAddress, I2CAddress,
@@ -89,36 +91,40 @@ static bool I2CDefaultWriteBytes( int Address, bool IsCommand, const uint8_t* Da
NullCheck( Data, return false ); NullCheck( Data, return false );
if ( ( CommandHandle = i2c_cmd_link_create( ) ) != NULL ) { if ( ( CommandHandle = i2c_cmd_link_create( ) ) != NULL ) {
ModeByte = ( IsCommand == true ) ? SSD1306_I2C_COMMAND_MODE: SSD1306_I2C_DATA_MODE; ModeByte = ( IsCommand == true ) ? SSD13x6_I2C_COMMAND_MODE: SSD13x6_I2C_DATA_MODE;
ESP_ERROR_CHECK_NONFATAL( i2c_master_start( CommandHandle ), return false ); ESP_ERROR_CHECK_NONFATAL( i2c_master_start( CommandHandle ), goto error );
ESP_ERROR_CHECK_NONFATAL( i2c_master_write_byte( CommandHandle, ( Address << 1 ) | I2C_MASTER_WRITE, true ), return false ); ESP_ERROR_CHECK_NONFATAL( i2c_master_write_byte( CommandHandle, ( Address << 1 ) | I2C_MASTER_WRITE, true ), goto error );
ESP_ERROR_CHECK_NONFATAL( i2c_master_write_byte( CommandHandle, ModeByte, true ), return false ); ESP_ERROR_CHECK_NONFATAL( i2c_master_write_byte( CommandHandle, ModeByte, true ), goto error );
ESP_ERROR_CHECK_NONFATAL( i2c_master_write( CommandHandle, ( uint8_t* ) Data, DataLength, true ), return false ); ESP_ERROR_CHECK_NONFATAL( i2c_master_write( CommandHandle, ( uint8_t* ) Data, DataLength, true ), goto error );
ESP_ERROR_CHECK_NONFATAL( i2c_master_stop( CommandHandle ), return false ); ESP_ERROR_CHECK_NONFATAL( i2c_master_stop( CommandHandle ), goto error );
ESP_ERROR_CHECK_NONFATAL( i2c_master_cmd_begin( I2CPortNumber, CommandHandle, pdMS_TO_TICKS( 1000 ) ), return false ); ESP_ERROR_CHECK_NONFATAL( i2c_master_cmd_begin( I2CPortNumber, CommandHandle, pdMS_TO_TICKS( 1000 ) ), goto error );
i2c_cmd_link_delete( CommandHandle ); i2c_cmd_link_delete( CommandHandle );
} }
return true; return true;
error:
if (CommandHandle) i2c_cmd_link_delete( CommandHandle );
return false;
} }
static bool I2CDefaultWriteCommand( struct SSD1306_Device* Display, SSDCmd Command ) { static bool I2CDefaultWriteCommand( struct SSD13x6_Device* Display, SSDCmd Command ) {
uint8_t CommandByte = ( uint8_t ) Command; uint8_t CommandByte = ( uint8_t ) Command;
NullCheck( Display, return false ); NullCheck( Display, return false );
return I2CDefaultWriteBytes( Display->Address, true, ( const uint8_t* ) &CommandByte, 1 ); return I2CDefaultWriteBytes( Display->Address, true, ( const uint8_t* ) &CommandByte, 1 );
} }
static bool I2CDefaultWriteData( struct SSD1306_Device* Display, const uint8_t* Data, size_t DataLength ) { static bool I2CDefaultWriteData( struct SSD13x6_Device* Display, const uint8_t* Data, size_t DataLength ) {
NullCheck( Display, return false ); NullCheck( Display, return false );
NullCheck( Data, return false ); NullCheck( Data, return false );
return I2CDefaultWriteBytes( Display->Address, false, Data, DataLength ); return I2CDefaultWriteBytes( Display->Address, false, Data, DataLength );
} }
static bool I2CDefaultReset( struct SSD1306_Device* Display ) { static bool I2CDefaultReset( struct SSD13x6_Device* Display ) {
NullCheck( Display, return false ); NullCheck( Display, return false );
if ( Display->RSTPin >= 0 ) { if ( Display->RSTPin >= 0 ) {

View File

@@ -0,0 +1,123 @@
/**
* Copyright (c) 2017-2018 Tara Keeling
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <driver/spi_master.h>
#include <driver/gpio.h>
#include <freertos/task.h>
#include "ssd13x6.h"
#include "ssd13x6_default_if.h"
static const int SSD13x6_SPI_Command_Mode = 0;
static const int SSD13x6_SPI_Data_Mode = 1;
static spi_host_device_t SPIHost;
static int DCPin;
static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength );
static bool SPIDefaultWriteCommand( struct SSD13x6_Device* DeviceHandle, SSDCmd Command );
static bool SPIDefaultWriteData( struct SSD13x6_Device* DeviceHandle, const uint8_t* Data, size_t DataLength );
static bool SPIDefaultReset( struct SSD13x6_Device* DeviceHandle );
bool SSD13x6_SPIMasterInitDefault( int SPI, int DC ) {
SPIHost = SPI;
DCPin = DC;
return true;
}
bool SSD13x6_SPIMasterAttachDisplayDefault( struct SSD13x6_Device* DeviceHandle, int Model, int Width, int Height, int CSPin, int RSTPin, int Speed ) {
spi_device_interface_config_t SPIDeviceConfig;
spi_device_handle_t SPIDeviceHandle;
NullCheck( DeviceHandle, return false );
if (CSPin >= 0) {
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( CSPin, GPIO_MODE_OUTPUT ), return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSPin, 0 ), return false );
}
memset( &SPIDeviceConfig, 0, sizeof( spi_device_interface_config_t ) );
SPIDeviceConfig.clock_speed_hz = Speed > 0 ? Speed : SPI_MASTER_FREQ_8M;
SPIDeviceConfig.spics_io_num = CSPin;
SPIDeviceConfig.queue_size = 1;
if ( RSTPin >= 0 ) {
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTPin, GPIO_MODE_OUTPUT ), return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTPin, 0 ), return false );
}
ESP_ERROR_CHECK_NONFATAL( spi_bus_add_device( SPIHost, &SPIDeviceConfig, &SPIDeviceHandle ), return false );
memset( DeviceHandle, 0, sizeof( struct SSD13x6_Device ) );
DeviceHandle->Model = Model;
return SSD13x6_Init_SPI( DeviceHandle,
Width,
Height,
RSTPin,
CSPin,
SPIDeviceHandle,
SPIDefaultWriteCommand,
SPIDefaultWriteData,
SPIDefaultReset
);
}
static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) {
spi_transaction_t SPITransaction = { 0 };
NullCheck( SPIHandle, return false );
NullCheck( Data, return false );
if ( DataLength > 0 ) {
gpio_set_level( DCPin, WriteMode );
SPITransaction.length = DataLength * 8;
SPITransaction.tx_buffer = Data;
// only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes)
ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false );
}
return true;
}
static bool SPIDefaultWriteCommand( struct SSD13x6_Device* DeviceHandle, SSDCmd Command ) {
static uint8_t CommandByte = 0;
NullCheck( DeviceHandle, return false );
NullCheck( DeviceHandle->SPIHandle, return false );
CommandByte = Command;
return SPIDefaultWriteBytes( DeviceHandle->SPIHandle, SSD13x6_SPI_Command_Mode, &CommandByte, 1 );
}
static bool SPIDefaultWriteData( struct SSD13x6_Device* DeviceHandle, const uint8_t* Data, size_t DataLength ) {
NullCheck( DeviceHandle, return false );
NullCheck( DeviceHandle->SPIHandle, return false );
return SPIDefaultWriteBytes( DeviceHandle->SPIHandle, SSD13x6_SPI_Data_Mode, Data, DataLength );
}
static bool SPIDefaultReset( struct SSD13x6_Device* DeviceHandle ) {
NullCheck( DeviceHandle, return false );
if ( DeviceHandle->RSTPin >= 0 ) {
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( DeviceHandle->RSTPin, 0 ), return false );
vTaskDelay( pdMS_TO_TICKS( 100 ) );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( DeviceHandle->RSTPin, 1 ), return false );
}
return true;
}

View File

@@ -0,0 +1,315 @@
/**
* Copyright (c) 2017-2018 Tara Keeling
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>
#include <esp_heap_caps.h>
#include "ssd13x6.h"
// used by both but different
static uint8_t SSDCmd_Set_Display_Start_Line;
static uint8_t SSDCmd_Set_Display_Offset;
static uint8_t SSDCmd_Set_Column_Address;
static uint8_t SSDCmd_Set_Display_CLK;
static uint8_t SSDCmd_Set_Page_Address;
// misc boundaries
static uint8_t SSD13x6_Max_Col;
static const uint8_t SSD13x6_Max_Row = 7;
static bool SSD13x6_Init( struct SSD13x6_Device* DeviceHandle, int Width, int Height );
int SSD13x6_GetCaps( struct SSD13x6_Device* DeviceHandle ) {
if (DeviceHandle->Model == SH1106) return 0;
else return CAPS_COLUMN_RANGE | CAPS_PAGE_RANGE | CAPS_ADDRESS_VERTICAL;
}
bool SSD13x6_WriteCommand( struct SSD13x6_Device* DeviceHandle, SSDCmd SSDCommand ) {
NullCheck( DeviceHandle->WriteCommand, return false );
return ( DeviceHandle->WriteCommand ) ( DeviceHandle, SSDCommand );
}
bool SSD13x6_WriteData( struct SSD13x6_Device* DeviceHandle, uint8_t* Data, size_t DataLength ) {
NullCheck( DeviceHandle->WriteData, return false );
return ( DeviceHandle->WriteData ) ( DeviceHandle, Data, DataLength );
}
void SSD13x6_SetMuxRatio( struct SSD13x6_Device* DeviceHandle, uint8_t Ratio ) {
SSD13x6_WriteCommand( DeviceHandle, 0xA8 );
SSD13x6_WriteCommand( DeviceHandle, Ratio );
}
void SSD13x6_SetDisplayOffset( struct SSD13x6_Device* DeviceHandle, uint8_t Offset ) {
SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Display_Offset );
SSD13x6_WriteCommand( DeviceHandle, Offset );
}
void SSD13x6_SetDisplayStartLine( struct SSD13x6_Device* DeviceHandle, int Line ) {
SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Display_Start_Line + ( uint32_t ) ( Line & 0x1F ) );
}
void SSD13x6_SetContrast( struct SSD13x6_Device* DeviceHandle, uint8_t Contrast ) {
SSD13x6_WriteCommand( DeviceHandle, 0x81 );
SSD13x6_WriteCommand( DeviceHandle, Contrast );
}
void SSD13x6_EnableDisplayRAM( struct SSD13x6_Device* DeviceHandle ) {
SSD13x6_WriteCommand( DeviceHandle, 0xA4 );
}
void SSD13x6_DisableDisplayRAM( struct SSD13x6_Device* DeviceHandle ) {
SSD13x6_WriteCommand( DeviceHandle, 0xA5 );
}
void SSD13x6_SetInverted( struct SSD13x6_Device* DeviceHandle, bool Inverted ) {
SSD13x6_WriteCommand( DeviceHandle, Inverted ? 0xA7 : 0xA6 );
}
void SSD13x6_SetDisplayClocks( struct SSD13x6_Device* DeviceHandle, uint32_t DisplayClockDivider, uint32_t OSCFrequency ) {
DisplayClockDivider&= 0x0F;
OSCFrequency&= 0x0F;
SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Display_CLK );
SSD13x6_WriteCommand( DeviceHandle, ( ( OSCFrequency << 4 ) | DisplayClockDivider ) );
}
void SSD13x6_DisplayOn( struct SSD13x6_Device* DeviceHandle ) {
SSD13x6_WriteCommand( DeviceHandle, 0xAF );
}
void SSD13x6_DisplayOff( struct SSD13x6_Device* DeviceHandle ) {
SSD13x6_WriteCommand( DeviceHandle, 0xAE );
}
void SSD132x_ReMap( struct SSD13x6_Device* DeviceHandle ) {
SSD13x6_WriteCommand( DeviceHandle, 0xA0 );
SSD13x6_WriteCommand( DeviceHandle, DeviceHandle->ReMap );
}
void SSD13x6_SetDisplayAddressMode( struct SSD13x6_Device* DeviceHandle, SSD13x6_AddressMode AddressMode ) {
switch (DeviceHandle->Model) {
case SH1106:
// does not exist on SH1106
break;
case SSD1306:
SSD13x6_WriteCommand( DeviceHandle, 0x20 );
SSD13x6_WriteCommand( DeviceHandle, AddressMode );
break;
case SSD1326:
DeviceHandle->ReMap = (AddressMode == AddressMode_Horizontal) ? (DeviceHandle->ReMap & ~0x80) : (DeviceHandle->ReMap | 0x80);
SSD132x_ReMap(DeviceHandle);
break;
}
}
void SSD13x6_Update( struct SSD13x6_Device* DeviceHandle ) {
if (DeviceHandle->Model == SH1106) {
// SH1106 requires a page-by-page update and ahs no end Page/Column
for (int i = 0; i < DeviceHandle->Height / 8 ; i++) {
SSD13x6_SetPageAddress( DeviceHandle, i, 0);
SSD13x6_SetColumnAddress( DeviceHandle, 0, 0);
SSD13x6_WriteData( DeviceHandle, DeviceHandle->Framebuffer + i*DeviceHandle->Width, DeviceHandle->Width );
}
} else {
// others have an automatic counter and end Page/Column
SSD13x6_SetColumnAddress( DeviceHandle, 0, DeviceHandle->Width - 1);
SSD13x6_SetPageAddress( DeviceHandle, 0, DeviceHandle->Height / 8 - 1);
SSD13x6_WriteData( DeviceHandle, DeviceHandle->Framebuffer, DeviceHandle->FramebufferSize );
}
}
void SSD13x6_WriteRawData( struct SSD13x6_Device* DeviceHandle, uint8_t* Data, size_t DataLength ) {
NullCheck( Data, return );
DataLength = DataLength > DeviceHandle->FramebufferSize ? DeviceHandle->FramebufferSize : DataLength;
if ( DataLength > 0 ) SSD13x6_WriteData( DeviceHandle, Data, DataLength );
}
void SSD13x6_SetHFlip( struct SSD13x6_Device* DeviceHandle, bool On ) {
switch (DeviceHandle->Model) {
case SH1106:
case SSD1306:
SSD13x6_WriteCommand( DeviceHandle, On ? 0xA1 : 0xA0 );
break;
case SSD1326:
DeviceHandle->ReMap = On ? (DeviceHandle->ReMap | 0x01) : (DeviceHandle->ReMap & ~0x01);
SSD132x_ReMap(DeviceHandle);
break;
}
}
void SSD13x6_SetVFlip( struct SSD13x6_Device* DeviceHandle, bool On ) {
switch (DeviceHandle->Model) {
case SH1106:
case SSD1306:
SSD13x6_WriteCommand( DeviceHandle, On ? 0xC8 : 0xC0 );
break;
case SSD1326:
DeviceHandle->ReMap = On ? (DeviceHandle->ReMap | 0x05) : (DeviceHandle->ReMap & ~0x05);
SSD132x_ReMap( DeviceHandle );
break;
}
}
void SSD13x6_SetColumnAddress( struct SSD13x6_Device* DeviceHandle, uint8_t Start, uint8_t End ) {
CheckBounds( Start > SSD13x6_Max_Col, return );
CheckBounds( End > SSD13x6_Max_Col, return );
// on SH1106, there is no "end column"
if (DeviceHandle->Model == SH1106) {
// well, unfortunately this driver is 132 colums but most displays are 128...
if (DeviceHandle->Width != 132) Start += 2;
SSD13x6_WriteCommand( DeviceHandle, 0x10 | (Start >> 4) );
SSD13x6_WriteCommand( DeviceHandle, 0x00 | (Start & 0x0f) );
} else {
SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Column_Address );
SSD13x6_WriteCommand( DeviceHandle, Start );
SSD13x6_WriteCommand( DeviceHandle, End );
}
}
void SSD13x6_SetPageAddress( struct SSD13x6_Device* DeviceHandle, uint8_t Start, uint8_t End ) {
NullCheck( DeviceHandle, return );
CheckBounds( Start > SSD13x6_Max_Row, return );
CheckBounds( End > SSD13x6_Max_Row, return );
// on SH1106, there is no "end page"
if (DeviceHandle->Model == SH1106) {
SSD13x6_WriteCommand( DeviceHandle, 0xB0 | Start );
} else {
// in case of SSD1326, this is sub-optimal as it can address by line, not by page
if (DeviceHandle->Model != SSD1306) {
Start *= 8;
End = (End + 1) * 8 - 1;
}
SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Page_Address );
SSD13x6_WriteCommand( DeviceHandle, Start );
SSD13x6_WriteCommand( DeviceHandle, End );
}
}
bool SSD13x6_HWReset( struct SSD13x6_Device* DeviceHandle ) {
NullCheck( DeviceHandle, return 0 );
if ( DeviceHandle->Reset != NULL ) {
return ( DeviceHandle->Reset ) ( DeviceHandle );
}
/* This should always return true if there is no reset callback as
* no error would have occurred during the non existant reset.
*/
return true;
}
static bool SSD13x6_Init( struct SSD13x6_Device* DeviceHandle, int Width, int Height ) {
DeviceHandle->Width = Width;
DeviceHandle->Height = Height;
SSD13x6_HWReset( DeviceHandle );
SSD13x6_DisplayOff( DeviceHandle );
if (DeviceHandle->Model == SSD1306 || DeviceHandle->Model == SH1106) {
SSDCmd_Set_Display_Start_Line = 0x40;
SSDCmd_Set_Display_Offset = 0xD3;
SSDCmd_Set_Column_Address = 0x21,
SSDCmd_Set_Display_CLK = 0xD5;
SSDCmd_Set_Page_Address = 0x22;
SSD13x6_Max_Col = 127;
if (DeviceHandle->Model == SSD1306) {
// charge pump regulator, do direct init
SSD13x6_WriteCommand( DeviceHandle, 0x8D );
SSD13x6_WriteCommand( DeviceHandle, 0x14 );
// COM pins HW config (alternative:EN if 64, DIS if 32, remap:DIS) - some display might need something difference
SSD13x6_WriteCommand( DeviceHandle, 0xDA );
SSD13x6_WriteCommand( DeviceHandle, ((Height == 64 ? 1 : 0) << 4) | (0 < 5) );
} else {
// charge pump regulator, do direct init
SSD13x6_WriteCommand( DeviceHandle, 0xAD );
SSD13x6_WriteCommand( DeviceHandle, 0x8B );
// COM pins HW config (alternative:EN) - some display might need something difference
SSD13x6_WriteCommand( DeviceHandle, 0xDA );
SSD13x6_WriteCommand( DeviceHandle, 1 << 4);
}
} else if (DeviceHandle->Model == SSD1326) {
SSDCmd_Set_Display_Start_Line = 0xA1;
SSDCmd_Set_Display_Offset = 0xA2;
SSDCmd_Set_Column_Address = 0x15;
SSDCmd_Set_Display_CLK = 0xB3;
SSDCmd_Set_Page_Address = 0x75; // not really a page but a row
SSD13x6_Max_Col = 255;
// no gray scale
DeviceHandle->ReMap |= 0x10;
SSD132x_ReMap( DeviceHandle );
}
SSD13x6_SetMuxRatio( DeviceHandle, Height - 1 );
SSD13x6_SetDisplayOffset( DeviceHandle, 0x00 );
SSD13x6_SetDisplayStartLine( DeviceHandle, 0 );
SSD13x6_SetContrast( DeviceHandle, 0x7F );
SSD13x6_DisableDisplayRAM( DeviceHandle );
SSD13x6_SetVFlip( DeviceHandle, false );
SSD13x6_SetHFlip( DeviceHandle, false );
SSD13x6_SetInverted( DeviceHandle, false );
SSD13x6_SetDisplayClocks( DeviceHandle, 0, 8 );
SSD13x6_SetDisplayAddressMode( DeviceHandle, AddressMode_Horizontal );
SSD13x6_SetColumnAddress( DeviceHandle, 0, DeviceHandle->Width - 1 );
SSD13x6_SetPageAddress( DeviceHandle, 0, ( DeviceHandle->Height / 8 ) - 1 );
SSD13x6_EnableDisplayRAM( DeviceHandle );
SSD13x6_DisplayOn( DeviceHandle );
SSD13x6_Update( DeviceHandle );
return true;
}
bool SSD13x6_Init_I2C( struct SSD13x6_Device* DeviceHandle, int Width, int Height, int I2CAddress, int ResetPin, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset ) {
NullCheck( DeviceHandle, return false );
NullCheck( WriteCommand, return false );
NullCheck( WriteData, return false );
DeviceHandle->WriteCommand = WriteCommand;
DeviceHandle->WriteData = WriteData;
DeviceHandle->Reset = Reset;
DeviceHandle->Address = I2CAddress;
DeviceHandle->RSTPin = ResetPin;
DeviceHandle->FramebufferSize = ( Width * Height ) / 8;
DeviceHandle->Framebuffer = calloc( 1, DeviceHandle->FramebufferSize );
NullCheck( DeviceHandle->Framebuffer, return false );
return SSD13x6_Init( DeviceHandle, Width, Height );
}
bool SSD13x6_Init_SPI( struct SSD13x6_Device* DeviceHandle, int Width, int Height, int ResetPin, int CSPin, spi_device_handle_t SPIHandle, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset ) {
NullCheck( DeviceHandle, return false );
NullCheck( WriteCommand, return false );
NullCheck( WriteData, return false );
DeviceHandle->WriteCommand = WriteCommand;
DeviceHandle->WriteData = WriteData;
DeviceHandle->Reset = Reset;
DeviceHandle->SPIHandle = SPIHandle;
DeviceHandle->RSTPin = ResetPin;
DeviceHandle->CSPin = CSPin;
DeviceHandle->FramebufferSize = ( Width * Height ) / 8;
DeviceHandle->Framebuffer = heap_caps_calloc( 1, DeviceHandle->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
NullCheck( DeviceHandle->Framebuffer, return false );
return SSD13x6_Init( DeviceHandle, Width, Height );
}

View File

@@ -0,0 +1,99 @@
#ifndef _SSD13X6_H_
#define _SSD13X6_H_
/* For uint(X)_t */
#include <stdint.h>
/* For booooool */
#include <stdbool.h>
#include "sdkconfig.h"
#include "ssd13x6_err.h"
#define SSD_ALWAYS_INLINE __attribute__( ( always_inline ) )
#define CAPS_COLUMN_RANGE 0x01
#define CAPS_PAGE_RANGE 0x02
#define CAPS_ADDRESS_VERTICAL 0x04
#if ! defined BIT
#define BIT( n ) ( 1 << n )
#endif
typedef uint8_t SSDCmd;
typedef enum {
AddressMode_Horizontal = 0,
AddressMode_Vertical,
AddressMode_Page,
AddressMode_Invalid
} SSD13x6_AddressMode;
struct SSD13x6_Device;
/*
* These can optionally return a succeed/fail but are as of yet unused in the driver.
*/
typedef bool ( *WriteCommandProc ) ( struct SSD13x6_Device* DeviceHandle, SSDCmd Command );
typedef bool ( *WriteDataProc ) ( struct SSD13x6_Device* DeviceHandle, const uint8_t* Data, size_t DataLength );
typedef bool ( *ResetProc ) ( struct SSD13x6_Device* DeviceHandle );
struct spi_device_t;
typedef struct spi_device_t* spi_device_handle_t;
struct SSD13x6_FontDef;
struct SSD13x6_Device {
/* I2C Specific */
int Address;
/* SPI Specific */
spi_device_handle_t SPIHandle;
int RSTPin;
int CSPin;
/* Everything else */
int Width;
int Height;
enum { SSD1306, SSD1326, SH1106 } Model;
uint8_t ReMap;
uint8_t* Framebuffer;
int FramebufferSize;
WriteCommandProc WriteCommand;
WriteDataProc WriteData;
ResetProc Reset;
const struct SSD13x6_FontDef* Font;
bool FontForceProportional;
bool FontForceMonospace;
};
void SSD13x6_SetMuxRatio( struct SSD13x6_Device* DeviceHandle, uint8_t Ratio );
void SSD13x6_SetDisplayOffset( struct SSD13x6_Device* DeviceHandle, uint8_t Offset );
void SSD13x6_SetDisplayStartLines( struct SSD13x6_Device* DeviceHandle );
void SSD13x6_SetSegmentRemap( struct SSD13x6_Device* DeviceHandle, bool Remap );
void SSD13x6_SetContrast( struct SSD13x6_Device* DeviceHandle, uint8_t Contrast );
void SSD13x6_EnableDisplayRAM( struct SSD13x6_Device* DeviceHandle );
void SSD13x6_DisableDisplayRAM( struct SSD13x6_Device* DeviceHandle );
void SSD13x6_SetInverted( struct SSD13x6_Device* DeviceHandle, bool Inverted );
void SSD13x6_SetHFlip( struct SSD13x6_Device* DeviceHandle, bool On );
void SSD13x6_SetVFlip( struct SSD13x6_Device* DeviceHandle, bool On );
void SSD13x6_DisplayOn( struct SSD13x6_Device* DeviceHandle );
void SSD13x6_DisplayOff( struct SSD13x6_Device* DeviceHandle );
void SSD13x6_SetDisplayAddressMode( struct SSD13x6_Device* DeviceHandle, SSD13x6_AddressMode AddressMode );
void SSD13x6_Update( struct SSD13x6_Device* DeviceHandle );
void SSD13x6_SetDisplayClocks( struct SSD13x6_Device* DeviceHandle, uint32_t DisplayClockDivider, uint32_t OSCFrequency );
void SSD13x6_SetColumnAddress( struct SSD13x6_Device* DeviceHandle, uint8_t Start, uint8_t End );
void SSD13x6_SetPageAddress( struct SSD13x6_Device* DeviceHandle, uint8_t Start, uint8_t End );
bool SSD13x6_HWReset( struct SSD13x6_Device* DeviceHandle );
bool SSD13x6_Init_I2C( struct SSD13x6_Device* DeviceHandle, int Width, int Height, int I2CAddress, int ResetPin, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset );
bool SSD13x6_Init_SPI( struct SSD13x6_Device* DeviceHandle, int Width, int Height, int ResetPin, int CSPin, spi_device_handle_t SPIHandle, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset );
int SSD13x6_GetCaps( struct SSD13x6_Device* DeviceHandle );
void SSD13x6_WriteRawData( struct SSD13x6_Device* DeviceHandle, uint8_t* Data, size_t DataLength );
#endif

View File

@@ -0,0 +1,18 @@
#ifndef _SSD13x6_DEFAULT_IF_H_
#define _SSD13x6_DEFAULT_IF_H_
#ifdef __cplusplus
extern "C" {
#endif
bool SSD13x6_I2CMasterInitDefault( int PortNumber, int SDA, int SCL );
bool SSD13x6_I2CMasterAttachDisplayDefault( struct SSD13x6_Device* DisplayHandle, int Model, int Width, int Height, int I2CAddress, int RSTPin );
bool SSD13x6_SPIMasterInitDefault( int SPI, int DC);
bool SSD13x6_SPIMasterAttachDisplayDefault( struct SSD13x6_Device* DeviceHandle, int Model, int Width, int Height, int CSPin, int RSTPin, int Speed );
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -13,10 +13,10 @@
#include <math.h> #include <math.h>
#include <esp_attr.h> #include <esp_attr.h>
#include "ssd1306.h" #include "ssd13x6.h"
#include "ssd1306_draw.h" #include "ssd13x6_draw.h"
__attribute__( ( always_inline ) ) static inline bool IsPixelVisible( struct SSD1306_Device* DeviceHandle, int x, int y ) { __attribute__( ( always_inline ) ) static inline bool IsPixelVisible( struct SSD13x6_Device* DeviceHandle, int x, int y ) {
bool Result = ( bool Result = (
( x >= 0 ) && ( x >= 0 ) &&
( x < DeviceHandle->Width ) && ( x < DeviceHandle->Width ) &&
@@ -24,7 +24,7 @@ __attribute__( ( always_inline ) ) static inline bool IsPixelVisible( struct SSD
( y < DeviceHandle->Height ) ( y < DeviceHandle->Height )
) ? true : false; ) ? true : false;
#if CONFIG_SSD1306_CLIPDEBUG > 0 #if CONFIG_SSD13x6_CLIPDEBUG > 0
if ( Result == false ) { if ( Result == false ) {
ClipDebug( x, y ); ClipDebug( x, y );
} }
@@ -40,7 +40,7 @@ __attribute__( ( always_inline ) ) static inline void SwapInt( int* a, int* b )
*a = Temp; *a = Temp;
} }
inline void IRAM_ATTR SSD1306_DrawPixelFast( struct SSD1306_Device* DeviceHandle, int X, int Y, int Color ) { inline void IRAM_ATTR SSD13x6_DrawPixelFast( struct SSD13x6_Device* DeviceHandle, int X, int Y, int Color ) {
uint32_t YBit = ( Y & 0x07 ); uint32_t YBit = ( Y & 0x07 );
uint8_t* FBOffset = NULL; uint8_t* FBOffset = NULL;
@@ -61,15 +61,15 @@ inline void IRAM_ATTR SSD1306_DrawPixelFast( struct SSD1306_Device* DeviceHandle
} }
} }
void IRAM_ATTR SSD1306_DrawPixel( struct SSD1306_Device* DeviceHandle, int x, int y, int Color ) { void IRAM_ATTR SSD13x6_DrawPixel( struct SSD13x6_Device* DeviceHandle, int x, int y, int Color ) {
NullCheck( DeviceHandle, return ); NullCheck( DeviceHandle, return );
if ( IsPixelVisible( DeviceHandle, x, y ) == true ) { if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {
SSD1306_DrawPixelFast( DeviceHandle, x, y, Color ); SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color );
} }
} }
void IRAM_ATTR SSD1306_DrawHLine( struct SSD1306_Device* DeviceHandle, int x, int y, int Width, int Color ) { void IRAM_ATTR SSD13x6_DrawHLine( struct SSD13x6_Device* DeviceHandle, int x, int y, int Width, int Color ) {
int XEnd = x + Width; int XEnd = x + Width;
NullCheck( DeviceHandle, return ); NullCheck( DeviceHandle, return );
@@ -77,14 +77,14 @@ void IRAM_ATTR SSD1306_DrawHLine( struct SSD1306_Device* DeviceHandle, int x, in
for ( ; x <= XEnd; x++ ) { for ( ; x <= XEnd; x++ ) {
if ( IsPixelVisible( DeviceHandle, x, y ) == true ) { if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {
SSD1306_DrawPixelFast( DeviceHandle, x, y, Color ); SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color );
} else { } else {
break; break;
} }
} }
} }
void IRAM_ATTR SSD1306_DrawVLine( struct SSD1306_Device* DeviceHandle, int x, int y, int Height, int Color ) { void IRAM_ATTR SSD13x6_DrawVLine( struct SSD13x6_Device* DeviceHandle, int x, int y, int Height, int Color ) {
int YEnd = y + Height; int YEnd = y + Height;
NullCheck( DeviceHandle, return ); NullCheck( DeviceHandle, return );
@@ -92,14 +92,14 @@ void IRAM_ATTR SSD1306_DrawVLine( struct SSD1306_Device* DeviceHandle, int x, in
for ( ; y <= YEnd; y++ ) { for ( ; y <= YEnd; y++ ) {
if ( IsPixelVisible( DeviceHandle, x, y ) == true ) { if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {
SSD1306_DrawPixel( DeviceHandle, x, y, Color ); SSD13x6_DrawPixel( DeviceHandle, x, y, Color );
} else { } else {
break; break;
} }
} }
} }
static inline void IRAM_ATTR DrawWideLine( struct SSD1306_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) { static inline void IRAM_ATTR DrawWideLine( struct SSD13x6_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) {
int dx = ( x1 - x0 ); int dx = ( x1 - x0 );
int dy = ( y1 - y0 ); int dy = ( y1 - y0 );
int Error = 0; int Error = 0;
@@ -116,7 +116,7 @@ static inline void IRAM_ATTR DrawWideLine( struct SSD1306_Device* DeviceHandle,
for ( ; x <= x1; x++ ) { for ( ; x <= x1; x++ ) {
if ( IsPixelVisible( DeviceHandle, x, y ) == true ) { if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {
SSD1306_DrawPixelFast( DeviceHandle, x, y, Color ); SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color );
} }
if ( Error > 0 ) { if ( Error > 0 ) {
@@ -128,7 +128,7 @@ static inline void IRAM_ATTR DrawWideLine( struct SSD1306_Device* DeviceHandle,
} }
} }
static inline void IRAM_ATTR DrawTallLine( struct SSD1306_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) { static inline void IRAM_ATTR DrawTallLine( struct SSD13x6_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) {
int dx = ( x1 - x0 ); int dx = ( x1 - x0 );
int dy = ( y1 - y0 ); int dy = ( y1 - y0 );
int Error = 0; int Error = 0;
@@ -145,7 +145,7 @@ static inline void IRAM_ATTR DrawTallLine( struct SSD1306_Device* DeviceHandle,
for ( ; y < y1; y++ ) { for ( ; y < y1; y++ ) {
if ( IsPixelVisible( DeviceHandle, x, y ) == true ) { if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {
SSD1306_DrawPixelFast( DeviceHandle, x, y, Color ); SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color );
} }
if ( Error > 0 ) { if ( Error > 0 ) {
@@ -157,14 +157,14 @@ static inline void IRAM_ATTR DrawTallLine( struct SSD1306_Device* DeviceHandle,
} }
} }
void IRAM_ATTR SSD1306_DrawLine( struct SSD1306_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) { void IRAM_ATTR SSD13x6_DrawLine( struct SSD13x6_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) {
NullCheck( DeviceHandle, return ); NullCheck( DeviceHandle, return );
NullCheck( DeviceHandle->Framebuffer, return ); NullCheck( DeviceHandle->Framebuffer, return );
if ( x0 == x1 ) { if ( x0 == x1 ) {
SSD1306_DrawVLine( DeviceHandle, x0, y0, ( y1 - y0 ), Color ); SSD13x6_DrawVLine( DeviceHandle, x0, y0, ( y1 - y0 ), Color );
} else if ( y0 == y1 ) { } else if ( y0 == y1 ) {
SSD1306_DrawHLine( DeviceHandle, x0, y0, ( x1 - x0 ), Color ); SSD13x6_DrawHLine( DeviceHandle, x0, y0, ( x1 - x0 ), Color );
} else { } else {
if ( abs( x1 - x0 ) > abs( y1 - y0 ) ) { if ( abs( x1 - x0 ) > abs( y1 - y0 ) ) {
/* Wide ( run > rise ) */ /* Wide ( run > rise ) */
@@ -186,7 +186,7 @@ void IRAM_ATTR SSD1306_DrawLine( struct SSD1306_Device* DeviceHandle, int x0, in
} }
} }
void IRAM_ATTR SSD1306_DrawBox( struct SSD1306_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color, bool Fill ) { void IRAM_ATTR SSD13x6_DrawBox( struct SSD13x6_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color, bool Fill ) {
int Width = ( x2 - x1 ); int Width = ( x2 - x1 );
int Height = ( y2 - y1 ); int Height = ( y2 - y1 );
@@ -195,25 +195,25 @@ void IRAM_ATTR SSD1306_DrawBox( struct SSD1306_Device* DeviceHandle, int x1, int
if ( Fill == false ) { if ( Fill == false ) {
/* Top side */ /* Top side */
SSD1306_DrawHLine( DeviceHandle, x1, y1, Width, Color ); SSD13x6_DrawHLine( DeviceHandle, x1, y1, Width, Color );
/* Bottom side */ /* Bottom side */
SSD1306_DrawHLine( DeviceHandle, x1, y1 + Height, Width, Color ); SSD13x6_DrawHLine( DeviceHandle, x1, y1 + Height, Width, Color );
/* Left side */ /* Left side */
SSD1306_DrawVLine( DeviceHandle, x1, y1, Height, Color ); SSD13x6_DrawVLine( DeviceHandle, x1, y1, Height, Color );
/* Right side */ /* Right side */
SSD1306_DrawVLine( DeviceHandle, x1 + Width, y1, Height, Color ); SSD13x6_DrawVLine( DeviceHandle, x1 + Width, y1, Height, Color );
} else { } else {
/* Fill the box by drawing horizontal lines */ /* Fill the box by drawing horizontal lines */
for ( ; y1 <= y2; y1++ ) { for ( ; y1 <= y2; y1++ ) {
SSD1306_DrawHLine( DeviceHandle, x1, y1, Width, Color ); SSD13x6_DrawHLine( DeviceHandle, x1, y1, Width, Color );
} }
} }
} }
void SSD1306_Clear( struct SSD1306_Device* DeviceHandle, int Color ) { void SSD13x6_Clear( struct SSD13x6_Device* DeviceHandle, int Color ) {
NullCheck( DeviceHandle, return ); NullCheck( DeviceHandle, return );
NullCheck( DeviceHandle->Framebuffer, return ); NullCheck( DeviceHandle->Framebuffer, return );

View File

@@ -1,5 +1,5 @@
#ifndef _SSD1306_DRAW_H_ #ifndef _SSD13x6_DRAW_H_
#define _SSD1306_DRAW_H_ #define _SSD13x6_DRAW_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -7,23 +7,23 @@ extern "C" {
#include "sdkconfig.h" #include "sdkconfig.h"
#define SSD1306_CLIPDEBUG_NONE 0 #define SSD13x6_CLIPDEBUG_NONE 0
#define SSD1306_CLIPDEBUG_WARNING 1 #define SSD13x6_CLIPDEBUG_WARNING 1
#define SSD1306_CLIPDEBUG_ERROR 2 #define SSD13x6_CLIPDEBUG_ERROR 2
#if CONFIG_SSD1306_CLIPDEBUG == SSD1306_CLIPDEBUG_NONE #if CONFIG_SSD13x6_CLIPDEBUG == SSD13x6_CLIPDEBUG_NONE
/* /*
* Clip silently with no console output. * Clip silently with no console output.
*/ */
#define ClipDebug( x, y ) #define ClipDebug( x, y )
#elif CONFIG_SSD1306_CLIPDEBUG == SSD1306_CLIPDEBUG_WARNING #elif CONFIG_SSD13x6_CLIPDEBUG == SSD13x6_CLIPDEBUG_WARNING
/* /*
* Log clipping to the console as a warning. * Log clipping to the console as a warning.
*/ */
#define ClipDebug( x, y ) { \ #define ClipDebug( x, y ) { \
ESP_LOGW( __FUNCTION__, "Line %d: Pixel at %d, %d CLIPPED", __LINE__, x, y ); \ ESP_LOGW( __FUNCTION__, "Line %d: Pixel at %d, %d CLIPPED", __LINE__, x, y ); \
} }
#elif CONFIG_SSD1306_CLIPDEBUG == SSD1306_CLIPDEBUG_ERROR #elif CONFIG_SSD13x6_CLIPDEBUG == SSD13x6_CLIPDEBUG_ERROR
/* /*
* Log clipping as an error to the console. * Log clipping as an error to the console.
* Also invokes an abort with stack trace. * Also invokes an abort with stack trace.
@@ -38,13 +38,13 @@ extern "C" {
#define SSD_COLOR_WHITE 1 #define SSD_COLOR_WHITE 1
#define SSD_COLOR_XOR 2 #define SSD_COLOR_XOR 2
void SSD1306_Clear( struct SSD1306_Device* DeviceHandle, int Color ); void SSD13x6_Clear( struct SSD13x6_Device* DeviceHandle, int Color );
void SSD1306_DrawPixel( struct SSD1306_Device* DeviceHandle, int X, int Y, int Color ); void SSD13x6_DrawPixel( struct SSD13x6_Device* DeviceHandle, int X, int Y, int Color );
void SSD1306_DrawPixelFast( struct SSD1306_Device* DeviceHandle, int X, int Y, int Color ); void SSD13x6_DrawPixelFast( struct SSD13x6_Device* DeviceHandle, int X, int Y, int Color );
void SSD1306_DrawHLine( struct SSD1306_Device* DeviceHandle, int x, int y, int Width, int Color ); void SSD13x6_DrawHLine( struct SSD13x6_Device* DeviceHandle, int x, int y, int Width, int Color );
void SSD1306_DrawVLine( struct SSD1306_Device* DeviceHandle, int x, int y, int Height, int Color ); void SSD13x6_DrawVLine( struct SSD13x6_Device* DeviceHandle, int x, int y, int Height, int Color );
void SSD1306_DrawLine( struct SSD1306_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ); void SSD13x6_DrawLine( struct SSD13x6_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color );
void SSD1306_DrawBox( struct SSD1306_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color, bool Fill ); void SSD13x6_DrawBox( struct SSD13x6_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color, bool Fill );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -1,15 +1,15 @@
#ifndef _SSD1306_ERR_H_ #ifndef _SSD13x6_ERR_H_
#define _SSD1306_ERR_H_ #define _SSD13x6_ERR_H_
#include <esp_log.h> #include <esp_log.h>
#define SSD1306_DoAbort( ) #define SSD13x6_DoAbort( )
#if ! defined NullCheck #if ! defined NullCheck
#define NullCheck( ptr, retexpr ) { \ #define NullCheck( ptr, retexpr ) { \
if ( ptr == NULL ) { \ if ( ptr == NULL ) { \
ESP_LOGE( __FUNCTION__, "%s == NULL", #ptr ); \ ESP_LOGE( __FUNCTION__, "%s == NULL", #ptr ); \
SSD1306_DoAbort( ); \ SSD13x6_DoAbort( ); \
retexpr; \ retexpr; \
} \ } \
} }
@@ -20,7 +20,7 @@
esp_err_t __err_rc = ( expr ); \ esp_err_t __err_rc = ( expr ); \
if ( __err_rc != ESP_OK ) { \ if ( __err_rc != ESP_OK ) { \
ESP_LOGE( __FUNCTION__, "%s != ESP_OK, result: %d", #expr, __err_rc ); \ ESP_LOGE( __FUNCTION__, "%s != ESP_OK, result: %d", #expr, __err_rc ); \
SSD1306_DoAbort( ); \ SSD13x6_DoAbort( ); \
retexpr; \ retexpr; \
} \ } \
} }
@@ -30,7 +30,7 @@
#define CheckBounds( expr, retexpr ) { \ #define CheckBounds( expr, retexpr ) { \
if ( expr ) { \ if ( expr ) { \
ESP_LOGE( __FUNCTION__, "Line %d: %s", __LINE__, #expr ); \ ESP_LOGE( __FUNCTION__, "Line %d: %s", __LINE__, #expr ); \
SSD1306_DoAbort( ); \ SSD13x6_DoAbort( ); \
retexpr; \ retexpr; \
} \ } \
} }

View File

@@ -9,11 +9,11 @@
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <math.h> #include <math.h>
#include "ssd1306.h" #include "ssd13x6.h"
#include "ssd1306_draw.h" #include "ssd13x6_draw.h"
#include "ssd1306_font.h" #include "ssd13x6_font.h"
static int RoundUpFontHeight( const struct SSD1306_FontDef* Font ) { static int RoundUpFontHeight( const struct SSD13x6_FontDef* Font ) {
int Height = Font->Height; int Height = Font->Height;
if ( ( Height % 8 ) != 0 ) { if ( ( Height % 8 ) != 0 ) {
@@ -23,11 +23,11 @@ static int RoundUpFontHeight( const struct SSD1306_FontDef* Font ) {
return Height; return Height;
} }
static const uint8_t* GetCharPtr( const struct SSD1306_FontDef* Font, char Character ) { static const uint8_t* GetCharPtr( const struct SSD13x6_FontDef* Font, char Character ) {
return &Font->FontData[ ( Character - Font->StartChar ) * ( ( Font->Width * ( RoundUpFontHeight( Font ) / 8 ) ) + 1 ) ]; return &Font->FontData[ ( Character - Font->StartChar ) * ( ( Font->Width * ( RoundUpFontHeight( Font ) / 8 ) ) + 1 ) ];
} }
void SSD1306_FontDrawChar( struct SSD1306_Device* DisplayHandle, char Character, int x, int y, int Color ) { void SSD13x6_FontDrawChar( struct SSD13x6_Device* DisplayHandle, char Character, int x, int y, int Color ) {
const uint8_t* GlyphData = NULL; const uint8_t* GlyphData = NULL;
int GlyphColumnLen = 0; int GlyphColumnLen = 0;
int CharStartX = 0; int CharStartX = 0;
@@ -52,8 +52,8 @@ void SSD1306_FontDrawChar( struct SSD1306_Device* DisplayHandle, char Character,
GlyphData++; GlyphData++;
GlyphColumnLen = RoundUpFontHeight( DisplayHandle->Font ) / 8; GlyphColumnLen = RoundUpFontHeight( DisplayHandle->Font ) / 8;
CharWidth = SSD1306_FontGetCharWidth( DisplayHandle, Character ); CharWidth = SSD13x6_FontGetCharWidth( DisplayHandle, Character );
CharHeight = SSD1306_FontGetHeight( DisplayHandle ); CharHeight = SSD13x6_FontGetHeight( DisplayHandle );
CharStartX = x; CharStartX = x;
CharStartY = y; CharStartY = y;
@@ -89,7 +89,7 @@ void SSD1306_FontDrawChar( struct SSD1306_Device* DisplayHandle, char Character,
YBit = ( i + OffsetY ) & 0x07; YBit = ( i + OffsetY ) & 0x07;
if ( GlyphData[ YByte ] & BIT( YBit ) ) { if ( GlyphData[ YByte ] & BIT( YBit ) ) {
SSD1306_DrawPixel( DisplayHandle, x, y, Color ); SSD13x6_DrawPixel( DisplayHandle, x, y, Color );
} }
} }
@@ -98,7 +98,7 @@ void SSD1306_FontDrawChar( struct SSD1306_Device* DisplayHandle, char Character,
} }
} }
bool SSD1306_SetFont( struct SSD1306_Device* Display, const struct SSD1306_FontDef* Font ) { bool SSD13x6_SetFont( struct SSD13x6_Device* Display, const struct SSD13x6_FontDef* Font ) {
NullCheck( Display, return false ); NullCheck( Display, return false );
NullCheck( Font, return false ); NullCheck( Font, return false );
@@ -109,35 +109,35 @@ bool SSD1306_SetFont( struct SSD1306_Device* Display, const struct SSD1306_FontD
return true; return true;
} }
void SSD1306_FontForceProportional( struct SSD1306_Device* Display, bool Force ) { void SSD13x6_FontForceProportional( struct SSD13x6_Device* Display, bool Force ) {
NullCheck( Display, return ); NullCheck( Display, return );
NullCheck( Display->Font, return ); NullCheck( Display->Font, return );
Display->FontForceProportional = Force; Display->FontForceProportional = Force;
} }
void SSD1306_FontForceMonospace( struct SSD1306_Device* Display, bool Force ) { void SSD13x6_FontForceMonospace( struct SSD13x6_Device* Display, bool Force ) {
NullCheck( Display, return ); NullCheck( Display, return );
NullCheck( Display->Font, return ); NullCheck( Display->Font, return );
Display->FontForceMonospace = Force; Display->FontForceMonospace = Force;
} }
int SSD1306_FontGetWidth( struct SSD1306_Device* Display ) { int SSD13x6_FontGetWidth( struct SSD13x6_Device* Display ) {
NullCheck( Display, return 0 ); NullCheck( Display, return 0 );
NullCheck( Display->Font, return 0 ); NullCheck( Display->Font, return 0 );
return Display->Font->Width; return Display->Font->Width;
} }
int SSD1306_FontGetHeight( struct SSD1306_Device* Display ) { int SSD13x6_FontGetHeight( struct SSD13x6_Device* Display ) {
NullCheck( Display, return 0 ); NullCheck( Display, return 0 );
NullCheck( Display->Font, return 0 ); NullCheck( Display->Font, return 0 );
return Display->Font->Height; return Display->Font->Height;
} }
int SSD1306_FontGetCharWidth( struct SSD1306_Device* Display, char Character ) { int SSD13x6_FontGetCharWidth( struct SSD13x6_Device* Display, char Character ) {
const uint8_t* CharPtr = NULL; const uint8_t* CharPtr = NULL;
int Width = 0; int Width = 0;
@@ -161,28 +161,28 @@ int SSD1306_FontGetCharWidth( struct SSD1306_Device* Display, char Character ) {
return Width; return Width;
} }
int SSD1306_FontGetMaxCharsPerRow( struct SSD1306_Device* Display ) { int SSD13x6_FontGetMaxCharsPerRow( struct SSD13x6_Device* Display ) {
NullCheck( Display, return 0 ); NullCheck( Display, return 0 );
NullCheck( Display->Font, return 0 ); NullCheck( Display->Font, return 0 );
return Display->Width / Display->Font->Width; return Display->Width / Display->Font->Width;
} }
int SSD1306_FontGetMaxCharsPerColumn( struct SSD1306_Device* Display ) { int SSD13x6_FontGetMaxCharsPerColumn( struct SSD13x6_Device* Display ) {
NullCheck( Display, return 0 ); NullCheck( Display, return 0 );
NullCheck( Display->Font, return 0 ); NullCheck( Display->Font, return 0 );
return Display->Height / Display->Font->Height; return Display->Height / Display->Font->Height;
} }
int SSD1306_FontGetCharHeight( struct SSD1306_Device* Display ) { int SSD13x6_FontGetCharHeight( struct SSD13x6_Device* Display ) {
NullCheck( Display, return 0 ); NullCheck( Display, return 0 );
NullCheck( Display->Font, return 0 ); NullCheck( Display->Font, return 0 );
return Display->Font->Height; return Display->Font->Height;
} }
int SSD1306_FontMeasureString( struct SSD1306_Device* Display, const char* Text ) { int SSD13x6_FontMeasureString( struct SSD13x6_Device* Display, const char* Text ) {
int Width = 0; int Width = 0;
int Len = 0; int Len = 0;
@@ -192,14 +192,14 @@ int SSD1306_FontMeasureString( struct SSD1306_Device* Display, const char* Text
for ( Len = strlen( Text ); Len >= 0; Len--, Text++ ) { for ( Len = strlen( Text ); Len >= 0; Len--, Text++ ) {
if ( *Text >= Display->Font->StartChar && *Text <= Display->Font->EndChar ) { if ( *Text >= Display->Font->StartChar && *Text <= Display->Font->EndChar ) {
Width+= SSD1306_FontGetCharWidth( Display, *Text ); Width+= SSD13x6_FontGetCharWidth( Display, *Text );
} }
} }
return Width; return Width;
} }
void SSD1306_FontDrawString( struct SSD1306_Device* Display, int x, int y, const char* Text, int Color ) { void SSD13x6_FontDrawString( struct SSD13x6_Device* Display, int x, int y, const char* Text, int Color ) {
int Len = 0; int Len = 0;
int i = 0; int i = 0;
@@ -208,25 +208,25 @@ void SSD1306_FontDrawString( struct SSD1306_Device* Display, int x, int y, const
NullCheck( Text, return ); NullCheck( Text, return );
for ( Len = strlen( Text ), i = 0; i < Len; i++ ) { for ( Len = strlen( Text ), i = 0; i < Len; i++ ) {
SSD1306_FontDrawChar( Display, *Text, x, y, Color ); SSD13x6_FontDrawChar( Display, *Text, x, y, Color );
x+= SSD1306_FontGetCharWidth( Display, *Text ); x+= SSD13x6_FontGetCharWidth( Display, *Text );
Text++; Text++;
} }
} }
void SSD1306_FontDrawAnchoredString( struct SSD1306_Device* Display, TextAnchor Anchor, const char* Text, int Color ) { void SSD13x6_FontDrawAnchoredString( struct SSD13x6_Device* Display, TextAnchor Anchor, const char* Text, int Color ) {
int x = 0; int x = 0;
int y = 0; int y = 0;
NullCheck( Display, return ); NullCheck( Display, return );
NullCheck( Text, return ); NullCheck( Text, return );
SSD1306_FontGetAnchoredStringCoords( Display, &x, &y, Anchor, Text ); SSD13x6_FontGetAnchoredStringCoords( Display, &x, &y, Anchor, Text );
SSD1306_FontDrawString( Display, x, y, Text, Color ); SSD13x6_FontDrawString( Display, x, y, Text, Color );
} }
void SSD1306_FontGetAnchoredStringCoords( struct SSD1306_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text ) { void SSD13x6_FontGetAnchoredStringCoords( struct SSD13x6_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text ) {
int StringWidth = 0; int StringWidth = 0;
int StringHeight = 0; int StringHeight = 0;
@@ -235,8 +235,8 @@ void SSD1306_FontGetAnchoredStringCoords( struct SSD1306_Device* Display, int* O
NullCheck( OutY, return ); NullCheck( OutY, return );
NullCheck( Text, return ); NullCheck( Text, return );
StringWidth = SSD1306_FontMeasureString( Display, Text ); StringWidth = SSD13x6_FontMeasureString( Display, Text );
StringHeight = SSD1306_FontGetCharHeight( Display ); StringHeight = SSD13x6_FontGetCharHeight( Display );
switch ( Anchor ) { switch ( Anchor ) {
case TextAnchor_East: { case TextAnchor_East: {

View File

@@ -0,0 +1,91 @@
#ifndef _SSD13x6_FONT_H_
#define _SSD13x6_FONT_H_
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
struct SSD13x6_Device;
/*
* X-GLCD Font format:
*
* First byte of glyph is it's width in pixels.
* Each data byte represents 8 pixels going down from top to bottom.
*
* Example glyph layout for a 16x16 font
* 'a': [Glyph width][Pixel column 0][Pixel column 1] where the number of pixel columns is the font height divided by 8
* 'b': [Glyph width][Pixel column 0][Pixel column 1]...
* 'c': And so on...
*/
struct SSD13x6_FontDef {
const uint8_t* FontData;
int Width;
int Height;
int StartChar;
int EndChar;
bool Monospace;
};
typedef enum {
TextAnchor_East = 0,
TextAnchor_West,
TextAnchor_North,
TextAnchor_South,
TextAnchor_NorthEast,
TextAnchor_NorthWest,
TextAnchor_SouthEast,
TextAnchor_SouthWest,
TextAnchor_Center
} TextAnchor;
bool SSD13x6_SetFont( struct SSD13x6_Device* Display, const struct SSD13x6_FontDef* Font );
void SSD13x6_FontForceProportional( struct SSD13x6_Device* Display, bool Force );
void SSD13x6_FontForceMonospace( struct SSD13x6_Device* Display, bool Force );
int SSD13x6_FontGetWidth( struct SSD13x6_Device* Display );
int SSD13x6_FontGetHeight( struct SSD13x6_Device* Display );
int SSD13x6_FontGetMaxCharsPerRow( struct SSD13x6_Device* Display );
int SSD13x6_FontGetMaxCharsPerColumn( struct SSD13x6_Device* Display );
int SSD13x6_FontGetCharWidth( struct SSD13x6_Device* Display, char Character );
int SSD13x6_FontGetCharHeight( struct SSD13x6_Device* Display );
int SSD13x6_FontMeasureString( struct SSD13x6_Device* Display, const char* Text );\
void SSD13x6_FontDrawChar( struct SSD13x6_Device* Display, char Character, int x, int y, int Color );
void SSD13x6_FontDrawString( struct SSD13x6_Device* Display, int x, int y, const char* Text, int Color );
void SSD13x6_FontDrawAnchoredString( struct SSD13x6_Device* Display, TextAnchor Anchor, const char* Text, int Color );
void SSD13x6_FontGetAnchoredStringCoords( struct SSD13x6_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text );
extern const struct SSD13x6_FontDef Font_droid_sans_fallback_11x13;
extern const struct SSD13x6_FontDef Font_droid_sans_fallback_15x17;
extern const struct SSD13x6_FontDef Font_droid_sans_fallback_24x28;
extern const struct SSD13x6_FontDef Font_droid_sans_mono_7x13;
extern const struct SSD13x6_FontDef Font_droid_sans_mono_13x24;
extern const struct SSD13x6_FontDef Font_droid_sans_mono_16x31;
extern const struct SSD13x6_FontDef Font_liberation_mono_9x15;
extern const struct SSD13x6_FontDef Font_liberation_mono_13x21;
extern const struct SSD13x6_FontDef Font_liberation_mono_17x30;
extern const struct SSD13x6_FontDef Font_Tarable7Seg_16x32;
extern const struct SSD13x6_FontDef Font_Tarable7Seg_32x64;
extern const struct SSD13x6_FontDef Font_line_1;
extern const struct SSD13x6_FontDef Font_line_2;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -9,7 +9,8 @@
#include <stdio.h> #include <stdio.h>
#include "esp_log.h" #include "esp_log.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include <driver/i2c.h> #include "driver/i2c.h"
#include "driver/spi_master.h"
#include "config.h" #include "config.h"
#include "accessors.h" #include "accessors.h"
#include "globdefs.h" #include "globdefs.h"
@@ -59,6 +60,31 @@ const i2c_config_t * config_i2c_get(int * i2c_port) {
return &i2c; return &i2c;
} }
/****************************************************************************************
*
*/
const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host) {
char *nvs_item, *p;
static spi_bus_config_t spi = {
.mosi_io_num = -1,
.sclk_io_num = -1,
.miso_io_num = -1,
.quadwp_io_num = -1,
.quadhd_io_num = -1
};
nvs_item = config_alloc_get(NVS_TYPE_STR, "spi_config");
if (nvs_item) {
if ((p = strcasestr(nvs_item, "data")) != NULL) spi.mosi_io_num = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(nvs_item, "clk")) != NULL) spi.sclk_io_num = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(nvs_item, "dc")) != NULL) spi_system_dc_gpio = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(nvs_item, "host")) != NULL) spi_system_host = atoi(strchr(p, '=') + 1);
free(nvs_item);
}
if(spi_host) *spi_host = spi_system_host;
return &spi;
}
/**************************************************************************************** /****************************************************************************************
* *
*/ */

View File

@@ -10,7 +10,9 @@
#include "esp_system.h" #include "esp_system.h"
#include "driver/i2c.h" #include "driver/i2c.h"
#include "driver/spi_master.h"
esp_err_t config_i2c_set(const i2c_config_t * config, int port); esp_err_t config_i2c_set(const i2c_config_t * config, int port);
const i2c_config_t * config_i2c_get(int * i2c_port); const i2c_config_t * config_i2c_get(int * i2c_port);
void parse_set_GPIO(void (*cb)(int gpio, char *value)); const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host);
void parse_set_GPIO(void (*cb)(int gpio, char *value));

View File

@@ -16,6 +16,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "driver/adc.h" #include "driver/adc.h"
#include "battery.h" #include "battery.h"
#include "config.h"
/* /*
There is a bug in esp32 which causes a spurious interrupt on gpio 36/39 when There is a bug in esp32 which causes a spurious interrupt on gpio 36/39 when
@@ -29,7 +30,8 @@
static const char *TAG = "battery"; static const char *TAG = "battery";
static struct { static struct {
float sum, avg; int channel;
float sum, avg, scale;
int count; int count;
TimerHandle_t timer; TimerHandle_t timer;
} battery; } battery;
@@ -37,37 +39,50 @@ static struct {
/**************************************************************************************** /****************************************************************************************
* *
*/ */
int battery_value_svc(void) { int battery_value_svc(void) {
return battery.avg; return battery.avg;
} }
/**************************************************************************************** /****************************************************************************************
* *
*/ */
#ifdef CONFIG_SQUEEZEAMP
static void battery_callback(TimerHandle_t xTimer) { static void battery_callback(TimerHandle_t xTimer) {
battery.sum += adc1_get_raw(battery.channel) * battery.scale / 4095.0;
battery.sum += adc1_get_raw(ADC1_CHANNEL_7) / 4095. * (10+174)/10. * 1.1;
if (++battery.count == 30) { if (++battery.count == 30) {
battery.avg = battery.sum / battery.count; battery.avg = battery.sum / battery.count;
battery.sum = battery.count = 0; battery.sum = battery.count = 0;
ESP_LOGI(TAG, "Voltage %.2fV", battery.avg); ESP_LOGI(TAG, "Voltage %.2fV", battery.avg);
} }
} }
#endif
/**************************************************************************************** /****************************************************************************************
* *
*/ */
void battery_svc_init(void) { void battery_svc_init(void) {
#ifdef CONFIG_SQUEEZEAMP battery.channel = CONFIG_BAT_CHANNEL;
ESP_LOGI(TAG, "Initializing battery"); #ifdef CONFIG_BAT_SCALE
battery.scale = atof(CONFIG_BAT_SCALE);
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_7, ADC_ATTEN_DB_0);
battery.timer = xTimerCreate("battery", BATTERY_TIMER / portTICK_RATE_MS, pdTRUE, NULL, battery_callback);
xTimerStart(battery.timer, portMAX_DELAY);
#endif #endif
#ifndef CONFIG_BAT_LOCKED
char *nvs_item = config_alloc_get_default(NVS_TYPE_STR, "bat_config", "n", 0);
if (nvs_item) {
char *p;
if ((p = strcasestr(nvs_item, "channel")) != NULL) battery.channel = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(nvs_item, "scale")) != NULL) battery.scale = atof(strchr(p, '=') + 1);
free(nvs_item);
}
#endif
if (battery.channel != -1) {
ESP_LOGI(TAG, "Battery measure channel: %u, scale %f", battery.channel, battery.scale);
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(battery.channel, ADC_ATTEN_DB_0);
battery.timer = xTimerCreate("battery", BATTERY_TIMER / portTICK_RATE_MS, pdTRUE, NULL, battery_callback);
xTimerStart(battery.timer, portMAX_DELAY);
} else {
ESP_LOGI(TAG, "No battery");
}
} }

View File

@@ -7,6 +7,5 @@
# please read the SDK documents if you need to do this. # please read the SDK documents if you need to do this.
# #
COMPONENT_SRCDIRS := . tarablessd1306 tarablessd1306/fonts tarablessd1306/ifaces COMPONENT_SRCDIRS := .
COMPONENT_ADD_INCLUDEDIRS := . COMPONENT_ADD_INCLUDEDIRS := .
COMPONENT_ADD_INCLUDEDIRS += ./tarablessd1306

View File

@@ -21,16 +21,17 @@
#pragma once #pragma once
#define I2C_SYSTEM_PORT 1 #define I2C_SYSTEM_PORT 1
#define SPI_SYSTEM_HOST SPI2_HOST
extern int i2c_system_port; extern int i2c_system_port;
extern int spi_system_host;
extern int spi_system_dc_gpio;
extern bool gpio36_39_used; extern bool gpio36_39_used;
#ifdef CONFIG_SQUEEZEAMP #ifdef CONFIG_SQUEEZEAMP
#define JACK_GPIO 34 #define ADAC dac_tas57xx
#define SPKFAULT_GPIO 2 // this requires a pull-up, so can't be >34 #elif defined(CONFIG_A1S)
#define LED_GREEN_GPIO 12 #define ADAC dac_a1s
#define LED_RED_GPIO 13
#else #else
#define LED_GREEN_GPIO CONFIG_LED_GREEN_GPIO #define ADAC dac_external
#define LED_RED_GPIO CONFIG_LED_RED_GPIO
#define JACK_GPIO CONFIG_JACK_GPIO
#endif #endif

View File

@@ -17,6 +17,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "led.h" #include "led.h"
#include "accessors.h"
#define MAX_LED 8 #define MAX_LED 8
#define BLOCKTIME 10 // up to portMAX_DELAY #define BLOCKTIME 10 // up to portMAX_DELAY
@@ -33,10 +34,15 @@ static struct led_s {
TimerHandle_t timer; TimerHandle_t timer;
} leds[MAX_LED]; } leds[MAX_LED];
void led_svc_init(void) { static struct {
ESP_LOGI(TAG, "Initializing led"); int gpio;
} int active;
} green = { CONFIG_LED_GREEN_GPIO, 0 },
red = { CONFIG_LED_RED_GPIO, 0 };
/****************************************************************************************
*
*/
static void vCallbackFunction( TimerHandle_t xTimer ) { static void vCallbackFunction( TimerHandle_t xTimer ) {
struct led_s *led = (struct led_s*) pvTimerGetTimerID (xTimer); struct led_s *led = (struct led_s*) pvTimerGetTimerID (xTimer);
@@ -53,6 +59,9 @@ static void vCallbackFunction( TimerHandle_t xTimer ) {
xTimerChangePeriod(xTimer, (led->on ? led->ontime : led->offtime) / portTICK_RATE_MS, BLOCKTIME); xTimerChangePeriod(xTimer, (led->on ? led->ontime : led->offtime) / portTICK_RATE_MS, BLOCKTIME);
} }
/****************************************************************************************
*
*/
bool led_blink_core(int idx, int ontime, int offtime, bool pushed) { bool led_blink_core(int idx, int ontime, int offtime, bool pushed) {
if (!leds[idx].gpio || leds[idx].gpio<0 ) return false; if (!leds[idx].gpio || leds[idx].gpio<0 ) return false;
@@ -99,6 +108,9 @@ bool led_blink_core(int idx, int ontime, int offtime, bool pushed) {
return true; return true;
} }
/****************************************************************************************
*
*/
bool led_unpush(int idx) { bool led_unpush(int idx) {
if (!leds[idx].gpio || leds[idx].gpio<0) return false; if (!leds[idx].gpio || leds[idx].gpio<0) return false;
@@ -108,6 +120,9 @@ bool led_unpush(int idx) {
return true; return true;
} }
/****************************************************************************************
*
*/
bool led_config(int idx, gpio_num_t gpio, int onstate) { bool led_config(int idx, gpio_num_t gpio, int onstate) {
if(gpio<0){ if(gpio<0){
ESP_LOGW(TAG,"LED GPIO not configured"); ESP_LOGW(TAG,"LED GPIO not configured");
@@ -127,6 +142,9 @@ bool led_config(int idx, gpio_num_t gpio, int onstate) {
return true; return true;
} }
/****************************************************************************************
*
*/
bool led_unconfig(int idx) { bool led_unconfig(int idx) {
if (idx >= MAX_LED) return false; if (idx >= MAX_LED) return false;
@@ -135,3 +153,36 @@ bool led_unconfig(int idx) {
return true; return true;
} }
/****************************************************************************************
*
*/
void set_led_gpio(int gpio, char *value) {
char *p;
if (strcasestr(value, "green")) {
green.gpio = gpio;
if ((p = strchr(value, ':')) != NULL) green.active = atoi(p + 1);
} else if (strcasestr(value, "red")) {
red.active = gpio;
if ((p = strchr(value, ':')) != NULL) red.active = atoi(p + 1);
}
}
void led_svc_init(void) {
#ifdef CONFIG_LED_GREEN_GPIO_LEVEL
green.active = CONFIG_LED_GREEN_GPIO_LEVEL;
#endif
#ifdef CONFIG_LED_RED_GPIO_LEVEL
red.active = CONFIG_LED_RED_GPIO_LEVEL;
#endif
#ifndef CONFIG_LED_LOCKED
parse_set_GPIO(set_led_gpio);
#endif
ESP_LOGI(TAG,"Configuring LEDs green:%d (active:%d), red:%d (active:%d)", green.gpio, green.active, red.gpio, red.active);
led_config(LED_GREEN, green.gpio, green.active);
led_config(LED_RED, red.gpio, red.active);
}

View File

@@ -21,17 +21,18 @@
#include "globdefs.h" #include "globdefs.h"
#include "config.h" #include "config.h"
#include "accessors.h" #include "accessors.h"
#include "accessors.h"
#define MONITOR_TIMER (10*1000) #define MONITOR_TIMER (10*1000)
static const char *TAG = "monitor"; static const char *TAG = "monitor";
static TimerHandle_t monitor_timer; static TimerHandle_t monitor_timer;
#ifdef JACK_GPIO
static int jack_gpio = JACK_GPIO; static struct {
#else int gpio;
static int jack_gpio = -1; int active;
#endif } jack = { CONFIG_JACK_GPIO, 0 },
spkfault = { CONFIG_SPKFAULT_GPIO, 0 };
void (*jack_handler_svc)(bool inserted); void (*jack_handler_svc)(bool inserted);
bool jack_inserted_svc(void); bool jack_inserted_svc(void);
@@ -62,8 +63,7 @@ static void jack_handler_default(void *id, button_event_e event, button_press_e
* *
*/ */
bool jack_inserted_svc (void) { bool jack_inserted_svc (void) {
if (jack_gpio != -1) return button_is_pressed(jack_gpio, NULL); return button_is_pressed(jack.gpio, NULL);
else return false;
} }
/**************************************************************************************** /****************************************************************************************
@@ -80,37 +80,30 @@ static void spkfault_handler_default(void *id, button_event_e event, button_pres
* *
*/ */
bool spkfault_svc (void) { bool spkfault_svc (void) {
#ifdef SPKFAULT_GPIO return button_is_pressed(spkfault.gpio, NULL);
return !gpio_get_level(SPKFAULT_GPIO);
#else
return false;
#endif
} }
/**************************************************************************************** /****************************************************************************************
* *
*/ */
void set_jack_gpio(int gpio, char *value) { void set_jack_gpio(int gpio, char *value) {
bool low = false; if (strcasestr(value, "jack")) {
char *p;
if (!strcasecmp(value, "jack_l")) { jack.gpio = gpio;
jack_gpio = gpio; if ((p = strchr(value, ':')) != NULL) jack.active = atoi(p + 1);
low = true;
} else if (!strcasecmp(value, "jack_h")) {
jack_gpio = gpio;
} }
}
if (jack_gpio != -1) { /****************************************************************************************
gpio_pad_select_gpio(jack_gpio); *
gpio_set_direction(jack_gpio, GPIO_MODE_INPUT); */
gpio_set_pull_mode(jack_gpio, low ? GPIO_PULLUP_ONLY : GPIO_PULLDOWN_ONLY); void set_spkfault_gpio(int gpio, char *value) {
if (strcasestr(value, "spkfault")) {
ESP_LOGI(TAG,"Adding jack (%s) detection GPIO %d", low ? "low" : "high", gpio); char *p;
spkfault.gpio = gpio;
// re-use button management for jack handler, it's a GPIO after all if ((p = strchr(value, ':')) != NULL) spkfault.active = atoi(p + 1);
button_create(NULL, jack_gpio, low ? BUTTON_LOW : BUTTON_HIGH, false, 250, jack_handler_default, 0, -1);
} }
} }
/**************************************************************************************** /****************************************************************************************
* *
@@ -118,25 +111,33 @@ void set_jack_gpio(int gpio, char *value) {
void monitor_svc_init(void) { void monitor_svc_init(void) {
ESP_LOGI(TAG, "Initializing monitoring"); ESP_LOGI(TAG, "Initializing monitoring");
// if JACK_GPIO is compiled-time defined set it there #ifdef CONFIG_JACK_GPIO_LEVEL
if (jack_gpio != -1) { jack.active = CONFIG_JACK_GPIO_LEVEL;
#if JACK_GPIO_LEVEL == 1
set_jack_gpio(JACK_GPIO, "jack_h");
#else
set_jack_gpio(JACK_GPIO, "jack_l");
#endif #endif
} else {
parse_set_GPIO(set_jack_gpio); #ifndef CONFIG_JACK_LOCKED
parse_set_GPIO(set_jack_gpio);
#endif
// re-use button management for jack handler, it's a GPIO after all
if (jack.gpio != -1) {
ESP_LOGI(TAG,"Adding jack (%s) detection GPIO %d", jack.active ? "high" : "low", jack.gpio);
button_create(NULL, jack.gpio, jack.active ? BUTTON_HIGH : BUTTON_LOW, false, 250, jack_handler_default, 0, -1);
} }
#ifdef SPKFAULT_GPIO #ifdef CONFIG_SPKFAULT_GPIO_LEVEL
gpio_pad_select_gpio(SPKFAULT_GPIO); spkfault.active = CONFIG_SPKFAULT_GPIO_LEVEL;
gpio_set_direction(SPKFAULT_GPIO, GPIO_MODE_INPUT); #endif
gpio_set_pull_mode(SPKFAULT_GPIO, GPIO_PULLUP_ONLY);
#ifndef CONFIG_SPKFAULT_LOCKED
parse_set_GPIO(set_spkfault_gpio);
#endif
// re-use button management for speaker fault handler, it's a GPIO after all // re-use button management for speaker fault handler, it's a GPIO after all
button_create(NULL, SPKFAULT_GPIO, BUTTON_LOW, true, 0, spkfault_handler_default, 0, -1); if (spkfault.gpio != -1) {
#endif ESP_LOGI(TAG,"Adding speaker fault (%s) detection GPIO %d", spkfault.active ? "high" : "low", spkfault.gpio);
button_create(NULL, spkfault.gpio, spkfault.active ? BUTTON_HIGH : BUTTON_LOW, false, 0, spkfault_handler_default, 0, -1);
}
// do we want stats // do we want stats
char *p = config_alloc_get_default(NVS_TYPE_STR, "stats", "n", 0); char *p = config_alloc_get_default(NVS_TYPE_STR, "stats", "n", 0);
@@ -145,5 +146,4 @@ void monitor_svc_init(void) {
xTimerStart(monitor_timer, portMAX_DELAY); xTimerStart(monitor_timer, portMAX_DELAY);
} }
free(p); free(p);
} }

View File

@@ -22,6 +22,8 @@ extern void monitor_svc_init(void);
extern void led_svc_init(void); extern void led_svc_init(void);
int i2c_system_port = I2C_SYSTEM_PORT; int i2c_system_port = I2C_SYSTEM_PORT;
int spi_system_host = SPI_SYSTEM_HOST;
int spi_system_dc_gpio = -1;
static const char *TAG = "services"; static const char *TAG = "services";
@@ -44,40 +46,52 @@ void set_power_gpio(int gpio, char *value) {
if (parsed) ESP_LOGI(TAG, "set GPIO %u to %s", gpio, value); if (parsed) ESP_LOGI(TAG, "set GPIO %u to %s", gpio, value);
} }
/**************************************************************************************** /****************************************************************************************
* *
*/ */
void services_init(void) { void services_init(void) {
char *nvs_item;
gpio_install_isr_service(0); gpio_install_isr_service(0);
#ifdef CONFIG_SQUEEZEAMP #ifdef CONFIG_I2C_LOCKED
if (i2c_system_port == 0) { if (i2c_system_port == 0) {
i2c_system_port = 1; i2c_system_port = 1;
ESP_LOGE(TAG, "can't use i2c port 0 on SqueezeAMP"); ESP_LOGE(TAG, "Port 0 is reserved for internal DAC use");
} }
#endif #endif
// set potential power GPIO // set potential power GPIO
parse_set_GPIO(set_power_gpio); parse_set_GPIO(set_power_gpio);
// shared I2C bus
const i2c_config_t * i2c_config = config_i2c_get(&i2c_system_port); const i2c_config_t * i2c_config = config_i2c_get(&i2c_system_port);
ESP_LOGI(TAG,"Configuring I2C sda:%d scl:%d port:%u speed:%u", i2c_config->sda_io_num, i2c_config->scl_io_num, i2c_system_port, i2c_config->master.clk_speed); ESP_LOGI(TAG,"Configuring I2C sda:%d scl:%d port:%u speed:%u", i2c_config->sda_io_num, i2c_config->scl_io_num, i2c_system_port, i2c_config->master.clk_speed);
if (i2c_config->sda_io_num != -1 && i2c_config->scl_io_num != -1) { if (i2c_config->sda_io_num != -1 && i2c_config->scl_io_num != -1) {
i2c_param_config(i2c_system_port, i2c_config); i2c_param_config(i2c_system_port, i2c_config);
i2c_driver_install(i2c_system_port, i2c_config->mode, 0, 0, 0 ); i2c_driver_install(i2c_system_port, i2c_config->mode, 0, 0, 0 );
} else { } else {
i2c_system_port = -1;
ESP_LOGW(TAG, "no I2C configured"); ESP_LOGW(TAG, "no I2C configured");
} }
ESP_LOGD(TAG,"Configuring LEDs"); const spi_bus_config_t * spi_config = config_spi_get((spi_host_device_t*) &spi_system_host);
led_svc_init(); ESP_LOGI(TAG,"Configuring SPI data:%d clk:%d host:%u dc:%d", spi_config->mosi_io_num, spi_config->sclk_io_num, spi_system_host, spi_system_dc_gpio);
led_config(LED_GREEN, LED_GREEN_GPIO, 0);
led_config(LED_RED, LED_RED_GPIO, 0);
if (spi_config->mosi_io_num != -1 && spi_config->sclk_io_num != -1) {
spi_bus_initialize( spi_system_host, spi_config, 1 );
if (spi_system_dc_gpio != -1) {
gpio_set_direction( spi_system_dc_gpio, GPIO_MODE_OUTPUT );
gpio_set_level( spi_system_dc_gpio, 0 );
} else {
ESP_LOGW(TAG, "No DC GPIO set, SPI display will not work");
}
} else {
spi_system_host = -1;
ESP_LOGW(TAG, "no SPI configured");
}
led_svc_init();
battery_svc_init(); battery_svc_init();
monitor_svc_init(); monitor_svc_init();
} }

View File

@@ -1,4 +0,0 @@
.vscode
build
.DS_Store

View File

@@ -1,3 +0,0 @@
set(COMPONENT_SRCDIRS ". fonts ifaces")
set(COMPONENT_ADD_INCLUDEDIRS ".")
register_component()

View File

@@ -1,106 +0,0 @@
menu "TarableSSD1306"
config SSD1306_ENABLE_DEFAULT_I2C_INTERFACE
bool "Enable default i2c master interface code"
default y
help
Provides initialization code for both the i2c bus and i2c display device.
config SSD1306_DEFAULT_I2C_SPEED
depends on SSD1306_ENABLE_DEFAULT_I2C_INTERFACE
int "Bus speed for i2c master"
default 250000
help
Default i2c interface speed in Hz
config SSD1306_DEFAULT_I2C_PORT_NUMBER
depends on SSD1306_ENABLE_DEFAULT_I2C_INTERFACE
int "I2C port number to use"
default 0
config SSD1306_DEFAULT_I2C_SCL_PIN
depends on SSD1306_ENABLE_DEFAULT_I2C_INTERFACE
int "Default SCL pin number"
default 22
config SSD1306_DEFAULT_I2C_SDA_PIN
depends on SSD1306_ENABLE_DEFAULT_I2C_INTERFACE
int "Default SDA pin number"
default 21
config SSD1306_ENABLE_DEFAULT_SPI_INTERFACE
bool "Enable default SPI interface"
default y
help
Provides initialization code for both the i2c device and spi attached display.
config SSD1306_DEFAULT_SPI_HOST
depends on SSD1306_ENABLE_DEFAULT_SPI_INTERFACE
int
default 1 if SSD1306_USE_HSPI_HOST
default 2 if SSD1306_USE_VSPI_HOST
choice
depends on SSD1306_ENABLE_DEFAULT_SPI_INTERFACE
prompt "Default SPI host"
default SSD1306_USE_HSPI_HOST
config SSD1306_USE_HSPI_HOST
bool "HSPI"
config SSD1306_USE_VSPI_HOST
bool "VSPI"
endchoice
config SSD1306_DEFAULT_SPI_FREQUENCY
depends on SSD1306_ENABLE_DEFAULT_SPI_INTERFACE
int "Default frequency for SPI attached display"
default 1000000
config SSD1306_DEFAULT_SPI_MOSI_PIN
depends on SSD1306_ENABLE_DEFAULT_SPI_INTERFACE
int "Default MOSI pin number"
default 13
config SSD1306_DEFAULT_SPI_SCLK_PIN
depends on SSD1306_ENABLE_DEFAULT_SPI_INTERFACE
int "Default SCLK pin number"
default 14
config SSD1306_DEFAULT_SPI_DC_PIN
depends on SSD1306_ENABLE_DEFAULT_SPI_INTERFACE
int "Default DC pin number"
default 33
config SSD1306_ERROR_ABORT
bool "Call abort() on all errors"
default y
config SSD1306_CLIPDEBUG
int
default 0 if CLIPDEBUG_NONE
default 1 if CLIPDEBUG_WARNING
default 2 if CLIPDEBUG_ERROR
choice
prompt "Clipping debug level"
default CLIPDEBUG_WARNING
config CLIPDEBUG_NONE
bool "None"
help
Drawing operations clip silently.
config CLIPDEBUG_WARNING
bool "Warning"
help
If a drawing operation is clipped a warning is written to the console.
config CLIPDEBUG_ERROR
bool "Error"
help
If a drawing operation is clipped an error is written to the console along with an abort.
endchoice
endmenu

View File

@@ -1,9 +0,0 @@
MIT License
Copyright (c) 2017 Tara Keeling
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,16 +0,0 @@
<!---
Copyright (c) 2017 Tara Keeling
This software is released under the MIT License.
https://opensource.org/licenses/MIT
-->
# SSD1306 Component for the ESP32 and ESP-IDF SDK
## About:
This is a simple component for the SSD1306 display.
It supports multiple display sizes on both i2c and spi interfaces.
Check out the wiki where most of the relevant information is.
***Examples:*** https://github.com/TaraHoleInIt/tarablessd1306_examples

View File

@@ -1,2 +0,0 @@
COMPONENT_SRCDIRS := . fonts ifaces
COMPONENT_ADD_INCLUDEDIRS := .

View File

@@ -1,139 +0,0 @@
/**
* Copyright (c) 2017-2018 Tara Keeling
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <driver/spi_master.h>
#include <driver/gpio.h>
#include <freertos/task.h>
#include "ssd1306.h"
#include "ssd1306_default_if.h"
/*
* HACKHACKHACK:
* Conditional compiling in component.mk does not seem to be working.
* This workaround looks ugly, but should work.
*/
#if defined CONFIG_SSD1306_ENABLE_DEFAULT_SPI_INTERFACE
static const spi_host_device_t SPIHost = ( spi_host_device_t ) CONFIG_SSD1306_DEFAULT_SPI_HOST;
static const int SPIFrequency = CONFIG_SSD1306_DEFAULT_SPI_FREQUENCY;
static const int MOSIPin = CONFIG_SSD1306_DEFAULT_SPI_MOSI_PIN;
static const int SCLKPin = CONFIG_SSD1306_DEFAULT_SPI_SCLK_PIN;
static const int DCPin = CONFIG_SSD1306_DEFAULT_SPI_DC_PIN;
static const int SSD1306_SPI_Command_Mode = 0;
static const int SSD1306_SPI_Data_Mode = 1;
static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength );
static bool SPIDefaultWriteCommand( struct SSD1306_Device* DeviceHandle, SSDCmd Command );
static bool SPIDefaultWriteData( struct SSD1306_Device* DeviceHandle, const uint8_t* Data, size_t DataLength );
static bool SPIDefaultReset( struct SSD1306_Device* DeviceHandle );
bool SSD1306_SPIMasterInitDefault( void ) {
spi_bus_config_t BusConfig = {
.sclk_io_num = SCLKPin,
.mosi_io_num = MOSIPin,
.miso_io_num = -1,
.quadwp_io_num = -1,
.quadhd_io_num = -1
};
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( DCPin, GPIO_MODE_OUTPUT ), return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( DCPin, 0 ), return false );
ESP_ERROR_CHECK_NONFATAL( spi_bus_initialize( SPIHost, &BusConfig, 1 ), return false );
return true;
}
bool SSD1306_SPIMasterAttachDisplayDefault( struct SSD1306_Device* DeviceHandle, int Width, int Height, int CSForThisDisplay, int RSTForThisDisplay ) {
spi_device_interface_config_t SPIDeviceConfig;
spi_device_handle_t SPIDeviceHandle;
NullCheck( DeviceHandle, return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( CSForThisDisplay, GPIO_MODE_OUTPUT ), return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSForThisDisplay, 0 ), return false );
memset( &SPIDeviceConfig, 0, sizeof( spi_device_interface_config_t ) );
SPIDeviceConfig.clock_speed_hz = SPIFrequency;
SPIDeviceConfig.spics_io_num = CSForThisDisplay;
SPIDeviceConfig.queue_size = 1;
if ( RSTForThisDisplay >= 0 ) {
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTForThisDisplay, GPIO_MODE_OUTPUT ), return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTForThisDisplay, 0 ), return false );
}
ESP_ERROR_CHECK_NONFATAL( spi_bus_add_device( SPIHost, &SPIDeviceConfig, &SPIDeviceHandle ), return false );
return SSD1306_Init_SPI( DeviceHandle,
Width,
Height,
RSTForThisDisplay,
CSForThisDisplay,
SPIDeviceHandle,
SPIDefaultWriteCommand,
SPIDefaultWriteData,
SPIDefaultReset
);
}
static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) {
spi_transaction_t SPITransaction;
NullCheck( SPIHandle, return false );
NullCheck( Data, return false );
if ( DataLength > 0 ) {
memset( &SPITransaction, 0, sizeof( spi_transaction_t ) );
SPITransaction.length = DataLength * 8;
SPITransaction.tx_buffer = Data;
gpio_set_level( DCPin, WriteMode );
ESP_ERROR_CHECK_NONFATAL( spi_device_transmit( SPIHandle, &SPITransaction ), return false );
}
return true;
}
static bool SPIDefaultWriteCommand( struct SSD1306_Device* DeviceHandle, SSDCmd Command ) {
static uint8_t CommandByte = 0;
NullCheck( DeviceHandle, return false );
NullCheck( DeviceHandle->SPIHandle, return false );
CommandByte = Command;
return SPIDefaultWriteBytes( DeviceHandle->SPIHandle, SSD1306_SPI_Command_Mode, &CommandByte, 1 );
}
static bool SPIDefaultWriteData( struct SSD1306_Device* DeviceHandle, const uint8_t* Data, size_t DataLength ) {
NullCheck( DeviceHandle, return false );
NullCheck( DeviceHandle->SPIHandle, return false );
return SPIDefaultWriteBytes( DeviceHandle->SPIHandle, SSD1306_SPI_Data_Mode, Data, DataLength );
}
static bool SPIDefaultReset( struct SSD1306_Device* DeviceHandle ) {
NullCheck( DeviceHandle, return false );
if ( DeviceHandle->RSTPin >= 0 ) {
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( DeviceHandle->RSTPin, 0 ), return false );
vTaskDelay( pdMS_TO_TICKS( 100 ) );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( DeviceHandle->RSTPin, 1 ), return false );
}
return true;
}
#endif

View File

@@ -1,272 +0,0 @@
/**
* Copyright (c) 2017-2018 Tara Keeling
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>
#include <esp_heap_caps.h>
#include "ssd1306.h"
#define COM_Disable_LR_Remap 0
#define COM_Enable_LR_Remap BIT( 5 )
#define COM_Pins_Sequential 0
#define COM_Pins_Alternative BIT( 4 )
#define COM_ScanDir_LR 0
#define COM_ScanDir_RL 1
static bool SSD1306_Init( struct SSD1306_Device* DeviceHandle, int Width, int Height );
bool SSD1306_WriteCommand( struct SSD1306_Device* DeviceHandle, SSDCmd SSDCommand ) {
NullCheck( DeviceHandle, return false );
NullCheck( DeviceHandle->WriteCommand, return false );
return ( DeviceHandle->WriteCommand ) ( DeviceHandle, SSDCommand );
}
bool SSD1306_WriteData( struct SSD1306_Device* DeviceHandle, uint8_t* Data, size_t DataLength ) {
NullCheck( DeviceHandle, return false );
NullCheck( DeviceHandle->WriteData, return false );
return ( DeviceHandle->WriteData ) ( DeviceHandle, Data, DataLength );
}
void SSD1306_SetMuxRatio( struct SSD1306_Device* DeviceHandle, uint8_t Ratio ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, 0xA8 );
SSD1306_WriteCommand( DeviceHandle, Ratio );
}
void SSD1306_SetDisplayOffset( struct SSD1306_Device* DeviceHandle, uint8_t Offset ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, 0xD3 );
SSD1306_WriteCommand( DeviceHandle, Offset );
}
void SSD1306_SetDisplayStartLine( struct SSD1306_Device* DeviceHandle, int Line ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle,
SSDCmd_Set_Display_Start_Line + ( uint32_t ) ( Line & 0x1F )
);
}
/*
* This is all a big giant mystery that I have yet to figure out.
* Beware all ye who enter.
*/
static void SetCOMPinConfiguration( struct SSD1306_Device* DeviceHandle, uint32_t RemapCFG, uint32_t PinCFG, int ScanDir ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Set_COM_Pin_Config );
SSD1306_WriteCommand( DeviceHandle, ( uint8_t ) ( RemapCFG | PinCFG | BIT( 1 ) ) );
SSD1306_WriteCommand( DeviceHandle,
( ScanDir == COM_ScanDir_LR ) ? SSDCmd_Set_Display_VFlip_Off : SSDCmd_Set_Display_VFlip_On
);
}
void SSD1306_SetContrast( struct SSD1306_Device* DeviceHandle, uint8_t Contrast ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Set_Contrast );
SSD1306_WriteCommand( DeviceHandle, Contrast );
}
void SSD1306_EnableDisplayRAM( struct SSD1306_Device* DeviceHandle ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Set_Display_Show_RAM );
}
void SSD1306_DisableDisplayRAM( struct SSD1306_Device* DeviceHandle ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Set_Display_Ignore_RAM );
}
void SSD1306_SetInverted( struct SSD1306_Device* DeviceHandle, bool Inverted ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, ( Inverted == true ) ? SSDCmd_Set_Inverted_Display : SSDCmd_Set_Normal_Display );
}
void SSD1306_SetDisplayClocks( struct SSD1306_Device* DeviceHandle, uint32_t DisplayClockDivider, uint32_t OSCFrequency ) {
NullCheck( DeviceHandle, return );
DisplayClockDivider&= 0x0F;
OSCFrequency&= 0x0F;
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Set_Display_CLK );
SSD1306_WriteCommand( DeviceHandle, ( ( OSCFrequency << 4 ) | DisplayClockDivider ) );
}
/* There is no documentation for this command, but it is required during init. */
static void EnableChargePumpRegulator( struct SSD1306_Device* DeviceHandle ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Enable_Charge_Pump_Regulator );
SSD1306_WriteCommand( DeviceHandle, 0x14 ); /* MAGIC NUMBER */
}
void SSD1306_DisplayOn( struct SSD1306_Device* DeviceHandle ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Set_Display_On );
}
void SSD1306_DisplayOff( struct SSD1306_Device* DeviceHandle ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Set_Display_Off );
}
void SSD1306_SetDisplayAddressMode( struct SSD1306_Device* DeviceHandle, SSD1306_AddressMode AddressMode ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Set_Memory_Addressing_Mode );
SSD1306_WriteCommand( DeviceHandle, AddressMode );
}
void SSD1306_Update( struct SSD1306_Device* DeviceHandle ) {
NullCheck( DeviceHandle, return );
SSD1306_SetColumnAddress( DeviceHandle, 0, DeviceHandle->Width - 1);
SSD1306_SetPageAddress( DeviceHandle, 0, DeviceHandle->Height / 8 - 1);
SSD1306_WriteData( DeviceHandle, DeviceHandle->Framebuffer, DeviceHandle->FramebufferSize );
}
void SSD1306_WriteRawData( struct SSD1306_Device* DeviceHandle, uint8_t* Data, size_t DataLength ) {
NullCheck( DeviceHandle, return );
NullCheck( Data, return );
DataLength = DataLength > DeviceHandle->FramebufferSize ? DeviceHandle->FramebufferSize : DataLength;
if ( DataLength > 0 ) {
SSD1306_WriteData( DeviceHandle, Data, DataLength );
}
}
void SSD1306_SetHFlip( struct SSD1306_Device* DeviceHandle, bool On ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, ( On == true ) ? SSDCmd_Set_Display_HFlip_On : SSDCmd_Set_Display_HFlip_Off );
}
void SSD1306_SetVFlip( struct SSD1306_Device* DeviceHandle, bool On ) {
NullCheck( DeviceHandle, return );
SSD1306_WriteCommand( DeviceHandle, ( On == true ) ? SSDCmd_Set_Display_VFlip_On : SSDCmd_Set_Display_VFlip_Off );
}
void SSD1306_SetColumnAddress( struct SSD1306_Device* DeviceHandle, uint8_t Start, uint8_t End ) {
NullCheck( DeviceHandle, return );
CheckBounds( Start > SSD1306_Max_Col, return );
CheckBounds( End > SSD1306_Max_Col, return );
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Set_Column_Address );
SSD1306_WriteCommand( DeviceHandle, Start );
SSD1306_WriteCommand( DeviceHandle, End );
}
void SSD1306_SetPageAddress( struct SSD1306_Device* DeviceHandle, uint8_t Start, uint8_t End ) {
NullCheck( DeviceHandle, return );
CheckBounds( Start > SSD1306_Max_Row, return );
CheckBounds( End > SSD1306_Max_Row, return );
SSD1306_WriteCommand( DeviceHandle, SSDCmd_Set_Page_Address );
SSD1306_WriteCommand( DeviceHandle, Start );
SSD1306_WriteCommand( DeviceHandle, End );
}
bool SSD1306_HWReset( struct SSD1306_Device* DeviceHandle ) {
NullCheck( DeviceHandle, return 0 );
if ( DeviceHandle->Reset != NULL ) {
return ( DeviceHandle->Reset ) ( DeviceHandle );
}
/* This should always return true if there is no reset callback as
* no error would have occurred during the non existant reset.
*/
return true;
}
static bool SSD1306_Init( struct SSD1306_Device* DeviceHandle, int Width, int Height ) {
DeviceHandle->Width = Width;
DeviceHandle->Height = Height;
DeviceHandle->FramebufferSize = ( DeviceHandle->Width * Height ) / 8;
// DeviceHandle->Framebuffer = heap_caps_calloc( 1, DeviceHandle->FramebufferSize, MALLOC_CAP_INTERNAL );
DeviceHandle->Framebuffer = calloc( 1, DeviceHandle->FramebufferSize );
NullCheck( DeviceHandle->Framebuffer, return false );
/* For those who have a hardware reset pin on their display */
SSD1306_HWReset( DeviceHandle );
/* Init sequence according to SSD1306.pdf */
SSD1306_SetMuxRatio( DeviceHandle, Height - 1 );
SSD1306_SetDisplayOffset( DeviceHandle, 0x00 );
SSD1306_SetDisplayStartLine( DeviceHandle, 0 );
SSD1306_SetHFlip( DeviceHandle, false );
SSD1306_SetVFlip( DeviceHandle, false );
if ( Height == 64 ) {
SetCOMPinConfiguration( DeviceHandle, COM_Disable_LR_Remap, COM_Pins_Alternative, COM_ScanDir_LR );
} else {
SetCOMPinConfiguration( DeviceHandle, COM_Disable_LR_Remap, COM_Pins_Sequential, COM_ScanDir_LR );
}
SSD1306_SetContrast( DeviceHandle, 0x7F );
SSD1306_DisableDisplayRAM( DeviceHandle );
SSD1306_SetInverted( DeviceHandle, false );
SSD1306_SetDisplayClocks( DeviceHandle, 0, 8 );
EnableChargePumpRegulator( DeviceHandle );
SSD1306_SetDisplayAddressMode( DeviceHandle, AddressMode_Vertical );
SSD1306_SetColumnAddress( DeviceHandle, 0, DeviceHandle->Width - 1 );
SSD1306_SetPageAddress( DeviceHandle, 0, ( DeviceHandle->Height / 8 ) - 1 );
SSD1306_EnableDisplayRAM( DeviceHandle );
SSD1306_DisplayOn( DeviceHandle );
SSD1306_Update( DeviceHandle );
return true;
}
bool SSD1306_Init_I2C( struct SSD1306_Device* DeviceHandle, int Width, int Height, int I2CAddress, int ResetPin, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset ) {
NullCheck( DeviceHandle, return false );
NullCheck( WriteCommand, return false );
NullCheck( WriteData, return false );
memset( DeviceHandle, 0, sizeof( struct SSD1306_Device ) );
DeviceHandle->WriteCommand = WriteCommand;
DeviceHandle->WriteData = WriteData;
DeviceHandle->Reset = Reset;
DeviceHandle->Address = I2CAddress;
DeviceHandle->RSTPin = ResetPin;
return SSD1306_Init( DeviceHandle, Width, Height );
}
bool SSD1306_Init_SPI( struct SSD1306_Device* DeviceHandle, int Width, int Height, int ResetPin, int CSPin, spi_device_handle_t SPIHandle, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset ) {
NullCheck( DeviceHandle, return false );
NullCheck( WriteCommand, return false );
NullCheck( WriteData, return false );
memset( DeviceHandle, 0, sizeof( struct SSD1306_Device ) );
DeviceHandle->WriteCommand = WriteCommand;
DeviceHandle->WriteData = WriteData;
DeviceHandle->Reset = Reset;
DeviceHandle->SPIHandle = SPIHandle;
DeviceHandle->RSTPin = ResetPin;
DeviceHandle->CSPin = CSPin;
return SSD1306_Init( DeviceHandle, Width, Height );
}

View File

@@ -1,117 +0,0 @@
#ifndef _SSD1306_H_
#define _SSD1306_H_
/* For uint(X)_t */
#include <stdint.h>
/* For booooool */
#include <stdbool.h>
#include "sdkconfig.h"
#include "ssd1306_err.h"
#define SSD_ALWAYS_INLINE __attribute__( ( always_inline ) )
#define SSD1306_Max_Col 127
#define SSD1306_Max_Row 7
#if ! defined BIT
#define BIT( n ) ( 1 << n )
#endif
typedef enum {
SSDCmd_Set_Contrast = 0x81,
SSDCmd_Set_Display_Show_RAM = 0xA4,
SSDCmd_Set_Display_Ignore_RAM = 0xA5,
SSDCmd_Set_Normal_Display = 0xA6,
SSDCmd_Set_Inverted_Display = 0xA7,
SSDCmd_Set_Display_Off = 0xAE,
SSDCmd_Set_Display_On = 0xAF,
SSDCmd_Set_Memory_Addressing_Mode = 0x20,
SSDCmd_Set_Mux_Ratio = 0xA8,
SSDCmd_Nop = 0xE3,
SSDCmd_Set_Display_Offset = 0xD3,
SSDCmd_Set_Display_Start_Line = 0x40,
SSDCmd_Set_Display_HFlip_Off = 0xA0,
SSDCmd_Set_Display_HFlip_On = 0xA1,
SSDCmd_Set_Display_VFlip_Off = 0xC0,
SSDCmd_Set_Display_VFlip_On = 0xC8,
SSDCmd_Set_COM_Pin_Config = 0xDA,
SSDCmd_Set_Display_CLK = 0xD5,
SSDCmd_Enable_Charge_Pump_Regulator = 0x8D,
SSDCmd_Set_Column_Address = 0x21,
SSDCmd_Set_Page_Address = 0x22
} SSDCmd;
typedef enum {
AddressMode_Horizontal = 0,
AddressMode_Vertical,
AddressMode_Page,
AddressMode_Invalid
} SSD1306_AddressMode;
struct SSD1306_Device;
/*
* These can optionally return a succeed/fail but are as of yet unused in the driver.
*/
typedef bool ( *WriteCommandProc ) ( struct SSD1306_Device* DeviceHandle, SSDCmd Command );
typedef bool ( *WriteDataProc ) ( struct SSD1306_Device* DeviceHandle, const uint8_t* Data, size_t DataLength );
typedef bool ( *ResetProc ) ( struct SSD1306_Device* DeviceHandle );
struct spi_device_t;
typedef struct spi_device_t* spi_device_handle_t;
struct SSD1306_FontDef;
struct SSD1306_Device {
/* I2C Specific */
int Address;
/* SPI Specific */
spi_device_handle_t SPIHandle;
int RSTPin;
int CSPin;
/* Everything else */
int Width;
int Height;
uint8_t* Framebuffer;
int FramebufferSize;
WriteCommandProc WriteCommand;
WriteDataProc WriteData;
ResetProc Reset;
const struct SSD1306_FontDef* Font;
bool FontForceProportional;
bool FontForceMonospace;
};
void SSD1306_SetMuxRatio( struct SSD1306_Device* DeviceHandle, uint8_t Ratio );
void SSD1306_SetDisplayOffset( struct SSD1306_Device* DeviceHandle, uint8_t Offset );
void SSD1306_SetDisplayStartLines( struct SSD1306_Device* DeviceHandle );
void SSD1306_SetSegmentRemap( struct SSD1306_Device* DeviceHandle, bool Remap );
void SSD1306_SetContrast( struct SSD1306_Device* DeviceHandle, uint8_t Contrast );
void SSD1306_EnableDisplayRAM( struct SSD1306_Device* DeviceHandle );
void SSD1306_DisableDisplayRAM( struct SSD1306_Device* DeviceHandle );
void SSD1306_SetInverted( struct SSD1306_Device* DeviceHandle, bool Inverted );
void SSD1306_SetHFlip( struct SSD1306_Device* DeviceHandle, bool On );
void SSD1306_SetVFlip( struct SSD1306_Device* DeviceHandle, bool On );
void SSD1306_DisplayOn( struct SSD1306_Device* DeviceHandle );
void SSD1306_DisplayOff( struct SSD1306_Device* DeviceHandle );
void SSD1306_SetDisplayAddressMode( struct SSD1306_Device* DeviceHandle, SSD1306_AddressMode AddressMode );
void SSD1306_Update( struct SSD1306_Device* DeviceHandle );
void SSD1306_SetDisplayClocks( struct SSD1306_Device* DeviceHandle, uint32_t DisplayClockDivider, uint32_t OSCFrequency );
void SSD1306_WriteRawData( struct SSD1306_Device* DeviceHandle, uint8_t* Data, size_t DataLength );
void SSD1306_SetColumnAddress( struct SSD1306_Device* DeviceHandle, uint8_t Start, uint8_t End );
void SSD1306_SetPageAddress( struct SSD1306_Device* DeviceHandle, uint8_t Start, uint8_t End );
bool SSD1306_HWReset( struct SSD1306_Device* DeviceHandle );
bool SSD1306_Init_I2C( struct SSD1306_Device* DeviceHandle, int Width, int Height, int I2CAddress, int ResetPin, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset );
bool SSD1306_Init_SPI( struct SSD1306_Device* DeviceHandle, int Width, int Height, int ResetPin, int CSPin, spi_device_handle_t SPIHandle, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset );
#endif

View File

@@ -1,36 +0,0 @@
#ifndef _SSD1306_DEFAULT_IF_H_
#define _SSD1306_DEFAULT_IF_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
* Initializes the i2c master
*
* Returns true on successful init of the i2c bus.
*/
bool SSD1306_I2CMasterInitDefault( int PortNumber, int SDA, int SCL );
/*
* Attaches a display to the I2C bus using default communication functions.
*
* Params:
* DisplayHandle: Pointer to your SSD1306_Device object
* Width: Width of display
* Height: Height of display
* I2CAddress: Address of your display
* RSTPin: Optional GPIO pin to use for hardware reset, if none pass -1 for this parameter.
*
* Returns true on successful init of display.
*/
bool SSD1306_I2CMasterAttachDisplayDefault( struct SSD1306_Device* DisplayHandle, int Width, int Height, int I2CAddress, int RSTPin );
bool SSD1306_SPIMasterInitDefault( void );
bool SSD1306_SPIMasterAttachDisplayDefault( struct SSD1306_Device* DeviceHandle, int Width, int Height, int CSForThisDisplay, int RSTForThisDisplay );
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,91 +0,0 @@
#ifndef _SSD1306_FONT_H_
#define _SSD1306_FONT_H_
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
struct SSD1306_Device;
/*
* X-GLCD Font format:
*
* First byte of glyph is it's width in pixels.
* Each data byte represents 8 pixels going down from top to bottom.
*
* Example glyph layout for a 16x16 font
* 'a': [Glyph width][Pixel column 0][Pixel column 1] where the number of pixel columns is the font height divided by 8
* 'b': [Glyph width][Pixel column 0][Pixel column 1]...
* 'c': And so on...
*/
struct SSD1306_FontDef {
const uint8_t* FontData;
int Width;
int Height;
int StartChar;
int EndChar;
bool Monospace;
};
typedef enum {
TextAnchor_East = 0,
TextAnchor_West,
TextAnchor_North,
TextAnchor_South,
TextAnchor_NorthEast,
TextAnchor_NorthWest,
TextAnchor_SouthEast,
TextAnchor_SouthWest,
TextAnchor_Center
} TextAnchor;
bool SSD1306_SetFont( struct SSD1306_Device* Display, const struct SSD1306_FontDef* Font );
void SSD1306_FontForceProportional( struct SSD1306_Device* Display, bool Force );
void SSD1306_FontForceMonospace( struct SSD1306_Device* Display, bool Force );
int SSD1306_FontGetWidth( struct SSD1306_Device* Display );
int SSD1306_FontGetHeight( struct SSD1306_Device* Display );
int SSD1306_FontGetMaxCharsPerRow( struct SSD1306_Device* Display );
int SSD1306_FontGetMaxCharsPerColumn( struct SSD1306_Device* Display );
int SSD1306_FontGetCharWidth( struct SSD1306_Device* Display, char Character );
int SSD1306_FontGetCharHeight( struct SSD1306_Device* Display );
int SSD1306_FontMeasureString( struct SSD1306_Device* Display, const char* Text );\
void SSD1306_FontDrawChar( struct SSD1306_Device* Display, char Character, int x, int y, int Color );
void SSD1306_FontDrawString( struct SSD1306_Device* Display, int x, int y, const char* Text, int Color );
void SSD1306_FontDrawAnchoredString( struct SSD1306_Device* Display, TextAnchor Anchor, const char* Text, int Color );
void SSD1306_FontGetAnchoredStringCoords( struct SSD1306_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text );
extern const struct SSD1306_FontDef Font_droid_sans_fallback_11x13;
extern const struct SSD1306_FontDef Font_droid_sans_fallback_15x17;
extern const struct SSD1306_FontDef Font_droid_sans_fallback_24x28;
extern const struct SSD1306_FontDef Font_droid_sans_mono_7x13;
extern const struct SSD1306_FontDef Font_droid_sans_mono_13x24;
extern const struct SSD1306_FontDef Font_droid_sans_mono_16x31;
extern const struct SSD1306_FontDef Font_liberation_mono_9x15;
extern const struct SSD1306_FontDef Font_liberation_mono_13x21;
extern const struct SSD1306_FontDef Font_liberation_mono_17x30;
extern const struct SSD1306_FontDef Font_Tarable7Seg_16x32;
extern const struct SSD1306_FontDef Font_Tarable7Seg_32x64;
extern const struct SSD1306_FontDef Font_line_1;
extern const struct SSD1306_FontDef Font_line_2;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -73,7 +73,6 @@ static int i2c_port;
static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config) { static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config) {
esp_err_t res; esp_err_t res;
ESP_LOGI(TAG, "Initializing AC101");
i2c_port = i2c_port_num; i2c_port = i2c_port_num;
// configure i2c // configure i2c
@@ -83,21 +82,25 @@ static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config) {
.sda_pullup_en = GPIO_PULLUP_ENABLE, .sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_io_num = 32, .scl_io_num = 32,
.scl_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 100000, .master.clk_speed = 250000,
}; };
i2c_param_config(i2c_port, &i2c_config); i2c_param_config(i2c_port, &i2c_config);
i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false); i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false);
ESP_LOGI(TAG, "DAC using I2C sda:%u, scl:%u", i2c_config.sda_io_num, i2c_config.scl_io_num);
res = i2c_read_reg(CHIP_AUDIO_RS);
if (!res) {
ESP_LOGW(TAG, "No AC101 detected");
i2c_driver_delete(i2c_port);
return 0;
}
ESP_LOGI(TAG, "AC101 DAC using I2C sda:%u, scl:%u", i2c_config.sda_io_num, i2c_config.scl_io_num);
res = i2c_write_reg(CHIP_AUDIO_RS, 0x123); res = i2c_write_reg(CHIP_AUDIO_RS, 0x123);
// huh? // huh?
vTaskDelay(100 / portTICK_PERIOD_MS); vTaskDelay(100 / portTICK_PERIOD_MS);
if (ESP_OK != res) {
ESP_LOGE(TAG, "AC101 reset failed! %d", res);
return false;
}
// enable the PLL from BCLK source // enable the PLL from BCLK source
i2c_write_reg(PLL_CTRL1, BIN(0000,0001,0100,1111)); // F=1,M=1,PLL,INT=31 (medium) i2c_write_reg(PLL_CTRL1, BIN(0000,0001,0100,1111)); // F=1,M=1,PLL,INT=31 (medium)
@@ -138,8 +141,8 @@ static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config) {
#endif #endif
// configure I2S pins & install driver // configure I2S pins & install driver
i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t) { .bck_io_num = 27, .ws_io_num = 26, i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t) { .bck_io_num = CONFIG_I2S_BCK_IO, .ws_io_num = CONFIG_I2S_WS_IO,
.data_out_num = 25, .data_in_num = 35 //Not used .data_out_num = CONFIG_I2S_DO_IO, .data_in_num = CONFIG_I2S_DI_IO
}; };
i2s_driver_install(i2s_num, i2s_config, 0, NULL); i2s_driver_install(i2s_num, i2s_config, 0, NULL);
i2s_set_pin(i2s_num, &i2s_pin_config); i2s_set_pin(i2s_num, &i2s_pin_config);

View File

@@ -19,6 +19,7 @@
#include <ctype.h> #include <ctype.h>
#include "squeezelite.h" #include "squeezelite.h"
#include "slimproto.h"
#include "display.h" #include "display.h"
#pragma pack(push, 1) #pragma pack(push, 1)
@@ -84,8 +85,9 @@ static struct scroller_s {
#define ANIM_SCREEN_2 0x08 #define ANIM_SCREEN_2 0x08
static u8_t ANIC_resp = ANIM_NONE; static u8_t ANIC_resp = ANIM_NONE;
static u8_t SETD_width;
#define SCROLL_STACK_SIZE 2048 #define SCROLL_STACK_SIZE (3*1024)
#define LINELEN 40 #define LINELEN 40
static log_level loglevel = lINFO; static log_level loglevel = lINFO;
@@ -150,6 +152,7 @@ bool sb_display_init(void) {
// need to force height to 32 maximum // need to force height to 32 maximum
display_width = display->width; display_width = display->width;
display_height = min(display->height, 32); display_height = min(display->height, 32);
SETD_width = display->width;
// create scroll management task // create scroll management task
display_mutex = xSemaphoreCreateMutex(); display_mutex = xSemaphoreCreateMutex();
@@ -195,6 +198,23 @@ static void send_server(void) {
ANIC_resp = ANIM_NONE; ANIC_resp = ANIM_NONE;
} }
if (SETD_width) {
struct SETD_header pkt_header;
LOG_INFO("sending width %u", SETD_width);
memset(&pkt_header, 0, sizeof(pkt_header));
memcpy(&pkt_header.opcode, "SETD", 4);
pkt_header.id = 0xfe; // id 0xfe is width S:P:Squeezebox2
pkt_header.length = htonl(sizeof(pkt_header) + 2 - 8);
send_packet((u8_t *)&pkt_header, sizeof(pkt_header));
send_packet(&SETD_width, 2);
SETD_width = 0;
}
if (slimp_loop_chain) (*slimp_loop_chain)(); if (slimp_loop_chain) (*slimp_loop_chain)();
} }
@@ -215,24 +235,25 @@ static bool handler(u8_t *data, int len){
bool res = true; bool res = true;
// don't do anything if we dont own the display (no lock needed) // don't do anything if we dont own the display (no lock needed)
if (output.external && output.state >= OUTPUT_STOPPED) return true; if (!output.external || output.state < OUTPUT_STOPPED) {
if (!strncmp((char*) data, "vfdc", 4)) {
if (!strncmp((char*) data, "vfdc", 4)) { vfdc_handler(data, len);
vfdc_handler(data, len); } else if (!strncmp((char*) data, "grfe", 4)) {
} else if (!strncmp((char*) data, "grfe", 4)) { grfe_handler(data, len);
grfe_handler(data, len); } else if (!strncmp((char*) data, "grfb", 4)) {
} else if (!strncmp((char*) data, "grfb", 4)) { grfb_handler(data, len);
grfb_handler(data, len); } else if (!strncmp((char*) data, "grfs", 4)) {
} else if (!strncmp((char*) data, "grfs", 4)) { grfs_handler(data, len);
grfs_handler(data, len); } else if (!strncmp((char*) data, "grfg", 4)) {
} else if (!strncmp((char*) data, "grfg", 4)) { grfg_handler(data, len);
grfg_handler(data, len); } else {
} else { res = false;
res = false; }
} }
// chain protocol handlers (bitwise or is fine) // chain protocol handlers (bitwise or is fine)
if (*slimp_handler_chain) res |= (*slimp_handler_chain)(data, len); if (*slimp_handler_chain) res |= (*slimp_handler_chain)(data, len);
return res; return res;
} }

View File

@@ -8,7 +8,7 @@
- pthread_create_name - pthread_create_name
- stack size - stack size
- s16_t, s32_t, s64_t and u64_t - s16_t, s32_t, s64_t and u64_t
- PLAYER_ID - PLAYER_ID / custom_player_id
can overload (use #define) can overload (use #define)
- exit - exit
- gettime_ms - gettime_ms

View File

@@ -38,9 +38,8 @@ struct adac_s dac_external = { init, deinit, power, speaker, headset, volume };
static char TAG[] = "DAC external"; static char TAG[] = "DAC external";
static bool init(int i2c_port_num, int i2s_num, i2s_config_t *config) { static bool init(int i2c_port_num, int i2s_num, i2s_config_t *config) {
#if !defined(CONFIG_SQUEEZEAMP) && !defined(CONFIG_A1S)
i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t) { .bck_io_num = CONFIG_I2S_BCK_IO, .ws_io_num = CONFIG_I2S_WS_IO, i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t) { .bck_io_num = CONFIG_I2S_BCK_IO, .ws_io_num = CONFIG_I2S_WS_IO,
.data_out_num = CONFIG_I2S_DO_IO, .data_in_num = -1 }; .data_out_num = CONFIG_I2S_DO_IO, .data_in_num = CONFIG_I2S_DI_IO };
char *nvs_item = config_alloc_get(NVS_TYPE_STR, "dac_config"); char *nvs_item = config_alloc_get(NVS_TYPE_STR, "dac_config");
if (nvs_item) { if (nvs_item) {
@@ -55,17 +54,14 @@ static bool init(int i2c_port_num, int i2s_num, i2s_config_t *config) {
i2s_driver_install(i2s_num, config, 0, NULL); i2s_driver_install(i2s_num, config, 0, NULL);
i2s_set_pin(i2s_num, &i2s_pin_config); i2s_set_pin(i2s_num, &i2s_pin_config);
ESP_LOGI(TAG, "DAC using I2S bck:%u, ws:%u, do:%u", i2s_pin_config.bck_io_num, i2s_pin_config.ws_io_num, i2s_pin_config.data_out_num); ESP_LOGI(TAG, "External DAC using I2S bck:%u, ws:%u, do:%u", i2s_pin_config.bck_io_num, i2s_pin_config.ws_io_num, i2s_pin_config.data_out_num);
return true; return true;
} else { } else {
ESP_LOGI(TAG, "Cannot initialize I2S for SPDIF bck:%d ws:%d do:%d", i2s_pin_config.bck_io_num, ESP_LOGI(TAG, "Cannot initialize I2S for DAC bck:%d ws:%d do:%d", i2s_pin_config.bck_io_num,
i2s_pin_config.ws_io_num, i2s_pin_config.ws_io_num,
i2s_pin_config.data_out_num); i2s_pin_config.data_out_num);
return false; return false;
} }
#else
return true;
#endif
} }

View File

@@ -53,6 +53,7 @@ sure that using rate_delay would fix that
#include "monitor.h" #include "monitor.h"
#include "config.h" #include "config.h"
#include "accessors.h" #include "accessors.h"
#include "globdefs.h"
#define LOCK mutex_lock(outputbuf->mutex) #define LOCK mutex_lock(outputbuf->mutex)
#define UNLOCK mutex_unlock(outputbuf->mutex) #define UNLOCK mutex_unlock(outputbuf->mutex)
@@ -112,16 +113,6 @@ static void *output_thread_i2s_stats(void *arg);
static void spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, size_t *count); static void spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, size_t *count);
static void (*jack_handler_chain)(bool inserted); static void (*jack_handler_chain)(bool inserted);
// force all GPIOs to what we need
#undef CONFIG_I2S_NUM
#define CONFIG_I2S_NUM 0
#ifdef CONFIG_SQUEEZEAMP
#undef CONFIG_SPDIF_DO_IO
#define CONFIG_SPDIF_DO_IO 15
#elif defined CONFIG_A1S
#endif
#define I2C_PORT 0 #define I2C_PORT 0
/**************************************************************************************** /****************************************************************************************
@@ -212,13 +203,9 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
if (strcasestr(device, "spdif")) { if (strcasestr(device, "spdif")) {
spdif = true; spdif = true;
#ifdef CONFIG_SQUEEZEAMP
i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t) { .bck_io_num = 33, .ws_io_num = 25,
.data_out_num = CONFIG_SPDIF_DO_IO, .data_in_num = -1 };
#else
i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t) { .bck_io_num = CONFIG_SPDIF_BCK_IO, .ws_io_num = CONFIG_SPDIF_WS_IO, i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t) { .bck_io_num = CONFIG_SPDIF_BCK_IO, .ws_io_num = CONFIG_SPDIF_WS_IO,
.data_out_num = CONFIG_SPDIF_DO_IO, .data_in_num = -1 }; .data_out_num = CONFIG_SPDIF_DO_IO, .data_in_num = -1 };
#ifndef CONFIG_SPDIF_LOCKED
char *nvs_item = config_alloc_get(NVS_TYPE_STR, "spdif_config"); char *nvs_item = config_alloc_get(NVS_TYPE_STR, "spdif_config");
if (nvs_item) { if (nvs_item) {
if ((p = strcasestr(nvs_item, "bck")) != NULL) i2s_pin_config.bck_io_num = atoi(strchr(p, '=') + 1); if ((p = strcasestr(nvs_item, "bck")) != NULL) i2s_pin_config.bck_io_num = atoi(strchr(p, '=') + 1);
@@ -226,13 +213,13 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
if ((p = strcasestr(nvs_item, "do")) != NULL) i2s_pin_config.data_out_num = atoi(strchr(p, '=') + 1); if ((p = strcasestr(nvs_item, "do")) != NULL) i2s_pin_config.data_out_num = atoi(strchr(p, '=') + 1);
free(nvs_item); free(nvs_item);
} }
#endif
if (i2s_pin_config.bck_io_num == -1 || i2s_pin_config.ws_io_num == -1 || i2s_pin_config.data_out_num == -1) { if (i2s_pin_config.bck_io_num == -1 || i2s_pin_config.ws_io_num == -1 || i2s_pin_config.data_out_num == -1) {
LOG_WARN("Cannot initialize I2S for SPDIF bck:%d ws:%d do:%d", i2s_pin_config.bck_io_num, LOG_WARN("Cannot initialize I2S for SPDIF bck:%d ws:%d do:%d", i2s_pin_config.bck_io_num,
i2s_pin_config.ws_io_num, i2s_pin_config.ws_io_num,
i2s_pin_config.data_out_num); i2s_pin_config.data_out_num);
} }
#endif
i2s_config.sample_rate = output.current_sample_rate * 2; i2s_config.sample_rate = output.current_sample_rate * 2;
i2s_config.bits_per_sample = 32; i2s_config.bits_per_sample = 32;
@@ -249,14 +236,12 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
i2s_set_pin(CONFIG_I2S_NUM, &i2s_pin_config); i2s_set_pin(CONFIG_I2S_NUM, &i2s_pin_config);
LOG_INFO("SPDIF using I2S bck:%u, ws:%u, do:%u", i2s_pin_config.bck_io_num, i2s_pin_config.ws_io_num, i2s_pin_config.data_out_num); LOG_INFO("SPDIF using I2S bck:%u, ws:%u, do:%u", i2s_pin_config.bck_io_num, i2s_pin_config.ws_io_num, i2s_pin_config.data_out_num);
} else { } else {
#ifdef CONFIG_SQUEEZEAMP #if CONFIG_SPDIF_DO_IO != -1
gpio_pad_select_gpio(CONFIG_SPDIF_DO_IO); gpio_pad_select_gpio(CONFIG_SPDIF_DO_IO);
gpio_set_direction(CONFIG_SPDIF_DO_IO, GPIO_MODE_OUTPUT); gpio_set_direction(CONFIG_SPDIF_DO_IO, GPIO_MODE_OUTPUT);
gpio_set_level(CONFIG_SPDIF_DO_IO, 0); gpio_set_level(CONFIG_SPDIF_DO_IO, 0);
adac = &dac_tas57xx;
#elif defined(CONFIG_A1S)
adac = &dac_a1s;
#endif #endif
i2s_config.sample_rate = output.current_sample_rate; i2s_config.sample_rate = output.current_sample_rate;
i2s_config.bits_per_sample = bytes_per_frame * 8 / 2; i2s_config.bits_per_sample = bytes_per_frame * 8 / 2;
// Counted in frames (but i2s allocates a buffer <= 4092 bytes) // Counted in frames (but i2s allocates a buffer <= 4092 bytes)
@@ -265,7 +250,12 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
dma_buf_frames = DMA_BUF_COUNT * DMA_BUF_LEN; dma_buf_frames = DMA_BUF_COUNT * DMA_BUF_LEN;
// finally let DAC driver initialize I2C and I2S // finally let DAC driver initialize I2C and I2S
adac->init(I2C_PORT, CONFIG_I2S_NUM, &i2s_config); if (dac_tas57xx.init(I2C_PORT, CONFIG_I2S_NUM, &i2s_config)) adac = &dac_tas57xx;
else if (dac_a1s.init(I2C_PORT, CONFIG_I2S_NUM, &i2s_config)) adac = &dac_a1s;
else {
dac_external.init(I2C_PORT, CONFIG_I2S_NUM, &i2s_config);
adac = &dac_external;
}
} }
LOG_INFO("Initializing I2S mode %s with rate: %d, bits per sample: %d, buffer frames: %d, number of buffers: %d ", LOG_INFO("Initializing I2S mode %s with rate: %d, bits per sample: %d, buffer frames: %d, number of buffers: %d ",

View File

@@ -78,15 +78,8 @@ static int tas57_detect(void);
* init * init
*/ */
static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config) { static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config) {
LOG_INFO("Initializing TAS57xx ");
i2c_port = i2c_port_num; i2c_port = i2c_port_num;
// init volume & mute
gpio_pad_select_gpio(VOLUME_GPIO);
gpio_set_direction(VOLUME_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(VOLUME_GPIO, 0);
// configure i2c // configure i2c
i2c_config_t i2c_config = { i2c_config_t i2c_config = {
.mode = I2C_MODE_MASTER, .mode = I2C_MODE_MASTER,
@@ -96,13 +89,26 @@ static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config) {
.scl_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 100000, .master.clk_speed = 100000,
}; };
i2c_param_config(i2c_port, &i2c_config); i2c_param_config(i2c_port, &i2c_config);
i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false); i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false);
LOG_INFO("DAC using I2C sda:%u, scl:%u", i2c_config.sda_io_num, i2c_config.scl_io_num);
// find which TAS we are using // find which TAS we are using (if any)
tas57_addr = tas57_detect(); tas57_addr = tas57_detect();
if (!tas57_addr) {
LOG_WARN("No TAS57xx detected");
i2c_driver_delete(i2c_port);
return 0;
}
LOG_INFO("TAS57xx DAC using I2C sda:%u, scl:%u", i2c_config.sda_io_num, i2c_config.scl_io_num);
// init volume & mute
gpio_pad_select_gpio(VOLUME_GPIO);
gpio_set_direction(VOLUME_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(VOLUME_GPIO, 0);
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create(); i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
for (int i = 0; tas57xx_init_sequence[i].reg != 0xff; i++) { for (int i = 0; tas57xx_init_sequence[i].reg != 0xff; i++) {
@@ -119,8 +125,8 @@ static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config) {
i2c_cmd_link_delete(i2c_cmd); i2c_cmd_link_delete(i2c_cmd);
// configure I2S pins & install driver // configure I2S pins & install driver
i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t) { .bck_io_num = 33, .ws_io_num = 25, i2s_pin_config_t i2s_pin_config = (i2s_pin_config_t) { .bck_io_num = CONFIG_I2S_BCK_IO, .ws_io_num = CONFIG_I2S_WS_IO,
.data_out_num = 32, .data_in_num = -1 //Not used .data_out_num = CONFIG_I2S_DO_IO, .data_in_num = CONFIG_I2S_DI_IO,
}; };
i2s_driver_install(i2s_num, i2s_config, 0, NULL); i2s_driver_install(i2s_num, i2s_config, 0, NULL);
i2s_set_pin(i2s_num, &i2s_pin_config); i2s_set_pin(i2s_num, &i2s_pin_config);

View File

@@ -40,34 +40,101 @@
#include "platform_esp32.h" #include "platform_esp32.h"
#define TELNET_STACK_SIZE 8048 /************************************
* Globals
*/
#define TELNET_STACK_SIZE 8048
#define TELNET_RX_BUF 1024
const static char tag[] = "telnet";
static int uart_fd=0;
RingbufHandle_t buf_handle; RingbufHandle_t buf_handle;
SemaphoreHandle_t xSemaphore = NULL; SemaphoreHandle_t xSemaphore = NULL;
static size_t send_chunk=300; static size_t send_chunk=300;
static size_t log_buf_size=2000; //32-bit aligned size static size_t log_buf_size=2000; //32-bit aligned size
static bool bIsEnabled=false; static bool bIsEnabled=false;
const static char tag[] = "telnet"; static int partnerSocket=0;
static void telnetTask(void *data);
static void doTelnet(int partnerSocket) ;
static int uart_fd=0;
// The global tnHandle ... since we are only processing ONE telnet
// client at a time, this can be a global static.
static telnet_t *tnHandle; static telnet_t *tnHandle;
static void handleLogBuffer(int partnerSocket, UBaseType_t bytes);
/************************************
* Forward declarations
*/
static void telnet_task(void *data);
static ssize_t stdout_read(int fd, void* data, size_t size);
static int stdout_open(const char * path, int flags, int mode);
static int stdout_close(int fd);
static int stdout_fstat(int fd, struct stat * st);
static ssize_t stdout_write(int fd, const void * data, size_t size);
static char *eventToString(telnet_event_type_t type);
static void handle_telnet_conn();
static void process_logs( UBaseType_t bytes);
struct telnetUserData { struct telnetUserData {
int sockfd; int sockfd;
telnet_t *tnHandle;
char * rxbuf;
}; };
static void telnetTask(void *data) {
ESP_LOGD(tag, ">> telnetTask");
int serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
void init_telnet(){
char *val= get_nvs_value_alloc(NVS_TYPE_STR, "telnet_enable");
if (!val || strlen(val) == 0 || !strcasestr("YX",val) ) {
ESP_LOGI(tag,"Telnet support disabled");
if(val) free(val);
return;
}
val=get_nvs_value_alloc(NVS_TYPE_STR, "telnet_block");
if(val){
send_chunk=atol(val);
free(val);
send_chunk=send_chunk>0?send_chunk:500;
}
val=get_nvs_value_alloc(NVS_TYPE_STR, "telnet_buffer");
if(val){
log_buf_size=atol(val);
free(val);
log_buf_size=log_buf_size>0?log_buf_size:4000;
}
// Create the semaphore to guard a shared resource.
vSemaphoreCreateBinary( xSemaphore );
// Redirect the output to our telnet handler as soon as possible
StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *)heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM);
uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*log_buf_size, MALLOC_CAP_SPIRAM);
buf_handle = xRingbufferCreateStatic(log_buf_size, RINGBUF_TYPE_BYTEBUF, buffer_storage, buffer_struct);
if (buf_handle == NULL) {
ESP_LOGE(tag,"Failed to create ring buffer for telnet!");
return;
}
ESP_LOGI(tag, "***Redirecting log output to telnet");
const esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &stdout_write,
.open = &stdout_open,
.fstat = &stdout_fstat,
.close = &stdout_close,
.read = &stdout_read,
};
uart_fd=open("/dev/uart/0", O_RDWR);
ESP_ERROR_CHECK(esp_vfs_register("/dev/pkspstdout", &vfs, NULL));
freopen("/dev/pkspstdout", "w", stdout);
freopen("/dev/pkspstdout", "w", stderr);
bIsEnabled=true;
}
void start_telnet(void * pvParameter){
static bool isStarted=false;
StaticTask_t *xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
StackType_t *xStack = malloc(TELNET_STACK_SIZE);
if(!isStarted && bIsEnabled) {
xTaskCreateStatic( (TaskFunction_t) &telnet_task, "telnet", TELNET_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, xTaskBuffer);
isStarted=true;
}
}
static void telnet_task(void *data) {
int serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in serverAddr; struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET; serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
@@ -93,155 +160,15 @@ static void telnetTask(void *data) {
return; return;
} }
else { else {
int partnerSocket = rc; partnerSocket = rc;
ESP_LOGD(tag, "We have a new client connection!"); ESP_LOGD(tag, "We have a new client connection!");
doTelnet(partnerSocket); handle_telnet_conn();
ESP_LOGD(tag, "Telnet connection terminated"); ESP_LOGD(tag, "Telnet connection terminated");
} }
} }
ESP_LOGD(tag, "<< telnetTask");
vTaskDelete(NULL); vTaskDelete(NULL);
} }
void start_telnet(void * pvParameter){
static bool isStarted=false;
if(!isStarted && bIsEnabled) {
StaticTask_t *xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
StackType_t *xStack = malloc(TELNET_STACK_SIZE);
xTaskCreateStatic( (TaskFunction_t) &telnetTask, "telnet", TELNET_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, xTaskBuffer);
isStarted=true;
}
}
static ssize_t stdout_write(int fd, const void * data, size_t size) {
if (xSemaphoreTake(xSemaphore, (TickType_t) 10) == pdTRUE) {
// #1 Write to ringbuffer
if (buf_handle == NULL) {
printf("%s() ABORT. file handle _log_remote_fp is NULL\n",
__FUNCTION__);
} else {
//Send an item
UBaseType_t res = xRingbufferSend(buf_handle, data, size,
pdMS_TO_TICKS(100));
if (res != pdTRUE) {
// flush some entries
handleLogBuffer(0, size);
res = xRingbufferSend(buf_handle, data, size,
pdMS_TO_TICKS(100));
if (res != pdTRUE) {
printf("%s() ABORT. Unable to store log entry in buffer\n",
__FUNCTION__);
}
}
}
xSemaphoreGive(xSemaphore);
} else {
// We could not obtain the semaphore and can therefore not access
// the shared resource safely.
}
return write(uart_fd, data, size);
}
static ssize_t uart_v_write(const char *fmt, va_list va) {
ssize_t required=vsnprintf(NULL,0,fmt,va);
if(required>0){
char * buf=malloc(required);
vsprintf(buf,fmt,va);
required=write(uart_fd, buf,required);
free(buf);
}
return required;
}
static ssize_t uart_printf(const char *fmt, ...) {
ssize_t printed=0;
va_list args;
va_start(args, fmt);
uart_v_write(fmt,args);
va_end(args);
return printed;
}
static ssize_t stdout_read(int fd, void* data, size_t size) {
return read(fd, data, size);
}
static int stdout_open(const char * path, int flags, int mode) {
return 0;
}
static int stdout_close(int fd) {
return 0;
}
static int stdout_fstat(int fd, struct stat * st) {
st->st_mode = S_IFCHR;
return 0;
}
void stdout_register() {
const esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &stdout_write,
.open = &stdout_open,
.fstat = &stdout_fstat,
.close = &stdout_close,
.read = &stdout_read,
};
uart_fd=open("/dev/uart/0", O_RDWR);
ESP_ERROR_CHECK(esp_vfs_register("/dev/pkspstdout", &vfs, NULL));
freopen("/dev/pkspstdout", "w", stdout);
freopen("/dev/pkspstdout", "w", stderr);
}
/*********************************
* Telnet Support
*/
void init_telnet(){
char *val= get_nvs_value_alloc(NVS_TYPE_STR, "telnet_enable");
if (!val || !strcasestr("YX",val) ) {
ESP_LOGI(tag,"Telnet support disabled");
if(val) free(val);
return;
}
val=get_nvs_value_alloc(NVS_TYPE_STR, "telnet_block");
if(val){
send_chunk=atol(val);
free(val);
send_chunk=send_chunk>0?send_chunk:500;
}
val=get_nvs_value_alloc(NVS_TYPE_STR, "telnet_buffer");
if(val){
log_buf_size=atol(val);
free(val);
log_buf_size=log_buf_size>0?log_buf_size:4000;
}
bIsEnabled=true;
// Create the semaphore to guard a shared resource.
vSemaphoreCreateBinary( xSemaphore );
// First thing we need to do here is to redirect the output to our telnet handler
//Allocate ring buffer data structure and storage area into external RAM
StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *)heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM);
uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*log_buf_size, MALLOC_CAP_SPIRAM);
//Create a ring buffer with manually allocated memory
buf_handle = xRingbufferCreateStatic(log_buf_size, RINGBUF_TYPE_BYTEBUF, buffer_storage, buffer_struct);
if (buf_handle == NULL) {
ESP_LOGE(tag,"Failed to create ring buffer for telnet!");
return;
}
ESP_LOGI(tag, "***Redirecting stdout and stderr output to telnet");
stdout_register();
}
/** /**
* Convert a telnet event type to its string representation. * Convert a telnet event type to its string representation.
*/ */
@@ -284,25 +211,30 @@ static char *eventToString(telnet_event_type_t type) {
/** /**
* Telnet handler. * Telnet handler.
*/ */
void processReceivedData(const char * buffer, size_t size){ void process_received_data(const char * buffer, size_t size){
//ESP_LOGD(tag, "received data, len=%d", event->data.size); //ESP_LOGD(tag, "received data, len=%d", event->data.size);
char * command = malloc(size+1); char * command = malloc(size+1);
memcpy(command,buffer,size); const char * c=buffer;
command[size]='\0';
// todo: implement conditional remote echo
//telnet_esp32_sendData((uint8_t *)command, size);
if(command[0]!='\r' && command[0]!='\n'){
// some telnet clients will send data and crlf in two separate buffers
printf(command);
printf("\r\n");
run_command((char *)command);
// scrub from any escape command
if(*c == '\e'){
while(*(c++) !='n'){
--size;
};
--size;
}
memcpy(command,c,size);
command[size]='\0';
if(command[0]!='\r' && command[0]!='\n'){
// echo the command buffer out to uart and run
write(uart_fd, command, size);
run_command((char *)command);
} }
free(command); free(command);
} }
static void telnetHandler( static void handle_telnet_events(
telnet_t *thisTelnet, telnet_t *thisTelnet,
telnet_event_t *event, telnet_event_t *event,
void *userData) { void *userData) {
@@ -317,23 +249,33 @@ static void telnetHandler(
break; break;
case TELNET_EV_DATA: case TELNET_EV_DATA:
processReceivedData(event->data.buffer, event->data.size); process_received_data(event->data.buffer, event->data.size);
break; break;
case TELNET_EV_TTYPE:
printf("telnet event: %s\n", eventToString(event->type));
telnet_ttype_send(telnetUserData->tnHandle);
break;
default: default:
printf("%s()=>telnet event: %s\n", __FUNCTION__, eventToString(event->type)); printf("telnet event: %s\n", eventToString(event->type));
break; break;
} // End of switch event type } // End of switch event type
} // myTelnetHandler } // myhandle_telnet_events
static void handleLogBuffer(int partnerSocket, UBaseType_t count){ static void process_logs(UBaseType_t count){
//Receive an item from no-split ring buffer //Receive an item from no-split ring buffer
size_t item_size; size_t item_size;
UBaseType_t uxItemsWaiting; UBaseType_t uxItemsWaiting;
UBaseType_t uxBytesToSend=count; UBaseType_t uxBytesToSend=count;
vRingbufferGetInfo(buf_handle, NULL, NULL, NULL,NULL, &uxItemsWaiting); vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting);
if(count == 0){
// this sends the entire buffer to the remote client
uxBytesToSend = uxItemsWaiting;
}
if( partnerSocket ==0 && (uxItemsWaiting*100 / log_buf_size) <75){ if( partnerSocket ==0 && (uxItemsWaiting*100 / log_buf_size) <75){
// We still have some room in the ringbuffer and there's no telnet // We still have some room in the ringbuffer and there's no telnet
// connection yet, so bail out for now. // connection yet, so bail out for now.
@@ -343,12 +285,12 @@ static void handleLogBuffer(int partnerSocket, UBaseType_t count){
while(uxBytesToSend>0){ while(uxBytesToSend>0){
char *item = (char *)xRingbufferReceiveUpTo(buf_handle, &item_size, pdMS_TO_TICKS(50), uxBytesToSend); char *item = (char *)xRingbufferReceiveUpTo(buf_handle, &item_size, pdMS_TO_TICKS(50), uxBytesToSend);
//Check received data
//Check received data
if (item != NULL) { if (item != NULL) {
uxBytesToSend-=item_size; uxBytesToSend-=item_size;
if(partnerSocket!=0 && tnHandle != NULL){ if(partnerSocket!=0){
telnet_send(tnHandle, (char *)item, item_size); telnet_send_text(tnHandle, item, item_size);
} }
//Return Item //Return Item
vRingbufferReturnItem(buf_handle, (void *)item); vRingbufferReturnItem(buf_handle, (void *)item);
@@ -359,42 +301,95 @@ static void handleLogBuffer(int partnerSocket, UBaseType_t count){
} }
} }
static void doTelnet(int partnerSocket) { static void handle_telnet_conn() {
//ESP_LOGD(tag, ">> doTelnet");
static const telnet_telopt_t my_telopts[] = {
{ TELNET_TELOPT_ECHO, TELNET_WILL, TELNET_DONT }, static const telnet_telopt_t my_telopts[] = {
{ TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO },
{ TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT }, { TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT },
{ TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO }, { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO },
{ TELNET_TELOPT_ZMP, TELNET_WONT, TELNET_DO }, { TELNET_TELOPT_ZMP, TELNET_WONT, TELNET_DO },
{ TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO }, { TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO },
{ TELNET_TELOPT_BINARY, TELNET_WILL, TELNET_DO }, { TELNET_TELOPT_BINARY, TELNET_WILL, TELNET_DO },
{ TELNET_TELOPT_NAWS, TELNET_WILL, TELNET_DONT }, { TELNET_TELOPT_NAWS, TELNET_WILL, TELNET_DONT },
{TELNET_TELOPT_LINEMODE, TELNET_WONT, TELNET_DO },
{ -1, 0, 0 } { -1, 0, 0 }
}; };
struct telnetUserData *pTelnetUserData = (struct telnetUserData *)malloc(sizeof(struct telnetUserData)); struct telnetUserData *pTelnetUserData = (struct telnetUserData *)malloc(sizeof(struct telnetUserData));
tnHandle = telnet_init(my_telopts, handle_telnet_events, 0, pTelnetUserData);
pTelnetUserData->rxbuf = (char *) heap_caps_malloc(TELNET_RX_BUF, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
pTelnetUserData->tnHandle = tnHandle;
pTelnetUserData->sockfd = partnerSocket; pTelnetUserData->sockfd = partnerSocket;
// flush all the log buffer on connect
process_logs(0);
tnHandle = telnet_init(my_telopts, telnetHandler, 0, pTelnetUserData);
uint8_t buffer[1024];
while(1) { while(1) {
//ESP_LOGD(tag, "waiting for data"); //ESP_LOGD(tag, "waiting for data");
ssize_t len = recv(partnerSocket, (char *)buffer, sizeof(buffer), MSG_DONTWAIT); ssize_t len = recv(partnerSocket, pTelnetUserData->rxbuf, TELNET_RX_BUF, MSG_DONTWAIT);
if (len >0 ) { if (len >0 ) {
//ESP_LOGD(tag, "received %d bytes", len); telnet_recv(tnHandle, pTelnetUserData->rxbuf, len);
telnet_recv(tnHandle, (char *)buffer, len);
} }
else if (errno != EAGAIN && errno !=EWOULDBLOCK ){ else if (errno != EAGAIN && errno !=EWOULDBLOCK ){
telnet_free(tnHandle); telnet_free(tnHandle);
tnHandle = NULL; tnHandle = NULL;
free(pTelnetUserData->rxbuf);
pTelnetUserData->rxbuf=NULL;
free(pTelnetUserData); free(pTelnetUserData);
partnerSocket = 0;
return; return;
} }
handleLogBuffer(partnerSocket, send_chunk); process_logs(send_chunk);
taskYIELD(); taskYIELD();
} }
} // doTelnet } // handle_telnet_conn
// ******************* stdout/stderr Redirection to ringbuffer
static ssize_t stdout_write(int fd, const void * data, size_t size) {
if (xSemaphoreTake(xSemaphore, (TickType_t) 10) == pdTRUE) {
// #1 Write to ringbuffer
if (buf_handle == NULL) {
printf("%s() ABORT. file handle _log_remote_fp is NULL\n",
__FUNCTION__);
} else {
//Send an item
UBaseType_t res = xRingbufferSend(buf_handle, data, size,
pdMS_TO_TICKS(100));
if (res != pdTRUE) {
// flush some entries
process_logs(size);
res = xRingbufferSend(buf_handle, data, size,
pdMS_TO_TICKS(100));
if (res != pdTRUE) {
printf("%s() ABORT. Unable to store log entry in buffer\n",
__FUNCTION__);
}
}
}
xSemaphoreGive(xSemaphore);
} else {
// We could not obtain the semaphore and can therefore not access
// the shared resource safely.
}
return write(uart_fd, data, size);
}
static ssize_t stdout_read(int fd, void* data, size_t size) {
return read(fd, data, size);
}
static int stdout_open(const char * path, int flags, int mode) {
return 0;
}
static int stdout_close(int fd) {
return 0;
}
static int stdout_fstat(int fd, struct stat * st) {
st->st_mode = S_IFCHR;
return 0;
}

View File

@@ -1,4 +1,3 @@
static ssize_t uart_printf(const char *fmt, ...);
void init_telnet(); void init_telnet();
void start_telnet(void * pvParameter); void start_telnet(void * pvParameter);

View File

@@ -382,6 +382,7 @@
<li>jQuery, The jQuery Foundation. Licensed under the MIT License.</li> <li>jQuery, The jQuery Foundation. Licensed under the MIT License.</li>
<li>cJSON, &copy; 2009-2017, Dave Gamble and cJSON contributors. Licensed under the MIT License.</li> <li>cJSON, &copy; 2009-2017, Dave Gamble and cJSON contributors. Licensed under the MIT License.</li>
<li>esp32-rotary-encoder, &copy; 2011-2019, David Antliff and Ben Buxton. Licensed under the GPL License.</li> <li>esp32-rotary-encoder, &copy; 2011-2019, David Antliff and Ben Buxton. Licensed under the GPL License.</li>
<li>tarablessd1306, &copy; 2017-2018, Tara Keeling. Licensed under the MIT license.</li>
</ul> </ul>
</div> </div>
<h2>Show NVS Editor</h2> <h2>Show NVS Editor</h2>

View File

@@ -21,99 +21,106 @@ menu "Squeezelite-ESP32"
help help
Set logging level info|debug|sdebug Set logging level info|debug|sdebug
endmenu endmenu
menu "Audio CODEC libraries" config JACK_LOCKED
config INCLUDE_FLAC bool
bool "FLAC" config BAT_LOCKED
default 1 bool
help config I2C_LOCKED
Include FLAC library for flc decoding. bool
config INCLUDE_FAAD config SPDIF_LOCKED
bool "FAAD" bool
default 1 config LED_LOCKED
help bool
Include FAAD library for aac decoding. config SPKFAULT_LOCKED
config INCLUDE_MAD bool
bool "MAD" menu "Audio Output"
default 1
help
Include mad library for mp3 decoding.
config INCLUDE_VORBIS
bool "VORBIS"
default 1
help
Include vorbis/ogg library for ogg/vorbis decoding.
config INCLUDE_ALAC
bool "ALAC"
default 1
help
Include alac library for alac decoding.
config INCLUDE_OPUS
bool "OPUS"
default 1
help
Include opus library for opus decoding.
endmenu
menu "Audio Output"
choice OUTPUT_TYPE choice OUTPUT_TYPE
prompt "Output Type" prompt "Output Type"
default BASIC_I2C_BT default BASIC_I2C_BT
help help
Type of hardware platform Type of hardware platform
config SQUEEZEAMP config SQUEEZEAMP
bool "SqueezeAMP (TAS575x & Bluetooth)" bool "SqueezeAMP"
select JACK_LOCKED
select BAT_LOCKED
select I2C_LOCKED
select SPDIF_LOCKED
select LED_LOCKED
select SPKFAULT_LOCKED
config A1S config A1S
bool "ESP32-A1S module" bool "ESP32-A1S module"
select I2C_LOCKED
config BASIC_I2C_BT config BASIC_I2C_BT
bool "Generic I2S & Bluetooth" bool "Generic I2S & Bluetooth"
endchoice endchoice
menu "DAC I2S settings" menu "DAC I2S settings"
depends on BASIC_I2C_BT visible if BASIC_I2C_BT
config I2S_NUM config I2S_NUM
int "I2S channel (0 or 1). " int "I2S channel (0 or 1). "
default 0 default 0
help help
I2S dma channel to use. I2S dma channel to use.
config I2S_BCK_IO config I2S_BCK_IO
int "I2S Bit clock GPIO number. " int "I2S Bit clock GPIO number. "
default 33 default 33 if !A1S
default 27 if A1S
help help
I2S Bit Clock gpio pin to use. I2S Bit Clock gpio pin to use.
config I2S_WS_IO config I2S_WS_IO
int "I2S Word Select GPIO number. " int "I2S Word Select GPIO number. "
default 25 default 25 if !A1S
default 26 if A1S
help help
I2S Word Select gpio pin to use. I2S Word Select gpio pin to use.
config I2S_DO_IO config I2S_DO_IO
int "I2S Data I/O GPIO number. " int "I2S Data Output GPIO number. "
default 32 default 32 if !A1S
default 25 if A1S
help help
I2S data I/O gpio pin to use. I2S data output gpio pin to use.
config I2S_DI_IO
int "I2S Data Input GPIO number. "
default -1 if !A1S
default 35 if A1S
help
I2S data input gpio pin to use (not used mostly, leave it to -1).
endmenu endmenu
menu "SPDIF settings" menu "SPDIF settings"
depends on BASIC_I2C_BT || A1S visible if BASIC_I2C_BT
config SDIF_NUM config SDIF_NUM
int "SDPIF/I2S channel (0 or 1)" int "I2S channel for SDPIF (0 or 1)"
default 0 default 0
help help
I2S dma channel to use. I2S dma channel to use.
config SPDIF_BCK_IO config SPDIF_BCK_IO
int "SDPIF/I2S Bit clock GPIO number" int "SDPIF Bit clock GPIO number"
default -1 default I2S_BCK_IO
help help
Must be set even if you don't use SPDIF Must be set as SPDIF re-uses I2S but only needs DO (recommendation: set it to I2S Bit clock value)
config SPDIF_WS_IO config SPDIF_WS_IO
int "SPDIF/I2S Word Select GPIO number" int "SPDIF Word Select GPIO number"
default -1 default I2S_WS_IO
help help
Must be set even if you don't use SPDIF Must be set as SPDIF re-uses I2S but only needs DO (recommendation: set it to I2S Word select value)
config SPDIF_DO_IO config SPDIF_DO_IO
int "I2S Data I/O GPIO number" int "SPDIF Data I/O GPIO number"
default -1 default 15 if SQUEEZEAMP
help default I2S_DO_IO if !A1S
Must be set even if you don't use SPDIF default -1 if A1S
help
I2S data output IO use to simulate SPDIF
endmenu
menu "SPDIF settings"
visible if A1S
config SPDIF_DO_IO
int "SPDIF Data I/O GPIO number"
default -1
help
I2S data output IO use to simulate SPDIF
endmenu endmenu
menu "A2DP settings" menu "A2DP settings"
@@ -179,11 +186,8 @@ menu "Squeezelite-ESP32"
default "" default ""
help help
Set parameters for display screen, leave empty for no screen Set parameters for display screen, leave empty for no screen
I2C,width=<size>,height=<size> I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,HFlip][,VFlip]
SPI,width=<size>,height=<size>,select=<gpio> SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,HFlip][,VFlip]
config DISPLAY_I2C_SPEED
int "I2C bus speed"
default 250000
endmenu endmenu
menu "Various I/O" menu "Various I/O"
@@ -192,26 +196,96 @@ menu "Squeezelite-ESP32"
default "" default ""
help help
Set parameters of shared I2C interface Set parameters of shared I2C interface
sda=<gpio>,scl=<gpio>,speed=<num>,port=<0|1> sda=<gpio>,scl=<gpio>[,speed=<num>][,port=<0|1>]
config SPI_CONFIG
string "SPI system configuration"
default ""
help
Set parameters of shared SPI interface
data=<gpio>,clk=<gpio>[,d/c=<num>][,host=<0|1|2>]
config SET_GPIO
string "Special GPIO configuration"
default ""
help
Set parameters of shared GPIO with special values.
<gpio_1>=Vcc|GND|amp|jack[:0|1][,<gpio_n>=Vcc|GND|amp|jack[:0|1]]
'amp' => GPIO that is set when playback starts
'jack' => GPIO used for audio jack detection
'green', 'red' => GPIO for status LED
'[:0|1] means set the active value for that GPIO can be low or high
config ROTARY_ENCODER
string "Rotary Encoder configuration"
default ""
help
Set GPIO for rotary encoder (quadrature phase). See README on SqueezeESP32 project's GitHub for more details
A=<gpio>,B=<gpio>[,SW=gpio>[,volume][,longpress]]
endmenu
menu "LED configuration"
visible if !SQUEEZEAMP
config LED_GREEN_GPIO config LED_GREEN_GPIO
int "Green led GPIO" int "Green led GPIO"
default -1 default -1 if !SQUEEZEAMP
default 12 if SQUEEZEAMP
help help
Set to -1 for no LED Set to -1 for no LED
config LED_GREEN_GPIO_LEVEL
int "Green led ON level"
depends on LED_GREEN_GPIO != -1
default 0 if SQUEEZEAMP
default 1 if !SQUEEZEAMP
config LED_RED_GPIO config LED_RED_GPIO
int "Red led GPIO" int "Red led GPIO"
default -1 default -1 if !SQUEEZEAMP
default 13 if SQUEEZEAMP
help help
Set to -1 for no LED Set to -1 for no LED
config LED_RED_GPIO_LEVEL
int "Red led ON level"
depends on LED_RED_GPIO != -1
default 0 if SQUEEZEAMP
default 1 if !SQUEEZEAMP
endmenu
menu "Audio JACK"
visible if !SQUEEZEAMP
config JACK_GPIO config JACK_GPIO
int "Jack insertion GPIO" int "Jack insertion GPIO"
default -1 default -1 if !SQUEEZEAMP
default 34 if SQUEEZEAMP
help help
GPIO to detect speaker jack insertion. Set to -1 for no detection GPIO to detect speaker jack insertion. Set to -1 for no detection.
config JACK_GPIO_LEVEL config JACK_GPIO_LEVEL
depends on JACK_GPIO != -1 depends on JACK_GPIO != -1
int "Level when inserted (0/1)" int "Level when inserted (0/1)"
default 0 default 0
endmenu
menu "Speaker Fault"
visible if !SQUEEZEAMP
config SPKFAULT_GPIO
int "Speaker fault GPIO"
default -1 if !SQUEEZEAMP
default 2 if SQUEEZEAMP
help
GPIO to detect speaker fault condition. Set to -1 for no detection.
config SPKFAULT_GPIO_LEVEL
depends on SPKFAULT_GPIO != -1
int "Level when fault (0/1)"
default 0
endmenu
menu "Battery measure"
visible if !SQUEEZEAMP
config BAT_CHANNEL
int "Set channel (0..7)"
default -1 if !SQUEEZEAMP
default 7 if SQUEEZEAMP
help
Read a value every 10s on ADC1 on set Channel
config BAT_SCALE
string "Set scaling factor"
depends on BAT_CHANNEL != -1
default "" if !SQUEEZEAMP
default "20.24" if SQUEEZEAMP
help
Set the scaling factor for this 12 bits ADC
endmenu endmenu
endmenu endmenu

View File

@@ -281,8 +281,8 @@ void register_default_nvs(){
ESP_LOGD(TAG,"Registering default Audio control board type %s, value ","actrls_config"); ESP_LOGD(TAG,"Registering default Audio control board type %s, value ","actrls_config");
config_set_default(NVS_TYPE_STR, "actrls_config", "", 0); config_set_default(NVS_TYPE_STR, "actrls_config", "", 0);
ESP_LOGD(TAG,"Registering default Audio control board type %s, value ","rotary_config"); ESP_LOGD(TAG,"Registering default Audio control board type %s, value %s", "rotary_config", CONFIG_ROTARY_ENCODER);
config_set_default(NVS_TYPE_STR, "rotary_config", "", 0); config_set_default(NVS_TYPE_STR, "rotary_config", CONFIG_ROTARY_ENCODER, 0);
char number_buffer[101] = {}; char number_buffer[101] = {};
snprintf(number_buffer,sizeof(number_buffer)-1,"%u",OTA_FLASH_ERASE_BLOCK); snprintf(number_buffer,sizeof(number_buffer)-1,"%u",OTA_FLASH_ERASE_BLOCK);
@@ -303,14 +303,26 @@ void register_default_nvs(){
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "enable_airplay", STR(CONFIG_AIRPLAY_SINK)); ESP_LOGD(TAG,"Registering default value for key %s, value %s", "enable_airplay", STR(CONFIG_AIRPLAY_SINK));
config_set_default(NVS_TYPE_STR, "enable_airplay", STR(CONFIG_AIRPLAY_SINK), 0); config_set_default(NVS_TYPE_STR, "enable_airplay", STR(CONFIG_AIRPLAY_SINK), 0);
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "display_config", STR(CONFIG_DISPLAY_CONFIG)); ESP_LOGD(TAG,"Registering default value for key %s, value %s", "display_config", CONFIG_DISPLAY_CONFIG);
config_set_default(NVS_TYPE_STR, "display_config", STR(CONFIG_DISPLAY_CONFIG), 0); config_set_default(NVS_TYPE_STR, "display_config", CONFIG_DISPLAY_CONFIG, 0);
ESP_LOGD(TAG,"Registering default value for key %s", "i2c_config"); ESP_LOGD(TAG,"Registering default value for key %s, value %s", "i2c_config", CONFIG_I2C_CONFIG);
config_set_default(NVS_TYPE_STR, "i2c_config", "", 0); config_set_default(NVS_TYPE_STR, "i2c_config", CONFIG_I2C_CONFIG, 0);
ESP_LOGD(TAG,"Registering default value for key %s", "set_GPIO"); ESP_LOGD(TAG,"Registering default value for key %s, value %s", "spi_config", CONFIG_SPI_CONFIG);
config_set_default(NVS_TYPE_STR, "set_GPIO", "", 0); config_set_default(NVS_TYPE_STR, "spi_config", CONFIG_SPI_CONFIG, 0);
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "set_GPIO", CONFIG_SET_GPIO);
config_set_default(NVS_TYPE_STR, "set_GPIO", CONFIG_SET_GPIO, 0);
ESP_LOGD(TAG,"Registering default value for key %s", "spdif_config");
config_set_default(NVS_TYPE_STR, "spdif_config", "", 0);
ESP_LOGD(TAG,"Registering default value for key %s", "dac_config");
config_set_default(NVS_TYPE_STR, "dac_config", "", 0);
ESP_LOGD(TAG,"Registering default value for key %s", "bat_config");
config_set_default(NVS_TYPE_STR, "bat_config", "", 0);
ESP_LOGD(TAG,"Registering default value for key %s", "metadata_config"); ESP_LOGD(TAG,"Registering default value for key %s", "metadata_config");
config_set_default(NVS_TYPE_STR, "metadata_config", "", 0); config_set_default(NVS_TYPE_STR, "metadata_config", "", 0);
@@ -327,12 +339,6 @@ void register_default_nvs(){
ESP_LOGD(TAG,"Registering default value for key %s", "stats"); ESP_LOGD(TAG,"Registering default value for key %s", "stats");
config_set_default(NVS_TYPE_STR, "stats", "n", 0); config_set_default(NVS_TYPE_STR, "stats", "n", 0);
ESP_LOGD(TAG,"Registering default value for key %s", "spdif_config");
config_set_default(NVS_TYPE_STR, "spdif_config", "", 0);
ESP_LOGD(TAG,"Registering default value for key %s", "dac_config");
config_set_default(NVS_TYPE_STR, "dac_config", "", 0);
ESP_LOGD(TAG,"Done setting default values in nvs."); ESP_LOGD(TAG,"Done setting default values in nvs.");
} }

Binary file not shown.

View File

@@ -7,6 +7,7 @@ use Slim::Utils::Log;
use Slim::Utils::Prefs; use Slim::Utils::Prefs;
my $prefs = preferences('plugin.squeezeesp32'); my $prefs = preferences('plugin.squeezeesp32');
my $log = logger('plugin.squeezeesp32');
sub model { 'squeezeesp32' } sub model { 'squeezeesp32' }
sub modelName { 'SqueezeESP32' } sub modelName { 'SqueezeESP32' }
@@ -23,10 +24,11 @@ sub playerSettingsFrame {
# New SETD command 0xfe for display width # New SETD command 0xfe for display width
if ($id == 0xfe) { if ($id == 0xfe) {
$value = (unpack('CC', $$data_ref))[1]; $value = (unpack('CC', $$data_ref))[1];
if ($value > 10 && $value < 200) { if ($value > 100 && $value < 400) {
$client->display->widthOverride(1, $value); $client->display->widthOverride(1, $value);
$client->update; $client->update;
} }
$log->info("Setting player width $value for ", $client->name);
} }
$client->SUPER::playerSettingsFrame($data_ref); $client->SUPER::playerSettingsFrame($data_ref);

View File

@@ -10,6 +10,6 @@
<name>PLUGIN_SQUEEZEESP32</name> <name>PLUGIN_SQUEEZEESP32</name>
<description>PLUGIN_SQUEEZEESP32_DESC</description> <description>PLUGIN_SQUEEZEESP32_DESC</description>
<module>Plugins::SqueezeESP32::Plugin</module> <module>Plugins::SqueezeESP32::Plugin</module>
<version>0.8</version> <version>0.9</version>
<creator>Philippe</creator> <creator>Philippe</creator>
</extensions> </extensions>

View File

@@ -1,10 +1,10 @@
<?xml version='1.0' standalone='yes'?> <?xml version='1.0' standalone='yes'?>
<extensions> <extensions>
<plugins> <plugins>
<plugin version="0.8" name="SqueezeESP32" minTarget="7.5" maxTarget="*"> <plugin version="0.9" name="SqueezeESP32" minTarget="7.5" maxTarget="*">
<link>https://github.com/sle118/squeezelite-esp32</link> <link>https://github.com/sle118/squeezelite-esp32</link>
<creator>Philippe</creator> <creator>Philippe</creator>
<sha>66cde7aee1f92e82087e5a7a68c6d57f1229e2a0</sha> <sha>89c68b54ad4373df6c0cd37222a07b53013c4815</sha>
<email>philippe_44@outlook.com</email> <email>philippe_44@outlook.com</email>
<desc lang="EN">SqueezeESP32 additional player id (100)</desc> <desc lang="EN">SqueezeESP32 additional player id (100)</desc>
<url>http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip</url> <url>http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip</url>

View File

@@ -11,11 +11,7 @@ CONFIG_IDF_TARGET="esp32"
CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-" CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-"
CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES=y CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES=y
CONFIG_APP_COMPILE_TIME_DATE=y CONFIG_APP_COMPILE_TIME_DATE=y
CONFIG_OTA_ALLOW_HTTP=y
CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y
@@ -28,10 +24,12 @@ CONFIG_BOOTLOADER_WDT_ENABLE=y
CONFIG_BOOTLOADER_WDT_TIME_MS=9000 CONFIG_BOOTLOADER_WDT_TIME_MS=9000
CONFIG_ESPTOOLPY_BAUD_2MB=y
CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
CONFIG_ESPTOOLPY_BAUD=2000000
CONFIG_ESPTOOLPY_COMPRESSED=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
@@ -104,7 +102,6 @@ CONFIG_DEFAULT_AP_NETMASK="255.255.255.0"
CONFIG_DEFAULT_AP_MAX_CONNECTIONS=4 CONFIG_DEFAULT_AP_MAX_CONNECTIONS=4
CONFIG_DEFAULT_AP_BEACON_INTERVAL=100 CONFIG_DEFAULT_AP_BEACON_INTERVAL=100
CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30" CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30"
CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
@@ -602,7 +599,6 @@ CONFIG_LWIP_LOCAL_HOSTNAME="espressif"
CONFIG_LWIP_TIMERS_ONDEMAND=y CONFIG_LWIP_TIMERS_ONDEMAND=y
CONFIG_LWIP_MAX_SOCKETS=16 CONFIG_LWIP_MAX_SOCKETS=16
CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE=y
CONFIG_LWIP_SO_REUSE_RXTOALL=y CONFIG_LWIP_SO_REUSE_RXTOALL=y
@@ -779,9 +775,9 @@ CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y
CONFIG_VFS_SUPPORT_TERMIOS=y CONFIG_VFS_SUPPORT_TERMIOS=y
CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
CONFIG_WL_SECTOR_SIZE_512=y
CONFIG_WL_SECTOR_SIZE_4096=y #CONFIG_WL_SECTOR_SIZE_4096 is not defined
CONFIG_WL_SECTOR_SIZE=4096 CONFIG_WL_SECTOR_SIZE=512
CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16