Compare commits

..

9 Commits

Author SHA1 Message Date
philippe44
60ba05d3d9 Protect artwork update with mutex - release 2022-07-09 14:13:04 -07:00
philippe44
099d9ffd1e forgot to push colorswap 2022-07-09 14:05:09 -07:00
philippe44
3d30b45723 Update README.md 2022-03-03 19:34:18 -08:00
philippe44
87fae72887 Update README.md 2022-02-26 17:46:22 -08:00
Philippe G
1f78db596e debounce is 50ms default, .defaults has always been overwritten by build params.... (battery scale) - release 2022-02-03 23:15:38 -08:00
Philippe G
c0bd080ea1 release 2022-02-02 11:30:59 -08:00
Philippe G
29d4214e28 Merge branch 'master-cmake' of https://github.com/sle118/squeezelite-esp32 into master-cmake 2022-02-02 11:28:34 -08:00
Philippe G
b828e7f3e6 ensure amp gpio lock, add longpress - release 2022-02-02 11:28:31 -08:00
philippe44
6843d4b1ef Update README.md 2022-01-30 13:13:05 -08:00
18 changed files with 104 additions and 62 deletions

View File

@@ -222,12 +222,14 @@ Ground -------------------------- coax signal ground
The NVS parameter "display_config" sets the parameters for an optional display. It can be I2C (see [here](#i2c) for shared bus) or SPI (see [here](#spi) for shared bus) Syntax is The NVS parameter "display_config" sets the parameters for an optional display. It can be I2C (see [here](#i2c) for shared bus) or SPI (see [here](#spi) for shared bus) Syntax is
``` ```
I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,reset=<gpio>][,HFlip][,VFlip][driver=SSD1306|SSD1326[:1|4]|SSD1327|SH1106] I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,reset=<gpio>][,HFlip][,VFlip][driver=SSD1306|SSD1326[:1|4]|SSD1327|SH1106]
SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed=<speed>][,HFlip][,VFlip][driver=SSD1306|SSD1322|SSD1326[:1|4]|SSD1327|SH1106|SSD1675|ST7735[:x=<offset>][:y=<offset>]|ST7789|ILI9341[:16|18][,rotate]] SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed=<speed>][,HFlip][,VFlip][driver=SSD1306|SSD1322|SSD1326[:1|4]|SSD1327|SH1106|SSD1675|ST7735[:x=<offset>][:y=<offset>]|ST7789|ILI9341[:16|18][,rotate][,invert][,cswap]
``` ```
- back: a LED backlight used by some older devices (ST7735). It is PWM controlled for brightness - back: a LED backlight used by some older devices (ST7735). It is PWM controlled for brightness
- reset: some display have a reset pin that is should normally be pulled up if unused. Most displays require reset and will not initialize well otherwise. - reset: some display have a reset pin that is should normally be pulled up if unused. Most displays require reset and will not initialize well otherwise.
- VFlip and HFlip are optional can be used to change display orientation - VFlip and HFlip are optional can be used to change display orientation
- rotate: for non-square *drivers*, move to portrait mode. Note that *width* and *height* must be inverted then - rotate: for non-square *drivers*, move to portrait mode. Note that *width* and *height* must be inverted then
- invert: pixel invertion
- cswap: some display require a GBR color ordering instead of RGB (ST77xx only)
- Default speed is 8000000 (8MHz) but SPI can work up to 26MHz or even 40MHz - Default speed is 8000000 (8MHz) but SPI can work up to 26MHz or even 40MHz
- SH1106 is 128x64 monochrome I2C/SPI [here](https://www.waveshare.com/wiki/1.3inch_OLED_HAT) - SH1106 is 128x64 monochrome I2C/SPI [here](https://www.waveshare.com/wiki/1.3inch_OLED_HAT)
- SSD1306 is 128x32 monochrome I2C/SPI [here](https://www.buydisplay.com/i2c-blue-0-91-inch-oled-display-module-128x32-arduino-raspberry-pi) - SSD1306 is 128x32 monochrome I2C/SPI [here](https://www.buydisplay.com/i2c-blue-0-91-inch-oled-display-module-128x32-arduino-raspberry-pi)
@@ -425,11 +427,11 @@ buttons
] ]
``` ```
**IMPORTANT NOTE**: LMS also supports the possibility to send 'raw' button codes. It's a bit complicated, so bear with me. Buttons can either be processed by SqueezeESP32 and mapped to a "function" like play/pause or they can be just sent to LMS as plain (raw) code and the full logic of press/release/longpress is handled by LMS, you don't have any control on that. **IMPORTANT NOTE**: LMS also supports the possibility to send 'raw' button codes. It's a bit complicated, so bear with me. Buttons can either be processed by SqueezeESP32 and mapped to a "function" like play/pause or they can be just sent to LMS as plain (raw) code and the full logic of press/release/longpress is handled by LMS, you don't have any control on that.
When buttons are mapped to a "function" (non "raw" mode) a *command* is sent to LMS using the CLI (Command Line Interface) but this only works if LMS does not have a password set. In "raw" mode, a button *code* is sent using the always-openn control socket between LMS and the player.
The benefit of the "raw" mode is that you can build a player which is as close as possible to a Boom (e.g.) but you can't use the remapping function nor longress or shift logics to do your own mapping when you have a limited set of buttons. In 'raw' mode, all you really need to define is the mapping between the gpio and the button. As far as LMS is concerned, any other option in these JSON payloads does not matter. Now, when you use BT or AirPlay, the full JSON construct described above fully applies, so the shift, longpress, remapping options still work. The benefit of the "raw" mode is that you can build a player which is as close as possible to a Boom (e.g.) but you can't use the remapping function nor longress or shift logics to do your own mapping when you have a limited set of buttons. In 'raw' mode, all you really need to define is the mapping between the gpio and the button. As far as LMS is concerned, any other option in these JSON payloads does not matter. Now, when you use BT or AirPlay, the full JSON construct described above fully applies, so the shift, longpress, remapping options still work.
**Be aware that when using non "raw" mode, the CLI (Command Line Interface) of LMS is used and *must* be available without password**
There is no good or bad option, it's your choice. Use the NVS parameter "lms_ctrls_raw" to change that option There is no good or bad option, it's your choice. Use the NVS parameter "lms_ctrls_raw" to change that option
**Note that gpio 36 and 39 are input only and cannot use interrupt. When using them for a button, a 100ms polling is started which is expensive. Long press is also likely to not work very well** **Note that gpio 36 and 39 are input only and cannot use interrupt. When using them for a button, a 100ms polling is started which is expensive. Long press is also likely to not work very well**

View File

@@ -27,8 +27,8 @@ CONFIG_JACK_GPIO_LEVEL=0
CONFIG_SPKFAULT_GPIO=-1 CONFIG_SPKFAULT_GPIO=-1
CONFIG_DAC_CONTROLSET="{\"init\":[ {\"reg\":0,\"val\":128}, {\"reg\":0,\"val\":0}, {\"reg\":25,\"val\":4}, {\"reg\":1,\"val\":80}, {\"reg\":2,\"val\":0}, {\"reg\":8,\"val\":0}, {\"reg\":4,\"val\":192}, {\"reg\":0,\"val\":18}, {\"reg\":1,\"val\":0}, {\"reg\":23,\"val\":24}, {\"reg\":24,\"val\":2}, {\"reg\":38,\"val\":9}, {\"reg\":39,\"val\":144}, {\"reg\":42,\"val\":144}, {\"reg\":43,\"val\":128}, {\"reg\":45,\"val\":128}, {\"reg\":27,\"val\":0}, {\"reg\":26,\"val\":0}, {\"reg\":2,\"val\":240}, {\"reg\":2,\"val\":0}, {\"reg\":29,\"val\":28}, {\"reg\":4,\"val\":48}, {\"reg\":25,\"val\":0} ]}" CONFIG_DAC_CONTROLSET="{\"init\":[ {\"reg\":0,\"val\":128}, {\"reg\":0,\"val\":0}, {\"reg\":25,\"val\":4}, {\"reg\":1,\"val\":80}, {\"reg\":2,\"val\":0}, {\"reg\":8,\"val\":0}, {\"reg\":4,\"val\":192}, {\"reg\":0,\"val\":18}, {\"reg\":1,\"val\":0}, {\"reg\":23,\"val\":24}, {\"reg\":24,\"val\":2}, {\"reg\":38,\"val\":9}, {\"reg\":39,\"val\":144}, {\"reg\":42,\"val\":144}, {\"reg\":43,\"val\":128}, {\"reg\":45,\"val\":128}, {\"reg\":27,\"val\":0}, {\"reg\":26,\"val\":0}, {\"reg\":2,\"val\":240}, {\"reg\":2,\"val\":0}, {\"reg\":29,\"val\":28}, {\"reg\":4,\"val\":48}, {\"reg\":25,\"val\":0} ]}"
CONFIG_AUDIO_CONTROLS="[{\"gpio\":32, \"pull\":true, \"debounce\":10, \"normal\":{\"pressed\":\"ACTRLS_VOLDOWN\"}}, {\"gpio\":19, \"pull\":true, \"debounce\":40, \"normal\":{\"pressed\":\"ACTRLS_VOLUP\"}}, {\"gpio\":12, \"pull\":true, \"debounce\":40, \"long_press\":1000, \"normal\":{\"pressed\":\"ACTRLS_TOGGLE\"},\"longpress\":{\"pressed\":\"ACTRLS_POWER\"}}]" CONFIG_AUDIO_CONTROLS=CONFIG_AUDIO_CONTROLS="[{\"gpio\":32, \"pull\":true, \"long_press\":1000, \"normal\":{\"pressed\":\"ACTRLS_VOLDOWN\"}, \"longpress\":{\"pressed\":\"ACTRLS_PREV\"}}, {\"gpio\":19, \"pull\":true, \"long_press\":1000, \"normal\":{\"pressed\":\"ACTRLS_VOLUP\"}, \"longpress\":{\"pressed\":\"ACTRLS_NEXT\"}}, {\"gpio\":12, \"pull\":true, \"long_press\":1000, \"normal\":{\"pressed\":\"ACTRLS_TOGGLE\"},\"longpress\":{\"pressed\":\"ACTRLS_POWER\"}}]"
CONFIG_BAT_CONFIG="channel=5,scale=1,atten=3,cells=1" CONFIG_BAT_CONFIG="channel=5,scale=7.00,atten=3,cells=1"
CONFIG_I2S_NUM=0 CONFIG_I2S_NUM=0
CONFIG_SPDIF_NUM=0 CONFIG_SPDIF_NUM=0
CONFIG_SPDIF_CONFIG="" CONFIG_SPDIF_CONFIG=""

View File

@@ -191,49 +191,54 @@ static void Update24( struct GDS_Device* Device ) {
#endif #endif
} }
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
ESP_LOGI(TAG, "SetLayout 197 HFlip=%d VFlip=%d Rotate=%d (1=true)", HFlip, VFlip, Rotate); ESP_LOGI(TAG, "SetLayout 197 HFlip=%d VFlip=%d Rotate=%d (1=true)", Layout->HFlip, Layout->VFlip, Layout->Rotate);
// D/CX RDX WRX D17-8 D7 D6 D5 D4 D3 D2 D1 D0 HEX // D/CX RDX WRX D17-8 D7 D6 D5 D4 D3 D2 D1 D0 HEX
//Command 0 1 ↑ XX 0 0 1 1 0 1 1 0 36h //Command 0 1 ↑ XX 0 0 1 1 0 1 1 0 36h
//Parameter 1 1 ↑ XX MY MX MV ML BGR MH 0 0 00 //Parameter 1 1 ↑ XX MY MX MV ML BGR MH 0 0 00
//Orientation 0: MADCtl = 0x80 = 1000 0000 (MY=1) //Orientation 0: MADCtl = 0x80 = 1000 0000 (MY=1)
if ((Device->Height)>(Device->Width)){ //Resolution = 320x240 if ((Device->Height)>(Device->Width)){ //Resolution = 320x240
Private->MADCtl = (1 << 7); // 0x80 = default (no Rotation an no Flip) Private->MADCtl = (1 << 7); // 0x80 = default (no Rotation an no Flip)
if (HFlip) { //Flip Horizontal if (Layout->HFlip) { //Flip Horizontal
int a = Private->MADCtl; int a = Private->MADCtl;
Private->MADCtl = (a ^ (1 << 7)); Private->MADCtl = (a ^ (1 << 7));
} }
if (Rotate) { //Rotate 180 degr. if (Layout->Rotate) { //Rotate 180 degr.
int a = Private->MADCtl; int a = Private->MADCtl;
a = (a ^ (1 << 7)); a = (a ^ (1 << 7));
Private->MADCtl = (a ^ (1 << 6)); Private->MADCtl = (a ^ (1 << 6));
} }
if (VFlip) { //Flip Vertical if (Layout->VFlip) { //Flip Vertical
int a = Private->MADCtl; int a = Private->MADCtl;
Private->MADCtl = (a ^ (1 << 6)); Private->MADCtl = (a ^ (1 << 6));
} }
} else { //Resolution = 240x320 } else { //Resolution = 240x320
Private->MADCtl = (1 << 5); // 0x20 = default (no Rotation an no Flip) Private->MADCtl = (1 << 5); // 0x20 = default (no Rotation an no Flip)
if (HFlip) { //Flip Horizontal if (Layout->HFlip) { //Flip Horizontal
int a = Private->MADCtl; int a = Private->MADCtl;
Private->MADCtl = (a ^ (1 << 6)); Private->MADCtl = (a ^ (1 << 6));
} }
if (Rotate) { //Rotate 180 degr. if (Layout->Rotate) { //Rotate 180 degr.
int a = Private->MADCtl; int a = Private->MADCtl;
a = (a ^ (1 << 7)); a = (a ^ (1 << 7));
Private->MADCtl = (a ^ (1 << 6)); Private->MADCtl = (a ^ (1 << 6));
} }
if (VFlip) { //Flip Vertical if (Layout->VFlip) { //Flip Vertical
int a = Private->MADCtl; int a = Private->MADCtl;
Private->MADCtl = (a ^ (1 << 7)); Private->MADCtl = (a ^ (1 << 7));
} }
} }
Private->MADCtl = Layout->ColorSwap ? (Private->MADCtl | (1 << 3)) : (Private->MADCtl & ~(1 << 3));
ESP_LOGI(TAG, "SetLayout 255 Private->MADCtl=%hhu", Private->MADCtl); ESP_LOGI(TAG, "SetLayout 255 Private->MADCtl=%hhu", Private->MADCtl);
Device->WriteCommand( Device, 0x36 ); Device->WriteCommand( Device, 0x36 );
WriteByte( Device, Private->MADCtl ); WriteByte( Device, Private->MADCtl );
Device->WriteCommand( Device, Layout->Invert ? 0x21 : 0x20 );
#ifdef SHADOW_BUFFER #ifdef SHADOW_BUFFER
// force a full refresh (almost ...) // force a full refresh (almost ...)
@@ -274,7 +279,8 @@ static bool Init( struct GDS_Device* Device ) {
// set flip modes & contrast // set flip modes & contrast
GDS_SetContrast( Device, 0x7f ); GDS_SetContrast( Device, 0x7f );
Device->SetLayout( Device, false, false, false ); struct GDS_Layout Layout = { };
Device->SetLayout( Device, &Layout );
// set screen depth (16/18) *** INTERFACE PIXEL FORMAT: 0x66=18 bit; 0x55=16 bit // set screen depth (16/18) *** INTERFACE PIXEL FORMAT: 0x66=18 bit; 0x55=16 bit
Device->WriteCommand( Device, 0x3A ); Device->WriteCommand( Device, 0x3A );

View File

@@ -73,9 +73,10 @@ static void Update( struct GDS_Device* Device ) {
#endif #endif
} }
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
Device->WriteCommand( Device, HFlip ? 0xA1 : 0xA0 ); Device->WriteCommand( Device, Layout->HFlip ? 0xA1 : 0xA0 );
Device->WriteCommand( Device, VFlip ? 0xC8 : 0xC0 ); Device->WriteCommand( Device, Layout->VFlip ? 0xC8 : 0xC0 );
Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 );
} }
static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); }
@@ -86,7 +87,7 @@ static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
Device->WriteCommand( Device, Contrast ); Device->WriteCommand( Device, Contrast );
} }
static void SPIParams(int Speed, uint8_t *mode, uint8_t *CS_pre, uint8_t *CS_post) { static void SPIParams(int Speed, uint8_t *mode, uint16_t *CS_pre, uint8_t *CS_post) {
*CS_post = Speed / (8*1000*1000); *CS_post = Speed / (8*1000*1000);
} }
@@ -124,7 +125,8 @@ static bool Init( struct GDS_Device* Device ) {
Device->WriteCommand( Device, 0x40 + 0x00 ); Device->WriteCommand( Device, 0x40 + 0x00 );
Device->SetContrast( Device, 0x7F ); Device->SetContrast( Device, 0x7F );
// set flip modes // set flip modes
Device->SetLayout( Device, false, false, false ); struct GDS_Layout Layout = { };
Device->SetLayout( Device, &Layout );
// no Display Inversion // no Display Inversion
Device->WriteCommand( Device, 0xA6 ); Device->WriteCommand( Device, 0xA6 );
// set Clocks // set Clocks

View File

@@ -85,9 +85,10 @@ static void Update( struct GDS_Device* Device ) {
#endif #endif
} }
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
Device->WriteCommand( Device, HFlip ? 0xA1 : 0xA0 ); Device->WriteCommand( Device, Layout->HFlip ? 0xA1 : 0xA0 );
Device->WriteCommand( Device, VFlip ? 0xC8 : 0xC0 ); Device->WriteCommand( Device, Layout->VFlip ? 0xC8 : 0xC0 );
Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 );
} }
static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); }
@@ -132,7 +133,8 @@ static bool Init( struct GDS_Device* Device ) {
Device->WriteCommand( Device, 0x40 + 0x00 ); Device->WriteCommand( Device, 0x40 + 0x00 );
Device->SetContrast( Device, 0x7F ); Device->SetContrast( Device, 0x7F );
// set flip modes // set flip modes
Device->SetLayout( Device, false, false, false); struct GDS_Layout Layout = { };
Device->SetLayout( Device, &Layout );
// no Display Inversion // no Display Inversion
Device->WriteCommand( Device, 0xA6 ); Device->WriteCommand( Device, 0xA6 );
// set Clocks // set Clocks

View File

@@ -96,13 +96,14 @@ static void Update( struct GDS_Device* Device ) {
#endif #endif
} }
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
Private->ReMap = HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1)); Private->ReMap = Layout->HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1));
Private->ReMap = VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4)); Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
Device->WriteCommand( Device, 0xA0 ); Device->WriteCommand( Device, 0xA0 );
Device->WriteData( Device, &Private->ReMap, 1 ); Device->WriteData( Device, &Private->ReMap, 1 );
WriteDataByte( Device, 0x11 ); WriteDataByte( Device, 0x11 );
Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 );
} }
static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); }
@@ -145,7 +146,8 @@ static bool Init( struct GDS_Device* Device ) {
// set flip modes // set flip modes
Private->ReMap = 0; Private->ReMap = 0;
Device->SetLayout( Device, false, false, false); struct GDS_Layout Layout = { };
Device->SetLayout( Device, &Layout );
// set Display Enhancement // set Display Enhancement
Device->WriteCommand( Device, 0xB4 ); Device->WriteCommand( Device, 0xB4 );

View File

@@ -222,17 +222,18 @@ static void DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, i
} }
} }
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
if (Private->Model == SSD1326) { if (Private->Model == SSD1326) {
Private->ReMap = HFlip ? (Private->ReMap | ((1 << 0) | (1 << 2))) : (Private->ReMap & ~((1 << 0) | (1 << 2))); Private->ReMap = Layout->HFlip ? (Private->ReMap | ((1 << 0) | (1 << 2))) : (Private->ReMap & ~((1 << 0) | (1 << 2)));
Private->ReMap = HFlip ? (Private->ReMap | (1 << 1)) : (Private->ReMap & ~(1 << 1)); Private->ReMap = Layout->HFlip ? (Private->ReMap | (1 << 1)) : (Private->ReMap & ~(1 << 1));
} else { } else {
Private->ReMap = VFlip ? (Private->ReMap | ((1 << 0) | (1 << 1))) : (Private->ReMap & ~((1 << 0) | (1 << 1))); Private->ReMap = Layout->VFlip ? (Private->ReMap | ((1 << 0) | (1 << 1))) : (Private->ReMap & ~((1 << 0) | (1 << 1)));
Private->ReMap = VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4)); Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
} }
Device->WriteCommand( Device, 0xA0 ); Device->WriteCommand( Device, 0xA0 );
Device->WriteCommand( Device, Private->ReMap ); Device->WriteCommand( Device, Private->ReMap );
Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 );
} }
static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); }
@@ -288,7 +289,8 @@ static bool Init( struct GDS_Device* Device ) {
Device->WriteCommand( Device, 0x00 ); Device->WriteCommand( Device, 0x00 );
Device->SetContrast( Device, 0x7F ); Device->SetContrast( Device, 0x7F );
// set flip modes // set flip modes
Device->SetLayout( Device, false, false, false ); struct GDS_Layout Layout = { };
Device->SetLayout( Device, &Layout );
// no Display Inversion // no Display Inversion
Device->WriteCommand( Device, 0xA6 ); Device->WriteCommand( Device, 0xA6 );
// set Clocks // set Clocks

View File

@@ -181,12 +181,13 @@ static void Update24( struct GDS_Device* Device ) {
#endif #endif
} }
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
Private->ReMap = HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1)); Private->ReMap = Layout->HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1));
Private->ReMap = VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4)); Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
Device->WriteCommand( Device, 0xA0 ); Device->WriteCommand( Device, 0xA0 );
WriteByte( Device, Private->ReMap ); WriteByte( Device, Private->ReMap );
Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 );
} }
static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); }
@@ -239,7 +240,8 @@ static bool Init( struct GDS_Device* Device ) {
// set flip modes & contrast // set flip modes & contrast
Device->SetContrast( Device, 0x7F ); Device->SetContrast( Device, 0x7F );
Device->SetLayout( Device, false, false, false ); struct GDS_Layout Layout = { };
Device->SetLayout( Device, &Layout );
// set Adressing Mode Horizontal // set Adressing Mode Horizontal
Private->ReMap |= (0 << 2); Private->ReMap |= (0 << 2);

View File

@@ -188,20 +188,25 @@ static void Update24( struct GDS_Device* Device ) {
#endif #endif
} }
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
Private->MADCtl = HFlip ? (Private->MADCtl | (1 << 7)) : (Private->MADCtl & ~(1 << 7)); if (Private->Model == ST7789) {
Private->MADCtl = VFlip ? (Private->MADCtl | (1 << 6)) : (Private->MADCtl & ~(1 << 6)); if (Layout->Rotate) Private->Offset.Width += Layout->HFlip ? 320 - Device->Width : 0;
Private->MADCtl = Rotate ? (Private->MADCtl | (1 << 5)) : (Private->MADCtl & ~(1 << 5)); else Private->Offset.Height += Layout->HFlip ? 320 - Device->Height : 0;
Device->WriteCommand( Device, Layout->Invert ? 0x20 : 0x21 );
Private->MADCtl = Layout->ColorSwap ? (Private->MADCtl & ~(1 << 3)) : (Private->MADCtl | (1 << 3));
} else {
Device->WriteCommand( Device, Layout->Invert ? 0x21 : 0x20 );
Private->MADCtl = Layout->ColorSwap ? (Private->MADCtl | (1 << 3)) : (Private->MADCtl & ~(1 << 3));
}
Private->MADCtl = Layout->HFlip ? (Private->MADCtl | (1 << 7)) : (Private->MADCtl & ~(1 << 7));
Private->MADCtl = Layout->VFlip ? (Private->MADCtl | (1 << 6)) : (Private->MADCtl & ~(1 << 6));
Private->MADCtl = Layout->Rotate ? (Private->MADCtl | (1 << 5)) : (Private->MADCtl & ~(1 << 5));
Device->WriteCommand( Device, 0x36 ); Device->WriteCommand( Device, 0x36 );
WriteByte( Device, Private->MADCtl ); WriteByte( Device, Private->MADCtl );
if (Private->Model == ST7789) {
if (Rotate) Private->Offset.Width += HFlip ? 320 - Device->Width : 0;
else Private->Offset.Height += HFlip ? 320 - Device->Height : 0;
}
#ifdef SHADOW_BUFFER #ifdef SHADOW_BUFFER
// force a full refresh (almost ...) // force a full refresh (almost ...)
@@ -239,24 +244,22 @@ static bool Init( struct GDS_Device* Device ) {
// Sleepout + Booster // Sleepout + Booster
Device->WriteCommand( Device, 0x11 ); Device->WriteCommand( Device, 0x11 );
// need BGR & Address Mode // need BGR & Address Mode
Private->MADCtl = 1 << 3; Private->MADCtl = 1 << 3;
Device->WriteCommand( Device, 0x36 ); Device->WriteCommand( Device, 0x36 );
WriteByte( Device, Private->MADCtl ); WriteByte( Device, Private->MADCtl );
// set flip modes & contrast // set flip modes & contrast
GDS_SetContrast( Device, 0x7f ); GDS_SetContrast( Device, 0x7f );
Device->SetLayout( Device, false, false, false ); struct GDS_Layout Layout = { };
Device->SetLayout( Device, &Layout );
// set screen depth (16/18) // set screen depth (16/18)
Device->WriteCommand( Device, 0x3A ); Device->WriteCommand( Device, 0x3A );
if (Private->Model == ST7789) WriteByte( Device, Device->Depth == 24 ? 0x066 : 0x55 ); if (Private->Model == ST7789) WriteByte( Device, Device->Depth == 24 ? 0x066 : 0x55 );
else WriteByte( Device, Device->Depth == 24 ? 0x06 : 0x05 ); else WriteByte( Device, Device->Depth == 24 ? 0x06 : 0x05 );
// no Display Inversion
Device->WriteCommand( Device, Private->Model == ST7735 ? 0x20 : 0x21 );
// gone with the wind // gone with the wind
Device->DisplayOn( Device ); Device->DisplayOn( Device );
Device->Update( Device ); Device->Update( Device );

View File

@@ -236,7 +236,7 @@ void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
} }
} }
void GDS_SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { if (Device->SetLayout) Device->SetLayout( Device, HFlip, VFlip, Rotate ); } 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; } void GDS_SetDirty( struct GDS_Device* Device ) { Device->Dirty = true; }
int GDS_GetWidth( struct GDS_Device* Device ) { return Device ? Device->Width : 0; } int GDS_GetWidth( struct GDS_Device* Device ) { return Device ? Device->Width : 0; }
void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ) { 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; }

