mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-07 12:07:09 +03:00
Compare commits
71 Commits
build-numb
...
v0.5.656-v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca97b8045e | ||
|
|
5e8a3fd755 | ||
|
|
92fffb7635 | ||
|
|
5e372860c8 | ||
|
|
36c3f0eb49 | ||
|
|
4ecc9da6d3 | ||
|
|
45e0dd38df | ||
|
|
3922851129 | ||
|
|
f08bde8d48 | ||
|
|
a6b57604d3 | ||
|
|
ca33ff4ba9 | ||
|
|
8b55fa3986 | ||
|
|
e04a631665 | ||
|
|
bcb087f9ee | ||
|
|
c5d871f5ee | ||
|
|
a87066fef6 | ||
|
|
683ec77424 | ||
|
|
e5050c9f72 | ||
|
|
daf98c7d50 | ||
|
|
91b0efd741 | ||
|
|
8820a85112 | ||
|
|
4a56b55b49 | ||
|
|
5c79b0c0e8 | ||
|
|
ffd0320e54 | ||
|
|
80bf63ed2a | ||
|
|
f9b7d10243 | ||
|
|
ad2846f50d | ||
|
|
340a1bd19e | ||
|
|
1dcd0aeacb | ||
|
|
0bcc2bcecc | ||
|
|
9d7c0eb48f | ||
|
|
a4200b4b85 | ||
|
|
80188e944c | ||
|
|
e6c5c04fd6 | ||
|
|
78563b20f3 | ||
|
|
9fd792cf98 | ||
|
|
c7697c31cd | ||
|
|
77e8c29936 | ||
|
|
bf4358f340 | ||
|
|
3de62b3ad2 | ||
|
|
4f90002c99 | ||
|
|
f4af5cfda0 | ||
|
|
f4f4570c2a | ||
|
|
be6bbe1bcc | ||
|
|
dfe468b610 | ||
|
|
da1aa2e74e | ||
|
|
c12e0b39f6 | ||
|
|
b929436f4f | ||
|
|
e39580ad5d | ||
|
|
254459fbf5 | ||
|
|
32a847bf02 | ||
|
|
22b86b3323 | ||
|
|
97856e2f0f | ||
|
|
fafb764120 | ||
|
|
4451aff1c8 | ||
|
|
af4472dbe9 | ||
|
|
cf81182dae | ||
|
|
ba75350455 | ||
|
|
0db1ac38e4 | ||
|
|
fbbe73b1d6 | ||
|
|
b4c17b02a0 | ||
|
|
8911d44327 | ||
|
|
3e39300759 | ||
|
|
dd9018ca28 | ||
|
|
ca5754be5d | ||
|
|
dc9e235157 | ||
|
|
c2c31a191e | ||
|
|
9f3bc774d4 | ||
|
|
e87bc7dd83 | ||
|
|
14cc21eb66 | ||
|
|
4517e9040a |
558
.cproject
558
.cproject
@@ -3,13 +3,383 @@
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
|
||||
<cconfiguration id="org.eclipse.cdt.core.default.config.959280881">
|
||||
<cconfiguration id="cdt.managedbuild.toolchain.gnu.cross.base.293933348">
|
||||
|
||||
<storageModule buildSystemId="org.eclipse.cdt.core.defaultConfigDataProvider" id="org.eclipse.cdt.core.default.config.959280881" moduleId="org.eclipse.cdt.core.settings" name="Configuration">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.cross.base.293933348" moduleId="org.eclipse.cdt.core.settings" name="Default">
|
||||
|
||||
<macros>
|
||||
|
||||
<stringMacro name="RECOVERY_APPLICATION" type="VALUE_TEXT" value="0"/>
|
||||
|
||||
</macros>
|
||||
|
||||
<externalSettings/>
|
||||
|
||||
<extensions/>
|
||||
<extensions>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.cross.base.293933348" name="Default" optionalBuildProperties="" parent="org.eclipse.cdt.build.core.emptycfg">
|
||||
|
||||
<folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.949515869" name="/" resourcePath="">
|
||||
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.1860816932" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
|
||||
|
||||
<option id="cdt.managedbuild.option.gnu.cross.prefix.211558150" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
|
||||
|
||||
<option id="cdt.managedbuild.option.gnu.cross.path.660444977" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path"/>
|
||||
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1109615480" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
||||
|
||||
<builder arguments="-j8 EXTRA_CPPFLAGS="-DRECOVERY_APPLICATION=0"" command="make" id="cdt.managedbuild.builder.gnu.cross.1247197310" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.924305212" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="gnu.c.compiler.option.preprocessor.def.symbols.237333664" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.851339966" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1689301712" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="gnu.cpp.compiler.option.preprocessor.def.1320841573" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1117032298" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.69706729" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.1919651858" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1241928244" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
||||
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
|
||||
</inputType>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.1543827445" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.1248561272" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.736707865" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
</toolChain>
|
||||
|
||||
</folderInfo>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
|
||||
</cconfiguration>
|
||||
|
||||
<cconfiguration id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934">
|
||||
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934" moduleId="org.eclipse.cdt.core.settings" name="recovery">
|
||||
|
||||
<macros>
|
||||
|
||||
<stringMacro name="RECOVERY_APPLICATION" type="VALUE_TEXT" value="1"/>
|
||||
|
||||
</macros>
|
||||
|
||||
<externalSettings/>
|
||||
|
||||
<extensions>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934" name="recovery" optionalBuildProperties="" parent="org.eclipse.cdt.build.core.emptycfg">
|
||||
|
||||
<folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934." name="/" resourcePath="">
|
||||
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.1561608239" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
|
||||
|
||||
<option id="cdt.managedbuild.option.gnu.cross.prefix.878380733" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
|
||||
|
||||
<option id="cdt.managedbuild.option.gnu.cross.path.576225618" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path"/>
|
||||
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1674304340" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
||||
|
||||
<builder arguments="-j8 EXTRA_CPPFLAGS="-DRECOVERY_APPLICATION=1"" command="make" id="cdt.managedbuild.builder.gnu.cross.1616827916" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.1397900624" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="gnu.c.compiler.option.preprocessor.def.symbols.1168574489" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.24917724" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.40066190" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="gnu.cpp.compiler.option.preprocessor.def.1538103313" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.773825889" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.750042642" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.791695355" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.363611836" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
||||
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
|
||||
</inputType>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.788163154" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.747849588" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.597864277" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
</toolChain>
|
||||
|
||||
</folderInfo>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
|
||||
</cconfiguration>
|
||||
|
||||
<cconfiguration id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291">
|
||||
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291" moduleId="org.eclipse.cdt.core.settings" name="recovery_windows">
|
||||
|
||||
<macros>
|
||||
|
||||
<stringMacro name="RECOVERY_APPLICATION" type="VALUE_TEXT" value="1"/>
|
||||
|
||||
</macros>
|
||||
|
||||
<externalSettings/>
|
||||
|
||||
<extensions>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<configuration artifactName="${ProjName}" buildProperties="" description="Building recovery in windows" id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291" name="recovery_windows" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="org.eclipse.cdt.build.core.emptycfg">
|
||||
|
||||
<folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291." name="/" resourcePath="">
|
||||
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.845245133" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
|
||||
|
||||
<option id="cdt.managedbuild.option.gnu.cross.prefix.1090509495" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
|
||||
|
||||
<option id="cdt.managedbuild.option.gnu.cross.path.447265559" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path"/>
|
||||
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1831977109" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
||||
|
||||
<builder arguments=""c:/msys32/opt/esp-idf/tools/windows/eclipse_make.py" EXTRA_CPPFLAGS='-DRECOVERY_APPLICATION=${RECOVERY_APPLICATION}'" buildPath="${workspace_loc:/squeezelite-esp32}" command="python" id="cdt.managedbuild.builder.gnu.cross.1069921467" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.1302011176" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="gnu.c.compiler.option.preprocessor.def.symbols.623798750" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.539301587" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1722031516" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="gnu.cpp.compiler.option.preprocessor.def.2010227748" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.2073997022" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.746651743" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.149944553" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1372009292" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
||||
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
|
||||
</inputType>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.649046248" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.2132030687" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1779870241" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
</toolChain>
|
||||
|
||||
</folderInfo>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
|
||||
</cconfiguration>
|
||||
|
||||
<cconfiguration id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736">
|
||||
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736" moduleId="org.eclipse.cdt.core.settings" name="squeezelite_windows">
|
||||
|
||||
<macros>
|
||||
|
||||
<stringMacro name="RECOVERY_APPLICATION" type="VALUE_TEXT" value="0"/>
|
||||
|
||||
</macros>
|
||||
|
||||
<externalSettings/>
|
||||
|
||||
<extensions>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<configuration artifactName="${ProjName}" buildProperties="" description="building squeezelite app in windows" id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736" name="squeezelite_windows" optionalBuildProperties="" parent="org.eclipse.cdt.build.core.emptycfg">
|
||||
|
||||
<folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736." name="/" resourcePath="">
|
||||
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.1034176750" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
|
||||
|
||||
<option id="cdt.managedbuild.option.gnu.cross.prefix.1038632104" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
|
||||
|
||||
<option id="cdt.managedbuild.option.gnu.cross.path.1589817380" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path"/>
|
||||
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.784380822" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
||||
|
||||
<builder arguments=""C:/msys32/opt/esp-idf/tools/windows/eclipse_make.py" -j8 EXTRA_CPPFLAGS="-DRECOVERY_APPLICATION=0"" command="python" id="cdt.managedbuild.builder.gnu.cross.1150681639" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.824219909" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="gnu.c.compiler.option.preprocessor.def.symbols.217201640" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.644208200" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1907231332" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="gnu.cpp.compiler.option.preprocessor.def.959275134" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.604467026" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1073903870" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.898376794" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1560070168" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
||||
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
|
||||
</inputType>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.1462690215" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
||||
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.40469999" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
||||
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.798539361" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
</toolChain>
|
||||
|
||||
</folderInfo>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
@@ -19,14 +389,190 @@
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.pathentry">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.pathentry"/>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<pathentry excluding="**/CMakeFiles/**" kind="out" path="build"/>
|
||||
<project id="squeezelite-esp32-merge.null.1711307563" name="squeezelite-esp32-merge"/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
<storageModule moduleId="refreshScope" versionNumber="2">
|
||||
|
||||
<configuration configurationName="squeezelite_windows">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/squeezelite-esp32-merge"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
<configuration configurationName="recovery_windows">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/squeezelite-esp32"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
<configuration configurationName="recovery">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/squeezelite-esp32"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
<configuration configurationName="Default">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/squeezelite-esp32"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
|
||||
|
||||
<buildTargets>
|
||||
|
||||
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
|
||||
<buildCommand>make</buildCommand>
|
||||
|
||||
<buildArguments>-j8 EXTRA_CPPFLAGS="-DRECOVERY_APPLICATION=1"</buildArguments>
|
||||
|
||||
<buildTarget>all</buildTarget>
|
||||
|
||||
<stopOnError>true</stopOnError>
|
||||
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
|
||||
</target>
|
||||
|
||||
<target name="app" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
|
||||
<buildCommand>make</buildCommand>
|
||||
|
||||
<buildArguments>-j8 EXTRA_CPPFLAGS="-DRECOVERY_APPLICATION=1"</buildArguments>
|
||||
|
||||
<buildTarget>app</buildTarget>
|
||||
|
||||
<stopOnError>true</stopOnError>
|
||||
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
|
||||
</target>
|
||||
|
||||
<target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
|
||||
<buildCommand>make</buildCommand>
|
||||
|
||||
<buildArguments>-j8 EXTRA_CPPFLAGS="-DRECOVERY_APPLICATION=1"</buildArguments>
|
||||
|
||||
<buildTarget>clean</buildTarget>
|
||||
|
||||
<stopOnError>true</stopOnError>
|
||||
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
|
||||
</target>
|
||||
|
||||
</buildTargets>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cygwin.base.58932738;cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.1067614858;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1865841553;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.1383814557">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934;cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934.;cdt.managedbuild.tool.gnu.cross.cpp.compiler.40066190;cdt.managedbuild.tool.gnu.cpp.compiler.input.773825889">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736;cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736.;cdt.managedbuild.tool.gnu.cross.cpp.compiler.1907231332;cdt.managedbuild.tool.gnu.cpp.compiler.input.604467026">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291;cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.;cdt.managedbuild.tool.gnu.cross.cpp.compiler.1722031516;cdt.managedbuild.tool.gnu.cpp.compiler.input.2073997022">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291;cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.;cdt.managedbuild.tool.gnu.cross.c.compiler.1302011176;cdt.managedbuild.tool.gnu.c.compiler.input.539301587">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cygwin.base.58932738;cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.1067614858;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.410547198;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.1499974240">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736;cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736.;cdt.managedbuild.tool.gnu.cross.c.compiler.824219909;cdt.managedbuild.tool.gnu.c.compiler.input.644208200">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707;cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707.;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.211315976;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.857914729">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1943329896;cdt.managedbuild.toolchain.gnu.cross.base.1943329896.30011915;cdt.managedbuild.tool.gnu.cross.cpp.compiler.1749746745;cdt.managedbuild.tool.gnu.cpp.compiler.input.1914005798">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1476804786;cdt.managedbuild.toolchain.gnu.cross.base.1476804786.1800826258;cdt.managedbuild.tool.gnu.cross.cpp.compiler.254690821;cdt.managedbuild.tool.gnu.cpp.compiler.input.1365876654">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1943329896;cdt.managedbuild.toolchain.gnu.cross.base.1943329896.30011915;cdt.managedbuild.tool.gnu.cross.c.compiler.2083405506;cdt.managedbuild.tool.gnu.c.compiler.input.404320567">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707;cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707.;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.145410566;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.1181636367">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1476804786;cdt.managedbuild.toolchain.gnu.cross.base.1476804786.1800826258;cdt.managedbuild.tool.gnu.cross.c.compiler.1502936757;cdt.managedbuild.tool.gnu.c.compiler.input.1614739014">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934;cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934.;cdt.managedbuild.tool.gnu.cross.c.compiler.1397900624;cdt.managedbuild.tool.gnu.c.compiler.input.24917724">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</scannerConfigBuildInfo>
|
||||
|
||||
</storageModule>
|
||||
|
||||
</cproject>
|
||||
|
||||
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,5 +1,5 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
# * text=auto
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
|
||||
90
.github/ISSUE_TEMPLATE/bug_report.md
vendored
90
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,90 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: How to Submit an Issue for the squeezelite-esp32 Project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
To help us resolve your issue as quickly as possible, please follow these guidelines when submitting an issue. Providing all the necessary information will save both your time and ours.
|
||||
|
||||
### Describe the bug
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
### Preliminary Information
|
||||
|
||||
1. **Firmware Version**: Specify the version of the firmware you are using.
|
||||
2. **Plugin Version**: Mention the version of the plugin installed on your LMS (Logitech Media Server).
|
||||
|
||||
### Hardware Details
|
||||
|
||||
Please describe your hardware setup:
|
||||
|
||||
- **ESP32 Module**: For example, ESP32 WROVER, ESP32-S3, etc.
|
||||
- **Board Type**: If applicable, e.g., ESP32 audio kit, etc.
|
||||
- **DAC Chip**: Specify the DAC chip you are using.
|
||||
- **Additional Hardware**: Include details about any other hardware like rotary controls, buttons, screens (SPI, I2C), Ethernet, IO expansion, etc.
|
||||
|
||||
### NVS Settings
|
||||
|
||||
Follow these steps to share your NVS settings:
|
||||
|
||||
1. Open the web UI of your device.
|
||||
2. Click on the "Credit" tab.
|
||||
3. Enable the "Show NVS Editor" checkbox. This allows you to view or change the NVS configuration even when not in recovery mode.
|
||||
4. Navigate to the "NVS Editor" tab.
|
||||
5. Scroll to the bottom and click "Download Config".
|
||||
6. Share the downloaded content here.
|
||||
|
||||
<details>
|
||||
<pre><code>
|
||||
Your log content here
|
||||
</code></pre>
|
||||
</details>
|
||||
|
||||
|
||||
### Logs
|
||||
|
||||
To share logs:
|
||||
|
||||
1. Connect your player to a computer using a USB cable. Use a built-in Serial-USB adapter if your player has one, or an external USB adapter otherwise.
|
||||
2. Go to the [web installer](https://sle118.github.io/squeezelite-esp32-installer/).
|
||||
3. Click "Connect to Device".
|
||||
4. Select the appropriate serial port.
|
||||
5. Click "Logs And Console".
|
||||
6. Download the logs and share them here. Please remove any sensitive information like Wi-Fi passwords or MAC addresses.
|
||||
- **If the problem occurs soon after booting**: Share the full log until the issue occurs.
|
||||
- **If the problem occurs later during playback**: Trim the logs to include information just before and after the problem occurs.
|
||||
|
||||
#### Example Log
|
||||
|
||||
Here's an example log for reference. Make sure to obfuscate sensitive information like Wi-Fi passwords, MAC addresses, and change IP addresses to something more generic.
|
||||
|
||||
<details>
|
||||
<pre><code>
|
||||
=== START OF LOG ===
|
||||
Example of log from the console
|
||||
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
|
||||
configsip: 0, SPIWP:0xee
|
||||
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
|
||||
mode:DIO, clock div:1
|
||||
...
|
||||
I (1041) cpu_start: Application information:
|
||||
I (1044) cpu_start: Project name: Squeezelite-ESP32
|
||||
I (1050) cpu_start: App version: I2S-4MFlash-1336
|
||||
I (1055) cpu_start: Compile time: Aug 12 2023 01:20:18
|
||||
I (1062) cpu_start: ELF file SHA256: 34241d6e99fd1d6b...
|
||||
I (1068) cpu_start: ESP-IDF: v4.3.5-dirty
|
||||
...
|
||||
I (1133) heap_init: At 40094A8C len 0000B574 (45 KiB): IRAM
|
||||
I (1139) spiram: Adding pool of 4066K of external SPI memory to heap allocator
|
||||
=== END OF LOG ===
|
||||
</code></pre>
|
||||
</details>
|
||||
|
||||
### Issue Description
|
||||
|
||||
1. **Observed Behavior**: Describe what you think is wrong.
|
||||
2. **Expected Behavior**: Describe what you expect should happen.
|
||||
3. **Steps to Reproduce**: Provide a step-by-step guide on how to replicate the issue.
|
||||
162
.github/workflows/CrossBuild.yml
vendored
162
.github/workflows/CrossBuild.yml
vendored
@@ -1,162 +0,0 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
name: Cross-Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master-cmake'
|
||||
- '!**4.3'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master-cmake'
|
||||
- '!**4.3'
|
||||
jobs:
|
||||
job1:
|
||||
name: Build Number
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
build_number: ${{ steps.buildnumber.outputs.build_number }}
|
||||
steps:
|
||||
- name: Generate common build number
|
||||
id: buildnumber
|
||||
uses: einaregilsson/build-number@v3
|
||||
with:
|
||||
token: ${{secrets.github_token}}
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: job1
|
||||
strategy:
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
node: [I2S-4MFlash, SqueezeAmp, Muse]
|
||||
depth: [16, 32]
|
||||
exclude:
|
||||
- node: Muse
|
||||
depth: 32
|
||||
steps:
|
||||
- name: Set target name
|
||||
run: |
|
||||
echo "TARGET_BUILD_NAME=${{ matrix.node }}" >> $GITHUB_ENV
|
||||
echo "build_version_prefix=1." >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 15
|
||||
submodules: true
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
build
|
||||
/var/lib/docker
|
||||
key: ${{ runner.os }}-${{ matrix.node }}-${{ matrix.depth }}
|
||||
- name: Set build parameters
|
||||
run: |
|
||||
git update-index --chmod=+x ./server_certs/getcert.sh
|
||||
cd server_certs;./getcert.sh;cat github.pem;cd ..
|
||||
shopt -s nocasematch
|
||||
branch_name="${GITHUB_REF//refs\/heads\//}"
|
||||
branch_name="${branch_name//[^a-zA-Z0-9\-~!@_\.]/}"
|
||||
BUILD_NUMBER=${{ needs.job1.outputs.build_number }}
|
||||
echo "BUILD_NUMBER=${BUILD_NUMBER}" >> $GITHUB_ENV
|
||||
tag="${TARGET_BUILD_NAME}.${{matrix.depth}}.${BUILD_NUMBER}.${branch_name}"
|
||||
echo "tag=${tag}" >> $GITHUB_ENV
|
||||
last_commit="$(git log --pretty=format:'%s' --max-count=1)"
|
||||
if [[ "$last_commit" =~ .*"Release".* ]]; then echo "release_flag=1" >> $GITHUB_ENV; else echo "release_flag=0" >> $GITHUB_ENV; fi
|
||||
name="1.${BUILD_NUMBER}-${{matrix.depth}}#v4.0#${TARGET_BUILD_NAME}#${branch_name}"
|
||||
artifact_prefix="squeezelite-esp32-${branch_name}-${TARGET_BUILD_NAME}-${{matrix.depth}}-${build_version_prefix}${BUILD_NUMBER}"
|
||||
artifact_file_name="${artifact_prefix}.zip"
|
||||
artifact_bin_file_name="${artifact_prefix}.bin"
|
||||
echo "name=${name}" >> $GITHUB_ENV
|
||||
echo "last_commit=${last_commit}" >> $GITHUB_ENV
|
||||
echo "artifact_file_name=${artifact_file_name}" >> $GITHUB_ENV
|
||||
echo "PROJECT_VER=${TARGET_BUILD_NAME}-${{ steps.buildnumber.outputs.build_number }} " >> $GITHUB_ENV
|
||||
echo "artifact_bin_file_name=${artifact_bin_file_name}" >> $GITHUB_ENV
|
||||
description=""
|
||||
description=${description}$'------------------------------\n### Revision Log\n\n'
|
||||
description="$description$(git log --pretty=format:'%h %s (%cI) <%an>' --abbrev-commit --max-count=15 | sed --r 's/(^[\*]+)/\\\1/g') "
|
||||
echo 'description<<~EOD' >> $GITHUB_ENV
|
||||
echo ${description}>> $GITHUB_ENV
|
||||
echo '~EOD' >> $GITHUB_ENV
|
||||
echo #######
|
||||
echo ####### Environment
|
||||
echo #######
|
||||
env
|
||||
echo #######
|
||||
echo ####### GITHUB ENV
|
||||
echo #######
|
||||
cat $GITHUB_ENV
|
||||
- name: Build the firmware
|
||||
run: |
|
||||
env | grep "artifact\|tag\|GITHUB\|version\|NUMBER\|TARGET" >${TARGET_BUILD_NAME}-env.txt
|
||||
echo "${tag}" >version.txt
|
||||
docker pull sle118/idf:release-v4.0
|
||||
docker info
|
||||
docker run --env-file=${TARGET_BUILD_NAME}-env.txt -v $PWD:/project -w /project sle118/idf:release-v4.0 /bin/bash -c "cp build-scripts/${TARGET_BUILD_NAME}-sdkconfig.defaults sdkconfig && idf.py build -DDEPTH=${{ matrix.depth }} -DBUILD_NUMBER=${BUILD_NUMBER}-${{ matrix.depth }} && zip -r build_output.zip build && zip build/${artifact_file_name} partitions*.csv build/*.bin build/bootloader/bootloader.bin build/partition_table/partition-table.bin build/flash_project_args build/size_*.txt"
|
||||
# - name: Build Mock firmware
|
||||
# run: |
|
||||
# mkdir -p build
|
||||
# cd build
|
||||
# mkdir -p partition_table
|
||||
# mkdir -p bootloader
|
||||
# echo "mock content"> squeezelite.bin
|
||||
# echo "mock content"> recovery.bin
|
||||
# echo "mock content"> ./bootloader/bootloader.bin
|
||||
# echo "mock content"> ./partition_table/partition-table.bin
|
||||
# echo "mock content"> flash_project_args
|
||||
# echo "mock content"> size_comp1.txt
|
||||
# echo "mock content"> size_comp2.txt
|
||||
# echo "mock content"> ../partitions.csv
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ env.artifact_file_name }}
|
||||
path: |
|
||||
build/*.bin
|
||||
build/bootloader/bootloader.bin
|
||||
build/partition_table/partition-table.bin
|
||||
build/flash_project_args
|
||||
build/size_comp1.txt
|
||||
build/size_comp2.txt
|
||||
partitions.csv
|
||||
sdkconfig
|
||||
server_certs/github.pem
|
||||
build_output.zip
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ env.artifact_bin_file_name }}
|
||||
path: |
|
||||
build/squeezelite.bin
|
||||
- name: Create Release
|
||||
if: env.release_flag == 1
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
|
||||
with:
|
||||
tag_name: ${{ env.tag }}
|
||||
release_name: ${{ env.name }}
|
||||
body: ${{ env.description }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
- name: Upload Release Asset - Squeezelite binary file
|
||||
if: env.release_flag == 1
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: build/squeezelite.bin
|
||||
asset_name: ${{ env.artifact_bin_file_name }}
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Upload Release Asset - Zip file
|
||||
if: env.release_flag == 1
|
||||
id: upload-release-asset-zip
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: build/${{ env.artifact_file_name }}
|
||||
asset_name: ${{ env.artifact_file_name }}
|
||||
asset_content_type: application/octet-stream
|
||||
229
.github/workflows/Platform_build.yml
vendored
229
.github/workflows/Platform_build.yml
vendored
@@ -1,229 +0,0 @@
|
||||
name: Platform Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**4.3'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ui_build:
|
||||
description: 'Force Rebuilding the UI. When not forced, the system will check for [ui-build] in the last commit message to trigger a ui rebuild'
|
||||
required: true
|
||||
type: boolean
|
||||
release_build:
|
||||
description: 'Force a Release build. When not forced, the system will check for release word in the last commit message to trigger a release'
|
||||
required: true
|
||||
type: boolean
|
||||
jobs:
|
||||
bootstrap:
|
||||
name: Global setup
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: sle118/squeezelite-esp32-idfv435
|
||||
outputs:
|
||||
build_number: ${{ steps.buildnumber.outputs.build_number }}
|
||||
ui_build: ${{ steps.build_flags.outputs.ui_build }}
|
||||
release_flag: ${{ steps.build_flags.outputs.release_flag }}
|
||||
mock: ${{ steps.build_flags.outputs.mock }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Generate common build number
|
||||
id: buildnumber
|
||||
uses: einaregilsson/build-number@v3
|
||||
with:
|
||||
token: ${{secrets.github_token}}
|
||||
|
||||
- name: Set build flags
|
||||
id: build_flags
|
||||
run: |
|
||||
git config --global --add safe.directory /__w/squeezelite-esp32/squeezelite-esp32
|
||||
[ ${{github.event.inputs.ui_build}} ] && ui_build_option="--ui_build" || ui_build_option=""
|
||||
[ ${{github.event.inputs.release_build}} ] && release_build_option="--force" || release_build_option=""
|
||||
echo "ui_build_option=$ui_build_option" >> "$GITHUB_OUTPUT"
|
||||
echo "release_build_option=$release_build_option" >> "$GITHUB_OUTPUT"
|
||||
echo "Dumping environment"
|
||||
env
|
||||
. /opt/esp/python_env/idf4.3_py3.8_env/bin/activate
|
||||
# build_flags support the following options
|
||||
# --mock - to mock the compilation part - this is to be used for testing only
|
||||
# --force - to force a release build even if the last commit message doesn't contain the word "release"
|
||||
# --ui_build - to force a ui_build even if the last commit message doesn't contain "[ui-build]"
|
||||
build_tools.py build_flags $ui_build_option $release_build_option
|
||||
- name: Show Build Flags
|
||||
run: |
|
||||
echo "Running with the following options"
|
||||
echo "Web Build Flag=${{steps.build_flags.outputs.ui_build}}"
|
||||
echo "Mock flag=${{steps.build_flags.outputs.mock}}"
|
||||
echo "Release Flag=${{steps.build_flags.outputs.release_flag}}"
|
||||
- name: Refresh certificates
|
||||
if: ${{ steps.build_flags.outputs.release_flag }}
|
||||
run: |
|
||||
git update-index --chmod=+x ./server_certs/getcert.sh
|
||||
cd server_certs;./getcert.sh;cat github.pem;cd ..
|
||||
- name: Setup Node.js dependencies
|
||||
if: ${{ !env.ACT }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: 'npm'
|
||||
cache-dependency-path: components/wifi-manager/webapp/package.json
|
||||
- name: Build Web Application
|
||||
if: ${{ steps.build_flags.outputs.ui_build == 1 }}
|
||||
run: |
|
||||
cd components/wifi-manager/webapp/
|
||||
npm install
|
||||
npm run-script build
|
||||
- name: Update repository with prebuilt items
|
||||
if: ${{ steps.build_flags.outputs.ui_build == 1 || steps.build_flags.outputs.release_flag == 1 }}
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
git add server_certs
|
||||
git add components/wifi-manager/webapp/*.h
|
||||
git add components/wifi-manager/webapp/*.c
|
||||
git add components/wifi-manager/webapp/*.cmake
|
||||
git add components/wifi-manager/webapp/dist/*
|
||||
git commit -m "Update prebuilt objects [skip actions]"
|
||||
git push https://${{secrets.github_token}}@github.com/sle118/squeezelite-esp32.git
|
||||
- name: Locally store commonly built objects
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: prebuilt_objects
|
||||
path: |
|
||||
server_certs
|
||||
components/wifi-manager/webapp/*.h
|
||||
components/wifi-manager/webapp/*.c
|
||||
components/wifi-manager/webapp/dist/*
|
||||
components/wifi-manager/webapp/*.cmake
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: sle118/squeezelite-esp32-idfv435
|
||||
needs: [bootstrap]
|
||||
strategy:
|
||||
matrix:
|
||||
node: [I2S-4MFlash, SqueezeAmp, Muse]
|
||||
depth: [16, 32]
|
||||
exclude:
|
||||
- node: Muse
|
||||
depth: 32
|
||||
- node: bootstrap
|
||||
depth: 32
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Show Build Flags
|
||||
run: |
|
||||
echo "Running with the following options"
|
||||
echo "Web Build Flag=${{needs.bootstrap.outputs.ui_build}}"
|
||||
echo "Mock flag=${{needs.bootstrap.outputs.mock}}"
|
||||
echo "Release Flag=${{needs.bootstrap.outputs.release_flag}}"
|
||||
echo Environment File name: $GITHUB_ENV
|
||||
- name: Set build parameters
|
||||
run: |
|
||||
. /opt/esp/python_env/idf4.3_py3.8_env/bin/activate
|
||||
git config --global --add safe.directory /__w/squeezelite-esp32/squeezelite-esp32
|
||||
git status
|
||||
build_tools.py environment --build ${{ needs.bootstrap.outputs.build_number }} --env_file "$GITHUB_ENV" --node "${{matrix.node}}" --depth ${{matrix.depth}} --major 2 --docker sle118/squeezelite-esp32-idfv435
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Restore common objects
|
||||
with:
|
||||
name: prebuilt_objects
|
||||
- name: Build the firmware
|
||||
if: ${{ needs.bootstrap.outputs.mock == 0 }}
|
||||
run: |
|
||||
. ${IDF_PYTHON_ENV_PATH}/bin/activate
|
||||
echo "Copying target sdkconfig"
|
||||
cp build-scripts/${TARGET_BUILD_NAME}-sdkconfig.defaults sdkconfig
|
||||
echo "Building project"
|
||||
idf.py build -DDEPTH=${DEPTH} -DBUILD_NUMBER=${BUILD_NUMBER}-${DEPTH}
|
||||
- name: Build Mock firmware
|
||||
if: ${{ needs.bootstrap.outputs.mock == 1 }}
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
mkdir -p partition_table
|
||||
mkdir -p bootloader
|
||||
echo \\"mock content\\"> ./squeezelite.bin
|
||||
echo \"mock content\"> ./recovery.bin
|
||||
echo \"mock content\"> ./bootloader/bootloader.bin
|
||||
echo \"mock content\"> ./partition_table/partition-table.bin
|
||||
echo \"mock content\"> ./ota_data_initial.bin
|
||||
echo \"mock content\"> ./flash_project_args
|
||||
echo \"mock content\"> ./size_comp1.txt
|
||||
echo \"mock content\"> ./size_comp2.txt
|
||||
echo \"mock content\"> ./partitions.csv
|
||||
echo { \"write_flash_args\" : [ \"--flash_mode\", \"dio\", \"--flash_size\", \"detect\", \"--flash_freq\", \"80m\" ], \"flash_settings\" : { \"flash_mode\": \"dio\", \"flash_size\": \"detect\", \"flash_freq\": \"80m\" }, \"flash_files\" : { \"0x8000\" : \"partition_table/partition-table.bin\", \"0xd000\" : \"ota_data_initial.bin\", \"0x1000\" : \"bootloader/bootloader.bin\", \"0x10000\" : \"recovery.bin\", \"0x150000\" : \"squeezelite.bin\" }, \"partition_table\" : { \"offset\" : \"0x8000\", \"file\" : \"partition_table/partition-table.bin\" }, \"otadata\" : { \"offset\" : \"0xd000\", \"file\" : \"ota_data_initial.bin\" }, \"bootloader\" : { \"offset\" : \"0x1000\", \"file\" : \"bootloader/bootloader.bin\" }, \"app\" : { \"offset\" : \"0x10000\", \"file\" : \"recovery.bin\" }, \"squeezelite\" : { \"offset\" : \"0x150000\", \"file\" : \"squeezelite.bin\" }, \"extra_esptool_args\" : { \"after\" : \"hard_reset\", \"before\" : \"default_reset\" } } > ./flasher_args.json
|
||||
- name: Create Release Artifact Zip
|
||||
if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
|
||||
run: |
|
||||
if [ -z "${artifact_file_name}" ]
|
||||
then
|
||||
echo "No artifact file name set. Will not generate zip file."
|
||||
else
|
||||
echo "Generating build artifact zip file"
|
||||
zip -r build_output.zip build
|
||||
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@v4
|
||||
if: ${{ needs.bootstrap.outputs.mock == 0 }}
|
||||
with:
|
||||
name: ${{ env.artifact_prefix }}
|
||||
path: |
|
||||
build/flash_project_args
|
||||
build/size_comp1.txt
|
||||
build/size_comp2.txt
|
||||
partitions.csv
|
||||
sdkconfig
|
||||
server_certs/github.pem
|
||||
build/*.bin
|
||||
build/bootloader/bootloader.bin
|
||||
build/partition_table/partition-table.bin
|
||||
build_output.zip
|
||||
- name: Create Release
|
||||
if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
|
||||
with:
|
||||
tag_name: ${{ env.tag }}
|
||||
release_name: ${{ env.name }}
|
||||
body: ${{ env.description }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
- name: Upload Release Asset - Squeezelite binary file
|
||||
if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: build/squeezelite.bin
|
||||
asset_name: ${{ env.artifact_bin_file_name }}
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Upload Release Asset - Zip file
|
||||
if: ${{ needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
|
||||
id: upload-release-asset-zip
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: build/${{ env.artifact_file_name }}
|
||||
asset_name: ${{ env.artifact_file_name }}
|
||||
asset_content_type: application/octet-stream
|
||||
update_web_installer:
|
||||
name: Update Web Installer After Release
|
||||
needs: [ bootstrap, build ]
|
||||
if: ${{ always() && !cancelled() && needs.bootstrap.outputs.release_flag == 1 && needs.bootstrap.outputs.mock == 0 }}
|
||||
uses: ./.github/workflows/web_deploy.yml
|
||||
secrets:
|
||||
WEB_INSTALLER: ${{ secrets.WEB_INSTALLER }}
|
||||
75
.github/workflows/codeql-analysis.yml
vendored
75
.github/workflows/codeql-analysis.yml
vendored
@@ -1,75 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master-cmake ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master-cmake ]
|
||||
schedule:
|
||||
- cron: '19 12 * * 4'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp', 'javascript', 'python']
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
# Exclude specific artifacts from analysis
|
||||
- name: Exclude Artifacts
|
||||
run: |
|
||||
# Exclude components/wifi-manager/webapp/dist/js/index* from analysis
|
||||
echo 'components/wifi-manager/webapp/dist/js/index*' >> .codeql-exclude-paths
|
||||
echo 'components/wifi-manager/webapp/dist/js/index*' >> .codeql-exclude-paths.txt
|
||||
echo 'components/wifi-manager/webapp/dist/index*' >> .codeql-exclude-paths
|
||||
echo 'components/wifi-manager/webapp/dist/index*' >> .codeql-exclude-paths.txt
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
167
.github/workflows/esp-idf-v4.3-build.yml
vendored
167
.github/workflows/esp-idf-v4.3-build.yml
vendored
@@ -1,167 +0,0 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
name: ESP-IDF v4.3.1
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**4.3'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**4.3'
|
||||
jobs:
|
||||
job1:
|
||||
name: Build Number
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
build_number: ${{ steps.buildnumber.outputs.build_number }}
|
||||
steps:
|
||||
- name: Generate common build number
|
||||
id: buildnumber
|
||||
uses: einaregilsson/build-number@v3
|
||||
with:
|
||||
token: ${{secrets.github_token}}
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: job1
|
||||
strategy:
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
node: [I2S-4MFlash, SqueezeAmp, Muse]
|
||||
depth: [16, 32]
|
||||
exclude:
|
||||
- node: Muse
|
||||
depth: 32
|
||||
steps:
|
||||
- name: Set target name
|
||||
run: |
|
||||
echo "TARGET_BUILD_NAME=${{ matrix.node }}" >> $GITHUB_ENV
|
||||
echo "build_version_prefix=2." >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 15
|
||||
submodules: true
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/build
|
||||
./
|
||||
key: ${{ runner.os }}-${{ matrix.node }}
|
||||
- name: Set build parameters
|
||||
run: |
|
||||
git update-index --chmod=+x ./server_certs/getcert.sh
|
||||
git update-index --chmod=+x ./buildFirmware.sh
|
||||
git update-index --chmod=+x ./components/spotify/cspot/bell/external/nanopb/generator/protoc
|
||||
git update-index --chmod=+x ./components/spotify/cspot/bell/external/nanopb/generator/protoc-gen-nanopb
|
||||
git update-index --chmod=+x ./components/spotify/cspot/bell/external/nanopb/generator/*.py
|
||||
git update-index --chmod=+x ./components/spotify/cspot/bell/external/nanopb/generator/*.py2
|
||||
git update-index --chmod=+x ./components/spotify/cspot/bell/external/nanopb/generator/proto/*.py
|
||||
|
||||
|
||||
cd server_certs;./getcert.sh;cat github.pem;cd ..
|
||||
shopt -s nocasematch
|
||||
branch_name="${GITHUB_REF//refs\/heads\//}"
|
||||
branch_name="${branch_name//[^a-zA-Z0-9\-~!@_\.]/}"
|
||||
BUILD_NUMBER=${{ needs.job1.outputs.build_number }}
|
||||
echo "BUILD_NUMBER=${BUILD_NUMBER}" >> $GITHUB_ENV
|
||||
echo "DOCKER_IMAGE_NAME=sle118/squeezelite-esp32-idfv4-master" >> $GITHUB_ENV
|
||||
tag="${TARGET_BUILD_NAME}.${{matrix.depth}}.${build_version_prefix}${BUILD_NUMBER}.${branch_name}"
|
||||
echo "tag=${tag}" >> $GITHUB_ENV
|
||||
last_commit="$(git log --pretty=format:'%s' --max-count=1)"
|
||||
if [[ "$last_commit" =~ .*"Release".* ]]; then echo "release_flag=1" >> $GITHUB_ENV; else echo "release_flag=0" >> $GITHUB_ENV; fi
|
||||
name="${build_version_prefix}${BUILD_NUMBER}-${{matrix.depth}}#v4.0#${TARGET_BUILD_NAME}#${branch_name}"
|
||||
artifact_prefix="squeezelite-esp32-${branch_name}-${TARGET_BUILD_NAME}-${{matrix.depth}}-${build_version_prefix}${BUILD_NUMBER}"
|
||||
artifact_file_name="${artifact_prefix}.zip"
|
||||
artifact_bin_file_name="${artifact_prefix}.bin"
|
||||
echo "name=${name}" >> $GITHUB_ENV
|
||||
echo "last_commit=${last_commit}" >> $GITHUB_ENV
|
||||
echo "artifact_file_name=${artifact_file_name}" >> $GITHUB_ENV
|
||||
echo "PROJECT_VER=${TARGET_BUILD_NAME}-${{ steps.buildnumber.outputs.build_number }} " >> $GITHUB_ENV
|
||||
echo "artifact_bin_file_name=${artifact_bin_file_name}" >> $GITHUB_ENV
|
||||
description=$'### Revision Log\n'
|
||||
githist="$(git log --pretty=format:'%h %s (%cI) <%an>' --abbrev-commit --max-count=15 | sed --r 's/(^[\*]+)/\\\1/g')"
|
||||
description="$description$githist"
|
||||
echo 'description<<~EOD' >> $GITHUB_ENV
|
||||
echo ${description}>> $GITHUB_ENV
|
||||
echo '~EOD' >> $GITHUB_ENV
|
||||
echo #######
|
||||
echo ####### Environment
|
||||
echo #######
|
||||
env
|
||||
echo #######
|
||||
echo ####### GITHUB ENV
|
||||
echo #######
|
||||
cat $GITHUB_ENV
|
||||
- name: Build the firmware
|
||||
run: |
|
||||
env | grep "artifact\|tag\|GITHUB\|version\|NUMBER\|TARGET" >${TARGET_BUILD_NAME}-env.txt
|
||||
echo pulling custom docker image ${DOCKER_IMAGE_NAME}
|
||||
docker pull ${DOCKER_IMAGE_NAME}
|
||||
docker run --env-file=${TARGET_BUILD_NAME}-env.txt -v $PWD:/project -w /project ${DOCKER_IMAGE_NAME} /bin/bash -c "./buildFirmware.sh"
|
||||
# - name: Build Mock firmware
|
||||
# run: |
|
||||
# mkdir -p build
|
||||
# cd build
|
||||
# mkdir -p partition_table
|
||||
# mkdir -p bootloader
|
||||
# echo "mock content"> squeezelite.bin
|
||||
# echo "mock content"> recovery.bin
|
||||
# echo "mock content"> ./bootloader/bootloader.bin
|
||||
# echo "mock content"> ./partition_table/partition-table.bin
|
||||
# echo "mock content"> flash_project_args
|
||||
# echo "mock content"> size_comp1.txt
|
||||
# echo "mock content"> size_comp2.txt
|
||||
# echo "mock content"> ../partitions.csv
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ env.artifact_file_name }}
|
||||
path: |
|
||||
build/*.bin
|
||||
build/bootloader/bootloader.bin
|
||||
build/partition_table/partition-table.bin
|
||||
build/flash_project_args
|
||||
build/size_comp1.txt
|
||||
build/size_comp2.txt
|
||||
partitions.csv
|
||||
sdkconfig
|
||||
server_certs/github.pem
|
||||
build_output.zip
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ env.artifact_bin_file_name }}
|
||||
path: |
|
||||
build/squeezelite.bin
|
||||
- name: Create Release
|
||||
if: env.release_flag == 1
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
|
||||
with:
|
||||
tag_name: ${{ env.tag }}
|
||||
release_name: ${{ env.name }}
|
||||
body: ${{ env.description }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
- name: Upload Release Asset - Squeezelite binary file
|
||||
if: env.release_flag == 1
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: build/squeezelite.bin
|
||||
asset_name: ${{ env.artifact_bin_file_name }}
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Upload Release Asset - Zip file
|
||||
if: env.release_flag == 1
|
||||
id: upload-release-asset-zip
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: build/${{ env.artifact_file_name }}
|
||||
asset_name: ${{ env.artifact_file_name }}
|
||||
asset_content_type: application/octet-stream
|
||||
26
.github/workflows/web_deploy.yml
vendored
26
.github/workflows/web_deploy.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: Update Web Installer
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
WEB_INSTALLER:
|
||||
required: true
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
update_web_installer:
|
||||
name: Update Web Installer After Release
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: sle118/squeezelite-esp32-idfv43
|
||||
env:
|
||||
WEB_INSTALLER: ${{ secrets.WEB_INSTALLER }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Update Web Installer Project
|
||||
run: |
|
||||
. /opt/esp/python_env/idf4.3_py3.8_env/bin/activate
|
||||
git config --global --add safe.directory /__w/squeezelite-esp32/squeezelite-esp32
|
||||
build_tools.py manifest --flash_file "/build/flash_project_args" --outdir "./bin_files" --manif_name "manifest" --max_count 3
|
||||
build_tools.py pushinstaller --source "./bin_files" --manif_name "manifest" --target "web-installer" --url "https://github.com/sle118/squeezelite-esp32-installer.git" --artifacts "docs/artifacts" --web_installer_branch "main" --token "${{env.WEB_INSTALLER}}"
|
||||
87
.gitignore
vendored
87
.gitignore
vendored
@@ -1,20 +1,69 @@
|
||||
build/
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/settings.json
|
||||
.vscode/tasks.json
|
||||
alltags.txt
|
||||
components/wifi-manager/network_manager_handlers.multi
|
||||
esp32.code-workspace
|
||||
sdkconfig.old
|
||||
test/.vscode/c_cpp_properties.json
|
||||
test/.vscode/launch.json
|
||||
test/.vscode/settings.json
|
||||
test/.vscode/tasks.json
|
||||
test/sdkconfig
|
||||
components/wifi-manager/UML-State-Machine-in-C
|
||||
*.bak
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
envfile.txt
|
||||
artifacts
|
||||
web-installer
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Build files with potential private info
|
||||
build/
|
||||
sdkconfig.old
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
|
||||
# Windows
|
||||
# =========================
|
||||
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
*.save
|
||||
libs/
|
||||
|
||||
/cdump.cmd
|
||||
/_*
|
||||
sdkconfig
|
||||
squeezelite-esp32-jsonblob.zip
|
||||
|
||||
12
.gitmodules
vendored
12
.gitmodules
vendored
@@ -2,12 +2,6 @@
|
||||
path = components/telnet/libtelnet
|
||||
url = https://github.com/seanmiddleditch/libtelnet
|
||||
branch = develop
|
||||
[submodule "components/esp-dsp"]
|
||||
path = components/esp-dsp
|
||||
url = https://github.com/philippe44/esp-dsp.git
|
||||
[submodule "components/wifi-manager/UML-State-Machine-in-C"]
|
||||
path = components/wifi-manager/UML-State-Machine-in-C
|
||||
url = https://github.com/kiishor/UML-State-Machine-in-C
|
||||
[submodule "components/wifi-manager/webapp/src/bootswatch"]
|
||||
path = components/wifi-manager/webapp/src/bootswatch
|
||||
url = https://github.com/thomaspark/bootswatch.git
|
||||
[submodule "esp-dsp"]
|
||||
path = esp-dsp
|
||||
url = https://github.com/philippe44/esp-dsp
|
||||
|
||||
16
.project
16
.project
@@ -1,20 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>squeezelite-esp32-idfv4</name>
|
||||
<name>squeezelite-esp32</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
<project>esp-idf</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.core.cBuilder</name>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
||||
<nature>com.espressif.idf.core.idfNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
</projectDescription>
|
||||
|
||||
1
.settings/.gitignore
vendored
Normal file
1
.settings/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/org.eclipse.ltk.core.refactoring.prefs
|
||||
100
.settings/language.settings.xml
Normal file
100
.settings/language.settings.xml
Normal file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project>
|
||||
|
||||
<configuration id="cdt.managedbuild.toolchain.gnu.cross.base.293933348" name="Default">
|
||||
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
|
||||
|
||||
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="66711578333" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
|
||||
</provider>
|
||||
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
|
||||
</extension>
|
||||
|
||||
</configuration>
|
||||
|
||||
<configuration id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934" name="recovery">
|
||||
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser" keep-relative-paths="true" name="CDT GCC Build Output Parser" parameter="xtensa-esp32-elf-(gcc|g\+\+|c\+\+|cc|cpp|clang)" prefer-non-shared="true"/>
|
||||
|
||||
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="29929057949" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="xtensa-esp32-elf-gcc ${FLAGS} -std=c++11 -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
|
||||
</provider>
|
||||
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
|
||||
</extension>
|
||||
|
||||
</configuration>
|
||||
|
||||
<configuration id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291" name="recovery_windows">
|
||||
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser" keep-relative-paths="false" name="CDT GCC Build Output Parser" parameter="(g?cc)|([gc]\+\+)|(clang)" prefer-non-shared="true"/>
|
||||
|
||||
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="1502478736382965477" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
|
||||
</provider>
|
||||
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
|
||||
</extension>
|
||||
|
||||
</configuration>
|
||||
|
||||
<configuration id="cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736" name="squeezelite_windows">
|
||||
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser" keep-relative-paths="true" name="CDT GCC Build Output Parser" parameter="xtensa-esp32-elf-(gcc|g\+\+|c\+\+|cc|cpp|clang)" prefer-non-shared="true"/>
|
||||
|
||||
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-1766868238676867652" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="xtensa-esp32-elf-gcc ${FLAGS} -std=c++11 -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
|
||||
</provider>
|
||||
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
|
||||
</extension>
|
||||
|
||||
</configuration>
|
||||
|
||||
</project>
|
||||
116
.settings/org.eclipse.cdt.core.prefs
Normal file
116
.settings/org.eclipse.cdt.core.prefs
Normal file
@@ -0,0 +1,116 @@
|
||||
eclipse.preferences.version=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/BATCH_BUILD/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/BATCH_BUILD/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/BATCH_BUILD/value=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/EXTRA_CFLAGS/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/EXTRA_CFLAGS/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/EXTRA_CFLAGS/value=-DRECOVERY_APPLICATION\=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/IDF_PATH/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/IDF_PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/IDF_PATH/value=/var/opt/esp-idf
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/append=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786.212420495/appendContributed=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/BATCH_BUILD/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/BATCH_BUILD/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/BATCH_BUILD/value=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/EXTRA_CFLAGS/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/EXTRA_CFLAGS/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/EXTRA_CFLAGS/value=
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/IDF_PATH/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/IDF_PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/IDF_PATH/value=/var/opt/esp-idf
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/PATH/delimiter=;
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/PATH/value=C\:/msys2/opt/xtensa-esp32-elf/bin;C\:/jdk-12.0.2/bin/server;C\:/jdk-12.0.2/bin;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files\\NVIDIA Corporation\\NVIDIA NvDLISR;C\:\\jdk-12.0.2\\bin;C\:\\Program Files\\PuTTY\\;C\:\\Program Files (x86)\\HP\\IdrsOCR_15.2.10.1114\\;C\:\\eclipse
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/append=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/appendContributed=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/BATCH_BUILD/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/BATCH_BUILD/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/BATCH_BUILD/value=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/IDF_PATH/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/IDF_PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/IDF_PATH/value=C\:/msys32/opt/esp-idf
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/PATH/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/PATH/value=C\:\\msys32\\usr\\bin;C\:\\msys32\\mingw32\\bin;C\:\\msys32\\opt\\xtensa-esp32-elf\\bin\\
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/PROJECT_NAME/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/PROJECT_NAME/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/PROJECT_NAME/value=recovery.custom
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/PROJECT_VER/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/PROJECT_VER/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/PROJECT_VER/value=custom
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/append=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/appendContributed=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/BATCH_BUILD/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/BATCH_BUILD/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/BATCH_BUILD/value=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/IDF_PATH/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/IDF_PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/IDF_PATH/value=C\:/msys32/opt/esp-idf
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/PATH/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/PATH/value=C\:\\msys32\\opt\\openocd-esp32\\bin;c\:\\msys32\\opt\\xtensa-esp32-elf\\bin\\;c\:\\msys32\\mingw32\\bin;C\:\\msys32\\usr\\bin;c\:\\Python27;C\:\\msys32\\usr\\bin\\vendor_perl;C\:\\msys32\\usr\\bin\\core_perl
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/PROJECT_NAME/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/PROJECT_NAME/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/PROJECT_NAME/value=recovery
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/PROJECT_VER/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/PROJECT_VER/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/PROJECT_VER/value=custom
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/append=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/appendContributed=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/BATCH_BUILD/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/BATCH_BUILD/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/BATCH_BUILD/value=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/IDF_PATH/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/IDF_PATH/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/IDF_PATH/value=/var/opt/esp-idf/
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/PATH/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/PATH/value=/var/opt/xtensa-esp32-elf/bin/\:/sbin\:/bin\:/usr/bin\:/usr/local/bin\:/snap/bin\:/bin\:/sbin\:/usr/bin\:/usr/local/bin\:/snap/bin
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/PROJECT_NAME/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/PROJECT_NAME/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/PROJECT_NAME/value=recovery.custom
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/PROJECT_VER/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/PROJECT_VER/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/PROJECT_VER/value=custom
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/append=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.839256934/appendContributed=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/BATCH_BUILD/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/BATCH_BUILD/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/BATCH_BUILD/value=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/IDF_PATH/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/IDF_PATH/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/IDF_PATH/value=/var/opt/esp-idf/
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/PATH/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/PATH/value=/var/opt/xtensa-esp32-elf/bin/\:/sbin\:/bin\:/usr/bin\:/usr/local/bin\:/snap/bin\:/bin\:/sbin\:/usr/bin\:/usr/local/bin\:/snap/bin
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/PROJECT_NAME/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/PROJECT_NAME/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/PROJECT_NAME/value=squeezelite.custom
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/PROJECT_VER/delimiter=\:
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/PROJECT_VER/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/PROJECT_VER/value=custom
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/append=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348/appendContributed=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/BATCH_BUILD/delimiter=;
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/BATCH_BUILD/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/BATCH_BUILD/value=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/IDF_PATH/delimiter=;
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/IDF_PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/IDF_PATH/value=c\:/msys32/opt/esp-idf
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/PATH/delimiter=;
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/PATH/value=C\:\\msys32\\usr\\bin;C\:\\msys32\\mingw32\\bin;C\:\\msys32\\opt\\xtensa-esp32-elf\\bin;C\:\\Python27
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/append=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738.859326707/appendContributed=false
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/BATCH_BUILD/delimiter=;
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/BATCH_BUILD/operation=append
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/BATCH_BUILD/value=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/IDF_PATH/delimiter=;
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/IDF_PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/IDF_PATH/value=c\:/msys32/opt/esp-idf
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/PATH/delimiter=;
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/PATH/value=C\:\\msys32\\usr\\bin;C\:\\msys32\\mingw32\\bin;C\:\\msys32\\opt\\xtensa-esp32-elf\\bin;C\:\\Python27
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/append=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.cygwin.base.58932738/appendContributed=false
|
||||
103
CHANGELOG
103
CHANGELOG
@@ -1,103 +0,0 @@
|
||||
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
|
||||
- complete libflac fix and add chaining enablement
|
||||
- fixed stream Ogg demux issue with unknown granule
|
||||
|
||||
2024-01-19
|
||||
- fixed libflac with OggFlac
|
||||
- AirPlay missed frame logging
|
||||
|
||||
2024-01-16
|
||||
- catch-up with cspot latest
|
||||
- refactor airplay flush/first packet
|
||||
- new libFLAC that supports multi-stream OggFlac
|
||||
- fix output threshold
|
||||
- log missed frames
|
||||
|
||||
2024-01-10
|
||||
- add OggFlac to stream metadata
|
||||
- fix OggFlac deadlock in flac callback when not enough data in streambuf
|
||||
- fix no displayer due to threadshold too high (use 500ms instead)
|
||||
- reset outputbuf when cspot starts
|
||||
|
||||
2024-01-01
|
||||
- ogg stream are parsed to foward metadata to LMS
|
||||
- fix some ogg parsing on multi-stream containers
|
||||
|
||||
2023-11-19
|
||||
- more robust (?) airplay RTP frame recovery
|
||||
- initialize of scratch string in monitor (trying to figure out random reboot)
|
||||
|
||||
2023-11-16
|
||||
- add SH1122 support
|
||||
- optimize GDS DrawPixel function
|
||||
|
||||
2023-11-09
|
||||
- force gpio_pad_select_gpio in dac_controlset in case somebody uses UART gpio's (or other pre-programmed)
|
||||
|
||||
2023-11-08
|
||||
- execute dac_controlset even when there is no i2s (for gpio)
|
||||
|
||||
2023-11-07
|
||||
- led-vu gain + misc fixes
|
||||
- bump plugin version to 0.600
|
||||
|
||||
2023-11-03
|
||||
- don't reboot when external decoder is connected even with a LMS server
|
||||
|
||||
2023-10-28
|
||||
- fix recovery size (remove bootstrap)
|
||||
- improve NVS initialization structure
|
||||
|
||||
2023-10-27
|
||||
- fix vorbis (and opus) memory leak
|
||||
|
||||
2023-10-25
|
||||
- fix vorbis codec close
|
||||
|
||||
2023-10-23
|
||||
- fix Spotify track insertion
|
||||
- [WEB] Allow running without LMS with option "Audio/Disable Squeezelite"
|
||||
|
||||
2023-10.07
|
||||
- catchup with official cspot
|
||||
|
||||
2023-10-06
|
||||
- fix cspot PREV on first track, NEXT on last track and normal ending
|
||||
- use DMA_AUTO for SPI
|
||||
- cspot share same time log
|
||||
|
||||
2023-10-06
|
||||
- Fix bootswatch bug that caused difficult to read UI ( issue #319)
|
||||
|
||||
2023-10-02
|
||||
- update cspot
|
||||
|
||||
2023-09-29
|
||||
- sleep mechanism
|
||||
- spotify can store credentials so that zeroconf is optional and players are always registered
|
||||
- add battery to led_vu (see credits)
|
||||
- spdif can do 24 bits (see credits)
|
||||
- rmt fixes
|
||||
- airplay & spotify artwork fixes
|
||||
- airplay stability improvments
|
||||
- fix UI text color
|
||||
230
CMakeLists.txt
230
CMakeLists.txt
@@ -1,231 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
set(PROJECT_VER $ENV{PROJECT_VER})
|
||||
add_definitions(-DMODEL_NAME=SqueezeESP32)
|
||||
|
||||
if(NOT DEFINED DEPTH)
|
||||
set(DEPTH "16")
|
||||
endif()
|
||||
|
||||
# State machine hierarchy enabled and logging enabled
|
||||
add_definitions(-DSTATE_MACHINE_LOGGER=1)
|
||||
add_definitions(-DHIERARCHICAL_STATES=1)
|
||||
|
||||
# Uncomment line below to get memory usage trace details
|
||||
#add_definitions(-DENABLE_MEMTRACE=1)
|
||||
#uncomment line below to get network ethernet debug logs
|
||||
#add_definitions(-DNETWORK_ETHERNET_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#uncomment line below to get network status debug logs
|
||||
#add_definitions(-DNETWORK_STATUS_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#add_definitions(-DNETWORK_HANDLERS_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#add_definitions(-DNETWORK_WIFI_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#add_definitions(-DNETWORK_MANAGER_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
#add_definitions(-DNETWORK_HTTP_SERVER_LOG_LEVEL=ESP_LOG_DEBUG)
|
||||
|
||||
# utility to build sizes
|
||||
function(build_size target_name)
|
||||
set(target_elf ${target_name}.elf)
|
||||
set(target_map ${target_name}.map)
|
||||
set(idf_size ${python} ${IDF_PATH}/tools/idf_size.py)
|
||||
|
||||
if(DEFINED OUTPUT_JSON AND OUTPUT_JSON)
|
||||
list(APPEND idf_size "--json")
|
||||
endif()
|
||||
|
||||
add_custom_target(size-${target_name} ALL
|
||||
DEPENDS ${target_elf}
|
||||
COMMAND ${idf_size} ${target_map} -o "size-${target_name}"
|
||||
)
|
||||
|
||||
add_custom_target(size-files-${target_name} ALL
|
||||
DEPENDS ${target_elf}
|
||||
COMMAND ${idf_size} --files ${target_map}
|
||||
)
|
||||
|
||||
add_custom_target(size-components-${target_name} ALL
|
||||
DEPENDS ${target_elf}
|
||||
COMMAND ${idf_size} --archives ${target_map}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# manually add the 2 versions for application: recovery and squeezelite
|
||||
set(EXTRA_COMPONENT_DIRS components/platform_console/app_recovery components/platform_console/app_squeezelite )
|
||||
|
||||
project(recovery)
|
||||
|
||||
# we need own "esp_app_desc" to take precedence
|
||||
add_custom_command(
|
||||
TARGET recovery.elf
|
||||
PRE_LINK
|
||||
COMMAND xtensa-esp32-elf-objcopy --weaken-symbol esp_app_desc ${BUILD_DIR}/esp-idf/app_update/libapp_update.a
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# when building recovery, add app_recovery to the link
|
||||
get_target_property(BCA recovery.elf LINK_LIBRARIES)
|
||||
list(REMOVE_ITEM BCA "idf::app_squeezelite" "idf::app_recovery" "-Wl,--Map=${BUILD_DIR}/recovery.map")
|
||||
set_target_properties(recovery.elf PROPERTIES LINK_LIBRARIES "${BCA};idf::app_recovery;-Wl,--Map=${BUILD_DIR}/recovery.map")
|
||||
|
||||
# create files with size for recovery
|
||||
# build_size(recovery)
|
||||
|
||||
# build squeezelite, add app_squeezelite to the link
|
||||
add_executable(squeezelite.elf "CMakeLists.txt")
|
||||
add_dependencies(squeezelite.elf recovery.elf)
|
||||
set_target_properties(squeezelite.elf PROPERTIES LINK_LIBRARIES "${BCA};idf::app_squeezelite;-Wl,--Map=${BUILD_DIR}/squeezelite.map,--wrap=esp_panic_handler")
|
||||
add_custom_command(
|
||||
TARGET squeezelite.elf
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generating ${BUILD_DIR}/squeezelite.bin"
|
||||
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS} -o "squeezelite.bin" "squeezelite.elf"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# create files with size for squeezelite
|
||||
# build_size(squeezelite)
|
||||
|
||||
# make it part of cleanup
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES "${BUILD_DIR}/squeezelite.elf" "${BUILD_DIR}/squeezelite.map"
|
||||
)
|
||||
|
||||
# adding OTA_0 partition
|
||||
partition_table_get_partition_info(otaapp_offset "--partition-type app --partition-subtype ota_0" "offset")
|
||||
idf_component_get_property(main_args esptool_py FLASH_ARGS)
|
||||
idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS)
|
||||
esptool_py_flash_target(squeezelite-flash "${main_args}" "${sub_args}")
|
||||
esptool_py_flash_target_image(squeezelite-flash squeezelite "${otaapp_offset}" "${BUILD_DIR}/squeezelite.bin")
|
||||
esptool_py_flash_target_image(flash squeezelite "${otaapp_offset}" "${BUILD_DIR}/squeezelite.bin")
|
||||
|
||||
# and JTAG scripts
|
||||
add_custom_target(_jtag_scripts ALL
|
||||
BYPRODUCTS "flash_dbg_project_args"
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_SOURCE_DIR}/generate_debug_scripts.cmake"
|
||||
)
|
||||
|
||||
if(CMAKE_HOST_UNIX)
|
||||
# Add custom target to set executable permissions before build for cspot component
|
||||
add_custom_target(set_cspot_permissions
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "************************************************************************************************"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "**** Setting permissions for required files"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "**** ${CMAKE_SOURCE_DIR}/components/spotify/cspot/bell/external/nanopb/generator/protoc-gen-nanopb"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "**** ${CMAKE_SOURCE_DIR}/components/spotify/cspot/bell/external/nanopb/generator/*.py"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "**** ${CMAKE_SOURCE_DIR}/components/spotify/cspot/bell/external/nanopb/generator/*.py2"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "**** ${CMAKE_SOURCE_DIR}/components/spotify/cspot/bell/external/nanopb/generator/proto/*.py"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "**** ${CMAKE_SOURCE_DIR}/components/spotify/cspot/bell/external/nanopb/generator/protoc"
|
||||
COMMAND chmod +x ${CMAKE_SOURCE_DIR}/components/spotify/cspot/bell/external/nanopb/generator/protoc-gen-nanopb
|
||||
COMMAND chmod +x ${CMAKE_SOURCE_DIR}/components/spotify/cspot/bell/external/nanopb/generator/*.py
|
||||
COMMAND chmod +x ${CMAKE_SOURCE_DIR}/components/spotify/cspot/bell/external/nanopb/generator/*.py2
|
||||
COMMAND chmod +x ${CMAKE_SOURCE_DIR}/components/spotify/cspot/bell/external/nanopb/generator/proto/*.py
|
||||
COMMAND chmod +x ${CMAKE_SOURCE_DIR}/components/spotify/cspot/bell/external/nanopb/generator/protoc
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "************************************************************************************************"
|
||||
)
|
||||
|
||||
# Add a dependency to ensure permissions are set before building cspot component
|
||||
add_dependencies(__idf_spotify set_cspot_permissions)
|
||||
endif()
|
||||
|
||||
# ======================= DEBUG FLAGS ============================
|
||||
|
||||
#target_compile_definitions(__idf_esp_eth PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO)
|
||||
|
||||
#target_compile_definitions(__idf_services PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
|
||||
#target_compile_definitions(__idf_driver PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
#target_compile_definitions(__idf_wifi-manager PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
#target_compile_definitions(__idf_esp_wifi PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
#target_compile_definitions(__idf_platform_console PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
|
||||
#target_compile_definitions(__idf_app_recovery PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO)
|
||||
# target_compile_definitions(__idf_esp_eth PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO)
|
||||
# target_compile_definitions(__idf_esp_event PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO)
|
||||
# target_compile_definitions(__idf_esp_netif PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
|
||||
# target_compile_definitions(__idf_freertos PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
#target_compile_definitions(__idf_bt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_ERROR)
|
||||
# target_compile_definitions(__idf_mdns PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_tcpip_adapter PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_tcp_transport PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
|
||||
#target_compile_definitions(__idf_app_squeezelite PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_app_trace PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_app_update PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_asio PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_audio PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_bootloader_support PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
|
||||
# target_compile_definitions(__idf_cbor PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_cmock PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_coap PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_console PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_cxx PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_display PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_driver PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_driver_bt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_efuse PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp-dsp PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp-tls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp32 PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_espcoredump PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_adc_cal PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_common PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_gdbstub PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_hid PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_https_ota PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_http_client PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_http_server PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_hw_support PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_ipc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_local_ctrl PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_pm PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_ringbuf PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_rom PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_serial_slave_link PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_system PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_timer PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_esp_websocket_client PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_expat PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_fatfs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_freemodbus PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_hal PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_heap PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_jsmn PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_json PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_libsodium PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_log PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_lwip PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_main PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_mbedtls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(mbedcrypto PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(mbedtls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(mbedx509 PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_mqtt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_newlib PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_nghttp PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_nvs_flash PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_openssl PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_perfmon PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_platform_config PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_protobuf-c PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_protocomm PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_pthread PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_raop PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_sdmmc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
|
||||
# target_compile_definitions(__idf_soc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_spiffs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_spi_flash PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_squeezelite PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_squeezelite-ota PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_telnet PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_tools PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_ulp PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_unity PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_vfs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_wear_levelling PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_wifi_provisioning PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_wpa_supplicant PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
# target_compile_definitions(__idf_xtensa PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
|
||||
project(squeezelite-esp32)
|
||||
219
Dockerfile
219
Dockerfile
@@ -1,200 +1,35 @@
|
||||
FROM ubuntu:20.04
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt-get update && apt-get install -y git wget libncurses-dev flex bison gperf \
|
||||
python python-pip python-setuptools python-serial python-click \
|
||||
python-cryptography python-future python-pyparsing \
|
||||
python-pyelftools cmake ninja-build ccache libusb-1.0
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV GCC_TOOLS_BASE=/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-
|
||||
# To build the image for a branch or a tag of IDF, pass --build-arg IDF_CLONE_BRANCH_OR_TAG=name.
|
||||
# To build the image with a specific commit ID of IDF, pass --build-arg IDF_CHECKOUT_REF=commit-id.
|
||||
# It is possibe to combine both, e.g.:
|
||||
# IDF_CLONE_BRANCH_OR_TAG=release/vX.Y
|
||||
# IDF_CHECKOUT_REF=<some commit on release/vX.Y branch>.
|
||||
# Docker build for release 4.3.5 as of 2023/05/18
|
||||
# docker build . --build-arg IDF_CHECKOUT_REF=6d04316cbe4dc35ea7e4885e9821bd9958ac996d -t sle118/squeezelite-esp32-idfv435
|
||||
# Updating the docker image in the repository
|
||||
# docker push sle118/squeezelite-esp32-idfv435
|
||||
# or to do both:
|
||||
# docker build . --build-arg IDF_CHECKOUT_REF=6d04316cbe4dc35ea7e4885e9821bd9958ac996d -t sle118/squeezelite-esp32-idfv435 && docker push sle118/squeezelite-esp32-idfv435
|
||||
#
|
||||
# (windows) To run the image interactive :
|
||||
# docker run --rm -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv435
|
||||
# (windows powershell)
|
||||
# docker run --rm -v ${PWD}:/project -w /project -it sle118/squeezelite-esp32-idfv435
|
||||
# (linux) To run the image interactive :
|
||||
# docker run --rm -v `pwd`:/project -w /project -it sle118/squeezelite-esp32-idfv435
|
||||
# to build the web app inside of the interactive session
|
||||
# pushd components/wifi-manager/webapp/ && npm install && npm run-script build && popd
|
||||
#
|
||||
# to run the docker with netwotrk port published on the host:
|
||||
# (windows)
|
||||
# docker run --rm -p 5000:5000/tcp -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv435
|
||||
# (linux)
|
||||
# docker run --rm -p 5000:5000/tcp -v `pwd`:/project -w /project -it sle118/squeezelite-esp32-idfv435
|
||||
RUN mkdir /workspace
|
||||
WORKDIR /workspace
|
||||
|
||||
# Download and checkout known good esp-idf commit
|
||||
RUN git clone --recursive https://github.com/espressif/esp-idf.git esp-idf
|
||||
RUN cd esp-idf && git checkout 4dac7c7df885adaa86a5c79f2adeaf8d68667349
|
||||
RUN git clone https://github.com/sle118/squeezelite-esp32.git
|
||||
|
||||
ARG IDF_CLONE_URL=https://github.com/espressif/esp-idf.git
|
||||
ARG IDF_CLONE_BRANCH_OR_TAG=master
|
||||
ARG IDF_CHECKOUT_REF=6d04316cbe4dc35ea7e4885e9821bd9958ac996d
|
||||
# Download GCC 5.2.0
|
||||
RUN wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
|
||||
RUN tar -xzf xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
|
||||
RUN rm xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
|
||||
|
||||
ENV IDF_PATH=/opt/esp/idf
|
||||
ENV IDF_TOOLS_PATH=/opt/esp
|
||||
# Patch I2S in esp-idf
|
||||
RUN cp /workspace/squeezelite-esp32/idf-patch/i2s.c /workspace/esp-idf/components/driver/i2s.c
|
||||
RUN rm -r /workspace/squeezelite-esp32
|
||||
RUN mkdir /workspace/squeezelite-esp32
|
||||
|
||||
# We need libpython2.7 due to GDB tools
|
||||
# we also need npm 8 for the webapp to work
|
||||
RUN : \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y \
|
||||
apt-utils \
|
||||
build-essential \
|
||||
bison \
|
||||
ca-certificates \
|
||||
ccache \
|
||||
check \
|
||||
curl \
|
||||
flex \
|
||||
git \
|
||||
git-lfs \
|
||||
gperf \
|
||||
lcov \
|
||||
libbsd-dev \
|
||||
libpython3.8 \
|
||||
libffi-dev \
|
||||
libncurses-dev \
|
||||
libusb-1.0-0-dev \
|
||||
make \
|
||||
ninja-build \
|
||||
python3.8 \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
ruby \
|
||||
unzip \
|
||||
wget \
|
||||
xz-utils \
|
||||
zip \
|
||||
npm \
|
||||
nodejs \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& update-alternatives --install /usr/bin/python python /usr/bin/python3 10 \
|
||||
&& python -m pip install --upgrade \
|
||||
pip \
|
||||
virtualenv \
|
||||
&& cd /opt \
|
||||
&& git clone https://github.com/HBehrens/puncover.git \
|
||||
&& cd puncover \
|
||||
&& python setup.py -q install \
|
||||
&& echo IDF_CHECKOUT_REF=$IDF_CHECKOUT_REF IDF_CLONE_BRANCH_OR_TAG=$IDF_CLONE_BRANCH_OR_TAG \
|
||||
&& git clone --recursive \
|
||||
${IDF_CLONE_BRANCH_OR_TAG:+-b $IDF_CLONE_BRANCH_OR_TAG} \
|
||||
$IDF_CLONE_URL $IDF_PATH \
|
||||
&& if [ -n "$IDF_CHECKOUT_REF" ]; then \
|
||||
cd $IDF_PATH \
|
||||
&& git checkout $IDF_CHECKOUT_REF \
|
||||
&& git submodule update --init --recursive; \
|
||||
fi \
|
||||
&& update-ca-certificates --fresh \
|
||||
&& $IDF_PATH/tools/idf_tools.py --non-interactive install required \
|
||||
&& $IDF_PATH/tools/idf_tools.py --non-interactive install cmake \
|
||||
&& $IDF_PATH/tools/idf_tools.py --non-interactive install-python-env \
|
||||
&& :
|
||||
RUN : \
|
||||
echo Installing pygit2 ******************************************************** \
|
||||
&& . /opt/esp/python_env/idf4.3_py3.8_env/bin/activate \
|
||||
&& ln -sf /opt/esp/python_env/idf4.3_py3.8_env/bin/python /usr/local/bin/python \
|
||||
&& pip install pygit2 requests \
|
||||
&& pip show pygit2 \
|
||||
&& python --version \
|
||||
&& pip --version \
|
||||
&& pip install protobuf grpcio-tools \
|
||||
&& rm -rf $IDF_TOOLS_PATH/dist \
|
||||
&& :
|
||||
# Setup PATH to use esp-idf and gcc-5.2.0
|
||||
RUN touch /root/.bashrc && \
|
||||
echo export PATH="\$PATH:/workspace/xtensa-esp32-elf/bin" >> /root/.bashrc && \
|
||||
echo export IDF_PATH=/workspace/esp-idf >> /root/.bashrc
|
||||
|
||||
COPY docker/patches $IDF_PATH
|
||||
# OPTIONAL: Install vim for text editing in Bash
|
||||
RUN apt-get update && apt-get install -y vim
|
||||
|
||||
#set idf environment variabies
|
||||
ENV PATH /opt/esp/idf/components/esptool_py/esptool:/opt/esp/idf/components/espcoredump:/opt/esp/idf/components/partition_table:/opt/esp/idf/components/app_update:/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin:/opt/esp/tools/xtensa-esp32s2-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32s2-elf/bin:/opt/esp/tools/xtensa-esp32s3-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32s3-elf/bin:/opt/esp/tools/riscv32-esp-elf/esp-2021r2-patch3-8.4.0/riscv32-esp-elf/bin:/opt/esp/tools/esp32ulp-elf/2.28.51-esp-20191205/esp32ulp-elf-binutils/bin:/opt/esp/tools/esp32s2ulp-elf/2.28.51-esp-20191205/esp32s2ulp-elf-binutils/bin:/opt/esp/tools/cmake/3.16.4/bin:/opt/esp/tools/openocd-esp32/v0.11.0-esp32-20220706/openocd-esp32/bin:/opt/esp/python_env/idf4.3_py3.8_env/bin:/opt/esp/idf/tools:$PATH
|
||||
ENV GCC_TOOLS_BASE="/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-"
|
||||
ENV IDF_PATH="/opt/esp/idf"
|
||||
ENV IDF_PYTHON_ENV_PATH="/opt/esp/python_env/idf4.3_py3.8_env"
|
||||
ENV IDF_TOOLS_EXPORT_CMD="/opt/esp/idf/export.sh"
|
||||
ENV IDF_TOOLS_INSTALL_CMD="/opt/esp/idf/install.sh"
|
||||
ENV IDF_TOOLS_PATH="/opt/esp"
|
||||
ENV NODE_PATH="/v8/lib/node_modules"
|
||||
ENV NODE_VERSION="8"
|
||||
ENV OPENOCD_SCRIPTS="/opt/esp/tools/openocd-esp32/v0.10.0-esp32-20211111/openocd-esp32/share/openocd/scripts"
|
||||
# Ccache is installed, enable it by default
|
||||
|
||||
# The constraint file has been downloaded and the right Python package versions installed. No need to check and
|
||||
# download this at every invocation of the container.
|
||||
ENV IDF_PYTHON_CHECK_CONSTRAINTS=no
|
||||
|
||||
# Ccache is installed, enable it by default
|
||||
ENV IDF_CCACHE_ENABLE=1
|
||||
|
||||
# Install QEMU runtime dependencies
|
||||
RUN : \
|
||||
&& apt-get update && apt-get install -y -q \
|
||||
libglib2.0-0 \
|
||||
libpixman-1-0 \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& :
|
||||
|
||||
# Install QEMU
|
||||
ARG QEMU_VER=esp-develop-20220919
|
||||
ARG QEMU_DIST=qemu-${QEMU_VER}.tar.bz2
|
||||
ARG QEMU_SHA256=f6565d3f0d1e463a63a7f81aec94cce62df662bd42fc7606de4b4418ed55f870
|
||||
RUN : \
|
||||
&& wget --no-verbose https://github.com/espressif/qemu/releases/download/${QEMU_VER}/${QEMU_DIST} \
|
||||
&& echo "${QEMU_SHA256} *${QEMU_DIST}" | sha256sum --check --strict - \
|
||||
&& tar -xf ${QEMU_DIST} -C /opt \
|
||||
&& rm ${QEMU_DIST} \
|
||||
&& :
|
||||
|
||||
COPY docker/entrypoint.sh /opt/esp/entrypoint.sh
|
||||
COPY components/wifi-manager/webapp/package.json /opt
|
||||
|
||||
ENV NODE_VERSION 8
|
||||
|
||||
SHELL ["/bin/bash", "--login", "-c"]
|
||||
# Install nvm with node and npm
|
||||
# RUN wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash \
|
||||
# && export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" \
|
||||
# && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" \
|
||||
# && nvm install $NODE_VERSION \
|
||||
# && nvm alias default $NODE_VERSION \
|
||||
# && nvm use default \
|
||||
# && echo installing nodejs version 16 \
|
||||
# && curl -sL https://deb.nodesource.com/setup_16.x | bash - \
|
||||
# && echo installing node modules \
|
||||
# && cd /opt \
|
||||
# && nvm use default \
|
||||
# && npm install -g \
|
||||
# && :
|
||||
|
||||
RUN : \
|
||||
&& curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \
|
||||
&& apt-get install -y nodejs jq \
|
||||
&& echo installing dev node modules globally \
|
||||
&& cd /opt \
|
||||
&& cat ./package.json | jq '.devDependencies | keys[] as $k | "\($k)@\(.[$k])"' | xargs -t npm install --global \
|
||||
&& echo installing npm global packages \
|
||||
&& npm i -g npm \
|
||||
&& node --version \
|
||||
&& npm install -g \
|
||||
&& :
|
||||
RUN : \
|
||||
&& npm install -g html-webpack-plugin
|
||||
|
||||
|
||||
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
|
||||
ENV PATH $IDF_PYTHON_ENV_PATH:$NVM_DIR/v$NODE_VERSION/bin:$PATH
|
||||
COPY ./docker/build_tools.py /usr/sbin/build_tools.py
|
||||
RUN : \
|
||||
&& echo Changing permissions ******************************************************** \
|
||||
&& chmod +x /opt/esp/entrypoint.sh \
|
||||
&& chmod +x /usr/sbin/build_tools.py \
|
||||
&& :
|
||||
|
||||
|
||||
|
||||
ENTRYPOINT [ "/opt/esp/entrypoint.sh" ]
|
||||
CMD [ "/bin/bash" ]
|
||||
WORKDIR /workspace/squeezelite-esp32
|
||||
CMD ["bash"]
|
||||
|
||||
10
Makefile
10
Makefile
@@ -10,13 +10,9 @@
|
||||
|
||||
|
||||
#recovery: PROJECT_NAME:=recovery.$(PROJECT_CONFIG_TARGET)
|
||||
#recovery: EXTRA_CPPFLAGS+=-DRECOVERY_APPLICATION=1
|
||||
#recovery: CPPFLAGS+=-DRECOVERY_APPLICATION=1
|
||||
|
||||
PROJECT_NAME?=squeezelite
|
||||
EXTRA_CPPFLAGS+= -I$(PROJECT_PATH)/main
|
||||
|
||||
#/-Wno-error=maybe-uninitialized
|
||||
EXTRA_COMPONENT_DIRS := esp-dsp
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
||||
# for future gcc version, this could be needed: CPPFLAGS+= -Wno-error=format-overflow -Wno-error=stringop-truncation
|
||||
|
||||
CPPFLAGS+= -Wno-error=maybe-uninitialized
|
||||
|
||||
568
README.md
568
README.md
@@ -1,146 +1,43 @@
|
||||
[](https://github.com/sle118/squeezelite-esp32/actions/workflows/Platform_build.yml)
|
||||
# Squeezelite-esp32
|
||||
## Forewords
|
||||
**More and more people seems to use this without a LMS server, just for BT, AirPlay or Spotify. It's fine but understand that squeezeliteESP32 is primarily a Logitech Media Server player and has been designed around that concept. All the others are add-ons stitched to it, so other modes have their shortcomings. So please make sure you read [this](#Additional-configuration-notes-from-the-Web-UI) before opening an issue**
|
||||
## What is this?
|
||||
Squeezelite-esp32 is an audio software suite made to run on espressif's esp32 and esp32-s3 wifi (b/g/n) and bluetooth chipsets. It offers the following capabilities
|
||||
|
||||
- Stream your local music and connect to all major on-line music providers (Spotify, Deezer, Tidal, Qobuz) using [Logitech Media Server - a.k.a LMS](https://forums.slimdevices.com/) and enjoy multi-room audio synchronization. LMS can be extended by numerous plugins and can be controlled using a Web browser or dedicated applications (iPhone, Android). It can also send audio to UPnP, Sonos, ChromeCast and AirPlay speakers/devices.
|
||||
- Stream from a **Bluetooth** device (iPhone, Android)
|
||||
- Stream from an **AirPlay** controller (iPhone, iTunes ...) and enjoy synchronization multiroom as well (although it's AirPlay 1 only)
|
||||
- Stream directly from **Spotify** using SpotifyConnect (thanks to [cspot](https://github.com/feelfreelinux/cspot)) - please read carefully [this](#spotify)
|
||||
|
||||
Depending on the hardware connected to the esp32, you can send audio to a local DAC, to SPDIF or to a Bluetooth speaker. The bare minimum required hardware is a WROVER module with 4MB of Flash and 4MB of PSRAM (https://www.espressif.com/en/products/modules/esp32). With that module standalone, just apply power and you can stream to a Bluetooth speaker. You can also send audio to most I2S DAC as well as to SPDIF receivers using just a cable or an optical transducer.
|
||||
|
||||
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).
|
||||
- [LED strip](#led-strip) for VU-meter
|
||||
- [Ethernet](#ethernet) using a Microchip LAN8720 with RMII interface or Davicom DM9051/W5500 over SPI.
|
||||
|
||||
Other features include
|
||||
|
||||
- Resampling (16 bits mode)
|
||||
- 10-bands equalizer (16 bits mode)
|
||||
- Automatic initial setup using any WiFi device
|
||||
- Full web interface for further configuration/management
|
||||
- Firmware over-the-air update
|
||||
|
||||
To control the equalizer or use the display on LMS, a new player model is required and this is provided through a plugin that is part of LMS' 3rd party repositories
|
||||
|
||||
## Performances
|
||||
*(opinions presented here so I = @philippe44)*
|
||||
The main build of squeezelite-esp32 is a 16 bits internal core with all calculations in 32 bits or float precision. This is a design choice I've made to preserve CPU performances (it is already stretching a lot the esp32 chipset) and optimize memory usage as we only have 4MB of usable RAM. Some might correctly comment that the WROVER module have 8MB of RAM, but the processor is only able to address 4MB and the remaining 4MB must be paginated by smaller blocks and I don't have patience to that.
|
||||
|
||||
Now, when I did the porting of squeezelite to esp32, I've also made the core 16 or 32 bits compatible at compile-time. So far, it works in 32 bits but less tests have been done. You can chose to compile it in 32 bits mode. I'm not very interested above 16 bits samples because it does not bring anything (I have an engineering background in theory of information).
|
||||
|
||||
| Capability |16 bits|32 bits| comment |
|
||||
|----------------------------|-------|-------|--------------------------------------------------------------------|
|
||||
| max sampling rate | 192k | 96k | 192k is very challenging, especially when combined with display |
|
||||
| max bit depth | 16 | 24 | 24 bits are truncated in 16 bits mode |
|
||||
| spdif |16 bits|20 bits| |
|
||||
| mp3, aac, opus, ogg/vorbis | 48k | 48k | |
|
||||
| alac, flac, ogg/flac | 96k | 96k | |
|
||||
| pcm, wav, aif | 192k | 96k | |
|
||||
| equalizer | Y | N | 48kHz max (after resampling) - equalization skipped on >48k tracks |
|
||||
| resampling | Y | N | |
|
||||
| cross-fade | 10s | <5s | depends on buffer size and sampling rate |
|
||||
|
||||
The esp32 must run at 240 MHz, with Quad-SPI I/O at 80 MHz and a clock of 40 Mhz. Still, it's a lot to run, especially knowing that it has a serial Flash and PSRAM, so kudos to Espressif for their chipset optimization. Now, to have all the decoding, resampling, equalizing, gain, display, spectrum/vu is a very (very) delicate equilibrium between use of internal /external RAM, tasks priorities and buffer handling. It is not perfect and the more you push the system to the limit, the higher the risk that some files would not play (see below). In general, the display will always have the lowest priority and you'll notice slowdown in scrolling and VU/Spectrum refresh rates. Now, even display thread has some critical section and impacts the capabilities. For example, a 16 bits-depth color display with low SPI speed might prevent 24/96 flac to work but still work with pcm 24/96
|
||||
|
||||
In 16 bits mode, although 192 kHz is reported as max rate, it's highly recommended to limit reported sampling rate to 96k (-Z 96000). Note that some high-speed 24/96k on-line streams might stutter because of TCP/IP stack performances. It is usually due to the fact that the server sends small packets of data and the esp32 cannot receive encoded audio fast enough, regardless of task priority settings (I've tried to tweak that a fair bit). The best option in that case is to let LMS proxy the stream as it will provide larger chunks and a "smoother" stream that can then be handled.
|
||||
|
||||
Note as well that some codecs consume more CPU than others or have not been optimized as much. I've done my best to tweak these, but that level of optimization includes writing some assembly which is painful. One very demanding codec is AAC when files are encoded with SBR. It allows reconstruction of upper part of spectrum and thus higher sampling rate, but the codec spec is such that this is optional, you can decode simply lower band and accept lower sampling rate - See the AAC_DISABLE_SBR option below.
|
||||
|
||||
**IMPORTANT: on esp32 (not esp32-s3), using Spotify with SPDIF produces stuttering audio when "stats" are enabled. You MUST disable them**
|
||||
|
||||
## Supported Hardware
|
||||
Any esp32-based hardware with at least 4MB of flash and 4MB of PSRAM will be capable of running squeezelite-esp32 and there are various boards that include such chip. A few are mentionned below, but any should work. You can find various help & instructions [here](https://forums.slimdevices.com/showthread.php?112697-ANNOUNCE-Squeezelite-ESP32-(dedicated-thread))
|
||||
|
||||
**For the sake of clarity, WROOM modules DO NOT work as they don't include PSRAM. Some designs might add it externally, but it's (very) unlikely.**
|
||||
|
||||
### Raw WROVER module
|
||||
Per above description, a [WROVER module](https://www.espressif.com/en/products/modules/esp32) is enough to run Squeezelite-esp32, but that requires a bit of tinkering to extend it to have analogue audio or hardware buttons (e.g.)
|
||||
|
||||
Please note that when sending to a Bluetooth speaker (source), only 44.1 kHz can be used, so you either let LMS do the resampling, but you must make sure it only sends 44.1kHz tracks or enable internal resampling (using -R) option. If you connect a DAC, choice of sample rates will depends on its capabilities. See below for more details.
|
||||
|
||||
Most DAC will work out-of-the-box with simply an I2S connection, but some require specific commands to be sent using I2C. See DAC option below to understand how to send these dedicated commands. There is build-in support for TAS575x, TAS5780, TAS5713 and AC101 DAC.
|
||||
|
||||
### Raw WROOM esp32-s3 module
|
||||
The esp32-s3 based modules like [this](https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf) are also supported but requires esp-idf 4.4. It is not yet part of official releases, but it compiles & runs. The s3 does not have bluetooth audio. Note that CPU performances are greatly enhanced.
|
||||
|
||||
## Supported Hardware
|
||||
### SqueezeAMP
|
||||
This is the main hardware companion of Squeezelite-esp32 and has been developped together. Details on capabilities can be found [here](https://forums.slimdevices.com/showthread.php?110926-pre-ANNOUNCE-SqueezeAMP-and-SqueezeliteESP32) and [here](https://github.com/philippe44/SqueezeAMP).
|
||||
Works with the SqueezeAMP see [here](https://forums.slimdevices.com/showthread.php?110926-pre-ANNOUNCE-SqueezeAMP-and-SqueezeliteESP32) and [here](https://github.com/philippe44/SqueezeAMP).
|
||||
|
||||
If you want to rebuild, use the `squeezelite-esp32-SqueezeAmp-sdkconfig.defaults` configuration file.
|
||||
if you want to rebuild, use the `squeezelite-esp32-SqueezeAmp-sdkconfig.defaults` configuration file.
|
||||
|
||||
NB: You can use the pre-build binaries SqueezeAMP4MBFlash 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
|
||||
- set_GPIO: `12=green,13=red,34=jack,2=spkfault`
|
||||
- bat_config: `channel=7,scale=20.24`
|
||||
- dac_config: `model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14:0`
|
||||
- spdif_config: `bck=33,ws=25,do=15`
|
||||
|
||||
The IR can be used as a wake-up signal using (setting `sleep_config` with `wake=0:0`). It's a pull-up so it stays at 1 when not receiving anything which means it cannot be used in conjuction with other wake-up IOs. See [Sleeping](#sleeping) for more details regarding the limitation of waking-up upon multiple inputs.
|
||||
|
||||
### MuseLuxe
|
||||
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=0`
|
||||
- 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}, {"reg":46,"val":33}, {"reg":47,"val":33} ]}`
|
||||
- actrls_config: buttons
|
||||
- define a "buttons" variable with: `[{"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"}}]`
|
||||
NB: You can use the pre-build binaries SqueezeAMP4MBFlash/SqueezeAMP8MBFlash 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
|
||||
- set_GPIO: 12=green,13=red,34=jack,2=spkfault
|
||||
- batt_config: channel=7,scale=20.24
|
||||
- dac_config: model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14:0
|
||||
- spdif_config: bck=33,ws=25,do=15
|
||||
|
||||
### ESP32-A1S
|
||||
Works with [ESP32-A1S](https://docs.ai-thinker.com/esp32-a1s) module that includes audio codec and headset output. You still need to use a demo board like [this](https://aliexpress.com/item/4000130915903.html) or an external amplifier if you want direct speaker connection. Note that there is a version with AC101 codec and another one with ES8388 with probably two variants - these boards are a mess (see below)
|
||||
Works with [ESP32-A1S](https://docs.ai-thinker.com/esp32-a1s) module that includes audio codec and headset output. You still need to use a demo board like [this](https://www.aliexpress.com/item/4000765857347.html?spm=2114.12010615.8148356.11.5d963cd0j669ns) or an external amplifier if you want direct speaker connection.
|
||||
|
||||
The board shown above has the following IO set
|
||||
The board showed above has the following IO set
|
||||
- amplifier: GPIO21
|
||||
- key2: GPIO13, key3: GPIO19, key4: GPIO23, key5: GPIO18, key6: GPIO5 (to be confirmed with dip switches)
|
||||
- key1: not sure, using GPIO36 in a matrix
|
||||
- key1: not sure, something with GPIO36
|
||||
- jack insertion: GPIO39 (inserted low)
|
||||
- D4 -> GPIO22 used for green LED (active low)
|
||||
- D5 -> GPIO19 (muxed with key3)
|
||||
- The IO connector also brings GPIO5, GPIO18, GPIO19, GPIO21, GPIO22 and GPIO23 (don't forget it's muxed with keys!)
|
||||
- The JTAG connector uses GPIO 12, 13, 14 and 15 (see dip switch) but these are also used for SD-card (and GPIO13 is key2 as well)
|
||||
- It's always possible to re-use GPIOO (download at boot) and GPIO1/GPIO3 which are RX/TX of UART0 but you'll lose trace
|
||||
|
||||
(note that some GPIO need pullups)
|
||||
- LED: GPIO22 (active low)
|
||||
(note that GPIO need pullups)
|
||||
|
||||
So a possible config would be
|
||||
- set_GPIO: `21=amp,22=green:0,39=jack:0`
|
||||
- set_GPIO: 21=amp,22=green:0,39=jack:0
|
||||
- dac_config: model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32
|
||||
- a button mapping:
|
||||
```json
|
||||
[{"gpio":5,"normal":{"pressed":"ACTRLS_TOGGLE"}},{"gpio":18,"pull":true,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLUP"}, "shifted":{"pressed":"ACTRLS_NEXT"}}, {"gpio":23,"pull":true,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLDOWN"},"shifted":{"pressed":"ACTRLS_PREV"}}]
|
||||
```
|
||||
for **AC101**
|
||||
- dac_config: `model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32`
|
||||
|
||||
for **ES8388** (it seems that there are variants with same version number - a total mess)
|
||||
- dac_config: `model=ES8388,bck=5,ws=25,do=26,sda=18,scl=23,i2c=16`
|
||||
or
|
||||
- dac_config: `model=ES8388,bck=27,ws=25,do=26,sda=33,scl=32,i2c=16`
|
||||
|
||||
```
|
||||
[{"gpio":5,"normal":{"pressed":"ACTRLS_TOGGLE"}},{"gpio":18,"pull":true,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLUP"}, "shifted":{"pressed":"ACTRLS_NEXT"}}, {"gpio":23,"pull":true,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLDOWN"},"shifted":{"pressed":"ACTRLS_PREV"}}]
|
||||
```
|
||||
### T-WATCH2020 by LilyGo
|
||||
This is a fun [smartwatch](http://www.lilygo.cn/prod_view.aspx?TypeId=50036&Id=1290&FId=t3:50036:3) based on ESP32. It has a 240x240 ST7789 screen and onboard audio. Not very useful to listen to anything but it works. This is an example of a device that requires an I2C set of commands for its DAC/APU (see below). There is a build-option if you decide to rebuild everything by yourself, otherwise the I2S default option works with the following parameters
|
||||
|
||||
- dac_config: `model=I2S,bck=26,ws=25,do=33,i2c=53,sda=21,scl=22`
|
||||
- dac_controlset:
|
||||
```json
|
||||
{ "init": [ {"reg":41, "val":128}, {"reg":18, "val":255} ], "poweron": [ {"reg":18, "val":64, "mode":"or"} ], "poweroff": [ {"reg":18, "val":191, "mode":"and"} ] }
|
||||
```
|
||||
- spi_config: `dc=27,data=19,clk=18`
|
||||
- display_config: `SPI,driver=ST7789,width=240,height=240,cs=5,back=12,speed=16000000,HFlip,VFlip`
|
||||
This is a fun [smartwatch](http://www.lilygo.cn/prod_view.aspx?TypeId=50036&Id=1290&FId=t3:50036:3) based on ESP32. It has a 240x240 ST7789 screen and onboard audio. Not very useful to listen to anything but it works. This is an example of a device that requires an I2C set of commands for its dac (see below). There is a build-option if you decide to rebuild everything by yourself, otherwise the I2S default option works with the following parameters
|
||||
|
||||
- dac_config: model=I2S,bck=26,ws=25,do=33,i2c=106,sda=21,scl=22
|
||||
- dac_controlset: { "init": [ {"reg":41, "val":128}, {"reg":18, "val":255} ], "poweron": [ {"reg":18, "val":64, "mode":"or"} ], "poweroff": [ {"reg":18, "val":191, "mode":"and"} ] }
|
||||
- spi_config: dc=27,data=19,clk=18
|
||||
- display_config: SPI,driver=ST7789,width=240,height=240,cs=5,back=12,speed=16000000,HFlip,VFlip
|
||||
### ESP32-WROVER + I2S DAC
|
||||
Squeezelite-esp32 requires esp32 chipset and 4MB PSRAM. ESP32-WROVER meets these requirements. To get an audio output an I2S DAC can be used. Cheap PCM5102 I2S DACs work but many others also do. PCM5012 DACs can be hooked up via:
|
||||
Squeezelite-esp32 requires esp32 chipset and 4MB PSRAM. ESP32-WROVER meets these requirements. To get an audio output an I2S DAC can be used. Cheap PCM5102 I2S DACs work others may also work. PCM5012 DACs can be hooked up via:
|
||||
|
||||
I2S - WROVER
|
||||
VCC - 3.3V
|
||||
@@ -164,112 +61,78 @@ 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
|
||||
```
|
||||
sda=<gpio>,scl=<gpio>[,port=0|1][,speed=<speed>]
|
||||
```
|
||||
**Please note that you can not use the same GPIO or port as the DAC.**
|
||||
|
||||
### SPI
|
||||
The esp32 has 4 SPI sub-systems, one is unaccessible so numbering is 0..2 and SPI0 is reserved for Flash/PSRAM. The NVS parameter "spi_config" set the spi's gpio used for generic purpose (e.g. display). Leave it blank to disable SPI usage. The DC parameter is needed for displays. Syntax is
|
||||
The NVS parameter "spi_config" set the spi's gpio used for generic purpose (e.g. display). Leave it blank to disable SPI usage. The DC parameter is needed for displays. Syntax is
|
||||
```
|
||||
data|mosi=<gpio>,clk=<gpio>[,dc=<gpio>][,host=1|2][,miso=<gpio>]
|
||||
data=<gpio>,clk=<gpio>[,dc=<gpio>][,host=1|2]
|
||||
```
|
||||
Default and only "host" is 1 as others are used already by flash and spiram. The optional "miso" (MasterInSlaveOut) parameter is only used when SPI bus is bi-directional and shared with other peripheral like ethernet, gpio expander. Note that "data" can also be named "mosi" (MasterOutSlaveIn).
|
||||
### DAC/I2S
|
||||
The NVS parameter "dac_config" set the gpio used for i2s communication with your DAC. You can define the defaults at compile time but nvs parameter takes precedence except for named configurations
|
||||
The NVS parameter "dac_config" set the gpio used for i2s communication with your DAC. You can define the defaults at compile time but nvs parameter takes precedence except for SqueezeAMP and A1S where these are forced at runtime. If your DAC also requires i2c, then you must go the re-compile route. Syntax is
|
||||
```
|
||||
bck=<gpio>,ws=<gpio>,do=<gpio>[,mck=0|1|2][,mute=<gpio>[:0|1][,model=TAS57xx|TAS5713|AC101|WM8978|ES8388|I2S][,sda=<gpio>,scl=<gpio>[,i2c=<addr>]]
|
||||
bck=<gpio>,ws=<gpio>,do=<gpio>[,mute=<gpio>[:0|1][,model=TAS57xx|TAS5713|AC101|I2S][,sda=<gpio>,scl=gpio[,i2c=<addr>]]
|
||||
```
|
||||
if "model" is not set or is not recognized, then default "I2S" is used. The option "mck" is used for some codecs that require a master clock (although they should not). By default GPIO0 is used as MCLK and only recent builds (post mid-2023) can use 1 or 2. Also be aware that this cannot coexit with RMII Ethernet (see ethernet section below). I2C parameters are optional and only needed if your DAC requires an I2C control (See 'dac_controlset' below). Note that "i2c" parameters are decimal, hex notation is not allowed.
|
||||
if "model" is not set or is not recognized, then default "I2S" is used. I2C parameters are optional an only needed if your dac requires an I2C control (See 'dac_controlset' below). Note that "i2c" parameters are decimal, hex notation is not allowed.
|
||||
|
||||
So far, TAS57xx, TAS5713, AC101, WM8978 and ES8388 are recognized models where the proper init sequence/volume/power controls are sent. For other codecs that might require an I2C commands, please use the parameter "dac_controlset" that allows definition of simple commands to be sent over i2c for init, power, speaker and headset on and off using a JSON syntax:
|
||||
```json
|
||||
{ <command>: [ <item1>, <item2>, ... <item3> ],
|
||||
<command>: [ <item1>, <item2>, ... <item3> ],
|
||||
... }
|
||||
The parameter "dac_controlset" allows definition of simple commands to be sent over i2c for init, power on and off using a JSON syntax:
|
||||
```
|
||||
Where `<command>` is one of init, poweron, poweroff, speakeron, speakeroff, headseton, headsetoff (it **must** be an array even for a single item). Item is any of the following elements
|
||||
{ init: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
|
||||
poweron: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
|
||||
poweroff: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ] }
|
||||
```
|
||||
{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}
|
||||
{"gpio":<gpio>,"level":0|1}
|
||||
{"delay":<ms>}
|
||||
```
|
||||
This is standard JSON notation, so if you are not familiar with it, Google is your best friend. Be aware that the '...' means you can have as many entries as you want, it's not part of the syntax. Every section is optional, but it does not make sense to set i2c in the 'dac_config' parameter and not setting anything here.
|
||||
|
||||
The `reg` key allow to write registers on i2c bus. The parameter `mode` allows to *or* the register with the value or to *and* it. Don't set `mode` if you simply want to write. The `val` parameter can be an array [v1, v2,...] to write a serie of bytes in a single i2c burst (in that case 'mode' is ignored). **Note that all values must be decimal**. You can use a validator like [this](https://jsonlint.com) to verify your syntax. The `gpio` key is simply to set a gpio as part of DAC action and `delay` allows a pause between elements.
|
||||
|
||||
The 'power' command is used when powering on/off the DAC after the idle period (see -C option of squeezelite) and the 'speaker/headset' commands are sent when switching between speakers and headsets (see headset jack detection).
|
||||
|
||||
NB: For named configurations ((SqueezeAMP, Muse ... all except I2S), all this is ignored. For know codecs, the built-in sequences can be overwritten using dac_controlset
|
||||
|
||||
**Please note that you can not use the same GPIO or port as the I2C.**
|
||||
This is standard JSON notation, so if you are not familiar with it, Google is your best friend. Be aware that the '...' means you can have as many entries as you want, it's not part of the syntax. Every section is optional, but it does not make sense to set i2c in the 'dac_config' parameter and not setting anything here. The parameter 'mode' allows to *or* the register with the value or to *and* it. Don't set 'mode' if you simply want to write. **Note that all values must be decimal**
|
||||
|
||||
NB: For well-known configuration, this is ignored
|
||||
### SPDIF
|
||||
The NVS parameter "spdif_config" sets the i2s's gpio needed for SPDIF.
|
||||
|
||||
SPDIF is made available by re-using i2s interface in a non-standard way, so although only one pin (DO) is needed, the controller must be fully initialized, so the bit clock (bck) and word clock (ws) must be set as well. As i2s and SPDIF are mutually exclusive, you can reuse the same IO if your hardware allows so.
|
||||
|
||||
You can define the defaults at compile time but nvs parameter takes precedence except for named configurations (SqueezeAMP, Muse ...)
|
||||
You can define the defaults at compile time but nvs parameter takes precedence except for SqueezeAMP where these are forced at runtime.
|
||||
|
||||
Leave it blank to disable SPDIF usage, you can also define them at compile time using "make menuconfig". Syntax is
|
||||
```
|
||||
bck=<gpio>,ws=<gpio>,do=<gpio>
|
||||
```
|
||||
NB: For named configurations, this is ignored
|
||||
|
||||
The maximum bit depth is 24 bits, even in 32 bits mode (this a SPDIF limitation - thank @UrbanLienert for theupdate from 20 to 24 bit). Now, you can also get SPDIF using a specialized chip that offers a I2S interface like a DAC but spits out SPDIF (optical and coax). Refers to DAC chapter then.
|
||||
|
||||
If you want coax, you can also use a poor-man's trick to generate signal from a 3.3V GPIO. All that does is dividing the 3.3V to generate a 0.6V peak-to-peak and then remove DC
|
||||
```
|
||||
100nF
|
||||
GPIO ----210ohm-----------||---- coax S/PDIF signal out
|
||||
|
|
||||
110ohm
|
||||
|
|
||||
Ground -------------------------- coax signal ground
|
||||
```
|
||||
|
||||
NB: For well-known configuration, this is ignored
|
||||
### Display
|
||||
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. 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|ST7789[:x=<offset>][:y=<offset>]|ILI9341[:16|18][,rotate]]
|
||||
I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,HFlip][,VFlip][driver=SSD1306|SSD1326[:1|4]|SSD1327|SH1106]
|
||||
SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,speed=<speed>][,HFlip][,VFlip][driver=SSD1306|SSD1322|SSD1326[:1|4]|SSD1327|SH1106|SSD1675|ST7735|ST7789[,rotate]]
|
||||
```
|
||||
- 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
|
||||
- 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)
|
||||
- SSD1322 is 256x64 grayscale 16-levels SPI in multiple sizes [here](https://www.buydisplay.com/oled-display/oled-display-module?resolution=159) - it is very nice
|
||||
- SSD1326 is 256x32 monochrome or grayscale 16-levels SPI [here](https://www.aliexpress.com/item/32833603664.html?spm=a2g0o.productlist.0.0.2d19776cyQvsBi&algo_pvid=c7a3db92-e019-4095-8a28-dfdf0a087f98&algo_expid=c7a3db92-e019-4095-8a28-dfdf0a087f98-1&btsid=0ab6f81e15955375483301352e4208&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_)
|
||||
- SSD1327 is 128x128 16-level grayscale SPI [here](https://www.amazon.com/gp/product/B079N1LLG8/ref=ox_sc_act_title_1?smid=A1N6DLY3NQK2VM&psc=1) - artwork can be up to 96x96 with vertical vu-meter/spectrum
|
||||
- SSD1322 is 128x128 16-level grayscale SPI [here](https://www.amazon.com/gp/product/B079N1LLG8/ref=ox_sc_act_title_1?smid=A1N6DLY3NQK2VM&psc=1) - artwork can be up to 96x96 with vertical vu-meter/spectrum
|
||||
- SSD1351 is 128x128 65k/262k color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/1.5inch-rgb-oled-module.htm)
|
||||
- SSD1326 is 256x32 monochrome or grayscale 16-levels SPI [here](https://www.aliexpress.com/item/32833603664.html?spm=a2g0o.productlist.0.0.2d19776cyQvsBi&algo_pvid=c7a3db92-e019-4095-8a28-dfdf0a087f98&algo_expid=c7a3db92-e019-4095-8a28-dfdf0a087f98-1&btsid=0ab6f81e15955375483301352e4208&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_)
|
||||
- SSD1327 is 256x64 grayscale 16-levels SPI in multiple sizes [here](https://www.buydisplay.com/oled-display/oled-display-module?resolution=159) - it is very nice
|
||||
- SSD1675 is an e-ink paper and is experimental as e-ink is really not suitable for LMS du to its very low refresh rate
|
||||
- ST7735 is a 128x160 65k color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/1.8inch-lcd-module.htm). This needs a backlight control. Some have X/Y offsets betwen the driver and the glass (green/black/red models) that can be added using "x" and "y" options (case sensitive!)
|
||||
- ST7735 is a 128x160 65k color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/1.8inch-lcd-module.htm). This needs a backlight control
|
||||
- ST7789 is a 240x320 65k (262k not enabled) color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/2inch-lcd-module.htm). It also exist with 240x240 displays. See **rotate** for use in portrait mode
|
||||
- ILI9341 is another 240x320 65k (262k capable) color SPI. I've not used it much, the driver it has been provided by one external contributor to the project
|
||||
|
||||
You can tweak how the vu-meter and spectrum analyzer are displayed, as well as size of artwork through a dedicated menu in player's settings (don't forget to add the plugin).
|
||||
To use the display on LMS, add repository https://raw.githubusercontent.com/sle118/squeezelite-esp32/master/plugin/repo.xml. You will then be able to tweak how the vu-meter and spectrum analyzer are displayed, as well as size of artwork. You can also install the excellent plugin "Music Information Screen" which is super useful to tweak the layout.
|
||||
|
||||
The NVS parameter "metadata_config" sets how metadata is displayed for AirPlay and Bluetooth. Syntax is
|
||||
```
|
||||
[format=<display_content>][,speed=<speed>][,pause=<pause>][,artwork[:0|1]]
|
||||
[format=<display_content>][,speed=<speed>][,pause=<pause>]
|
||||
```
|
||||
- 'speed' is the scrolling speed in ms (default is 33ms)
|
||||
|
||||
- 'pause' is the pause time between scrolls in ms (default is 3600ms)
|
||||
- 'format' can contain free text and any of the 3 keywords `%artist%`, `%album%`, `%title%`. Using that format string, the keywords are replaced by their value to build the string to be displayed. Note that the plain text following a keyword that happens to be empty during playback of a track will be removed. For example, if you have set format=`%artist% - %title%` and there is no artist in the metadata then only `<title>` will be displayed not ` - <title>`.
|
||||
- 'artwork' enables coverart display, if available (does not work for Bluetooth). The optional parameter indicates if the artwork should be resized (1) to fit the available space. Note that the built-in resizer can only do 2,4 and 8 downsizing, so fit is not optimal. The artwork will be placed at the right of the display for landscape displays and underneath the two information lines for others (there is no user option to tweak that).
|
||||
|
||||
- 'format' can contain free text and any of the 3 keywords %artist%, %album%, %title%. Using that format string, the keywords are replaced by their value to build the string to be displayed. Note that the plain text following a keyword that happens to be empty during playback of a track will be removed. For example, if you have set format=%artist% - %title% and there is no artist in the metadata then only <title> will be displayed not " - <title>".
|
||||
|
||||
### Infrared
|
||||
You can use any IR receiver compatible with NEC protocol (38KHz) or RC5. Vcc, GND and output are the only pins that need to be connected, no pullup, no filtering capacitor, it's a straight connection.
|
||||
You can use any IR receiver compatible with NEC protocol (38KHz). Vcc, GND and output are the only pins that need to be connected, no pullup, no filtering capacitor, it's a straight connection.
|
||||
|
||||
The IR codes are send "as is" to LMS, so only a Logitech SB remote from Boom, Classic or Touch will work. I think the file Slim_Devices_Remote.ir in the "server" directory of LMS can be modified to adapt to other codes, but I've not tried that.
|
||||
|
||||
@@ -282,108 +145,56 @@ The parameter "set_GPIO" is used to assign GPIO to various functions.
|
||||
|
||||
GPIO can be set to GND provide or Vcc at boot. This is convenient to power devices that consume less than 40mA from the side connector. Be careful because there is no conflict checks being made wrt which GPIO you're changing, so you might damage your board or create a conflict here.
|
||||
|
||||
The `<amp>` parameter can use used to assign a GPIO that will be set to active level (default 1) when playback starts. It will be reset when squeezelite becomes idle. The idle timeout is set on the squeezelite command line through `-C <timeout>`
|
||||
|
||||
The `<power>` parameter can use used to assign a GPIO that will be set to active level (default 1) when player is powered on and reset when powered off (in LMS, does not apply to AirPlay, Spotify or BT).
|
||||
The \<amp\> parameter can use used to assign a GPIO that will be set to active level (default 1) when playback starts. It will be reset when squeezelite becomes idle. The idle timeout is set on the squeezelite command line through -C \<timeout\>
|
||||
|
||||
If you have an audio jack that supports insertion (use :0 or :1 to set the level when inserted), you can specify which GPIO it's connected to. Using the parameter jack_mutes_amp allows to mute the amp when headset (e.g.) is inserted.
|
||||
|
||||
You can set the Green and Red status led as well with their respective active state (:0 or :1) or specific the chipset if you use addressable RGB led.
|
||||
You can set the Green and Red status led as well with their respective active state (:0 or :1)
|
||||
|
||||
The `<ir>` parameter set the GPIO associated to an IR receiver. No need to add pullup or capacitor
|
||||
The \<ir\> parameter set the GPIO associated to an IR receiver. No need to add pullup or capacitor
|
||||
|
||||
Syntax is:
|
||||
|
||||
```
|
||||
<gpio>=Vcc|GND|amp[:1|0]|power[:1:0]|ir[:nec|rc5]|jack[:0|1]|green[:0|1|ws2812]|red[:0|1|ws2812]|spkfault[:0|1][,<repeated sequence for next GPIO>]
|
||||
<gpio>=Vcc|GND|amp[:1|0]|ir|jack[:0|1]|green[:0|1]|red[:0|1]|spkfault[:0|1][,<repeated sequence for next GPIO>]
|
||||
```
|
||||
You can define the defaults for jack, spkfault leds at compile time but nvs parameter takes precedence except for named configurations ((SqueezeAMP, Muse ...) where these are forced at runtime.
|
||||
**Note that gpio 36 and 39 are input only and cannot use interrupt. When set to jack or speaker fault, a 100ms polling checks their value but that's expensive**
|
||||
|
||||
### GPIO expanders
|
||||
It is possible to add GPIO expanders using I2C or SPI bus. They should mainly be used for buttons but they can support generic-purpose outputs as well. These additional GPIOs can be numbered starting from an arbitrary value (40 and above as esp32 has GPIO 0..39). Then these new "virtual" GPIOs from (e.g) 100 to 115 can be used in [button](#Buttons) configuration, [set_GPIO](#set-gpio) or other config settings.
|
||||
|
||||
Each expander can support up to 32 GPIO. To use an expander for buttons, an interrupt must be provided, polling mode is not acceptable. An expander w/o interruption can still be configured, but only output will be usable. Note that the same interrupt can be shared accross expanders, as long as they are using open drain or open collectors (which they probably all do)
|
||||
|
||||
The parameter "gpio_exp_config" is a semicolon (;) separated list with following syntax for each expander
|
||||
```
|
||||
model=<model>,addr=<addr>,[,port=system|dac][,base=<n>][,count=<n>][,intr=<gpio>][,cs=<gpio>][,speed=<Hz>]
|
||||
```
|
||||
- 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
|
||||
- speed (SPI): speed of the SPI bus for that device (in Hz)
|
||||
- base: GPIO numbering offset to use everywhere else (default 40 on esp32 and 48 on esp32-s3)
|
||||
- count: number of GPIO of expander (default 16 - might be obsolted if model if sufficient to decide)
|
||||
- intr: real GPIO to use as interrupt.
|
||||
|
||||
Note that PWM ("led_brightness" below) is not supported for expanded GPIOs and they cannot be used for high speed or precise timing signals like CS, D/C, Reset and Ready. Buttons, rotary encoder, amplifier control and power are supported. Depending on the actual chipset, pullup or pulldown might be supported so you might have to add external resistors (only MCP23x17 does pullup). The pca8575 is not a great chip, it generate a fair bit of spurious interrupts when used for GPIO out. When using a SPI expander, the bus must be configured using shared [SPI](#SPI) bus
|
||||
|
||||
You can define the defaults for jack, spkfault leds at compile time but nvs parameter takes precedence except for well-known configurations where these are forced at runtime.
|
||||
### LED
|
||||
See [set_GPIO](#set-gpio) for how to set the green and red LEDs (including addressable RGB ones). In addition, their brightness can be controlled using the "led_brigthness" parameter. The syntax is
|
||||
See §**set_GPIO** for how to set the green and red LEDs. In addition, their brightness can be controlled using the "led_brigthness" parameter. The syntax is
|
||||
```
|
||||
[green=0..100][,red=0..100]
|
||||
```
|
||||
NB: For named configuration, GPIO affected to green and red LED cannot be changed but brightness option applies
|
||||
|
||||
### LED Strip
|
||||
One LED strip with up to 255 addressable LEDs can be configured to offer enhanced visualizations. The VU Meter visualizer includes a battery status indicator (see Battery). Currently only WS2812B LEDs are supported. Set the LED Strip hardware configuration, or the NVS led_vu_config syntax is
|
||||
```
|
||||
type=[WS2812],length=<n>,gpio=<dataPin>[,scale=<gain>]
|
||||
```
|
||||
where `<n>` is the number of LEDs in the strip (1..255). A `<scale>` gain value (percentage) can be added to enhance effect responses.
|
||||
|
||||
The latest LMS plugin update is required to set the visualizer mode and brightness in the ESP32 Settings page for the player, or a controllable display (see Extra/SqueezeESP32 menus). The plugin adds additional LMS CLI commands.
|
||||
|
||||
| Command | Notes |
|
||||
| -------------------------------------------------- | ----------- |
|
||||
| \<playerid\> led_visual \[\<mode\>\] \[\<brightness\>\] | Toggles or selects the visualizer "mode".<br />The visualizer brightness(0..255) can be controlled using the "brightness" tag. |
|
||||
| \<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 /> |
|
||||
|
||||
NB: For well-known configuration, this is ignored
|
||||
### Rotary Encoder
|
||||
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.
|
||||
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.
|
||||
|
||||
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').
|
||||
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').
|
||||
|
||||
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'
|
||||
- double press is 'Back' (Left in LMS's terminology).
|
||||
- a quick left-right movement on the encoder is 'Pause'
|
||||
|
||||
The speed of double click (or left-right) can be set using the optional parameter of 'knobonly'. This is not a perfect solution, and other ideas are welcome. Be aware that the longer you set double click speed, the less responsive the interface will be. The reason is that I need to wait for that delay before deciding if it's a single or double click. It can also make menu navigation "hesitations" being easily interpreted as 'Pause'
|
||||
The speed of double click (or left-right) can be set using the optional parameter of 'knobonly'. This is not a perfect solution, and other ideas are welcome. Be aware that the longer you set double click speed, the less responsive the interface will be. The reason is that I need to wait for that delay before deciding if it's a single or double click. It can also make menu navigation "hesitations" being easoly interpreted as 'Pause'
|
||||
|
||||
Use parameter rotary_config with the following syntax:
|
||||
|
||||
```
|
||||
A=<gpio>,B=<gpio>[,SW=gpio>[[,knobonly[=<ms>]]|[[,volume][,longpress]]]]
|
||||
A=<gpio>,B=<gpio>[,SW=gpio>[[,knobonly[=<ms>]|[,volume][,longpress]]
|
||||
```
|
||||
|
||||
HW note: all gpio used for rotary have internal pull-up so normally there is no need to provide Vcc to the encoder. Nevertheless if the encoder board you're using also has its own pull-up that are stronger than ESP32's ones (which is likely the case), then there will be crosstalk between gpio, so you must bring Vcc. Look at your board schematic and you'll understand that these board pull-up create a "winning" pull-down when any other pin is grounded.
|
||||
|
||||
The SW gpio is optional, you can re-affect it to a pure button if you prefer but the volume, longpress and knobonly options make little sense as the missing switch plays an important role in these modes. You could still have the "volume" mode, but you won't be able to use it for *anything* expect volume up and down. So be aware that the use of syntax [] is a bit misleading hereabove.
|
||||
|
||||
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 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
|
||||
```json
|
||||
```
|
||||
[
|
||||
{"gpio":<num>,
|
||||
"type":"BUTTON_LOW | BUTTON_HIGH",
|
||||
{"gpio":<num>,
|
||||
"type":"BUTTON_LOW | BUTTON_HIGH",
|
||||
"pull":[true|false],
|
||||
"long_press":<ms>,
|
||||
"long_press":<ms>,
|
||||
"debounce":<ms>,
|
||||
"shifter_gpio":<-1|num>,
|
||||
"normal": {"pressed":"<action>","released":"<action>"},
|
||||
@@ -407,22 +218,19 @@ Where (all parameters are optionals except gpio)
|
||||
- "shifted": action to take when a button is pressed/released and shifted (see above/below)
|
||||
- "longshifted": action to take when a button is long-pressed/released and shifted (see above/below)
|
||||
|
||||
Where `<action>` is either the name of another configuration to load (remap) or one amongst
|
||||
Where \<action\> is either the name of another configuration to load (remap) or one amongst
|
||||
|
||||
```
|
||||
ACTRLS_NONE, ACTRLS_POWER, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY,
|
||||
ACTRLS_NONE, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY,
|
||||
ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT,
|
||||
BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT,
|
||||
BCTRLS_PS1, BCTRLS_PS2, BCTRLS_PS3, BCTRLS_PS4, BCTRLS_PS5, BCTRLS_PS6, BCTRLS_PS7, BCTRLS_PS8, BCTRLS_PS9, BCTRLS_PS10,
|
||||
KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH,
|
||||
ACTRLS_SLEEP,
|
||||
BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT,
|
||||
KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH
|
||||
```
|
||||
Note that ACTRLS_SLEEP is not an actual button that can be sent to LMS, but it's a hook to activate deep sleep mode (see [Sleeping](#sleeping)).
|
||||
|
||||
|
||||
One you've created such a string, use it to fill a new NVS parameter with any name below 16(?) characters. You can have as many of these configs as you can. Then set the config parameter "actrls_config" with the name of your default config
|
||||
|
||||
For example a config named "buttons" :
|
||||
```json
|
||||
```
|
||||
[{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000,"normal":{"pressed":"ACTRLS_VOLDOWN"},"longpress":{"pressed":"buttons_remap"}},
|
||||
{"gpio":5,"type":"BUTTON_LOW","pull":true,"shifter_gpio":4,"normal":{"pressed":"ACTRLS_VOLUP"}, "shifted":{"pressed":"ACTRLS_TOGGLE"}}]
|
||||
```
|
||||
@@ -431,7 +239,7 @@ Defines two buttons
|
||||
- second on GPIO 5, active low. When pressed it triggers a volume up command. If first button is pressed together with this button, then a play/pause toggle command is generated.
|
||||
|
||||
While the config named "buttons_remap"
|
||||
```json
|
||||
```
|
||||
[{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000,"normal":{"pressed":"BCTRLS_DOWN"},"longpress":{"pressed":"buttons"}},
|
||||
{"gpio":5,"type":"BUTTON_LOW","pull":true,"shifter_gpio":4,"normal":{"pressed":"BCTRLS_UP"}}]
|
||||
```
|
||||
@@ -439,14 +247,10 @@ Defines two buttons
|
||||
- first on GPIO 4, active low. When pressed, it triggers a navigation down command. When pressed more than 1000ms, it changes the button configuration for the one described above
|
||||
- second on GPIO 5, active low. When pressed it triggers a navigation up command. That button, in that configuration, has no shift option
|
||||
|
||||
Below is a difficult but functional 2-buttons interface for your decoding pleasure:
|
||||
Below is a difficult but functional 2-buttons interface for your decoding pleasure
|
||||
|
||||
`actrls_config`:
|
||||
*buttons*
|
||||
```
|
||||
buttons
|
||||
```
|
||||
`buttons`:
|
||||
```json
|
||||
[{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000,
|
||||
"normal":{"pressed":"ACTRLS_VOLDOWN"},
|
||||
"longpress":{"pressed":"buttons_remap"}},
|
||||
@@ -456,8 +260,8 @@ buttons
|
||||
"longpress":{"pressed":"ACTRLS_NEXT"}}
|
||||
]
|
||||
```
|
||||
`buttons_remap`:
|
||||
```json
|
||||
*buttons_remap*
|
||||
```
|
||||
[{"gpio":4,"type":"BUTTON_LOW","pull":true,"long_press":1000,
|
||||
"normal":{"pressed":"BCTRLS_DOWN"},
|
||||
"longpress":{"pressed":"buttons"}},
|
||||
@@ -468,96 +272,19 @@ buttons
|
||||
"longshifted":{"pressed":"BCTRLS_LEFT"}}
|
||||
]
|
||||
```
|
||||
**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.
|
||||
<strong>IMPORTANT NOTE</strong>: 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.
|
||||
|
||||
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 longpress 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**
|
||||
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.
|
||||
|
||||
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**
|
||||
### Ethernet
|
||||
Wired ethernet is supported by esp32 with various options but squeezeESP32 is only supporting a Microchip LAN8720 with a RMII interface like [this](https://www.aliexpress.com/item/32858432526.html) or SPI-ethernet bridges like Davicom DM9051 [that](https://www.amazon.com/dp/B08JLFWX9Z) or W5500 like [this](https://www.aliexpress.com/item/32312441357.html).
|
||||
|
||||
**Note:** Touch buttons that can be find on some board like the LyraT V4.3 are not supported currently.
|
||||
|
||||
#### RMII (LAN8720)
|
||||
- RMII PHY wiring is fixed and can not be changed
|
||||
|
||||
| GPIO | RMII Signal | Notes |
|
||||
| ------ | ----------- | ------------ |
|
||||
| GPIO21 | TX_EN | EMAC_TX_EN |
|
||||
| GPIO19 | TX0 | EMAC_TXD0 |
|
||||
| GPIO22 | TX1 | EMAC_TXD1 |
|
||||
| GPIO25 | RX0 | EMAC_RXD0 |
|
||||
| GPIO26 | RX1 | EMAC_RXD1 |
|
||||
| GPIO27 | CRS_DV | EMAC_RX_DRV |
|
||||
| GPIO0 | REF_CLK | 50MHz clock |
|
||||
|
||||
- SMI (Serial Management Interface) wiring is not fixed and you can change it either in the configuration or using "eth_config" parameter with the following syntax:
|
||||
```
|
||||
model=lan8720,mdc=<gpio>,mdio=<gpio>[,rst=<gpio>]
|
||||
```
|
||||
Connecting a reset pin for the LAN8720 is optional but recommended to avoid that GPIO0 (50MHz input clock) locks the esp32 in download mode at boot time.
|
||||
- Clock
|
||||
|
||||
The APLL of the esp32 is required for the audio codec, so we **need** a LAN8720 that provides a 50MHz clock. That clock **must** be connected to GPIO0, there is no alternative. This means that if your DAC requires an MCLK, you need a recent build (later than mid-2023) to be able to select either GPIO 1 or 2.
|
||||
|
||||
#### SPI (DM9051 or W5500)
|
||||
Ethernet over SPI is supported as well and requires less GPIOs but is obvsiously slower. SPI is the shared bus set with [spi_config](#spi). The "eth_config" parameter syntax becomes:
|
||||
```
|
||||
model=dm9051|w5500,cs=<gpio>,speed=<clk_in_Hz>,intr=<gpio>[,rst=<gpio>]
|
||||
```
|
||||
- To use the system SPI, shared with display (see spi_config) "host" must be set to -1. Any other value will reserve the SPI interface (careful of conflict with spi_config). The default "host" is 2 to avoid conflicting wiht default "spi_config" settings.
|
||||
- When not using system SPI, "mosi" for data out, "miso" for data in and "clk" **must** be set
|
||||
- The esp32 has a special I/O multiplexer for faster speed (up to 80 MHz) but that requires using specific GPIOs, which depends on SPI bus (See [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html) for more details)
|
||||
|
||||
| Pin Name | SPI1 | SPI2 |
|
||||
| -------- | ---- | ---- |
|
||||
| CS | 15 | 5 |
|
||||
| SCLK | 14 | 18 |
|
||||
| MISO | 12 | 19 |
|
||||
| MOSI | 13 | 23 |
|
||||
|
||||
### Battery / ADC
|
||||
The NVS parameter "bat_config" sets the ADC1 channel used to measure battery/DC voltage. The "atten" value attenuates the input voltage to the ADC input (the read value maintains a 0-1V rage) where: 0=no attenuation(0..800mV), 1=2.5dB attenuation(0..1.1V), 2=6dB attenuation(0..1.35V), 3=11dB attenuation(0..2.6V). Scale is a float ratio applied to every sample of the 12 bits ADC. A measure is taken every 10s and an average is made every 5 minutes (not a sliding window). Syntax is
|
||||
The NVS parameter "bat_config" sets the ADC1 channel used to measure battery/DC voltage. Scale is a float ratio applied to every sample of the 12 bits ADC. A measure is taken every 10s and an average is made every 5 minutes (not a sliding window). Syntax is
|
||||
```
|
||||
channel=0..7,scale=<scale>,cells=<1..3>[,atten=<0|1|2|3>]
|
||||
channel=0..7,scale=<scale>,cells=<2|3>
|
||||
```
|
||||
NB: Set parameter to empty to disable battery reading. For named configurations (SqueezeAMP, Muse ...), this is ignored (except for SqueezeAMP where number of cells is required)
|
||||
|
||||
### Sleeping
|
||||
The esp32 can be put in deep sleep mode to save some power. How much really depends on the connected periperals, so best is to do your own measures. Waking-up from deep sleep is the equivalent of a reboot, but as the chip takes a few seconds to connect, it's still an efficient process.
|
||||
|
||||
The esp32 can enter deep sleep after an audio inactivity timeout, after a button has been pressed, after a GPIO is set to a given level (there is a subtle difference, see below) or if the battery reaches a threashold. It wakes up only on some GPIO events. Note that *all* GPIO are isolated when sleeping (unless they are set with the `rtc`option) so you can not assume anything about their value, except that they will not drain current. The `rtc` option allows to keep some GPIO (from the RTC domain only) either pulled up or down. This can be useful if you want to keep some periperal active, for example a GPIO expander whose interrupt will be used to wake-up the system.
|
||||
|
||||
The NVS parameter `sleep_config` is mostly used for setting sleep conditions
|
||||
```
|
||||
[delay=<mins>][,sleep=<gpio>[:0|1]][,wake=<gpio>[:0|1][|<gpio>[:0|1]...][,rtc=<gpio>[:0|1][|<gpio>[:0|1]...][,batt=<voltage>][,spurious=<mins>]
|
||||
```
|
||||
- delay: inactivity in **minutes** before going to sleep
|
||||
- spurious: when using IR, wake-up can be triggered by any activity on the allocated GPIO, hence other remotes may cause unwanted wake-up. This sets (in **minutes** - default is 1) an inactivity delay after which sleep resumes.
|
||||
- sleep: GPIO that will put the system into sleep and it can be a level 0 or 1.
|
||||
- wake: **list** of GPIOs that with cause it to wake up (reboot) with their respective values. In such list, GPIO's are separated by an actual '|'.
|
||||
- batt: threshold in **volts** under which the system will enter into sleep.
|
||||
|
||||
The battery voltage is measured every 10 seconds and 30 values are averaged before producing a result. The result must be 3 times below the threshold to enter sleep, so it takes a total of 10\*30\*3 = 15 minutes.
|
||||
|
||||
Be mindful that if the same GPIO is used to go to sleep and wakeup with the *same* level (in other word it's a transition/edge that triggers the action) the above will not work and the esp32 will immediately restart. In such case, you case use a button definition. The benefit of buttons is that not only can you re-use one actual button (e.g. 'stop') to make it the sleep trigger (using a long-press or a shift-press) but by selecting the ACTRLS_SLEEP action upon 'release', you can got to sleep upon release (1-0-1 transition) but also wake up upon another press (0 level applied on GPIO) because you only go to sleep *after* the GPIO returned to 1.
|
||||
|
||||
Please see [buttons](#buttons) for detailed syntax.
|
||||
|
||||
The option to use multiple GPIOs is very limited on esp32 and the esp-idf 4.3.x we are using: it is only possible to wake-up when **any** of the defined GPIO is set to 1. The fact that you can specify different levels in the wake list is irrelevant for now, it's just a provision for future upgrades to more recent versions of esp-idf.
|
||||
|
||||
**Only the following GPIOs can be used to wake-up the esp32**
|
||||
- ESP32: 0, 2, 4, 12-15, 25-27, 32-39;
|
||||
- ESP32-S3: 0-21.
|
||||
|
||||
Some have asked for a soft power on/off option. Although this is not built-in, it's easy to create yours as long as the regulator/power supply of the board can be controlled by Vcc or GND. Depending on how it is active, add a pull-up/down resistor to the regulator's control and connect it also to one GPIO of the esp32. Then using set_GPIO, set that GPIO to Vcc or GND. Use a hardware button that forces the regulator on with a pull- up/down and once the esp32 has booted, it will force the GPIO to the desired value maintaining the board on by software. To power it off by software, just use the deep sleep option which will suspend all GPIO hence switching off the regulator.
|
||||
|
||||
# Software configuration
|
||||
|
||||
NB: Set parameter to empty to disable battery reading. For well-known configuration, this is ignored (except for SqueezeAMP where number of cells is required)
|
||||
# Configuration
|
||||
## Setup WiFi
|
||||
- Boot the esp, look for a new wifi access point showing up and connect to it. Default build ssid and passwords are "squeezelite"/"squeezelite".
|
||||
- Once connected, navigate to 192.168.4.1
|
||||
@@ -566,6 +293,7 @@ Some have asked for a soft power on/off option. Although this is not built-in, i
|
||||
- Once connection is established, note down the address the device received; this is the address you will use to configure it going forward
|
||||
|
||||
## Setup squeezelite command line (optional)
|
||||
|
||||
At this point, the device should have disabled its built-in access point and should be connected to a known WiFi network.
|
||||
- navigate to the address that was noted in step #1
|
||||
- Using the list of predefined options, choose the mode in which you want squeezelite to start
|
||||
@@ -577,16 +305,8 @@ At this point, the device should have disabled its built-in access point and sho
|
||||
- The toggle switch should be set to 'ON' to ensure that squeezelite is active after booting (you might have to fiddle with it a few times)
|
||||
- You can enable accessto NVS parameters under 'credits'
|
||||
|
||||
## Spotify
|
||||
By default, SqueezeESP32 will use ZeroConf to advertise its Spotify capabilties. This means that until at least one local Spotify Connect application controllers discovers and connects to it, SqueezeESP32 will not be registered to Spotify servers. As a consequence, Spotify's WebAPI will not be able to see it (for example, Home Assistant services will miss it). Once you are connected to it using for example Spotify Desktop app, it will be registered and displayed everywhere.
|
||||
|
||||
If you want the player to be registered at start-up, you need to disable the ZeroConf option using the WebUI or `cspot_config::ZeroConf`. In that mode, the first time you run SqueezeESP32, it will be in ZeroConf mode and when you connect to it using a controller for the firt time, it receives and store credentials that will be used next time (after reboot).
|
||||
|
||||
Set ZeroConf to 1 will always force ZeroConf mode to be used.
|
||||
|
||||
The ZeroConf mode consumes less memory as it uses the built-in HTTP and mDNS servers to broadcast its capabilities. A Spotify controller will then discover these and trigger the SqueezeESP32 Spotify stack (cspot) to start. When the controller disconnects, the stack is shut down. In non-ZeroConf mode, the stack starts immediately (providing stored credentials are valid) and always run - a disconnect will not shut it down.
|
||||
|
||||
## Monitor
|
||||
|
||||
In addition of the esp-idf serial link monitor option, you can also enable a telnet server (see NVS parameters) where you'll have access to a ton of logs of what's happening inside the WROVER.
|
||||
|
||||
## Update Squeezelite
|
||||
@@ -611,87 +331,103 @@ For example, so use a BT speaker named MySpeaker, accept audio up to 192kHz and
|
||||
|
||||
squeezelite -o "BT -n 'BT <sinkname>'" -b 500:2000 -R -u m -Z 192000 -r "44100-44100"
|
||||
|
||||
See squeezelite command line, but keys options are
|
||||
See squeezlite command line, but keys options are
|
||||
|
||||
- Z <rate> : tell LMS what is the max sample rate supported before LMS resamples
|
||||
- R (see above)
|
||||
- r "<minrate>-<maxrate>"
|
||||
- C <sec> : set timeout to switch off amp gpio
|
||||
- W : activate WAV and AIFF header parsing
|
||||
- s <name>|-disable: connect to a specific server. Use -disable to not search for any server
|
||||
|
||||
**There is a safety feature to protect against WiFi/LMS connection loss that forces a reboot every few minutes when there is no LMS server detected. In case you don't want to use LMS at all, please set the server name to "-disable" on squeezelite command line ("-s -disable")**
|
||||
|
||||
# Building everything yourself
|
||||
|
||||
## Setting up ESP-IDF
|
||||
|
||||
### Docker
|
||||
A simple alternative to building the project's binaries is to leverage the same docker image that is being used on the GitHub Actions to build our releases. The instructions below assume that you have cloned the squeezelite-esp32 code that you want to build locally and that you have opened a command line/bash session in the folder that contains the code.
|
||||
Pull the most recent docker image for the environment:
|
||||
You can use docker to build squeezelite-esp32 (optional)
|
||||
First you need to build the Docker container:
|
||||
```
|
||||
docker pull sle118/squeezelite-esp32-idfv435
|
||||
docker build -t esp-idf .
|
||||
```
|
||||
Then run the container interactively :
|
||||
Then you need to run the container:
|
||||
```
|
||||
for windows:
|
||||
docker run -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv435
|
||||
for linux:
|
||||
docker run -it -v `pwd`:/workspace/squeezelite-esp32 sle118/squeezelite-esp32-idfv435
|
||||
docker run -i -t -v `pwd`:/workspace/squeezelite-esp32 esp-idf
|
||||
```
|
||||
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.
|
||||
The above command will mount this repo into the docker container and start a bash terminal
|
||||
for you to then follow the below build steps
|
||||
|
||||
### Manual Install of ESP-IDF
|
||||
First you need git and python (e.g 3.10.x), install these and let it add to system path.
|
||||
<strong>Currently the master branch of this project requires this [IDF](https://github.com/espressif/esp-idf/tree/28f1cdf5ed7149d146ad5019c265c8bc3bfa2ac9) with gcc 5.2 (toolschain dated 20181001)
|
||||
If you want to use a more recent version of gcc and IDF (4.0 stable), move to cmake-master branch</strong>
|
||||
|
||||
**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.
|
||||
```
|
||||
$ sudo pip3 install protobuf grpcio-tools
|
||||
```
|
||||
NB: I need to check on a fresh installation, but you might also require "protoc". You should do that within the esp32 local Python environment.
|
||||
|
||||
Don't forget to choose one of the config files in build_scripts/ and rename it sdkconfig.defaults or sdkconfig as many important WiFi/BT options are set there. **The codecs libraries will not be rebuilt by these scripts (it's a tedious process - see below)**
|
||||
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/
|
||||
And then copying the i2s.c patch file from this repo over to the esp-idf folder
|
||||
You also need to use esp-dsp recent version or at least make sure you have this patch https://github.com/espressif/esp-dsp/pull/12/commits/8b082c1071497d49346ee6ed55351470c1cb4264. As of this writing (08.2020), espressif has patched esp-dsp so this is no more needed
|
||||
|
||||
## Building Squeezelite-esp32
|
||||
Don't forget the to choose one of the config files in build_scripts/ and rename it sdkconfig.defaults or sdkconfig as many important WiFi/BT options are set there. The codecs libraries will not be rebuilt by these scripts (it's a tedious process - see below)
|
||||
### Usng make (deprecated)
|
||||
MOST IMPORTANT: create the right default config file
|
||||
- make defconfig
|
||||
(Note: You can also copy over config files from the build-scripts folder to ./sdkconfig)
|
||||
Then adapt the config file to your wifi/BT/I2C device (can also be done on the command line)
|
||||
- make menuconfig
|
||||
Then
|
||||
|
||||
Create and tweak your config using `idf.py menuconfig` then build binaries using `idf.py all`. It will build the recovery and the application (squeezelite). then use `idf.py flash` to write everything. Otherwise, if you just want to download squeezelite, do (assuming you have set ESPPORT (e.g. COM10) and ESPBAUD (e.g. 921600)
|
||||
```
|
||||
<path_to_your_python>/python.exe <path_to_your_esptool>/esptool.py -p %ESPPORT% -b %ESPBAUD% --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x150000 build/squeezelite.bin
|
||||
# Build recovery.bin, bootloader.bin, ota_data_initial.bin, partitions.bin
|
||||
# force appropriate rebuild by touching all the files which may have a RECOVERY_APPLICATION specific source compile logic
|
||||
find . \( -name "*.cpp" -o -name "*.c" -o -name "*.h" \) -type f -print0 | xargs -0 grep -l "RECOVERY_APPLICATION" | xargs touch
|
||||
export PROJECT_NAME="recovery"
|
||||
make -j4 all EXTRA_CPPFLAGS='-DRECOVERY_APPLICATION=1'
|
||||
make flash
|
||||
#
|
||||
# Build squeezelite.bin
|
||||
# Now force a rebuild by touching all the files which may have a RECOVERY_APPLICATION specific source compile logic
|
||||
find . \( -name "*.cpp" -o -name "*.c" -o -name "*.h" \) -type f -print0 | xargs -0 grep -l "RECOVERY_APPLICATION" | xargs touch
|
||||
export PROJECT_NAME="squeezelite"
|
||||
make -j4 app EXTRA_CPPFLAGS='-DRECOVERY_APPLICATION=0'
|
||||
python ${IDF_PATH}/components/esptool_py/esptool/esptool.py --chip esp32 --port ${ESPPORT} --baud ${ESPBAUD} --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0x150000 ./build/squeezelite.bin
|
||||
# monitor serial output
|
||||
make monitor
|
||||
|
||||
```
|
||||
Use `idf.py monitor` to monitor the application (see esp-idf documentation)
|
||||
|
||||
Note: You can use `idf.py build -DDEPTH=32` to build the 32 bits version and add the `-DVERSION=<your_version>` to add a custom version name (it will be 0.0-<your_version>). If you want to change the whole version string, see squeezelite.h. You can also disable the SBR extension of AAC codecs as it consumes a lot of CPU and might overload the esp32. Use `-DAAC_DISABLE_SBR=1` for that
|
||||
|
||||
If you have already cloned the repository and you are getting compile errors on one of the submodules (e.g. telnet), run the following git command in the root of the repository location: `git submodule update --init --recursive`
|
||||
|
||||
### Rebuild codecs (highly recommended to NOT try that)
|
||||
You can also manually download the recovery & initial boot
|
||||
```
|
||||
python ${IDF_PATH}/components/esptool_py/esptool/esptool.py --chip esp32 --port ${ESPPORT} --baud ${ESPBAUD} --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xd000 ./build/ota_data_initial.bin 0x1000 ./build/bootloader/bootloader.bin 0x10000 ./build/recovery.bin 0x8000 ./build/partitions.bin
|
||||
```
|
||||
### Using cmake
|
||||
Create you config using 'idf.py menuconfig' then build binaries using 'idf.py all'. It will build the recovery and the application (squeezelite) itself. See the recommended command to upload everything. Otherwise, if you just want to download squeezelite, do
|
||||
```
|
||||
python.exe <idf_path>\components\esptool_py\esptool\esptool.py -p COM<n> -b 921600 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x150000 build\squeezelite.bin
|
||||
```
|
||||
Use 'idf monitor' to monitor the application (see esp-idf documentation)
|
||||
## Additional misc notes to do you build (kitchen sink)
|
||||
- as of this writing, ESP-IDF has a bug int he way the PLL values are calculated for i2s, so you *must* use the i2s.c file in the patch directory
|
||||
- for codecs libraries, add -mlongcalls if you want to rebuild them, but you should not (use the provided ones in codecs/lib). if you really want to rebuild them, open an issue
|
||||
- libmad, libflac (no esp's version), libvorbis (tremor - not esp's version), alac work
|
||||
- libfaad does not really support real time, but if you want to try (but using helixaac is a better option)
|
||||
- libfaad does not really support real time, but if you want to try
|
||||
- -O3 -DFIXED_POINT -DSMALL_STACK
|
||||
- change ac_link in configure and case ac_files, remove ''
|
||||
- compiler but in cfft.c and cffti1, must disable optimization using
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("O0")
|
||||
#pragma GCC pop_options
|
||||
- better use helixaac
|
||||
- opus & opusfile
|
||||
- for opus, the ESP-provided library seems to work, but opusfile is still needed
|
||||
- per mad & few others, edit configure and change $ac_link to add -c (faking link)
|
||||
- change ac_files to remove ''
|
||||
- add DEPS_CFLAGS and DEPS_LIBS to avoid pkg-config to be required
|
||||
- stack consumption can be very high with some codec variants, so set NONTHREADSAFE_PSEUDOSTACK and GLOBAL_STACK_SIZE=48000 and unset VAR_ARRAYS in config.h
|
||||
- libmad has been patched to avoid using a lot of stack and is not provided here. There is an issue with sync detection in 1.15.1b from where the original stack patch was done but since a few fixes have been made wrt sync detection. This 1.15.1b-10 found on debian fixes the issue where mad thinks it has reached sync but has not and so returns a wrong sample rate. It comes at the expense of 8KB (!) of code where a simple check in squeezelite/mad.c that next_frame[0] is 0xff and next_frame[1] & 0xf0 is 0xf0 does the trick ...
|
||||
|
||||
# Hardware tips
|
||||
There is a possibility to have a software on/off where a temporary switch can power-up the esp32 which then will auto-sustain its power. Depending on the selected hardware, it a can also include a power-off by using a long press on the same button.
|
||||
|
||||
The auto-power is simply acheived by using `setGPIO` and forcing a GPIO to Vcc or GND and the sustain on/off requires a button creation whose longpress is an ACTRLS_SLEEP action (see also the [Sleeping](#sleeping) section). Credits [Renber78](http://github.com/Renber78) for schedmatics below
|
||||
|
||||

|
||||
|
||||
# Footnotes
|
||||
- stack consumption can be very high with some codec variants, so set NONTHREADSAFE_PSEUDOSTACK and GLOBAL_STACK_SIZE=32000 and unset VAR_ARRAYS in config.h
|
||||
- set IDF_PATH=/home/esp-idf
|
||||
- other compiler #define
|
||||
- use no resampling or set RESAMPLE (soxr) or set RESAMPLE16 for fast fixed 16 bits resampling
|
||||
- use LOOPBACK (mandatory)
|
||||
- use BYTES_PER_FRAME=4 (8 is not fully functionnal)
|
||||
- LINKALL (mandatory)
|
||||
- NO_FAAD unless you want to us faad, which currently overloads the CPU
|
||||
- TREMOR_ONLY (mandatory)
|
||||
- better use helixaac
|
||||
- When initially cloning the repo, make sure you do it recursively. For example:
|
||||
- git clone --recursive https://github.com/sle118/squeezelite-esp32.git
|
||||
- If you have already cloned the repository and you are getting compile errors on one of the submodules (e.g. telnet), run the following git command in the root of the repository location
|
||||
- git submodule update --init --recursive
|
||||
|
||||
BIN
Soft Power.png
BIN
Soft Power.png
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
3
TODO
3
TODO
@@ -1,5 +1,4 @@
|
||||
- in squeezelite some buffers (stream, output, header, recv) are allocated
|
||||
although they are almost static (expect output). This creates a risk of
|
||||
memory fragmentation, especially because the large output is re-allocated for
|
||||
AirPlay
|
||||
- libflac in lpc.c can be unrolled - that gains 43k of code, at the expense of 4% CPU
|
||||
AirPlay
|
||||
65
alltags.txt
Normal file
65
alltags.txt
Normal file
@@ -0,0 +1,65 @@
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.15
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.20
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.47
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.49
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.50
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.51
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.52
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.53
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.54
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.55
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.59
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.60
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.61
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.62
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.63
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.64
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.65
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.66
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/I2S-4MFlash-v0.1.67
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/SqueezeAmp-v0.1.13
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/SqueezeAmp-v0.1.14
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/SqueezeAmp-v0.1.15
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/SqueezeAmp-v0.1.20
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/WiFi-Manager/SqueezeAmp-v0.1.66
|
||||
3bd886b8dff0fb5bc59079e83f1d283097a14697 refs/tags/v0.1.12-I2S-4MFlash
|
||||
3bd886b8dff0fb5bc59079e83f1d283097a14697 refs/tags/v0.1.12-SqueezeAmp
|
||||
3bd886b8dff0fb5bc59079e83f1d283097a14697 refs/tags/v0.1.16-I2S-4MFlash
|
||||
3bd886b8dff0fb5bc59079e83f1d283097a14697 refs/tags/v0.1.16-SqueezeAmp
|
||||
d9c6c78df2f3ba49d74d91cf246f300a881af742 refs/tags/v0.1.44-I2S-4MFlash
|
||||
d9c6c78df2f3ba49d74d91cf246f300a881af742 refs/tags/v0.1.44-SqueezeAmp
|
||||
d9c6c78df2f3ba49d74d91cf246f300a881af742 refs/tags/v0.1.45-I2S-4MFlash
|
||||
d9c6c78df2f3ba49d74d91cf246f300a881af742 refs/tags/v0.1.45-SqueezeAmp
|
||||
d9c6c78df2f3ba49d74d91cf246f300a881af742 refs/tags/v0.1.46-I2S-4MFlash
|
||||
d9c6c78df2f3ba49d74d91cf246f300a881af742 refs/tags/v0.1.46-SqueezeAmp
|
||||
d9c6c78df2f3ba49d74d91cf246f300a881af742 refs/tags/v0.1.47-I2S-4MFlash
|
||||
d9c6c78df2f3ba49d74d91cf246f300a881af742 refs/tags/v0.1.47-SqueezeAmp
|
||||
3bd886b8dff0fb5bc59079e83f1d283097a14697 refs/tags/v0.1.5-I2S-4MFlash
|
||||
3bd886b8dff0fb5bc59079e83f1d283097a14697 refs/tags/v0.1.5-SqueezeAmp
|
||||
c34cf06be18ea4ab14ce28d77e1d48d0a1bb70f7 refs/tags/v0.1.50-I2S-4MFlash
|
||||
c34cf06be18ea4ab14ce28d77e1d48d0a1bb70f7 refs/tags/v0.1.50-SqueezeAmp
|
||||
c34cf06be18ea4ab14ce28d77e1d48d0a1bb70f7 refs/tags/v0.1.51-I2S-4MFlash
|
||||
c34cf06be18ea4ab14ce28d77e1d48d0a1bb70f7 refs/tags/v0.1.51-SqueezeAmp
|
||||
20edae43287b4c2d8942ea4263ccf9547f310946 refs/tags/v0.1.52-I2S-4MFlash
|
||||
20edae43287b4c2d8942ea4263ccf9547f310946 refs/tags/v0.1.52-SqueezeAmp
|
||||
964bb4d57d35bca06badfb504534b42e9b3b8678 refs/tags/v0.1.53-I2S-4MFlash
|
||||
964bb4d57d35bca06badfb504534b42e9b3b8678 refs/tags/v0.1.53-SqueezeAmp
|
||||
71531bcdc20d7c7da254699855eb2e1e7b2bd48f refs/tags/v0.1.54-I2S-4MFlash
|
||||
71531bcdc20d7c7da254699855eb2e1e7b2bd48f refs/tags/v0.1.54-SqueezeAmp
|
||||
9c56cfb1d05862bca5763b3fbe9911b4bab9619a refs/tags/v0.1.55-I2S-4MFlash
|
||||
9c56cfb1d05862bca5763b3fbe9911b4bab9619a refs/tags/v0.1.55-SqueezeAmp
|
||||
53369475dc85471a4d7f2d78c62f37fcd7f6e3da refs/tags/v0.1.57-I2S-4MFlash
|
||||
53369475dc85471a4d7f2d78c62f37fcd7f6e3da refs/tags/v0.1.57-SqueezeAmp
|
||||
3bd886b8dff0fb5bc59079e83f1d283097a14697 refs/tags/v0.1.6-I2S-4MFlash
|
||||
3bd886b8dff0fb5bc59079e83f1d283097a14697 refs/tags/v0.1.6-SqueezeAmp
|
||||
eef9ae969cdfd1a62d7057d8edf2c31af60804f3 refs/tags/v0.1.67-WiFi-Manager/I2S-4MFlash
|
||||
2cf87d5943caa0d0b15c8692482ff72308c0c0a8 refs/tags/v0.1.71-I2S-4MFlash
|
||||
2cf87d5943caa0d0b15c8692482ff72308c0c0a8 refs/tags/v0.1.71-SqueezeAmp
|
||||
2cf87d5943caa0d0b15c8692482ff72308c0c0a8 refs/tags/v0.1.72-I2S-4MFlash
|
||||
2cf87d5943caa0d0b15c8692482ff72308c0c0a8 refs/tags/v0.1.72-SqueezeAmp
|
||||
2cf87d5943caa0d0b15c8692482ff72308c0c0a8 refs/tags/v0.1.73-I2S-4MFlash
|
||||
2cf87d5943caa0d0b15c8692482ff72308c0c0a8 refs/tags/v0.1.73-SqueezeAmp
|
||||
2cf87d5943caa0d0b15c8692482ff72308c0c0a8 refs/tags/v0.1.74-I2S-4MFlash
|
||||
2cf87d5943caa0d0b15c8692482ff72308c0c0a8 refs/tags/v0.1.74-SqueezeAmp
|
||||
3bd886b8dff0fb5bc59079e83f1d283097a14697 refs/tags/v0.1.9-I2S-4MFlash
|
||||
3bd886b8dff0fb5bc59079e83f1d283097a14697 refs/tags/v0.1.9-SqueezeAmp
|
||||
1158
build-scripts/ESP32-A1S-sdkconfig.defaults
Normal file
1158
build-scripts/ESP32-A1S-sdkconfig.defaults
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1165
build-scripts/NonOTA-I2S-4MFlash-sdkconfig.defaults
Normal file
1165
build-scripts/NonOTA-I2S-4MFlash-sdkconfig.defaults
Normal file
File diff suppressed because it is too large
Load Diff
1164
build-scripts/NonOTA-SqueezeAmp-sdkconfig.defaults
Normal file
1164
build-scripts/NonOTA-SqueezeAmp-sdkconfig.defaults
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1158
build-scripts/SqueezeAmp4MBFlash-sdkconfig.defaults
Normal file
1158
build-scripts/SqueezeAmp4MBFlash-sdkconfig.defaults
Normal file
File diff suppressed because it is too large
Load Diff
1152
build-scripts/SqueezeAmp8MBFlash-sdkconfig.defaults
Normal file
1152
build-scripts/SqueezeAmp8MBFlash-sdkconfig.defaults
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,47 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
|
||||
echo "Build process started"
|
||||
echo "Setting up build name and build number"
|
||||
if [ -z "${TARGET_BUILD_NAME}" ]
|
||||
then
|
||||
export TARGET_BUILD_NAME="I2S-4MFlash"
|
||||
echo "TARGET_BUILD_NAME is not set. Defaulting to ${TARGET_BUILD_NAME}"
|
||||
fi
|
||||
if [ -z "${BUILD_NUMBER}" ]
|
||||
then
|
||||
export BUILD_NUMBER="500"
|
||||
echo "BUILD_NUMBER is not set. Defaulting to ${BUILD_NUMBER}"
|
||||
fi
|
||||
if [ -z "$DEPTH" ]
|
||||
then
|
||||
export DEPTH="16"
|
||||
echo "DEPTH is not set. Defaulting to ${DEPTH}"
|
||||
fi
|
||||
if [ -z "$tag" ]
|
||||
then
|
||||
branch_name="$(git rev-parse --abbrev-ref HEAD)"
|
||||
branch_name="${branch_name//[^a-zA-Z0-9\-~!@_\.]/}"
|
||||
app_name="${TARGET_BUILD_NAME}.${DEPTH}.dev-$(git log --pretty=format:'%h' --max-count=1).${branch_name}"
|
||||
echo "${app_name}">version.txt
|
||||
echo "app_name is not set. Defaulting to ${app_name}"
|
||||
else
|
||||
echo "${tag}" >version.txt
|
||||
fi
|
||||
|
||||
echo "Copying target sdkconfig"
|
||||
cp build-scripts/${TARGET_BUILD_NAME}-sdkconfig.defaults sdkconfig
|
||||
echo "Building project"
|
||||
idf.py build -DDEPTH=${DEPTH} -DBUILD_NUMBER=${BUILD_NUMBER}-${DEPTH}
|
||||
echo "Generating size report"
|
||||
idf.py size-components >build/size_components.txt
|
||||
idf.py size-components-squeezelite build/size_components_squeezelite.txt
|
||||
if [ -z "${artifact_file_name}" ]
|
||||
then
|
||||
echo "No artifact file name set. Will not generate zip file."
|
||||
else
|
||||
echo "Generating build artifact zip file"
|
||||
zip -r build_output.zip build
|
||||
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
|
||||
@@ -1,113 +0,0 @@
|
||||
#!/bin/bash
|
||||
echo
|
||||
echo =================================================================
|
||||
echo Build flash command
|
||||
echo =================================================================
|
||||
# Location of partitions.csv relative to this script
|
||||
partitionsCsv="../partitions.csv"
|
||||
|
||||
# File to output readme instructions to
|
||||
outputReadme="./flash_cmd.txt"
|
||||
|
||||
# File to output bash script to
|
||||
outputBashScript="./writeSequeezeEsp.sh"
|
||||
|
||||
# File to output bat script to
|
||||
outputBatScript="./writeSequeezeEsp.bat"
|
||||
|
||||
# The name of partitions to ignore from partitions.csv
|
||||
paritionsToIgnore=(
|
||||
"nvs"
|
||||
"phy_init"
|
||||
"storage"
|
||||
"coredump"
|
||||
"settings"
|
||||
)
|
||||
|
||||
# Function that maps partition name to actual bin file
|
||||
# defaults to "[PARTION_NAME_FROM_CSV].bin"
|
||||
function partitionNameToBinFile {
|
||||
if [[ "$1" == "otadata" ]]; then
|
||||
echo "ota_data_initial.bin"
|
||||
elif [[ "$1" == "ota_0" || "$1" == "factory" ]]; then
|
||||
echo "squeezelite.bin"
|
||||
else
|
||||
echo $1.bin
|
||||
fi
|
||||
}
|
||||
|
||||
# write parameters for esptool.py
|
||||
writeParameters="$writeParameters write_flash"
|
||||
writeParameters="$writeParameters --flash_mode dio --flash_freq 80m --flash_size detect"
|
||||
|
||||
# bootloader.bin and partitions.bin not in partitions.csv so manually add here
|
||||
partitionsParameters=" 0x1000 bootloader/bootloader.bin"
|
||||
partitionsParameters="$partitionsParameters 0x8000 partitions.bin"
|
||||
|
||||
# ==============================================================================
|
||||
|
||||
# Loop over partitions.csv and add partition bins and offsets to partitionsParameters
|
||||
|
||||
for line in $($IDF_PATH/components/partition_table/gen_esp32part.py --quiet build/partitions.bin | grep '^[^#]')
|
||||
do
|
||||
partitionName=$(echo $line | awk -F',' '{printf "%s", $1}' )
|
||||
partitionOffset=$(echo $line |awk -F',' '{printf "%s", $4}' )
|
||||
partitionFile=$(partitionNameToBinFile $partitionName)
|
||||
|
||||
if [[ " ${paritionsToIgnore[@]} " =~ " ${partitionName} " ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
partitionsParameters="$partitionsParameters $partitionOffset $partitionFile"
|
||||
echo "$partitionsParameters"
|
||||
|
||||
done
|
||||
|
||||
# Write README Instructions
|
||||
if [ ! -f "$outputReadme" ]; then
|
||||
touch $outputReadme
|
||||
fi
|
||||
|
||||
echo "" >> $outputReadme
|
||||
echo "====LINUX====" >> $outputReadme
|
||||
echo "To flash sequeezelite run the following script:" >> $outputReadme
|
||||
echo "$outputBashScript [PORT_HERE] [BAUD_RATE]" >> $outputReadme
|
||||
echo "e.g. $outputBashScript /dev/ttyUSB0 115200" >> $outputReadme
|
||||
echo "" >> $outputReadme
|
||||
echo "====WINDOWS====" >> $outputReadme
|
||||
echo "To flash sequeezelite run the following script:" >> $outputReadme
|
||||
echo "$outputBatScript [PORT_HERE] [BAUD_RATE]" >> $outputReadme
|
||||
echo "e.g. $outputBatScript COM11 115200" >> $outputReadme
|
||||
echo "" >> $outputReadme
|
||||
echo "If you don't know how to run the BAT file with arguments then you can" >> $outputReadme
|
||||
echo "edit the bat file in Notepad. Open the file up and edit the following:" >> $outputReadme
|
||||
echo "Change 'set port=%1' to 'set port=[PORT_HERE]'. E.g. 'set port=COM11'" >> $outputReadme
|
||||
echo "Change 'set baud=%2' to 'set baud=[BAUD_RATE]'. E.g. 'set baud=115200'" >> $outputReadme
|
||||
echo "" >> $outputReadme
|
||||
echo "====MANUAL====" >> $outputReadme
|
||||
echo "Python esptool.py --port [PORT_HERE] --baud [BAUD_RATE] $writeParameters $partitionsParameters" >> $outputReadme
|
||||
|
||||
# Write Linux BASH File
|
||||
if [ ! -f "$outputBashScript" ]; then
|
||||
touch $outputBashScript
|
||||
fi
|
||||
|
||||
echo "#!/bin/bash" >> $outputBashScript
|
||||
echo >> $outputBashScript
|
||||
echo "port=\$1" >> $outputBashScript
|
||||
echo "baud=\$2" >> $outputBashScript
|
||||
linuxFlashCommand="Python esptool.py --port \$port --baud \$baud"
|
||||
echo "$linuxFlashCommand $writeParameters $partitionsParameters" >> $outputBashScript
|
||||
|
||||
# Write Windows BAT File
|
||||
if [ ! -f "$outputBatScript" ]; then
|
||||
touch $outputBatScript
|
||||
fi
|
||||
|
||||
echo "echo off" >> $outputBatScript
|
||||
echo "" >> $outputBatScript
|
||||
echo "set port=%1" >> $outputBatScript
|
||||
echo "set baud=%2" >> $outputBatScript
|
||||
windowsFlashCommand="Python esptool.py --port %port% --baud %baud%"
|
||||
echo "$windowsFlashCommand $writeParameters $partitionsParameters" >> $outputBatScript
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
if(IDF_TARGET STREQUAL esp32 AND IDF_VERSION_MAJOR EQUAL 4 AND IDF_VERSION_MINOR LESS 4)
|
||||
set(lib_dir ${build_dir}/esp-idf)
|
||||
set(driver esp32/i2s.c)
|
||||
string(REPLACE ".c" ".c.obj" driver_obj "${driver}")
|
||||
|
||||
idf_component_register( SRCS ${driver}
|
||||
REQUIRES driver
|
||||
INCLUDE_DIRS ${IDF_PATH}/components/driver
|
||||
PRIV_INCLUDE_DIRS ${IDF_PATH}/components/driver/include/driver
|
||||
)
|
||||
|
||||
# CMake is just a pile of crap
|
||||
message(STATUS "!! overriding ${driver} !!")
|
||||
message(STATUS "CAREFUL, LIBRARIES STRIPPING FROM DUPLICATED COMPONENTS DEPENDS ON THIS BEING REBUILD")
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${COMPONENT_LIB}
|
||||
PRE_LINK
|
||||
COMMAND xtensa-esp32-elf-ar -d ${lib_dir}/driver/libdriver.a ${driver_obj}
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
message(STATUS "==> NO OVERRIDE <==")
|
||||
endif()
|
||||
@@ -1,10 +0,0 @@
|
||||
idf_component_register( SRC_DIRS .
|
||||
INCLUDE_DIRS . inc
|
||||
)
|
||||
add_prebuilt_library(esp_processing lib/libesp_processing.a)
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE esp_processing)
|
||||
#target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--undefined=")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u pow")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u cos")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u sin")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u sqrt")
|
||||
@@ -1,3 +0,0 @@
|
||||
void dummy_obj() {
|
||||
return;
|
||||
}
|
||||
5
components/cmd_i2c/CMakeLists.txt
Normal file
5
components/cmd_i2c/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
set(COMPONENT_SRCS "cmd_i2ctools.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||
set(COMPONENT_REQUIRES console spi_flash)
|
||||
|
||||
register_component()
|
||||
919
components/cmd_i2c/cmd_i2ctools.c
Normal file
919
components/cmd_i2c/cmd_i2ctools.c
Normal file
@@ -0,0 +1,919 @@
|
||||
/* cmd_i2ctools.c
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include <stdio.h>
|
||||
#include "cmd_i2ctools.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_log.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "config.h"
|
||||
#include "accessors.h"
|
||||
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
|
||||
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
|
||||
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
||||
#define ACK_VAL 0x0 /*!< I2C ack value */
|
||||
#define NACK_VAL 0x1 /*!< I2C nack value */
|
||||
|
||||
static const char *TAG = "cmd_i2ctools";
|
||||
|
||||
static gpio_num_t i2c_gpio_sda = 19;
|
||||
static gpio_num_t i2c_gpio_scl = 18;
|
||||
static uint32_t i2c_frequency = 100000;
|
||||
#ifdef CONFIG_I2C_LOCKED
|
||||
static i2c_port_t i2c_port = I2C_NUM_1;
|
||||
#else
|
||||
static i2c_port_t i2c_port = I2C_NUM_0;
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
struct arg_int *chip_address;
|
||||
struct arg_int *register_address;
|
||||
struct arg_int *data_length;
|
||||
struct arg_end *end;
|
||||
} i2cget_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int *chip_address;
|
||||
struct arg_int *register_address;
|
||||
struct arg_int *data;
|
||||
struct arg_end *end;
|
||||
} i2cset_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int *chip_address;
|
||||
struct arg_int *size;
|
||||
struct arg_end *end;
|
||||
} i2cdump_args;
|
||||
|
||||
static struct {
|
||||
struct arg_lit *load;
|
||||
struct arg_int *port;
|
||||
struct arg_int *freq;
|
||||
struct arg_int *sda;
|
||||
struct arg_int *scl;
|
||||
struct arg_end *end;
|
||||
} i2cconfig_args;
|
||||
|
||||
|
||||
static struct {
|
||||
struct arg_int *port;
|
||||
struct arg_end *end;
|
||||
} i2cstop_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int *port;
|
||||
struct arg_end *end;
|
||||
} i2ccheck_args;
|
||||
|
||||
static struct {
|
||||
struct arg_lit *clear;
|
||||
struct arg_lit *hflip;
|
||||
struct arg_lit *vflip;
|
||||
struct arg_lit *rotate;
|
||||
struct arg_int *address;
|
||||
struct arg_int *width;
|
||||
struct arg_int *height;
|
||||
struct arg_str *name;
|
||||
struct arg_str *driver;
|
||||
struct arg_end *end;
|
||||
} i2cdisp_args;
|
||||
|
||||
|
||||
bool is_i2c_started(i2c_port_t port){
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_LOGD(TAG,"Determining if i2c is started on port %u", port);
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
ret = i2c_master_start(cmd);
|
||||
if(ret == ESP_OK){
|
||||
ret = i2c_master_write_byte(cmd,WRITE_BIT, ACK_CHECK_EN);
|
||||
}
|
||||
if(ret == ESP_OK){
|
||||
ret = i2c_master_stop(cmd);
|
||||
}
|
||||
if(ret == ESP_OK){
|
||||
ret = i2c_master_cmd_begin(port, cmd, 50 / portTICK_RATE_MS);
|
||||
}
|
||||
i2c_cmd_link_delete(cmd);
|
||||
ESP_LOGD(TAG,"i2c is %s. %s",ret!=ESP_ERR_INVALID_STATE?"started":"not started", esp_err_to_name(ret));
|
||||
return (ret!=ESP_ERR_INVALID_STATE);
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t address;
|
||||
char * description;
|
||||
} i2c_db_t;
|
||||
|
||||
|
||||
// the list was taken from https://i2cdevices.org/addresses
|
||||
// on 2020-01-16
|
||||
static const i2c_db_t i2c_db[] = {
|
||||
{ .address = 0x00, .description = "Unknown"},
|
||||
{ .address = 0x01, .description = "Unknown"},
|
||||
{ .address = 0x02, .description = "Unknown"},
|
||||
{ .address = 0x03, .description = "Unknown"},
|
||||
{ .address = 0x04, .description = "Unknown"},
|
||||
{ .address = 0x05, .description = "Unknown"},
|
||||
{ .address = 0x06, .description = "Unknown"},
|
||||
{ .address = 0x07, .description = "Unknown"},
|
||||
{ .address = 0x0c, .description = "AK8975"},
|
||||
{ .address = 0x0d, .description = "AK8975"},
|
||||
{ .address = 0x0e, .description = "MAG3110 AK8975 IST-8310"},
|
||||
{ .address = 0x0f, .description = "AK8975"},
|
||||
{ .address = 0x10, .description = "VEML7700 VML6075"},
|
||||
{ .address = 0x11, .description = "Si4713 SAA5246 SAA5243P/K SAA5243P/L SAA5243P/E SAA5243P/H"},
|
||||
{ .address = 0x13, .description = "VCNL40x0"},
|
||||
{ .address = 0x18, .description = "MCP9808 LIS3DH LSM303"},
|
||||
{ .address = 0x19, .description = "MCP9808 LIS3DH LSM303"},
|
||||
{ .address = 0x1a, .description = "MCP9808"},
|
||||
{ .address = 0x1b, .description = "MCP9808"},
|
||||
{ .address = 0x1c, .description = "MCP9808 MMA845x FXOS8700"},
|
||||
{ .address = 0x1d, .description = "MCP9808 MMA845x ADXL345 FXOS8700"},
|
||||
{ .address = 0x1e, .description = "MCP9808 FXOS8700 HMC5883 LSM303 LSM303"},
|
||||
{ .address = 0x1f, .description = "MCP9808 FXOS8700"},
|
||||
{ .address = 0x20, .description = "FXAS21002 MCP23008 MCP23017 Chirp!"},
|
||||
{ .address = 0x21, .description = "FXAS21002 MCP23008 MCP23017 SAA4700"},
|
||||
{ .address = 0x22, .description = "MCP23008 MCP23017 PCA1070"},
|
||||
{ .address = 0x23, .description = "MCP23008 MCP23017 SAA4700"},
|
||||
{ .address = 0x24, .description = "MCP23008 MCP23017 PCD3311C PCD3312C"},
|
||||
{ .address = 0x25, .description = "MCP23008 MCP23017 PCD3311C PCD3312C"},
|
||||
{ .address = 0x26, .description = "MCP23008 MCP23017"},
|
||||
{ .address = 0x27, .description = "MCP23008 MCP23017"},
|
||||
{ .address = 0x28, .description = "BNO055 CAP1188"},
|
||||
{ .address = 0x29, .description = "BNO055 CAP1188 TCS34725 TSL2591 VL53L0x VL6180X"},
|
||||
{ .address = 0x2a, .description = "CAP1188"},
|
||||
{ .address = 0x2b, .description = "CAP1188"},
|
||||
{ .address = 0x2c, .description = "CAP1188 AD5248 AD5251 AD5252 CAT5171"},
|
||||
{ .address = 0x2d, .description = "CAP1188 AD5248 AD5251 AD5252 CAT5171"},
|
||||
{ .address = 0x2e, .description = "AD5248 AD5251 AD5252"},
|
||||
{ .address = 0x2f, .description = "AD5248 AD5243 AD5251 AD5252"},
|
||||
{ .address = 0x30, .description = "SAA2502"},
|
||||
{ .address = 0x31, .description = "SAA2502"},
|
||||
{ .address = 0x38, .description = "FT6x06 VEML6070 BMA150 SAA1064"},
|
||||
{ .address = 0x39, .description = "TSL2561 APDS-9960 VEML6070 SAA1064"},
|
||||
{ .address = 0x3a, .description = "PCF8577C SAA1064"},
|
||||
{ .address = 0x3b, .description = "SAA1064 PCF8569"},
|
||||
{ .address = 0x3c, .description = "SSD1305 SSD1306 PCF8578 PCF8569 SH1106"},
|
||||
{ .address = 0x3d, .description = "SSD1305 SSD1306 PCF8578 SH1106"},
|
||||
{ .address = 0x40, .description = "HTU21D-F TMP007 PCA9685 NE5751 TDA8421 INA260 TEA6320 TEA6330 TMP006 TEA6300 Si7021 INA219 TDA9860"},
|
||||
{ .address = 0x41, .description = "TMP007 PCA9685 STMPE811 TDA8424 NE5751 TDA8421 INA260 STMPE610 TDA8425 TMP006 INA219 TDA9860 TDA8426"},
|
||||
{ .address = 0x42, .description = "HDC1008 TMP007 TMP006 PCA9685 INA219 TDA8415 TDA8417 INA260"},
|
||||
{ .address = 0x43, .description = "HDC1008 TMP007 TMP006 PCA9685 INA219 INA260"},
|
||||
{ .address = 0x44, .description = "TMP007 TMP006 PCA9685 INA219 STMPE610 SHT31 ISL29125 STMPE811 TDA4688 TDA4672 TDA4780 TDA4670 TDA8442 TDA4687 TDA4671 TDA4680 INA260"},
|
||||
{ .address = 0x45, .description = "TMP007 TMP006 PCA9685 INA219 SHT31 TDA8376 INA260"},
|
||||
{ .address = 0x46, .description = "TMP007 TMP006 PCA9685 INA219 TDA9150 TDA8370 INA260"},
|
||||
{ .address = 0x47, .description = "TMP007 TMP006 PCA9685 INA219 INA260"},
|
||||
{ .address = 0x48, .description = "PCA9685 INA219 PN532 TMP102 INA260 ADS1115"},
|
||||
{ .address = 0x49, .description = "TSL2561 PCA9685 INA219 TMP102 INA260 ADS1115 AS7262"},
|
||||
{ .address = 0x4a, .description = "PCA9685 INA219 TMP102 ADS1115 MAX44009 INA260"},
|
||||
{ .address = 0x4b, .description = "PCA9685 INA219 TMP102 ADS1115 MAX44009 INA260"},
|
||||
{ .address = 0x4c, .description = "PCA9685 INA219 INA260"},
|
||||
{ .address = 0x4d, .description = "PCA9685 INA219 INA260"},
|
||||
{ .address = 0x4e, .description = "PCA9685 INA219 INA260"},
|
||||
{ .address = 0x4f, .description = "PCA9685 INA219 INA260"},
|
||||
{ .address = 0x50, .description = "PCA9685 MB85RC"},
|
||||
{ .address = 0x51, .description = "PCA9685 MB85RC"},
|
||||
{ .address = 0x52, .description = "PCA9685 MB85RC Nunchuck controller APDS-9250"},
|
||||
{ .address = 0x53, .description = "ADXL345 PCA9685 MB85RC"},
|
||||
{ .address = 0x54, .description = "PCA9685 MB85RC"},
|
||||
{ .address = 0x55, .description = "PCA9685 MB85RC"},
|
||||
{ .address = 0x56, .description = "PCA9685 MB85RC"},
|
||||
{ .address = 0x57, .description = "PCA9685 MB85RC MAX3010x"},
|
||||
{ .address = 0x58, .description = "PCA9685 TPA2016 SGP30"},
|
||||
{ .address = 0x59, .description = "PCA9685"},
|
||||
{ .address = 0x5a, .description = "PCA9685 CCS811 MLX90614 DRV2605 MPR121"},
|
||||
{ .address = 0x5b, .description = "PCA9685 CCS811 MPR121"},
|
||||
{ .address = 0x5c, .description = "PCA9685 AM2315 MPR121"},
|
||||
{ .address = 0x5d, .description = "PCA9685 MPR121"},
|
||||
{ .address = 0x5e, .description = "PCA9685"},
|
||||
{ .address = 0x5f, .description = "PCA9685 HTS221"},
|
||||
{ .address = 0x60, .description = "PCA9685 MPL115A2 MPL3115A2 Si5351A Si1145 MCP4725A0 TEA5767 TSA5511 SAB3037 SAB3035 MCP4725A1"},
|
||||
{ .address = 0x61, .description = "PCA9685 Si5351A MCP4725A0 TEA6100 TSA5511 SAB3037 SAB3035 MCP4725A1"},
|
||||
{ .address = 0x62, .description = "PCA9685 MCP4725A1 TSA5511 SAB3037 SAB3035 UMA1014T"},
|
||||
{ .address = 0x63, .description = "Si4713 PCA9685 MCP4725A1 TSA5511 SAB3037 SAB3035 UMA1014T"},
|
||||
{ .address = 0x64, .description = "PCA9685 MCP4725A2 MCP4725A1"},
|
||||
{ .address = 0x65, .description = "PCA9685 MCP4725A2 MCP4725A1"},
|
||||
{ .address = 0x66, .description = "PCA9685 MCP4725A3 IS31FL3731 MCP4725A1"},
|
||||
{ .address = 0x67, .description = "PCA9685 MCP4725A3 MCP4725A1"},
|
||||
{ .address = 0x68, .description = "PCA9685 AMG8833 DS1307 PCF8523 DS3231 MPU-9250 ITG3200 PCF8573 MPU6050"},
|
||||
{ .address = 0x69, .description = "PCA9685 AMG8833 MPU-9250 ITG3200 PCF8573 SPS30 MPU6050"},
|
||||
{ .address = 0x6a, .description = "PCA9685 L3GD20H PCF8573"},
|
||||
{ .address = 0x6b, .description = "PCA9685 L3GD20H PCF8573"},
|
||||
{ .address = 0x6c, .description = "PCA9685"},
|
||||
{ .address = 0x6d, .description = "PCA9685"},
|
||||
{ .address = 0x6e, .description = "PCA9685"},
|
||||
{ .address = 0x6f, .description = "PCA9685"},
|
||||
{ .address = 0x70, .description = "PCA9685 TCA9548 HT16K33"},
|
||||
{ .address = 0x71, .description = "PCA9685 TCA9548 HT16K33"},
|
||||
{ .address = 0x72, .description = "PCA9685 TCA9548 HT16K33"},
|
||||
{ .address = 0x73, .description = "PCA9685 TCA9548 HT16K33"},
|
||||
{ .address = 0x74, .description = "PCA9685 TCA9548 HT16K33"},
|
||||
{ .address = 0x75, .description = "PCA9685 TCA9548 HT16K33"},
|
||||
{ .address = 0x76, .description = "PCA9685 TCA9548 HT16K33 BME280 BMP280 MS5607 MS5611 BME680"},
|
||||
{ .address = 0x77, .description = "PCA9685 TCA9548 HT16K33 IS31FL3731 BME280 BMP280 MS5607 BMP180 BMP085 BMA180 MS5611 BME680"},
|
||||
{ .address = 0x78, .description = "PCA9685"},
|
||||
{ .address = 0x79, .description = "PCA9685"},
|
||||
{ .address = 0x7a, .description = "PCA9685"},
|
||||
{ .address = 0x7b, .description = "PCA9685"},
|
||||
{ .address = 0x7c, .description = "PCA9685"},
|
||||
{ .address = 0x7d, .description = "PCA9685"},
|
||||
{ .address = 0x7e, .description = "PCA9685"},
|
||||
{ .address = 0x7f, .description = "PCA9685"},
|
||||
{ .address = 0, .description = NULL}
|
||||
};
|
||||
void i2c_load_configuration(){
|
||||
ESP_LOGD(TAG,"Loading configuration from nvs");
|
||||
const i2c_config_t * conf = config_i2c_get((int *)&i2c_port);
|
||||
i2c_gpio_scl = conf->scl_io_num;
|
||||
i2c_gpio_sda = conf->sda_io_num;
|
||||
i2c_frequency = conf->master.clk_speed;
|
||||
}
|
||||
|
||||
const char * i2c_get_description(uint8_t address){
|
||||
uint8_t i=0;
|
||||
while(i2c_db[i].description && i2c_db[i].address!=address) i++;
|
||||
return i2c_db[i].description?i2c_db[i].description:"Unlisted";
|
||||
}
|
||||
|
||||
static esp_err_t i2c_get_port(int port, i2c_port_t *i2c_port)
|
||||
{
|
||||
if (port >= I2C_NUM_MAX) {
|
||||
ESP_LOGE(TAG, "Wrong port number: %d", port);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
switch (port) {
|
||||
case 0:
|
||||
*i2c_port = I2C_NUM_0;
|
||||
break;
|
||||
case 1:
|
||||
*i2c_port = I2C_NUM_1;
|
||||
break;
|
||||
default:
|
||||
*i2c_port = I2C_NUM_0;
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
static esp_err_t i2c_master_driver_install(){
|
||||
esp_err_t err=ESP_OK;
|
||||
ESP_LOGD(TAG,"Installing i2c driver on port %u", i2c_port);
|
||||
if((err=i2c_driver_install(i2c_port, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0))!=ESP_OK){
|
||||
ESP_LOGE(TAG,"Driver install failed! %s", esp_err_to_name(err));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t i2c_master_driver_initialize()
|
||||
{
|
||||
esp_err_t err=ESP_OK;
|
||||
i2c_config_t conf = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = i2c_gpio_sda,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_io_num = i2c_gpio_scl,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = i2c_frequency
|
||||
};
|
||||
ESP_LOGI(TAG,"Initializing i2c driver configuration.\n mode = I2C_MODE_MASTER, \n scl_pullup_en = GPIO_PULLUP_ENABLE, \n i2c port = %u, \n sda_io_num = %u, \n sda_pullup_en = GPIO_PULLUP_ENABLE, \n scl_io_num = %u, \n scl_pullup_en = GPIO_PULLUP_ENABLE, \n master.clk_speed = %u", i2c_port, i2c_gpio_sda,i2c_gpio_scl,i2c_frequency);
|
||||
if((err=i2c_param_config(i2c_port, &conf))!=ESP_OK){
|
||||
ESP_LOGE(TAG,"i2c driver config load failed. %s", esp_err_to_name(err));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t i2c_initialize_driver_from_config(){
|
||||
esp_err_t err = ESP_OK;
|
||||
ESP_LOGD(TAG,"Initializing driver from configuration.");
|
||||
i2c_load_configuration();
|
||||
if(is_i2c_started(i2c_port)){
|
||||
ESP_LOGW(TAG, "Stopping i2c driver on port %u", i2c_port);
|
||||
// stop the current driver instance
|
||||
if((err=i2c_driver_delete(i2c_port))!=ESP_OK){
|
||||
ESP_LOGE(TAG,"i2c driver delete failed. %s", esp_err_to_name(err));
|
||||
}
|
||||
}
|
||||
if(err==ESP_OK){
|
||||
err = i2c_master_driver_initialize();
|
||||
}
|
||||
if(err == ESP_OK){
|
||||
err = i2c_master_driver_install();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int do_i2c_stop(int argc, char **argv ){
|
||||
|
||||
int nerrors = arg_parse(argc, argv, (void **)&i2cstop_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, i2cstop_args.end, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
if (i2cstop_args.port->count && i2c_get_port(i2cstop_args.port->ival[0], &i2c_port) != ESP_OK) {
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGW(TAG,"Stopping i2c on port %u.",i2c_port);
|
||||
i2c_driver_delete(i2c_port);
|
||||
return 0;
|
||||
}
|
||||
static int do_i2c_check(int argc, char **argv ){
|
||||
|
||||
i2c_port_t port=0;
|
||||
int nerrors = arg_parse(argc, argv, (void **)&i2ccheck_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, i2ccheck_args.end, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
port=i2c_port;
|
||||
|
||||
if (i2ccheck_args.port->count && i2c_get_port(i2ccheck_args.port->ival[0], &port) != ESP_OK) {
|
||||
return 1;
|
||||
}
|
||||
bool started=is_i2c_started(port);
|
||||
ESP_LOGI(TAG,"i2c is %s on port %u.", started?"started":"not started",port );
|
||||
return 0;
|
||||
}
|
||||
static int do_i2c_show_display(int argc, char **argv){
|
||||
char * config_string = (char * )config_alloc_get(NVS_TYPE_STR, "display_config") ;
|
||||
if(config_string){
|
||||
ESP_LOGI(TAG,"Display configuration string is : \n"
|
||||
"display_config = \"%s\"",config_string);
|
||||
free(config_string);
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG,"No display configuration found in nvs config display_config");
|
||||
}
|
||||
char * nvs_item = config_alloc_get(NVS_TYPE_STR, "i2c_config");
|
||||
if (nvs_item) {
|
||||
ESP_LOGI(TAG,"I2C configuration is: %s", nvs_item);
|
||||
free(nvs_item);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_i2c_set_display(int argc, char **argv)
|
||||
{
|
||||
int width=0, height=0, address=60;
|
||||
char * name = NULL;
|
||||
char * driver= NULL;
|
||||
char config_string[200]={};
|
||||
int nerrors = arg_parse(argc, argv, (void **)&i2cdisp_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, i2cdisp_args.end, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check "--clear" option */
|
||||
if (i2cdisp_args.clear->count) {
|
||||
ESP_LOGW(TAG,"Clearing display config");
|
||||
config_set_value(NVS_TYPE_STR, "display_config", "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Check "--address" option */
|
||||
if (i2cdisp_args.address->count) {
|
||||
address=i2cdisp_args.address->ival[0];
|
||||
}
|
||||
|
||||
/* Check "--width" option */
|
||||
if (i2cdisp_args.width->count) {
|
||||
width=i2cdisp_args.width->ival[0];
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Missing parameter: --width");
|
||||
nerrors ++;
|
||||
}
|
||||
|
||||
/* Check "--height" option */
|
||||
if (i2cdisp_args.height->count) {
|
||||
height=i2cdisp_args.height->ival[0];
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Missing parameter: --height");
|
||||
nerrors ++;
|
||||
}
|
||||
/* Check "--name" option */
|
||||
if (i2cdisp_args.name->count) {
|
||||
name=strdup(i2cdisp_args.name->sval[0]);
|
||||
}
|
||||
|
||||
/* Check "--driver" option */
|
||||
if (i2cdisp_args.driver->count) {
|
||||
driver=strdup(i2cdisp_args.driver->sval[0]);
|
||||
}
|
||||
|
||||
if(!name) name = strdup("I2C");
|
||||
if(!driver) driver = strdup("SSD1306");
|
||||
|
||||
bool rotate = i2cdisp_args.rotate->count>0;
|
||||
|
||||
snprintf(config_string, sizeof(config_string),"%s:width=%i,height=%i,address=%i,driver=%s%s%s",
|
||||
name,width,height,address,driver,rotate || i2cdisp_args.hflip->count?",HFlip":"",rotate || i2cdisp_args.vflip->count?",VFlip":"" );
|
||||
free(name);
|
||||
free(driver);
|
||||
|
||||
if(nerrors!=0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG,"Updating display configuration string configuration to :\n"
|
||||
"display_config = \"%s\"",config_string );
|
||||
|
||||
return config_set_value(NVS_TYPE_STR, "display_config", config_string)!=ESP_OK;
|
||||
}
|
||||
|
||||
static int do_i2cconfig_cmd(int argc, char **argv)
|
||||
{
|
||||
esp_err_t err=ESP_OK;
|
||||
int res=0;
|
||||
int nerrors = arg_parse(argc, argv, (void **)&i2cconfig_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, i2cconfig_args.end, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
/* Check "--load" option */
|
||||
if (i2cconfig_args.load->count) {
|
||||
ESP_LOGW(TAG,"Loading i2c config");
|
||||
i2c_load_configuration();
|
||||
}
|
||||
else {
|
||||
|
||||
/* Check "--port" option */
|
||||
if (i2cconfig_args.port->count) {
|
||||
if (i2c_get_port(i2cconfig_args.port->ival[0], &i2c_port) != ESP_OK) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* Check "--freq" option */
|
||||
if (i2cconfig_args.freq->count) {
|
||||
i2c_frequency = i2cconfig_args.freq->ival[0];
|
||||
}
|
||||
if (i2cconfig_args.sda->count){
|
||||
/* Check "--sda" option */
|
||||
i2c_gpio_sda = i2cconfig_args.sda->ival[0];
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Missing --sda option.");
|
||||
res=1;
|
||||
}
|
||||
|
||||
if (i2cconfig_args.scl->count){
|
||||
/* Check "--sda" option */
|
||||
i2c_gpio_scl = i2cconfig_args.scl->ival[0];
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Missing --scl option.");
|
||||
res=1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SQUEEZEAMP
|
||||
if (i2c_port == I2C_NUM_0) {
|
||||
i2c_port = I2C_NUM_1;
|
||||
ESP_LOGE(TAG, "can't use i2c port 0 on SqueezeAMP. Changing to port 1.");
|
||||
}
|
||||
#endif
|
||||
if(!res){
|
||||
ESP_LOGI(TAG, "Uninstall i2c driver from port %u if needed",i2c_port);
|
||||
if(is_i2c_started(i2c_port)){
|
||||
if((err=i2c_driver_delete(i2c_port))!=ESP_OK){
|
||||
ESP_LOGE(TAG,"i2c driver delete failed. %s", esp_err_to_name(err));
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!res){
|
||||
ESP_LOGI(TAG,"Initializing driver with config scl=%u sda=%u speed=%u port=%u",i2c_gpio_scl,i2c_gpio_sda,i2c_frequency,i2c_port);
|
||||
if((err=i2c_master_driver_initialize())==ESP_OK){
|
||||
ESP_LOGI(TAG,"Initalize success.");
|
||||
// now start the i2c driver
|
||||
ESP_LOGI(TAG,"Starting the i2c driver.");
|
||||
if((err=i2c_master_driver_install())!=ESP_OK){
|
||||
res=1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"I2C initialization failed. %s", esp_err_to_name(err));
|
||||
res=1;
|
||||
}
|
||||
}
|
||||
if(!res && !i2cconfig_args.load->count){
|
||||
ESP_LOGI(TAG,"Storing i2c parameters.");
|
||||
i2c_config_t config={
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = i2c_gpio_sda,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_io_num = i2c_gpio_scl,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = i2c_frequency
|
||||
};
|
||||
config_i2c_set(&config, i2c_port);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define RUN_SHOW_ERROR(c)
|
||||
|
||||
|
||||
static int do_i2cdump_cmd(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&i2cdump_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, i2cdump_args.end, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check chip address: "-c" option */
|
||||
int chip_addr = i2cdump_args.chip_address->ival[0];
|
||||
/* Check read size: "-s" option */
|
||||
int size = 1;
|
||||
if (i2cdump_args.size->count) {
|
||||
size = i2cdump_args.size->ival[0];
|
||||
}
|
||||
if (size != 1 && size != 2 && size != 4) {
|
||||
ESP_LOGE(TAG, "Wrong read size. Only support 1,2,4");
|
||||
return 1;
|
||||
}
|
||||
esp_err_t ret = i2c_initialize_driver_from_config();
|
||||
if(ret!=ESP_OK) return 0;
|
||||
|
||||
uint8_t data_addr;
|
||||
uint8_t data[4];
|
||||
int32_t block[16];
|
||||
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"
|
||||
" 0123456789abcdef\r\n");
|
||||
for (int i = 0; i < 128; i += 16) {
|
||||
printf("%02x: ", i);
|
||||
for (int j = 0; j < 16; j += size) {
|
||||
fflush(stdout);
|
||||
data_addr = i + j;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, chip_addr << 1 | WRITE_BIT, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, data_addr, ACK_CHECK_EN);
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, chip_addr << 1 | READ_BIT, ACK_CHECK_EN);
|
||||
if (size > 1) {
|
||||
i2c_master_read(cmd, data, size - 1, ACK_VAL);
|
||||
}
|
||||
i2c_master_read_byte(cmd, data + size - 1, NACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 50 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_OK) {
|
||||
for (int k = 0; k < size; k++) {
|
||||
printf("%02x ", data[k]);
|
||||
block[j + k] = data[k];
|
||||
}
|
||||
} else {
|
||||
for (int k = 0; k < size; k++) {
|
||||
printf("XX ");
|
||||
block[j + k] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf(" ");
|
||||
for (int k = 0; k < 16; k++) {
|
||||
if (block[k] < 0) {
|
||||
printf("X");
|
||||
}
|
||||
if ((block[k] & 0xff) == 0x00 || (block[k] & 0xff) == 0xff) {
|
||||
printf(".");
|
||||
} else if ((block[k] & 0xff) < 32 || (block[k] & 0xff) >= 127) {
|
||||
printf("?");
|
||||
} else {
|
||||
printf("%c", block[k] & 0xff);
|
||||
}
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
// Don't stop the driver; our firmware may be using it for screen, etc
|
||||
//i2c_driver_delete(i2c_port);
|
||||
return 0;
|
||||
}
|
||||
static int do_i2cset_cmd(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&i2cset_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, i2cset_args.end, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check chip address: "-c" option */
|
||||
int chip_addr = i2cset_args.chip_address->ival[0];
|
||||
/* Check register address: "-r" option */
|
||||
int data_addr = 0;
|
||||
if (i2cset_args.register_address->count) {
|
||||
data_addr = i2cset_args.register_address->ival[0];
|
||||
}
|
||||
/* Check data: "-d" option */
|
||||
int len = i2cset_args.data->count;
|
||||
|
||||
i2c_master_driver_initialize();
|
||||
if(i2c_master_driver_install()!=ESP_OK){
|
||||
return 1;
|
||||
}
|
||||
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, chip_addr << 1 | WRITE_BIT, ACK_CHECK_EN);
|
||||
if (i2cset_args.register_address->count) {
|
||||
i2c_master_write_byte(cmd, data_addr, ACK_CHECK_EN);
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
i2c_master_write_byte(cmd, i2cset_args.data->ival[i], ACK_CHECK_EN);
|
||||
}
|
||||
i2c_master_stop(cmd);
|
||||
esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Write OK");
|
||||
} else if (ret == ESP_ERR_TIMEOUT) {
|
||||
ESP_LOGW(TAG, "Bus is busy");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Write Failed");
|
||||
}
|
||||
// Don't stop the driver; our firmware may be using it for screen, etc
|
||||
//i2c_driver_delete(i2c_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_i2cget_cmd(int argc, char **argv)
|
||||
{
|
||||
esp_err_t err=ESP_OK;
|
||||
int nerrors = arg_parse(argc, argv, (void **)&i2cget_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, i2cget_args.end, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check chip address: "-c" option */
|
||||
int chip_addr = i2cget_args.chip_address->ival[0];
|
||||
/* Check register address: "-r" option */
|
||||
int data_addr = -1;
|
||||
if (i2cget_args.register_address->count) {
|
||||
data_addr = i2cget_args.register_address->ival[0];
|
||||
}
|
||||
/* Check data length: "-l" option */
|
||||
int len = 1;
|
||||
if (i2cget_args.data_length->count) {
|
||||
len = i2cget_args.data_length->ival[0];
|
||||
}
|
||||
|
||||
|
||||
if((err=i2c_master_driver_initialize())!=ESP_OK){
|
||||
ESP_LOGE(TAG,"Error initializing i2c driver. %s",esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
if((err=i2c_master_driver_install())!=ESP_OK){
|
||||
return 1;
|
||||
}
|
||||
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
uint8_t *data = malloc(len);
|
||||
if (data_addr != -1) {
|
||||
i2c_master_write_byte(cmd, chip_addr << 1 | WRITE_BIT, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, data_addr, ACK_CHECK_EN);
|
||||
i2c_master_start(cmd);
|
||||
}
|
||||
i2c_master_write_byte(cmd, chip_addr << 1 | READ_BIT, ACK_CHECK_EN);
|
||||
if (len > 1) {
|
||||
i2c_master_read(cmd, data, len - 1, ACK_VAL);
|
||||
}
|
||||
i2c_master_read_byte(cmd, data + len - 1, NACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_OK) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
printf("0x%02x ", data[i]);
|
||||
if ((i + 1) % 16 == 0) {
|
||||
printf("\r\n");
|
||||
}
|
||||
}
|
||||
if (len % 16) {
|
||||
printf("\r\n");
|
||||
}
|
||||
} else if (ret == ESP_ERR_TIMEOUT) {
|
||||
ESP_LOGW(TAG, "Bus is busy");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Read failed");
|
||||
}
|
||||
free(data);
|
||||
// Don't stop the driver; our firmware may be using it for screen, etc
|
||||
//i2c_driver_delete(i2c_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_i2cdetect_cmd(int argc, char **argv)
|
||||
{
|
||||
uint8_t matches[128]={};
|
||||
int last_match=0;
|
||||
esp_err_t ret = i2c_initialize_driver_from_config();
|
||||
if(ret!=ESP_OK) return 0;
|
||||
uint8_t address;
|
||||
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
|
||||
for (int i = 0; i < 128 ; i += 16) {
|
||||
printf("%02x: ", i);
|
||||
for (int j = 0; j < 16 ; j++) {
|
||||
fflush(stdout);
|
||||
address = i + j;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (address << 1) | WRITE_BIT, ACK_CHECK_EN);
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(i2c_port, cmd, 50 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_OK) {
|
||||
printf("%02x ", address);
|
||||
matches[++last_match-1] = address;
|
||||
} else if (ret == ESP_ERR_TIMEOUT) {
|
||||
printf("UU ");
|
||||
} else {
|
||||
printf("-- ");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\r\n");
|
||||
|
||||
}
|
||||
if(last_match) {
|
||||
printf("\r\n------------------------------------------------------------------------------------"
|
||||
"\r\nDetected the following devices (names provided by https://i2cdevices.org/addresses).");
|
||||
|
||||
for(int i=0;i<last_match;i++){
|
||||
//printf("%02x = %s\r\n", matches[i], i2c_get_description(matches[i]));
|
||||
printf("\r\n%u [%02xh]- %s", matches[i], matches[i], i2c_get_description(matches[i]));
|
||||
}
|
||||
printf("\r\n------------------------------------------------------------------------------------\r\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static void register_i2c_set_display(){
|
||||
i2cdisp_args.address = arg_int0("a", "address", "<n>", "Set the device address, default 60");
|
||||
i2cdisp_args.width = arg_int0("w", "width", "<n>", "Set the display width");
|
||||
i2cdisp_args.height = arg_int0("h", "height", "<n>", "Set the display height");
|
||||
i2cdisp_args.name = arg_str0("t", "type", "<I2C|SPI>", "Set the display type. default I2C");
|
||||
i2cdisp_args.driver = arg_str0("d", "driver", "<string>", "Set the display driver name. Default SSD1306");
|
||||
i2cdisp_args.clear = arg_litn(NULL, "clear", 0, 1, "clear configuration and return");
|
||||
i2cdisp_args.hflip = arg_litn(NULL, "hf", 0, 1, "Flip picture horizontally");
|
||||
i2cdisp_args.vflip = arg_litn(NULL, "vf", 0, 1, "Flip picture vertically");
|
||||
i2cdisp_args.rotate = arg_litn("r", "rotate", 0, 1, "Rotate the picture 180 deg");
|
||||
i2cdisp_args.end = arg_end(8);
|
||||
const esp_console_cmd_t i2c_set_display= {
|
||||
.command = "setdisplay",
|
||||
.help="Sets the display options for the board",
|
||||
.hint = NULL,
|
||||
.func = &do_i2c_set_display,
|
||||
.argtable = &i2cdisp_args
|
||||
};
|
||||
|
||||
const esp_console_cmd_t i2c_show_display= {
|
||||
.command = "getdisplay",
|
||||
.help="Shows display options and global i2c configuration",
|
||||
.hint = NULL,
|
||||
.func = &do_i2c_show_display,
|
||||
.argtable = NULL
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2c_set_display));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2c_show_display));
|
||||
}
|
||||
static void register_i2cdectect(void)
|
||||
{
|
||||
const esp_console_cmd_t i2cdetect_cmd = {
|
||||
.command = "i2cdetect",
|
||||
.help = "Scan I2C bus for devices",
|
||||
.hint = NULL,
|
||||
.func = &do_i2cdetect_cmd,
|
||||
.argtable = NULL
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2cdetect_cmd));
|
||||
}
|
||||
|
||||
static void register_i2cget(void)
|
||||
{
|
||||
i2cget_args.chip_address = arg_int1("c", "chip", "<chip_addr>", "Specify the address of the chip on that bus");
|
||||
i2cget_args.register_address = arg_int0("r", "register", "<register_addr>", "Specify the address on that chip to read from");
|
||||
i2cget_args.data_length = arg_int0("l", "length", "<length>", "Specify the length to read from that data address");
|
||||
i2cget_args.end = arg_end(1);
|
||||
const esp_console_cmd_t i2cget_cmd = {
|
||||
.command = "i2cget",
|
||||
.help = "Read registers visible through the I2C bus",
|
||||
.hint = NULL,
|
||||
.func = &do_i2cget_cmd,
|
||||
.argtable = &i2cget_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2cget_cmd));
|
||||
}
|
||||
|
||||
|
||||
static void register_i2cset(void)
|
||||
{
|
||||
i2cset_args.chip_address = arg_int1("c", "chip", "<chip_addr>", "Specify the address of the chip on that bus");
|
||||
i2cset_args.register_address = arg_int0("r", "register", "<register_addr>", "Specify the address on that chip to read from");
|
||||
i2cset_args.data = arg_intn(NULL, NULL, "<data>", 0, 256, "Specify the data to write to that data address");
|
||||
i2cset_args.end = arg_end(2);
|
||||
const esp_console_cmd_t i2cset_cmd = {
|
||||
.command = "i2cset",
|
||||
.help = "Set registers visible through the I2C bus",
|
||||
.hint = NULL,
|
||||
.func = &do_i2cset_cmd,
|
||||
.argtable = &i2cset_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2cset_cmd));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void register_i2cdump(void)
|
||||
{
|
||||
i2cdump_args.chip_address = arg_int1("c", "chip", "<chip_addr>", "Specify the address of the chip on that bus");
|
||||
i2cdump_args.size = arg_int0("s", "size", "<size>", "Specify the size of each read");
|
||||
i2cdump_args.end = arg_end(3);
|
||||
const esp_console_cmd_t i2cdump_cmd = {
|
||||
.command = "i2cdump",
|
||||
.help = "Examine registers visible through the I2C bus",
|
||||
.hint = NULL,
|
||||
.func = &do_i2cdump_cmd,
|
||||
.argtable = &i2cdump_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2cdump_cmd));
|
||||
}
|
||||
|
||||
static void register_i2ccheck(){
|
||||
i2ccheck_args.port = arg_int0("p", "port", "<0|1>", "Set the I2C bus port number");
|
||||
i2ccheck_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "i2ccheck",
|
||||
.help = "Check if the I2C bus is installed",
|
||||
.hint = NULL,
|
||||
.func = &do_i2c_check,
|
||||
.argtable = &i2ccheck_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
|
||||
static void register_i2cstop(){
|
||||
i2cstop_args.port = arg_int0("p", "port", "<0|1>", "Set the I2C bus port number");
|
||||
i2cstop_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t i2cconfig_cmd = {
|
||||
.command = "i2cstop",
|
||||
.help = "Stop the I2C bus",
|
||||
.hint = NULL,
|
||||
.func = &do_i2c_stop,
|
||||
.argtable = &i2cstop_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2cconfig_cmd));
|
||||
}
|
||||
|
||||
static void register_i2cconfig(void)
|
||||
{
|
||||
i2cconfig_args.port = arg_int0("p", "port", "<0|1>", "Set the I2C bus port number");
|
||||
i2cconfig_args.freq = arg_int0("f", "freq", "<Hz>", "Set the frequency(Hz) of I2C bus. e.g. 100000");
|
||||
i2cconfig_args.sda = arg_int0("d", "sda", "<gpio>", "Set the gpio for I2C SDA. e.g. 19");
|
||||
i2cconfig_args.scl = arg_int0("c", "scl", "<gpio>", "Set the gpio for I2C SCL. e.g. 18");
|
||||
i2cconfig_args.load = arg_litn("l", "load", 0, 1, "load existing configuration and return");
|
||||
i2cconfig_args.end = arg_end(4);
|
||||
const esp_console_cmd_t i2cconfig_cmd = {
|
||||
.command = "i2cconfig",
|
||||
.help = "Config I2C bus",
|
||||
.hint = NULL,
|
||||
.func = &do_i2cconfig_cmd,
|
||||
.argtable = &i2cconfig_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2cconfig_cmd));
|
||||
}
|
||||
|
||||
void register_i2ctools(void)
|
||||
{
|
||||
register_i2cconfig();
|
||||
register_i2cdectect();
|
||||
register_i2cget();
|
||||
register_i2cset();
|
||||
register_i2cdump();
|
||||
register_i2c_set_display();
|
||||
register_i2cstop();
|
||||
register_i2ccheck();
|
||||
}
|
||||
@@ -8,13 +8,13 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void register_i2ctools(void);
|
||||
esp_err_t cmd_i2ctools_scan_bus(FILE *f,int sda, int scl);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
4
components/cmd_i2c/component.mk
Normal file
4
components/cmd_i2c/component.mk
Normal file
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# Main Makefile. This is basically the same as a component makefile.
|
||||
#
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
7
components/cmd_nvs/CMakeLists.txt
Normal file
7
components/cmd_nvs/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
set(COMPONENT_ADD_INCLUDEDIRS .)
|
||||
|
||||
set(COMPONENT_SRCS "cmd_nvs.c")
|
||||
|
||||
set(COMPONENT_REQUIRES console nvs_flash)
|
||||
|
||||
register_component()
|
||||
@@ -6,6 +6,7 @@
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
//#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -24,52 +25,42 @@ extern "C" {
|
||||
#include "cmd_nvs.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_utilities.h"
|
||||
#include "platform_console.h"
|
||||
#include "messaging.h"
|
||||
#include "tools.h"
|
||||
#include "trace.h"
|
||||
|
||||
extern esp_err_t network_wifi_erase_legacy();
|
||||
extern esp_err_t network_wifi_erase_known_ap();
|
||||
|
||||
|
||||
static const char *ARG_TYPE_STR = "type can be: i8, u8, i16, u16 i32, u32 i64, u64, str, blob";
|
||||
static const char * TAG = "cmd_nvs";
|
||||
|
||||
EXT_RAM_ATTR static struct {
|
||||
static struct {
|
||||
struct arg_str *key;
|
||||
struct arg_str *type;
|
||||
struct arg_str *value;
|
||||
struct arg_end *end;
|
||||
} set_args;
|
||||
|
||||
EXT_RAM_ATTR static struct {
|
||||
static struct {
|
||||
struct arg_str *key;
|
||||
struct arg_str *type;
|
||||
struct arg_end *end;
|
||||
} get_args;
|
||||
|
||||
EXT_RAM_ATTR static struct {
|
||||
static struct {
|
||||
struct arg_str *key;
|
||||
struct arg_end *end;
|
||||
} erase_args;
|
||||
|
||||
EXT_RAM_ATTR static struct {
|
||||
static struct {
|
||||
struct arg_str *namespace;
|
||||
struct arg_end *end;
|
||||
} erase_all_args;
|
||||
|
||||
EXT_RAM_ATTR static struct {
|
||||
static struct {
|
||||
struct arg_str *partition;
|
||||
struct arg_str *namespace;
|
||||
struct arg_str *type;
|
||||
struct arg_end *end;
|
||||
} list_args;
|
||||
|
||||
EXT_RAM_ATTR static struct {
|
||||
struct arg_lit *legacy;
|
||||
struct arg_lit *ap_list;
|
||||
struct arg_end *end;
|
||||
} wifi_erase_args;
|
||||
|
||||
|
||||
static esp_err_t store_blob(nvs_handle nvs, const char *key, const char *str_values)
|
||||
@@ -79,11 +70,11 @@ static esp_err_t store_blob(nvs_handle nvs, const char *key, const char *str_val
|
||||
size_t blob_len = str_len / 2;
|
||||
|
||||
if (str_len % 2) {
|
||||
log_send_messaging(MESSAGING_ERROR, "Blob data must contain even number of characters");
|
||||
ESP_LOGE(TAG, "Blob data must contain even number of characters");
|
||||
return ESP_ERR_NVS_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
char *blob = (char *)malloc_init_external(blob_len);
|
||||
char *blob = (char *)malloc(blob_len);
|
||||
if (blob == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
@@ -97,7 +88,7 @@ static esp_err_t store_blob(nvs_handle nvs, const char *key, const char *str_val
|
||||
} else if (ch >= 'a' && ch <= 'f') {
|
||||
value = ch - 'a' + 10;
|
||||
} else {
|
||||
log_send_messaging(MESSAGING_ERROR, "Blob data contain invalid character");
|
||||
ESP_LOGE(TAG, "Blob data contain invalid character");
|
||||
free(blob);
|
||||
return ESP_ERR_NVS_TYPE_MISMATCH;
|
||||
}
|
||||
@@ -196,10 +187,10 @@ static esp_err_t set_value_in_nvs(const char *key, const char *str_type, const c
|
||||
}
|
||||
|
||||
if (err == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO, "Set value ok. Committing '%s'", key);
|
||||
ESP_LOGI(TAG, "Set value ok. Committing '%s'", key);
|
||||
err = nvs_commit(nvs);
|
||||
if (err == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO, "Value stored under key '%s'", key);
|
||||
ESP_LOGI(TAG, "Value stored under key '%s'", key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,60 +218,60 @@ static esp_err_t get_value_from_nvs(const char *key, const char *str_type)
|
||||
int8_t value;
|
||||
err = nvs_get_i8(nvs, key, &value);
|
||||
if (err == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %d \n", key, value);
|
||||
printf("Value associated with key '%s' is %d \n", key, value);
|
||||
}
|
||||
} else if (type == NVS_TYPE_U8) {
|
||||
uint8_t value;
|
||||
err = nvs_get_u8(nvs, key, &value);
|
||||
if (err == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %u \n", key, value);
|
||||
printf("Value associated with key '%s' is %u \n", key, value);
|
||||
}
|
||||
} else if (type == NVS_TYPE_I16) {
|
||||
int16_t value;
|
||||
err = nvs_get_i16(nvs, key, &value);
|
||||
if (err == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %d \n", key, value);
|
||||
printf("Value associated with key '%s' is %d \n", key, value);
|
||||
}
|
||||
} else if (type == NVS_TYPE_U16) {
|
||||
uint16_t value;
|
||||
if ((err = nvs_get_u16(nvs, key, &value)) == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %u", key, value);
|
||||
printf("Value associated with key '%s' is %u", key, value);
|
||||
}
|
||||
} else if (type == NVS_TYPE_I32) {
|
||||
int32_t value;
|
||||
if ((err = nvs_get_i32(nvs, key, &value)) == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %d \n", key, value);
|
||||
printf("Value associated with key '%s' is %d \n", key, value);
|
||||
}
|
||||
} else if (type == NVS_TYPE_U32) {
|
||||
uint32_t value;
|
||||
if ((err = nvs_get_u32(nvs, key, &value)) == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %u \n", key, value);
|
||||
printf("Value associated with key '%s' is %u \n", key, value);
|
||||
}
|
||||
} else if (type == NVS_TYPE_I64) {
|
||||
int64_t value;
|
||||
if ((err = nvs_get_i64(nvs, key, &value)) == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %lld \n", key, value);
|
||||
printf("Value associated with key '%s' is %lld \n", key, value);
|
||||
}
|
||||
} else if (type == NVS_TYPE_U64) {
|
||||
uint64_t value;
|
||||
if ( (err = nvs_get_u64(nvs, key, &value)) == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO,"Value associated with key '%s' is %llu \n", key, value);
|
||||
printf("Value associated with key '%s' is %llu \n", key, value);
|
||||
}
|
||||
} else if (type == NVS_TYPE_STR) {
|
||||
size_t len=0;
|
||||
if ( (err = nvs_get_str(nvs, key, NULL, &len)) == ESP_OK) {
|
||||
char *str = (char *)malloc_init_external(len);
|
||||
char *str = (char *)malloc(len);
|
||||
if ( (err = nvs_get_str(nvs, key, str, &len)) == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO,"String associated with key '%s' is %s \n", key, str);
|
||||
printf("String associated with key '%s' is %s \n", key, str);
|
||||
}
|
||||
free(str);
|
||||
}
|
||||
} else if (type == NVS_TYPE_BLOB) {
|
||||
size_t len;
|
||||
if ( (err = nvs_get_blob(nvs, key, NULL, &len)) == ESP_OK) {
|
||||
char *blob = (char *)malloc_init_external(len);
|
||||
char *blob = (char *)malloc(len);
|
||||
if ( (err = nvs_get_blob(nvs, key, blob, &len)) == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO,"Blob associated with key '%s' is %d bytes long: \n", key, len);
|
||||
printf("Blob associated with key '%s' is %d bytes long: \n", key, len);
|
||||
print_blob(blob, len);
|
||||
}
|
||||
free(blob);
|
||||
@@ -301,7 +292,7 @@ static esp_err_t erase(const char *key)
|
||||
if (err == ESP_OK) {
|
||||
err = nvs_commit(nvs);
|
||||
if (err == ESP_OK) {
|
||||
log_send_messaging(MESSAGING_INFO, "Value with key '%s' erased", key);
|
||||
ESP_LOGI(TAG, "Value with key '%s' erased", key);
|
||||
}
|
||||
}
|
||||
nvs_close(nvs);
|
||||
@@ -322,7 +313,7 @@ static esp_err_t erase_all(const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
log_send_messaging(MESSAGING_INFO, "Namespace '%s' was %s erased", name, (err == ESP_OK) ? "" : "not");
|
||||
ESP_LOGI(TAG, "Namespace '%s' was %s erased", name, (err == ESP_OK) ? "" : "not");
|
||||
nvs_close(nvs);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -330,19 +321,22 @@ static esp_err_t erase_all(const char *name)
|
||||
static int set_value(int argc, char **argv)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s %u - Parsing keys ",__func__,__LINE__);
|
||||
int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&set_args);
|
||||
int nerrors = arg_parse(argc, argv, (void **) &set_args);
|
||||
|
||||
if (nerrors != 0) {
|
||||
ESP_LOGE(TAG, "%s %u - Error Parsing keys ",__func__,__LINE__);
|
||||
arg_print_errors(stderr, set_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *key = set_args.key->sval[0];
|
||||
const char *type = set_args.type->sval[0];
|
||||
const char *values = set_args.value->sval[0];
|
||||
cmd_send_messaging(argv[0],MESSAGING_INFO, "Setting '%s' (type %s)", key,type);
|
||||
ESP_LOGI(TAG, "Setting '%s' (type %s)", key,type);
|
||||
esp_err_t err = set_value_in_nvs(key, type, values);
|
||||
|
||||
if (err != ESP_OK) {
|
||||
cmd_send_messaging(argv[0],MESSAGING_ERROR, "%s", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG, "%s", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -352,8 +346,9 @@ static int set_value(int argc, char **argv)
|
||||
|
||||
static int get_value(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&get_args);
|
||||
int nerrors = arg_parse(argc, argv, (void **) &get_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, get_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -363,7 +358,7 @@ static int get_value(int argc, char **argv)
|
||||
esp_err_t err = get_value_from_nvs(key, type);
|
||||
|
||||
if (err != ESP_OK) {
|
||||
cmd_send_messaging(argv[0],MESSAGING_ERROR, "%s", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG, "%s", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -372,8 +367,9 @@ static int get_value(int argc, char **argv)
|
||||
|
||||
static int erase_value(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&erase_args);
|
||||
int nerrors = arg_parse(argc, argv, (void **) &erase_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, erase_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -382,7 +378,7 @@ static int erase_value(int argc, char **argv)
|
||||
esp_err_t err = erase(key);
|
||||
|
||||
if (err != ESP_OK) {
|
||||
cmd_send_messaging(argv[0],MESSAGING_ERROR, "%s", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG, "%s", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -391,8 +387,9 @@ static int erase_value(int argc, char **argv)
|
||||
|
||||
static int erase_namespace(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&erase_all_args);
|
||||
int nerrors = arg_parse(argc, argv, (void **) &erase_all_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, erase_all_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -400,14 +397,14 @@ static int erase_namespace(int argc, char **argv)
|
||||
|
||||
esp_err_t err = erase_all(name);
|
||||
if (err != ESP_OK) {
|
||||
cmd_send_messaging(argv[0],MESSAGING_ERROR, "%s", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG, "%s", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int erase_network_manager(int argc, char **argv)
|
||||
static int erase_wifi_manager(int argc, char **argv)
|
||||
{
|
||||
nvs_handle nvs;
|
||||
esp_err_t err = nvs_open("config", NVS_READWRITE, &nvs);
|
||||
@@ -419,49 +416,15 @@ static int erase_network_manager(int argc, char **argv)
|
||||
}
|
||||
nvs_close(nvs);
|
||||
if (err != ESP_OK) {
|
||||
cmd_send_messaging(argv[0],MESSAGING_ERROR, "System configuration was not erased. %s", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG, "wifi manager configuration was not erase. %s", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
cmd_send_messaging(argv[0],MESSAGING_WARNING, "system configuration was erased. Please reboot.");
|
||||
ESP_LOGW(TAG, "Wifi manager configuration was erased");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wifi_erase_config(int argc, char **argv)
|
||||
{
|
||||
esp_err_t err=ESP_OK;
|
||||
esp_err_t err_ap_list=ESP_OK;
|
||||
bool done = false;
|
||||
int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&wifi_erase_args);
|
||||
if (nerrors != 0) {
|
||||
return 1;
|
||||
}
|
||||
if(wifi_erase_args.ap_list->count>0){
|
||||
err_ap_list = network_wifi_erase_known_ap();
|
||||
if (err_ap_list != ESP_OK) {
|
||||
cmd_send_messaging(argv[0],MESSAGING_ERROR, "Could not erase legacy wifi configuration: %s", esp_err_to_name(err));
|
||||
}
|
||||
else {
|
||||
cmd_send_messaging(argv[0],MESSAGING_ERROR, "Legacy wifi configuration was erased");
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
if(wifi_erase_args.legacy->count>0){
|
||||
err = network_wifi_erase_legacy();
|
||||
if (err != ESP_OK) {
|
||||
cmd_send_messaging(argv[0],MESSAGING_ERROR, "Could not erase known ap list : %s", esp_err_to_name(err));
|
||||
}
|
||||
else {
|
||||
cmd_send_messaging(argv[0],MESSAGING_ERROR, "Known access point list was erased");
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
if(!done){
|
||||
cmd_send_messaging(argv[0],MESSAGING_WARNING, "Please specify at least one configuration type to erase.", esp_err_to_name(err));
|
||||
}
|
||||
return (err_ap_list==ESP_OK && err==ESP_OK)?0:1;
|
||||
}
|
||||
|
||||
static int list(const char *part, const char *name, const char *str_type)
|
||||
{
|
||||
@@ -469,7 +432,7 @@ static int list(const char *part, const char *name, const char *str_type)
|
||||
|
||||
nvs_iterator_t it = nvs_entry_find(part, NULL, type);
|
||||
if (it == NULL) {
|
||||
log_send_messaging(MESSAGING_ERROR, "No such enty was found");
|
||||
ESP_LOGE(TAG, "No such enty was found");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -478,7 +441,7 @@ static int list(const char *part, const char *name, const char *str_type)
|
||||
nvs_entry_info(it, &info);
|
||||
it = nvs_entry_next(it);
|
||||
|
||||
log_send_messaging(MESSAGING_INFO, "namespace '%s', key '%s', type '%s' \n",
|
||||
printf("namespace '%s', key '%s', type '%s' \n",
|
||||
info.namespace_name, info.key, type_to_str(info.type));
|
||||
} while (it != NULL);
|
||||
|
||||
@@ -490,8 +453,9 @@ static int list_entries(int argc, char **argv)
|
||||
list_args.namespace->sval[0] = "";
|
||||
list_args.type->sval[0] = "";
|
||||
|
||||
int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&list_args);
|
||||
int nerrors = arg_parse(argc, argv, (void **) &list_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, list_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -518,10 +482,6 @@ void register_nvs()
|
||||
erase_all_args.namespace = arg_str1(NULL, NULL, "<namespace>", "namespace to be erased");
|
||||
erase_all_args.end = arg_end(2);
|
||||
|
||||
wifi_erase_args.ap_list = arg_lit0("a","ap_list","Erases Known access points list");
|
||||
wifi_erase_args.legacy = arg_lit0("l","legacy","Erases legacy access point storage");
|
||||
wifi_erase_args.end = arg_end(1);
|
||||
|
||||
list_args.partition = arg_str1(NULL, NULL, "<partition>", "partition name");
|
||||
list_args.namespace = arg_str0("n", "namespace", "<namespace>", "namespace name");
|
||||
list_args.type = arg_str0("t", "type", "<type>", ARG_TYPE_STR);
|
||||
@@ -562,19 +522,11 @@ void register_nvs()
|
||||
.func = &erase_namespace,
|
||||
.argtable = &erase_all_args
|
||||
};
|
||||
const esp_console_cmd_t erase_config_cmd = {
|
||||
.command = "wifi_erase_config",
|
||||
.help = "Erases all stored access points from flash",
|
||||
const esp_console_cmd_t erase_wifimanager_cmd = {
|
||||
.command = "nvs_erase_wifi_manager",
|
||||
.help = "Erases wifi_manager's config",
|
||||
.hint = NULL,
|
||||
.func = &wifi_erase_config,
|
||||
.argtable = &wifi_erase_args
|
||||
};
|
||||
|
||||
const esp_console_cmd_t erase_networkmanager_cmd = {
|
||||
.command = "nvs_erase_configuration",
|
||||
.help = "Erases system's configuration",
|
||||
.hint = NULL,
|
||||
.func = &erase_network_manager,
|
||||
.func = &erase_wifi_manager,
|
||||
.argtable = NULL
|
||||
};
|
||||
|
||||
@@ -589,21 +541,12 @@ void register_nvs()
|
||||
.func = &list_entries,
|
||||
.argtable = &list_args
|
||||
};
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("registering list_entries_cmd");
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&list_entries_cmd));
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("registering set_cmd");
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&set_cmd));
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("registering get_cmd");
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&get_cmd));
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("registering erase_cmd");
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&erase_cmd));
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("registering erase_namespace_cmd");
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&erase_namespace_cmd));
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("registering erase_config_cmd");
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&erase_networkmanager_cmd));
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("registering erase_config_cmd");
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&erase_config_cmd));
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("Done");
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&erase_wifimanager_cmd));
|
||||
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
@@ -8,5 +8,6 @@
|
||||
#
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
CFLAGS += -I$(COMPONENT_PATH)/../squeezelite-ota
|
||||
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/components/tools/
|
||||
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main
|
||||
7
components/cmd_system/CMakeLists.txt
Normal file
7
components/cmd_system/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
set(COMPONENT_ADD_INCLUDEDIRS .)
|
||||
|
||||
set(COMPONENT_SRCS "cmd_system.c")
|
||||
|
||||
set(COMPONENT_REQUIRES console spi_flash)
|
||||
|
||||
register_component()
|
||||
489
components/cmd_system/cmd_system.c
Normal file
489
components/cmd_system/cmd_system.c
Normal file
@@ -0,0 +1,489 @@
|
||||
/* Console example — various system commands
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_INFO
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "driver/uart.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "cmd_system.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "platform_esp32.h"
|
||||
#include "config.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/uart.h" // for the uart driver access
|
||||
|
||||
#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
|
||||
#define WITH_TASKS_INFO 1
|
||||
#endif
|
||||
|
||||
|
||||
static const char * TAG = "cmd_system";
|
||||
|
||||
static void register_free();
|
||||
static void register_heap();
|
||||
static void register_version();
|
||||
static void register_restart();
|
||||
static void register_deep_sleep();
|
||||
static void register_light_sleep();
|
||||
static void register_factory_boot();
|
||||
static void register_restart_ota();
|
||||
#if WITH_TASKS_INFO
|
||||
static void register_tasks();
|
||||
#endif
|
||||
|
||||
void register_system()
|
||||
{
|
||||
register_free();
|
||||
register_heap();
|
||||
register_version();
|
||||
register_restart();
|
||||
register_deep_sleep();
|
||||
register_light_sleep();
|
||||
register_factory_boot();
|
||||
register_restart_ota();
|
||||
#if WITH_TASKS_INFO
|
||||
register_tasks();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 'version' command */
|
||||
static int get_version(int argc, char **argv)
|
||||
{
|
||||
esp_chip_info_t info;
|
||||
esp_chip_info(&info);
|
||||
printf("IDF Version:%s\r\n", esp_get_idf_version());
|
||||
printf("Chip info:\r\n");
|
||||
printf("\tmodel:%s\r\n", info.model == CHIP_ESP32 ? "ESP32" : "Unknow");
|
||||
printf("\tcores:%d\r\n", info.cores);
|
||||
printf("\tfeature:%s%s%s%s%d%s\r\n",
|
||||
info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "",
|
||||
info.features & CHIP_FEATURE_BLE ? "/BLE" : "",
|
||||
info.features & CHIP_FEATURE_BT ? "/BT" : "",
|
||||
info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:",
|
||||
spi_flash_get_chip_size() / (1024 * 1024), " MB");
|
||||
printf("\trevision number:%d\r\n", info.revision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_version()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "version",
|
||||
.help = "Get version of chip and SDK",
|
||||
.hint = NULL,
|
||||
.func = &get_version,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
||||
/** 'restart' command restarts the program */
|
||||
|
||||
|
||||
esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
|
||||
{
|
||||
#if RECOVERY_APPLICATION
|
||||
if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){
|
||||
ESP_LOGW(TAG,"RECOVERY application is already active");
|
||||
if(!wait_for_commit()){
|
||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||
}
|
||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
||||
esp_restart();
|
||||
return ESP_OK;
|
||||
}
|
||||
#else
|
||||
if(partition_subtype !=ESP_PARTITION_SUBTYPE_APP_FACTORY){
|
||||
ESP_LOGW(TAG,"SQUEEZELITE application is already active");
|
||||
if(!wait_for_commit()){
|
||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||
}
|
||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
||||
esp_restart();
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
esp_err_t err = ESP_OK;
|
||||
bool bFound=false;
|
||||
ESP_LOGI(TAG, "Looking for partition type %u",partition_subtype);
|
||||
const esp_partition_t *partition;
|
||||
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, partition_subtype, NULL);
|
||||
|
||||
if(it == NULL){
|
||||
ESP_LOGE(TAG,"Unable initialize partition iterator!");
|
||||
set_status_message(ERROR, "Reboot failed. Cannot iterate through partitions");
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGD(TAG, "Found partition. Getting info.");
|
||||
partition = (esp_partition_t *) esp_partition_get(it);
|
||||
ESP_LOGD(TAG, "Releasing partition iterator");
|
||||
esp_partition_iterator_release(it);
|
||||
if(partition != NULL){
|
||||
ESP_LOGI(TAG, "Found application partition %s sub type %u", partition->label,partition_subtype);
|
||||
err=esp_ota_set_boot_partition(partition);
|
||||
if(err!=ESP_OK){
|
||||
ESP_LOGE(TAG,"Unable to set partition as active for next boot. %s",esp_err_to_name(err));
|
||||
bFound=false;
|
||||
set_status_message(ERROR, "Unable to select partition for reboot.");
|
||||
}
|
||||
else{
|
||||
ESP_LOGW(TAG, "Application partition %s sub type %u is selected for boot", partition->label,partition_subtype);
|
||||
bFound=true;
|
||||
set_status_message(WARNING, "Rebooting!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG,"partition type %u not found! Unable to reboot to recovery.",partition_subtype);
|
||||
set_status_message(ERROR, "Partition not found.");
|
||||
}
|
||||
ESP_LOGD(TAG, "Yielding to other processes");
|
||||
taskYIELD();
|
||||
if(bFound) {
|
||||
ESP_LOGW(TAG,"Configuration %s changes. ",config_has_changes()?"has":"does not have");
|
||||
if(!wait_for_commit()){
|
||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||
}
|
||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
||||
esp_restart();
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int restart(int argc, char **argv)
|
||||
{
|
||||
ESP_LOGW(TAG, "\n\nPerforming a simple restart to the currently active partition.");
|
||||
if(!wait_for_commit()){
|
||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||
}
|
||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
||||
esp_restart();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void simple_restart()
|
||||
{
|
||||
ESP_LOGW(TAG,"\n\n Called to perform a simple system reboot.");
|
||||
if(!wait_for_commit()){
|
||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
esp_err_t guided_restart_ota(){
|
||||
ESP_LOGW(TAG,"\n\nCalled for a reboot to OTA Application");
|
||||
guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0);
|
||||
return ESP_FAIL; // return fail. This should never return... we're rebooting!
|
||||
}
|
||||
esp_err_t guided_factory(){
|
||||
ESP_LOGW(TAG,"\n\nCalled for a reboot to recovery application");
|
||||
guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
|
||||
return ESP_FAIL; // return fail. This should never return... we're rebooting!
|
||||
}
|
||||
static int restart_factory(int argc, char **argv)
|
||||
{
|
||||
ESP_LOGW(TAG, "Executing guided boot into recovery");
|
||||
guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
|
||||
return 0; // return fail. This should never return... we're rebooting!
|
||||
}
|
||||
static int restart_ota(int argc, char **argv)
|
||||
{
|
||||
ESP_LOGW(TAG, "Executing guided boot into ota app 0");
|
||||
guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0);
|
||||
return 0; // return fail. This should never return... we're rebooting!
|
||||
}
|
||||
static void register_restart()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "restart",
|
||||
.help = "Software reset of the chip",
|
||||
.hint = NULL,
|
||||
.func = &restart,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
static void register_restart_ota()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "restart_ota",
|
||||
.help = "Selects the ota app partition to boot from and performa a software reset of the chip",
|
||||
.hint = NULL,
|
||||
.func = &restart_ota,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
||||
static void register_factory_boot()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "recovery",
|
||||
.help = "Resets and boot to recovery (if available)",
|
||||
.hint = NULL,
|
||||
.func = &restart_factory,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
/** 'free' command prints available heap memory */
|
||||
|
||||
static int free_mem(int argc, char **argv)
|
||||
{
|
||||
printf("%d\n", esp_get_free_heap_size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_free()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "free",
|
||||
.help = "Get the current size of free heap memory",
|
||||
.hint = NULL,
|
||||
.func = &free_mem,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
||||
/* 'heap' command prints minumum heap size */
|
||||
static int heap_size(int argc, char **argv)
|
||||
{
|
||||
uint32_t heap_size = heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT);
|
||||
ESP_LOGI(TAG, "min heap size: %u", heap_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_heap()
|
||||
{
|
||||
const esp_console_cmd_t heap_cmd = {
|
||||
.command = "heap",
|
||||
.help = "Get minimum size of free heap memory that was available during program execution",
|
||||
.hint = NULL,
|
||||
.func = &heap_size,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&heap_cmd) );
|
||||
|
||||
}
|
||||
|
||||
/** 'tasks' command prints the list of tasks and related information */
|
||||
#if WITH_TASKS_INFO
|
||||
|
||||
static int tasks_info(int argc, char **argv)
|
||||
{
|
||||
const size_t bytes_per_task = 40; /* see vTaskList description */
|
||||
char *task_list_buffer = malloc(uxTaskGetNumberOfTasks() * bytes_per_task);
|
||||
if (task_list_buffer == NULL) {
|
||||
ESP_LOGE(TAG, "failed to allocate buffer for vTaskList output");
|
||||
return 1;
|
||||
}
|
||||
fputs("Task Name\tStatus\tPrio\tHWM\tTask#", stdout);
|
||||
#ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
|
||||
fputs("\tAffinity", stdout);
|
||||
#endif
|
||||
fputs("\n", stdout);
|
||||
vTaskList(task_list_buffer);
|
||||
fputs(task_list_buffer, stdout);
|
||||
free(task_list_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_tasks()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "tasks",
|
||||
.help = "Get information about running tasks",
|
||||
.hint = NULL,
|
||||
.func = &tasks_info,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
||||
#endif // WITH_TASKS_INFO
|
||||
|
||||
/** 'deep_sleep' command puts the chip into deep sleep mode */
|
||||
|
||||
static struct {
|
||||
struct arg_int *wakeup_time;
|
||||
struct arg_int *wakeup_gpio_num;
|
||||
struct arg_int *wakeup_gpio_level;
|
||||
struct arg_end *end;
|
||||
} deep_sleep_args;
|
||||
|
||||
|
||||
static int deep_sleep(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **) &deep_sleep_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, deep_sleep_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (deep_sleep_args.wakeup_time->count) {
|
||||
uint64_t timeout = 1000ULL * deep_sleep_args.wakeup_time->ival[0];
|
||||
ESP_LOGI(TAG, "Enabling timer wakeup, timeout=%lluus", timeout);
|
||||
ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) );
|
||||
}
|
||||
if (deep_sleep_args.wakeup_gpio_num->count) {
|
||||
int io_num = deep_sleep_args.wakeup_gpio_num->ival[0];
|
||||
if (!rtc_gpio_is_valid_gpio(io_num)) {
|
||||
ESP_LOGE(TAG, "GPIO %d is not an RTC IO", io_num);
|
||||
return 1;
|
||||
}
|
||||
int level = 0;
|
||||
if (deep_sleep_args.wakeup_gpio_level->count) {
|
||||
level = deep_sleep_args.wakeup_gpio_level->ival[0];
|
||||
if (level != 0 && level != 1) {
|
||||
ESP_LOGE(TAG, "Invalid wakeup level: %d", level);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level",
|
||||
io_num, level ? "HIGH" : "LOW");
|
||||
|
||||
ESP_ERROR_CHECK( esp_sleep_enable_ext1_wakeup(1ULL << io_num, level) );
|
||||
}
|
||||
rtc_gpio_isolate(GPIO_NUM_12);
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
static void register_deep_sleep()
|
||||
{
|
||||
deep_sleep_args.wakeup_time =
|
||||
arg_int0("t", "time", "<t>", "Wake up time, ms");
|
||||
deep_sleep_args.wakeup_gpio_num =
|
||||
arg_int0(NULL, "io", "<n>",
|
||||
"If specified, wakeup using GPIO with given number");
|
||||
deep_sleep_args.wakeup_gpio_level =
|
||||
arg_int0(NULL, "io_level", "<0|1>", "GPIO level to trigger wakeup");
|
||||
deep_sleep_args.end = arg_end(3);
|
||||
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "deep_sleep",
|
||||
.help = "Enter deep sleep mode. "
|
||||
"Two wakeup modes are supported: timer and GPIO. "
|
||||
"If no wakeup option is specified, will sleep indefinitely.",
|
||||
.hint = NULL,
|
||||
.func = &deep_sleep,
|
||||
.argtable = &deep_sleep_args
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
||||
/** 'light_sleep' command puts the chip into light sleep mode */
|
||||
|
||||
static struct {
|
||||
struct arg_int *wakeup_time;
|
||||
struct arg_int *wakeup_gpio_num;
|
||||
struct arg_int *wakeup_gpio_level;
|
||||
struct arg_end *end;
|
||||
} light_sleep_args;
|
||||
|
||||
static int light_sleep(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **) &light_sleep_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, light_sleep_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
|
||||
if (light_sleep_args.wakeup_time->count) {
|
||||
uint64_t timeout = 1000ULL * light_sleep_args.wakeup_time->ival[0];
|
||||
ESP_LOGI(TAG, "Enabling timer wakeup, timeout=%lluus", timeout);
|
||||
ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) );
|
||||
}
|
||||
int io_count = light_sleep_args.wakeup_gpio_num->count;
|
||||
if (io_count != light_sleep_args.wakeup_gpio_level->count) {
|
||||
ESP_LOGE(TAG, "Should have same number of 'io' and 'io_level' arguments");
|
||||
return 1;
|
||||
}
|
||||
for (int i = 0; i < io_count; ++i) {
|
||||
int io_num = light_sleep_args.wakeup_gpio_num->ival[i];
|
||||
int level = light_sleep_args.wakeup_gpio_level->ival[i];
|
||||
if (level != 0 && level != 1) {
|
||||
ESP_LOGE(TAG, "Invalid wakeup level: %d", level);
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level",
|
||||
io_num, level ? "HIGH" : "LOW");
|
||||
|
||||
ESP_ERROR_CHECK( gpio_wakeup_enable(io_num, level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL) );
|
||||
}
|
||||
if (io_count > 0) {
|
||||
ESP_ERROR_CHECK( esp_sleep_enable_gpio_wakeup() );
|
||||
}
|
||||
if (CONFIG_CONSOLE_UART_NUM <= UART_NUM_1) {
|
||||
ESP_LOGI(TAG, "Enabling UART wakeup (press ENTER to exit light sleep)");
|
||||
ESP_ERROR_CHECK( uart_set_wakeup_threshold(CONFIG_CONSOLE_UART_NUM, 3) );
|
||||
ESP_ERROR_CHECK( esp_sleep_enable_uart_wakeup(CONFIG_CONSOLE_UART_NUM) );
|
||||
}
|
||||
fflush(stdout);
|
||||
uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM);
|
||||
esp_light_sleep_start();
|
||||
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||
const char *cause_str;
|
||||
switch (cause) {
|
||||
case ESP_SLEEP_WAKEUP_GPIO:
|
||||
cause_str = "GPIO";
|
||||
break;
|
||||
case ESP_SLEEP_WAKEUP_UART:
|
||||
cause_str = "UART";
|
||||
break;
|
||||
case ESP_SLEEP_WAKEUP_TIMER:
|
||||
cause_str = "timer";
|
||||
break;
|
||||
default:
|
||||
cause_str = "unknown";
|
||||
printf("%d\n", cause);
|
||||
}
|
||||
ESP_LOGI(TAG, "Woke up from: %s", cause_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_light_sleep()
|
||||
{
|
||||
light_sleep_args.wakeup_time =
|
||||
arg_int0("t", "time", "<t>", "Wake up time, ms");
|
||||
light_sleep_args.wakeup_gpio_num =
|
||||
arg_intn(NULL, "io", "<n>", 0, 8,
|
||||
"If specified, wakeup using GPIO with given number");
|
||||
light_sleep_args.wakeup_gpio_level =
|
||||
arg_intn(NULL, "io_level", "<0|1>", 0, 8, "GPIO level to trigger wakeup");
|
||||
light_sleep_args.end = arg_end(3);
|
||||
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "light_sleep",
|
||||
.help = "Enter light sleep mode. "
|
||||
"Two wakeup modes are supported: timer and GPIO. "
|
||||
"Multiple GPIO pins can be specified using pairs of "
|
||||
"'io' and 'io_level' arguments. "
|
||||
"Will also wake up on UART input.",
|
||||
.hint = NULL,
|
||||
.func = &light_sleep,
|
||||
.argtable = &light_sleep_args
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ void register_system();
|
||||
esp_err_t guided_factory();
|
||||
esp_err_t guided_restart_ota();
|
||||
void simple_restart();
|
||||
FILE * system_open_memstream(const char * cmdname,char **buf,size_t *buf_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
12
components/cmd_system/component.mk
Normal file
12
components/cmd_system/component.mk
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Component Makefile
|
||||
#
|
||||
# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
|
||||
# this will take the sources in the src/ directory, compile them and link them into
|
||||
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
|
||||
# please read the SDK documents if you need to do this.
|
||||
#
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main/
|
||||
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/components/tools/
|
||||
@@ -1,26 +0,0 @@
|
||||
idf_component_register(
|
||||
INCLUDE_DIRS . ./inc inc/alac inc/helix-aac inc/mad inc/resample16 inc/soxr inc/vorbis inc/opus
|
||||
)
|
||||
|
||||
if (DEFINED AAC_DISABLE_SBR)
|
||||
add_prebuilt_library(libhelix-aac lib/libhelix-aac.a )
|
||||
else ()
|
||||
add_prebuilt_library(libhelix-aac lib/libhelix-aac-sbr.a )
|
||||
endif()
|
||||
|
||||
add_prebuilt_library(libmad lib/libmad.a)
|
||||
add_prebuilt_library(libFLAC lib/libFLAC.a )
|
||||
add_prebuilt_library(libvorbisidec lib/libvorbisidec.a )
|
||||
add_prebuilt_library(libogg lib/libogg.a )
|
||||
add_prebuilt_library(libalac lib/libalac.a )
|
||||
add_prebuilt_library(libresample16 lib/libresample16.a )
|
||||
add_prebuilt_library(libopus lib/libopus.a )
|
||||
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE libmad)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE libFLAC)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE libhelix-aac)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE libvorbisidec)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE libogg)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE libalac)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE libresample16)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE libopus)
|
||||
@@ -1,6 +1,6 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2022 Xiph.Org Foundation
|
||||
* Copyright (C) 2011-2014 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -52,7 +52,7 @@
|
||||
* level idea of the structure and how to find the information you
|
||||
* need. As a prerequisite you should have at least a basic
|
||||
* knowledge of the FLAC format, documented
|
||||
* <A HREF="https://xiph.org/flac/format.html">here</A>.
|
||||
* <A HREF="../format.html">here</A>.
|
||||
*
|
||||
* \section c_api FLAC C API
|
||||
*
|
||||
@@ -64,7 +64,7 @@
|
||||
*
|
||||
* By writing a little code and linking against libFLAC, it is
|
||||
* relatively easy to add FLAC support to another program. The
|
||||
* library is licensed under <A HREF="https://xiph.org/flac/license.html">Xiph's BSD license</A>.
|
||||
* library is licensed under <A HREF="../license.html">Xiph's BSD license</A>.
|
||||
* Complete source code of libFLAC as well as the command-line
|
||||
* encoder and plugins is available and is a useful source of
|
||||
* examples.
|
||||
@@ -97,7 +97,7 @@
|
||||
* example /usr/include/FLAC++/...).
|
||||
*
|
||||
* libFLAC++ is also licensed under
|
||||
* <A HREF="https://xiph.org/flac/license.html">Xiph's BSD license</A>.
|
||||
* <A HREF="../license.html">Xiph's BSD license</A>.
|
||||
*
|
||||
* \section getting_started Getting Started
|
||||
*
|
||||
@@ -113,7 +113,7 @@
|
||||
* functions through the links in top bar across this page.
|
||||
*
|
||||
* If you prefer a more hands-on approach, you can jump right to some
|
||||
* <A HREF="https://xiph.org/flac/documentation_example_code.html">example code</A>.
|
||||
* <A HREF="../documentation_example_code.html">example code</A>.
|
||||
*
|
||||
* \section porting_guide Porting Guide
|
||||
*
|
||||
@@ -147,7 +147,7 @@
|
||||
* library.
|
||||
*
|
||||
* Also, there are several places in the libFLAC code with comments marked
|
||||
* with "OPT:" where a \#define can be changed to enable code that might be
|
||||
* with "OPT:" where a #define can be changed to enable code that might be
|
||||
* faster on a specific platform. Experimenting with these can yield faster
|
||||
* binaries.
|
||||
*/
|
||||
@@ -159,9 +159,9 @@
|
||||
* the libraries to newer versions of FLAC.
|
||||
*
|
||||
* One simple facility for making porting easier that has been added
|
||||
* in FLAC 1.1.3 is a set of \#defines in \c export.h of each
|
||||
* in FLAC 1.1.3 is a set of \c #defines in \c export.h of each
|
||||
* library's includes (e.g. \c include/FLAC/export.h). The
|
||||
* \#defines mirror the libraries'
|
||||
* \c #defines mirror the libraries'
|
||||
* <A HREF="http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning">libtool version numbers</A>,
|
||||
* e.g. in libFLAC there are \c FLAC_API_VERSION_CURRENT,
|
||||
* \c FLAC_API_VERSION_REVISION, and \c FLAC_API_VERSION_AGE.
|
||||
@@ -176,7 +176,7 @@
|
||||
* #endif
|
||||
* \endcode
|
||||
*
|
||||
* The source will work for multiple versions and the legacy code can
|
||||
* The the source will work for multiple versions and the legacy code can
|
||||
* easily be removed when the transition is complete.
|
||||
*
|
||||
* Another available symbol is FLAC_API_SUPPORTS_OGG_FLAC (defined in
|
||||
@@ -321,7 +321,7 @@
|
||||
*
|
||||
* The \a bytes parameter to FLAC__StreamDecoderReadCallback,
|
||||
* FLAC__StreamEncoderReadCallback, and FLAC__StreamEncoderWriteCallback
|
||||
* is now \c size_t instead of \c uint32_t.
|
||||
* is now \c size_t instead of \c unsigned.
|
||||
*/
|
||||
|
||||
/** \defgroup porting_1_1_3_to_1_1_4 Porting from FLAC 1.1.3 to 1.1.4
|
||||
@@ -357,85 +357,6 @@
|
||||
* \c FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN
|
||||
*/
|
||||
|
||||
/** \defgroup porting_1_3_4_to_1_4_0 Porting from FLAC 1.3.4 to 1.4.0
|
||||
* \ingroup porting
|
||||
*
|
||||
* \brief
|
||||
* This module describes porting from FLAC 1.3.4 to FLAC 1.4.0.
|
||||
*
|
||||
* \section porting_1_3_4_to_1_4_0_summary Summary
|
||||
*
|
||||
* Between FLAC 1.3.4 and FLAC 1.4.0, there have four breaking changes
|
||||
* - the function get_client_data_from_decoder has been renamed to
|
||||
* FLAC__get_decoder_client_data
|
||||
* - some data types in the FLAC__Frame struct have changed
|
||||
* - all functions resizing metadata blocks now return the object
|
||||
* untouched if memory allocation fails, whereas previously the
|
||||
* handling varied and was more or less undefined
|
||||
* - all functions accepting a filename now take UTF-8 encoded filenames
|
||||
* on Windows instead of filenames in the current codepage
|
||||
*
|
||||
* Furthermore, there have been the following additions
|
||||
* - the functions FLAC__stream_encoder_set_limit_min_bitrate,
|
||||
* FLAC__stream_encoder_get_limit_min_bitrate,
|
||||
* FLAC::encoder::file::set_limit_min_bitrate() and
|
||||
* FLAC::encoder::file::get_limit_min_bitrate() have been added
|
||||
* - Added FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA to the
|
||||
* FLAC__StreamDecoderErrorStatus enum
|
||||
*
|
||||
* \section porting_1_3_4_to_1_4_0_breaking Breaking changes
|
||||
*
|
||||
* The function \b get_client_data_from_decoder was added in FLAC 1.3.3
|
||||
* but did not follow the API naming convention and was not properly
|
||||
* exported. The function is now renamed and properly integrated as
|
||||
* FLAC__stream_decoder_get_client_data
|
||||
*
|
||||
* To accomodate encoding and decoding 32-bit int PCM, some data types
|
||||
* in the \b FLAC__frame struct were changed. Specifically, warmup
|
||||
* in both the FLAC__Subframe_Fixed struc and the FLAC__Subframe_LPC
|
||||
* struct is changed from FLAC__int32 to FLAC__int64. Also, value
|
||||
* in the FLAC__Subframe_Constant is changed from FLAC__int32 to
|
||||
* FLAC__int64. Finally, in FLAC__Subframe_Verbatim struct data is
|
||||
* changes from a FLAC__int32 array to a union containing a FLAC__int32
|
||||
* array and a FLAC__int64 array. Also, a new member is added,
|
||||
* data_type, which clarifies whether the FLAC__int32 or FLAC__int64
|
||||
* array is in use.
|
||||
*
|
||||
* Furthermore, the following functions now return the object untouched
|
||||
* if memory allocation fails, whereas previously the handling varied
|
||||
* and was more or less undefined
|
||||
*
|
||||
* - FLAC__metadata_object_seektable_resize_points
|
||||
* - FLAC__metadata_object_vorbiscomment_resize_comments
|
||||
* - FLAC__metadata_object_cuesheet_track_resize_indices
|
||||
* - FLAC__metadata_object_cuesheet_resize_tracks
|
||||
*
|
||||
* The last breaking change is that all API functions taking a filename
|
||||
* as an argument now, on Windows, must be supplied with that filename
|
||||
* in the UTF-8 character encoding instead of using the current code
|
||||
* page. libFLAC internally translates these UTF-8 encoded filenames to
|
||||
* an appropriate representation to use with _wfopen. On all other
|
||||
* systems, filename is passed to fopen without any translation, as it
|
||||
* in libFLAC 1.3.4 and earlier.
|
||||
*
|
||||
* \section porting_1_3_4_to_1_4_0_additions Additions
|
||||
*
|
||||
* To aid in creating properly streamable FLAC files, a set of functions
|
||||
* was added to make it possible to enfore a minimum bitrate to files
|
||||
* created through libFLAC's stream_encoder.h interface. With this
|
||||
* function enabled the resulting FLAC files have a minimum bitrate of
|
||||
* 1bit/sample independent of the number of channels, i.e. 48kbit/s for
|
||||
* 48kHz. This can be beneficial for streaming, as very low bitrates for
|
||||
* silent sections compressed with 'constant' subframes can result in a
|
||||
* bitrate of 1kbit/s, creating problems with clients that aren't aware
|
||||
* of this possibility and buffer too much data.
|
||||
*
|
||||
* Finally, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA was added to
|
||||
* the FLAC__StreamDecoderErrorStatus enum to signal that the decoder
|
||||
* encountered unreadable metadata.
|
||||
*
|
||||
*/
|
||||
|
||||
/** \defgroup flac FLAC C API
|
||||
*
|
||||
* The FLAC C API is the interface to libFLAC, a set of structures
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2022 Xiph.Org Foundation
|
||||
* Copyright (C) 2011-2014 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -34,11 +34,7 @@
|
||||
#define FLAC__ASSERT_H
|
||||
|
||||
/* we need this since some compilers (like MSVC) leave assert()s on release code (and we don't want to use their ASSERT) */
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
#define FLAC__ASSERT(x) if(!(x)) __builtin_abort();
|
||||
#define FLAC__ASSERT_DECLARATION(x) x
|
||||
#else
|
||||
#ifndef NDEBUG
|
||||
#ifdef DEBUG
|
||||
#include <assert.h>
|
||||
#define FLAC__ASSERT(x) assert(x)
|
||||
#define FLAC__ASSERT_DECLARATION(x) x
|
||||
@@ -46,6 +42,5 @@
|
||||
#define FLAC__ASSERT(x)
|
||||
#define FLAC__ASSERT_DECLARATION(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2004-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2022 Xiph.Org Foundation
|
||||
* Copyright (C) 2011-2014 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -165,15 +165,15 @@ typedef int (*FLAC__IOCallback_Close) (FLAC__IOHandle handle);
|
||||
* required may be set to NULL.
|
||||
*
|
||||
* If the seek requirement for an interface is optional, you can signify that
|
||||
* a data source is not seekable by setting the \a seek field to \c NULL.
|
||||
* a data sorce is not seekable by setting the \a seek field to \c NULL.
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__IOCallback_Read read; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Write write; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Seek seek; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Tell tell; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Eof eof; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Close close; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Read read;
|
||||
FLAC__IOCallback_Write write;
|
||||
FLAC__IOCallback_Seek seek;
|
||||
FLAC__IOCallback_Tell tell;
|
||||
FLAC__IOCallback_Eof eof;
|
||||
FLAC__IOCallback_Close close;
|
||||
} FLAC__IOCallbacks;
|
||||
|
||||
/* \} */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2022 Xiph.Org Foundation
|
||||
* Copyright (C) 2011-2014 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -36,7 +36,7 @@
|
||||
/** \file include/FLAC/export.h
|
||||
*
|
||||
* \brief
|
||||
* This module contains \#defines and symbols for exporting function
|
||||
* This module contains #defines and symbols for exporting function
|
||||
* calls, and providing version information and compiled-in features.
|
||||
*
|
||||
* See the \link flac_export export \endlink module.
|
||||
@@ -46,43 +46,25 @@
|
||||
* \ingroup flac
|
||||
*
|
||||
* \brief
|
||||
* This module contains \#defines and symbols for exporting function
|
||||
* This module contains #defines and symbols for exporting function
|
||||
* calls, and providing version information and compiled-in features.
|
||||
*
|
||||
* If you are compiling for Windows (with Visual Studio or MinGW for
|
||||
* example) and will link to the static library (libFLAC++.lib) you
|
||||
* should define FLAC__NO_DLL in your project to make sure the symbols
|
||||
* are exported properly.
|
||||
* If you are compiling with MSVC and will link to the static library
|
||||
* (libFLAC.lib) you should define FLAC__NO_DLL in your project to
|
||||
* make sure the symbols are exported properly.
|
||||
*
|
||||
* \{
|
||||
*/
|
||||
|
||||
/** This \#define is used internally in libFLAC and its headers to make
|
||||
* sure the correct symbols are exported when working with shared
|
||||
* libraries. On Windows, this \#define is set to __declspec(dllexport)
|
||||
* when compiling libFLAC into a library and to __declspec(dllimport)
|
||||
* when the headers are used to link to that DLL. On non-Windows systems
|
||||
* it is used to set symbol visibility.
|
||||
*
|
||||
* Because of this, the define FLAC__NO_DLL must be defined when linking
|
||||
* to libFLAC statically or linking will fail.
|
||||
*/
|
||||
/* This has grown quite complicated. FLAC__NO_DLL is used by MSVC sln
|
||||
* files and CMake, which build either static or shared. autotools can
|
||||
* build static, shared or **both**. Therefore, DLL_EXPORT, which is set
|
||||
* by libtool, must override FLAC__NO_DLL on building shared components
|
||||
*/
|
||||
#if defined(_WIN32)
|
||||
|
||||
#if defined(FLAC__NO_DLL) && !(defined(DLL_EXPORT))
|
||||
#if defined(FLAC__NO_DLL)
|
||||
#define FLAC_API
|
||||
#else
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
#ifdef FLAC_API_EXPORTS
|
||||
#define FLAC_API __declspec(dllexport)
|
||||
#else
|
||||
#define FLAC_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined(FLAC__USE_VISIBILITY_ATTR)
|
||||
#define FLAC_API __attribute__ ((visibility ("default")))
|
||||
@@ -92,12 +74,12 @@
|
||||
|
||||
#endif
|
||||
|
||||
/** These \#defines will mirror the libtool-based library version number, see
|
||||
/** These #defines will mirror the libtool-based library version number, see
|
||||
* http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning
|
||||
*/
|
||||
#define FLAC_API_VERSION_CURRENT 12
|
||||
#define FLAC_API_VERSION_CURRENT 11
|
||||
#define FLAC_API_VERSION_REVISION 0 /**< see above */
|
||||
#define FLAC_API_VERSION_AGE 0 /**< see above */
|
||||
#define FLAC_API_VERSION_AGE 3 /**< see above */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2022 Xiph.Org Foundation
|
||||
* Copyright (C) 2011-2014 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -60,7 +60,7 @@ extern "C" {
|
||||
* structures used by the rest of the interfaces.
|
||||
*
|
||||
* First, you should be familiar with the
|
||||
* <A HREF="https://xiph.org/flac/format.html">FLAC format</A>. Many of the values here
|
||||
* <A HREF="../format.html">FLAC format</A>. Many of the values here
|
||||
* follow directly from the specification. As a user of libFLAC, the
|
||||
* interesting parts really are the structures that describe the frame
|
||||
* header and metadata blocks.
|
||||
@@ -113,16 +113,19 @@ extern "C" {
|
||||
|
||||
/** The maximum sample resolution permitted by libFLAC.
|
||||
*
|
||||
* \warning
|
||||
* FLAC__MAX_BITS_PER_SAMPLE is the limit of the FLAC format. However,
|
||||
* the reference encoder/decoder used to be limited to 24 bits. This
|
||||
* value was used to signal that limit.
|
||||
* the reference encoder/decoder is currently limited to 24 bits because
|
||||
* of prevalent 32-bit math, so make sure and use this value when
|
||||
* appropriate.
|
||||
*/
|
||||
#define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (32u)
|
||||
#define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (24u)
|
||||
|
||||
/** The maximum sample rate permitted by the format. The value is
|
||||
* ((2 ^ 20) - 1)
|
||||
* ((2 ^ 16) - 1) * 10; see <A HREF="../format.html">FLAC format</A>
|
||||
* as to why.
|
||||
*/
|
||||
#define FLAC__MAX_SAMPLE_RATE (1048575u)
|
||||
#define FLAC__MAX_SAMPLE_RATE (655350u)
|
||||
|
||||
/** The maximum LPC order permitted by the format. */
|
||||
#define FLAC__MAX_LPC_ORDER (32u)
|
||||
@@ -170,10 +173,10 @@ extern FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */
|
||||
/** The 32-bit integer big-endian representation of the beginning of
|
||||
* a FLAC stream.
|
||||
*/
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_SYNC; /* = 0x664C6143 */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */
|
||||
|
||||
/** The length of the FLAC signature in bits. */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_SYNC_LEN; /* = 32 bits */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */
|
||||
|
||||
/** The length of the FLAC signature in bytes. */
|
||||
#define FLAC__STREAM_SYNC_LENGTH (4u)
|
||||
@@ -210,26 +213,26 @@ extern FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[];
|
||||
*/
|
||||
typedef struct {
|
||||
|
||||
uint32_t *parameters;
|
||||
unsigned *parameters;
|
||||
/**< The Rice parameters for each context. */
|
||||
|
||||
uint32_t *raw_bits;
|
||||
unsigned *raw_bits;
|
||||
/**< Widths for escape-coded partitions. Will be non-zero for escaped
|
||||
* partitions and zero for unescaped partitions.
|
||||
*/
|
||||
|
||||
uint32_t capacity_by_order;
|
||||
unsigned capacity_by_order;
|
||||
/**< The capacity of the \a parameters and \a raw_bits arrays
|
||||
* specified as an order, i.e. the number of array elements
|
||||
* allocated is 2 ^ \a capacity_by_order.
|
||||
*/
|
||||
} FLAC__EntropyCodingMethod_PartitionedRiceContents;
|
||||
|
||||
/** Header for a Rice partitioned residual. (c.f. <A HREF="https://xiph.org/flac/format.html#partitioned_rice">format specification</A>)
|
||||
/** Header for a Rice partitioned residual. (c.f. <A HREF="../format.html#partitioned_rice">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
|
||||
uint32_t order;
|
||||
unsigned order;
|
||||
/**< The partition order, i.e. # of contexts = 2 ^ \a order. */
|
||||
|
||||
const FLAC__EntropyCodingMethod_PartitionedRiceContents *contents;
|
||||
@@ -237,17 +240,17 @@ typedef struct {
|
||||
|
||||
} FLAC__EntropyCodingMethod_PartitionedRice;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN; /**< == 5 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN; /**< == 5 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN; /**< == 5 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN; /**< == 5 (bits) */
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
|
||||
extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
|
||||
/**< == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)-1 */
|
||||
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER;
|
||||
extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER;
|
||||
/**< == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN)-1 */
|
||||
|
||||
/** Header for the entropy coding method. (c.f. <A HREF="https://xiph.org/flac/format.html#residual">format specification</A>)
|
||||
/** Header for the entropy coding method. (c.f. <A HREF="../format.html#residual">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__EntropyCodingMethodType type;
|
||||
@@ -256,7 +259,7 @@ typedef struct {
|
||||
} data;
|
||||
} FLAC__EntropyCodingMethod;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_TYPE_LEN; /**< == 2 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN; /**< == 2 (bits) */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -276,40 +279,30 @@ typedef enum {
|
||||
extern FLAC_API const char * const FLAC__SubframeTypeString[];
|
||||
|
||||
|
||||
/** CONSTANT subframe. (c.f. <A HREF="https://xiph.org/flac/format.html#subframe_constant">format specification</A>)
|
||||
/** CONSTANT subframe. (c.f. <A HREF="../format.html#subframe_constant">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__int64 value; /**< The constant signal value. */
|
||||
FLAC__int32 value; /**< The constant signal value. */
|
||||
} FLAC__Subframe_Constant;
|
||||
|
||||
/** An enumeration of the possible verbatim subframe data types. */
|
||||
typedef enum {
|
||||
FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT32, /**< verbatim subframe has 32-bit int */
|
||||
FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT64 /**< verbatim subframe has 64-bit int */
|
||||
} FLAC__VerbatimSubframeDataType;
|
||||
|
||||
|
||||
/** VERBATIM subframe. (c.f. <A HREF="https://xiph.org/flac/format.html#subframe_verbatim">format specification</A>)
|
||||
/** VERBATIM subframe. (c.f. <A HREF="../format.html#subframe_verbatim">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
const FLAC__int32 *int32; /**< A FLAC__int32 pointer to verbatim signal. */
|
||||
const FLAC__int64 *int64; /**< A FLAC__int64 pointer to verbatim signal. */
|
||||
} data;
|
||||
FLAC__VerbatimSubframeDataType data_type;
|
||||
const FLAC__int32 *data; /**< A pointer to verbatim signal. */
|
||||
} FLAC__Subframe_Verbatim;
|
||||
|
||||
|
||||
/** FIXED subframe. (c.f. <A HREF="https://xiph.org/flac/format.html#subframe_fixed">format specification</A>)
|
||||
/** FIXED subframe. (c.f. <A HREF="../format.html#subframe_fixed">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__EntropyCodingMethod entropy_coding_method;
|
||||
/**< The residual coding method. */
|
||||
|
||||
uint32_t order;
|
||||
unsigned order;
|
||||
/**< The polynomial order. */
|
||||
|
||||
FLAC__int64 warmup[FLAC__MAX_FIXED_ORDER];
|
||||
FLAC__int32 warmup[FLAC__MAX_FIXED_ORDER];
|
||||
/**< Warmup samples to prime the predictor, length == order. */
|
||||
|
||||
const FLAC__int32 *residual;
|
||||
@@ -317,16 +310,16 @@ typedef struct {
|
||||
} FLAC__Subframe_Fixed;
|
||||
|
||||
|
||||
/** LPC subframe. (c.f. <A HREF="https://xiph.org/flac/format.html#subframe_lpc">format specification</A>)
|
||||
/** LPC subframe. (c.f. <A HREF="../format.html#subframe_lpc">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__EntropyCodingMethod entropy_coding_method;
|
||||
/**< The residual coding method. */
|
||||
|
||||
uint32_t order;
|
||||
unsigned order;
|
||||
/**< The FIR order. */
|
||||
|
||||
uint32_t qlp_coeff_precision;
|
||||
unsigned qlp_coeff_precision;
|
||||
/**< Quantized FIR filter coefficient precision in bits. */
|
||||
|
||||
int quantization_level;
|
||||
@@ -335,18 +328,18 @@ typedef struct {
|
||||
FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
|
||||
/**< FIR filter coefficients. */
|
||||
|
||||
FLAC__int64 warmup[FLAC__MAX_LPC_ORDER];
|
||||
FLAC__int32 warmup[FLAC__MAX_LPC_ORDER];
|
||||
/**< Warmup samples to prime the predictor, length == order. */
|
||||
|
||||
const FLAC__int32 *residual;
|
||||
/**< The residual signal, length == (blocksize minus order) samples. */
|
||||
} FLAC__Subframe_LPC;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN; /**< == 5 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN; /**< == 5 (bits) */
|
||||
|
||||
|
||||
/** FLAC subframe structure. (c.f. <A HREF="https://xiph.org/flac/format.html#subframe">format specification</A>)
|
||||
/** FLAC subframe structure. (c.f. <A HREF="../format.html#subframe">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__SubframeType type;
|
||||
@@ -356,7 +349,7 @@ typedef struct {
|
||||
FLAC__Subframe_LPC lpc;
|
||||
FLAC__Subframe_Verbatim verbatim;
|
||||
} data;
|
||||
uint32_t wasted_bits;
|
||||
unsigned wasted_bits;
|
||||
} FLAC__Subframe;
|
||||
|
||||
/** == 1 (bit)
|
||||
@@ -366,14 +359,14 @@ typedef struct {
|
||||
* mandatory value of \c 0 but in the future may take on the value \c 0 or \c 1
|
||||
* to mean something else.
|
||||
*/
|
||||
extern FLAC_API const uint32_t FLAC__SUBFRAME_ZERO_PAD_LEN;
|
||||
extern FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_LEN; /**< == 6 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN;
|
||||
extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN; /**< == 6 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN; /**< == 1 (bit) */
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK; /**< = 0x00 */
|
||||
extern FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK; /**< = 0x02 */
|
||||
extern FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK; /**< = 0x10 */
|
||||
extern FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK; /**< = 0x40 */
|
||||
extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK; /**< = 0x00 */
|
||||
extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK; /**< = 0x02 */
|
||||
extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK; /**< = 0x10 */
|
||||
extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK; /**< = 0x40 */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -413,22 +406,22 @@ typedef enum {
|
||||
extern FLAC_API const char * const FLAC__FrameNumberTypeString[];
|
||||
|
||||
|
||||
/** FLAC frame header structure. (c.f. <A HREF="https://xiph.org/flac/format.html#frame_header">format specification</A>)
|
||||
/** FLAC frame header structure. (c.f. <A HREF="../format.html#frame_header">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t blocksize;
|
||||
unsigned blocksize;
|
||||
/**< The number of samples per subframe. */
|
||||
|
||||
uint32_t sample_rate;
|
||||
unsigned sample_rate;
|
||||
/**< The sample rate in Hz. */
|
||||
|
||||
uint32_t channels;
|
||||
unsigned channels;
|
||||
/**< The number of channels (== number of subframes). */
|
||||
|
||||
FLAC__ChannelAssignment channel_assignment;
|
||||
/**< The channel assignment for the frame. */
|
||||
|
||||
uint32_t bits_per_sample;
|
||||
unsigned bits_per_sample;
|
||||
/**< The sample resolution. */
|
||||
|
||||
FLAC__FrameNumberType number_type;
|
||||
@@ -450,19 +443,19 @@ typedef struct {
|
||||
*/
|
||||
} FLAC__FrameHeader;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_SYNC; /**< == 0x3ffe; the frame header sync code */
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_SYNC_LEN; /**< == 14 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_RESERVED_LEN; /**< == 1 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN; /**< == 1 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_BLOCK_SIZE_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_SAMPLE_RATE_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN; /**< == 3 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_ZERO_PAD_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_HEADER_CRC_LEN; /**< == 8 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC; /**< == 0x3ffe; the frame header sync code */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN; /**< == 14 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN; /**< == 1 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN; /**< == 1 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN; /**< == 4 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN; /**< == 3 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN; /**< == 8 (bits) */
|
||||
|
||||
|
||||
/** FLAC frame footer structure. (c.f. <A HREF="https://xiph.org/flac/format.html#frame_footer">format specification</A>)
|
||||
/** FLAC frame footer structure. (c.f. <A HREF="../format.html#frame_footer">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__uint16 crc;
|
||||
@@ -472,10 +465,10 @@ typedef struct {
|
||||
*/
|
||||
} FLAC__FrameFooter;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__FRAME_FOOTER_CRC_LEN; /**< == 16 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN; /**< == 16 (bits) */
|
||||
|
||||
|
||||
/** FLAC frame structure. (c.f. <A HREF="https://xiph.org/flac/format.html#frame">format specification</A>)
|
||||
/** FLAC frame structure. (c.f. <A HREF="../format.html#frame">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__FrameHeader header;
|
||||
@@ -496,31 +489,31 @@ typedef struct {
|
||||
typedef enum {
|
||||
|
||||
FLAC__METADATA_TYPE_STREAMINFO = 0,
|
||||
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_streaminfo">STREAMINFO</A> block */
|
||||
/**< <A HREF="../format.html#metadata_block_streaminfo">STREAMINFO</A> block */
|
||||
|
||||
FLAC__METADATA_TYPE_PADDING = 1,
|
||||
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_padding">PADDING</A> block */
|
||||
/**< <A HREF="../format.html#metadata_block_padding">PADDING</A> block */
|
||||
|
||||
FLAC__METADATA_TYPE_APPLICATION = 2,
|
||||
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_application">APPLICATION</A> block */
|
||||
/**< <A HREF="../format.html#metadata_block_application">APPLICATION</A> block */
|
||||
|
||||
FLAC__METADATA_TYPE_SEEKTABLE = 3,
|
||||
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_seektable">SEEKTABLE</A> block */
|
||||
/**< <A HREF="../format.html#metadata_block_seektable">SEEKTABLE</A> block */
|
||||
|
||||
FLAC__METADATA_TYPE_VORBIS_COMMENT = 4,
|
||||
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_vorbis_comment">VORBISCOMMENT</A> block (a.k.a. FLAC tags) */
|
||||
/**< <A HREF="../format.html#metadata_block_vorbis_comment">VORBISCOMMENT</A> block (a.k.a. FLAC tags) */
|
||||
|
||||
FLAC__METADATA_TYPE_CUESHEET = 5,
|
||||
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_cuesheet">CUESHEET</A> block */
|
||||
/**< <A HREF="../format.html#metadata_block_cuesheet">CUESHEET</A> block */
|
||||
|
||||
FLAC__METADATA_TYPE_PICTURE = 6,
|
||||
/**< <A HREF="https://xiph.org/flac/format.html#metadata_block_picture">PICTURE</A> block */
|
||||
/**< <A HREF="../format.html#metadata_block_picture">PICTURE</A> block */
|
||||
|
||||
FLAC__METADATA_TYPE_UNDEFINED = 7,
|
||||
/**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */
|
||||
|
||||
FLAC__MAX_METADATA_TYPE = FLAC__MAX_METADATA_TYPE_CODE,
|
||||
/**< No type will ever be greater than this. There is not enough room in the protocol block. */
|
||||
FLAC__MAX_METADATA_TYPE = FLAC__MAX_METADATA_TYPE_CODE,
|
||||
/**< No type will ever be greater than this. There is not enough room in the protocol block. */
|
||||
} FLAC__MetadataType;
|
||||
|
||||
/** Maps a FLAC__MetadataType to a C string.
|
||||
@@ -531,32 +524,32 @@ typedef enum {
|
||||
extern FLAC_API const char * const FLAC__MetadataTypeString[];
|
||||
|
||||
|
||||
/** FLAC STREAMINFO structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_streaminfo">format specification</A>)
|
||||
/** FLAC STREAMINFO structure. (c.f. <A HREF="../format.html#metadata_block_streaminfo">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t min_blocksize, max_blocksize;
|
||||
uint32_t min_framesize, max_framesize;
|
||||
uint32_t sample_rate;
|
||||
uint32_t channels;
|
||||
uint32_t bits_per_sample;
|
||||
unsigned min_blocksize, max_blocksize;
|
||||
unsigned min_framesize, max_framesize;
|
||||
unsigned sample_rate;
|
||||
unsigned channels;
|
||||
unsigned bits_per_sample;
|
||||
FLAC__uint64 total_samples;
|
||||
FLAC__byte md5sum[16];
|
||||
} FLAC__StreamMetadata_StreamInfo;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; /**< == 16 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; /**< == 16 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; /**< == 24 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; /**< == 24 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; /**< == 20 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; /**< == 3 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; /**< == 5 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; /**< == 36 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN; /**< == 128 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; /**< == 16 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; /**< == 16 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; /**< == 24 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; /**< == 24 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; /**< == 20 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; /**< == 3 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; /**< == 5 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; /**< == 36 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN; /**< == 128 (bits) */
|
||||
|
||||
/** The total stream length of the STREAMINFO block in bytes. */
|
||||
#define FLAC__STREAM_METADATA_STREAMINFO_LENGTH (34u)
|
||||
|
||||
/** FLAC PADDING structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_padding">format specification</A>)
|
||||
/** FLAC PADDING structure. (c.f. <A HREF="../format.html#metadata_block_padding">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
int dummy;
|
||||
@@ -567,16 +560,16 @@ typedef struct {
|
||||
} FLAC__StreamMetadata_Padding;
|
||||
|
||||
|
||||
/** FLAC APPLICATION structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_application">format specification</A>)
|
||||
/** FLAC APPLICATION structure. (c.f. <A HREF="../format.html#metadata_block_application">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__byte id[4];
|
||||
FLAC__byte *data;
|
||||
} FLAC__StreamMetadata_Application;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_APPLICATION_ID_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN; /**< == 32 (bits) */
|
||||
|
||||
/** SeekPoint structure used in SEEKTABLE blocks. (c.f. <A HREF="https://xiph.org/flac/format.html#seekpoint">format specification</A>)
|
||||
/** SeekPoint structure used in SEEKTABLE blocks. (c.f. <A HREF="../format.html#seekpoint">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__uint64 sample_number;
|
||||
@@ -586,13 +579,13 @@ typedef struct {
|
||||
/**< The offset, in bytes, of the target frame with respect to
|
||||
* beginning of the first frame. */
|
||||
|
||||
uint32_t frame_samples;
|
||||
unsigned frame_samples;
|
||||
/**< The number of samples in the target frame. */
|
||||
} FLAC__StreamMetadata_SeekPoint;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN; /**< == 64 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN; /**< == 64 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN; /**< == 16 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN; /**< == 64 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN; /**< == 64 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN; /**< == 16 (bits) */
|
||||
|
||||
/** The total stream length of a seek point in bytes. */
|
||||
#define FLAC__STREAM_METADATA_SEEKPOINT_LENGTH (18u)
|
||||
@@ -604,7 +597,7 @@ extern FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN
|
||||
extern FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
|
||||
|
||||
|
||||
/** FLAC SEEKTABLE structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_seektable">format specification</A>)
|
||||
/** FLAC SEEKTABLE structure. (c.f. <A HREF="../format.html#metadata_block_seektable">format specification</A>)
|
||||
*
|
||||
* \note From the format specification:
|
||||
* - The seek points must be sorted by ascending sample number.
|
||||
@@ -617,12 +610,12 @@ extern FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
|
||||
* present in a stream.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t num_points;
|
||||
unsigned num_points;
|
||||
FLAC__StreamMetadata_SeekPoint *points;
|
||||
} FLAC__StreamMetadata_SeekTable;
|
||||
|
||||
|
||||
/** Vorbis comment entry structure used in VORBIS_COMMENT blocks. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_vorbis_comment">format specification</A>)
|
||||
/** Vorbis comment entry structure used in VORBIS_COMMENT blocks. (c.f. <A HREF="../format.html#metadata_block_vorbis_comment">format specification</A>)
|
||||
*
|
||||
* For convenience, the APIs maintain a trailing NUL character at the end of
|
||||
* \a entry which is not counted toward \a length, i.e.
|
||||
@@ -633,10 +626,10 @@ typedef struct {
|
||||
FLAC__byte *entry;
|
||||
} FLAC__StreamMetadata_VorbisComment_Entry;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN; /**< == 32 (bits) */
|
||||
|
||||
|
||||
/** FLAC VORBIS_COMMENT structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block_vorbis_comment">format specification</A>)
|
||||
/** FLAC VORBIS_COMMENT structure. (c.f. <A HREF="../format.html#metadata_block_vorbis_comment">format specification</A>)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__StreamMetadata_VorbisComment_Entry vendor_string;
|
||||
@@ -644,11 +637,11 @@ typedef struct {
|
||||
FLAC__StreamMetadata_VorbisComment_Entry *comments;
|
||||
} FLAC__StreamMetadata_VorbisComment;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN; /**< == 32 (bits) */
|
||||
|
||||
|
||||
/** FLAC CUESHEET track index structure. (See the
|
||||
* <A HREF="https://xiph.org/flac/format.html#cuesheet_track_index">format specification</A> for
|
||||
* <A HREF="../format.html#cuesheet_track_index">format specification</A> for
|
||||
* the full description of each field.)
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -661,13 +654,13 @@ typedef struct {
|
||||
/**< The index point number. */
|
||||
} FLAC__StreamMetadata_CueSheet_Index;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN; /**< == 64 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN; /**< == 8 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN; /**< == 3*8 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN; /**< == 64 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN; /**< == 8 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN; /**< == 3*8 (bits) */
|
||||
|
||||
|
||||
/** FLAC CUESHEET track structure. (See the
|
||||
* <A HREF="https://xiph.org/flac/format.html#cuesheet_track">format specification</A> for
|
||||
* <A HREF="../format.html#cuesheet_track">format specification</A> for
|
||||
* the full description of each field.)
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -680,10 +673,10 @@ typedef struct {
|
||||
char isrc[13];
|
||||
/**< Track ISRC. This is a 12-digit alphanumeric code plus a trailing \c NUL byte */
|
||||
|
||||
uint32_t type:1;
|
||||
unsigned type:1;
|
||||
/**< The track type: 0 for audio, 1 for non-audio. */
|
||||
|
||||
uint32_t pre_emphasis:1;
|
||||
unsigned pre_emphasis:1;
|
||||
/**< The pre-emphasis flag: 0 for no pre-emphasis, 1 for pre-emphasis. */
|
||||
|
||||
FLAC__byte num_indices;
|
||||
@@ -694,17 +687,17 @@ typedef struct {
|
||||
|
||||
} FLAC__StreamMetadata_CueSheet_Track;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN; /**< == 64 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN; /**< == 8 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN; /**< == 12*8 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN; /**< == 6+13*8 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN; /**< == 8 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN; /**< == 64 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN; /**< == 8 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN; /**< == 12*8 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN; /**< == 6+13*8 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN; /**< == 8 (bits) */
|
||||
|
||||
|
||||
/** FLAC CUESHEET structure. (See the
|
||||
* <A HREF="https://xiph.org/flac/format.html#metadata_block_cuesheet">format specification</A>
|
||||
* <A HREF="../format.html#metadata_block_cuesheet">format specification</A>
|
||||
* for the full description of each field.)
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -720,7 +713,7 @@ typedef struct {
|
||||
FLAC__bool is_cd;
|
||||
/**< \c true if CUESHEET corresponds to a Compact Disc, else \c false. */
|
||||
|
||||
uint32_t num_tracks;
|
||||
unsigned num_tracks;
|
||||
/**< The number of tracks. */
|
||||
|
||||
FLAC__StreamMetadata_CueSheet_Track *tracks;
|
||||
@@ -728,11 +721,11 @@ typedef struct {
|
||||
|
||||
} FLAC__StreamMetadata_CueSheet;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN; /**< == 128*8 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN; /**< == 64 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN; /**< == 7+258*8 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN; /**< == 128*8 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN; /**< == 64 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN; /**< == 7+258*8 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */
|
||||
|
||||
|
||||
/** An enumeration of the PICTURE types (see FLAC__StreamMetadataPicture and id3 v2.4 APIC tag). */
|
||||
@@ -770,7 +763,7 @@ typedef enum {
|
||||
extern FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[];
|
||||
|
||||
/** FLAC PICTURE structure. (See the
|
||||
* <A HREF="https://xiph.org/flac/format.html#metadata_block_picture">format specification</A>
|
||||
* <A HREF="../format.html#metadata_block_picture">format specification</A>
|
||||
* for the full description of each field.)
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -817,14 +810,14 @@ typedef struct {
|
||||
|
||||
} FLAC__StreamMetadata_Picture;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_TYPE_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_COLORS_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN; /**< == 32 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN; /**< == 32 (bits) */
|
||||
|
||||
|
||||
/** Structure that is used when a metadata block of unknown type is loaded.
|
||||
@@ -836,9 +829,9 @@ typedef struct {
|
||||
} FLAC__StreamMetadata_Unknown;
|
||||
|
||||
|
||||
/** FLAC metadata block structure. (c.f. <A HREF="https://xiph.org/flac/format.html#metadata_block">format specification</A>)
|
||||
/** FLAC metadata block structure. (c.f. <A HREF="../format.html#metadata_block">format specification</A>)
|
||||
*/
|
||||
typedef struct FLAC__StreamMetadata {
|
||||
typedef struct {
|
||||
FLAC__MetadataType type;
|
||||
/**< The type of the metadata block; used determine which member of the
|
||||
* \a data union to dereference. If type >= FLAC__METADATA_TYPE_UNDEFINED
|
||||
@@ -847,7 +840,7 @@ typedef struct FLAC__StreamMetadata {
|
||||
FLAC__bool is_last;
|
||||
/**< \c true if this metadata block is the last, else \a false */
|
||||
|
||||
uint32_t length;
|
||||
unsigned length;
|
||||
/**< Length, in bytes, of the block data as it appears in the stream. */
|
||||
|
||||
union {
|
||||
@@ -864,9 +857,9 @@ typedef struct FLAC__StreamMetadata {
|
||||
* to use. */
|
||||
} FLAC__StreamMetadata;
|
||||
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_IS_LAST_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_TYPE_LEN; /**< == 7 (bits) */
|
||||
extern FLAC_API const uint32_t FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN; /**< == 1 (bit) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN; /**< == 7 (bits) */
|
||||
extern FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bits) */
|
||||
|
||||
/** The total stream length of a metadata block header in bytes. */
|
||||
#define FLAC__STREAM_METADATA_HEADER_LENGTH (4u)
|
||||
@@ -887,7 +880,7 @@ extern FLAC_API const uint32_t FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bit
|
||||
* \c true if the given sample rate conforms to the specification, else
|
||||
* \c false.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(uint32_t sample_rate);
|
||||
FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate);
|
||||
|
||||
/** Tests that a blocksize at the given sample rate is valid for the FLAC
|
||||
* subset.
|
||||
@@ -899,7 +892,7 @@ FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(uint32_t sample_rate);
|
||||
* \c true if the given blocksize conforms to the specification for the
|
||||
* subset at the given sample rate, else \c false.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(uint32_t blocksize, uint32_t sample_rate);
|
||||
FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(unsigned blocksize, unsigned sample_rate);
|
||||
|
||||
/** Tests that a sample rate is valid for the FLAC subset. The subset rules
|
||||
* for valid sample rates are slightly more complex since the rate has to
|
||||
@@ -910,7 +903,7 @@ FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(uint32_t blocksize, uint32_
|
||||
* \c true if the given sample rate conforms to the specification for the
|
||||
* subset, else \c false.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(uint32_t sample_rate);
|
||||
FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate);
|
||||
|
||||
/** Check a Vorbis comment entry name to see if it conforms to the Vorbis
|
||||
* comment specification.
|
||||
@@ -933,14 +926,14 @@ FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *n
|
||||
*
|
||||
* \param value A string to be checked.
|
||||
* \param length A the length of \a value in bytes. May be
|
||||
* \c (uint32_t)(-1) to indicate that \a value is a plain
|
||||
* \c (unsigned)(-1) to indicate that \a value is a plain
|
||||
* UTF-8 NUL-terminated string.
|
||||
* \assert
|
||||
* \code value != NULL \endcode
|
||||
* \retval FLAC__bool
|
||||
* \c false if entry name is illegal, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, uint32_t length);
|
||||
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length);
|
||||
|
||||
/** Check a Vorbis comment entry to see if it conforms to the Vorbis
|
||||
* comment specification.
|
||||
@@ -957,7 +950,7 @@ FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__
|
||||
* \retval FLAC__bool
|
||||
* \c false if entry name is illegal, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, uint32_t length);
|
||||
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length);
|
||||
|
||||
/** Check a seek table to see if it conforms to the FLAC specification.
|
||||
* See the format specification for limits on the contents of the
|
||||
@@ -980,10 +973,10 @@ FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_S
|
||||
* \param seek_table A pointer to a seek table to be sorted.
|
||||
* \assert
|
||||
* \code seek_table != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* The number of duplicate seek points converted into placeholders.
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table);
|
||||
FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table);
|
||||
|
||||
/** Check a cue sheet to see if it conforms to the FLAC specification.
|
||||
* See the format specification for limits on the contents of the
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2022 Xiph.Org Foundation
|
||||
* Copyright (C) 2011-2014 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -93,7 +93,7 @@
|
||||
* Efficient means the whole file is rewritten at most one time, and only
|
||||
* when necessary. Level 1 is not efficient only in the case that you
|
||||
* cause more than one metadata block to grow or shrink beyond what can
|
||||
* be accommodated by padding. In this case you should probably use level
|
||||
* be accomodated by padding. In this case you should probably use level
|
||||
* 2, which allows you to edit all the metadata for a file in memory and
|
||||
* write it out all at once.
|
||||
*
|
||||
@@ -134,11 +134,6 @@ extern "C" {
|
||||
* STREAMINFO, VORBIS_COMMENT, CUESHEET, and PICTURE blocks, requiring
|
||||
* only a filename.
|
||||
*
|
||||
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
|
||||
* internally translates to an appropriate representation to use with
|
||||
* _wfopen. On all other systems, filename is passed to fopen without
|
||||
* any translation.
|
||||
*
|
||||
* They try to skip any ID3v2 tag at the head of the file.
|
||||
*
|
||||
* \{
|
||||
@@ -222,13 +217,13 @@ FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__Stre
|
||||
* matched exactly. Use \c NULL to mean "any
|
||||
* description".
|
||||
* \param max_width The maximum width in pixels desired. Use
|
||||
* \c (uint32_t)(-1) to mean "any width".
|
||||
* \c (unsigned)(-1) to mean "any width".
|
||||
* \param max_height The maximum height in pixels desired. Use
|
||||
* \c (uint32_t)(-1) to mean "any height".
|
||||
* \c (unsigned)(-1) to mean "any height".
|
||||
* \param max_depth The maximum color depth in bits-per-pixel desired.
|
||||
* Use \c (uint32_t)(-1) to mean "any depth".
|
||||
* Use \c (unsigned)(-1) to mean "any depth".
|
||||
* \param max_colors The maximum number of colors desired. Use
|
||||
* \c (uint32_t)(-1) to mean "any number of colors".
|
||||
* \c (unsigned)(-1) to mean "any number of colors".
|
||||
* \assert
|
||||
* \code filename != NULL \endcode
|
||||
* \code picture != NULL \endcode
|
||||
@@ -239,7 +234,7 @@ FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__Stre
|
||||
* error, a file decoder error, or the file contained no PICTURE
|
||||
* block, and \a *picture will be set to \c NULL.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, uint32_t max_width, uint32_t max_height, uint32_t max_depth, uint32_t max_colors);
|
||||
FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors);
|
||||
|
||||
/* \} */
|
||||
|
||||
@@ -392,11 +387,6 @@ FLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_stat
|
||||
/** Initialize the iterator to point to the first metadata block in the
|
||||
* given FLAC file.
|
||||
*
|
||||
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
|
||||
* internally translates to an appropriate representation to use with
|
||||
* _wfopen. On all other systems, filename is passed to fopen without
|
||||
* any translation.
|
||||
*
|
||||
* \param iterator A pointer to an existing iterator.
|
||||
* \param filename The path to the FLAC file.
|
||||
* \param read_only If \c true, the FLAC file will be opened
|
||||
@@ -507,13 +497,13 @@ FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const
|
||||
* \code iterator != NULL \endcode
|
||||
* \a iterator has been successfully initialized with
|
||||
* FLAC__metadata_simple_iterator_init()
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* The length of the metadata block at the current iterator position.
|
||||
* The is same length as that in the
|
||||
* <a href="http://xiph.org/flhttps://xiph.org/flac/format.html#metadata_block_header">metadata block header</a>,
|
||||
* <a href="http://xiph.org/flac/format.html#metadata_block_header">metadata block header</a>,
|
||||
* i.e. the length of the metadata body that follows the header.
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator);
|
||||
FLAC_API unsigned FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator);
|
||||
|
||||
/** Get the application ID of the \c APPLICATION block at the current
|
||||
* position. This avoids reading the actual block data which can save
|
||||
@@ -677,7 +667,7 @@ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_S
|
||||
*
|
||||
* - Create a new chain using FLAC__metadata_chain_new(). A chain is a
|
||||
* linked list of FLAC metadata blocks.
|
||||
* - Read all metadata into the chain from a FLAC file using
|
||||
* - Read all metadata into the the chain from a FLAC file using
|
||||
* FLAC__metadata_chain_read() or FLAC__metadata_chain_read_ogg() and
|
||||
* check the status.
|
||||
* - Optionally, consolidate the padding using
|
||||
@@ -774,7 +764,7 @@ typedef enum {
|
||||
FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH,
|
||||
/**< FLAC__metadata_chain_write() was called on a chain read by
|
||||
* FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(),
|
||||
* or
|
||||
* or
|
||||
* FLAC__metadata_chain_write_with_callbacks()/FLAC__metadata_chain_write_with_callbacks_and_tempfile()
|
||||
* was called on a chain read by
|
||||
* FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg().
|
||||
@@ -829,11 +819,6 @@ FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain);
|
||||
FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain);
|
||||
|
||||
/** Read all metadata from a FLAC file into the chain.
|
||||
*
|
||||
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
|
||||
* internally translates to an appropriate representation to use with
|
||||
* _wfopen. On all other systems, filename is passed to fopen without
|
||||
* any translation.
|
||||
*
|
||||
* \param chain A pointer to an existing chain.
|
||||
* \param filename The path to the FLAC file to read.
|
||||
@@ -848,11 +833,6 @@ FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_C
|
||||
FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename);
|
||||
|
||||
/** Read all metadata from an Ogg FLAC file into the chain.
|
||||
*
|
||||
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
|
||||
* internally translates to an appropriate representation to use with
|
||||
* _wfopen. On all other systems, filename is passed to fopen without
|
||||
* any translation.
|
||||
*
|
||||
* \note Ogg FLAC metadata data writing is not supported yet and
|
||||
* FLAC__metadata_chain_write() will fail.
|
||||
@@ -1393,13 +1373,12 @@ FLAC_API FLAC__bool FLAC__metadata_object_is_equal(const FLAC__StreamMetadata *b
|
||||
* \retval FLAC__bool
|
||||
* \c false if \a copy is \c true and malloc() fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, uint32_t length, FLAC__bool copy);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, unsigned length, FLAC__bool copy);
|
||||
|
||||
/** Resize the seekpoint array.
|
||||
*
|
||||
* If the size shrinks, elements will truncated; if it grows, new placeholder
|
||||
* points will be added to the end. If this function returns false, the
|
||||
* object is left untouched.
|
||||
* points will be added to the end.
|
||||
*
|
||||
* \param object A pointer to an existing SEEKTABLE object.
|
||||
* \param new_num_points The desired length of the array; may be \c 0.
|
||||
@@ -1411,7 +1390,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetad
|
||||
* \retval FLAC__bool
|
||||
* \c false if memory allocation error, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMetadata *object, uint32_t new_num_points);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMetadata *object, unsigned new_num_points);
|
||||
|
||||
/** Set a seekpoint in a seektable.
|
||||
*
|
||||
@@ -1423,7 +1402,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMe
|
||||
* \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode
|
||||
* \code object->data.seek_table.num_points > point_num \endcode
|
||||
*/
|
||||
FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *object, uint32_t point_num, FLAC__StreamMetadata_SeekPoint point);
|
||||
FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point);
|
||||
|
||||
/** Insert a seekpoint into a seektable.
|
||||
*
|
||||
@@ -1437,7 +1416,7 @@ FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *ob
|
||||
* \retval FLAC__bool
|
||||
* \c false if memory allocation error, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMetadata *object, uint32_t point_num, FLAC__StreamMetadata_SeekPoint point);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point);
|
||||
|
||||
/** Delete a seekpoint from a seektable.
|
||||
*
|
||||
@@ -1450,7 +1429,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMet
|
||||
* \retval FLAC__bool
|
||||
* \c false if memory allocation error, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_delete_point(FLAC__StreamMetadata *object, uint32_t point_num);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_delete_point(FLAC__StreamMetadata *object, unsigned point_num);
|
||||
|
||||
/** Check a seektable to see if it conforms to the FLAC specification.
|
||||
* See the format specification for limits on the contents of the
|
||||
@@ -1480,7 +1459,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_is_legal(const FLAC__StreamM
|
||||
* \retval FLAC__bool
|
||||
* \c false if memory allocation fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_placeholders(FLAC__StreamMetadata *object, uint32_t num);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_placeholders(FLAC__StreamMetadata *object, unsigned num);
|
||||
|
||||
/** Append a specific seek point template to the end of a seek table.
|
||||
*
|
||||
@@ -1515,7 +1494,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_point(FLAC__
|
||||
* \retval FLAC__bool
|
||||
* \c false if memory allocation fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC__StreamMetadata *object, FLAC__uint64 sample_numbers[], uint32_t num);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC__StreamMetadata *object, FLAC__uint64 sample_numbers[], unsigned num);
|
||||
|
||||
/** Append a set of evenly-spaced seek point templates to the end of a
|
||||
* seek table.
|
||||
@@ -1537,7 +1516,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC_
|
||||
* \retval FLAC__bool
|
||||
* \c false if memory allocation fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points(FLAC__StreamMetadata *object, uint32_t num, FLAC__uint64 total_samples);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points(FLAC__StreamMetadata *object, unsigned num, FLAC__uint64 total_samples);
|
||||
|
||||
/** Append a set of evenly-spaced seek point templates to the end of a
|
||||
* seek table.
|
||||
@@ -1565,7 +1544,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_point
|
||||
* \retval FLAC__bool
|
||||
* \c false if memory allocation fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, uint32_t samples, FLAC__uint64 total_samples);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, unsigned samples, FLAC__uint64 total_samples);
|
||||
|
||||
/** Sort a seek table's seek points according to the format specification,
|
||||
* removing duplicates.
|
||||
@@ -1612,8 +1591,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__
|
||||
/** Resize the comment array.
|
||||
*
|
||||
* If the size shrinks, elements will truncated; if it grows, new empty
|
||||
* fields will be added to the end. If this function returns false, the
|
||||
* object is left untouched.
|
||||
* fields will be added to the end.
|
||||
*
|
||||
* \param object A pointer to an existing VORBIS_COMMENT object.
|
||||
* \param new_num_comments The desired length of the array; may be \c 0.
|
||||
@@ -1625,7 +1603,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__
|
||||
* \retval FLAC__bool
|
||||
* \c false if memory allocation fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__StreamMetadata *object, uint32_t new_num_comments);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__StreamMetadata *object, unsigned new_num_comments);
|
||||
|
||||
/** Sets a comment in a VORBIS_COMMENT block.
|
||||
*
|
||||
@@ -1652,7 +1630,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__St
|
||||
* \c false if memory allocation fails or \a entry does not comply with the
|
||||
* Vorbis comment specification, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetadata *object, uint32_t comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy);
|
||||
|
||||
/** Insert a comment in a VORBIS_COMMENT block at the given index.
|
||||
*
|
||||
@@ -1682,7 +1660,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__Stream
|
||||
* \c false if memory allocation fails or \a entry does not comply with the
|
||||
* Vorbis comment specification, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetadata *object, uint32_t comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy);
|
||||
|
||||
/** Appends a comment to a VORBIS_COMMENT block.
|
||||
*
|
||||
@@ -1714,7 +1692,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_append_comment(FLAC__Str
|
||||
* For convenience, a trailing NUL is added to the entry if it doesn't have
|
||||
* one already.
|
||||
*
|
||||
* Depending on the value of \a all, either all or just the first comment
|
||||
* Depending on the the value of \a all, either all or just the first comment
|
||||
* whose field name(s) match the given entry's name will be replaced by the
|
||||
* given entry. If no comments match, \a entry will simply be appended.
|
||||
*
|
||||
@@ -1755,7 +1733,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_replace_comment(FLAC__St
|
||||
* \retval FLAC__bool
|
||||
* \c false if realloc() fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetadata *object, uint32_t comment_num);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetadata *object, unsigned comment_num);
|
||||
|
||||
/** Creates a Vorbis comment entry from NUL-terminated name and value strings.
|
||||
*
|
||||
@@ -1811,7 +1789,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair
|
||||
* \retval FLAC__bool
|
||||
* \c true if the field names match, else \c false
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC__StreamMetadata_VorbisComment_Entry entry, const char *field_name, uint32_t field_name_length);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC__StreamMetadata_VorbisComment_Entry entry, const char *field_name, unsigned field_name_length);
|
||||
|
||||
/** Find a Vorbis comment with the given field name.
|
||||
*
|
||||
@@ -1830,7 +1808,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC
|
||||
* The offset in the comment array of the first comment whose field
|
||||
* name matches \a field_name, or \c -1 if no match was found.
|
||||
*/
|
||||
FLAC_API int FLAC__metadata_object_vorbiscomment_find_entry_from(const FLAC__StreamMetadata *object, uint32_t offset, const char *field_name);
|
||||
FLAC_API int FLAC__metadata_object_vorbiscomment_find_entry_from(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name);
|
||||
|
||||
/** Remove first Vorbis comment matching the given field name.
|
||||
*
|
||||
@@ -1893,8 +1871,7 @@ FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_C
|
||||
/** Resize a track's index point array.
|
||||
*
|
||||
* If the size shrinks, elements will truncated; if it grows, new blank
|
||||
* indices will be added to the end. If this function returns false, the
|
||||
* track object is left untouched.
|
||||
* indices will be added to the end.
|
||||
*
|
||||
* \param object A pointer to an existing CUESHEET object.
|
||||
* \param track_num The index of the track to modify. NOTE: this is not
|
||||
@@ -1909,7 +1886,7 @@ FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_C
|
||||
* \retval FLAC__bool
|
||||
* \c false if memory allocation error, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, uint32_t track_num, uint32_t new_num_indices);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, unsigned track_num, unsigned new_num_indices);
|
||||
|
||||
/** Insert an index point in a CUESHEET track at the given index.
|
||||
*
|
||||
@@ -1932,7 +1909,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__St
|
||||
* \retval FLAC__bool
|
||||
* \c false if realloc() fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, uint32_t track_num, uint32_t index_num, FLAC__StreamMetadata_CueSheet_Index index);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num, FLAC__StreamMetadata_CueSheet_Index index);
|
||||
|
||||
/** Insert a blank index point in a CUESHEET track at the given index.
|
||||
*
|
||||
@@ -1956,7 +1933,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__Stre
|
||||
* \retval FLAC__bool
|
||||
* \c false if realloc() fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC__StreamMetadata *object, uint32_t track_num, uint32_t index_num);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num);
|
||||
|
||||
/** Delete an index point in a CUESHEET track at the given index.
|
||||
*
|
||||
@@ -1975,13 +1952,12 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC
|
||||
* \retval FLAC__bool
|
||||
* \c false if realloc() fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, uint32_t track_num, uint32_t index_num);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num);
|
||||
|
||||
/** Resize the track array.
|
||||
*
|
||||
* If the size shrinks, elements will truncated; if it grows, new blank
|
||||
* tracks will be added to the end. If this function returns false, the
|
||||
* object is left untouched.
|
||||
* tracks will be added to the end.
|
||||
*
|
||||
* \param object A pointer to an existing CUESHEET object.
|
||||
* \param new_num_tracks The desired length of the array; may be \c 0.
|
||||
@@ -1993,7 +1969,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__Stre
|
||||
* \retval FLAC__bool
|
||||
* \c false if memory allocation error, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, uint32_t new_num_tracks);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, unsigned new_num_tracks);
|
||||
|
||||
/** Sets a track in a CUESHEET block.
|
||||
*
|
||||
@@ -2015,7 +1991,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMet
|
||||
* \retval FLAC__bool
|
||||
* \c false if \a copy is \c true and malloc() fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, uint32_t track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy);
|
||||
|
||||
/** Insert a track in a CUESHEET block at the given index.
|
||||
*
|
||||
@@ -2038,7 +2014,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadat
|
||||
* \retval FLAC__bool
|
||||
* \c false if \a copy is \c true and malloc() fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, uint32_t track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy);
|
||||
|
||||
/** Insert a blank track in a CUESHEET block at the given index.
|
||||
*
|
||||
@@ -2057,7 +2033,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMeta
|
||||
* \retval FLAC__bool
|
||||
* \c false if \a copy is \c true and malloc() fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__StreamMetadata *object, uint32_t track_num);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__StreamMetadata *object, unsigned track_num);
|
||||
|
||||
/** Delete a track in a CUESHEET block at the given index.
|
||||
*
|
||||
@@ -2072,7 +2048,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__Stre
|
||||
* \retval FLAC__bool
|
||||
* \c false if realloc() fails, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, uint32_t track_num);
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, unsigned track_num);
|
||||
|
||||
/** Check a cue sheet to see if it conforms to the FLAC specification.
|
||||
* See the format specification for limits on the contents of the
|
||||
@@ -2197,34 +2173,6 @@ FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation);
|
||||
|
||||
|
||||
/** Get the raw (binary) representation of a FLAC__StreamMetadata objeect.
|
||||
* After use, free() the returned buffer. The length of the buffer is
|
||||
* the length of the input metadata object plus 4 bytes for the header.
|
||||
*
|
||||
* \param object A pointer to metadata block to be converted.
|
||||
* \assert
|
||||
* \code object != NULL \endcode
|
||||
* \retval FLAC__byte*
|
||||
* \c NULL if there was an error, else a pointer to a buffer holding
|
||||
* the requested data.
|
||||
*/
|
||||
FLAC_API FLAC__byte * FLAC__metadata_object_get_raw(const FLAC__StreamMetadata *object);
|
||||
|
||||
|
||||
/** Turn a raw (binary) representation into a FLAC__StreamMetadata objeect.
|
||||
* The returned object must be deleted with FLAC__metadata_object_delete()
|
||||
* after use.
|
||||
*
|
||||
* \param buffer A pointer to a buffer containing a binary representation
|
||||
* to be converted to a FLAC__StreamMetadata object
|
||||
* \param length The length of the supplied buffer
|
||||
* \retval FLAC__StreamMetadata*
|
||||
* \c NULL if there was an error, else a pointer to a FLAC__StreamMetadata
|
||||
* holding the requested data.
|
||||
*/
|
||||
|
||||
FLAC_API FLAC__StreamMetadata * FLAC__metadata_object_set_raw(FLAC__byte *buffer, FLAC__uint32 length);
|
||||
/* \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2022 Xiph.Org Foundation
|
||||
* Copyright (C) 2011-2014 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -33,10 +33,27 @@
|
||||
#ifndef FLAC__ORDINALS_H
|
||||
#define FLAC__ORDINALS_H
|
||||
|
||||
/* This of course assumes C99 headers */
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
|
||||
/* Microsoft Visual Studio earlier than the 2010 version did not provide
|
||||
* the 1999 ISO C Standard header file <stdint.h>.
|
||||
*/
|
||||
|
||||
typedef __int8 FLAC__int8;
|
||||
typedef unsigned __int8 FLAC__uint8;
|
||||
|
||||
typedef __int16 FLAC__int16;
|
||||
typedef __int32 FLAC__int32;
|
||||
typedef __int64 FLAC__int64;
|
||||
typedef unsigned __int16 FLAC__uint16;
|
||||
typedef unsigned __int32 FLAC__uint32;
|
||||
typedef unsigned __int64 FLAC__uint64;
|
||||
|
||||
#else
|
||||
|
||||
/* For MSVC 2010 and everything else which provides <stdint.h>. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef int8_t FLAC__int8;
|
||||
typedef uint8_t FLAC__uint8;
|
||||
@@ -48,8 +65,22 @@ typedef uint16_t FLAC__uint16;
|
||||
typedef uint32_t FLAC__uint32;
|
||||
typedef uint64_t FLAC__uint64;
|
||||
|
||||
#endif
|
||||
|
||||
typedef int FLAC__bool;
|
||||
|
||||
typedef FLAC__uint8 FLAC__byte;
|
||||
|
||||
|
||||
#ifdef true
|
||||
#undef true
|
||||
#endif
|
||||
#ifdef false
|
||||
#undef false
|
||||
#endif
|
||||
#ifndef __cplusplus
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
* Copyright (C) 2011-2014 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -228,7 +228,7 @@ typedef enum {
|
||||
*/
|
||||
|
||||
FLAC__STREAM_DECODER_ABORTED,
|
||||
/**< The decoder was aborted by the read or write callback. */
|
||||
/**< The decoder was aborted by the read callback. */
|
||||
|
||||
FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
|
||||
/**< An error occurred allocating memory. The decoder is in an invalid
|
||||
@@ -422,11 +422,7 @@ extern FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[];
|
||||
* could be because the decoder encountered a valid frame made by a future
|
||||
* version of the encoder which it cannot parse, or because of a false
|
||||
* sync making it appear as though an encountered frame was generated by
|
||||
* a future encoder. \c FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA is
|
||||
* caused by finding data that doesn't fit a metadata block (too large
|
||||
* or too small) or finding inconsistencies in the metadata, for example
|
||||
* a PICTURE block with an image that exceeds the size of the metadata
|
||||
* block.
|
||||
* a future encoder.
|
||||
*/
|
||||
typedef enum {
|
||||
|
||||
@@ -439,12 +435,9 @@ typedef enum {
|
||||
FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH,
|
||||
/**< The frame's data did not match the CRC in the footer. */
|
||||
|
||||
FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM,
|
||||
FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM
|
||||
/**< The decoder encountered reserved fields in use in the stream. */
|
||||
|
||||
FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA
|
||||
/**< The decoder encountered a corrupted metadata block. */
|
||||
|
||||
} FLAC__StreamDecoderErrorStatus;
|
||||
|
||||
/** Maps a FLAC__StreamDecoderErrorStatus to a C string.
|
||||
@@ -681,7 +674,7 @@ typedef FLAC__bool (*FLAC__StreamDecoderEofCallback)(const FLAC__StreamDecoder *
|
||||
* samples of length \a frame->header.blocksize.
|
||||
* Channels will be ordered according to the FLAC
|
||||
* specification; see the documentation for the
|
||||
* <A HREF="https://xiph.org/flac/format.html#frame_header">frame header</A>.
|
||||
* <A HREF="../format.html#frame_header">frame header</A>.
|
||||
* \param client_data The callee's client data set through
|
||||
* FLAC__stream_decoder_init_*().
|
||||
* \retval FLAC__StreamDecoderWriteStatus
|
||||
@@ -782,25 +775,6 @@ FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder);
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_decoder_set_ogg_serial_number(FLAC__StreamDecoder *decoder, long serial_number);
|
||||
|
||||
/** Set the "allow Ogg chaining" flag. If set, the Ogg decoder will
|
||||
* prepare to receive a new stream once the last Ogg page arrives for
|
||||
* the stream encapsulating the FLAC audio data. This can be used to
|
||||
* support chained Ogg FLAC streams; a new \c STREAMINFO signals the
|
||||
* beginning of a new stream.
|
||||
*
|
||||
* \note
|
||||
* This function has no effect with native FLAC decoding.
|
||||
*
|
||||
* \default \c false
|
||||
* \param decoder A decoder instance to set.
|
||||
* \param allow Whether to allow chained streams.
|
||||
* \assert
|
||||
* \code decoder != NULL \endcode
|
||||
* \retval FLAC__bool
|
||||
* \c false if the decoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_decoder_set_ogg_chaining(FLAC__StreamDecoder* decoder, FLAC__bool value);
|
||||
|
||||
/** Set the "MD5 signature checking" flag. If \c true, the decoder will
|
||||
* compute the MD5 signature of the unencoded audio data while decoding
|
||||
* and compare it to the signature from the STREAMINFO block, if it
|
||||
@@ -925,17 +899,6 @@ FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__Str
|
||||
*/
|
||||
FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder);
|
||||
|
||||
/** Get the "allow Ogg chaining" flag as described in
|
||||
* \code FLAC__stream_decoder_set_ogg_chaining \endcode.
|
||||
*
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
* \code decoder != NULL \endcode
|
||||
* \retval FLAC__bool
|
||||
* See above.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_decoder_get_ogg_chaining(const FLAC__StreamDecoder* decoder);
|
||||
|
||||
/** Get the "MD5 signature checking" flag.
|
||||
* This is the value of the setting, not whether or not the decoder is
|
||||
* currently checking the MD5 (remember, it can be turned off automatically
|
||||
@@ -957,7 +920,7 @@ FLAC_API FLAC__bool FLAC__stream_decoder_get_md5_checking(const FLAC__StreamDeco
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
* \code decoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See above.
|
||||
*/
|
||||
FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder);
|
||||
@@ -969,10 +932,10 @@ FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamD
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
* \code decoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See above.
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder);
|
||||
FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder);
|
||||
|
||||
/** Get the current channel assignment in the stream being decoded.
|
||||
* Will only be valid after decoding has started and will contain the
|
||||
@@ -993,10 +956,10 @@ FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(con
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
* \code decoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See above.
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder);
|
||||
FLAC_API unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder);
|
||||
|
||||
/** Get the current sample rate in Hz of the stream being decoded.
|
||||
* Will only be valid after decoding has started and will contain the
|
||||
@@ -1005,10 +968,10 @@ FLAC_API uint32_t FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDec
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
* \code decoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See above.
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder);
|
||||
FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder);
|
||||
|
||||
/** Get the current blocksize of the stream being decoded.
|
||||
* Will only be valid after decoding has started and will contain the
|
||||
@@ -1017,10 +980,10 @@ FLAC_API uint32_t FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
* \code decoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See above.
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder);
|
||||
FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder);
|
||||
|
||||
/** Returns the decoder's current read position within the stream.
|
||||
* The position is the byte offset from the start of the stream.
|
||||
@@ -1043,16 +1006,6 @@ FLAC_API uint32_t FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position);
|
||||
|
||||
/** Return client_data from decoder.
|
||||
* The data pointed to by the pointer should not be modified.
|
||||
*
|
||||
* \param decoder A decoder instance.
|
||||
* \retval const void *
|
||||
* The callee's client data set through FLAC__stream_decoder_init_*().
|
||||
* Do not modify the contents.
|
||||
*/
|
||||
FLAC_API const void *FLAC__stream_decoder_get_client_data(FLAC__StreamDecoder *decoder);
|
||||
|
||||
/** Initialize the decoder instance to decode native FLAC streams.
|
||||
*
|
||||
* This flavor of initialization sets up the decoder to decode from a
|
||||
@@ -1231,7 +1184,7 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream(
|
||||
* Unless \a file is \c stdin, it will be closed
|
||||
* when FLAC__stream_decoder_finish() is called.
|
||||
* Note however that seeking will not work when
|
||||
* decoding from \c stdin since it is not seekable.
|
||||
* decoding from \c stdout since it is not seekable.
|
||||
* \param write_callback See FLAC__StreamDecoderWriteCallback. This
|
||||
* pointer must not be \c NULL.
|
||||
* \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This
|
||||
@@ -1281,7 +1234,7 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE(
|
||||
* Unless \a file is \c stdin, it will be closed
|
||||
* when FLAC__stream_decoder_finish() is called.
|
||||
* Note however that seeking will not work when
|
||||
* decoding from \c stdin since it is not seekable.
|
||||
* decoding from \c stdout since it is not seekable.
|
||||
* \param write_callback See FLAC__StreamDecoderWriteCallback. This
|
||||
* pointer must not be \c NULL.
|
||||
* \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This
|
||||
@@ -1310,15 +1263,11 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE(
|
||||
/** Initialize the decoder instance to decode native FLAC files.
|
||||
*
|
||||
* This flavor of initialization sets up the decoder to decode from a plain
|
||||
* native FLAC file. If POSIX fopen() semantics are not sufficient, you must
|
||||
* use FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream()
|
||||
* native FLAC file. If POSIX fopen() semantics are not sufficient, (for
|
||||
* example, with Unicode filenames on Windows), you must use
|
||||
* FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream()
|
||||
* and provide callbacks for the I/O.
|
||||
*
|
||||
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
|
||||
* internally translates to an appropriate representation to use with
|
||||
* _wfopen. On all other systems, filename is passed to fopen without
|
||||
* any translation.
|
||||
*
|
||||
* This function should be called after FLAC__stream_decoder_new() and
|
||||
* FLAC__stream_decoder_set_*() but before any of the
|
||||
* FLAC__stream_decoder_process_*() functions. Will set and return the
|
||||
@@ -1356,15 +1305,11 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file(
|
||||
/** Initialize the decoder instance to decode Ogg FLAC files.
|
||||
*
|
||||
* This flavor of initialization sets up the decoder to decode from a plain
|
||||
* Ogg FLAC file. If POSIX fopen() semantics are not sufficient, you must use
|
||||
* Ogg FLAC file. If POSIX fopen() semantics are not sufficient, (for
|
||||
* example, with Unicode filenames on Windows), you must use
|
||||
* FLAC__stream_decoder_init_ogg_FILE(), or FLAC__stream_decoder_init_ogg_stream()
|
||||
* and provide callbacks for the I/O.
|
||||
*
|
||||
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
|
||||
* internally translates to an appropriate representation to use with
|
||||
* _wfopen. On all other systems, filename is passed to fopen without
|
||||
* any translation.
|
||||
*
|
||||
* This function should be called after FLAC__stream_decoder_new() and
|
||||
* FLAC__stream_decoder_set_*() but before any of the
|
||||
* FLAC__stream_decoder_process_*() functions. Will set and return the
|
||||
@@ -1458,7 +1403,8 @@ FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder);
|
||||
* and is not seekable (i.e. no seek callback was provided or the seek
|
||||
* callback returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED), it
|
||||
* is the duty of the client to start feeding data from the beginning of
|
||||
* the stream on the next FLAC__stream_decoder_process_*() call.
|
||||
* the stream on the next FLAC__stream_decoder_process() or
|
||||
* FLAC__stream_decoder_process_interleaved() call.
|
||||
*
|
||||
* \param decoder A decoder instance.
|
||||
* \assert
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2022 Xiph.Org Foundation
|
||||
* Copyright (C) 2011-2014 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -129,8 +129,8 @@ extern "C" {
|
||||
* Unlike the decoders, the stream encoder has many options that can
|
||||
* affect the speed and compression ratio. When setting these parameters
|
||||
* you should have some basic knowledge of the format (see the
|
||||
* <A HREF="https://xiph.org/flac/documentation_format_overview.html">user-level documentation</A>
|
||||
* or the <A HREF="https://xiph.org/flac/format.html">formal description</A>). The
|
||||
* <A HREF="../documentation_format_overview.html">user-level documentation</A>
|
||||
* or the <A HREF="../format.html">formal description</A>). The
|
||||
* FLAC__stream_encoder_set_*() functions themselves do not validate the
|
||||
* values as many are interdependent. The FLAC__stream_encoder_init_*()
|
||||
* functions will do this, so make sure to pay attention to the state
|
||||
@@ -311,7 +311,8 @@ typedef enum {
|
||||
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE,
|
||||
/**< The encoder has an invalid setting for bits-per-sample.
|
||||
* FLAC supports 4-32 bps.
|
||||
* FLAC supports 4-32 bps but the reference encoder currently supports
|
||||
* only up to 24 bps.
|
||||
*/
|
||||
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE,
|
||||
@@ -330,7 +331,7 @@ typedef enum {
|
||||
/**< The specified block size is less than the maximum LPC order. */
|
||||
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE,
|
||||
/**< The encoder is bound to the <A HREF="https://xiph.org/flac/format.html#subset">Subset</A> but other settings violate it. */
|
||||
/**< The encoder is bound to the <A HREF="../format.html#subset">Subset</A> but other settings violate it. */
|
||||
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA,
|
||||
/**< The metadata input to the encoder is invalid, in one of the following ways:
|
||||
@@ -553,7 +554,7 @@ typedef FLAC__StreamEncoderReadStatus (*FLAC__StreamEncoderReadCallback)(const F
|
||||
* \retval FLAC__StreamEncoderWriteStatus
|
||||
* The callee's return status.
|
||||
*/
|
||||
typedef FLAC__StreamEncoderWriteStatus (*FLAC__StreamEncoderWriteCallback)(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, uint32_t samples, uint32_t current_frame, void *client_data);
|
||||
typedef FLAC__StreamEncoderWriteStatus (*FLAC__StreamEncoderWriteCallback)(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data);
|
||||
|
||||
/** Signature for the seek callback.
|
||||
*
|
||||
@@ -674,7 +675,7 @@ typedef void (*FLAC__StreamEncoderMetadataCallback)(const FLAC__StreamEncoder *e
|
||||
* \param client_data The callee's client data set through
|
||||
* FLAC__stream_encoder_init_*().
|
||||
*/
|
||||
typedef void (*FLAC__StreamEncoderProgressCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, uint32_t frames_written, uint32_t total_frames_estimate, void *client_data);
|
||||
typedef void (*FLAC__StreamEncoderProgressCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
@@ -742,7 +743,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_ogg_serial_number(FLAC__StreamEncod
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value);
|
||||
|
||||
/** Set the <A HREF="https://xiph.org/flac/format.html#subset">Subset</A> flag. If \c true,
|
||||
/** Set the <A HREF="../format.html#subset">Subset</A> flag. If \c true,
|
||||
* the encoder will comply with the Subset and will check the
|
||||
* settings during FLAC__stream_encoder_init_*() to see if all settings
|
||||
* comply. If \c false, the settings may take advantage of the full
|
||||
@@ -770,7 +771,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncod
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, uint32_t value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value);
|
||||
|
||||
/** Set the sample resolution of the input to be encoded.
|
||||
*
|
||||
@@ -786,7 +787,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encod
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, uint32_t value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value);
|
||||
|
||||
/** Set the sample rate (in Hz) of the input to be encoded.
|
||||
*
|
||||
@@ -798,7 +799,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, uint32_t value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value);
|
||||
|
||||
/** Set the compression level
|
||||
*
|
||||
@@ -842,15 +843,15 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *en
|
||||
* <td>max residual partition order</td>
|
||||
* <td>rice parameter search dist</td>
|
||||
* </tr>
|
||||
* <tr> <td><b>0</b></td> <td>false</td> <td>false</td> <td>tukey(0.5)</td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>1</b></td> <td>true</td> <td>true</td> <td>tukey(0.5)</td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>2</b></td> <td>true</td> <td>false</td> <td>tukey(0.5)</td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>3</b></td> <td>false</td> <td>false</td> <td>tukey(0.5)</td> <td>6</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>4</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>4</b></td> <td>true</td> <td>true</td> <td>tukey(0.5)</td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>4</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>5</b></td> <td>true</td> <td>false</td> <td>tukey(0.5)</td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>5</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>6</b></td> <td>true</td> <td>false</td> <td>subdivide_tukey(2)</td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>7</b></td> <td>true</td> <td>false</td> <td>subdivide_tukey(2)</td> <td>12</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>8</b></td> <td>true</td> <td>false</td> <td>subdivide_tukey(2)</td> <td>12</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>0</b></td> <td>false</td> <td>false</td> <td>tukey(0.5)<td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>1</b></td> <td>true</td> <td>true</td> <td>tukey(0.5)<td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>2</b></td> <td>true</td> <td>false</td> <td>tukey(0.5)<td> <td>0</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>3</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>3</b></td> <td>false</td> <td>false</td> <td>tukey(0.5)<td> <td>6</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>4</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>4</b></td> <td>true</td> <td>true</td> <td>tukey(0.5)<td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>4</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>5</b></td> <td>true</td> <td>false</td> <td>tukey(0.5)<td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>5</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>6</b></td> <td>true</td> <td>false</td> <td>tukey(0.5);partial_tukey(2)<td> <td>8</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>7</b></td> <td>true</td> <td>false</td> <td>tukey(0.5);partial_tukey(2)<td> <td>12</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr>
|
||||
* <tr> <td><b>8</b></td> <td>true</td> <td>false</td> <td>tukey(0.5);partial_tukey(2);punchout_tukey(3)</td> <td>12</td> <td>0</td> <td>false</td> <td>false</td> <td>false</td> <td>0</td> <td>6</td> <td>0</td> </tr>
|
||||
* </table>
|
||||
*
|
||||
* \default \c 5
|
||||
@@ -861,7 +862,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *en
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncoder *encoder, uint32_t value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncoder *encoder, unsigned value);
|
||||
|
||||
/** Set the blocksize to use while encoding.
|
||||
*
|
||||
@@ -876,13 +877,13 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncod
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, uint32_t value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value);
|
||||
|
||||
/** Set to \c true to enable mid-side encoding on stereo input. The
|
||||
* number of channels must be 2 for this to have any effect. Set to
|
||||
* \c false to use only independent channel coding.
|
||||
*
|
||||
* \default \c true
|
||||
* \default \c false
|
||||
* \param encoder An encoder instance to set.
|
||||
* \param value Flag value (see above).
|
||||
* \assert
|
||||
@@ -920,7 +921,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamE
|
||||
* \c blackman, \c blackman_harris_4term_92db, \c connes, \c flattop,
|
||||
* \c gauss(STDDEV), \c hamming, \c hann, \c kaiser_bessel, \c nuttall,
|
||||
* \c rectangle, \c triangle, \c tukey(P), \c partial_tukey(n[/ov[/P]]),
|
||||
* \c punchout_tukey(n[/ov[/P]]), \c subdivide_tukey(n[/P]), \c welch.
|
||||
* \c punchout_tukey(n[/ov[/P]]), \c welch.
|
||||
*
|
||||
* For \c gauss(STDDEV), STDDEV specifies the standard deviation
|
||||
* (0<STDDEV<=0.5).
|
||||
@@ -947,20 +948,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamE
|
||||
* and partial_tukey(3/0.3/0.5) are all valid. ov should be smaller than 1
|
||||
* and can be negative.
|
||||
*
|
||||
* subdivide_tukey(n) is a more efficient reimplementation of
|
||||
* partial_tukey and punchout_tukey taken together, recycling as much data
|
||||
* as possible. It combines all possible non-redundant partial_tukey(n)
|
||||
* and punchout_tukey(n) up to the n specified. Specifying
|
||||
* subdivide_tukey(3) is equivalent to specifying tukey, partial_tukey(2),
|
||||
* partial_tukey(3) and punchout_tukey(3), specifying subdivide_tukey(5)
|
||||
* equivalently adds partial_tukey(4), punchout_tukey(4), partial_tukey(5)
|
||||
* and punchout_tukey(5). To be able to reuse data as much as possible,
|
||||
* the tukey taper is taken equal for all windows, and the P specified is
|
||||
* applied for the smallest used window. In other words,
|
||||
* subdivide_tukey(2/0.5) results in a taper equal to that of tukey(0.25)
|
||||
* and subdivide_tukey(5) in a taper equal to that of tukey(0.1). The
|
||||
* default P for subdivide_tukey when none is specified is 0.5.
|
||||
*
|
||||
* Example specifications are \c "blackman" or
|
||||
* \c "hann;triangle;tukey(0.5);tukey(0.25);tukey(0.125)"
|
||||
*
|
||||
@@ -976,8 +963,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamE
|
||||
* floating point array in which to store the window. Also note that the
|
||||
* values of P, STDDEV and ov are locale-specific, so if the comma
|
||||
* separator specified by the locale is a comma, a comma should be used.
|
||||
* A locale-independent way is to specify using scientific notation,
|
||||
* e.g. 5e-1 instad of 0.5 or 0,5.
|
||||
*
|
||||
* \default \c "tukey(0.5)"
|
||||
* \param encoder An encoder instance to set.
|
||||
@@ -992,7 +977,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *en
|
||||
|
||||
/** Set the maximum LPC order, or \c 0 to use only the fixed predictors.
|
||||
*
|
||||
* \default \c 8
|
||||
* \default \c 0
|
||||
* \param encoder An encoder instance to set.
|
||||
* \param value See above.
|
||||
* \assert
|
||||
@@ -1000,12 +985,16 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *en
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, uint32_t value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, unsigned value);
|
||||
|
||||
/** Set the precision, in bits, of the quantized linear predictor
|
||||
* coefficients, or \c 0 to let the encoder select it based on the
|
||||
* blocksize.
|
||||
*
|
||||
* \note
|
||||
* In the current implementation, qlp_coeff_precision + bits_per_sample must
|
||||
* be less than 32.
|
||||
*
|
||||
* \default \c 0
|
||||
* \param encoder An encoder instance to set.
|
||||
* \param value See above.
|
||||
@@ -1014,7 +1003,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, uint32_t value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, unsigned value);
|
||||
|
||||
/** Set to \c false to use only the specified quantized linear predictor
|
||||
* coefficient precision, or \c true to search neighboring precision
|
||||
@@ -1077,7 +1066,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_do_exhaustive_model_search(FLAC__St
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, uint32_t value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value);
|
||||
|
||||
/** Set the maximum partition order to search when coding the residual.
|
||||
* This is used in tandem with
|
||||
@@ -1092,7 +1081,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__
|
||||
* all orders, using the mean of each context for its Rice parameter,
|
||||
* and use the best.
|
||||
*
|
||||
* \default \c 5
|
||||
* \default \c 0
|
||||
* \param encoder An encoder instance to set.
|
||||
* \param value See above.
|
||||
* \assert
|
||||
@@ -1100,7 +1089,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, uint32_t value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value);
|
||||
|
||||
/** Deprecated. Setting this value has no effect.
|
||||
*
|
||||
@@ -1112,7 +1101,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, uint32_t value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value);
|
||||
|
||||
/** Set an estimate of the total samples that will be encoded.
|
||||
* This is merely an estimate and may be set to \c 0 if unknown.
|
||||
@@ -1211,25 +1200,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__Stream
|
||||
* \c false if the encoder is already initialized, or if
|
||||
* \a num_blocks > 65535 if encoding to Ogg FLAC, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, uint32_t num_blocks);
|
||||
|
||||
/** Set to \c true to make the encoder not output frames which contain
|
||||
* only constant subframes. This is beneficial for streaming
|
||||
* applications: very small frames can cause problems with buffering
|
||||
* as bitrates can drop as low 1kbit/s for CDDA audio encoded within
|
||||
* subset. The minimum bitrate for a FLAC file encoded with this
|
||||
* function used is raised to 1bit/sample (i.e. 48kbit/s for 48kHz
|
||||
* material).
|
||||
*
|
||||
* \default \c false
|
||||
* \param encoder An encoder instance to set.
|
||||
* \param value Flag value (see above).
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_limit_min_bitrate(FLAC__StreamEncoder *encoder, FLAC__bool value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
|
||||
|
||||
/** Get the current encoder state.
|
||||
*
|
||||
@@ -1283,7 +1254,7 @@ FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
*/
|
||||
FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, uint32_t *frame_number, uint32_t *channel, uint32_t *sample, FLAC__int32 *expected, FLAC__int32 *got);
|
||||
FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
|
||||
|
||||
/** Get the "verify" flag.
|
||||
*
|
||||
@@ -1295,7 +1266,7 @@ FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__St
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get the <A HREF="https://xiph.org/flac/format.html#subset">Subset</A> flag.
|
||||
/** Get the <A HREF="../format.html#subset>Subset</A> flag.
|
||||
*
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
@@ -1310,40 +1281,40 @@ FLAC_API FLAC__bool FLAC__stream_encoder_get_streamable_subset(const FLAC__Strea
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See FLAC__stream_encoder_set_channels().
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder);
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get the input sample resolution setting.
|
||||
*
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See FLAC__stream_encoder_set_bits_per_sample().
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder);
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get the input sample rate setting.
|
||||
*
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See FLAC__stream_encoder_set_sample_rate().
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder);
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get the blocksize setting.
|
||||
*
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See FLAC__stream_encoder_set_blocksize().
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder);
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get the "mid/side stereo coding" flag.
|
||||
*
|
||||
@@ -1370,20 +1341,20 @@ FLAC_API FLAC__bool FLAC__stream_encoder_get_loose_mid_side_stereo(const FLAC__S
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See FLAC__stream_encoder_set_max_lpc_order().
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder);
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get the quantized linear predictor coefficient precision setting.
|
||||
*
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See FLAC__stream_encoder_set_qlp_coeff_precision().
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder);
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get the qlp coefficient precision search flag.
|
||||
*
|
||||
@@ -1420,30 +1391,30 @@ FLAC_API FLAC__bool FLAC__stream_encoder_get_do_exhaustive_model_search(const FL
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See FLAC__stream_encoder_set_min_residual_partition_order().
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder);
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get maximum residual partition order setting.
|
||||
*
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See FLAC__stream_encoder_set_max_residual_partition_order().
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder);
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get the Rice parameter search distance setting.
|
||||
*
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval uint32_t
|
||||
* \retval unsigned
|
||||
* See FLAC__stream_encoder_set_rice_parameter_search_dist().
|
||||
*/
|
||||
FLAC_API uint32_t FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder);
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get the previously set estimate of the total samples to be encoded.
|
||||
* The encoder merely mimics back the value given to
|
||||
@@ -1458,16 +1429,6 @@ FLAC_API uint32_t FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC
|
||||
*/
|
||||
FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Get the "limit_min_bitrate" flag.
|
||||
*
|
||||
* \param encoder An encoder instance to query.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \retval FLAC__bool
|
||||
* See FLAC__stream_encoder_set_limit_min_bitrate().
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_get_limit_min_bitrate(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
/** Initialize the encoder instance to encode native FLAC streams.
|
||||
*
|
||||
* This flavor of initialization sets up the encoder to encode to a
|
||||
@@ -1672,15 +1633,11 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_ogg_FILE(FLAC__
|
||||
/** Initialize the encoder instance to encode native FLAC files.
|
||||
*
|
||||
* This flavor of initialization sets up the encoder to encode to a plain
|
||||
* FLAC file. If POSIX fopen() semantics are not sufficient you must use
|
||||
* FLAC file. If POSIX fopen() semantics are not sufficient (for example,
|
||||
* with Unicode filenames on Windows), you must use
|
||||
* FLAC__stream_encoder_init_FILE(), or FLAC__stream_encoder_init_stream()
|
||||
* and provide callbacks for the I/O.
|
||||
*
|
||||
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
|
||||
* internally translates to an appropriate representation to use with
|
||||
* _wfopen. On all other systems, filename is passed to fopen without
|
||||
* any translation.
|
||||
*
|
||||
* This function should be called after FLAC__stream_encoder_new() and
|
||||
* FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process()
|
||||
* or FLAC__stream_encoder_process_interleaved().
|
||||
@@ -1708,15 +1665,11 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_file(FLAC__Stre
|
||||
/** Initialize the encoder instance to encode Ogg FLAC files.
|
||||
*
|
||||
* This flavor of initialization sets up the encoder to encode to a plain
|
||||
* Ogg FLAC file. If POSIX fopen() semantics are not sufficient, you must use
|
||||
* Ogg FLAC file. If POSIX fopen() semantics are not sufficient (for example,
|
||||
* with Unicode filenames on Windows), you must use
|
||||
* FLAC__stream_encoder_init_ogg_FILE(), or FLAC__stream_encoder_init_ogg_stream()
|
||||
* and provide callbacks for the I/O.
|
||||
*
|
||||
* On Windows, filename must be a UTF-8 encoded filename, which libFLAC
|
||||
* internally translates to an appropriate representation to use with
|
||||
* _wfopen. On all other systems, filename is passed to fopen without
|
||||
* any translation.
|
||||
*
|
||||
* This function should be called after FLAC__stream_encoder_new() and
|
||||
* FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process()
|
||||
* or FLAC__stream_encoder_process_interleaved().
|
||||
@@ -1781,7 +1734,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder);
|
||||
*
|
||||
* For applications where channel order is important, channels must
|
||||
* follow the order as described in the
|
||||
* <A HREF="https://xiph.org/flac/format.html#frame_header">frame header</A>.
|
||||
* <A HREF="../format.html#frame_header">frame header</A>.
|
||||
*
|
||||
* \param encoder An initialized encoder instance in the OK state.
|
||||
* \param buffer An array of pointers to each channel's signal.
|
||||
@@ -1794,7 +1747,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder);
|
||||
* encoder state with FLAC__stream_encoder_get_state() to see what
|
||||
* went wrong.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], uint32_t samples);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples);
|
||||
|
||||
/** Submit data for encoding.
|
||||
* This version allows you to supply the input data where the channels
|
||||
@@ -1810,7 +1763,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c
|
||||
*
|
||||
* For applications where channel order is important, channels must
|
||||
* follow the order as described in the
|
||||
* <A HREF="https://xiph.org/flac/format.html#frame_header">frame header</A>.
|
||||
* <A HREF="../format.html#frame_header">frame header</A>.
|
||||
*
|
||||
* \param encoder An initialized encoder instance in the OK state.
|
||||
* \param buffer An array of channel-interleaved data (see above).
|
||||
@@ -1826,7 +1779,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c
|
||||
* encoder state with FLAC__stream_encoder_get_state() to see what
|
||||
* went wrong.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], uint32_t samples);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples);
|
||||
|
||||
/* \} */
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ extern "C" {
|
||||
|
||||
struct alac_codec_s *alac_create_decoder(int magic_cookie_size, unsigned char *magic_cookie,
|
||||
unsigned char *sample_size, unsigned *sample_rate,
|
||||
unsigned char *channels, unsigned int *block_size);
|
||||
unsigned char *channels);
|
||||
void alac_delete_decoder(struct alac_codec_s *codec);
|
||||
bool alac_to_pcm(struct alac_codec_s *codec, unsigned char* input,
|
||||
unsigned char *output, char channels, unsigned *out_frames);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __CONFIG_TYPES_H__
|
||||
#define __CONFIG_TYPES_H__
|
||||
|
||||
/* these are filled in by configure or cmake*/
|
||||
/* these are filled in by configure */
|
||||
#define INCLUDE_INTTYPES_H 1
|
||||
#define INCLUDE_STDINT_H 1
|
||||
#define INCLUDE_SYS_TYPES_H 1
|
||||
@@ -21,6 +21,5 @@ typedef uint16_t ogg_uint16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef uint32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
typedef uint64_t ogg_uint64_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
********************************************************************
|
||||
|
||||
function: toplevel libogg include
|
||||
last mod: $Id$
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OGG_H
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: Define a consistent set of types on each platform.
|
||||
function: #ifdef jail to whip a few platforms into the UNIX ideal.
|
||||
last mod: $Id$
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OS_TYPES_H
|
||||
@@ -43,7 +44,6 @@
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
# elif defined(__MWERKS__)
|
||||
typedef long long ogg_int64_t;
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef short ogg_int16_t;
|
||||
@@ -62,7 +62,6 @@
|
||||
typedef __int64 ogg_int64_t;
|
||||
typedef __int32 ogg_int32_t;
|
||||
typedef unsigned __int32 ogg_uint32_t;
|
||||
typedef unsigned __int64 ogg_uint64_t;
|
||||
typedef __int16 ogg_int16_t;
|
||||
typedef unsigned __int16 ogg_uint16_t;
|
||||
# endif
|
||||
@@ -70,13 +69,12 @@
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <inttypes.h>
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef u_int16_t ogg_uint16_t;
|
||||
typedef uint16_t ogg_uint16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef u_int32_t ogg_uint32_t;
|
||||
typedef uint32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
typedef u_int64_t ogg_uint64_t;
|
||||
|
||||
#elif defined(__HAIKU__)
|
||||
|
||||
@@ -87,7 +85,6 @@
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long ogg_int64_t;
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
|
||||
@@ -98,7 +95,6 @@
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef uint32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
typedef uint64_t ogg_uint64_t;
|
||||
|
||||
#elif defined (__EMX__)
|
||||
|
||||
@@ -108,8 +104,6 @@
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long ogg_int64_t;
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
|
||||
|
||||
#elif defined (DJGPP)
|
||||
|
||||
@@ -118,13 +112,11 @@
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long ogg_int64_t;
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
|
||||
#elif defined(R5900)
|
||||
|
||||
/* PS2 EE */
|
||||
typedef long ogg_int64_t;
|
||||
typedef unsigned long ogg_uint64_t;
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned ogg_uint32_t;
|
||||
typedef short ogg_int16_t;
|
||||
@@ -137,7 +129,6 @@
|
||||
typedef signed int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long int ogg_int64_t;
|
||||
typedef unsigned long long int ogg_uint64_t;
|
||||
|
||||
#elif defined(__TMS320C6X__)
|
||||
|
||||
@@ -147,7 +138,6 @@
|
||||
typedef signed int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long int ogg_int64_t;
|
||||
typedef unsigned long long int ogg_uint64_t;
|
||||
|
||||
#else
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
|
||||
* @param [in] application <tt>int</tt>: Coding mode (one of @ref OPUS_APPLICATION_VOIP, @ref OPUS_APPLICATION_AUDIO, or @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @param [in] application <tt>int</tt>: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @param [out] error <tt>int*</tt>: @ref opus_errorcodes
|
||||
* @note Regardless of the sampling rate and number channels selected, the Opus encoder
|
||||
* can switch to a lower audio bandwidth or number of channels if the bitrate
|
||||
@@ -222,7 +222,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
|
||||
* @param [in] application <tt>int</tt>: Coding mode (one of OPUS_APPLICATION_VOIP, OPUS_APPLICATION_AUDIO, or OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @param [in] application <tt>int</tt>: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @retval #OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT int opus_encoder_init(
|
||||
|
||||
@@ -104,8 +104,7 @@ typedef struct OpusCustomDecoder OpusCustomDecoder;
|
||||
/** The mode contains all the information necessary to create an
|
||||
encoder. Both the encoder and decoder need to be initialized
|
||||
with exactly the same mode, otherwise the output will be
|
||||
corrupted. The mode MUST NOT BE DESTROYED until the encoders and
|
||||
decoders that use it are destroyed as well.
|
||||
corrupted.
|
||||
@brief Mode configuration
|
||||
*/
|
||||
typedef struct OpusCustomMode OpusCustomMode;
|
||||
@@ -179,7 +178,7 @@ OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encode
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
|
||||
/** Destroys an encoder state.
|
||||
/** Destroys a an encoder state.
|
||||
* @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
|
||||
@@ -287,7 +286,7 @@ OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decode
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Destroys a decoder state.
|
||||
/** Destroys a an decoder state.
|
||||
* @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
|
||||
|
||||
@@ -64,7 +64,7 @@ extern "C" {
|
||||
/**Export control for opus functions */
|
||||
|
||||
#ifndef OPUS_EXPORT
|
||||
# if defined(_WIN32)
|
||||
# if defined(WIN32)
|
||||
# if defined(OPUS_BUILD) && defined(DLL_EXPORT)
|
||||
# define OPUS_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
@@ -482,8 +482,7 @@ extern "C" {
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Disable inband FEC (default).</dd>
|
||||
* <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
|
||||
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
|
||||
* <dt>1</dt><dd>Enable inband FEC.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
|
||||
@@ -492,8 +491,7 @@ extern "C" {
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Inband FEC disabled (default).</dd>
|
||||
* <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
|
||||
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
|
||||
* <dt>1</dt><dd>Inband FEC enabled.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 *
|
||||
* by the Xiph.Org Foundation and contributors https://xiph.org/ *
|
||||
* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
reference
|
||||
<tt><a href="https://www.xiph.org/ogg/doc/libogg/reference.html">libogg</a></tt>
|
||||
and
|
||||
<tt><a href="https://opus-codec.org/docs/opus_api-1.3.1/">libopus</a></tt>
|
||||
<tt><a href="https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/index.html">libopus</a></tt>
|
||||
libraries.
|
||||
|
||||
<tt>libopusfile</tt> provides several sets of built-in routines for
|
||||
@@ -58,7 +58,7 @@
|
||||
it is stored in the header to allow you to resample to it after decoding
|
||||
(the <tt>libopusfile</tt> API does not currently provide a resampler,
|
||||
but the
|
||||
<a href="https://www.speex.org/docs/manual/speex-manual/node7.html#SECTION00760000000000000000">the
|
||||
<a href="http://www.speex.org/docs/manual/speex-manual/node7.html#SECTION00760000000000000000">the
|
||||
Speex resampler</a> is a good choice if you need one).
|
||||
In general, if you are playing back the audio, you should leave it at
|
||||
48 kHz, provided your audio hardware supports it.
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
Opus files can contain anywhere from 1 to 255 channels of audio.
|
||||
The channel mappings for up to 8 channels are the same as the
|
||||
<a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis
|
||||
<a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis
|
||||
mappings</a>.
|
||||
A special stereo API can convert everything to 2 channels, making it simple
|
||||
to support multichannel files in an application which only has stereo
|
||||
@@ -147,18 +147,18 @@ typedef struct OggOpusFile OggOpusFile;
|
||||
/**@endcond*/
|
||||
|
||||
/**\defgroup error_codes Error Codes*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
/**\name List of possible error codes
|
||||
Many of the functions in this library return a negative error code when a
|
||||
function fails.
|
||||
This list provides a brief explanation of the common errors.
|
||||
See each individual function for more details on what a specific error code
|
||||
means in that context.*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
|
||||
/**A request did not succeed.*/
|
||||
#define OP_FALSE (-1)
|
||||
/**Currently not used externally.**/
|
||||
/*Currently not used externally.*/
|
||||
#define OP_EOF (-2)
|
||||
/**There was a hole in the page sequence numbers (e.g., a page was corrupt or
|
||||
missing).*/
|
||||
@@ -185,7 +185,7 @@ typedef struct OggOpusFile OggOpusFile;
|
||||
#define OP_EBADHEADER (-133)
|
||||
/**The ID header contained an unrecognized version number.*/
|
||||
#define OP_EVERSION (-134)
|
||||
/**Currently not used at all.**/
|
||||
/*Currently not used at all.*/
|
||||
#define OP_ENOTAUDIO (-135)
|
||||
/**An audio packet failed to decode properly.
|
||||
This is usually caused by a multistream Ogg packet where the durations of
|
||||
@@ -200,11 +200,11 @@ typedef struct OggOpusFile OggOpusFile;
|
||||
/**The first or last granule position of a link failed basic validity checks.*/
|
||||
#define OP_EBADTIMESTAMP (-139)
|
||||
|
||||
/**@}*/
|
||||
/**@}*/
|
||||
/*@}*/
|
||||
/*@}*/
|
||||
|
||||
/**\defgroup header_info Header Information*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
|
||||
/**The maximum number of channels in an Ogg Opus stream.*/
|
||||
#define OPUS_CHANNEL_COUNT_MAX (255)
|
||||
@@ -284,7 +284,7 @@ struct OpusHead{
|
||||
A particular tag may occur more than once, and order is significant.
|
||||
The character set encoding for the strings is always UTF-8, but the tag
|
||||
names are limited to ASCII, and treated as case-insensitive.
|
||||
See <a href="https://www.xiph.org/vorbis/doc/v-comment.html">the Vorbis
|
||||
See <a href="http://www.xiph.org/vorbis/doc/v-comment.html">the Vorbis
|
||||
comment header specification</a> for details.
|
||||
|
||||
In filling in this structure, <tt>libopusfile</tt> will null-terminate the
|
||||
@@ -311,7 +311,7 @@ struct OpusTags{
|
||||
};
|
||||
|
||||
/**\name Picture tag image formats*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
|
||||
/**The MIME type was not recognized, or the image data did not match the
|
||||
declared MIME type.*/
|
||||
@@ -325,7 +325,7 @@ struct OpusTags{
|
||||
/**The image is a GIF.*/
|
||||
#define OP_PIC_FORMAT_GIF (3)
|
||||
|
||||
/**@}*/
|
||||
/*@}*/
|
||||
|
||||
/**The contents of a METADATA_BLOCK_PICTURE tag.*/
|
||||
struct OpusPictureTag{
|
||||
@@ -398,7 +398,7 @@ struct OpusPictureTag{
|
||||
These can be used to query the headers returned by <tt>libopusfile</tt>, or
|
||||
to parse Opus headers from sources other than an Ogg Opus stream, provided
|
||||
they use the same format.*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
|
||||
/**Parses the contents of the ID header packet of an Ogg Opus stream.
|
||||
\param[out] _head Returns the contents of the parsed packet.
|
||||
@@ -671,12 +671,12 @@ void opus_picture_tag_init(OpusPictureTag *_pic) OP_ARG_NONNULL(1);
|
||||
\param _pic The #OpusPictureTag structure to clear.*/
|
||||
void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
/*@}*/
|
||||
|
||||
/**@}*/
|
||||
/*@}*/
|
||||
|
||||
/**\defgroup url_options URL Reading Options*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
/**\name URL reading options
|
||||
Options for op_url_stream_create() and associated functions.
|
||||
These allow you to provide proxy configuration parameters, skip SSL
|
||||
@@ -685,7 +685,7 @@ void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1);
|
||||
times, only the value specified by the last occurrence has an effect
|
||||
(unless otherwise specified).
|
||||
They may be expanded in the future.*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
|
||||
/**@cond PRIVATE*/
|
||||
|
||||
@@ -698,7 +698,7 @@ void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1);
|
||||
#define OP_HTTP_PROXY_PASS_REQUEST (6720)
|
||||
#define OP_GET_SERVER_INFO_REQUEST (6784)
|
||||
|
||||
#define OP_URL_OPT(_request) ((char *)(_request))
|
||||
#define OP_URL_OPT(_request) ((_request)+(char *)0)
|
||||
|
||||
/*These macros trigger compilation errors or warnings if the wrong types are
|
||||
provided to one of the URL options.*/
|
||||
@@ -843,11 +843,11 @@ void opus_server_info_clear(OpusServerInfo *_info) OP_ARG_NONNULL(1);
|
||||
#define OP_GET_SERVER_INFO(_info) \
|
||||
OP_URL_OPT(OP_GET_SERVER_INFO_REQUEST),OP_CHECK_SERVER_INFO_PTR(_info)
|
||||
|
||||
/**@}*/
|
||||
/**@}*/
|
||||
/*@}*/
|
||||
/*@}*/
|
||||
|
||||
/**\defgroup stream_callbacks Abstract Stream Reading Interface*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
/**\name Functions for reading from streams
|
||||
These functions define the interface used to read from and seek in a stream
|
||||
of data.
|
||||
@@ -856,7 +856,7 @@ void opus_server_info_clear(OpusServerInfo *_info) OP_ARG_NONNULL(1);
|
||||
These functions also include some convenience routines for working with
|
||||
standard <code>FILE</code> pointers, complete streams stored in a single
|
||||
block of memory, or URLs.*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
|
||||
/**Reads up to \a _nbytes bytes of data from \a _stream.
|
||||
\param _stream The stream to read from.
|
||||
@@ -1034,18 +1034,18 @@ OP_WARN_UNUSED_RESULT void *op_url_stream_vcreate(OpusFileCallbacks *_cb,
|
||||
OP_WARN_UNUSED_RESULT void *op_url_stream_create(OpusFileCallbacks *_cb,
|
||||
const char *_url,...) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2);
|
||||
|
||||
/**@}*/
|
||||
/**@}*/
|
||||
/*@}*/
|
||||
/*@}*/
|
||||
|
||||
/**\defgroup stream_open_close Opening and Closing*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
/**\name Functions for opening and closing streams
|
||||
|
||||
These functions allow you to test a stream to see if it is Opus, open it,
|
||||
and close it.
|
||||
Several flavors are provided for each of the built-in stream types, plus a
|
||||
more general version which takes a set of application-provided callbacks.*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
|
||||
/**Test to see if this is an Opus stream.
|
||||
For good results, you will need at least 57 bytes (for a pure Opus-only
|
||||
@@ -1159,16 +1159,20 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url,
|
||||
This value will be passed verbatim as the first
|
||||
argument to all of the callbacks.
|
||||
\param _cb The callbacks with which to access the stream.
|
||||
\ref op_read_func "read()" must be implemented.
|
||||
\ref op_seek_func "seek()" and \ref op_tell_func
|
||||
"tell()" may be <code>NULL</code>, or may always
|
||||
return -1 to indicate a stream is unseekable, but if
|
||||
\ref op_seek_func "seek()" is implemented and
|
||||
succeeds on a particular stream, then \ref
|
||||
op_tell_func "tell()" must also.
|
||||
\ref op_close_func "close()" may be <code>NULL</code>,
|
||||
but if it is not, it will be called when the \c
|
||||
OggOpusFile is destroyed by op_free().
|
||||
<code><a href="#op_read_func">read()</a></code> must
|
||||
be implemented.
|
||||
<code><a href="#op_seek_func">seek()</a></code> and
|
||||
<code><a href="#op_tell_func">tell()</a></code> may
|
||||
be <code>NULL</code>, or may always return -1 to
|
||||
indicate a stream is unseekable, but if
|
||||
<code><a href="#op_seek_func">seek()</a></code> is
|
||||
implemented and succeeds on a particular stream, then
|
||||
<code><a href="#op_tell_func">tell()</a></code> must
|
||||
also.
|
||||
<code><a href="#op_close_func">close()</a></code> may
|
||||
be <code>NULL</code>, but if it is not, it will be
|
||||
called when the \c OggOpusFile is destroyed by
|
||||
op_free().
|
||||
It will not be called if op_open_callbacks() fails
|
||||
with an error.
|
||||
\param _initial_data An initial buffer of data from the start of the
|
||||
@@ -1179,8 +1183,10 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url,
|
||||
stream to be opened, even if it is unseekable.
|
||||
\param _initial_bytes The number of bytes in \a _initial_data.
|
||||
If the stream is seekable, its current position (as
|
||||
reported by \ref op_tell_func "tell()" at the start
|
||||
of this function) must be equal to \a _initial_bytes.
|
||||
reported by
|
||||
<code><a href="#opus_tell_func">tell()</a></code>
|
||||
at the start of this function) must be equal to
|
||||
\a _initial_bytes.
|
||||
Otherwise, seeking to absolute positions will
|
||||
generate inconsistent results.
|
||||
\param[out] _error Returns 0 on success, or a failure code on error.
|
||||
@@ -1200,10 +1206,11 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url,
|
||||
implemented, such as an unsupported channel
|
||||
family.</dd>
|
||||
<dt>#OP_EINVAL</dt>
|
||||
<dd>\ref op_seek_func "seek()" was implemented and
|
||||
succeeded on this source, but \ref op_tell_func
|
||||
"tell()" did not, or the starting position
|
||||
indicator was not equal to \a _initial_bytes.</dd>
|
||||
<dd><code><a href="#op_seek_func">seek()</a></code>
|
||||
was implemented and succeeded on this source, but
|
||||
<code><a href="#op_tell_func">tell()</a></code>
|
||||
did not, or the starting position indicator was
|
||||
not equal to \a _initial_bytes.</dd>
|
||||
<dt>#OP_ENOTFORMAT</dt>
|
||||
<dd>The stream contained a link that did not have
|
||||
any logical Opus streams in it.</dd>
|
||||
@@ -1334,16 +1341,20 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url,
|
||||
This value will be passed verbatim as the first
|
||||
argument to all of the callbacks.
|
||||
\param _cb The callbacks with which to access the stream.
|
||||
\ref op_read_func "read()" must be implemented.
|
||||
\ref op_seek_func "seek()" and \ref op_tell_func
|
||||
"tell()" may be <code>NULL</code>, or may always
|
||||
return -1 to indicate a stream is unseekable, but if
|
||||
\ref op_seek_func "seek()" is implemented and
|
||||
succeeds on a particular stream, then \ref
|
||||
op_tell_func "tell()" must also.
|
||||
\ref op_close_func "close()" may be <code>NULL</code>,
|
||||
but if it is not, it will be called when the \c
|
||||
OggOpusFile is destroyed by op_free().
|
||||
<code><a href="#op_read_func">read()</a></code> must
|
||||
be implemented.
|
||||
<code><a href="#op_seek_func">seek()</a></code> and
|
||||
<code><a href="#op_tell_func">tell()</a></code> may
|
||||
be <code>NULL</code>, or may always return -1 to
|
||||
indicate a stream is unseekable, but if
|
||||
<code><a href="#op_seek_func">seek()</a></code> is
|
||||
implemented and succeeds on a particular stream, then
|
||||
<code><a href="#op_tell_func">tell()</a></code> must
|
||||
also.
|
||||
<code><a href="#op_close_func">close()</a></code> may
|
||||
be <code>NULL</code>, but if it is not, it will be
|
||||
called when the \c OggOpusFile is destroyed by
|
||||
op_free().
|
||||
It will not be called if op_open_callbacks() fails
|
||||
with an error.
|
||||
\param _initial_data An initial buffer of data from the start of the
|
||||
@@ -1356,8 +1367,9 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url,
|
||||
\param _initial_bytes The number of bytes in \a _initial_data.
|
||||
If the stream is seekable, its current position (as
|
||||
reported by
|
||||
\ref op_tell_func "tell()" at the start of this
|
||||
function) must be equal to \a _initial_bytes.
|
||||
<code><a href="#opus_tell_func">tell()</a></code>
|
||||
at the start of this function) must be equal to
|
||||
\a _initial_bytes.
|
||||
Otherwise, seeking to absolute positions will
|
||||
generate inconsistent results.
|
||||
\param[out] _error Returns 0 on success, or a failure code on error.
|
||||
@@ -1406,11 +1418,11 @@ int op_test_open(OggOpusFile *_of) OP_ARG_NONNULL(1);
|
||||
\param _of The \c OggOpusFile to free.*/
|
||||
void op_free(OggOpusFile *_of);
|
||||
|
||||
/**@}*/
|
||||
/**@}*/
|
||||
/*@}*/
|
||||
/*@}*/
|
||||
|
||||
/**\defgroup stream_info Stream Information*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
/**\name Functions for obtaining information about streams
|
||||
|
||||
These functions allow you to get basic information about a stream, including
|
||||
@@ -1425,17 +1437,18 @@ void op_free(OggOpusFile *_of);
|
||||
streams returned by op_test_callbacks() or one of the associated
|
||||
convenience functions.
|
||||
Their documention will indicate so explicitly.*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
|
||||
/**Returns whether or not the stream being read is seekable.
|
||||
This is true if
|
||||
<ol>
|
||||
<li>The \ref op_seek_func "seek()" and \ref op_tell_func "tell()"
|
||||
callbacks are both non-<code>NULL</code>,</li>
|
||||
<li>The \ref op_seek_func "seek()" callback was successfully executed at
|
||||
least once, and</li>
|
||||
<li>The \ref op_tell_func "tell()" callback was successfully able to report
|
||||
the position indicator afterwards.</li>
|
||||
<li>The <code><a href="#op_seek_func">seek()</a></code> and
|
||||
<code><a href="#op_tell_func">tell()</a></code> callbacks are both
|
||||
non-<code>NULL</code>,</li>
|
||||
<li>The <code><a href="#op_seek_func">seek()</a></code> callback was
|
||||
successfully executed at least once, and</li>
|
||||
<li>The <code><a href="#op_tell_func">tell()</a></code> callback was
|
||||
successfully able to report the position indicator afterwards.</li>
|
||||
</ol>
|
||||
This function may be called on partially-opened streams.
|
||||
\param _of The \c OggOpusFile whose seekable status is to be returned.
|
||||
@@ -1625,11 +1638,11 @@ opus_int64 op_raw_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1);
|
||||
\retval #OP_EINVAL The stream was only partially open.*/
|
||||
ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
/**@}*/
|
||||
/*@}*/
|
||||
/*@}*/
|
||||
|
||||
/**\defgroup stream_seeking Seeking*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
/**\name Functions for seeking in Opus streams
|
||||
|
||||
These functions let you seek in Opus streams, if the underlying stream
|
||||
@@ -1654,7 +1667,7 @@ ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1);
|
||||
values as would be obtained by decoding the stream straight through.
|
||||
However, such differences are expected to be smaller than the loss
|
||||
introduced by Opus's lossy compression.*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
|
||||
/**Seek to a byte offset relative to the <b>compressed</b> data.
|
||||
This also scans packets to update the PCM cursor.
|
||||
@@ -1689,11 +1702,11 @@ int op_raw_seek(OggOpusFile *_of,opus_int64 _byte_offset) OP_ARG_NONNULL(1);
|
||||
seeking to the target destination was impossible.*/
|
||||
int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset) OP_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
/**@}*/
|
||||
/*@}*/
|
||||
/*@}*/
|
||||
|
||||
/**\defgroup stream_decoding Decoding*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
/**\name Functions for decoding audio data
|
||||
|
||||
These functions retrieve actual decoded audio data from the stream.
|
||||
@@ -1731,7 +1744,7 @@ int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset) OP_ARG_NONNULL(1);
|
||||
If you are reading from an <https:> URL (particularly if seeking is not
|
||||
supported), you should make sure to check for this error and warn the user
|
||||
appropriately.*/
|
||||
/**@{*/
|
||||
/*@{*/
|
||||
|
||||
/**Indicates that the decoding callback should produce signed 16-bit
|
||||
native-endian output samples.*/
|
||||
@@ -1877,7 +1890,7 @@ void op_set_dither_enabled(OggOpusFile *_of,int _enabled) OP_ARG_NONNULL(1);
|
||||
signed native-endian 16-bit values at 48 kHz
|
||||
with a nominal range of <code>[-32768,32767)</code>.
|
||||
Multiple channels are interleaved using the
|
||||
<a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis
|
||||
<a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis
|
||||
channel ordering</a>.
|
||||
This must have room for at least \a _buf_size values.
|
||||
\param _buf_size The number of values that can be stored in \a _pcm.
|
||||
@@ -1959,7 +1972,7 @@ OP_WARN_UNUSED_RESULT int op_read(OggOpusFile *_of,
|
||||
signed floats at 48 kHz with a nominal range of
|
||||
<code>[-1.0,1.0]</code>.
|
||||
Multiple channels are interleaved using the
|
||||
<a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis
|
||||
<a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis
|
||||
channel ordering</a>.
|
||||
This must have room for at least \a _buf_size floats.
|
||||
\param _buf_size The number of floats that can be stored in \a _pcm.
|
||||
@@ -2137,8 +2150,8 @@ OP_WARN_UNUSED_RESULT int op_read_stereo(OggOpusFile *_of,
|
||||
OP_WARN_UNUSED_RESULT int op_read_float_stereo(OggOpusFile *_of,
|
||||
float *_pcm,int _buf_size) OP_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
/**@}*/
|
||||
/*@}*/
|
||||
/*@}*/
|
||||
|
||||
# if OP_GNUC_PREREQ(4,0)
|
||||
# pragma GCC visibility pop
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
components/codecs/lib/libopusfile.a
Normal file
BIN
components/codecs/lib/libopusfile.a
Normal file
Binary file not shown.
@@ -2,25 +2,16 @@
|
||||
* Squeezelite for esp32
|
||||
*
|
||||
* (c) Sebastien 2019
|
||||
* Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* (c) Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
#include "platform_config.h"
|
||||
//#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
||||
#include "config.h"
|
||||
#include "nvs_utilities.h"
|
||||
#include "platform_esp32.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
@@ -30,26 +21,25 @@
|
||||
#include "driver/uart.h"
|
||||
#include "linenoise/linenoise.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs_utilities.h"
|
||||
#include "cJSON.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "tools.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
#define CONFIG_COMMIT_DELAY 1000
|
||||
#define LOCK_MAX_WAIT 20*CONFIG_COMMIT_DELAY
|
||||
static const char * TAG = "config";
|
||||
EXT_RAM_ATTR static cJSON * nvs_json=NULL;
|
||||
EXT_RAM_ATTR static TimerHandle_t timer;
|
||||
EXT_RAM_ATTR static SemaphoreHandle_t config_mutex = NULL;
|
||||
EXT_RAM_ATTR static EventGroupHandle_t config_group;
|
||||
static cJSON * nvs_json=NULL;
|
||||
static TimerHandle_t timer;
|
||||
static SemaphoreHandle_t config_mutex = NULL;
|
||||
static EventGroupHandle_t config_group;
|
||||
/* @brief indicate that the ESP32 is currently connected. */
|
||||
EXT_RAM_ATTR static const int CONFIG_NO_COMMIT_PENDING = BIT0;
|
||||
EXT_RAM_ATTR static const int CONFIG_LOAD_BIT = BIT1;
|
||||
static const int CONFIG_NO_COMMIT_PENDING = BIT0;
|
||||
static const int CONFIG_LOAD_BIT = BIT1;
|
||||
|
||||
bool config_lock(TickType_t xTicksToWait);
|
||||
void config_unlock();
|
||||
@@ -57,11 +47,11 @@ extern esp_err_t nvs_load_config();
|
||||
void config_raise_change(bool flag);
|
||||
cJSON_bool config_is_entry_changed(cJSON * entry);
|
||||
bool config_set_group_bit(int bit_num,bool flag);
|
||||
cJSON * config_set_value_safe(nvs_type_t nvs_type, const char *key,const void * value);
|
||||
cJSON * config_set_value_safe(nvs_type_t nvs_type, const char *key, void * value);
|
||||
static void vCallbackFunction( TimerHandle_t xTimer );
|
||||
void config_set_entry_changed_flag(cJSON * entry, cJSON_bool flag);
|
||||
#define IMPLEMENT_SET_DEFAULT(t,nt) void config_set_default_## t (const char *key, t value){\
|
||||
void * pval = malloc_init_external(sizeof(value));\
|
||||
void * pval = malloc(sizeof(value));\
|
||||
*((t *) pval) = value;\
|
||||
config_set_default(nt, key,pval,0);\
|
||||
free(pval); }
|
||||
@@ -69,43 +59,55 @@ void config_set_entry_changed_flag(cJSON * entry, cJSON_bool flag);
|
||||
void * pval = config_alloc_get(nt, key);\
|
||||
if(pval!=NULL){ *value = *(t * )pval; free(pval); return ESP_OK; }\
|
||||
return ESP_FAIL;}
|
||||
#if RECOVERY_APPLICATION==0
|
||||
static void * malloc_fn(size_t sz){
|
||||
|
||||
void * ptr = is_recovery_running?malloc(sz):heap_caps_malloc(sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
void * ptr = heap_caps_malloc(sz, MALLOC_CAP_SPIRAM);
|
||||
if(ptr==NULL){
|
||||
ESP_LOGE(TAG,"malloc_fn: unable to allocate memory!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
/*
|
||||
static void * free_fn(void * ptr){
|
||||
if(ptr!=NULL){
|
||||
heap_caps_free(ptr);
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG,"free_fn: Cannot free null pointer!");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
void init_cJSON(){
|
||||
static cJSON_Hooks hooks;
|
||||
// initialize cJSON hooks it uses SPIRAM memory
|
||||
// as opposed to IRAM
|
||||
#if RECOVERY_APPLICATION==0
|
||||
// In squeezelite mode, allocate memory from PSRAM. Otherwise allocate from internal RAM
|
||||
// as recovery will lock flash access when erasing FLASH or writing to OTA partition.
|
||||
hooks.malloc_fn=&malloc_fn;
|
||||
//hooks.free_fn=&free_fn;
|
||||
cJSON_InitHooks(&hooks);
|
||||
#endif
|
||||
}
|
||||
void config_init(){
|
||||
ESP_LOGD(TAG, "Creating mutex for Config");
|
||||
MEMTRACE_PRINT_DELTA();
|
||||
config_mutex = xSemaphoreCreateMutex();
|
||||
MEMTRACE_PRINT_DELTA();
|
||||
ESP_LOGD(TAG, "Creating event group");
|
||||
MEMTRACE_PRINT_DELTA();
|
||||
config_group = xEventGroupCreate();
|
||||
MEMTRACE_PRINT_DELTA();
|
||||
ESP_LOGD(TAG, "Loading config from nvs");
|
||||
|
||||
init_cJSON();
|
||||
MEMTRACE_PRINT_DELTA();
|
||||
if(nvs_json !=NULL){
|
||||
cJSON_Delete(nvs_json);
|
||||
}
|
||||
nvs_json = cJSON_CreateObject();
|
||||
|
||||
config_set_group_bit(CONFIG_LOAD_BIT,true);
|
||||
MEMTRACE_PRINT_DELTA();
|
||||
nvs_load_config();
|
||||
MEMTRACE_PRINT_DELTA();
|
||||
config_set_group_bit(CONFIG_LOAD_BIT,false);
|
||||
MEMTRACE_PRINT_DELTA();
|
||||
config_start_timer();
|
||||
}
|
||||
|
||||
@@ -121,7 +123,7 @@ void config_start_timer(){
|
||||
nvs_type_t config_get_item_type(cJSON * entry){
|
||||
if(entry==NULL){
|
||||
ESP_LOGE(TAG,"null pointer received!");
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
cJSON * item_type = cJSON_GetObjectItemCaseSensitive(entry, "type");
|
||||
if(item_type ==NULL ) {
|
||||
@@ -133,7 +135,7 @@ nvs_type_t config_get_item_type(cJSON * entry){
|
||||
}
|
||||
|
||||
|
||||
cJSON * config_set_value_safe(nvs_type_t nvs_type, const char *key, const void * value){
|
||||
cJSON * config_set_value_safe(nvs_type_t nvs_type, const char *key, void * value){
|
||||
cJSON * entry = cJSON_CreateObject();
|
||||
|
||||
double numvalue = 0;
|
||||
@@ -142,7 +144,7 @@ cJSON * config_set_value_safe(nvs_type_t nvs_type, const char *key, const void
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cJSON * existing = cJSON_GetObjectItemCaseSensitive(nvs_json, key);
|
||||
cJSON * existing = cJSON_GetObjectItemCaseSensitive(nvs_json, key);
|
||||
if(existing !=NULL && nvs_type == NVS_TYPE_STR && config_get_item_type(existing) != NVS_TYPE_STR ) {
|
||||
ESP_LOGW(TAG, "Storing numeric value from string");
|
||||
numvalue = atof((char *)value);
|
||||
@@ -325,51 +327,49 @@ void * config_safe_alloc_get_entry_value(nvs_type_t nvs_type, cJSON * entry){
|
||||
return NULL;
|
||||
}
|
||||
if (nvs_type == NVS_TYPE_I8) {
|
||||
value=malloc_init_external(sizeof(int8_t));
|
||||
value=malloc(sizeof(int8_t));
|
||||
*(int8_t *)value = (int8_t)entry_value->valuedouble;
|
||||
} else if (nvs_type == NVS_TYPE_U8) {
|
||||
value=malloc_init_external(sizeof(uint8_t));
|
||||
value=malloc(sizeof(uint8_t));
|
||||
*(uint8_t *)value = (uint8_t)entry_value->valuedouble;
|
||||
} else if (nvs_type == NVS_TYPE_I16) {
|
||||
value=malloc_init_external(sizeof(int16_t));
|
||||
value=malloc(sizeof(int16_t));
|
||||
*(int16_t *)value = (int16_t)entry_value->valuedouble;
|
||||
} else if (nvs_type == NVS_TYPE_U16) {
|
||||
value=malloc_init_external(sizeof(uint16_t));
|
||||
value=malloc(sizeof(uint16_t));
|
||||
*(uint16_t *)value = (uint16_t)entry_value->valuedouble;
|
||||
} else if (nvs_type == NVS_TYPE_I32) {
|
||||
value=malloc_init_external(sizeof(int32_t));
|
||||
value=malloc(sizeof(int32_t));
|
||||
*(int32_t *)value = (int32_t)entry_value->valuedouble;
|
||||
} else if (nvs_type == NVS_TYPE_U32) {
|
||||
value=malloc_init_external(sizeof(uint32_t));
|
||||
value=malloc(sizeof(uint32_t));
|
||||
*(uint32_t *)value = (uint32_t)entry_value->valuedouble;
|
||||
} else if (nvs_type == NVS_TYPE_I64) {
|
||||
value=malloc_init_external(sizeof(int64_t));
|
||||
value=malloc(sizeof(int64_t));
|
||||
*(int64_t *)value = (int64_t)entry_value->valuedouble;
|
||||
} else if (nvs_type == NVS_TYPE_U64) {
|
||||
value=malloc_init_external(sizeof(uint64_t));
|
||||
value=malloc(sizeof(uint64_t));
|
||||
*(uint64_t *)value = (uint64_t)entry_value->valuedouble;
|
||||
} else if (nvs_type == NVS_TYPE_STR) {
|
||||
if(!cJSON_IsString(entry_value)){
|
||||
char * entry_str = cJSON_PrintUnformatted(entry);
|
||||
if(entry_str!=NULL){
|
||||
ESP_LOGE(TAG, "requested value type string, config type is different. key: %s, value: %s, type %d, Object: \n%s",
|
||||
str_or_null(entry_value->string),
|
||||
str_or_null(entry_value->valuestring),
|
||||
entry_value->type,
|
||||
str_or_null(entry_str));
|
||||
entry_value->string,
|
||||
entry_value->valuestring,
|
||||
entry_value->type,
|
||||
entry_str);
|
||||
free(entry_str);
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG, "requested value type string, config type is different. key: %s, value: %s, type %d",
|
||||
str_or_null(entry_value->string),
|
||||
str_or_null(entry_value->valuestring),
|
||||
entry_value->type);
|
||||
entry_value->string,
|
||||
entry_value->valuestring,
|
||||
entry_value->type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t len=strlen(cJSON_GetStringValue(entry_value));
|
||||
value=(void *)malloc_init_external(len+1);
|
||||
memcpy(value,cJSON_GetStringValue(entry_value),len);
|
||||
value=(void *)strdup(cJSON_GetStringValue(entry_value));
|
||||
if(value==NULL){
|
||||
char * entry_str = cJSON_PrintUnformatted(entry);
|
||||
if(entry_str!=NULL){
|
||||
@@ -389,6 +389,7 @@ void * config_safe_alloc_get_entry_value(nvs_type_t nvs_type, cJSON * entry){
|
||||
|
||||
void config_commit_to_nvs(){
|
||||
ESP_LOGI(TAG,"Committing configuration to nvs. Locking config object.");
|
||||
ESP_LOGV(TAG,"config_commit_to_nvs. Locking config object.");
|
||||
if(!config_lock(LOCK_MAX_WAIT/portTICK_PERIOD_MS)){
|
||||
ESP_LOGE(TAG, "config_commit_to_nvs: Unable to lock config for commit ");
|
||||
return ;
|
||||
@@ -411,13 +412,8 @@ void config_commit_to_nvs(){
|
||||
nvs_type_t type = config_get_entry_type(entry);
|
||||
void * value = config_safe_alloc_get_entry_value(type, entry);
|
||||
if(value!=NULL){
|
||||
size_t len=strlen(entry->string);
|
||||
char * key=(void *)malloc_init_external(len+1);
|
||||
memcpy(key,entry->string,len);
|
||||
esp_err_t err = store_nvs_value(type,key,value);
|
||||
FREE_AND_NULL(key);
|
||||
FREE_AND_NULL(value);
|
||||
|
||||
esp_err_t err = store_nvs_value(type,entry->string,value);
|
||||
free(value);
|
||||
if(err!=ESP_OK){
|
||||
char * entry_str = cJSON_PrintUnformatted(entry);
|
||||
if(entry_str!=NULL){
|
||||
@@ -453,7 +449,6 @@ void config_commit_to_nvs(){
|
||||
config_raise_change(false);
|
||||
ESP_LOGV(TAG,"config_commit_to_nvs. Releasing the lock object.");
|
||||
config_unlock();
|
||||
ESP_LOGI(TAG,"Done Committing configuration to nvs.");
|
||||
}
|
||||
bool config_has_changes(){
|
||||
return (xEventGroupGetBits(config_group) & CONFIG_NO_COMMIT_PENDING)==0;
|
||||
@@ -538,7 +533,7 @@ bool config_set_group_bit(int bit_num,bool flag){
|
||||
return result;
|
||||
}
|
||||
|
||||
void config_set_default(nvs_type_t type, const char *key, const void * default_value, size_t blob_size) {
|
||||
void config_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size) {
|
||||
if(!config_lock(LOCK_MAX_WAIT/portTICK_PERIOD_MS)){
|
||||
ESP_LOGE(TAG, "Unable to lock config");
|
||||
return;
|
||||
@@ -573,7 +568,7 @@ void config_delete_key(const char *key){
|
||||
ESP_LOGD(TAG, "Deleting nvs entry for [%s]", key);
|
||||
if(!config_lock(LOCK_MAX_WAIT/portTICK_PERIOD_MS)){
|
||||
ESP_LOGE(TAG, "Unable to lock config for delete");
|
||||
return ;
|
||||
return false;
|
||||
}
|
||||
esp_err_t err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs);
|
||||
if (err == ESP_OK) {
|
||||
@@ -620,47 +615,13 @@ void config_delete_key(const char *key){
|
||||
void * config_alloc_get(nvs_type_t nvs_type, const char *key) {
|
||||
return config_alloc_get_default(nvs_type, key, NULL, 0);
|
||||
}
|
||||
cJSON * config_alloc_get_cjson(const char *key){
|
||||
char * conf_str = config_alloc_get_default(NVS_TYPE_STR, key, NULL, 0);
|
||||
if(conf_str==NULL){
|
||||
ESP_LOGE(TAG, "Unable to get config value for key [%s]", key);
|
||||
return NULL;
|
||||
}
|
||||
cJSON * conf_json = cJSON_Parse(conf_str);
|
||||
free(conf_str);
|
||||
if(conf_json==NULL){
|
||||
ESP_LOGE(TAG, "Unable to parse config value for key [%s]", key);
|
||||
return NULL;
|
||||
}
|
||||
return conf_json;
|
||||
}
|
||||
esp_err_t config_set_cjson_str_and_free(const char *key, cJSON *value){
|
||||
char * value_str = cJSON_PrintUnformatted(value);
|
||||
if(value_str==NULL){
|
||||
ESP_LOGE(TAG, "Unable to print cJSON for key [%s]", key);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
esp_err_t err = config_set_value(NVS_TYPE_STR,key, value_str);
|
||||
free(value_str);
|
||||
cJSON_Delete(value);
|
||||
return err;
|
||||
}
|
||||
void config_get_uint16t_from_str(const char *key, uint16_t *value, uint16_t default_value){
|
||||
char * str_value = config_alloc_get(NVS_TYPE_STR, key);
|
||||
if(str_value == NULL){
|
||||
*value = default_value;
|
||||
return ;
|
||||
}
|
||||
*value = atoi(str_value);
|
||||
free(str_value);
|
||||
}
|
||||
|
||||
void * config_alloc_get_str(const char *key, char *lead, char *fallback) {
|
||||
if (lead && *lead) return strdup_psram(lead);
|
||||
if (lead && *lead) return strdup(lead);
|
||||
char *value = config_alloc_get_default(NVS_TYPE_STR, key, NULL, 0);
|
||||
if ((!value || !*value) && fallback) {
|
||||
if (value) free(value);
|
||||
value = strdup_psram(fallback);
|
||||
value = strdup(fallback);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -712,7 +673,7 @@ char * config_alloc_get_json(bool bFormatted){
|
||||
char * json_buffer = NULL;
|
||||
if(!config_lock(LOCK_MAX_WAIT/portTICK_PERIOD_MS)){
|
||||
ESP_LOGE(TAG, "Unable to lock config after %d ms",LOCK_MAX_WAIT);
|
||||
return strdup_psram("{\"error\":\"Unable to lock configuration object.\"}");
|
||||
return strdup("{\"error\":\"Unable to lock configuration object.\"}");
|
||||
}
|
||||
if(bFormatted){
|
||||
json_buffer= cJSON_Print(nvs_json);
|
||||
@@ -723,12 +684,8 @@ char * config_alloc_get_json(bool bFormatted){
|
||||
config_unlock();
|
||||
return json_buffer;
|
||||
}
|
||||
esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, const void * value){
|
||||
esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value){
|
||||
esp_err_t result = ESP_OK;
|
||||
if(!key ||!key[0]){
|
||||
ESP_LOGW(TAG,"Empty key passed. Ignoring entry!");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if(!config_lock(LOCK_MAX_WAIT/portTICK_PERIOD_MS)){
|
||||
ESP_LOGE(TAG, "Unable to lock config after %d ms",LOCK_MAX_WAIT);
|
||||
result = ESP_FAIL;
|
||||
@@ -750,42 +707,7 @@ esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, const void * va
|
||||
config_unlock();
|
||||
return result;
|
||||
}
|
||||
cJSON* cjson_update_string(cJSON** root, const char* key, const char* value) {
|
||||
if (*root == NULL) {
|
||||
*root = cJSON_CreateObject();
|
||||
if (*root == NULL) {
|
||||
ESP_LOGE(TAG, "Error creating cJSON object!");
|
||||
}
|
||||
}
|
||||
if (!key || !value || strlen(key) == 0) {
|
||||
ESP_LOGE(TAG, "cjson_update_string. Invalid key or value passed! key: %s, value: %s", STR_OR_ALT(key, ""), STR_OR_ALT(value, ""));
|
||||
return *root;
|
||||
}
|
||||
cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
|
||||
if (cjsonvalue && strcasecmp(cJSON_GetStringValue(cjsonvalue), value) != 0) {
|
||||
ESP_LOGD(TAG, "Value %s changed from %s to %s", key, cJSON_GetStringValue(cjsonvalue), value);
|
||||
cJSON_SetValuestring(cjsonvalue, value);
|
||||
} else if(!cjsonvalue){
|
||||
ESP_LOGD(TAG, "Adding new value %s: %s", key, value);
|
||||
cJSON_AddItemToObject(*root, key, cJSON_CreateString(value));
|
||||
}
|
||||
return *root;
|
||||
}
|
||||
cJSON* cjson_update_number(cJSON** root, const char* key, int value) {
|
||||
|
||||
if (*root == NULL) {
|
||||
*root = cJSON_CreateObject();
|
||||
}
|
||||
if (key && strlen(key) != 0) {
|
||||
cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
|
||||
if (cjsonvalue) {
|
||||
cJSON_SetNumberValue(cjsonvalue, value);
|
||||
} else {
|
||||
cJSON_AddNumberToObject(*root, key, value);
|
||||
}
|
||||
}
|
||||
return *root;
|
||||
}
|
||||
IMPLEMENT_SET_DEFAULT(uint8_t,NVS_TYPE_U8);
|
||||
IMPLEMENT_SET_DEFAULT(int8_t,NVS_TYPE_I8);
|
||||
IMPLEMENT_SET_DEFAULT(uint16_t,NVS_TYPE_U16);
|
||||
41
components/config/config.h
Normal file
41
components/config/config.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "nvs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define DECLARE_SET_DEFAULT(t) void config_set_default_## t (const char *key, t value);
|
||||
#define DECLARE_GET_NUM(t) esp_err_t config_get_## t (const char *key, t * value);
|
||||
|
||||
|
||||
DECLARE_SET_DEFAULT(uint8_t);
|
||||
DECLARE_SET_DEFAULT(uint16_t);
|
||||
DECLARE_SET_DEFAULT(uint32_t);
|
||||
DECLARE_SET_DEFAULT(int8_t);
|
||||
DECLARE_SET_DEFAULT(int16_t);
|
||||
DECLARE_SET_DEFAULT(int32_t);
|
||||
DECLARE_GET_NUM(uint8_t);
|
||||
DECLARE_GET_NUM(uint16_t);
|
||||
DECLARE_GET_NUM(uint32_t);
|
||||
DECLARE_GET_NUM(int8_t);
|
||||
DECLARE_GET_NUM(int16_t);
|
||||
DECLARE_GET_NUM(int32_t);
|
||||
|
||||
bool config_has_changes();
|
||||
void config_commit_to_nvs();
|
||||
void config_start_timer();
|
||||
void config_init();
|
||||
void * config_alloc_get_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
|
||||
void config_delete_key(const char *key);
|
||||
void config_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
|
||||
void * config_alloc_get(nvs_type_t nvs_type, const char *key) ;
|
||||
void * config_alloc_get_str(const char *key, char *lead, char *fallback);
|
||||
bool wait_for_commit();
|
||||
char * config_alloc_get_json(bool bFormatted);
|
||||
esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
||||
#include "nvs_utilities.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -9,12 +10,11 @@
|
||||
#include "driver/uart.h"
|
||||
#include "linenoise/linenoise.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs_utilities.h"
|
||||
#include "platform_config.h"
|
||||
#include "tools.h"
|
||||
#include "config.h"
|
||||
|
||||
const char current_namespace[] = "config";
|
||||
const char settings_partition[] = "settings";
|
||||
@@ -69,11 +69,6 @@ const char *type_to_str(nvs_type_t type)
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
void erase_settings_partition(){
|
||||
ESP_LOGW(TAG, "Erasing nvs on partition %s",settings_partition);
|
||||
ESP_ERROR_CHECK(nvs_flash_erase_partition(settings_partition));
|
||||
nvs_flash_init_partition(settings_partition);
|
||||
}
|
||||
void initialize_nvs() {
|
||||
ESP_LOGI(TAG, "Initializing flash nvs ");
|
||||
esp_err_t err = nvs_flash_init();
|
||||
@@ -100,89 +95,62 @@ void initialize_nvs() {
|
||||
ESP_LOGD(TAG, "nvs init completed");
|
||||
}
|
||||
|
||||
esp_err_t nvs_load_config() {
|
||||
nvs_entry_info_t info;
|
||||
esp_err_t err = ESP_OK;
|
||||
size_t malloc_int = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
size_t malloc_spiram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||
esp_err_t nvs_load_config(){
|
||||
nvs_entry_info_t info;
|
||||
esp_err_t err = ESP_OK;
|
||||
size_t malloc_int = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
size_t malloc_spiram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||
|
||||
nvs_iterator_t it = nvs_entry_find(settings_partition, NULL, NVS_TYPE_ANY);
|
||||
if (it == NULL) {
|
||||
ESP_LOGW(TAG, "empty nvs partition %s, namespace %s", settings_partition, current_namespace);
|
||||
}
|
||||
while (it != NULL) {
|
||||
nvs_entry_info(it, &info);
|
||||
nvs_iterator_t it = nvs_entry_find(settings_partition, NULL, NVS_TYPE_ANY);
|
||||
if(it == NULL) {
|
||||
ESP_LOGW(TAG, "empty nvs partition %s, namespace %s",settings_partition,current_namespace );
|
||||
}
|
||||
while (it != NULL) {
|
||||
nvs_entry_info(it, &info);
|
||||
|
||||
if (strstr(info.namespace_name, current_namespace)) {
|
||||
if (strlen(info.key) == 0) {
|
||||
ESP_LOGW(TAG, "empty key name in namespace %s. Removing it.", current_namespace);
|
||||
nvs_handle_t nvs_handle;
|
||||
err = nvs_open(settings_partition, NVS_READWRITE, &nvs_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "nvs_open failed. %s", esp_err_to_name(err));
|
||||
} else {
|
||||
if ((err = nvs_erase_key(nvs_handle, info.key)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "nvs_erase_key failed. %s", esp_err_to_name(err));
|
||||
} else {
|
||||
nvs_commit(nvs_handle);
|
||||
}
|
||||
nvs_close(nvs_handle);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGW(TAG, "nvs_erase_key completed on empty key. Restarting system to apply changes.");
|
||||
esp_restart();
|
||||
}
|
||||
}
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "nvs_erase_key failed on empty key. Configuration partition should be erased. %s", esp_err_to_name(err));
|
||||
err = ESP_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
void* value = get_nvs_value_alloc(info.type, info.key);
|
||||
if (value == NULL) {
|
||||
ESP_LOGE(TAG, "nvs read failed.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
config_set_value(info.type, info.key, value);
|
||||
free(value);
|
||||
if(strstr(info.namespace_name, current_namespace)) {
|
||||
void * value = get_nvs_value_alloc(info.type,info.key);
|
||||
if(value==NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "nvs read failed.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
it = nvs_entry_next(it);
|
||||
}
|
||||
char* json_string = config_alloc_get_json(false);
|
||||
if (json_string != NULL) {
|
||||
ESP_LOGD(TAG, "config json : %s\n", json_string);
|
||||
free(json_string);
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "Configuration memory usage. Heap internal:%zu (min:%zu) (used:%zu) external:%zu (min:%zu) (used:%zd)",
|
||||
heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL),
|
||||
malloc_int - heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM),
|
||||
malloc_spiram - heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
return err;
|
||||
config_set_value(info.type, info.key, value);
|
||||
free(value );
|
||||
}
|
||||
it = nvs_entry_next(it);
|
||||
}
|
||||
char * json_string= config_alloc_get_json(false);
|
||||
if(json_string!=NULL) {
|
||||
ESP_LOGD(TAG, "config json : %s\n", json_string);
|
||||
free(json_string);
|
||||
}
|
||||
ESP_LOGD(TAG,"Config memory usage. Heap internal:%zu (min:%zu) (used:%zu) external:%zu (min:%zu) (used:%zd)",
|
||||
heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL),
|
||||
malloc_int-heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM),
|
||||
malloc_spiram -heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t store_nvs_value(nvs_type_t type, const char *key, void * data) {
|
||||
if (type == NVS_TYPE_BLOB)
|
||||
return ESP_ERR_NVS_TYPE_MISMATCH;
|
||||
return store_nvs_value_len(type, key, data,0);
|
||||
}
|
||||
esp_err_t store_nvs_value_len_for_partition(const char * partition,const char * namespace,nvs_type_t type, const char *key, const void * data,size_t data_len) {
|
||||
esp_err_t store_nvs_value_len(nvs_type_t type, const char *key, void * data,
|
||||
size_t data_len) {
|
||||
esp_err_t err;
|
||||
nvs_handle nvs;
|
||||
if(!key || key[0]=='\0'){
|
||||
ESP_LOGE(TAG, "Cannot store value to nvs: key is empty");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
if (type == NVS_TYPE_ANY) {
|
||||
return ESP_ERR_NVS_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
err = nvs_open_from_partition(partition, namespace, NVS_READWRITE, &nvs);
|
||||
err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
@@ -217,65 +185,53 @@ esp_err_t store_nvs_value_len_for_partition(const char * partition,const char *
|
||||
nvs_close(nvs);
|
||||
return err;
|
||||
}
|
||||
esp_err_t store_nvs_value_len(nvs_type_t type, const char *key, void * data,
|
||||
size_t data_len) {
|
||||
return store_nvs_value_len_for_partition(settings_partition,current_namespace,type,key,data,data_len);
|
||||
}
|
||||
void * get_nvs_value_alloc_for_partition(const char * partition,const char * namespace,nvs_type_t type, const char *key, size_t * size){
|
||||
void * get_nvs_value_alloc(nvs_type_t type, const char *key) {
|
||||
nvs_handle nvs;
|
||||
esp_err_t err;
|
||||
void * value=NULL;
|
||||
if(size){
|
||||
*size=0;
|
||||
}
|
||||
err = nvs_open_from_partition(partition, namespace, NVS_READONLY, &nvs);
|
||||
|
||||
err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READONLY, &nvs);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not open the nvs storage.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (type == NVS_TYPE_I8) {
|
||||
value=malloc_init_external(sizeof(int8_t));
|
||||
value=malloc(sizeof(int8_t));
|
||||
err = nvs_get_i8(nvs, key, (int8_t *) value);
|
||||
} else if (type == NVS_TYPE_U8) {
|
||||
value=malloc_init_external(sizeof(uint8_t));
|
||||
value=malloc(sizeof(uint8_t));
|
||||
err = nvs_get_u8(nvs, key, (uint8_t *) value);
|
||||
} else if (type == NVS_TYPE_I16) {
|
||||
value=malloc_init_external(sizeof(int16_t));
|
||||
value=malloc(sizeof(int16_t));
|
||||
err = nvs_get_i16(nvs, key, (int16_t *) value);
|
||||
} else if (type == NVS_TYPE_U16) {
|
||||
value=malloc_init_external(sizeof(uint16_t));
|
||||
value=malloc(sizeof(uint16_t));
|
||||
err = nvs_get_u16(nvs, key, (uint16_t *) value);
|
||||
} else if (type == NVS_TYPE_I32) {
|
||||
value=malloc_init_external(sizeof(int32_t));
|
||||
value=malloc(sizeof(int32_t));
|
||||
err = nvs_get_i32(nvs, key, (int32_t *) value);
|
||||
} else if (type == NVS_TYPE_U32) {
|
||||
value=malloc_init_external(sizeof(uint32_t));
|
||||
value=malloc(sizeof(uint32_t));
|
||||
err = nvs_get_u32(nvs, key, (uint32_t *) value);
|
||||
} else if (type == NVS_TYPE_I64) {
|
||||
value=malloc_init_external(sizeof(int64_t));
|
||||
value=malloc(sizeof(int64_t));
|
||||
err = nvs_get_i64(nvs, key, (int64_t *) value);
|
||||
} else if (type == NVS_TYPE_U64) {
|
||||
value=malloc_init_external(sizeof(uint64_t));
|
||||
value=malloc(sizeof(uint64_t));
|
||||
err = nvs_get_u64(nvs, key, (uint64_t *) value);
|
||||
} else if (type == NVS_TYPE_STR) {
|
||||
size_t len=0;
|
||||
err = nvs_get_str(nvs, key, NULL, &len);
|
||||
if (err == ESP_OK) {
|
||||
value=malloc_init_external(len+1);
|
||||
value=malloc(len);
|
||||
err = nvs_get_str(nvs, key, value, &len);
|
||||
if(size){
|
||||
*size=len;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type == NVS_TYPE_BLOB) {
|
||||
size_t len;
|
||||
err = nvs_get_blob(nvs, key, NULL, &len);
|
||||
if (err == ESP_OK) {
|
||||
value=malloc_init_external(len+1);
|
||||
if(size){
|
||||
*size=len;
|
||||
}
|
||||
value=malloc(len+1);
|
||||
err = nvs_get_blob(nvs, key, value, &len);
|
||||
}
|
||||
}
|
||||
@@ -288,9 +244,6 @@ void * get_nvs_value_alloc_for_partition(const char * partition,const char * nam
|
||||
nvs_close(nvs);
|
||||
return value;
|
||||
}
|
||||
void * get_nvs_value_alloc(nvs_type_t type, const char *key) {
|
||||
return get_nvs_value_alloc_for_partition(settings_partition, current_namespace,type,key,NULL);
|
||||
}
|
||||
esp_err_t get_nvs_value(nvs_type_t type, const char *key, void*value, const uint8_t buf_size) {
|
||||
nvs_handle nvs;
|
||||
esp_err_t err;
|
||||
@@ -343,10 +296,11 @@ esp_err_t get_nvs_value(nvs_type_t type, const char *key, void*value, const uint
|
||||
nvs_close(nvs);
|
||||
return err;
|
||||
}
|
||||
esp_err_t erase_nvs_for_partition(const char * partition, const char * namespace,const char *key)
|
||||
esp_err_t erase_nvs(const char *key)
|
||||
{
|
||||
nvs_handle nvs;
|
||||
esp_err_t err = nvs_open_from_partition(partition,namespace, NVS_READWRITE, &nvs);
|
||||
|
||||
esp_err_t err = nvs_open(current_namespace, NVS_READWRITE, &nvs);
|
||||
if (err == ESP_OK) {
|
||||
err = nvs_erase_key(nvs, key);
|
||||
if (err == ESP_OK) {
|
||||
@@ -357,35 +311,7 @@ esp_err_t erase_nvs_for_partition(const char * partition, const char * namespace
|
||||
}
|
||||
nvs_close(nvs);
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Could not erase key %s from partition %s namespace %s : %s", key,partition,namespace, esp_err_to_name(err));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
esp_err_t erase_nvs(const char *key)
|
||||
{
|
||||
return erase_nvs_for_partition(NVS_DEFAULT_PART_NAME, current_namespace,key);
|
||||
}
|
||||
|
||||
esp_err_t erase_nvs_partition(const char * partition, const char * namespace){
|
||||
nvs_handle nvs;
|
||||
const char * step = "Opening";
|
||||
ESP_LOGD(TAG,"%s partition %s, namespace %s ",step,partition,namespace);
|
||||
esp_err_t err = nvs_open_from_partition(partition,namespace, NVS_READWRITE, &nvs);
|
||||
if (err == ESP_OK) {
|
||||
step = "Erasing";
|
||||
ESP_LOGD(TAG,"%s namespace %s ",step,partition);
|
||||
err = nvs_erase_all(nvs);
|
||||
if (err == ESP_OK) {
|
||||
step = "Committing";
|
||||
ESP_LOGD(TAG,"%s",step);
|
||||
err = nvs_commit(nvs);
|
||||
}
|
||||
}
|
||||
if(err !=ESP_OK){
|
||||
ESP_LOGE(TAG,"%s partition %s, name space %s : %s",step,partition,namespace,esp_err_to_name(err));
|
||||
}
|
||||
ESP_LOGD(TAG,"Closing %s ",namespace);
|
||||
nvs_close(nvs);
|
||||
return err;
|
||||
}
|
||||
@@ -13,15 +13,10 @@ esp_err_t store_nvs_value_len(nvs_type_t type, const char *key, void * data, siz
|
||||
esp_err_t store_nvs_value(nvs_type_t type, const char *key, void * data);
|
||||
esp_err_t get_nvs_value(nvs_type_t type, const char *key, void*value, const uint8_t buf_size);
|
||||
void * get_nvs_value_alloc(nvs_type_t type, const char *key);
|
||||
void * get_nvs_value_alloc_for_partition(const char * partition,const char * ns,nvs_type_t type, const char *key, size_t * size);
|
||||
esp_err_t erase_nvs_for_partition(const char * partition, const char * ns,const char *key);
|
||||
esp_err_t store_nvs_value_len_for_partition(const char * partition,const char * ns,nvs_type_t type, const char *key, const void * data,size_t data_len);
|
||||
esp_err_t erase_nvs(const char *key);
|
||||
void print_blob(const char *blob, size_t len);
|
||||
const char *type_to_str(nvs_type_t type);
|
||||
nvs_type_t str_to_type(const char *type);
|
||||
esp_err_t erase_nvs_partition(const char * partition, const char * ns);
|
||||
void erase_settings_partition();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,16 +1,6 @@
|
||||
# the JPEG library is in ROM but seems to fail randomly (PSRAM issue?)
|
||||
set(TJPGD tjpgd)
|
||||
idf_component_register(SRCS "led.c" "audio_controls.c" "buttons.c" "services.c" "monitor.c"INCLUDE_DIRS
|
||||
INCLUDE_DIRS . ../tools/
|
||||
|
||||
)
|
||||
|
||||
idf_component_register(SRC_DIRS . core core/ifaces fonts
|
||||
INCLUDE_DIRS . fonts core
|
||||
REQUIRES platform_config tools esp_common
|
||||
PRIV_REQUIRES services freertos driver ${TJPGD}
|
||||
EMBED_FILES note.jpg )
|
||||
|
||||
if (NOT TJPGD)
|
||||
add_compile_definitions(TJPGD_ROM)
|
||||
endif()
|
||||
|
||||
set_source_files_properties(display.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
-Wno-format-overflow )
|
||||
|
||||
@@ -1,347 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2018 Tara Keeling
|
||||
* 2020 Philippe G.
|
||||
* 2021 Mumpf and Harry1999
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include "gds.h"
|
||||
#include "gds_private.h"
|
||||
|
||||
#define SHADOW_BUFFER
|
||||
#define USE_IRAM
|
||||
#define PAGE_BLOCK 2048
|
||||
#define ENABLE_WRITE 0x2c
|
||||
#define MADCTL_MX 0x40
|
||||
#define TFT_RGB_BGR 0x08
|
||||
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
static char TAG[] = "ILI9341";
|
||||
|
||||
enum { ILI9341, ILI9341_24 }; //ILI9341_24 for future use...
|
||||
|
||||
struct PrivateSpace {
|
||||
uint8_t *iRAM, *Shadowbuffer;
|
||||
struct {
|
||||
uint16_t Height, Width;
|
||||
} Offset;
|
||||
uint8_t MADCtl, PageSize;
|
||||
uint8_t Model;
|
||||
};
|
||||
|
||||
// Functions are not declared to minimize # of lines
|
||||
|
||||
static void WriteByte( struct GDS_Device* Device, uint8_t Data ) {
|
||||
Device->WriteData( Device, &Data, 1 );
|
||||
}
|
||||
|
||||
static void SetColumnAddress( struct GDS_Device* Device, uint16_t Start, uint16_t End ) {
|
||||
uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16);
|
||||
Device->WriteCommand( Device, 0x2A );
|
||||
Device->WriteData( Device, (uint8_t*) &Addr, 4 );
|
||||
}
|
||||
|
||||
static void SetRowAddress( struct GDS_Device* Device, uint16_t Start, uint16_t End ) {
|
||||
uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16);
|
||||
Device->WriteCommand( Device, 0x2B );
|
||||
Device->WriteData( Device, (uint8_t*) &Addr, 4 );
|
||||
}
|
||||
|
||||
static void Update16( struct GDS_Device* Device ) {
|
||||
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
|
||||
|
||||
#ifdef SHADOW_BUFFER
|
||||
uint32_t *optr = (uint32_t*) Private->Shadowbuffer, *iptr = (uint32_t*) Device->Framebuffer;
|
||||
int FirstCol = Device->Width / 2, LastCol = 0, FirstRow = -1, LastRow = 0;
|
||||
|
||||
for (int r = 0; r < Device->Height; r++) {
|
||||
// look for change and update shadow (cheap optimization = width is always a multiple of 2)
|
||||
for (int c = 0; c < Device->Width / 2; c++, iptr++, optr++) {
|
||||
if (*optr != *iptr) {
|
||||
*optr = *iptr;
|
||||
if (c < FirstCol) FirstCol = c;
|
||||
if (c > LastCol) LastCol = c;
|
||||
if (FirstRow < 0) FirstRow = r;
|
||||
LastRow = r;
|
||||
}
|
||||
}
|
||||
|
||||
// wait for a large enough window - careful that window size might increase by more than a line at once !
|
||||
if (FirstRow < 0 || ((LastCol - FirstCol + 1) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue;
|
||||
|
||||
FirstCol *= 2;
|
||||
LastCol = LastCol * 2 + 1;
|
||||
SetRowAddress( Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height);
|
||||
SetColumnAddress( Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width );
|
||||
Device->WriteCommand( Device, ENABLE_WRITE );
|
||||
|
||||
int ChunkSize = (LastCol - FirstCol + 1) * 2;
|
||||
|
||||
// own use of IRAM has not proven to be much better than letting SPI do its copy
|
||||
if (Private->iRAM) {
|
||||
uint8_t *optr = Private->iRAM;
|
||||
for (int i = FirstRow; i <= LastRow; i++) {
|
||||
memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize);
|
||||
optr += ChunkSize;
|
||||
if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue;
|
||||
Device->WriteData(Device, Private->iRAM, optr - Private->iRAM);
|
||||
optr = Private->iRAM;
|
||||
}
|
||||
} else for (int i = FirstRow; i <= LastRow; i++) {
|
||||
Device->WriteData( Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize );
|
||||
}
|
||||
|
||||
FirstCol = Device->Width / 2; LastCol = 0;
|
||||
FirstRow = -1;
|
||||
}
|
||||
#else
|
||||
// always update by full lines
|
||||
SetColumnAddress( Device, Private->Offset.Width, Device->Width - 1);
|
||||
|
||||
for (int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) {
|
||||
int Height = min(Private->PageSize, Device->Height - r);
|
||||
|
||||
SetRowAddress( Device, Private->Offset.Height + r, Private->Offset.Height + r + Height - 1 );
|
||||
Device->WriteCommand(Device, ENABLE_WRITE);
|
||||
|
||||
if (Private->iRAM) {
|
||||
memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2 );
|
||||
Device->WriteData( Device, Private->iRAM, Height * Device->Width * 2 );
|
||||
} else {
|
||||
Device->WriteData( Device, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void Update24( struct GDS_Device* Device ) {
|
||||
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
|
||||
|
||||
#ifdef SHADOW_BUFFER
|
||||
uint16_t *optr = (uint16_t*) Private->Shadowbuffer, *iptr = (uint16_t*) Device->Framebuffer;
|
||||
int FirstCol = (Device->Width * 3) / 2, LastCol = 0, FirstRow = -1, LastRow = 0;
|
||||
|
||||
for (int r = 0; r < Device->Height; r++) {
|
||||
// look for change and update shadow (cheap optimization = width always / by 2)
|
||||
for (int c = 0; c < (Device->Width * 3) / 2; c++, optr++, iptr++) {
|
||||
if (*optr != *iptr) {
|
||||
*optr = *iptr;
|
||||
if (c < FirstCol) FirstCol = c;
|
||||
if (c > LastCol) LastCol = c;
|
||||
if (FirstRow < 0) FirstRow = r;
|
||||
LastRow = r;
|
||||
}
|
||||
}
|
||||
|
||||
// do we have enough to send (cols are divided by 3/2)
|
||||
if (FirstRow < 0 || ((((LastCol - FirstCol + 1) * 2 ) / 3) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue;
|
||||
|
||||
FirstCol = (FirstCol * 2) / 3;
|
||||
LastCol = (LastCol * 2 + 1 ) / 3;
|
||||
SetRowAddress( Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height);
|
||||
SetColumnAddress( Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width );
|
||||
Device->WriteCommand( Device, ENABLE_WRITE );
|
||||
|
||||
int ChunkSize = (LastCol - FirstCol + 1) * 3;
|
||||
|
||||
// own use of IRAM has not proven to be much better than letting SPI do its copy
|
||||
if (Private->iRAM) {
|
||||
uint8_t *optr = Private->iRAM;
|
||||
for (int i = FirstRow; i <= LastRow; i++) {
|
||||
memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize);
|
||||
optr += ChunkSize;
|
||||
if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue;
|
||||
Device->WriteData(Device, Private->iRAM, optr - Private->iRAM);
|
||||
optr = Private->iRAM;
|
||||
}
|
||||
} else for (int i = FirstRow; i <= LastRow; i++) {
|
||||
Device->WriteData( Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize );
|
||||
}
|
||||
|
||||
FirstCol = (Device->Width * 3) / 2; LastCol = 0;
|
||||
FirstRow = -1;
|
||||
}
|
||||
#else
|
||||
// always update by full lines
|
||||
SetColumnAddress( Device, Private->Offset.Width, Device->Width - 1);
|
||||
|
||||
for (int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) {
|
||||
int Height = min(Private->PageSize, Device->Height - r);
|
||||
|
||||
SetRowAddress( Device, Private->Offset.Height + r, Private->Offset.Height + r + Height - 1 );
|
||||
Device->WriteCommand(Device, ENABLE_WRITE);
|
||||
|
||||
if (Private->iRAM) {
|
||||
memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3 );
|
||||
Device->WriteData( Device, Private->iRAM, Height * Device->Width * 3 );
|
||||
} else {
|
||||
Device->WriteData( Device, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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)", 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 (Layout->HFlip) { //Flip Horizontal
|
||||
int a = Private->MADCtl;
|
||||
Private->MADCtl = (a ^ (1 << 7));
|
||||
}
|
||||
if (Layout->Rotate) { //Rotate 180 degr.
|
||||
int a = Private->MADCtl;
|
||||
a = (a ^ (1 << 7));
|
||||
Private->MADCtl = (a ^ (1 << 6));
|
||||
}
|
||||
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 (Layout->HFlip) { //Flip Horizontal
|
||||
int a = Private->MADCtl;
|
||||
Private->MADCtl = (a ^ (1 << 6));
|
||||
}
|
||||
if (Layout->Rotate) { //Rotate 180 degr.
|
||||
int a = Private->MADCtl;
|
||||
a = (a ^ (1 << 7));
|
||||
Private->MADCtl = (a ^ (1 << 6));
|
||||
}
|
||||
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 ...)
|
||||
memset(Private->Shadowbuffer, 0xAA, Device->FramebufferSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0x29 ); } //DISPON =0x29
|
||||
static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0x28 ); } //DISPOFF=0x28
|
||||
|
||||
static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
|
||||
Device->WriteCommand( Device, 0x51 );
|
||||
WriteByte( Device, Contrast );
|
||||
|
||||
Device->SetContrast = NULL;
|
||||
GDS_SetContrast( Device, Contrast );
|
||||
Device->SetContrast = SetContrast; // 0x00 value means the lowest brightness and 0xFF value means the highest brightness.
|
||||
}
|
||||
|
||||
static bool Init( struct GDS_Device* Device ) {
|
||||
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
|
||||
int Depth = (Device->Depth + 8 - 1) / 8;
|
||||
|
||||
Private->PageSize = min(8, PAGE_BLOCK / (Device->Width * Depth));
|
||||
|
||||
#ifdef SHADOW_BUFFER
|
||||
Private->Shadowbuffer = malloc( Device->FramebufferSize );
|
||||
memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize);
|
||||
#endif
|
||||
#ifdef USE_IRAM
|
||||
Private->iRAM = heap_caps_malloc( (Private->PageSize + 1) * Device->Width * Depth, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "ILI9341 with bit default-depth %u, page %u, iRAM %p", Device->Depth, Private->PageSize, Private->iRAM);
|
||||
|
||||
// Sleepout + Booster
|
||||
Device->WriteCommand( Device, 0x11 );
|
||||
|
||||
// set flip modes & contrast
|
||||
GDS_SetContrast( Device, 0x7f );
|
||||
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 );
|
||||
if (Private->Model == ILI9341_24) WriteByte( Device, Device->Depth == 24 ? 0x66 : 0x55 );
|
||||
else WriteByte( Device, Device->Depth == 24 ? 0x66 : 0x55 );
|
||||
|
||||
ESP_LOGI(TAG, "ILI9341_Init 312 device-depth %u, 0x66/0x55=0x%X", Device->Depth, Device->Depth == 24 ? 0x66 : 0x55);
|
||||
|
||||
// no Display Inversion (INVOFF=0x20 INVON=0x21)
|
||||
Device->WriteCommand( Device, 0x20 );
|
||||
|
||||
//Gamma Correction: Enable next two line and enabel one of the Test0x Section... or build you own 15 Parameter...
|
||||
Device->WriteCommand( Device, 0xF2 ); WriteByte( Device, 0x03 ); // 3Gamma Function: Disable = default (0x02), Enable (0x03)
|
||||
Device->WriteCommand( Device, 0x26 ); WriteByte( Device, 0x01 ); // Gamma curve selected (0x01, 0x02, 0x04, 0x08) - A maximum of 4 fixed gamma curves can be selected
|
||||
//Gamma Correction Test01
|
||||
Device->WriteCommand( Device, 0xE0 ); // Positive Gamma Correction (15 Parameter)
|
||||
WriteByte( Device, 0x0F ); WriteByte( Device, 0x31 ); WriteByte( Device, 0x2B ); WriteByte( Device, 0x0C ); WriteByte( Device, 0x0E );
|
||||
WriteByte( Device, 0x08 ); WriteByte( Device, 0x4E ); WriteByte( Device, 0xF1 ); WriteByte( Device, 0x37 ); WriteByte( Device, 0x07 );
|
||||
WriteByte( Device, 0x10 ); WriteByte( Device, 0x03 ); WriteByte( Device, 0x0E ); WriteByte( Device, 0x09 ); WriteByte( Device, 0x00 );
|
||||
Device->WriteCommand( Device, 0xE1 ); // Negative Gamma Correction (15 Parameter)
|
||||
WriteByte( Device, 0x00 ); WriteByte( Device, 0x0E ); WriteByte( Device, 0x14 ); WriteByte( Device, 0x03 ); WriteByte( Device, 0x11 );
|
||||
WriteByte( Device, 0x07 ); WriteByte( Device, 0x31 ); WriteByte( Device, 0xC1 ); WriteByte( Device, 0x48 ); WriteByte( Device, 0x08 );
|
||||
WriteByte( Device, 0x0F ); WriteByte( Device, 0x0C ); WriteByte( Device, 0x31 ); WriteByte( Device, 0x36 ); WriteByte( Device, 0x0F );
|
||||
|
||||
// gone with the wind
|
||||
Device->DisplayOn( Device );
|
||||
Device->Update( Device );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct GDS_Device ILI9341_X = {
|
||||
.DisplayOn = DisplayOn, .DisplayOff = DisplayOff,
|
||||
.SetLayout = SetLayout,
|
||||
.Update = Update16, .Init = Init,
|
||||
.Mode = GDS_RGB565, .Depth = 16,
|
||||
};
|
||||
|
||||
struct GDS_Device* ILI9341_Detect(char *Driver, struct GDS_Device* Device) {
|
||||
uint8_t Model;
|
||||
int Depth=16; // 16bit colordepth
|
||||
|
||||
if (strcasestr(Driver, "ILI9341")) Model = ILI9341;
|
||||
else if (strcasestr(Driver, "ILI9341_24")) Model = ILI9341_24; //for future use...
|
||||
else return NULL;
|
||||
|
||||
if (!Device) Device = calloc(1, sizeof(struct GDS_Device));
|
||||
|
||||
*Device = ILI9341_X;
|
||||
sscanf(Driver, "%*[^:]:%u", &Depth); // NVS-Parameter driver=ILI9341[:16|18]
|
||||
struct PrivateSpace* Private = (struct PrivateSpace*) Device->Private;
|
||||
Private->Model = Model;
|
||||
ESP_LOGI(TAG, "ILI9341_Detect 391 Driver= %s Depth=%d", Driver, Depth);
|
||||
|
||||
if (Depth == 18) {
|
||||
Device->Mode = GDS_RGB888;
|
||||
Device->Depth = 24;
|
||||
Device->Update = Update24;
|
||||
}
|
||||
|
||||
if (Model == ILI9341_24) Device->SetContrast = SetContrast;
|
||||
|
||||
return Device;
|
||||
}
|
||||
@@ -73,10 +73,9 @@ static void Update( struct GDS_Device* Device ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
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 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 DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); }
|
||||
@@ -87,10 +86,6 @@ static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
|
||||
Device->WriteCommand( Device, Contrast );
|
||||
}
|
||||
|
||||
static void SPIParams(int Speed, uint8_t *mode, uint16_t *CS_pre, uint8_t *CS_post) {
|
||||
*CS_post = Speed / (8*1000*1000);
|
||||
}
|
||||
|
||||
static bool Init( struct GDS_Device* Device ) {
|
||||
#ifdef SHADOW_BUFFER
|
||||
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
|
||||
@@ -125,8 +120,7 @@ static bool Init( struct GDS_Device* Device ) {
|
||||
Device->WriteCommand( Device, 0x40 + 0x00 );
|
||||
Device->SetContrast( Device, 0x7F );
|
||||
// set flip modes
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
Device->SetLayout( Device, false, false, false );
|
||||
// no Display Inversion
|
||||
Device->WriteCommand( Device, 0xA6 );
|
||||
// set Clocks
|
||||
@@ -146,7 +140,6 @@ static const struct GDS_Device SH1106 = {
|
||||
.SetLayout = SetLayout,
|
||||
.Update = Update, .Init = Init,
|
||||
.Depth = 1,
|
||||
.SPIParams = SPIParams,
|
||||
#if !defined SHADOW_BUFFER && defined USE_IRAM
|
||||
.Alloc = GDS_ALLOC_IRAM_SPI;
|
||||
#endif
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2018 Tara Keeling
|
||||
* 2020 Philippe G.
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include "gds.h"
|
||||
#include "gds_private.h"
|
||||
|
||||
#define SHADOW_BUFFER
|
||||
#define PAGE_BLOCK 1024
|
||||
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
static char TAG[] = "SH1122";
|
||||
|
||||
struct PrivateSpace {
|
||||
uint8_t *iRAM, *Shadowbuffer;
|
||||
uint8_t PageSize;
|
||||
};
|
||||
|
||||
// Functions are not declared to minimize # of lines
|
||||
|
||||
static void SetColumnAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) {
|
||||
Device->WriteCommand( Device, 0x10 | (Start >> 4) );
|
||||
Device->WriteCommand( Device, 0x00 | (Start & 0x0f) );
|
||||
}
|
||||
|
||||
static void SetRowAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) {
|
||||
Device->WriteCommand( Device, 0xB0 );
|
||||
Device->WriteCommand( Device, Start );
|
||||
}
|
||||
|
||||
static void Update( struct GDS_Device* Device ) {
|
||||
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
|
||||
|
||||
// RAM is by columns of 4 pixels ...
|
||||
SetColumnAddress( Device, 0, Device->Width / 4 - 1);
|
||||
|
||||
#ifdef SHADOW_BUFFER
|
||||
uint16_t *optr = (uint16_t*) Private->Shadowbuffer, *iptr = (uint16_t*) Device->Framebuffer;
|
||||
bool dirty = false;
|
||||
|
||||
for (int r = 0, page = 0; r < Device->Height; r++) {
|
||||
// look for change and update shadow (cheap optimization = width always / by 2)
|
||||
for (int c = Device->Width / 2 / 2; --c >= 0;) {
|
||||
if (*optr != *iptr) {
|
||||
dirty = true;
|
||||
*optr = *iptr;
|
||||
}
|
||||
iptr++; optr++;
|
||||
}
|
||||
|
||||
// one line done, check for page boundary
|
||||
if (++page == Private->PageSize) {
|
||||
if (dirty) {
|
||||
SetRowAddress( Device, r - page + 1, r );
|
||||
if (Private->iRAM) {
|
||||
memcpy(Private->iRAM, Private->Shadowbuffer + (r - page + 1) * Device->Width / 2, page * Device->Width / 2 );
|
||||
Device->WriteData( Device, Private->iRAM, Device->Width * page / 2 );
|
||||
} else {
|
||||
Device->WriteData( Device, Private->Shadowbuffer + (r - page + 1) * Device->Width / 2, page * Device->Width / 2);
|
||||
}
|
||||
dirty = false;
|
||||
}
|
||||
page = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
SetRowAddress( Device, 0, Device->Height - 1 );
|
||||
for (int r = 0; r < Device->Height; r += Private->PageSize) {
|
||||
if (Private->iRAM) {
|
||||
memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 );
|
||||
Device->WriteData( Device, Private->iRAM, Private->PageSize * Device->Width / 2 );
|
||||
} else {
|
||||
Device->WriteData( Device, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
|
||||
if (Layout->HFlip) {
|
||||
Device->WriteCommand( Device, 0x40 + 0x20 );
|
||||
Device->WriteCommand( Device, 0xA1 );
|
||||
} else {
|
||||
Device->WriteCommand( Device, 0x40 + 0x00 );
|
||||
Device->WriteCommand( Device, 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 ); }
|
||||
static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAE ); }
|
||||
|
||||
static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
|
||||
Device->WriteCommand( Device, 0x81 );
|
||||
Device->WriteCommand( Device, Contrast );
|
||||
}
|
||||
|
||||
static bool Init( struct GDS_Device* Device ) {
|
||||
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
|
||||
|
||||
// find a page size that is not too small is an integer of height
|
||||
Private->PageSize = min(8, PAGE_BLOCK / (Device->Width / 2));
|
||||
while (Private->PageSize && Device->Height != (Device->Height / Private->PageSize) * Private->PageSize) Private->PageSize--;
|
||||
|
||||
#ifdef SHADOW_BUFFER
|
||||
Private->Shadowbuffer = malloc( Device->FramebufferSize );
|
||||
memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize);
|
||||
#endif
|
||||
|
||||
// only use iRAM for SPI
|
||||
if (Device->IF == GDS_IF_SPI) {
|
||||
Private->iRAM = heap_caps_malloc( Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "SH1122 page %u, iRAM %p", Private->PageSize, Private->iRAM);
|
||||
|
||||
// need to be off and disable display RAM
|
||||
Device->DisplayOff( Device );
|
||||
Device->WriteCommand( Device, 0xA5 );
|
||||
|
||||
// Display Offset
|
||||
Device->WriteCommand( Device, 0xD3 );
|
||||
Device->WriteCommand( Device, 0 );
|
||||
|
||||
// set flip modes
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
|
||||
// set Clocks => check value
|
||||
Device->WriteCommand( Device, 0xD5 );
|
||||
Device->WriteCommand( Device, ( 0x04 << 4 ) | 0x00 );
|
||||
|
||||
// MUX Ratio => fixed
|
||||
Device->WriteCommand( Device, 0xA8 );
|
||||
Device->WriteCommand( Device, Device->Height - 1);
|
||||
|
||||
// no Display Inversion
|
||||
Device->WriteCommand( Device, 0xA6 );
|
||||
|
||||
// gone with the wind
|
||||
Device->WriteCommand( Device, 0xA4 );
|
||||
Device->DisplayOn( Device );
|
||||
Device->Update( Device );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct GDS_Device SH1122 = {
|
||||
.DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast,
|
||||
.SetLayout = SetLayout,
|
||||
.Update = Update, .Init = Init,
|
||||
.Mode = GDS_GRAYSCALE, .Depth = 4,
|
||||
.HighNibble = true,
|
||||
};
|
||||
|
||||
struct GDS_Device* SH1122_Detect(char *Driver, struct GDS_Device* Device) {
|
||||
if (!strcasestr(Driver, "SH1122")) return NULL;
|
||||
|
||||
if (!Device) Device = calloc(1, sizeof(struct GDS_Device));
|
||||
*Device = SH1122;
|
||||
|
||||
return Device;
|
||||
}
|
||||
@@ -85,10 +85,9 @@ static void Update( struct GDS_Device* Device ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
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 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 DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); }
|
||||
@@ -133,8 +132,7 @@ static bool Init( struct GDS_Device* Device ) {
|
||||
Device->WriteCommand( Device, 0x40 + 0x00 );
|
||||
Device->SetContrast( Device, 0x7F );
|
||||
// set flip modes
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
Device->SetLayout( Device, false, false, false);
|
||||
// no Display Inversion
|
||||
Device->WriteCommand( Device, 0xA6 );
|
||||
// set Clocks
|
||||
|
||||
@@ -71,8 +71,8 @@ static void Update( struct GDS_Device* Device ) {
|
||||
if (dirty) {
|
||||
uint16_t *optr = (uint16_t*) Private->iRAM, *iptr = (uint16_t*) (Private->Shadowbuffer + (r - page + 1) * Device->Width / 2);
|
||||
SetRowAddress( Device, r - page + 1, r );
|
||||
// need byte swapping
|
||||
for (int i = page * Device->Width / 2 / 2; --i >= 0; iptr++) *optr++ = (*iptr >> 8) | (*iptr << 8);
|
||||
//memcpy(Private->iRAM, Private->Shadowbuffer + (r - page + 1) * Device->Width / 2, page * Device->Width / 2 );
|
||||
Device->WriteCommand( Device, 0x5c );
|
||||
Device->WriteData( Device, Private->iRAM, Device->Width * page / 2 );
|
||||
dirty = false;
|
||||
@@ -84,22 +84,25 @@ static void Update( struct GDS_Device* Device ) {
|
||||
for (int r = 0; r < Device->Height; r += Private->PageSize) {
|
||||
SetRowAddress( Device, r, r + Private->PageSize - 1 );
|
||||
Device->WriteCommand( Device, 0x5c );
|
||||
// need byte swapping
|
||||
uint16_t *optr = (uint16_t*) Private->iRAM, *iptr = (uint16_t*) (Device->Framebuffer + r * Device->Width / 2);
|
||||
for (int i = Private->PageSize * Device->Width / 2 / 2; --i >= 0; iptr++) *optr++ = (*iptr >> 8) | (*iptr << 8);
|
||||
Device->WriteData( Device, Private->iRAM, Private->PageSize * Device->Width / 2 );
|
||||
if (Private->iRAM) {
|
||||
uint16_t *optr = (uint16_t*) Private->iRAM, *iptr = (uint16_t*) (Device->Framebuffer + r * Device->Width / 2);
|
||||
for (int i = Private->PageSize * Device->Width / 2 / 2; --i >= 0; iptr++) *optr++ = (*iptr >> 8) | (*iptr << 8);
|
||||
//memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 );
|
||||
Device->WriteData( Device, Private->iRAM, Private->PageSize * Device->Width / 2 );
|
||||
} else {
|
||||
Device->WriteData( Device, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
|
||||
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) {
|
||||
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
|
||||
Private->ReMap = Layout->HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1));
|
||||
Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
|
||||
Private->ReMap = HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1));
|
||||
Private->ReMap = 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 ); }
|
||||
@@ -142,31 +145,25 @@ static bool Init( struct GDS_Device* Device ) {
|
||||
|
||||
// set flip modes
|
||||
Private->ReMap = 0;
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
|
||||
// set Display Enhancement
|
||||
Device->WriteCommand( Device, 0xB4 );
|
||||
WriteDataByte( Device, 0xA0 );
|
||||
WriteDataByte( Device, 0xB5 );
|
||||
Device->SetLayout( Device, false, false, false);
|
||||
|
||||
// set Clocks
|
||||
Device->WriteCommand( Device, 0xB3 );
|
||||
WriteDataByte( Device, 0xB2 ); // 0x91 seems to be common but is too slow for 5.5'
|
||||
WriteDataByte( Device, 0x91 );
|
||||
|
||||
// set MUX
|
||||
Device->WriteCommand( Device, 0xCA );
|
||||
WriteDataByte( Device, Device->Height - 1 );
|
||||
|
||||
// phase 1 & 2 period
|
||||
// phase 1 & 2 period (needed?)
|
||||
Device->WriteCommand( Device, 0xB1 );
|
||||
WriteDataByte( Device, 0xE3 ); // 0xE2 was recommended
|
||||
WriteDataByte( Device, 0xE2 );
|
||||
|
||||
// set pre-charge V
|
||||
// set pre-charge V (needed?°)
|
||||
Device->WriteCommand( Device, 0xBB );
|
||||
WriteDataByte( Device, 0x0F); // 0x1F causes column interferences
|
||||
WriteDataByte( Device, 0x1F );
|
||||
|
||||
// set COM deselect voltage
|
||||
// set COM deselect voltage (needed?)
|
||||
Device->WriteCommand( Device, 0xBE );
|
||||
WriteDataByte( Device, 0x07 );
|
||||
|
||||
|
||||
@@ -222,18 +222,17 @@ static void DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, i
|
||||
}
|
||||
}
|
||||
|
||||
static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
|
||||
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) {
|
||||
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
|
||||
if (Private->Model == SSD1326) {
|
||||
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));
|
||||
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));
|
||||
} else {
|
||||
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));
|
||||
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));
|
||||
}
|
||||
Device->WriteCommand( Device, 0xA0 );
|
||||
Device->WriteCommand( Device, Private->ReMap );
|
||||
Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA4 );
|
||||
}
|
||||
|
||||
static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); }
|
||||
@@ -289,8 +288,7 @@ static bool Init( struct GDS_Device* Device ) {
|
||||
Device->WriteCommand( Device, 0x00 );
|
||||
Device->SetContrast( Device, 0x7F );
|
||||
// set flip modes
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
Device->SetLayout( Device, false, false, false );
|
||||
// no Display Inversion
|
||||
Device->WriteCommand( Device, 0xA6 );
|
||||
// set Clocks
|
||||
|
||||
@@ -181,13 +181,12 @@ static void Update24( struct GDS_Device* Device ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
|
||||
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) {
|
||||
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
|
||||
Private->ReMap = Layout->HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1));
|
||||
Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
|
||||
Private->ReMap = HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1));
|
||||
Private->ReMap = 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 ); }
|
||||
@@ -240,8 +239,7 @@ static bool Init( struct GDS_Device* Device ) {
|
||||
|
||||
// set flip modes & contrast
|
||||
Device->SetContrast( Device, 0x7F );
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
Device->SetLayout( Device, false, false, false );
|
||||
|
||||
// set Adressing Mode Horizontal
|
||||
Private->ReMap |= (0 << 2);
|
||||
|
||||
@@ -243,7 +243,7 @@ struct GDS_Device* SSD1675_Detect(char *Driver, struct GDS_Device* Device) {
|
||||
char *p;
|
||||
struct PrivateSpace* Private = (struct PrivateSpace*) Device->Private;
|
||||
Private->ReadyPin = -1;
|
||||
if ((p = strcasestr(Driver, "ready")) && (p = strchr(p, '='))) Private->ReadyPin = atoi(p + 1);
|
||||
if ((p = strcasestr(Driver, "ready")) != NULL) Private->ReadyPin = atoi(strchr(p, '=') + 1);
|
||||
|
||||
ESP_LOGI(TAG, "SSD1675 driver with ready GPIO %d", Private->ReadyPin);
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ static void Update16( struct GDS_Device* Device ) {
|
||||
for (int i = FirstRow; i <= LastRow; i++) {
|
||||
memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize);
|
||||
optr += ChunkSize;
|
||||
if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue;
|
||||
if (optr - Private->iRAM < PAGE_BLOCK && i < LastRow) continue;
|
||||
Device->WriteData(Device, Private->iRAM, optr - Private->iRAM);
|
||||
optr = Private->iRAM;
|
||||
}
|
||||
@@ -157,7 +157,7 @@ static void Update24( struct GDS_Device* Device ) {
|
||||
for (int i = FirstRow; i <= LastRow; i++) {
|
||||
memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize);
|
||||
optr += ChunkSize;
|
||||
if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue;
|
||||
if (optr - Private->iRAM < PAGE_BLOCK && i < LastRow) continue;
|
||||
Device->WriteData(Device, Private->iRAM, optr - Private->iRAM);
|
||||
optr = Private->iRAM;
|
||||
}
|
||||
@@ -188,24 +188,20 @@ static void Update24( struct GDS_Device* Device ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) {
|
||||
static void SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) {
|
||||
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
|
||||
|
||||
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 );
|
||||
} else {
|
||||
Device->WriteCommand( Device, Layout->Invert ? 0x21 : 0x20 );
|
||||
}
|
||||
|
||||
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));
|
||||
Private->MADCtl = Layout->ColorSwap ? (Private->MADCtl & ~(1 << 3)) : (Private->MADCtl | (1 << 3));
|
||||
|
||||
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));
|
||||
|
||||
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,26 +235,28 @@ static bool Init( struct GDS_Device* Device ) {
|
||||
Private->iRAM = heap_caps_malloc( (Private->PageSize + 1) * Device->Width * Depth, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "ST77xx with bit depth %u, offsets %hu:%hu, page %u, iRAM %p", Device->Depth, Private->Offset.Height, Private->Offset.Width, Private->PageSize, Private->iRAM);
|
||||
ESP_LOGI(TAG, "ST77xx with bit depth %u, page %u, iRAM %p", Device->Depth, Private->PageSize, Private->iRAM);
|
||||
|
||||
// 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 );
|
||||
struct GDS_Layout Layout = { };
|
||||
Device->SetLayout( Device, &Layout );
|
||||
Device->SetLayout( Device, false, false, false );
|
||||
|
||||
// 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 );
|
||||
@@ -285,12 +283,8 @@ struct GDS_Device* ST77xx_Detect(char *Driver, struct GDS_Device* Device) {
|
||||
|
||||
*Device = ST77xx;
|
||||
sscanf(Driver, "%*[^:]:%u", &Depth);
|
||||
|
||||
struct PrivateSpace* Private = (struct PrivateSpace*) Device->Private;
|
||||
Private->Model = Model;
|
||||
|
||||
sscanf(Driver, "%*[^:]%*[^x]%*[^=]=%hu", &Private->Offset.Height);
|
||||
sscanf(Driver, "%*[^:]%*[^y]%*[^=]=%hu", &Private->Offset.Width);
|
||||
|
||||
if (Depth == 18) {
|
||||
Device->Mode = GDS_RGB666;
|
||||
|
||||
@@ -19,12 +19,6 @@
|
||||
#include "gds.h"
|
||||
#include "gds_private.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
#define LEDC_SPEED_MODE LEDC_LOW_SPEED_MODE
|
||||
#else
|
||||
#define LEDC_SPEED_MODE LEDC_HIGH_SPEED_MODE
|
||||
#endif
|
||||
|
||||
static struct GDS_Device Display;
|
||||
static struct GDS_BacklightPWM PWMConfig;
|
||||
|
||||
@@ -40,7 +34,7 @@ struct GDS_Device* GDS_AutoDetect( char *Driver, GDS_DetectFunc* DetectFunc[], s
|
||||
ledc_timer_config_t PWMTimer = {
|
||||
.duty_resolution = LEDC_TIMER_13_BIT,
|
||||
.freq_hz = 5000,
|
||||
.speed_mode = LEDC_SPEED_MODE,
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
.timer_num = PWMConfig.Timer,
|
||||
};
|
||||
ledc_timer_config(&PWMTimer);
|
||||
@@ -109,7 +103,7 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
|
||||
int c = x1;
|
||||
// for a row that is not on a boundary, no optimization possible
|
||||
while (r & 0x07 && r <= y2) {
|
||||
for (c = x1; c <= x2; c++) Device->DrawPixelFast( Device, c, r, Color );
|
||||
for (c = x1; c <= x2; c++) DrawPixelFast( Device, c, r, Color );
|
||||
r++;
|
||||
}
|
||||
// go fast if we have more than 8 lines to write
|
||||
@@ -117,7 +111,7 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
|
||||
memset(optr + Width * r + x1, _Color, x2 - x1 + 1);
|
||||
r += 8;
|
||||
} else while (r <= y2) {
|
||||
for (c = x1; c <= x2; c++) Device->DrawPixelFast( Device, c, r, Color );
|
||||
for (c = x1; c <= x2; c++) DrawPixelFast( Device, c, r, Color );
|
||||
r++;
|
||||
}
|
||||
}
|
||||
@@ -133,10 +127,10 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
|
||||
// try to do byte processing as much as possible
|
||||
for (int r = y1; r <= y2; r++) {
|
||||
int c = x1;
|
||||
if (c & 0x01) Device->DrawPixelFast( Device, c++, r, Color);
|
||||
if (c & 0x01) DrawPixelFast( Device, c++, r, Color);
|
||||
int chunk = (x2 - c + 1) >> 1;
|
||||
memset(optr + ((r * Width + c) >> 1), _Color, chunk);
|
||||
if (c + chunk <= x2) Device->DrawPixelFast( Device, x2, r, Color);
|
||||
if (c + chunk <= x2) DrawPixelFast( Device, x2, r, Color);
|
||||
}
|
||||
}
|
||||
} else if (Device->Depth == 8) {
|
||||
@@ -148,7 +142,7 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
|
||||
} else {
|
||||
for (int y = y1; y <= y2; y++) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
Device->DrawPixelFast( Device, x, y, Color);
|
||||
DrawPixelFast( Device, x, y, Color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,76 +165,10 @@ bool GDS_Reset( struct GDS_Device* Device ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR DrawPixel1Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint32_t YBit = ( Y & 0x07 );
|
||||
uint8_t* FBOffset;
|
||||
|
||||
/*
|
||||
* We only need to modify the Y coordinate since the pitch
|
||||
* of the screen is the same as the width.
|
||||
* Dividing Y by 8 gives us which row the pixel is in but not
|
||||
* the bit position.
|
||||
*/
|
||||
Y>>= 3;
|
||||
|
||||
FBOffset = Device->Framebuffer + ( ( Y * Device->Width ) + X );
|
||||
|
||||
if ( Color == GDS_COLOR_XOR ) {
|
||||
*FBOffset ^= BIT( YBit );
|
||||
} else {
|
||||
*FBOffset = ( Color == GDS_COLOR_BLACK ) ? *FBOffset & ~BIT( YBit ) : *FBOffset | BIT( YBit );
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR DrawPixel4Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint8_t* FBOffset = Device->Framebuffer + ( (Y * Device->Width >> 1) + (X >> 1));
|
||||
*FBOffset = X & 0x01 ? (*FBOffset & 0x0f) | ((Color & 0x0f) << 4) : ((*FBOffset & 0xf0) | (Color & 0x0f));
|
||||
}
|
||||
|
||||
static void IRAM_ATTR DrawPixel4FastHigh( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint8_t* FBOffset = Device->Framebuffer + ( (Y * Device->Width >> 1) + (X >> 1));
|
||||
*FBOffset = X & 0x01 ? ((*FBOffset & 0xf0) | (Color & 0x0f)) : (*FBOffset & 0x0f) | ((Color & 0x0f) << 4);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR DrawPixel8Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
Device->Framebuffer[Y * Device->Width + X] = Color;
|
||||
}
|
||||
|
||||
// assumes that Color is 16 bits R..RG..GB..B from MSB to LSB and FB wants 1st serialized byte to start with R
|
||||
static void IRAM_ATTR DrawPixel16Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint16_t* FBOffset = (uint16_t*) Device->Framebuffer + Y * Device->Width + X;
|
||||
*FBOffset = __builtin_bswap16(Color);
|
||||
}
|
||||
|
||||
// assumes that Color is 18 bits RGB from MSB to LSB RRRRRRGGGGGGBBBBBB, so byte[0] is B
|
||||
// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = xxRRRRRR xxGGGGGG xxBBBBBB
|
||||
static void IRAM_ATTR DrawPixel18Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3;
|
||||
*FBOffset++ = Color >> 12; *FBOffset++ = (Color >> 6) & 0x3f; *FBOffset = Color & 0x3f;
|
||||
}
|
||||
|
||||
// assumes that Color is 24 bits RGB from MSB to LSB RRRRRRRRGGGGGGGGBBBBBBBB, so byte[0] is B
|
||||
// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = RRRRRRRR GGGGGGGG BBBBBBBB
|
||||
static void IRAM_ATTR DrawPixel24Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3;
|
||||
*FBOffset++ = Color >> 16; *FBOffset++ = Color >> 8; *FBOffset = Color;
|
||||
}
|
||||
|
||||
bool GDS_Init( struct GDS_Device* Device ) {
|
||||
|
||||
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);
|
||||
|
||||
// set the proper DrawPixel function if not already set by driver
|
||||
if (!Device->DrawPixelFast) {
|
||||
if (Device->Depth == 1) Device->DrawPixelFast = DrawPixel1Fast;
|
||||
else if (Device->Depth == 4 && Device->HighNibble) Device->DrawPixelFast = DrawPixel4FastHigh;
|
||||
else if (Device->Depth == 4) Device->DrawPixelFast = DrawPixel4Fast;
|
||||
else if (Device->Depth == 8) Device->DrawPixelFast = DrawPixel8Fast;
|
||||
else if (Device->Depth == 16) Device->DrawPixelFast = DrawPixel16Fast;
|
||||
else if (Device->Depth == 24 && Device->Mode == GDS_RGB666) Device->DrawPixelFast = DrawPixel18Fast;
|
||||
else if (Device->Depth == 24 && Device->Mode == GDS_RGB888) Device->DrawPixelFast = DrawPixel24Fast;
|
||||
}
|
||||
|
||||
// allocate FB unless explicitely asked not to
|
||||
if (!(Device->Alloc & GDS_ALLOC_NONE)) {
|
||||
@@ -260,7 +188,7 @@ bool GDS_Init( struct GDS_Device* Device ) {
|
||||
.channel = Device->Backlight.Channel,
|
||||
.duty = Device->Backlight.PWM,
|
||||
.gpio_num = Device->Backlight.Pin,
|
||||
.speed_mode = LEDC_SPEED_MODE,
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
.hpoint = 0,
|
||||
.timer_sel = PWMConfig.Timer,
|
||||
};
|
||||
@@ -303,17 +231,16 @@ void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
|
||||
if (Device->SetContrast) Device->SetContrast( Device, Contrast );
|
||||
else if (Device->Backlight.Pin >= 0) {
|
||||
Device->Backlight.PWM = PWMConfig.Max * powf(Contrast / 255.0, 3);
|
||||
ledc_set_duty( LEDC_SPEED_MODE, Device->Backlight.Channel, Device->Backlight.PWM );
|
||||
ledc_update_duty( LEDC_SPEED_MODE, Device->Backlight.Channel );
|
||||
ledc_set_duty( LEDC_HIGH_SPEED_MODE, Device->Backlight.Channel, Device->Backlight.PWM );
|
||||
ledc_update_duty( LEDC_HIGH_SPEED_MODE, Device->Backlight.Channel );
|
||||
}
|
||||
}
|
||||
|
||||
void GDS_SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { if (Device->SetLayout) Device->SetLayout( Device, Layout ); }
|
||||
|
||||
void GDS_SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate ) { if (Device->SetLayout) Device->SetLayout( Device, HFlip, VFlip, Rotate ); }
|
||||
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; }
|
||||
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; }
|
||||
int GDS_GetWidth( struct GDS_Device* Device ) { return Device->Width; }
|
||||
int GDS_GetHeight( struct GDS_Device* Device ) { return Device->Height; }
|
||||
int GDS_GetDepth( struct GDS_Device* Device ) { return Device->Depth; }
|
||||
int GDS_GetMode( struct GDS_Device* Device ) { return Device->Mode; }
|
||||
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 ); }
|
||||
@@ -26,12 +26,6 @@ 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);
|
||||
|
||||
@@ -41,10 +35,9 @@ 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, struct GDS_Layout* Layout);
|
||||
void GDS_SetLayout( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate );
|
||||
void GDS_SetDirty( struct GDS_Device* Device );
|
||||
int GDS_GetWidth( struct GDS_Device* Device );
|
||||
void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth );
|
||||
int GDS_GetHeight( struct GDS_Device* Device );
|
||||
int GDS_GetDepth( struct GDS_Device* Device );
|
||||
int GDS_GetMode( struct GDS_Device* Device );
|
||||
|
||||
@@ -11,7 +11,7 @@ bool GDS_I2CInit( int PortNumber, int SDA, int SCL, int speed );
|
||||
bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int I2CAddress, int RSTPin, int BacklightPin );
|
||||
|
||||
bool GDS_SPIInit( int SPI, int DC );
|
||||
bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int Speed, int BacklightPin, int Mode );
|
||||
bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int Speed, int BacklightPin );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ __attribute__( ( always_inline ) ) static inline void SwapInt( int* a, int* b )
|
||||
}
|
||||
|
||||
void IRAM_ATTR GDS_DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
Device->DrawPixelFast( Device, X, Y, Color );
|
||||
DrawPixelFast( Device, X, Y, Color );
|
||||
}
|
||||
|
||||
void IRAM_ATTR GDS_DrawPixel( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
@@ -63,7 +63,7 @@ void GDS_DrawHLine( struct GDS_Device* Device, int x, int y, int Width, int Colo
|
||||
if (y < 0) y = 0;
|
||||
else if (y >= Device->Height) y = Device->Height - 1;
|
||||
|
||||
for ( ; x < XEnd; x++ ) Device->DrawPixelFast( Device, x, y, Color );
|
||||
for ( ; x < XEnd; x++ ) DrawPixelFast( Device, x, y, Color );
|
||||
}
|
||||
|
||||
void GDS_DrawVLine( struct GDS_Device* Device, int x, int y, int Height, int Color ) {
|
||||
@@ -97,7 +97,7 @@ static inline void DrawWideLine( struct GDS_Device* Device, int x0, int y0, int
|
||||
|
||||
for ( ; x < x1; x++ ) {
|
||||
if ( IsPixelVisible( Device, x, y ) == true ) {
|
||||
Device->DrawPixelFast( Device, x, y, Color );
|
||||
DrawPixelFast( Device, x, y, Color );
|
||||
}
|
||||
|
||||
if ( Error > 0 ) {
|
||||
@@ -126,7 +126,7 @@ static inline void DrawTallLine( struct GDS_Device* Device, int x0, int y0, int
|
||||
|
||||
for ( ; y < y1; y++ ) {
|
||||
if ( IsPixelVisible( Device, x, y ) == true ) {
|
||||
Device->DrawPixelFast( Device, x, y, Color );
|
||||
DrawPixelFast( Device, x, y, Color );
|
||||
}
|
||||
|
||||
if ( Error > 0 ) {
|
||||
@@ -213,65 +213,37 @@ void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int
|
||||
iptr += Height;
|
||||
}
|
||||
}
|
||||
} else if (Device->Depth == 4) {
|
||||
} else if (Device->Depth == 4) {
|
||||
uint8_t *optr = Device->Framebuffer;
|
||||
int LineLen = Device->Width >> 1;
|
||||
|
||||
Height >>= 3;
|
||||
Color &= 0x0f;
|
||||
|
||||
if (Device->HighNibble) {
|
||||
for (int i = Width * Height, r = 0, c = 0; --i >= 0;) {
|
||||
uint8_t Byte = BitReverseTable256[*Data++];
|
||||
// we need to linearize code to let compiler better optimize
|
||||
if (c & 0x01) {
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen;
|
||||
} else {
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen;
|
||||
}
|
||||
// end of a column, move to next one
|
||||
if (++r == Height) { c++; r = 0; optr = Device->Framebuffer + (c >> 1); }
|
||||
}
|
||||
} else {
|
||||
for (int i = Width * Height, r = 0, c = 0; --i >= 0;) {
|
||||
uint8_t Byte = BitReverseTable256[*Data++];
|
||||
// we need to linearize code to let compiler better optimize
|
||||
if (c & 0x01) {
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen;
|
||||
} else {
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen;
|
||||
}
|
||||
// end of a column, move to next one
|
||||
if (++r == Height) { c++; r = 0; optr = Device->Framebuffer + (c >> 1); }
|
||||
}
|
||||
|
||||
for (int i = Width * Height, r = 0, c = 0; --i >= 0;) {
|
||||
uint8_t Byte = BitReverseTable256[*Data++];
|
||||
// we need to linearize code to let compiler better optimize
|
||||
if (c & 0x01) {
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen;
|
||||
} else {
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1;
|
||||
*optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen;
|
||||
}
|
||||
// end of a column, move to next one
|
||||
if (++r == Height) { c++; r = 0; optr = Device->Framebuffer + (c >> 1); }
|
||||
}
|
||||
} else if (Device->Depth == 8) {
|
||||
uint8_t *optr = Device->Framebuffer;
|
||||
@@ -348,14 +320,14 @@ void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int
|
||||
// don't know bitdepth, use brute-force solution
|
||||
for (int i = Width * Height, r = 0, c = 0; --i >= 0;) {
|
||||
uint8_t Byte = *Data++;
|
||||
Device->DrawPixelFast( Device, c, (r << 3) + 7, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
Device->DrawPixelFast( Device, c, (r << 3) + 6, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
Device->DrawPixelFast( Device, c, (r << 3) + 5, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
Device->DrawPixelFast( Device, c, (r << 3) + 4, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
Device->DrawPixelFast( Device, c, (r << 3) + 3, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
Device->DrawPixelFast( Device, c, (r << 3) + 2, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
Device->DrawPixelFast( Device, c, (r << 3) + 1, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
Device->DrawPixelFast( Device, c, (r << 3) + 0, (Byte & 0x01) * Color );
|
||||
DrawPixelFast( Device, c, (r << 3) + 7, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
DrawPixelFast( Device, c, (r << 3) + 6, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
DrawPixelFast( Device, c, (r << 3) + 5, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
DrawPixelFast( Device, c, (r << 3) + 4, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
DrawPixelFast( Device, c, (r << 3) + 3, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
DrawPixelFast( Device, c, (r << 3) + 2, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
DrawPixelFast( Device, c, (r << 3) + 1, (Byte & 0x01) * Color ); Byte >>= 1;
|
||||
DrawPixelFast( Device, c, (r << 3) + 0, (Byte & 0x01) * Color );
|
||||
if (++r == Height) { c++; r = 0; }
|
||||
}
|
||||
/* for better understanding, here is the mundane version
|
||||
|
||||
@@ -73,13 +73,13 @@ void GDS_FontDrawChar( struct GDS_Device* Device, char Character, int x, int y,
|
||||
CharStartY+= OffsetY;
|
||||
|
||||
/* Do not attempt to draw if this character is entirely offscreen */
|
||||
if ( CharEndX < 0 || CharStartX >= Device->TextWidth || CharEndY < 0 || CharStartY >= Device->Height ) {
|
||||
if ( CharEndX < 0 || CharStartX >= Device->Width || CharEndY < 0 || CharStartY >= Device->Height ) {
|
||||
ClipDebug( x, y );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do not attempt to draw past the end of the screen */
|
||||
CharEndX = ( CharEndX >= Device->TextWidth ) ? Device->TextWidth - 1 : CharEndX;
|
||||
CharEndX = ( CharEndX >= Device->Width ) ? Device->Width - 1 : CharEndX;
|
||||
CharEndY = ( CharEndY >= Device->Height ) ? Device->Height - 1 : CharEndY;
|
||||
Device->Dirty = true;
|
||||
|
||||
@@ -98,14 +98,12 @@ void GDS_FontDrawChar( struct GDS_Device* Device, char Character, int x, int y,
|
||||
}
|
||||
}
|
||||
|
||||
const struct GDS_FontDef* GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font ) {
|
||||
const struct GDS_FontDef* OldFont = Display->Font;
|
||||
|
||||
bool GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font ) {
|
||||
Display->FontForceProportional = false;
|
||||
Display->FontForceMonospace = false;
|
||||
Display->Font = Font;
|
||||
|
||||
return OldFont;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GDS_FontForceProportional( struct GDS_Device* Display, bool Force ) {
|
||||
@@ -146,7 +144,7 @@ int GDS_FontGetCharWidth( struct GDS_Device* Display, char Character ) {
|
||||
}
|
||||
|
||||
int GDS_FontGetMaxCharsPerRow( struct GDS_Device* Display ) {
|
||||
return Display->TextWidth / Display->Font->Width;
|
||||
return Display->Width / Display->Font->Width;
|
||||
}
|
||||
|
||||
int GDS_FontGetMaxCharsPerColumn( struct GDS_Device* Display ) {
|
||||
@@ -210,7 +208,7 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int
|
||||
switch ( Anchor ) {
|
||||
case TextAnchor_East: {
|
||||
*OutY = ( Display->Height / 2 ) - ( StringHeight / 2 );
|
||||
*OutX = ( Display->TextWidth - StringWidth );
|
||||
*OutX = ( Display->Width - StringWidth );
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -221,19 +219,19 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int
|
||||
break;
|
||||
}
|
||||
case TextAnchor_North: {
|
||||
*OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 );
|
||||
*OutX = ( Display->Width / 2 ) - ( StringWidth / 2 );
|
||||
*OutY = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
case TextAnchor_South: {
|
||||
*OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 );
|
||||
*OutX = ( Display->Width / 2 ) - ( StringWidth / 2 );
|
||||
*OutY = ( Display->Height - StringHeight );
|
||||
|
||||
break;
|
||||
}
|
||||
case TextAnchor_NorthEast: {
|
||||
*OutX = ( Display->TextWidth - StringWidth );
|
||||
*OutX = ( Display->Width - StringWidth );
|
||||
*OutY = 0;
|
||||
|
||||
break;
|
||||
@@ -246,7 +244,7 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int
|
||||
}
|
||||
case TextAnchor_SouthEast: {
|
||||
*OutY = ( Display->Height - StringHeight );
|
||||
*OutX = ( Display->TextWidth - StringWidth );
|
||||
*OutX = ( Display->Width - StringWidth );
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -258,7 +256,7 @@ void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int
|
||||
}
|
||||
case TextAnchor_Center: {
|
||||
*OutY = ( Display->Height / 2 ) - ( StringHeight / 2 );
|
||||
*OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 );
|
||||
*OutX = ( Display->Width / 2 ) - ( StringWidth / 2 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ typedef enum {
|
||||
TextAnchor_Center
|
||||
} TextAnchor;
|
||||
|
||||
const struct GDS_FontDef* GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font );
|
||||
bool GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font );
|
||||
|
||||
void GDS_FontForceProportional( struct GDS_Device* Display, bool Force );
|
||||
void GDS_FontForceMonospace( struct GDS_Device* Display, bool Force );
|
||||
@@ -59,8 +59,7 @@ int GDS_FontGetMaxCharsPerColumn( struct GDS_Device* Display );
|
||||
|
||||
int GDS_FontGetCharWidth( struct GDS_Device* Display, char Character );
|
||||
int GDS_FontGetCharHeight( struct GDS_Device* Display );
|
||||
int GDS_FontMeasureString( struct GDS_Device* Display, const char* Text );
|
||||
int GDS_FontMeasureStringLine( struct GDS_Device* Display, int Line, const char* Text );
|
||||
int GDS_FontMeasureString( struct GDS_Device* Display, const char* Text );\
|
||||
|
||||
void GDS_FontDrawChar( struct GDS_Device* Display, char Character, int x, int y, int Color );
|
||||
void GDS_FontDrawString( struct GDS_Device* Display, int x, int y, const char* Text, int Color );
|
||||
|
||||
@@ -8,18 +8,14 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "math.h"
|
||||
#ifdef TJPGD_ROM
|
||||
#include "esp32/rom/tjpgd.h"
|
||||
#else
|
||||
#include "tjpgd.h"
|
||||
#endif
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "gds.h"
|
||||
#include "gds_private.h"
|
||||
#include "gds_image.h"
|
||||
|
||||
const static char TAG[] = "ImageDec";
|
||||
const char TAG[] = "ImageDec";
|
||||
|
||||
#define SCRATCH_SIZE 3100
|
||||
|
||||
@@ -171,7 +167,7 @@ static unsigned OutHandlerDirect(JDEC *Decoder, void *Bitmap, JRECT *Frame) {
|
||||
static void* DecodeJPEG(uint8_t *Source, int *Width, int *Height, float Scale, bool SizeOnly, int RGB_Mode) {
|
||||
JDEC Decoder;
|
||||
JpegCtx Context;
|
||||
char *Scratch = malloc(SCRATCH_SIZE);
|
||||
char *Scratch = calloc(SCRATCH_SIZE, 1);
|
||||
|
||||
if (!Scratch) {
|
||||
ESP_LOGE(TAG, "Cannot allocate workspace");
|
||||
@@ -376,7 +372,7 @@ bool GDS_DrawJPEG(struct GDS_Device* Device, uint8_t *Source, int x, int y, int
|
||||
JDEC Decoder;
|
||||
JpegCtx Context;
|
||||
bool Ret = false;
|
||||
char *Scratch = malloc(SCRATCH_SIZE);
|
||||
char *Scratch = calloc(SCRATCH_SIZE, 1);
|
||||
|
||||
if (!Scratch) {
|
||||
ESP_LOGE(TAG, "Cannot allocate workspace");
|
||||
|
||||
@@ -95,10 +95,9 @@ struct GDS_Device {
|
||||
const struct GDS_FontDef* Font;
|
||||
} Lines[MAX_LINES];
|
||||
|
||||
uint16_t Width, TextWidth;
|
||||
uint16_t Width;
|
||||
uint16_t Height;
|
||||
uint8_t Depth, Mode;
|
||||
bool HighNibble;
|
||||
|
||||
uint8_t Alloc;
|
||||
uint8_t* Framebuffer;
|
||||
@@ -118,15 +117,13 @@ 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, struct GDS_Layout *Layout );
|
||||
void (*SetLayout)( struct GDS_Device* Device, bool HFlip, bool VFlip, bool Rotate );
|
||||
// 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 );
|
||||
// may provide for optimization
|
||||
void (*DrawRGB)( struct GDS_Device* Device, uint8_t *Image,int x, int y, int Width, int Height, int RGB_Mode );
|
||||
void (*ClearWindow)( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color );
|
||||
// may provide for tweaking
|
||||
void (*SPIParams)(int Speed, uint8_t *mode, uint16_t *CS_pre, uint8_t *CS_post);
|
||||
|
||||
// interface-specific methods
|
||||
WriteCommandProc WriteCommand;
|
||||
@@ -156,9 +153,69 @@ static inline bool IsPixelVisible( struct GDS_Device* Device, int x, int y ) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
static inline void DrawPixel1Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint32_t YBit = ( Y & 0x07 );
|
||||
uint8_t* FBOffset;
|
||||
|
||||
/*
|
||||
* We only need to modify the Y coordinate since the pitch
|
||||
* of the screen is the same as the width.
|
||||
* Dividing Y by 8 gives us which row the pixel is in but not
|
||||
* the bit position.
|
||||
*/
|
||||
Y>>= 3;
|
||||
|
||||
FBOffset = Device->Framebuffer + ( ( Y * Device->Width ) + X );
|
||||
|
||||
if ( Color == GDS_COLOR_XOR ) {
|
||||
*FBOffset ^= BIT( YBit );
|
||||
} else {
|
||||
*FBOffset = ( Color == GDS_COLOR_BLACK ) ? *FBOffset & ~BIT( YBit ) : *FBOffset | BIT( YBit );
|
||||
}
|
||||
}
|
||||
|
||||
static inline void DrawPixel4Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint8_t* FBOffset = Device->Framebuffer + ( (Y * Device->Width >> 1) + (X >> 1));
|
||||
*FBOffset = X & 0x01 ? (*FBOffset & 0x0f) | ((Color & 0x0f) << 4) : ((*FBOffset & 0xf0) | (Color & 0x0f));
|
||||
}
|
||||
|
||||
static inline void DrawPixel8Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
Device->Framebuffer[Y * Device->Width + X] = Color;
|
||||
}
|
||||
|
||||
// assumes that Color is 16 bits R..RG..GB..B from MSB to LSB and FB wants 1st serialized byte to start with R
|
||||
static inline void DrawPixel16Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint16_t* FBOffset = (uint16_t*) Device->Framebuffer + Y * Device->Width + X;
|
||||
*FBOffset = __builtin_bswap16(Color);
|
||||
}
|
||||
|
||||
// assumes that Color is 18 bits RGB from MSB to LSB RRRRRRGGGGGGBBBBBB, so byte[0] is B
|
||||
// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = xxRRRRRR xxGGGGGG xxBBBBBB
|
||||
static inline void DrawPixel18Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3;
|
||||
*FBOffset++ = Color >> 12; *FBOffset++ = (Color >> 6) & 0x3f; *FBOffset = Color & 0x3f;
|
||||
}
|
||||
|
||||
// assumes that Color is 24 bits RGB from MSB to LSB RRRRRRRRGGGGGGGGBBBBBBBB, so byte[0] is B
|
||||
// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = RRRRRRRR GGGGGGGG BBBBBBBB
|
||||
static inline void DrawPixel24Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3;
|
||||
*FBOffset++ = Color >> 16; *FBOffset++ = Color >> 8; *FBOffset = Color;
|
||||
}
|
||||
|
||||
static inline void IRAM_ATTR DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ) {
|
||||
if (Device->DrawPixelFast) Device->DrawPixelFast( Device, X, Y, Color );
|
||||
else if (Device->Depth == 4) DrawPixel4Fast( Device, X, Y, Color );
|
||||
else if (Device->Depth == 1) DrawPixel1Fast( Device, X, Y, Color );
|
||||
else if (Device->Depth == 16) DrawPixel16Fast( Device, X, Y, Color );
|
||||
else if (Device->Depth == 24 && Device->Mode == GDS_RGB666) DrawPixel18Fast( Device, X, Y, Color );
|
||||
else if (Device->Depth == 24 && Device->Mode == GDS_RGB888) DrawPixel24Fast( Device, X, Y, Color );
|
||||
else if (Device->Depth == 8) DrawPixel8Fast( Device, X, Y, Color );
|
||||
}
|
||||
|
||||
static inline void IRAM_ATTR DrawPixel( struct GDS_Device* Device, int x, int y, int Color ) {
|
||||
if ( IsPixelVisible( Device, x, y ) == true ) {
|
||||
Device->DrawPixelFast( Device, x, y, Color );
|
||||
DrawPixelFast( Device, x, y, Color );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,20 +26,19 @@ static char TAG[] = "gds";
|
||||
*/
|
||||
static const struct GDS_FontDef *GuessFont( struct GDS_Device *Device, int FontType) {
|
||||
switch(FontType) {
|
||||
case GDS_FONT_DEFAULT:
|
||||
return Device->Font;
|
||||
case GDS_FONT_LINE_1:
|
||||
return &Font_line_1;
|
||||
case GDS_FONT_LINE_2:
|
||||
return &Font_line_2;
|
||||
case GDS_FONT_MEDIUM:
|
||||
//return &Font_droid_sans_fallback_15x17;
|
||||
case GDS_FONT_SMALL:
|
||||
default:
|
||||
return &Font_droid_sans_fallback_11x13;
|
||||
case GDS_FONT_MEDIUM:
|
||||
default:
|
||||
return &Font_droid_sans_fallback_15x17;
|
||||
#ifdef USE_LARGE_FONTS
|
||||
case GDS_FONT_LARGE:
|
||||
return &Font_droid_sans_fallback_24x28;
|
||||
break;
|
||||
case GDS_FONT_SEGMENT:
|
||||
if (Device->Height == 32) return &Font_Tarable7Seg_16x32;
|
||||
else return &Font_Tarable7Seg_32x64;
|
||||
@@ -47,8 +46,8 @@ static const struct GDS_FontDef *GuessFont( struct GDS_Device *Device, int FontT
|
||||
case GDS_FONT_LARGE:
|
||||
case GDS_FONT_SEGMENT:
|
||||
ESP_LOGW(TAG, "large fonts disabled");
|
||||
//return &Font_droid_sans_fallback_15x17;
|
||||
return &Font_droid_sans_fallback_11x13;
|
||||
return &Font_droid_sans_fallback_15x17;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -100,15 +99,15 @@ bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Tex
|
||||
Width = GDS_FontMeasureString( Device, Text );
|
||||
|
||||
// adjusting position, erase only EoL for rigth-justified
|
||||
if (Pos == GDS_TEXT_RIGHT) X = Device->TextWidth - Width - 1;
|
||||
else if (Pos == GDS_TEXT_CENTER) X = (Device->TextWidth - Width) / 2;
|
||||
if (Pos == GDS_TEXT_RIGHT) X = Device->Width - Width - 1;
|
||||
else if (Pos == GDS_TEXT_CENTER) X = (Device->Width - Width) / 2;
|
||||
|
||||
// erase if requested
|
||||
if (Attr & GDS_TEXT_CLEAR) {
|
||||
int Y_min = max(0, Device->Lines[N].Y), Y_max = max(0, Device->Lines[N].Y + Device->Lines[N].Font->Height);
|
||||
for (int c = (Attr & GDS_TEXT_CLEAR_EOL) ? X : 0; c < Device->TextWidth; c++)
|
||||
for (int c = (Attr & GDS_TEXT_CLEAR_EOL) ? X : 0; c < Device->Width; c++)
|
||||
for (int y = Y_min; y < Y_max; y++)
|
||||
Device->DrawPixelFast( Device, c, y, GDS_COLOR_BLACK );
|
||||
DrawPixelFast( Device, c, y, GDS_COLOR_BLACK );
|
||||
}
|
||||
|
||||
GDS_FontDrawString( Device, X, Device->Lines[N].Y, Text, GDS_COLOR_WHITE );
|
||||
@@ -119,20 +118,7 @@ bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Tex
|
||||
Device->Dirty = true;
|
||||
if (Attr & GDS_TEXT_UPDATE) GDS_Update( Device );
|
||||
|
||||
return Width + X < Device->TextWidth;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
int GDS_GetTextWidth(struct GDS_Device* Device, int N, int Attr, char *Text) {
|
||||
const struct GDS_FontDef *Font = GDS_SetFont( Device, Device->Lines[N-1].Font );
|
||||
|
||||
if (Attr & GDS_TEXT_MONOSPACE) GDS_FontForceMonospace( Device, true );
|
||||
int Width = GDS_FontMeasureString( Device, Text );
|
||||
GDS_SetFont( Device, Font );
|
||||
|
||||
return Width;
|
||||
return Width + X < Device->Width;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -146,7 +132,7 @@ int GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max) {
|
||||
|
||||
// we might already fit
|
||||
GDS_SetFont( Device, Device->Lines[N].Font );
|
||||
if (GDS_FontMeasureString( Device, String ) <= Device->TextWidth) return 0;
|
||||
if (GDS_FontMeasureString( Device, String ) <= Device->Width) return 0;
|
||||
|
||||
// add some space for better visual
|
||||
strncat(String, Space, Max-Len);
|
||||
@@ -157,7 +143,7 @@ int GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max) {
|
||||
Boundary = GDS_FontMeasureString( Device, String );
|
||||
|
||||
// add a full display width
|
||||
while (Len < Max && GDS_FontMeasureString( Device, String ) - Boundary < Device->TextWidth) {
|
||||
while (Len < Max && GDS_FontMeasureString( Device, String ) - Boundary < Device->Width) {
|
||||
String[Len++] = String[Extra++];
|
||||
String[Len] = '\0';
|
||||
}
|
||||
|
||||
@@ -31,6 +31,5 @@ struct GDS_Device;
|
||||
bool GDS_TextSetFontAuto(struct GDS_Device* Device, int N, int FontType, int Space);
|
||||
bool GDS_TextSetFont(struct GDS_Device* Device, int N, const struct GDS_FontDef *Font, int Space);
|
||||
bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Text);
|
||||
int GDS_GetTextWidth(struct GDS_Device* Device, int N, int Attr, char *Text);
|
||||
int GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max);
|
||||
void GDS_TextPos(struct GDS_Device* Device, int FontType, int Where, int Attr, char *Text, ...);
|
||||
@@ -35,7 +35,7 @@ static bool I2CDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data,
|
||||
bool GDS_I2CInit( int PortNumber, int SDA, int SCL, int Speed ) {
|
||||
I2CPortNumber = PortNumber;
|
||||
|
||||
I2CWait = pdMS_TO_TICKS( Speed ? (250 * 250000) / Speed : 250 );
|
||||
I2CWait = pdMS_TO_TICKS( Speed ? Speed / 4000 : 100 );
|
||||
|
||||
if (SDA != -1 && SCL != -1) {
|
||||
i2c_config_t Config = { 0 };
|
||||
@@ -75,7 +75,7 @@ bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int
|
||||
Device->RSTPin = RSTPin;
|
||||
Device->Backlight.Pin = BacklightPin;
|
||||
Device->IF = GDS_IF_I2C;
|
||||
Device->Width = Device->TextWidth = Width;
|
||||
Device->Width = Width;
|
||||
Device->Height = Height;
|
||||
|
||||
if ( RSTPin >= 0 ) {
|
||||
|
||||
@@ -34,8 +34,8 @@ bool GDS_SPIInit( int SPI, int DC ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int BackLightPin, int Speed, int Mode ) {
|
||||
spi_device_interface_config_t SPIDeviceConfig = { };
|
||||
bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int BackLightPin, int Speed ) {
|
||||
spi_device_interface_config_t SPIDeviceConfig;
|
||||
spi_device_handle_t SPIDevice;
|
||||
|
||||
NullCheck( Device, return false );
|
||||
@@ -43,16 +43,15 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
|
||||
if (CSPin >= 0) {
|
||||
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( CSPin, GPIO_MODE_OUTPUT ), return false );
|
||||
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSPin, 0 ), return false );
|
||||
}
|
||||
}
|
||||
|
||||
memset( &SPIDeviceConfig, 0, sizeof( spi_device_interface_config_t ) );
|
||||
|
||||
SPIDeviceConfig.clock_speed_hz = Speed > 0 ? Speed : SPI_MASTER_FREQ_8M;
|
||||
SPIDeviceConfig.spics_io_num = CSPin;
|
||||
SPIDeviceConfig.queue_size = 1;
|
||||
SPIDeviceConfig.mode = Mode;
|
||||
SPIDeviceConfig.flags = SPI_DEVICE_NO_DUMMY;
|
||||
if (Device->SPIParams) Device->SPIParams(SPIDeviceConfig.clock_speed_hz, &SPIDeviceConfig.mode,
|
||||
&SPIDeviceConfig.cs_ena_pretrans, &SPIDeviceConfig.cs_ena_posttrans);
|
||||
|
||||
|
||||
ESP_ERROR_CHECK_NONFATAL( spi_bus_add_device( SPIHost, &SPIDeviceConfig, &SPIDevice ), return false );
|
||||
|
||||
Device->WriteCommand = SPIDefaultWriteCommand;
|
||||
@@ -62,7 +61,7 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
|
||||
Device->CSPin = CSPin;
|
||||
Device->Backlight.Pin = BackLightPin;
|
||||
Device->IF = GDS_IF_SPI;
|
||||
Device->Width = Device->TextWidth = Width;
|
||||
Device->Width = Width;
|
||||
Device->Height = Height;
|
||||
|
||||
if ( RSTPin >= 0 ) {
|
||||
@@ -75,23 +74,16 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
|
||||
}
|
||||
|
||||
static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) {
|
||||
spi_transaction_t SPITransaction = { };
|
||||
spi_transaction_t SPITransaction = { 0 };
|
||||
|
||||
NullCheck( SPIHandle, return false );
|
||||
NullCheck( Data, return false );
|
||||
|
||||
if ( DataLength > 0 ) {
|
||||
gpio_set_level( DCPin, WriteMode );
|
||||
|
||||
SPITransaction.length = DataLength * 8;
|
||||
|
||||
if (DataLength <= 4) {
|
||||
SPITransaction.flags = SPI_TRANS_USE_TXDATA;
|
||||
SPITransaction.tx_data[0] = *Data++; SPITransaction.tx_data[1] = *Data++;
|
||||
SPITransaction.tx_data[2] = *Data++; SPITransaction.tx_data[3] = *Data;
|
||||
} else {
|
||||
SPITransaction.tx_buffer = Data;
|
||||
}
|
||||
SPITransaction.length = DataLength * 8;
|
||||
SPITransaction.tx_buffer = Data;
|
||||
|
||||
// only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes)
|
||||
ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false );
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user