mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-18 05:28:29 +03:00
Compare commits
19 Commits
SqueezeAmp
...
Muse.16.10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60ba05d3d9 | ||
|
|
099d9ffd1e | ||
|
|
3d30b45723 | ||
|
|
87fae72887 | ||
|
|
1f78db596e | ||
|
|
c0bd080ea1 | ||
|
|
29d4214e28 | ||
|
|
b828e7f3e6 | ||
|
|
6843d4b1ef | ||
|
|
78877914ef | ||
|
|
dbcaf15e7b | ||
|
|
4f318e217f | ||
|
|
270ee819ea | ||
|
|
ace8206b4d | ||
|
|
564e98d90e | ||
|
|
796d39d0a9 | ||
|
|
20c00de728 | ||
|
|
9775fd52b8 | ||
|
|
7a04ec03e9 |
3
.github/workflows/CrossBuild.yml
vendored
3
.github/workflows/CrossBuild.yml
vendored
@@ -28,6 +28,9 @@ jobs:
|
||||
matrix:
|
||||
node: [I2S-4MFlash, SqueezeAmp, Muse]
|
||||
depth: [16, 32]
|
||||
exclude:
|
||||
- node: Muse
|
||||
depth: 32
|
||||
steps:
|
||||
- name: Set target name
|
||||
run: |
|
||||
|
||||
13
README.md
13
README.md
@@ -81,6 +81,7 @@ NB: You can use the pre-build binaries SqueezeAMP4MBFlash which has all the hard
|
||||
This portable battery-powered [speaker](https://raspiaudio.com/produit/esp-muse-luxe) is compatible with squeezelite-esp32 for which there is a dedicated build supplied with every update. If you want to rebuild, use the `squeezelite-esp32-Muse-sdkconfig.defaults` configuration file.
|
||||
|
||||
NB: You can use the pre-build binaries Muse4MBFlash which has all the hardware I/O set properly. You can also use the generic binary I2S4MBFlash in which case the NVS parameters shall be set to get the exact same behavior
|
||||
- target: `muse`
|
||||
- bat_config: `channel=5,scale=7.48,atten=3,cells=1`
|
||||
- spi_config: `"mosi=15,miso=2,clk=14` *(this one is probably optional)*
|
||||
- dac_config: `model=I2S,bck=5,ws=25,do=26,di=35,i2c=16,sda=18,scl=23,mck`
|
||||
@@ -154,6 +155,10 @@ And the super cool project https://github.com/rochuck/squeeze-amp-too
|
||||
## Configuration
|
||||
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.
|
||||
|
||||
As mentionned above, there are a few dedicated builds that are provided today: SqueezeAMP and Muse but if you build it yourself, you can also create a build for T-WATCH2020. The default build is a generic firmware named I2S which can be configured through NVS to produce *exactly* the same results than dedicated builds. The difference is that parameters must be entered and can accidently be erased. The GUI provides a great help to load "known config sets" as well.
|
||||
|
||||
By design choice, there is no code that is only embedded for a given version, all code is always there. The philosophy is to minimize as much as possible platform-specific code and use of specific `#ifdef` is prohibited, no matter what. So if you want to add your own platfrom, please look **very hard** at the `main\KConfig.projbuild` to see how you can, using parameters below, make your device purely a configuration-based solution. When there is really no other option, look at `targets\<target>` to add your own code. I will not accept PR for code that can avoid creating such dedicated code whenever possible. The NVS "target" will be used to call target-specific code then, but again this is purely runtime, not compile-time.
|
||||
|
||||
### 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. Default speed is 400000 but some display can do up to 800000 or more. Syntax is
|
||||
```
|
||||
@@ -217,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
|
||||
```
|
||||
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
|
||||
- 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
|
||||
- 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
|
||||
- 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)
|
||||
@@ -420,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.
|
||||
|
||||
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.
|
||||
|
||||
**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
|
||||
|
||||
**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**
|
||||
|
||||
@@ -27,8 +27,8 @@ CONFIG_JACK_GPIO_LEVEL=0
|
||||
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_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_BAT_CONFIG="channel=5,scale=1,atten=3,cells=1"
|
||||
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=7.00,atten=3,cells=1"
|
||||
CONFIG_I2S_NUM=0
|
||||
CONFIG_SPDIF_NUM=0
|
||||
CONFIG_SPDIF_CONFIG=""
|
||||
|
||||
@@ -191,49 +191,54 @@ static void Update24( struct GDS_Device* Device ) {
|
||||
#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;
|
||||
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
|
||||
//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
|
||||
//Orientation 0: MADCtl = 0x80 = 1000 0000 (MY=1)
|
||||
if ((Device->Height)>(Device->Width)){ //Resolution = 320x240
|
||||
Private->MADCtl = (1 << 7); // 0x80 = default (no Rotation an no Flip)
|
||||
if (HFlip) { //Flip Horizontal
|
||||
if (Layout->HFlip) { //Flip Horizontal
|
||||
int a = Private->MADCtl;
|
||||
Private->MADCtl = (a ^ (1 << 7));
|
||||
}
|
||||
if (Rotate) { //Rotate 180 degr.
|
||||
if (Layout->Rotate) { //Rotate 180 degr.
|
||||
int a = Private->MADCtl;
|
||||
a = (a ^ (1 << 7));
|
||||
Private->MADCtl = (a ^ (1 << 6));
|
||||
}
|
||||
if (VFlip) { //Flip Vertical
|
||||
if (Layout->VFlip) { //Flip Vertical
|
||||
int a = Private->MADCtl;
|
||||
Private->MADCtl = (a ^ (1 << 6));
|
||||
}
|
||||
} else { //Resolution = 240x320
|
||||
Private->MADCtl = (1 << 5); // 0x20 = default (no Rotation an no Flip)
|
||||
if (HFlip) { //Flip Horizontal
|
||||
if (Layout->HFlip) { //Flip Horizontal
|
||||
int a = Private->MADCtl;
|
||||
Private->MADCtl = (a ^ (1 << 6));
|
||||
}
|
||||
if (Rotate) { //Rotate 180 degr.
|
||||
if (Layout->Rotate) { //Rotate 180 degr.
|
||||
int a = Private->MADCtl;
|
||||
a = (a ^ (1 << 7));
|
||||
Private->MADCtl = (a ^ (1 << 6));
|
||||
}
|
||||
if (VFlip) { //Flip Vertical
|
||||
if (Layout->VFlip) { //Flip Vertical
|
||||
int a = Private->MADCtl;
|
||||
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);
|
||||
|
||||
Device->WriteCommand( Device, 0x36 );
|
||||
WriteByte( Device, Private->MADCtl );
|
||||
|
||||
Device->WriteCommand( Device, Layout->Invert ? 0x21 : 0x20 );
|
||||
|
||||
|
||||
#ifdef SHADOW_BUFFER
|
||||
// force a full refresh (almost ...)
|
||||
@@ -274,7 +279,8 @@ static bool Init( struct GDS_Device* Device ) {
|
||||
|
||||
// set flip modes & contrast
|
||||
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
|
||||
Device->WriteCommand( Device, 0x3A );
|
||||
|
||||
@@ -73,9 +73,10 @@ static void Update( struct GDS_Device* Device ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) {
|
||||
Device->WriteCommand( Device, HFlip ? 0xA1 : 0xA0 );
|
||||
Device->WriteCommand( Device, VFlip ? 0xC8 : 0xC0 );
|
||||
static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
|
||||
Device->WriteCommand( Device, Layout->HFlip ? 0xA1 : 0xA0 );
|
||||
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 ); }
|
||||
@@ -86,7 +87,7 @@ static void SetContrast( struct GDS_Device* Device, uint8_t 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);
|
||||
}
|
||||
|
||||
@@ -124,7 +125,8 @@ static bool Init( struct GDS_Device* Device ) {
|
||||
Device->WriteCommand( Device, 0x40 + 0x00 );
|
||||
Device->SetContrast( Device, 0x7F );
|
||||
// set flip modes
|
||||
Device->SetLayout( Device, false, false, false );
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
// no Display Inversion
|
||||
Device->WriteCommand( Device, 0xA6 );
|
||||
// set Clocks
|
||||
|
||||
@@ -85,9 +85,10 @@ static void Update( struct GDS_Device* Device ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) {
|
||||
Device->WriteCommand( Device, HFlip ? 0xA1 : 0xA0 );
|
||||
Device->WriteCommand( Device, VFlip ? 0xC8 : 0xC0 );
|
||||
static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
|
||||
Device->WriteCommand( Device, Layout->HFlip ? 0xA1 : 0xA0 );
|
||||
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 ); }
|
||||
@@ -132,7 +133,8 @@ static bool Init( struct GDS_Device* Device ) {
|
||||
Device->WriteCommand( Device, 0x40 + 0x00 );
|
||||
Device->SetContrast( Device, 0x7F );
|
||||
// set flip modes
|
||||
Device->SetLayout( Device, false, false, false);
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
// no Display Inversion
|
||||
Device->WriteCommand( Device, 0xA6 );
|
||||
// set Clocks
|
||||
|
||||
@@ -96,13 +96,14 @@ static void Update( struct GDS_Device* Device ) {
|
||||
#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;
|
||||
Private->ReMap = HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1));
|
||||
Private->ReMap = VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
|
||||
Private->ReMap = Layout->HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1));
|
||||
Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
|
||||
Device->WriteCommand( Device, 0xA0 );
|
||||
Device->WriteData( Device, &Private->ReMap, 1 );
|
||||
WriteDataByte( Device, 0x11 );
|
||||
Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 );
|
||||
}
|
||||
|
||||
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
|
||||
Private->ReMap = 0;
|
||||
Device->SetLayout( Device, false, false, false);
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
|
||||
// set Display Enhancement
|
||||
Device->WriteCommand( Device, 0xB4 );
|
||||
|
||||
@@ -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;
|
||||
if (Private->Model == SSD1326) {
|
||||
Private->ReMap = 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 << 0) | (1 << 2))) : (Private->ReMap & ~((1 << 0) | (1 << 2)));
|
||||
Private->ReMap = Layout->HFlip ? (Private->ReMap | (1 << 1)) : (Private->ReMap & ~(1 << 1));
|
||||
} else {
|
||||
Private->ReMap = 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 << 0) | (1 << 1))) : (Private->ReMap & ~((1 << 0) | (1 << 1)));
|
||||
Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
|
||||
}
|
||||
Device->WriteCommand( Device, 0xA0 );
|
||||
Device->WriteCommand( Device, Private->ReMap );
|
||||
Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 );
|
||||
}
|
||||
|
||||
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->SetContrast( Device, 0x7F );
|
||||
// set flip modes
|
||||
Device->SetLayout( Device, false, false, false );
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
// no Display Inversion
|
||||
Device->WriteCommand( Device, 0xA6 );
|
||||
// set Clocks
|
||||
|
||||
@@ -181,12 +181,13 @@ static void Update24( struct GDS_Device* Device ) {
|
||||
#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;
|
||||
Private->ReMap = HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1));
|
||||
Private->ReMap = VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
|
||||
Private->ReMap = Layout->HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1));
|
||||
Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
|
||||
Device->WriteCommand( Device, 0xA0 );
|
||||
WriteByte( Device, Private->ReMap );
|
||||
Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 );
|
||||
}
|
||||
|
||||
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
|
||||
Device->SetContrast( Device, 0x7F );
|
||||
Device->SetLayout( Device, false, false, false );
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
|
||||
// set Adressing Mode Horizontal
|
||||
Private->ReMap |= (0 << 2);
|
||||
|
||||
@@ -188,20 +188,25 @@ static void Update24( struct GDS_Device* Device ) {
|
||||
#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;
|
||||
|
||||
Private->MADCtl = HFlip ? (Private->MADCtl | (1 << 7)) : (Private->MADCtl & ~(1 << 7));
|
||||
Private->MADCtl = VFlip ? (Private->MADCtl | (1 << 6)) : (Private->MADCtl & ~(1 << 6));
|
||||
Private->MADCtl = Rotate ? (Private->MADCtl | (1 << 5)) : (Private->MADCtl & ~(1 << 5));
|
||||
|
||||
if (Private->Model == ST7789) {
|
||||
if (Layout->Rotate) Private->Offset.Width += Layout->HFlip ? 320 - Device->Width : 0;
|
||||
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 );
|
||||
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
|
||||
// force a full refresh (almost ...)
|
||||
@@ -239,24 +244,22 @@ static bool Init( struct GDS_Device* Device ) {
|
||||
|
||||
// Sleepout + Booster
|
||||
Device->WriteCommand( Device, 0x11 );
|
||||
|
||||
|
||||
// need BGR & Address Mode
|
||||
Private->MADCtl = 1 << 3;
|
||||
Device->WriteCommand( Device, 0x36 );
|
||||
WriteByte( Device, Private->MADCtl );
|
||||
|
||||
|
||||
// set flip modes & contrast
|
||||
GDS_SetContrast( Device, 0x7f );
|
||||
Device->SetLayout( Device, false, false, false );
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
|
||||
// set screen depth (16/18)
|
||||
Device->WriteCommand( Device, 0x3A );
|
||||
if (Private->Model == ST7789) WriteByte( Device, Device->Depth == 24 ? 0x066 : 0x55 );
|
||||
else WriteByte( Device, Device->Depth == 24 ? 0x06 : 0x05 );
|
||||
|
||||
// no Display Inversion
|
||||
Device->WriteCommand( Device, Private->Model == ST7735 ? 0x20 : 0x21 );
|
||||
|
||||
// gone with the wind
|
||||
Device->DisplayOn( Device );
|
||||
Device->Update( Device );
|
||||
|
||||
@@ -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; }
|
||||
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; }
|
||||
|
||||
@@ -26,6 +26,12 @@ struct GDS_BacklightPWM {
|
||||
int Channel, Timer, Max;
|
||||
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);
|
||||
|
||||
@@ -35,7 +41,7 @@ void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast );
|
||||
void GDS_DisplayOn( struct GDS_Device* Device );
|
||||
void GDS_DisplayOff( 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 );
|
||||
int GDS_GetWidth( struct GDS_Device* Device );
|
||||
void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth );
|
||||
|
||||
@@ -117,7 +117,7 @@ struct GDS_Device {
|
||||
void (*SetContrast)( struct GDS_Device* Device, uint8_t Contrast );
|
||||
void (*DisplayOn)( 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)
|
||||
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 );
|
||||
|
||||
@@ -141,8 +141,15 @@ void display_init(char *welcome) {
|
||||
if (init) {
|
||||
static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4)));
|
||||
static EXT_RAM_ATTR StackType_t xStack[DISPLAYER_STACK_SIZE] __attribute__ ((aligned (4)));
|
||||
|
||||
GDS_SetLayout(display, strcasestr(config, "HFlip"), strcasestr(config, "VFlip"), strcasestr(config, "rotate"));
|
||||
struct GDS_Layout Layout = {
|
||||
.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_TextPos(display, GDS_FONT_MEDIUM, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, welcome);
|
||||
|
||||
|
||||
@@ -368,7 +368,9 @@ const display_config_t * config_display_get(){
|
||||
.hflip = false,
|
||||
.type = NULL,
|
||||
.speed = 0,
|
||||
.rotate = false
|
||||
.rotate = false,
|
||||
.invert = false,
|
||||
.colorswap = 0,
|
||||
};
|
||||
char *config = config_alloc_get(NVS_TYPE_STR, "display_config");
|
||||
if (!config) {
|
||||
@@ -396,6 +398,8 @@ const display_config_t * config_display_get(){
|
||||
dstruct.hflip= strcasestr(config, "HFlip") ? true : false;
|
||||
dstruct.vflip= strcasestr(config, "VFlip") ? 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ typedef struct {
|
||||
int depth;
|
||||
const char *type;
|
||||
bool rotate;
|
||||
bool invert;
|
||||
int colorswap;
|
||||
} display_config_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -875,7 +875,9 @@ static void grfa_handler(u8_t *data, int len) {
|
||||
artwork.size += size;
|
||||
if (artwork.size == length) {
|
||||
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);
|
||||
xSemaphoreGive(displayer.mutex);
|
||||
free(artwork.data);
|
||||
artwork.data = NULL;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ static void jack_handler(bool inserted) {
|
||||
/****************************************************************************************
|
||||
* amp GPIO
|
||||
*/
|
||||
#ifndef AMP_GPIO_LOCKED
|
||||
#ifndef AMP_LOCKED
|
||||
static void set_amp_gpio(int gpio, char *value) {
|
||||
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_svc = jack_handler;
|
||||
|
||||
#ifndef AMP_GPIO_LOCKED
|
||||
#ifndef AMP_LOCKED
|
||||
parse_set_GPIO(set_amp_gpio);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <esp_system.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
//#include <driver/adc.h>
|
||||
#include "driver/rmt.h"
|
||||
#include "monitor.h"
|
||||
#include "targets.h"
|
||||
@@ -24,14 +23,18 @@
|
||||
|
||||
// These values are determined by measuring pulse timing with logic analyzer and adjusting to match datasheet.
|
||||
#define T0H 14 // 0 bit high time
|
||||
#define T1H 52 // 1 bit high time
|
||||
#define T1H 52 // 1 bit high time
|
||||
#define TL 52 // low time for either bit
|
||||
|
||||
#define GREEN 0xFF0000
|
||||
#define RED 0x00FF00
|
||||
#define BLUE 0x0000FF
|
||||
#define WHITE 0xFFFFFF
|
||||
#define YELLOW 0xE0F060
|
||||
// sets a color based on RGB from 0..255 and a brightness in % from 0..100
|
||||
#define RGB(R,G,B,BR) (((G*BR)/100) << 16) | (((R*BR)/100) << 8) | ((B*BR)/100)
|
||||
|
||||
#define RED RGB(255,0,0,10)
|
||||
#define GREEN RGB(0,255,0,10)
|
||||
#define BLUE RGB(0,0,255,10)
|
||||
#define WHITE RGB(255,255,255,10)
|
||||
#define YELLOW RGB(255,118,13,10)
|
||||
|
||||
struct led_state {
|
||||
uint32_t leds[NUM_LEDS];
|
||||
};
|
||||
|
||||
@@ -128,12 +128,12 @@ menu "Squeezelite-ESP32"
|
||||
default ""
|
||||
config AUDIO_CONTROLS
|
||||
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 ""
|
||||
config BAT_CONFIG
|
||||
string
|
||||
default "channel=7,scale=20.24,atten=0" if SQUEEZEAMP
|
||||
default "channel=5,scale=7.48,atten=3,cells=1" if MUSE
|
||||
default "channel=5,scale=7.00,atten=3,cells=1" if MUSE
|
||||
default ""
|
||||
config TARGET
|
||||
string
|
||||
|
||||
Reference in New Issue
Block a user