View File

@@ -26,6 +26,12 @@ struct GDS_BacklightPWM {
int Channel, Timer, Max; int Channel, Timer, Max;
bool Init; bool Init;
}; };
struct GDS_Layout {
bool HFlip, VFlip;
bool Rotate;
bool Invert;
bool ColorSwap;
};
typedef struct GDS_Device* GDS_DetectFunc(char *Driver, struct GDS_Device *Device); typedef struct GDS_Device* GDS_DetectFunc(char *Driver, struct GDS_Device *Device);
@@ -35,7 +41,7 @@ void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast );
void GDS_DisplayOn( struct GDS_Device* Device ); void GDS_DisplayOn( struct GDS_Device* Device );
void GDS_DisplayOff( struct GDS_Device* Device ); void GDS_DisplayOff( struct GDS_Device* Device );
void GDS_Update( struct GDS_Device* Device ); void GDS_Update( struct GDS_Device* Device );
void GDS_SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ); void GDS_SetLayout( struct GDS_Device* Device, struct GDS_Layout* Layout);
void GDS_SetDirty( struct GDS_Device* Device ); void GDS_SetDirty( struct GDS_Device* Device );
int GDS_GetWidth( struct GDS_Device* Device ); int GDS_GetWidth( struct GDS_Device* Device );
void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ); void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth );

