Compare commits

..

32 Commits

Author SHA1 Message Date
philippe44
752cfbf3b2 Update .gitattributes 2025-03-30 14:19:09 +02:00
philippe44
cecb7fd876 Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2025-02-17 23:26:07 +01:00
philippe44
e92e431b45 add MCK in get_dac_config 2025-02-17 23:26:01 +01:00
philippe44
db792e47bd Update Platform_build.yml 2025-02-17 22:47:05 +01:00
philippe44
a22f75a13a limit display checks 2025-02-17 22:39:48 +01:00
philippe44
1f220895e6 Update README.md 2025-02-17 12:55:44 +01:00
philippe44
769ff99f7d Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2024-09-28 23:17:23 +02:00
philippe44
424fb93ec4 add 2nd encoder for volume only 2024-09-28 23:17:09 +02:00
philippe44
e270963dbd Update README.md 2024-09-28 23:11:52 +02:00
philippe44
2cae41d29c Update README.md 2024-09-28 23:11:10 +02:00
philippe44
84b95cd79c Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2024-09-28 18:55:48 +02:00
philippe44
6369f4bd69 another misplaced NVS #ifdef 2024-09-28 18:55:43 +02:00
philippe44
4c1bca3166 Update CHANGELOG 2024-09-28 14:43:23 +02:00
philippe44
3a5163e6f6 Update esp_app_main.c
autoexec default was created at the wrong place!
2024-09-28 14:42:08 +02:00
philippe44
cbe42b56bc Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2024-09-27 18:53:46 +02:00
philippe44
ab9812cb75 make i2s emergency stop platform independant 2024-09-27 18:52:26 +02:00
philippe44
084caedd7e Update README.md 2024-09-27 16:35:15 +02:00
philippe44
f254bf49af Update README.md 2024-09-27 15:35:59 +02:00
philippe44
66bd26f007 Update README.md 2024-09-27 15:35:03 +02:00
philippe44
dd6c932c39 Update README.md 2024-09-27 15:06:38 +02:00
philippe44
50070378ad Merge pull request #440 from digidocs/loudness_plugin_fix1
SqueezeESP32 plugin loudness control fix
2024-09-12 12:33:31 +02:00
github-actions
b50bc8f376 Update prebuilt objects [skip actions] 2024-09-12 09:32:21 +00:00
philippe44
e6723dfa2f Update CHANGELOG 2024-09-12 11:27:55 +02:00
philippe44
ffaff5ac27 Merge pull request #430 from StefanKrupop/aw9523_expander
Add support for AW9523 GPIO expander
2024-09-12 11:25:31 +02:00
philippe44
33ef4b01e7 Update CHANGELOG 2024-09-12 11:24:23 +02:00
github-actions
302865b167 Update prebuilt objects [skip actions] 2024-09-11 18:05:43 +00:00
David Carr
fdd8b0a4c9 Change to //= operator 2024-09-04 14:48:07 -05:00
David Carr
f8d7ac23e1 Updated SqueezeESP32 plugin and zip file 2024-08-21 12:07:57 -05:00
David Carr
befc81f573 Fix for wrong loudness value being sent when user requests loudness 0 2024-08-21 11:01:18 -05:00
Stefan Krupop
9d71b8ee26 Added "aw9523" to list of possible expanders 2024-07-26 21:01:10 +02:00
Stefan Krupop
672aca8258 Fixed resetting interrupt 2024-07-26 20:18:55 +02:00
Stefan Krupop
a2351ba0d5 Add support for AW9523 port expander 2024-07-25 01:13:14 +02:00
44 changed files with 313 additions and 155 deletions

2
.gitattributes vendored
View File

@@ -1,5 +1,5 @@
# Auto detect text files and perform LF normalization
* text=auto
# * text=auto
# Custom for Visual Studio
*.cs diff=csharp

View File