View File

@@ -117,7 +117,7 @@ struct GDS_Device {
void (*SetContrast)( struct GDS_Device* Device, uint8_t Contrast ); void (*SetContrast)( struct GDS_Device* Device, uint8_t Contrast );
void (*DisplayOn)( struct GDS_Device* Device ); void (*DisplayOn)( struct GDS_Device* Device );
void (*DisplayOff)( struct GDS_Device* Device ); void (*DisplayOff)( struct GDS_Device* Device );
void (*SetLayout)( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ); void (*SetLayout)( struct GDS_Device* Device, struct GDS_Layout *Layout );
// must provide for depth other than 1 (vertical) and 4 (may provide for optimization) // must provide for depth other than 1 (vertical) and 4 (may provide for optimization)
void (*DrawPixelFast)( struct GDS_Device* Device, int X, int Y, int Color ); void (*DrawPixelFast)( struct GDS_Device* Device, int X, int Y, int Color );
void (*DrawBitmapCBR)(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color ); void (*DrawBitmapCBR)(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color );

View File

@@ -141,8 +141,15 @@ void display_init(char *welcome) {
if (init) { if (init) {
static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4))); static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4)));
static EXT_RAM_ATTR StackType_t xStack[DISPLAYER_STACK_SIZE] __attribute__ ((aligned (4))); static EXT_RAM_ATTR StackType_t xStack[DISPLAYER_STACK_SIZE] __attribute__ ((aligned (4)));
struct GDS_Layout Layout = {
GDS_SetLayout(display, strcasestr(config, "HFlip"), strcasestr(config, "VFlip"), strcasestr(config, "rotate")); .HFlip = strcasestr(config, "HFlip"),
.VFlip = strcasestr(config, "VFlip"),
.Rotate = strcasestr(config, "rotate"),
.Invert = strcasestr(config, "invert"),
.ColorSwap = strcasestr(config, "cswap"),
};
GDS_SetLayout(display, &Layout);
GDS_SetFont(display, &Font_droid_sans_fallback_15x17 ); GDS_SetFont(display, &Font_droid_sans_fallback_15x17 );
GDS_TextPos(display, GDS_FONT_MEDIUM, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, welcome); GDS_TextPos(display, GDS_FONT_MEDIUM, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, welcome);