@@ -171,7 +171,7 @@ jobs:
zip build/${artifact_file_name} partitions*.csv components/ build/*.bin build/bootloader/bootloader.bin build/partition_table/partition-table.bin build/flash_project_args build/size_*.txt
fi
- name: Upload Build Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: ${{ needs.bootstrap.outputs.mock == 0 }}
with:
name: ${{ env.artifact_prefix }}

View File

@@ -1,3 +1,21 @@
2025-02-17
- reverse some checks on display not NULL in gds.c. As it is about being fast, I'd prefer the caller to know that there is no display and don't call. I'm sure I have missed something when there is only led_vu and no display, but people will remind me soon enough :-)
2024-09-28
- add dedicated volume encoder
- fix memory leak in rotary config creation
2024-09-28
- create autoexec NVS entry at the right place (not only whne BT is enabled!
- try to make i2s panic mode work for all esp versions
2024-09-12
- add AW9523 GPIO expander credits @Stefan Krupop (https://github.com/sle118/squeezelite-esp32/pull/430
2024-09-10
- Merge pull request # 439 from digidocs/eq_update_fix2 (# 309)
- Fix for I2S noise burst when ESP32 panic occurs (# 437)
2024-05-05
- Fix crash when led_vu is configured without display
2024-01-27

View File

@@ -15,6 +15,7 @@ Depending on the hardware connected to the esp32, you can send audio to a local
But squeezelite-esp32 is highly extensible and you can add
- [Buttons](#buttons) and [Rotary Encoder](#rotary-encoder) and map/combine them to various functions (play, pause, volume, next ...)
- [Volume Encoder](#volume-rotary-encoder) for a dedicated volume rotary encoder
- [GPIO expander](#gpio-expanders) (buttons, led and rotary)
- [IR receiver](#infrared) (no pullup resistor or capacitor needed, just the 38kHz receiver)
- [Monochrome, GrayScale or Color displays](#display) using SPI or I2C (supported drivers are SH1106, SSD1306, SSD1322, SSD1326/7, SSD1351, ST7735, ST7789 and ILI9341).
@@ -308,7 +309,7 @@ The parameter "gpio_exp_config" is a semicolon (;) separated list with following
```
model=<model>,addr=<addr>,[,port=system|dac][,base=<n>][,count=<n>][,intr=<gpio>][,cs=<gpio>][,speed=<Hz>]
```
- model: pca9535, pca85xx, mcp23017 and mcp23s17 (SPI version)
- model: pca9535, pca85xx, mcp23017, aw9523 and mcp23s17 (SPI version)
- addr: chip i2c/spi address (decimal)
- port (I2C): use either "system" port (shared with display for example) or "dac" port (system is default)
- cs (SPI): gpio used for Chip Select
@@ -341,9 +342,9 @@ The latest LMS plugin update is required to set the visualizer mode and brightne
| \<playerid\> dmx \<R,G,B,R,G,B, ... R,G,B\> \[\<offset\>\] | Sets the LED color starting at position "offset"<br /> with "R"(red),"G"(green),and "B"(blue) color sequences.<br />Add additional RGB values to the delimited string to set multiple LEDs.<br /> |
### 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 general 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.
Encoder is normally hard-coded to respectively knob left, right and push on LMS and to volume down/up/play toggle on BT and AirPlay. Using the option 'volume' makes it hard-coded to volume down/up/play toggle all the time (even in LMS). The option 'longpress' allows an alternate mode when SW is long-pressed. In that mode, left is previous, right is next and press is toggle. Every long press on SW alternates between modes (the main mode actual behavior depends on 'volume').
Encoder is normally hard-coded to respectively knob left, right and push on LMS and to volume down/up/play toggle on BT, AirPlay and Spotify. Using the option 'volume' makes it hard-coded to volume down/up/play toggle all the time (even in LMS). The option 'longpress' allows an alternate mode when SW is long-pressed. In that mode, left is previous, right is next and press is toggle. Every long press on SW alternates between modes (the main mode actual behavior depends on 'volume').
There is also the possibility to use 'knobonly' option (exclusive with 'volume' and 'longpress'). This mode attempts to offer a single knob full navigation which is a bit contorded due to LMS UI's principles. Left, Right and Press obey to LMS's navigation rules and especially Press always goes to lower submenu item, even when navigating in the Music Library. That causes a challenge as there is no 'Play', 'Back' or 'Pause' button. Workaround are as of below:
- longpress is 'Play'
@@ -364,7 +365,16 @@ The SW gpio is optional, you can re-affect it to a pure button if you prefer but
See also the "IMPORTANT NOTE" on the "Buttons" section and remember that when 'lms_ctrls_raw' (see below) is activated, none of these knobonly,volume,longpress options apply, raw button codes (not actions) are simply sent to LMS
**Note that gpio 36 and 39 are input only and cannot use interrupt, so they cannot be set to A or B. When using them for SW, a 100ms polling is used which is expensive**
**Note that on esp32, gpio 36 and 39 are input only and cannot use interrupt, so they cannot be set to A or B. When using them for SW, a 100ms polling is used which is expensive**
### Volume Rotary Encoder
One dedicated volume rotary encoder is supported, quadrature shift with press. Encoder is hard-coded to volume-up, down and play toggle for LMS, BT, AirPlay and Spotify (see note above for filtering and HW note as well GPIO 36 and 39 on esp32)
Use parameter volume_rotary with the following syntax:
```
A=<gpio>,B=<gpio>[,SW=gpio>]
```
### Buttons
Buttons are described using a JSON string with the following syntax
@@ -632,10 +642,14 @@ docker run -it -v `pwd`:/workspace/squeezelite-esp32 sle118/squeezelite-esp32-id
The above command will mount this repo into the docker container and start a bash terminal. From there, simply run idf.py build to build, etc. Note that at the time of writing these lines, flashing is not possible for docker running under windows https://github.com/docker/for-win/issues/1018.
### Manual Install of ESP-IDF
You can install IDF manually on Linux or Windows (using the Subsystem for Linux) following the instructions at: https://www.instructables.com/id/ESP32-Development-on-Windows-Subsystem-for-Linux/ or see here https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html for a direct install. You also need a few extra Python libraries for cspot by addingsudo `pip3 install protobuf grpcio-tools`
**Use the esp-idf 4.3.5 https://github.com/espressif/esp-idf/tree/release/v4.3.5 ** or the 4.4.5 (and above version) if you want to build for esp32-s3
First you need git and python (e.g 3.10.x), install these and let it add to system path.
**Use the esp-idf 4.3.5 https://github.com/espressif/esp-idf/tree/release/v4.3.5 ** or the 4.4.5 (and above version) if you want to build for esp32-s3. You should clone recursively the whole branch (at the version you need) `git clone -b v4.3.5 https://github.com/espressif/esp-idf --recursive`and run the installer (`install.bat [esp32[,esp32s3]]` from there. Some Windows version (at least) have now a SSL certificate issue. You can workaround this by editing idf-tools.py and adding the following under ìmport ssl`
```
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
```
And because the fun never ends, some Windows installations might fail to build a few files and spit a tons of errors on the output. It seems that the cache of the compile is a problem, so try to disable it by running `idf.py --no-ccache build` (I know...)
## Building SqueezeESP32
When initially cloning the repo, make sure you do it recursively. For example: `git clone --recursive https://github.com/sle118/squeezelite-esp32.git`. You also should install cspot additional components for protobuf use.
```

View File

@@ -705,26 +705,6 @@ esp_err_t i2s_stop(i2s_port_t i2s_num)
return ESP_OK;
}
/*
* When a panic occurs during playback, the I2S interface can produce a loud noise burst.
* This code runs just before the system panic handler to "emergency stop" the I2S iterface
* to prevent the noise burst from happening. Note that when this code is called the system
* has already crashed, so no need to disable interrupts, acquire locks, or otherwise be nice.
*
* This code makes use of the linker --wrap feature to intercept the call to esp_panic_handler.
*/
void __real_esp_panic_handler(void*);
void __wrap_esp_panic_handler (void* info) {
esp_rom_printf("I2S abort!\r\n");
i2s_hal_stop_tx(&(p_i2s_obj[CONFIG_I2S_NUM]->hal));
/* Call the original panic handler function to finish processing this error */
__real_esp_panic_handler(info);
}
#if SOC_I2S_SUPPORTS_ADC_DAC
esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode)
{

View File

@@ -54,7 +54,6 @@ struct GDS_Device* GDS_AutoDetect( char *Driver, GDS_DetectFunc* DetectFunc[], s
}
void GDS_ClearExt(struct GDS_Device* Device, bool full, ...) {
GDS_CHECK_FOR_DEVICE(Device,return);
bool commit = true;
if (full) {
@@ -75,7 +74,6 @@ void GDS_ClearExt(struct GDS_Device* Device, bool full, ...) {
}
void GDS_Clear( struct GDS_Device* Device, int Color ) {
GDS_CHECK_FOR_DEVICE(Device,return);
if (Color == GDS_COLOR_BLACK) memset( Device->Framebuffer, 0, Device->FramebufferSize );
else if (Device->Depth == 1) memset( Device->Framebuffer, 0xff, Device->FramebufferSize );
else if (Device->Depth == 4) memset( Device->Framebuffer, Color | (Color << 4), Device->FramebufferSize );
@@ -91,7 +89,6 @@ void GDS_Clear( struct GDS_Device* Device, int Color ) {
}
void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ) {
GDS_CHECK_FOR_DEVICE(Device,return);
// -1 means up to width/height
if (x2 < 0) x2 = Device->Width - 1;
if (y2 < 0) y2 = Device->Height - 1;
@@ -161,13 +158,11 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
}
void GDS_Update( struct GDS_Device* Device ) {
GDS_CHECK_FOR_DEVICE(Device,return);
if (Device->Dirty) Device->Update( Device );
Device->Dirty = false;
}
bool GDS_Reset( struct GDS_Device* Device ) {
GDS_CHECK_FOR_DEVICE(Device,return false);
if ( Device->RSTPin >= 0 ) {
gpio_set_level( Device->RSTPin, 0 );
vTaskDelay( pdMS_TO_TICKS( 100 ) );
@@ -232,7 +227,7 @@ static void IRAM_ATTR DrawPixel24Fast( struct GDS_Device* Device, int X, int Y,
}
bool GDS_Init( struct GDS_Device* Device ) {
GDS_CHECK_FOR_DEVICE(Device,return false);
if (Device->Depth > 8) Device->FramebufferSize = Device->Width * Device->Height * ((8 + Device->Depth - 1) / 8);
else Device->FramebufferSize = (Device->Width * Device->Height) / (8 / Device->Depth);
@@ -279,7 +274,6 @@ bool GDS_Init( struct GDS_Device* Device ) {
}
int GDS_GrayMap( struct GDS_Device* Device, uint8_t Level) {
GDS_CHECK_FOR_DEVICE(Device,return -1);
switch(Device->Mode) {
case GDS_MONO: return Level;
case GDS_GRAYSCALE: return Level >> (8 - Device->Depth);
@@ -306,7 +300,6 @@ int GDS_GrayMap( struct GDS_Device* Device, uint8_t Level) {
}
void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
GDS_CHECK_FOR_DEVICE(Device,return);
if (Device->SetContrast) Device->SetContrast( Device, Contrast );
else if (Device->Backlight.Pin >= 0) {
Device->Backlight.PWM = PWMConfig.Max * powf(Contrast / 255.0, 3);
@@ -315,12 +308,12 @@ void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
}
}
void GDS_SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { if (Device && Device->SetLayout) Device->SetLayout( Device, Layout ); }
void GDS_SetDirty( struct GDS_Device* Device ) { GDS_CHECK_FOR_DEVICE(Device,return); Device->Dirty = true; }
void GDS_SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { if (Device->SetLayout) Device->SetLayout( Device, Layout ); }
void GDS_SetDirty( struct GDS_Device* Device ) { Device->Dirty = true; }
int GDS_GetWidth( struct GDS_Device* Device ) { return Device ? Device->Width : 0; }
void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ) { GDS_CHECK_FOR_DEVICE(Device,return); Device->TextWidth = Device && TextWidth && TextWidth < Device->Width ? TextWidth : Device->Width; }
void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ) { Device->TextWidth = Device && TextWidth && TextWidth < Device->Width ? TextWidth : Device->Width; }
int GDS_GetHeight( struct GDS_Device* Device ) { return Device ? Device->Height : 0; }
int GDS_GetDepth( struct GDS_Device* Device ) { return Device ? Device->Depth : 0; }
int GDS_GetMode( struct GDS_Device* Device ) { return Device ? Device->Mode : 0; }
void GDS_DisplayOn( struct GDS_Device* Device ) { if (Device && Device->DisplayOn) Device->DisplayOn( Device ); }
void GDS_DisplayOff( struct GDS_Device* Device ) { if (Device && Device->DisplayOff) Device->DisplayOff( Device ); }
void GDS_DisplayOn( struct GDS_Device* Device ) { if (Device->DisplayOn) Device->DisplayOn( Device ); }
void GDS_DisplayOff( struct GDS_Device* Device ) { if (Device->DisplayOff) Device->DisplayOff( Device ); }

View File

@@ -52,6 +52,5 @@ int GDS_GrayMap( struct GDS_Device* Device, uint8_t Level );
void GDS_ClearExt( struct GDS_Device* Device, bool full, ...);
void GDS_Clear( struct GDS_Device* Device, int Color );
void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color );
#define GDS_CHECK_FOR_DEVICE(dev,ret_act) if(!dev) ret_act
#endif

View File

@@ -70,7 +70,7 @@ static char * get_dac_config_string(){
return config_alloc_get_str("dac_config", CONFIG_DAC_CONFIG, "model=i2s,bck=" STR(CONFIG_I2S_BCK_IO)
",ws=" STR(CONFIG_I2S_WS_IO) ",do=" STR(CONFIG_I2S_DO_IO)
",sda=" STR(CONFIG_I2C_SDA) ",scl=" STR(CONFIG_I2C_SCL)
",mute=" STR(CONFIG_MUTE_GPIO));
",mute=" STR(CONFIG_MUTE_GPIO) ",mck=" STR(CONFIG_I2S_MCK_IO));
}
/****************************************************************************************

View File

@@ -38,6 +38,7 @@ static esp_err_t actrls_process_action (const cJSON * member, actrls_config_t *c
static esp_err_t actrls_init_json(const char *profile_name, bool create);
static void control_rotary_handler(void *client, rotary_event_e event, bool long_press);
static void volume_rotary_handler(void *client, rotary_event_e event, bool long_press);
static void rotary_timer( TimerHandle_t xTimer );
static const actrls_config_map_t actrls_config_map[] =
@@ -157,6 +158,24 @@ esp_err_t actrls_init(const char *profile_name) {
err = create_rotary(NULL, A, B, SW, longpress, control_rotary_handler) ? ESP_OK : ESP_FAIL;
}
free(config);
config = config_alloc_get_default(NVS_TYPE_STR, "volume_rotary", NULL, 0);
// now see if we have a dedicated volume rotary
if (config && *config) {
int A = -1, B = -1, SW = -1;
// parse config
PARSE_PARAM(config, "A", '=', A);
PARSE_PARAM(config, "B", '=', B);
PARSE_PARAM(config, "SW", '=', SW);
// create rotary (no handling of long press)
err |= create_volume_rotary(NULL, A, B, SW, volume_rotary_handler) ? ESP_OK : ESP_FAIL;
}
free(config);
// set infrared GPIO if any
parse_set_GPIO(set_ir_gpio);
@@ -290,6 +309,29 @@ static void control_rotary_handler(void *client, rotary_event_e event, bool long
if (action != ACTRLS_NONE) (*current_controls[action])(pressed);
}
/****************************************************************************************
*
*/
static void volume_rotary_handler(void *client, rotary_event_e event, bool long_press) {
actrls_action_e action = ACTRLS_NONE;
bool pressed = true;
switch(event) {
case ROTARY_LEFT:
action = ACTRLS_VOLDOWN;
break;
case ROTARY_RIGHT:
action = ACTRLS_VOLUP;
break;
case ROTARY_PRESSED:
action = ACTRLS_TOGGLE;
default:
break;
}
if (action != ACTRLS_NONE) (*current_controls[action])(pressed);
}
/****************************************************************************************
*
*/
@@ -568,6 +610,13 @@ exit:
return err;
}
/****************************************************************************************
*
*/
actrls_handler get_ctrl_handler(actrls_action_e action) {
return current_controls[action];
}
/****************************************************************************************
*
*/

View File

@@ -53,3 +53,9 @@ void actrls_set_default(const actrls_t controls, bool raw_controls, actrls_hook_
void actrls_set(const actrls_t controls, bool raw_controls, actrls_hook_t *hook, actrls_ir_handler_t *ir_handler);
void actrls_unset(void);
bool actrls_ir_action(uint16_t addr, uint16_t code);
/* Call this to get the handler for any of the audio actions. It will map to the control specific
to the current mode (LMS, AirPlay, Spotify). This is useful if you have a custom way to create
buttons (like analogue buttons)
*/
actrls_handler get_ctrl_handler(actrls_action_e);

View File

@@ -58,13 +58,13 @@ static struct {
static TimerHandle_t polled_timer;
static EXT_RAM_ATTR struct {
static EXT_RAM_ATTR struct encoder {
QueueHandle_t queue;
void *client;
rotary_encoder_info_t info;
int A, B, SW;
rotary_handler handler;
} rotary;
} rotary, volume;
static EXT_RAM_ATTR struct {
RingbufHandle_t rb;
@@ -227,11 +227,22 @@ static void buttons_task(void* arg) {
// received a rotary event
xQueueReceive(rotary.queue, &event, 0);
ESP_LOGD(TAG, "Event: position %d, direction %s", event.state.position,
ESP_LOGD(TAG, "Rotary event: position %d, direction %s", event.state.position,
event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET");
rotary.handler(rotary.client, event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ?
ROTARY_RIGHT : ROTARY_LEFT, false);
} else if (xActivatedMember == volume.queue) {
rotary_encoder_event_t event = { 0 };
// received a volume rotary event
xQueueReceive(volume.queue, &event, 0);
ESP_LOGD(TAG, "Volume event: position %d, direction %s", event.state.position,
event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET");
volume.handler(volume.client, event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ?
ROTARY_RIGHT : ROTARY_LEFT, false);
} else {
// this is IR
active = infrared_receive(infrared.rb, infrared.handler);
@@ -395,7 +406,55 @@ void *button_remap(void *client, int gpio, button_handler handler, int long_pres
}
/****************************************************************************************
* Rotary encoder handler
* Create rotary encoder
*/
static bool create_rotary_encoder(struct encoder *encoder, void *id, int A, int B, int SW, int long_press, rotary_handler handler, button_handler button) {
// nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated
if (A == -1 || B == -1 || A == 36 || A == 39 || B == 36 || B == 39) {
ESP_LOGI(TAG, "Cannot create rotary %d %d", A, B);
return false;
}
encoder->A = A;
encoder->B = B;
encoder->SW = SW;
encoder->client = id;
encoder->handler = handler;
// Initialise the rotary encoder device with the GPIOs for A and B signals
rotary_encoder_init(&encoder->info, A, B);
// Create a queue for events from the rotary encoder driver.
encoder->queue = rotary_encoder_create_queue();
rotary_encoder_set_queue(&encoder->info, encoder->queue);
common_task_init();
xQueueAddToSet( encoder->queue, common_queue_set );
// create companion button if rotary has a switch
if (SW != -1) button_create(id, SW, BUTTON_LOW, true, 0, button, long_press, -1);
return true;
}
/****************************************************************************************
* Volume button encoder handler
*/
static void volume_button_handler(void *id, button_event_e event, button_press_e mode, bool long_press) {
ESP_LOGI(TAG, "Volume encoder push-button %d", event);
volume.handler(id, event == BUTTON_PRESSED ? ROTARY_PRESSED : ROTARY_RELEASED, long_press);
}
/****************************************************************************************
* Create volume encoder
*/
bool create_volume_rotary(void *id, int A, int B, int SW, rotary_handler handler) {
ESP_LOGI(TAG, "Created volume encoder A:%d B:%d, SW:%d", A, B, SW);
return create_rotary_encoder(&volume, id, A, B, SW, false, handler, volume_button_handler);
}
/****************************************************************************************
* Rotary button encoder handler
*/
static void rotary_button_handler(void *id, button_event_e event, button_press_e mode, bool long_press) {
ESP_LOGI(TAG, "Rotary push-button %d", event);
@@ -406,34 +465,8 @@ static void rotary_button_handler(void *id, button_event_e event, button_press_e
* Create rotary encoder
*/
bool create_rotary(void *id, int A, int B, int SW, int long_press, rotary_handler handler) {
// nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated
if (A == -1 || B == -1 || A == 36 || A == 39 || B == 36 || B == 39) {
ESP_LOGI(TAG, "Cannot create rotary %d %d", A, B);
return false;
}
rotary.A = A;
rotary.B = B;
rotary.SW = SW;
rotary.client = id;
rotary.handler = handler;
// Initialise the rotary encoder device with the GPIOs for A and B signals
rotary_encoder_init(&rotary.info, A, B);
// Create a queue for events from the rotary encoder driver.
rotary.queue = rotary_encoder_create_queue();
rotary_encoder_set_queue(&rotary.info, rotary.queue);
common_task_init();
xQueueAddToSet( rotary.queue, common_queue_set );
// create companion button if rotary has a switch
if (SW != -1) button_create(id, SW, BUTTON_LOW, true, 0, rotary_button_handler, long_press, -1);
ESP_LOGI(TAG, "Created rotary encoder A:%d B:%d, SW:%d", A, B, SW);
return true;
return create_rotary_encoder(&rotary, id, A, B, SW, long_press, handler, rotary_button_handler);
}
/****************************************************************************************

View File

@@ -34,5 +34,5 @@ typedef enum { ROTARY_LEFT, ROTARY_RIGHT, ROTARY_PRESSED, ROTARY_RELEASED } rota
typedef void (*rotary_handler)(void *id, rotary_event_e event, bool long_press);
bool create_rotary(void *id, int A, int B, int SW, int long_press, rotary_handler handler);
bool create_volume_rotary(void *id, int A, int B, int SW, rotary_handler handler);
bool create_infrared(int gpio, infrared_handler handler, infrared_mode_t mode);

View File

@@ -83,6 +83,10 @@ static void mcp23s17_set_direction(gpio_exp_t* self);
static uint32_t mcp23s17_read(gpio_exp_t* self);
static void mcp23s17_write(gpio_exp_t* self);
static void aw9523_set_direction(gpio_exp_t* self);
static uint32_t aw9523_read(gpio_exp_t* self);
static void aw9523_write(gpio_exp_t* self);
static void service_handler(void *arg);
static void debounce_handler( TimerHandle_t xTimer );
@@ -130,6 +134,11 @@ static const struct gpio_exp_model_s {
.set_pull_mode = mcp23s17_set_pull_mode,
.read = mcp23s17_read,
.write = mcp23s17_write, },
{ .model = "aw9523",
.trigger = GPIO_INTR_LOW_LEVEL,
.set_direction = aw9523_set_direction,
.read = aw9523_read,
.write = aw9523_write, },
};
static EXT_RAM_ATTR uint8_t n_expanders;
@@ -671,6 +680,24 @@ static void mcp23s17_write(gpio_exp_t* self) {
spi_write(self->spi_handle, self->phy.addr, 0x12, self->shadow, 2);
}
/****************************************************************************************
* AW9523 family : direction, read and write
*/
static void aw9523_set_direction(gpio_exp_t* self) {
i2c_write(self->phy.port, self->phy.addr, 0x04, self->r_mask, 2);
i2c_write(self->phy.port, self->phy.addr, 0x06, ~self->r_mask, 2);
}
static uint32_t aw9523_read(gpio_exp_t* self) {
// Reading both registers in one go does not seem to reset IRQ correctly
uint8_t port1 = i2c_read(self->phy.port, self->phy.addr, 0x00, 1);
return (i2c_read(self->phy.port, self->phy.addr, 0x01, 1) << 8) | port1;
}
static void aw9523_write(gpio_exp_t* self) {
i2c_write(self->phy.port, self->phy.addr, 0x02, self->shadow, 2);
}
/***************************************************************************************
I2C low level
***************************************************************************************/
@@ -793,4 +820,4 @@ static uint32_t spi_read(spi_device_handle_t handle, uint8_t addr, uint8_t reg,
free(transaction);
return data;
}
}

View File

@@ -687,7 +687,8 @@ void draw_VU(struct GDS_Device * display, int level, int x, int y, int width, bo
static void grfe_handler( u8_t *data, int len) {
struct grfe_packet *pkt = (struct grfe_packet*) data;
GDS_CHECK_FOR_DEVICE(display,return);
if (!display) return;
// we don't support transition, simply claim we're done
if (pkt->transition != 'c') {
LOG_INFO("Transition %c requested with offset %hu, param %d", pkt->transition, pkt->offset, pkt->param);
@@ -764,6 +765,8 @@ static void grfs_handler(u8_t *data, int len) {
int size = len - sizeof(struct grfs_packet);
int offset = htons(pkt->offset);
if (!display) return;
LOG_DEBUG("grfs s:%u d:%u p:%u sp:%u by:%hu m:%hu w:%hu o:%hu",
(int) pkt->screen,
(int) pkt->direction, // 1=left, 2=right
@@ -775,7 +778,6 @@ static void grfs_handler(u8_t *data, int len) {
htons(pkt->offset) // offset if multiple packets are sent
);
GDS_CHECK_FOR_DEVICE(display,return);
// new grfs frame, build scroller info
if (!offset) {
// use the display as a general lock
@@ -820,9 +822,10 @@ static void grfs_handler(u8_t *data, int len) {
static void grfg_handler(u8_t *data, int len) {
struct grfg_packet *pkt = (struct grfg_packet*) data;
if (!display) return;
LOG_DEBUG("gfrg s:%hu w:%hu (len:%u)", htons(pkt->screen), htons(pkt->width), len);
GDS_CHECK_FOR_DEVICE(display,return);
// full screen artwork or for small screen, visu has priority when full screen
if (((visu.mode & VISU_ESP32) && !visu.col && visu.row < displayer.height) || artwork.full) {
return;
@@ -867,7 +870,8 @@ static void grfa_handler(u8_t *data, int len) {
int offset = htonl(pkt->offset);
int length = htonl(pkt->length);
GDS_CHECK_FOR_DEVICE(display,return);
if (!display) return;
// when using full screen visualizer on small screen there is a brief overlay
artwork.enable = (length != 0);

View File

@@ -222,6 +222,25 @@ static void set_i2s_pin(char *config, i2s_pin_config_t *pin_config) {
#endif
}
/* When a panic occurs during playback, the I2S interface can produce a loud noise burst.
* This code runs just before the system panic handler to "emergency stop" the I2S iterface
* to prevent the noise burst from happening. Note that when this code is called the system
* has already crashed, so no need to disable interrupts, acquire locks, or otherwise be nice.
*
* This code makes use of the linker --wrap feature to intercept the call to esp_panic_handler.
*/
void __real_esp_panic_handler(void*);
void __wrap_esp_panic_handler (void* info) {
esp_rom_printf("I2S abort!\r\n");
i2s_stop(CONFIG_I2S_NUM);
/* Call the original panic handler function to finish processing this error */
__real_esp_panic_handler(info);
}
/****************************************************************************************
* Initialize the DAC output
*/

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -77,6 +77,10 @@ declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
@@ -235,6 +239,8 @@ declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare let sd: {};
declare let rf: boolean;
declare function refreshStatus(): void;

View File

@@ -1,5 +1,5 @@
target_add_binary_data( __idf_wifi-manager webapp/dist/css/index.6d425ac534311a0131b2.css.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/favicon-32x32.png BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/index.html.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.29cc48.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.29cc48.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.95ad03.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.95ad03.bundle.js.gz BINARY)

View File

@@ -6,29 +6,29 @@ extern const uint8_t _favicon_32x32_png_start[] asm("_binary_favicon_32x32_png_s
extern const uint8_t _favicon_32x32_png_end[] asm("_binary_favicon_32x32_png_end");
extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start");
extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end");
extern const uint8_t _index_29cc48_bundle_js_gz_start[] asm("_binary_index_29cc48_bundle_js_gz_start");
extern const uint8_t _index_29cc48_bundle_js_gz_end[] asm("_binary_index_29cc48_bundle_js_gz_end");
extern const uint8_t _node_vendors_29cc48_bundle_js_gz_start[] asm("_binary_node_vendors_29cc48_bundle_js_gz_start");
extern const uint8_t _node_vendors_29cc48_bundle_js_gz_end[] asm("_binary_node_vendors_29cc48_bundle_js_gz_end");
extern const uint8_t _index_95ad03_bundle_js_gz_start[] asm("_binary_index_95ad03_bundle_js_gz_start");
extern const uint8_t _index_95ad03_bundle_js_gz_end[] asm("_binary_index_95ad03_bundle_js_gz_end");
extern const uint8_t _node_vendors_95ad03_bundle_js_gz_start[] asm("_binary_node_vendors_95ad03_bundle_js_gz_start");
extern const uint8_t _node_vendors_95ad03_bundle_js_gz_end[] asm("_binary_node_vendors_95ad03_bundle_js_gz_end");
const char * resource_lookups[] = {
"/css/index.6d425ac534311a0131b2.css.gz",
"/favicon-32x32.png",
"/index.html.gz",
"/js/index.29cc48.bundle.js.gz",
"/js/node_vendors.29cc48.bundle.js.gz",
"/js/index.95ad03.bundle.js.gz",
"/js/node_vendors.95ad03.bundle.js.gz",
""
};
const uint8_t * resource_map_start[] = {
_index_6d425ac534311a0131b2_css_gz_start,
_favicon_32x32_png_start,
_index_html_gz_start,
_index_29cc48_bundle_js_gz_start,
_node_vendors_29cc48_bundle_js_gz_start
_index_95ad03_bundle_js_gz_start,
_node_vendors_95ad03_bundle_js_gz_start
};
const uint8_t * resource_map_end[] = {
_index_6d425ac534311a0131b2_css_gz_end,
_favicon_32x32_png_end,
_index_html_gz_end,
_index_29cc48_bundle_js_gz_end,
_node_vendors_29cc48_bundle_js_gz_end
_index_95ad03_bundle_js_gz_end,
_node_vendors_95ad03_bundle_js_gz_end
};

View File

@@ -1,6 +1,6 @@
/***********************************
webpack_headers
dist/css/index.6d425ac534311a0131b2.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.29cc48.bundle.js.gz,dist/js/node_vendors.29cc48.bundle.js.gz
dist/css/index.6d425ac534311a0131b2.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.95ad03.bundle.js.gz,dist/js/node_vendors.95ad03.bundle.js.gz
***********************************/
#pragma once
#include <inttypes.h>

View File

@@ -369,6 +369,12 @@ menu "Squeezelite-ESP32"
help
Set GPIO for rotary encoder (quadrature phase). See README on SqueezeESP32 project's GitHub for more details
A=<gpio>,B=<gpio>[,SW=gpio>[[,knobonly[=<ms>]|[,volume][,longpress]]
config VOLUME_ROTARY_ENCODER
string "Volume Rotary Encoder configuration"
default ""
help
Set GPIO for volume rotary encoder (quadrature phase). See README on SqueezeESP32 project's GitHub for more details
A=<gpio>,B=<gpio>[,SW=gpio>]
config GPIO_EXP_CONFIG
string "GPIO expander configuration"
help

View File

@@ -89,6 +89,7 @@ const DefaultStringVal defaultStringVals[] = {
{"actrls_config", ""},
{"lms_ctrls_raw", "n"},
{"rotary_config", CONFIG_ROTARY_ENCODER},
{"volume_rotary", CONFIG_VOLUME_ROTARY_ENCODER},
{"display_config", CONFIG_DISPLAY_CONFIG},
{"eth_config", CONFIG_ETH_CONFIG},
{"i2c_config", CONFIG_I2C_CONFIG},
@@ -114,6 +115,7 @@ const DefaultStringVal defaultStringVals[] = {
{"dhcp_tmout", "8"},
{"target", CONFIG_TARGET},
{"led_vu_config", ""},
{"autoexec", "1"},
#ifdef CONFIG_BT_SINK
{"bt_sink_pin", STR(CONFIG_BT_SINK_PIN)},
{"bt_sink_volume", "127"},
@@ -123,11 +125,10 @@ const DefaultStringVal defaultStringVals[] = {
{"a2dp_ctmt", STR(CONFIG_A2DP_CONNECT_TIMEOUT_MS)},
{"a2dp_ctrld", STR(CONFIG_A2DP_CONTROL_DELAY_MS)},
{"a2dp_sink_name", CONFIG_A2DP_SINK_NAME},
{"autoexec", "1"},
#endif
#ifdef CONFIG_AIRPLAY_SINK
{"airplay_port", CONFIG_AIRPLAY_PORT},
{"enable_airplay", STR(CONFIG_AIRPLAY_SINK)}
#endif
#endif
};
static bool bNetworkConnected=false;

Binary file not shown.

View File

@@ -220,7 +220,8 @@ sub send_equalizer {
sub send_loudness {
my ($client, $loudness) = @_;
$loudness ||= $prefs->client($client)->get('loudness') || 0;
$loudness //= $prefs->client($client)->get('loudness');
my $data = pack("c1", $loudness);
$client->sendFrame( loud => \$data );
}

View File

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

View File

@@ -1,10 +1,10 @@
<?xml version='1.0' standalone='yes'?>
<extensions>
<plugins>
<plugin version="0.600" name="SqueezeESP32" minTarget="7.9" maxTarget="*">
<plugin version="0.601" name="SqueezeESP32" minTarget="7.9" maxTarget="*">
<link>https://github.com/sle118/squeezelite-esp32</link>
<creator>Philippe</creator>
<sha>335b585e22eddbddacce00f34001d8bf2ee0f54f</sha>
<sha>439637e01db7410157a333446cd284509f877849</sha>
<email>philippe_44@outlook.com</email>
<desc lang="EN">SqueezeESP32 additional player id (100/101)</desc>
<url>http://raw.githubusercontent.com/sle118/squeezelite-esp32/master-v4.3/plugin/SqueezeESP32.zip</url>

View File

@@ -162,18 +162,18 @@ dW5qVOc3BlhtITW53ASyhvKC7HArhj7LwQH8C/dRgn1agIHP9vVJ1NaZnPXhK98T
ohv++OO0E/F/bVGNWVnLBQ4v5PjQzRQUTGvM2mU=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIIPDCCBySgAwIBAgIQCoUc0xRNvf782dBaZzL1GDANBgkqhkiG9w0BAQsFADA8
MIIIPTCCByWgAwIBAgIQDYmiKjFPsahj6xtW4YeyETANBgkqhkiG9w0BAQsFADA8
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g
UlNBIDIwNDggTTAxMB4XDTI0MDIwODAwMDAwMFoXDTI1MDExMTIzNTk1OVowGzEZ
UlNBIDIwNDggTTAxMB4XDTI0MDUyNTAwMDAwMFoXDTI1MDUwMjIzNTk1OVowGzEZ
MBcGA1UEAxMQczMuYW1hem9uYXdzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBALwJqC+8pyil6exbAjVQQF7gCYVso0DkcF26ZUwAd7YMSSLDeeRD
tmJkAq42fVbwgnaCsrCIguG2hwNxyD74jIuFY2hDQIjQN1q4kPVuXzAGJ/Ovys+C
TYyeNoKwYAt40D1Cs7gcFetvf26fdanJAdfgwnXKNDqWi9U7re/gA1XMqlezPHs8
rNPNm+cGYNLAtpHyeES6CIBLHL3lchDSxgK5myhFYDdIevMg4X/1j1YdEl7QzMj5
G34hJqEfqPDDOQlvWBW/rCd3xfjOcYyjPB0mGmY2XTVukQiD2Gruvhg7AW7QXsai
dHfn3RmSQ8zniuRvvziAjEunZuActUH8lKkCAwEAAaOCBVkwggVVMB8GA1UdIwQY
MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBSczB3nSKDvmULmm/oN
oj26JpG8ojCCAokGA1UdEQSCAoAwggJ8ghBzMy5hbWF6b25hd3MuY29tghIqLnMz
ADCCAQoCggEBAI8ZD014LDUraEdhKlNbyazq6JqEltWQ/8EwwEpDZltKJVo25fGh
9L8Uayv1Fwj8m70MeRKt/FlMv4aatJx8d8Ijd0tJ9YZa+8GoS0jcCWo0m3nyLT1i
/iWB5AE7Bq/TiQ0gvp7QOxTGiTe2w7lO3BkTTKCyXjMWKleClMLZW+J6AuOvw02B
XftIdXj9cwcn4rqE266F9V/ewLlpV89Vp4CzHny6A/LhnvHegDUOAEkncF9klBIP
24/av+/vr+WncIlOjwJpUC0EiRH/04AZ7pM+mQTO9NGHufRf+CDW1NXDC4jnGGMX
biRRH3XZ1iJgqtlwlhdTRm5rfpi4Qse6awUCAwEAAaOCBVowggVWMB8GA1UdIwQY
MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBRcq6uGY92hy5eAQeOJ
94CUob5JezCCAokGA1UdEQSCAoAwggJ8ghBzMy5hbWF6b25hd3MuY29tghIqLnMz
LmFtYXpvbmF3cy5jb22CJiouczMuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25h
d3MuY29tgiRzMy5kdWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CHCou
czMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CGnMzLnVzLWVhc3QtMS5hbWF6b25h
@@ -192,18 +192,19 @@ KwYBBQUHAwIwOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5yMm0wMS5hbWF6
b250cnVzdC5jb20vcjJtMDEuY3JsMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcw
AYYhaHR0cDovL29jc3AucjJtMDEuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAC
hipodHRwOi8vY3J0LnIybTAxLmFtYXpvbnRydXN0LmNvbS9yMm0wMS5jZXIwDAYD
VR0TAQH/BAIwADCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHcATnWjJ1yaEMM4
W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGNiq0a7AAABAMASDBGAiEAudzKuZ93
XwCkNvsOtCfkpgKu8egAFdXeCG6CPI+muiQCIQDGHiAYvh59sW14WsNF1gX6Wu1A
7JOtTemHgdTsFwmIdAB1AD8XS0/XIkdYlB1lHIS+DRLtkDd/H4Vq68G/KIXs+GRu
AAABjYqtGuwAAAQDAEYwRAIgGECWncBSVe5FGWQ5qgOotqodK6f2dTLwCjQqy3zp
QuACIHPLNnOXzyO8cxbe9iEy1ZWqdh2bqWqMtHUEx4kIY7awAHYAVYHUwhaQNgFK
6gubVzxT8MDkOHhwJQgXL6OqHQcT0wwAAAGNiq0begAABAMARzBFAiBi1XBFN0j+
SJ5PBCByXcJ8xP5anjWJRyuMdK6EkiDzZgIhAKaUpLPdOdiUxx9Xlar4tPz7Bnyw
bx0UFNyiSzPjD6i+MA0GCSqGSIb3DQEBCwUAA4IBAQCtvdXGbz9xJEg9DAPIlfRH
KE2pta2NMLObOqydPjkUFL9dOdgwAxHib9x6X3oTb5PDGqR7DZ5zyf8kdY/UN+nH
3h3WifDXrE2NlVBJ1NwABJ2ZFg2A0G9uchLc0wAvsl86ziQETHWqff7wlGrN5bek
HItY6nc90BH+Jk9nbTa66DMLw26V443hKLcGdq8Fu/N8VING5cw/yMg9HN0tKaZy
o4z9hbT4W12zwCyPPBLxoboTzJY0yTPUYdDbW1b1QIssj/BKwgm0Tfkm6V/MMnqs
BluqB+8VNGPJNhO0zoAI9TMIf2s0MElDyR08ABjvUjy00Gn/g0ZHXSWPEP+NQLoM
VR0TAQH/BAIwADCCAX8GCisGAQQB1nkCBAIEggFvBIIBawFpAHUATnWjJ1yaEMM4
W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGPsPwa0QAABAMARjBEAiB4Gfq+8TAW
Fo7DqSyg2v+D9ZBfSKdmitPDb3oEsKq3FAIgJn6BcEQfiMXP6iry6mb8Zxq6u2Ls
TJhyt9w+k2u2UkoAdwB9WR4S4XgqexxhZ3xe/fjQh1wUoE6VnrkDL9kOjC55uAAA
AY+w/BqPAAAEAwBIMEYCIQDQP1WHgUZ93as6Cqs2WymphNiEQBu4sAMzVF5UCbaV
cQIhAPdsdIBMFI9Lzd8UILJGXjnFFO06nAnp7rcEgiO/AsvPAHcA5tIxY0B3jMEQ
QQbXcbnOwdJA9paEhvu6hzId/R43jlAAAAGPsPwapQAABAMASDBGAiEAtXDI9A5B
zxJJe7/+8lqJM+cbuPDUTvZ1S8vugTQHR3ECIQDIT3tvpT7y294xgUGtYJgZ19hg
MuNmgMHUBThNIooDIjANBgkqhkiG9w0BAQsFAAOCAQEAbA1vQgPLM1/WkNgtsRTb
ryftKRyT4jld6f+7i3o2EFA2n84JxzumPugbpKT5ADgHDFNKrqgkgpwd7KshoF2J
TZWu4uqbdNjrFjOdbAQx4NvMl51pqhR1z9cCemIpcg4sk6r0pBif/pAPap4721J+
BSUY8d3afHzS3vEmfK3Mq9dj6PoYG2rs1sPG/sGwYZuB+zlzOnwodBTu1coMdyei
QM3Ubsdirruqtnq27CWWbOKW+ClWYNArOyi3EmuXlvbFx719W1tr+2utPJP+cWm/
ZM8Z5Ikf3A/ilzuKAfMpDtTGM8fy5ISVoUA+2UrG3BQYpI/vRfud4JG+DHOyJq05
GA==
-----END CERTIFICATE-----

BIN
server_certs/r2m01.cer.53 Normal file

Binary file not shown.

BIN
server_certs/r2m01.cer.54 Normal file

Binary file not shown.

View File

@@ -1,16 +1,16 @@
-----BEGIN CERTIFICATE-----
MIIIPDCCBySgAwIBAgIQCoUc0xRNvf782dBaZzL1GDANBgkqhkiG9w0BAQsFADA8
MIIIPTCCByWgAwIBAgIQDYmiKjFPsahj6xtW4YeyETANBgkqhkiG9w0BAQsFADA8
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g
UlNBIDIwNDggTTAxMB4XDTI0MDIwODAwMDAwMFoXDTI1MDExMTIzNTk1OVowGzEZ
UlNBIDIwNDggTTAxMB4XDTI0MDUyNTAwMDAwMFoXDTI1MDUwMjIzNTk1OVowGzEZ
MBcGA1UEAxMQczMuYW1hem9uYXdzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBALwJqC+8pyil6exbAjVQQF7gCYVso0DkcF26ZUwAd7YMSSLDeeRD
tmJkAq42fVbwgnaCsrCIguG2hwNxyD74jIuFY2hDQIjQN1q4kPVuXzAGJ/Ovys+C
TYyeNoKwYAt40D1Cs7gcFetvf26fdanJAdfgwnXKNDqWi9U7re/gA1XMqlezPHs8
rNPNm+cGYNLAtpHyeES6CIBLHL3lchDSxgK5myhFYDdIevMg4X/1j1YdEl7QzMj5
G34hJqEfqPDDOQlvWBW/rCd3xfjOcYyjPB0mGmY2XTVukQiD2Gruvhg7AW7QXsai
dHfn3RmSQ8zniuRvvziAjEunZuActUH8lKkCAwEAAaOCBVkwggVVMB8GA1UdIwQY
MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBSczB3nSKDvmULmm/oN
oj26JpG8ojCCAokGA1UdEQSCAoAwggJ8ghBzMy5hbWF6b25hd3MuY29tghIqLnMz
ADCCAQoCggEBAI8ZD014LDUraEdhKlNbyazq6JqEltWQ/8EwwEpDZltKJVo25fGh
9L8Uayv1Fwj8m70MeRKt/FlMv4aatJx8d8Ijd0tJ9YZa+8GoS0jcCWo0m3nyLT1i
/iWB5AE7Bq/TiQ0gvp7QOxTGiTe2w7lO3BkTTKCyXjMWKleClMLZW+J6AuOvw02B
XftIdXj9cwcn4rqE266F9V/ewLlpV89Vp4CzHny6A/LhnvHegDUOAEkncF9klBIP
24/av+/vr+WncIlOjwJpUC0EiRH/04AZ7pM+mQTO9NGHufRf+CDW1NXDC4jnGGMX
biRRH3XZ1iJgqtlwlhdTRm5rfpi4Qse6awUCAwEAAaOCBVowggVWMB8GA1UdIwQY
MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBRcq6uGY92hy5eAQeOJ
94CUob5JezCCAokGA1UdEQSCAoAwggJ8ghBzMy5hbWF6b25hd3MuY29tghIqLnMz
LmFtYXpvbmF3cy5jb22CJiouczMuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25h
d3MuY29tgiRzMy5kdWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CHCou
czMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CGnMzLnVzLWVhc3QtMS5hbWF6b25h
@@ -29,18 +29,19 @@ KwYBBQUHAwIwOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5yMm0wMS5hbWF6
b250cnVzdC5jb20vcjJtMDEuY3JsMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcw
AYYhaHR0cDovL29jc3AucjJtMDEuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAC
hipodHRwOi8vY3J0LnIybTAxLmFtYXpvbnRydXN0LmNvbS9yMm0wMS5jZXIwDAYD
VR0TAQH/BAIwADCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHcATnWjJ1yaEMM4
W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGNiq0a7AAABAMASDBGAiEAudzKuZ93
XwCkNvsOtCfkpgKu8egAFdXeCG6CPI+muiQCIQDGHiAYvh59sW14WsNF1gX6Wu1A
7JOtTemHgdTsFwmIdAB1AD8XS0/XIkdYlB1lHIS+DRLtkDd/H4Vq68G/KIXs+GRu
AAABjYqtGuwAAAQDAEYwRAIgGECWncBSVe5FGWQ5qgOotqodK6f2dTLwCjQqy3zp
QuACIHPLNnOXzyO8cxbe9iEy1ZWqdh2bqWqMtHUEx4kIY7awAHYAVYHUwhaQNgFK
6gubVzxT8MDkOHhwJQgXL6OqHQcT0wwAAAGNiq0begAABAMARzBFAiBi1XBFN0j+
SJ5PBCByXcJ8xP5anjWJRyuMdK6EkiDzZgIhAKaUpLPdOdiUxx9Xlar4tPz7Bnyw
bx0UFNyiSzPjD6i+MA0GCSqGSIb3DQEBCwUAA4IBAQCtvdXGbz9xJEg9DAPIlfRH
KE2pta2NMLObOqydPjkUFL9dOdgwAxHib9x6X3oTb5PDGqR7DZ5zyf8kdY/UN+nH
3h3WifDXrE2NlVBJ1NwABJ2ZFg2A0G9uchLc0wAvsl86ziQETHWqff7wlGrN5bek
HItY6nc90BH+Jk9nbTa66DMLw26V443hKLcGdq8Fu/N8VING5cw/yMg9HN0tKaZy
o4z9hbT4W12zwCyPPBLxoboTzJY0yTPUYdDbW1b1QIssj/BKwgm0Tfkm6V/MMnqs
BluqB+8VNGPJNhO0zoAI9TMIf2s0MElDyR08ABjvUjy00Gn/g0ZHXSWPEP+NQLoM
VR0TAQH/BAIwADCCAX8GCisGAQQB1nkCBAIEggFvBIIBawFpAHUATnWjJ1yaEMM4
W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGPsPwa0QAABAMARjBEAiB4Gfq+8TAW
Fo7DqSyg2v+D9ZBfSKdmitPDb3oEsKq3FAIgJn6BcEQfiMXP6iry6mb8Zxq6u2Ls
TJhyt9w+k2u2UkoAdwB9WR4S4XgqexxhZ3xe/fjQh1wUoE6VnrkDL9kOjC55uAAA
AY+w/BqPAAAEAwBIMEYCIQDQP1WHgUZ93as6Cqs2WymphNiEQBu4sAMzVF5UCbaV
cQIhAPdsdIBMFI9Lzd8UILJGXjnFFO06nAnp7rcEgiO/AsvPAHcA5tIxY0B3jMEQ
QQbXcbnOwdJA9paEhvu6hzId/R43jlAAAAGPsPwapQAABAMASDBGAiEAtXDI9A5B
zxJJe7/+8lqJM+cbuPDUTvZ1S8vugTQHR3ECIQDIT3tvpT7y294xgUGtYJgZ19hg
MuNmgMHUBThNIooDIjANBgkqhkiG9w0BAQsFAAOCAQEAbA1vQgPLM1/WkNgtsRTb
ryftKRyT4jld6f+7i3o2EFA2n84JxzumPugbpKT5ADgHDFNKrqgkgpwd7KshoF2J
TZWu4uqbdNjrFjOdbAQx4NvMl51pqhR1z9cCemIpcg4sk6r0pBif/pAPap4721J+
BSUY8d3afHzS3vEmfK3Mq9dj6PoYG2rs1sPG/sGwYZuB+zlzOnwodBTu1coMdyei
QM3Ubsdirruqtnq27CWWbOKW+ClWYNArOyi3EmuXlvbFx719W1tr+2utPJP+cWm/
ZM8Z5Ikf3A/ilzuKAfMpDtTGM8fy5ISVoUA+2UrG3BQYpI/vRfud4JG+DHOyJq05
GA==
-----END CERTIFICATE-----