View File

@@ -368,7 +368,9 @@ const display_config_t * config_display_get(){
.hflip = false, .hflip = false,
.type = NULL, .type = NULL,
.speed = 0, .speed = 0,
.rotate = false .rotate = false,
.invert = false,
.colorswap = 0,
}; };
char *config = config_alloc_get(NVS_TYPE_STR, "display_config"); char *config = config_alloc_get(NVS_TYPE_STR, "display_config");
if (!config) { if (!config) {
@@ -396,6 +398,8 @@ const display_config_t * config_display_get(){
dstruct.hflip= strcasestr(config, "HFlip") ? true : false; dstruct.hflip= strcasestr(config, "HFlip") ? true : false;
dstruct.vflip= strcasestr(config, "VFlip") ? true : false; dstruct.vflip= strcasestr(config, "VFlip") ? true : false;
dstruct.rotate= strcasestr(config, "rotate") ? true : false; dstruct.rotate= strcasestr(config, "rotate") ? true : false;
dstruct.invert= strcasestr(config, "invert") ? true : false;
dstruct.colorswap= strcasestr(config, "cswap") ? 1 : 0;
return &dstruct; return &dstruct;
} }

View File

@@ -31,6 +31,8 @@ typedef struct {
int depth; int depth;
const char *type; const char *type;
bool rotate; bool rotate;
bool invert;
int colorswap;
} display_config_t; } display_config_t;
typedef struct { typedef struct {

View File

@@ -875,7 +875,9 @@ static void grfa_handler(u8_t *data, int len) {
artwork.size += size; artwork.size += size;
if (artwork.size == length) { if (artwork.size == length) {
GDS_ClearWindow(display, artwork.x, artwork.y, -1, -1, GDS_COLOR_BLACK); GDS_ClearWindow(display, artwork.x, artwork.y, -1, -1, GDS_COLOR_BLACK);
xSemaphoreTake(displayer.mutex, portMAX_DELAY);
GDS_DrawJPEG(display, artwork.data, artwork.x, artwork.y, artwork.y < displayer.height ? (GDS_IMAGE_RIGHT | GDS_IMAGE_TOP) : GDS_IMAGE_CENTER); GDS_DrawJPEG(display, artwork.data, artwork.x, artwork.y, artwork.y < displayer.height ? (GDS_IMAGE_RIGHT | GDS_IMAGE_TOP) : GDS_IMAGE_CENTER);
xSemaphoreGive(displayer.mutex);
free(artwork.data); free(artwork.data);
artwork.data = NULL; artwork.data = NULL;
} }

View File

@@ -175,7 +175,7 @@ static void jack_handler(bool inserted) {
/**************************************************************************************** /****************************************************************************************
* amp GPIO * amp GPIO
*/ */
#ifndef AMP_GPIO_LOCKED #ifndef AMP_LOCKED
static void set_amp_gpio(int gpio, char *value) { static void set_amp_gpio(int gpio, char *value) {
char *p; char *p;
@@ -347,7 +347,7 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
jack_handler_chain = jack_handler_svc; jack_handler_chain = jack_handler_svc;
jack_handler_svc = jack_handler; jack_handler_svc = jack_handler;
#ifndef AMP_GPIO_LOCKED #ifndef AMP_LOCKED
parse_set_GPIO(set_amp_gpio); parse_set_GPIO(set_amp_gpio);
#endif #endif

View File

@@ -128,7 +128,7 @@ menu "Squeezelite-ESP32"
default "" default ""
config AUDIO_CONTROLS config AUDIO_CONTROLS
string string
default "[{\"gpio\":32, \"pull\":true, \"debounce\":10, \"normal\":{\"pressed\":\"ACTRLS_VOLDOWN\"}}, {\"gpio\":19, \"pull\":true, \"debounce\":40, \"normal\":{\"pressed\":\"ACTRLS_VOLUP\"}}, {\"gpio\":12, \"pull\":true, \"debounce\":40, \"long_press\":1000, \"normal\":{\"pressed\":\"ACTRLS_TOGGLE\"},\"longpress\":{\"pressed\":\"ACTRLS_POWER\"}}]" if MUSE default "[{\"gpio\":32, \"pull\":true, \"long_press\":1000, \"normal\":{\"pressed\":\"ACTRLS_VOLDOWN\"}, \"longpress\":{\"pressed\":\"ACTRLS_PREV\"}}, {\"gpio\":19, \"pull\":true, \"long_press\":1000, \"normal\":{\"pressed\":\"ACTRLS_VOLUP\"}, \"longpress\":{\"pressed\":\"ACTRLS_NEXT\"}}, {\"gpio\":12, \"pull\":true, \"long_press\":1000, \"normal\":{\"pressed\":\"ACTRLS_TOGGLE\"},\"longpress\":{\"pressed\":\"ACTRLS_POWER\"}}]" if MUSE
default "" default ""
config BAT_CONFIG config BAT_CONFIG
string string