[Fw] Add Dummy controller firmware.

Add description of Firmware.
This commit is contained in:
peng-zhihui 2021-10-27 10:43:08 +08:00
parent f3150c8c50
commit 52c8328f51
397 changed files with 610670 additions and 3 deletions

View File

@ -0,0 +1,275 @@
<?xml version="1.0" encoding="UTF-8"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="fr.ac6.managedbuild.config.gnu.cross.exe.debug.1465527105">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="fr.ac6.managedbuild.config.gnu.cross.exe.debug.1465527105" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<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 artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="fr.ac6.managedbuild.config.gnu.cross.exe.debug.1465527105" name="Debug" parent="fr.ac6.managedbuild.config.gnu.cross.exe.debug" postannouncebuildStep="Generating hex and Printing size information:" postbuildStep="arm-none-eabi-objcopy -O ihex &quot;${BuildArtifactFileBaseName}.elf&quot; &quot;${BuildArtifactFileBaseName}.hex&quot; &amp;&amp; arm-none-eabi-size &quot;${BuildArtifactFileName}&quot;">
<folderInfo id="fr.ac6.managedbuild.config.gnu.cross.exe.debug.1465527105." name="/" resourcePath="">
<toolChain id="fr.ac6.managedbuild.toolchain.gnu.cross.exe.debug.682049980" name="Ac6 STM32 MCU GCC" superClass="fr.ac6.managedbuild.toolchain.gnu.cross.exe.debug">
<option id="fr.ac6.managedbuild.option.gnu.cross.prefix.14716717" name="Prefix" superClass="fr.ac6.managedbuild.option.gnu.cross.prefix" value="arm-none-eabi-" valueType="string" />
<option id="fr.ac6.managedbuild.option.gnu.cross.mcu.1649063108" name="Mcu" superClass="fr.ac6.managedbuild.option.gnu.cross.mcu" value="STM32F405RGTx" valueType="string" />
<option id="fr.ac6.managedbuild.option.gnu.cross.board.1450084087" name="Board" superClass="fr.ac6.managedbuild.option.gnu.cross.board" value="REF-STM32F4" valueType="string" />
<option id="fr.ac6.managedbuild.option.gnu.cross.core.1083960614" name="Core" superClass="fr.ac6.managedbuild.option.gnu.cross.core" valueType="stringList">
<listOptionValue builtIn="false" value="ARM Cortex-M4" />
<listOptionValue builtIn="false" value="CM4" />
</option>
<option id="fr.ac6.managedbuild.option.gnu.cross.instructionSet.1135067759" name="Instruction Set" superClass="fr.ac6.managedbuild.option.gnu.cross.instructionSet" value="fr.ac6.managedbuild.option.gnu.cross.instructionSet.thumbII" valueType="enumerated" />
<option id="fr.ac6.managedbuild.option.gnu.cross.fpu.381891948" name="Floating point hardware" superClass="fr.ac6.managedbuild.option.gnu.cross.fpu" value="fr.ac6.managedbuild.option.gnu.cross.fpu.fpv4-sp-d16" valueType="enumerated" />
<option id="fr.ac6.managedbuild.option.gnu.cross.floatabi.1935780784" name="Floating-point ABI" superClass="fr.ac6.managedbuild.option.gnu.cross.floatabi" value="fr.ac6.managedbuild.option.gnu.cross.floatabi.hard" valueType="enumerated" />
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="fr.ac6.managedbuild.targetPlatform.gnu.cross.1694166814" isAbstract="false" osList="all" superClass="fr.ac6.managedbuild.targetPlatform.gnu.cross" />
<builder buildPath="${workspace_loc:/REF-STM32F4}/Debug" id="fr.ac6.managedbuild.builder.gnu.cross.821918229" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="fr.ac6.managedbuild.builder.gnu.cross">
<outputEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="Debug" />
</outputEntries>
</builder>
<tool id="fr.ac6.managedbuild.tool.gnu.cross.c.compiler.1162984751" name="MCU GCC Compiler" superClass="fr.ac6.managedbuild.tool.gnu.cross.c.compiler">
<option defaultValue="gnu.c.optimization.level.none" id="fr.ac6.managedbuild.gnu.c.compiler.option.optimization.level.576766831" name="Optimization Level" superClass="fr.ac6.managedbuild.gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="fr.ac6.managedbuild.gnu.c.optimization.level.debug" valueType="enumerated" />
<option id="gnu.c.compiler.option.debugging.level.1533010097" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated" />
<option id="gnu.c.compiler.option.include.paths.2074577941" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="../Core/Inc" />
<listOptionValue builtIn="false" value="../USB_DEVICE/App" />
<listOptionValue builtIn="false" value="../USB_DEVICE/Target" />
<listOptionValue builtIn="false" value="../Drivers/STM32F4xx_HAL_Driver/Inc" />
<listOptionValue builtIn="false" value="../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/include" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F" />
<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Core/Inc" />
<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" />
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Device/ST/STM32F4xx/Include" />
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Include" />
</option>
<option id="gnu.c.compiler.option.preprocessor.def.symbols.1169568840" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="USE_HAL_DRIVER" />
<listOptionValue builtIn="false" value="STM32F405xx" />
</option>
<option id="fr.ac6.managedbuild.gnu.c.compiler.option.misc.other.1096527460" superClass="fr.ac6.managedbuild.gnu.c.compiler.option.misc.other" value="-fmessage-length=0" valueType="string" />
<inputType id="fr.ac6.managedbuild.tool.gnu.cross.c.compiler.input.c.595876878" superClass="fr.ac6.managedbuild.tool.gnu.cross.c.compiler.input.c" />
<inputType id="fr.ac6.managedbuild.tool.gnu.cross.c.compiler.input.s.1177508511" superClass="fr.ac6.managedbuild.tool.gnu.cross.c.compiler.input.s" />
</tool>
<tool id="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler.2118009532" name="MCU G++ Compiler" superClass="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler">
<option defaultValue="gnu.cpp.optimization.level.none" id="fr.ac6.managedbuild.gnu.cpp.compiler.option.optimization.level.1303523993" name="Optimization Level" superClass="fr.ac6.managedbuild.gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="fr.ac6.managedbuild.gnu.cpp.optimization.level.debug" valueType="enumerated" />
<option id="gnu.cpp.compiler.option.debugging.level.1276823941" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated" />
<option id="gnu.cpp.compiler.option.include.paths.1415562010" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="../Core/Inc" />
<listOptionValue builtIn="false" value="../USB_DEVICE/App" />
<listOptionValue builtIn="false" value="../USB_DEVICE/Target" />
<listOptionValue builtIn="false" value="../Drivers/STM32F4xx_HAL_Driver/Inc" />
<listOptionValue builtIn="false" value="../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/include" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F" />
<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Core/Inc" />
<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" />
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Device/ST/STM32F4xx/Include" />
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Include" />
</option>
<option id="gnu.cpp.compiler.option.preprocessor.def.1226284813" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="USE_HAL_DRIVER" />
<listOptionValue builtIn="false" value="STM32F405xx" />
</option>
<option id="fr.ac6.managedbuild.gnu.cpp.compiler.option.misc.other.1616325870" superClass="fr.ac6.managedbuild.gnu.cpp.compiler.option.misc.other" value="-fmessage-length=0" valueType="string" />
<inputType id="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler.input.cpp.712707357" superClass="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler.input.cpp" />
<inputType id="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler.input.s.1717008927" superClass="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler.input.s" />
</tool>
<tool id="fr.ac6.managedbuild.tool.gnu.cross.c.linker.713353907" name="MCU GCC Linker" superClass="fr.ac6.managedbuild.tool.gnu.cross.c.linker">
<option id="fr.ac6.managedbuild.tool.gnu.cross.c.linker.script.642728547" name="Linker Script (-T)" superClass="fr.ac6.managedbuild.tool.gnu.cross.c.linker.script" value="../STM32F405RGTx_FLASH.ld" valueType="string" />
<option id="gnu.c.link.option.libs.1205507832" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs" />
<option id="gnu.c.link.option.paths.1193687791" name="Library search path (-L)" superClass="gnu.c.link.option.paths" valueType="libPaths" />
<option id="gnu.c.link.option.ldflags.168982979" superClass="gnu.c.link.option.ldflags" value="-specs=nosys.specs -specs=nano.specs" valueType="string" />
<option id="gnu.c.link.option.other.620578026" name="Other options (-Xlinker [option])" superClass="gnu.c.link.option.other" useByScannerDiscovery="false" valueType="stringList" />
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.1991085701" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)" />
<additionalInput kind="additionalinput" paths="$(LIBS)" />
</inputType>
</tool>
<tool id="fr.ac6.managedbuild.tool.gnu.cross.cpp.linker.1754125851" name="MCU G++ Linker" superClass="fr.ac6.managedbuild.tool.gnu.cross.cpp.linker">
<option id="fr.ac6.managedbuild.tool.gnu.cross.cpp.linker.script.1172171715" name="Linker Script (-T)" superClass="fr.ac6.managedbuild.tool.gnu.cross.cpp.linker.script" value="../STM32F405RGTx_FLASH.ld" valueType="string" />
<option id="gnu.cpp.link.option.libs.2027761599" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs" />
<option id="gnu.cpp.link.option.paths.749732967" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths" />
<option id="gnu.cpp.link.option.flags.1182954689" superClass="gnu.cpp.link.option.flags" value="-specs=nosys.specs -specs=nano.specs" valueType="string" />
<option id="gnu.cpp.link.option.other.467536573" name="Other options (-Xlinker [option])" superClass="gnu.cpp.link.option.other" useByScannerDiscovery="false" valueType="stringList" />
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1019092565" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)" />
<additionalInput kind="additionalinput" paths="$(LIBS)" />
</inputType>
</tool>
<tool id="fr.ac6.managedbuild.tool.gnu.archiver.798545704" name="MCU GCC Archiver" superClass="fr.ac6.managedbuild.tool.gnu.archiver" />
<tool id="fr.ac6.managedbuild.tool.gnu.cross.assembler.1320032457" name="MCU GCC Assembler" superClass="fr.ac6.managedbuild.tool.gnu.cross.assembler">
<option id="gnu.both.asm.option.include.paths.208729480" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
</option>
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.2111521164" superClass="cdt.managedbuild.tool.gnu.assembler.input" />
<inputType id="fr.ac6.managedbuild.tool.gnu.cross.assembler.input.1318668642" superClass="fr.ac6.managedbuild.tool.gnu.cross.assembler.input" />
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="startup" />
<entry excluding="" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Middlewares" />
<entry excluding="" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Drivers" />
<entry excluding="" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="USB_DEVICE" />
<entry excluding="" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core" />
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings" />
</cconfiguration>
<cconfiguration id="fr.ac6.managedbuild.config.gnu.cross.exe.release.1792971278">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="fr.ac6.managedbuild.config.gnu.cross.exe.release.1792971278" moduleId="org.eclipse.cdt.core.settings" name="Release">
<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 artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="fr.ac6.managedbuild.config.gnu.cross.exe.release.1792971278" name="Release" parent="fr.ac6.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating hex and Printing size information:" postbuildStep="arm-none-eabi-objcopy -O ihex &quot;${BuildArtifactFileBaseName}.elf&quot; &quot;${BuildArtifactFileBaseName}.hex&quot; &amp;&amp; arm-none-eabi-size &quot;${BuildArtifactFileName}&quot;">
<folderInfo id="fr.ac6.managedbuild.config.gnu.cross.exe.release.1792971278." name="/" resourcePath="">
<toolChain id="fr.ac6.managedbuild.toolchain.gnu.cross.exe.release.1069307058" name="Ac6 STM32 MCU GCC" superClass="fr.ac6.managedbuild.toolchain.gnu.cross.exe.release">
<option id="fr.ac6.managedbuild.option.gnu.cross.prefix.14716717" name="Prefix" superClass="fr.ac6.managedbuild.option.gnu.cross.prefix" value="arm-none-eabi-" valueType="string" />
<option id="fr.ac6.managedbuild.option.gnu.cross.mcu.1649063108" name="Mcu" superClass="fr.ac6.managedbuild.option.gnu.cross.mcu" value="STM32F405RGTx" valueType="string" />
<option id="fr.ac6.managedbuild.option.gnu.cross.board.1450084087" name="Board" superClass="fr.ac6.managedbuild.option.gnu.cross.board" value="REF-STM32F4" valueType="string" />
<option id="fr.ac6.managedbuild.option.gnu.cross.core.1083960614" name="Core" superClass="fr.ac6.managedbuild.option.gnu.cross.core" valueType="stringList">
<listOptionValue builtIn="false" value="ARM Cortex-M4" />
<listOptionValue builtIn="false" value="CM4" />
</option>
<option id="fr.ac6.managedbuild.option.gnu.cross.instructionSet.1135067759" name="Instruction Set" superClass="fr.ac6.managedbuild.option.gnu.cross.instructionSet" value="fr.ac6.managedbuild.option.gnu.cross.instructionSet.thumbII" valueType="enumerated" />
<option id="fr.ac6.managedbuild.option.gnu.cross.fpu.381891948" name="Floating point hardware" superClass="fr.ac6.managedbuild.option.gnu.cross.fpu" value="fr.ac6.managedbuild.option.gnu.cross.fpu.fpv4-sp-d16" valueType="enumerated" />
<option id="fr.ac6.managedbuild.option.gnu.cross.floatabi.1935780784" name="Floating-point ABI" superClass="fr.ac6.managedbuild.option.gnu.cross.floatabi" value="fr.ac6.managedbuild.option.gnu.cross.floatabi.hard" valueType="enumerated" />
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="fr.ac6.managedbuild.targetPlatform.gnu.cross.1694166814" isAbstract="false" osList="all" superClass="fr.ac6.managedbuild.targetPlatform.gnu.cross" />
<builder buildPath="${workspace_loc:/REF-STM32F4}/Release" id="fr.ac6.managedbuild.builder.gnu.cross.821918229" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="fr.ac6.managedbuild.builder.gnu.cross">
<outputEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="Release" />
</outputEntries>
</builder>
<tool id="fr.ac6.managedbuild.tool.gnu.cross.c.compiler.1162984751" name="MCU GCC Compiler" superClass="fr.ac6.managedbuild.tool.gnu.cross.c.compiler">
<option defaultValue="gnu.c.optimization.level.none" id="fr.ac6.managedbuild.gnu.c.compiler.option.optimization.level.576766831" name="Optimization Level" superClass="fr.ac6.managedbuild.gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="fr.ac6.managedbuild.gnu.c.optimization.level.debug" valueType="enumerated" />
<option id="gnu.c.compiler.option.debugging.level.1533010097" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated" />
<option id="gnu.c.compiler.option.include.paths.2074577941" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="../Core/Inc" />
<listOptionValue builtIn="false" value="../USB_DEVICE/App" />
<listOptionValue builtIn="false" value="../USB_DEVICE/Target" />
<listOptionValue builtIn="false" value="../Drivers/STM32F4xx_HAL_Driver/Inc" />
<listOptionValue builtIn="false" value="../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/include" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F" />
<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Core/Inc" />
<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" />
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Device/ST/STM32F4xx/Include" />
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Include" />
</option>
<option id="gnu.c.compiler.option.preprocessor.def.symbols.1169568840" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="USE_HAL_DRIVER" />
<listOptionValue builtIn="false" value="STM32F405xx" />
</option>
<option id="fr.ac6.managedbuild.gnu.c.compiler.option.misc.other.1096527460" superClass="fr.ac6.managedbuild.gnu.c.compiler.option.misc.other" value="-fmessage-length=0" valueType="string" />
<inputType id="fr.ac6.managedbuild.tool.gnu.cross.c.compiler.input.c.595876878" superClass="fr.ac6.managedbuild.tool.gnu.cross.c.compiler.input.c" />
<inputType id="fr.ac6.managedbuild.tool.gnu.cross.c.compiler.input.s.1177508511" superClass="fr.ac6.managedbuild.tool.gnu.cross.c.compiler.input.s" />
</tool>
<tool id="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler.2118009532" name="MCU G++ Compiler" superClass="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler">
<option defaultValue="gnu.cpp.optimization.level.none" id="fr.ac6.managedbuild.gnu.cpp.compiler.option.optimization.level.1303523993" name="Optimization Level" superClass="fr.ac6.managedbuild.gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="fr.ac6.managedbuild.gnu.cpp.optimization.level.debug" valueType="enumerated" />
<option id="gnu.cpp.compiler.option.debugging.level.1276823941" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.debugging.level.max" valueType="enumerated" />
<option id="gnu.cpp.compiler.option.include.paths.1415562010" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="../Core/Inc" />
<listOptionValue builtIn="false" value="../USB_DEVICE/App" />
<listOptionValue builtIn="false" value="../USB_DEVICE/Target" />
<listOptionValue builtIn="false" value="../Drivers/STM32F4xx_HAL_Driver/Inc" />
<listOptionValue builtIn="false" value="../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/include" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2" />
<listOptionValue builtIn="false" value="../Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F" />
<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Core/Inc" />
<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" />
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Device/ST/STM32F4xx/Include" />
<listOptionValue builtIn="false" value="../Drivers/CMSIS/Include" />
</option>
<option id="gnu.cpp.compiler.option.preprocessor.def.symbols.1498708839" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="USE_HAL_DRIVER" />
<listOptionValue builtIn="false" value="STM32F405xx" />
</option>
<option id="fr.ac6.managedbuild.gnu.cpp.compiler.option.misc.other.1616325870" superClass="fr.ac6.managedbuild.gnu.cpp.compiler.option.misc.other" value="-fmessage-length=0" valueType="string" />
<inputType id="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler.input.cpp.712707357" superClass="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler.input.cpp" />
<inputType id="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler.input.s.1717008927" superClass="fr.ac6.managedbuild.tool.gnu.cross.cpp.compiler.input.s" />
</tool>
<tool id="fr.ac6.managedbuild.tool.gnu.cross.c.linker.713353907" name="MCU GCC Linker" superClass="fr.ac6.managedbuild.tool.gnu.cross.c.linker">
<option id="fr.ac6.managedbuild.tool.gnu.cross.c.linker.script.642728547" name="Linker Script (-T)" superClass="fr.ac6.managedbuild.tool.gnu.cross.c.linker.script" value="../STM32F405RGTx_FLASH.ld" valueType="string" />
<option id="gnu.c.link.option.libs.1205507832" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs" />
<option id="gnu.c.link.option.paths.1193687791" name="Library search path (-L)" superClass="gnu.c.link.option.paths" valueType="libPaths" />
<option id="gnu.c.link.option.ldflags.168982979" superClass="gnu.c.link.option.ldflags" value="-specs=nosys.specs -specs=nano.specs" valueType="string" />
<option id="gnu.c.link.option.other.620578026" name="Other options (-Xlinker [option])" superClass="gnu.c.link.option.other" useByScannerDiscovery="false" valueType="stringList" />
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.1991085701" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)" />
<additionalInput kind="additionalinput" paths="$(LIBS)" />
</inputType>
</tool>
<tool id="fr.ac6.managedbuild.tool.gnu.cross.cpp.linker.1754125851" name="MCU G++ Linker" superClass="fr.ac6.managedbuild.tool.gnu.cross.cpp.linker">
<option id="fr.ac6.managedbuild.tool.gnu.cross.cpp.linker.script.1172171715" name="Linker Script (-T)" superClass="fr.ac6.managedbuild.tool.gnu.cross.cpp.linker.script" value="../STM32F405RGTx_FLASH.ld" valueType="string" />
<option id="gnu.cpp.link.option.libs.2027761599" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs" />
<option id="gnu.cpp.link.option.paths.749732967" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths" />
<option id="gnu.cpp.link.option.ldflags.1873645031" superClass="gnu.cpp.link.option.ldflags" value="-specs=nosys.specs -specs=nano.specs" valueType="string" />
<option id="gnu.cpp.link.option.other.467536573" name="Other options (-Xlinker [option])" superClass="gnu.cpp.link.option.other" useByScannerDiscovery="false" valueType="stringList" />
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1019092565" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)" />
<additionalInput kind="additionalinput" paths="$(LIBS)" />
</inputType>
</tool>
<tool id="fr.ac6.managedbuild.tool.gnu.archiver.798545704" name="MCU GCC Archiver" superClass="fr.ac6.managedbuild.tool.gnu.archiver" />
<tool id="fr.ac6.managedbuild.tool.gnu.cross.assembler.exe.release.360626725" name="MCU GCC Assembler" superClass="fr.ac6.managedbuild.tool.gnu.cross.assembler.exe.release">
<option id="gnu.both.asm.option.include.paths.208729480" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
</option>
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.2111521164" superClass="cdt.managedbuild.tool.gnu.assembler.input" />
<inputType id="fr.ac6.managedbuild.tool.gnu.cross.assembler.input.1318668642" superClass="fr.ac6.managedbuild.tool.gnu.cross.assembler.input" />
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="startup" />
<entry excluding="" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Middlewares" />
<entry excluding="" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Drivers" />
<entry excluding="" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="USB_DEVICE" />
<entry excluding="" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core" />
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings" />
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="REF-STM32F4.fr.ac6.managedbuild.target.gnu.cross.exe.434315245" name="Executable" projectType="fr.ac6.managedbuild.target.gnu.cross.exe" />
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="" />
<scannerConfigBuildInfo instanceId="fr.ac6.managedbuild.config.gnu.cross.exe.debug.1465527105;fr.ac6.managedbuild.config.gnu.cross.exe.debug.1465527105.;fr.ac6.managedbuild.tool.gnu.cross.c.compiler.1162984751;fr.ac6.managedbuild.tool.gnu.cross.c.compiler.input.c.595876878">
<autodiscovery enabled="false" problemReportingEnabled="true" selectedProfileId="" />
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders" />
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration artifactName="${ProjName}" configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="REF-STM32F4" />
</configuration>
</storageModule>
</cproject>

1
2.Firmware/REF-STM32F4-fw/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
cmake-build-*

8
2.Firmware/REF-STM32F4-fw/.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false">
<serverData>
<paths name="Remote Host (c7522b82-40ae-46b0-83ac-fe381ec0cb50)">
<serverdata>
<mappings>
<mapping local="$PROJECT_DIR$" web="/" />
</mappings>
</serverdata>
</paths>
</serverData>
</component>
</project>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/Robot/actuator/mintasca" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuator/mintasca/sca.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuator/mintasca/sca.hpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuator/mintasca/sca_api.c" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuator/mintasca/sca_api.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuator/mintasca/sca_protocol.c" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuator/mintasca/sca_protocol.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuators/mintasca/sca.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuators/mintasca/sca.hpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuators/mintasca/sca_api.c" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuators/mintasca/sca_api.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuators/mintasca/sca_protocol.c" charset="GBK" />
<file url="file://$PROJECT_DIR$/Robot/actuators/mintasca/sca_protocol.h" charset="GBK" />
</component>
</project>

View File

@ -0,0 +1,9 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ClangTidy" enabled="true" level="WARNING" enabled_by_default="true">
<option name="clangTidyChecks" value="-*,bugprone-argument-comment,bugprone-assert-side-effect,bugprone-bad-signal-to-kill-thread,bugprone-branch-clone,bugprone-copy-constructor-init,bugprone-dangling-handle,bugprone-dynamic-static-initializers,bugprone-fold-init-type,bugprone-forward-declaration-namespace,bugprone-forwarding-reference-overload,bugprone-inaccurate-erase,bugprone-incorrect-roundings,bugprone-integer-division,bugprone-lambda-function-name,bugprone-macro-parentheses,bugprone-macro-repeated-side-effects,bugprone-misplaced-operator-in-strlen-in-alloc,bugprone-misplaced-pointer-arithmetic-in-alloc,bugprone-misplaced-widening-cast,bugprone-move-forwarding-reference,bugprone-multiple-statement-macro,bugprone-no-escape,bugprone-not-null-terminated-result,bugprone-parent-virtual-call,bugprone-posix-return,bugprone-reserved-identifier,bugprone-sizeof-container,bugprone-sizeof-expression,bugprone-spuriously-wake-up-functions,bugprone-string-constructor,bugprone-string-integer-assignment,bugprone-string-literal-with-embedded-nul,bugprone-suspicious-enum-usage,bugprone-suspicious-include,bugprone-suspicious-memset-usage,bugprone-suspicious-missing-comma,bugprone-suspicious-semicolon,bugprone-suspicious-string-compare,bugprone-swapped-arguments,bugprone-terminating-continue,bugprone-throw-keyword-missing,bugprone-too-small-loop-variable,bugprone-undefined-memory-manipulation,bugprone-undelegated-constructor,bugprone-unhandled-self-assignment,bugprone-unused-raii,bugprone-unused-return-value,bugprone-use-after-move,bugprone-virtual-near-miss,cert-dcl21-cpp,cert-dcl58-cpp,cert-err52-cpp,cert-err60-cpp,cert-flp30-c,cert-msc50-cpp,cert-msc51-cpp,cert-str34-c,cppcoreguidelines-interfaces-global-init,cppcoreguidelines-narrowing-conversions,cppcoreguidelines-pro-type-member-init,cppcoreguidelines-pro-type-static-cast-downcast,cppcoreguidelines-slicing,google-default-arguments,google-explicit-constructor,google-runtime-operator,hicpp-exception-baseclass,hicpp-multiway-paths-covered,misc-misplaced-const,misc-new-delete-overloads,misc-no-recursion,misc-non-copyable-objects,misc-throw-by-value-catch-by-reference,misc-unconventional-assign-operator,misc-uniqueptr-reset-release,modernize-avoid-bind,modernize-concat-nested-namespaces,modernize-deprecated-headers,modernize-deprecated-ios-base-aliases,modernize-loop-convert,modernize-make-shared,modernize-make-unique,modernize-pass-by-value,modernize-raw-string-literal,modernize-redundant-void-arg,modernize-replace-auto-ptr,modernize-replace-disallow-copy-and-assign-macro,modernize-replace-random-shuffle,modernize-return-braced-init-list,modernize-shrink-to-fit,modernize-unary-static-assert,modernize-use-auto,modernize-use-bool-literals,modernize-use-emplace,modernize-use-equals-default,modernize-use-equals-delete,modernize-use-nodiscard,modernize-use-noexcept,modernize-use-nullptr,modernize-use-override,modernize-use-transparent-functors,modernize-use-uncaught-exceptions,mpi-buffer-deref,mpi-type-mismatch,openmp-use-default-none,performance-faster-string-find,performance-for-range-copy,performance-implicit-conversion-in-loop,performance-inefficient-algorithm,performance-inefficient-string-concatenation,performance-inefficient-vector-operation,performance-move-const-arg,performance-move-constructor-init,performance-no-automatic-move,performance-noexcept-move-constructor,performance-trivially-destructible,performance-type-promotion-in-math-fn,performance-unnecessary-copy-initialization,performance-unnecessary-value-param,portability-simd-intrinsics,readability-avoid-const-params-in-decls,readability-const-return-type,readability-container-size-empty,readability-convert-member-functions-to-static,readability-delete-null-pointer,readability-deleted-default,readability-inconsistent-declaration-parameter-name,readability-make-member-function-const,readability-misleading-indentation,readability-misplaced-array-index,readability-non-const-parameter,readability-redundant-control-flow,readability-redundant-declaration,readability-redundant-function-ptr-dereference,readability-redundant-smartptr-get,readability-redundant-string-cstr,readability-redundant-string-init,readability-simplify-subscript-expr,readability-static-accessed-through-instance,readability-static-definition-in-anonymous-namespace,readability-string-compare,readability-uniqueptr-delete-release,readability-use-anyofallof" />
</inspection_tool>
<inspection_tool class="EndlessLoop" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

View File

@ -0,0 +1,7 @@
<component name="libraryTable">
<library name="ROS">
<CLASSES />
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -0,0 +1,7 @@
<component name="libraryTable">
<library name="workspace">
<CLASSES />
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/REF-STM32F4.iml" filepath="$PROJECT_DIR$/.idea/REF-STM32F4.iml" />
</modules>
</component>
</project>

12
2.Firmware/REF-STM32F4-fw/.idea/ros.xml generated Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ROSSettings">
<option name="rosPath" value="" />
<option name="workspacePath" value="" />
<option name="additionalSources" value="" />
<option name="excludedXmls" value="" />
<option name="licenseLinkType" value="Summary" />
<option name="knownKeys" value="" />
<option name="depSources" value="https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml&quot;https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml&quot;https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml" />
</component>
</project>

View File

@ -0,0 +1,10 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="OCD REF-STM32F4" type="com.jetbrains.cidr.embedded.openocd.conf.type" factoryName="com.jetbrains.cidr.embedded.openocd.conf.factory" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="REF-STM32F4-fw" TARGET_NAME="REF-STM32F4-fw.elf" CONFIG_NAME="Debug" version="1" RUN_TARGET_PROJECT_NAME="REF-STM32F4-fw" RUN_TARGET_NAME="REF-STM32F4-fw.elf">
<openocd version="1" gdb-port="3333" telnet-port="4444" board-config="I:\onWorking\_Private\REF-STM32F4-dev\2.Firmware\REF-STM32F4-fw\stlink.cfg" reset-type="INIT" download-type="UPDATED_ONLY">
<debugger kind="GDB" isBundled="true" />
</openocd>
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
</component>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SerialMonitorSettings" PortName="COM7" BaudRate="115200" LineEndingsIndex="1" ShowStatusWidget="true" />
</project>

6
2.Firmware/REF-STM32F4-fw/.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>REF-STM32F4</name>
<comment />
<projects>
</projects>
<buildSpec>
<buildCommand>
<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.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
<nature>fr.ac6.mcu.ide.core.MCUProjectNature</nature>
</natures>
<linkedResources>
<link>
<name>FreeRTOS/croutine.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/Third_Party/FreeRTOS/Source/croutine.c</location>
</link><link>
<name>FreeRTOS/event_groups.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c</location>
</link><link>
<name>FreeRTOS/list.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/Third_Party/FreeRTOS/Source/list.c</location>
</link><link>
<name>FreeRTOS/queue.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/Third_Party/FreeRTOS/Source/queue.c</location>
</link><link>
<name>FreeRTOS/stream_buffer.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/Third_Party/FreeRTOS/Source/stream_buffer.c</location>
</link><link>
<name>FreeRTOS/tasks.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/Third_Party/FreeRTOS/Source/tasks.c</location>
</link><link>
<name>FreeRTOS/timers.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/Third_Party/FreeRTOS/Source/timers.c</location>
</link><link>
<name>FreeRTOS/cmsis_os2.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c</location>
</link><link>
<name>FreeRTOS/heap_4.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c</location>
</link><link>
<name>FreeRTOS/port.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c</location>
</link><link>
<name>USB_Device_Library/usbd_core.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c</location>
</link><link>
<name>USB_Device_Library/usbd_ctlreq.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c</location>
</link><link>
<name>USB_Device_Library/usbd_ioreq.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c</location>
</link><link>
<name>USB_Device_Library/usbd_cdc.c</name>
<type>1</type>
<location>PARENT-2-PROJECT_LOC/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c</location>
</link></linkedResources>
</projectDescription>

View File

@ -0,0 +1,198 @@
#ifndef __CPP_UTILS_HPP
#define __CPP_UTILS_HPP
/*
## Advanced C++ Topics
This is an overview of some of the more obscure C++ techniques used in this project.
This assumes you're already familiar with templates in C++.
### Template recursion
[TODO]
### Almost perfect template forwarding
This is adapted from https://akrzemi1.wordpress.com/2013/10/10/too-perfect-forwarding/
Suppose you have a inner class, with a couple of constructors:
```
class InnerClass {
public:
InnerClass(int arg1, int arg2);
InnerClass(int arg1);
InnerClass();
};
```
Now you want to create a wrapper class. This wrapper class should provide the exact same constructors as `InnerClass`, so you use perfect forwarding:
```
class WrapperClass {
public:
template<typename ... Args>
WrapperClass(Args&& ... args)
: inner_object(std::forward<Args>(args)...)
{}
InnerClass inner_object;
};
```
Now you can almost use the wrapper class as expected, but only almost:
```
void make_wrappers(void) {
WrapperClass wrapper1; // ok, maps to InnerClass()
WrapperClass wrapper2(1); // ok, maps to InnerClass(int arg1)
WrapperClass wrapper3(1,2); // ok, maps to InnerClass(int arg1, arg2)
WrapperClass wrapper4 = wrapper1; // does not compile
}
```
The last assignment fails. What _you_ obviously wanted, is to use the copy constructor of WrapperClass.
However the compiler will use the perfect forwarding constructor of WrapperClass for this assignment.
So after template expansion it would try to use the following constructor:
```
WrapperClass(InnerClass& arg)
: inner_object(arg)
{}
```
Clearly this is not what we wanted and in this case it will fail because the exists no
constructor of the form `InnerClass(WrapperClass& arg)`.
And thus we need to make the perfect forwarding a little less perfect, by telling it
"only enable this constructor if the first argument of the argument list is not of type WrapperClass".
The modified version thus looks like this:
```
class WrapperClass {
public:
template<typename ... Args, ENABLE_IF(TypeChecker<Args...>::template first_is_not<WrapperClass>())>
WrapperClass(Args&& ... args)
: inner_object(std::forward<Args>(args)...)
{}
InnerClass inner_object;
};
```
*/
// Backport definitions from C++14
#if __cplusplus <= 201103L
namespace std {
template< class T >
using underlying_type_t = typename underlying_type<T>::type;
// source: http://en.cppreference.com/w/cpp/types/enable_if
template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type;
}
#endif
// @brief Supports various queries on a list of types
template<typename ... Ts>
class TypeChecker;
template<typename T, typename ... Ts>
class TypeChecker<T, Ts...>
{
public:
using DecayedT = typename std::decay<T>::type;
// @brief Returns false if type T is equal to U or inherits from U. Returns true otherwise.
template<typename U>
constexpr static inline bool first_is_not()
{
return !std::is_same<DecayedT, U>::value
&& !std::is_base_of<U, DecayedT>::value;
}
// @brief Returns true if all types [T, Ts...] are either equal to U or inherit from U.
template<typename U>
constexpr static inline bool all_are()
{
return std::is_base_of<U, DecayedT>::value
&& TypeChecker<Ts...>::template all_are<U>();
}
};
template<>
class TypeChecker<>
{
public:
template<typename U>
constexpr static inline bool first_is_not()
{
return std::true_type::value;
}
template<typename U>
constexpr static inline bool all_are()
{
return std::true_type::value;
}
};
#include <type_traits>
#define ENABLE_IF(...) \
typename = std::enable_if_t<__VA_ARGS__>
#define ENABLE_IF_SAME(a, b, type) \
template<typename T = a> typename std::enable_if_t<std::is_same<T, b>::value, type>
template<class T, class M>
M get_member_type(M T::*);
#define GET_TYPE_OF(mem) decltype(get_member_type(mem))
//#include <type_traits>
// @brief Statically asserts that T is derived from type BaseType
#define EXPECT_TYPE(T, BaseType) static_assert(std::is_base_of<BaseType, typename std::decay<T>::type>::value || std::is_convertible<typename std::decay<T>::type, BaseType>::value, "expected template argument of type " #BaseType)
//#define EXPECT_TYPE(T, BaseType) static_assert(, "expected template argument of type " #BaseType)
template<typename TObj, typename TRet, typename ... TArgs>
class function_traits
{
public:
template<unsigned IUnpacked, typename ... TUnpackedArgs, ENABLE_IF(IUnpacked != sizeof...(TArgs)) >
static TRet
invoke(TObj &obj, TRet(TObj::*func_ptr)(TArgs...), std::tuple<TArgs...> packed_args, TUnpackedArgs ... args)
{
return invoke<IUnpacked + 1>(obj, func_ptr, packed_args, args..., std::get<IUnpacked>(packed_args));
}
template<unsigned IUnpacked>
static TRet invoke(TObj &obj, TRet(TObj::*func_ptr)(TArgs...), std::tuple<TArgs...> packed_args, TArgs ... args)
{
return (obj.*func_ptr)(args...);
}
};
/* @brief Invoke a class member function with a variable number of arguments that are supplied as a tuple
Example usage:
class MyClass {
public:
int MyFunction(int a, int b) {
return 0;
}
};
MyClass my_object;
std::tuple<int, int> my_args(3, 4); // arguments are supplied as a tuple
int result = invoke_function_with_tuple(my_object, &MyClass::MyFunction, my_args);
*/
template<typename TObj, typename TRet, typename ... TArgs>
TRet invoke_function_with_tuple(TObj &obj, TRet(TObj::*func_ptr)(TArgs...), std::tuple<TArgs...> packed_args)
{
return function_traits<TObj, TRet, TArgs...>::template invoke<0>(obj, func_ptr, packed_args);
}
#endif // __CPP_UTILS_HPP

View File

@ -0,0 +1,65 @@
#ifndef __CRC_HPP
#define __CRC_HPP
#include <stdint.h>
#include <limits.h>
// Calculates an arbitrary CRC for one byte.
// Adapted from https://barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code
template<typename T, unsigned POLYNOMIAL>
static T calc_crc(T remainder, uint8_t value)
{
constexpr T BIT_WIDTH = (CHAR_BIT * sizeof(T));
constexpr T TOPBIT = ((T) 1 << (BIT_WIDTH - 1));
// Bring the next byte into the remainder.
remainder ^= (value << (BIT_WIDTH - 8));
// Perform modulo-2 division, a bit at a time.
for (uint8_t bit = 8; bit; --bit)
{
if (remainder & TOPBIT)
{
remainder = (remainder << 1) ^ POLYNOMIAL;
} else
{
remainder = (remainder << 1);
}
}
return remainder;
}
template<typename T, unsigned POLYNOMIAL>
static T calc_crc(T remainder, const uint8_t *buffer, size_t length)
{
while (length--)
remainder = calc_crc<T, POLYNOMIAL>(remainder, *(buffer++));
return remainder;
}
template<unsigned POLYNOMIAL>
static uint8_t calc_crc8(uint8_t remainder, uint8_t value)
{
return calc_crc<uint8_t, POLYNOMIAL>(remainder, value);
}
template<unsigned POLYNOMIAL>
static uint16_t calc_crc16(uint16_t remainder, uint8_t value)
{
return calc_crc<uint16_t, POLYNOMIAL>(remainder, value);
}
template<unsigned POLYNOMIAL>
static uint8_t calc_crc8(uint8_t remainder, const uint8_t *buffer, size_t length)
{
return calc_crc<uint8_t, POLYNOMIAL>(remainder, buffer, length);
}
template<unsigned POLYNOMIAL>
static uint16_t calc_crc16(uint16_t remainder, const uint8_t *buffer, size_t length)
{
return calc_crc<uint16_t, POLYNOMIAL>(remainder, buffer, length);
}
#endif /* __CRC_HPP */

View File

@ -0,0 +1,405 @@
#ifndef __DECODERS_HPP
#define __DECODERS_HPP
#include "protocol.hpp"
#include "crc.hpp"
#include "cpp_utils.hpp"
#include <utility>
/* Base classes --------------------------------------------------------------*/
// @brief Base class for stream based decoders.
// A stream based decoder is a decoder that processes arbitrary length data blocks.
class StreamDecoder : public StreamSink
{
public:
// @brief Returns 0 if no error ocurred, otherwise a non-zero error code.
// Once process_bytes returned an error, subsequent calls to get_status must return the same error.
// If the decoder is in an error state, the behavior of get_expected_bytes and process_bytes is undefined.
virtual int get_status() = 0;
// @brief Returns the minimum number of bytes that are still needed to complete this decoder.
// If 0, the decoder is considered complete and any subsequent call to process_bytes must process
// exactly 0 bytes.
// process_bytes() must always process all provided bytes unless the decoder expects no more bytes
// afterwards
virtual size_t get_expected_bytes() = 0;
};
// @brief Base class for a decoder that is fed in a block-wise fashion.
// This base class is provided for convenience when implementing certain types of decoders.
// A StreamDecoder can be obtained from a BlockDecoder by using StreamDecoder_from_BlockDecoder.
template<unsigned BLOCKSIZE>
class BlockDecoder
{
public:
typedef std::integral_constant<size_t, BLOCKSIZE> block_size;
virtual int get_status() = 0;
virtual size_t get_expected_blocks() = 0;
virtual int process_block(const uint8_t block[BLOCKSIZE]) = 0;
private:
};
// @brief Base class for a decoder that is fed in a byte-wise fashion
// This base class is provided for convenience when implementing certain types of decoders.
// A StreamDecoder can be obtained from a ByteDecoder by using StreamDecoder_from_ByteDecoder.
class ByteDecoder
{
public:
virtual int get_status() = 0;
virtual size_t get_expected_bytes() = 0;
virtual int process_byte(uint8_t byte) = 0;
};
/* Converter classes ---------------------------------------------------------*/
// @brief Encapsulates a BlockDecoder to make it look like a StreamDecoder
// @tparam T The encapsulated BlockDecoder type.
// Must inherit from BlockDecoder.
template<typename T, ENABLE_IF(TypeChecker<T>::template all_are<BlockDecoder<T::block_size::value>>()) >
class StreamDecoder_from_BlockDecoder : public StreamDecoder
{
public:
// @brief Imitates the constructor signature of the encapsulated type.
template<typename ... Args, ENABLE_IF(
TypeChecker<Args...>::template first_is_not<StreamDecoder_from_BlockDecoder>()) >
explicit StreamDecoder_from_BlockDecoder(Args &&... args)
: block_decoder_(std::forward<Args>(args)...)
{
EXPECT_TYPE(T, BlockDecoder<T::block_size::value>);
}
inline int get_status() final
{
return block_decoder_.get_status();
}
inline size_t get_expected_bytes() final
{
size_t expected_bytes = block_decoder_.get_expected_blocks() * T::block_size::value;
return expected_bytes - std::min(expected_bytes, buffer_pos_);
}
inline int process_bytes(const uint8_t *buffer, size_t length, size_t *processed_bytes) final
{
while (!get_status() && get_expected_bytes() && length)
{
// use the incoming bytes to fill internal buffer to get a complete block
size_t n_copy = std::min(length, T::block_size::value - buffer_pos_);
memcpy(buffer_ + buffer_pos_, buffer, n_copy);
buffer += n_copy;
length -= n_copy;
if (processed_bytes) (*processed_bytes) += n_copy;
buffer_pos_ += n_copy;
// if we have a full block, process it
if (buffer_pos_ == T::block_size::value)
{
block_decoder_.process_block(buffer_);
buffer_pos_ = 0;
}
}
return get_status();
}
size_t get_free_space()
{ return SIZE_MAX; } // TODO: deprecate
private:
T block_decoder_;
size_t buffer_pos_ = 0;
uint8_t buffer_[T::block_size::value];
};
// @brief Encapsulates a ByteDecoder to make it look like a BlockDecoder
// @tparam T The encapsulated ByteDecoder type.
// Must inherit from ByteDecoder.
template<typename T, ENABLE_IF(TypeChecker<T>::template all_are<ByteDecoder>()) >
class BlockDecoder_from_ByteDecoder : public BlockDecoder<1>
{
public:
// @brief Imitates the constructor signature of the encapsulated type.
template<typename ... Args, ENABLE_IF(
TypeChecker<Args...>::template first_is_not<BlockDecoder_from_ByteDecoder>()) >
BlockDecoder_from_ByteDecoder(Args &&... args)
: byte_decoder_(std::forward<Args>(args)...)
{
EXPECT_TYPE(T, ByteDecoder);
}
inline int get_status() final
{
return byte_decoder_.get_status();
}
inline size_t get_expected_blocks() final
{
return byte_decoder_.get_expected_bytes();
}
inline int process_block(const uint8_t block[1]) final
{
int status = byte_decoder_.process_byte(*block);
return status;
}
private:
T byte_decoder_;
};
// @brief Encapsulates a ByteDecoder to make it look like a StreamDecoder
// @tparam T The encapsulated ByteDecoder type.
// Must inherit from ByteDecoder.
template<typename T, ENABLE_IF(TypeChecker<T>::template all_are<ByteDecoder>()) >
class StreamDecoder_from_ByteDecoder : public StreamDecoder
{
public:
// @brief Imitates the constructor signature of the encapsulated type.
template<typename ... Args, ENABLE_IF(
TypeChecker<Args...>::template first_is_not<StreamDecoder_from_ByteDecoder>()) >
StreamDecoder_from_ByteDecoder(Args &&... args)
: byte_decoder_(std::forward<Args>(args)...)
{
EXPECT_TYPE(T, ByteDecoder);
}
inline int get_status() final
{
return byte_decoder_.get_status();
}
inline size_t get_expected_bytes() final
{
return byte_decoder_.get_expected_bytes();
}
inline size_t get_free_space()
{ return SIZE_MAX; }
inline int process_bytes(const uint8_t *buffer, size_t length, size_t *processed_bytes) final
{
while (!byte_decoder_.get_status() && byte_decoder_.get_expected_bytes() && length)
{
length--;
if (processed_bytes) (*processed_bytes)++;
byte_decoder_.process_byte(*(buffer++));
}
return byte_decoder_.get_status();
}
private:
T byte_decoder_;
};
/* Decoder implementations ---------------------------------------------------*/
template<typename T>
class VarintByteDecoder : public ByteDecoder
{
public:
static constexpr T BIT_WIDTH = (CHAR_BIT * sizeof(T));
VarintByteDecoder(T &state_variable) :
state_variable_(state_variable)
{
}
size_t get_expected_bytes() final
{
return done_ ? 0 : 1;
}
int get_status() final
{
return status_;
}
int process_byte(uint8_t input_byte) final
{
if (bit_pos_ == 0)
{
LOG_FIBRE("start decoding varint, with 0x%02x => %zx\n", input_byte, (uintptr_t) &state_variable_);
state_variable_ = 0;
}
LOG_FIBRE("varint: decode %02x << %zu at %zx\n", input_byte, bit_pos_, &bit_pos_);
// we assume bit_pos_ < BIT_WIDTH
state_variable_ |= (static_cast<T>(input_byte & 0x7f) << bit_pos_);
if (((state_variable_ >> bit_pos_) & 0x7f) != static_cast<T>(input_byte & 0x7f))
{
LOG_FIBRE("varint overflow: tried to add %02x << %zu\n", input_byte, bit_pos_);
return (status_ = -1); // overflow
}
bit_pos_ += 7;
done_ = !(input_byte & 0x80);
return (status_ = (done_ || bit_pos_ < BIT_WIDTH) ? 0 : -1);
}
private:
T &state_variable_;
// At all times where status_ != 0 the following statement holds:
// (done_ || bit_pos_ < BIT_WIDTH)
//size_t bit_pos_ = 0; // bit position
size_t bit_pos_ = 0; // bit position
int status_ = 0;
bool done_ = false;
int data[1024] = {0};
};
template<typename T>
using VarintStreamDecoder = StreamDecoder_from_ByteDecoder<VarintByteDecoder<T>>;
// This double nested type should work identically but makes it way harder for the compiler to optimize
//template<typename T>
//using VarintBlockDecoder = BlockDecoder_from_ByteDecoder<VarintByteDecoder<T>>;
//template<typename T>
//using VarintStreamDecoder = StreamDecoder_from_BlockDecoder<VarintBlockDecoder<T>>;
template<typename T>
inline VarintStreamDecoder<T> make_varint_decoder(T &variable)
{
return VarintStreamDecoder<T>(variable);
}
inline VarintStreamDecoder<GET_TYPE_OF(&ReceiverState::endpoint_id)> make_endpoint_id_decoder(ReceiverState &state)
{
return make_varint_decoder(state.endpoint_id);
}
inline VarintStreamDecoder<GET_TYPE_OF(&ReceiverState::length)> make_length_decoder(ReceiverState &state)
{
return make_varint_decoder(state.length);
}
template<uint8_t INIT, uint8_t POLYNOMIAL, typename TDecoder,
ENABLE_IF(TypeChecker<TDecoder>::template all_are<StreamDecoder>()) >
class CRC8BlockDecoder : public BlockDecoder<CRC8_BLOCKSIZE>
{
public:
CRC8BlockDecoder(TDecoder &&inner_decoder) :
inner_decoder_(std::forward<TDecoder>(inner_decoder))
{
}
int get_status() final
{
return status_;
}
size_t get_expected_blocks() final
{
return (inner_decoder_.get_expected_bytes() + CRC8_BLOCKSIZE - 2) / (CRC8_BLOCKSIZE - 1);
}
int process_block(const uint8_t input_block[4]) final
{
current_crc_ = calc_crc8<POLYNOMIAL>(current_crc_, input_block, CRC8_BLOCKSIZE - 1);
if (current_crc_ != input_block[CRC8_BLOCKSIZE - 1])
return status_ = -1;
return status_ = inner_decoder_.process_bytes(input_block, CRC8_BLOCKSIZE - 1, nullptr);
}
private:
TDecoder inner_decoder_;
int status_ = 0;
uint8_t current_crc_ = INIT;
};
template<unsigned INIT, unsigned POLYNOMIAL, typename TDecoder>
using CRC8StreamDecoder = StreamDecoder_from_BlockDecoder<CRC8BlockDecoder<INIT, POLYNOMIAL, TDecoder>>;
template<unsigned INIT, unsigned POLYNOMIAL, typename TDecoder>
inline CRC8StreamDecoder<INIT, POLYNOMIAL, TDecoder> make_crc8_decoder(TDecoder &&decoder)
{
return CRC8StreamDecoder<INIT, POLYNOMIAL, TDecoder>(std::forward<TDecoder>(decoder));
}
// TODO: ENABLE_IF(TypeChecker<TDecoders...>::template all_are<StreamDecoder>())
template<typename ... TDecoders>
class DecoderChain;
template<>
class DecoderChain<> : public StreamDecoder
{
public:
size_t get_expected_bytes()
{ return 0; }
int get_status()
{ return 0; }
int process_bytes(const uint8_t *input, size_t length, size_t *processed_bytes)
{ return 0; }
size_t get_free_space()
{ return SIZE_MAX; } // TODO: deprecate
};
template<typename TDecoder, typename ... TDecoders>
class DecoderChain<TDecoder, TDecoders...> : public StreamDecoder
{
public:
DecoderChain(TDecoder &&this_decoder, TDecoders &&... subsequent_decoders) :
this_decoder_(std::forward<TDecoder>(this_decoder)),
subsequent_decoders_(std::forward<TDecoders>(subsequent_decoders)...)
{
EXPECT_TYPE(TDecoder, StreamDecoder);
}
int get_status() final
{
// If this decoder or any of the subsequent decoders failed, return error code.
int this_status = this_decoder_.get_status();
int subsequent_status = subsequent_decoders_.get_status();
if (this_status)
return this_status;
else if (subsequent_status)
return subsequent_status;
else
return 0;
}
size_t get_expected_bytes() final
{
return this_decoder_.get_expected_bytes() + subsequent_decoders_.get_expected_bytes();
}
int process_bytes(const uint8_t *input, size_t length, size_t *processed_bytes) final
{
if (this_decoder_.get_expected_bytes())
{
LOG_FIBRE("decoder chain: process %zu bytes in segment %s\n", length, typeid(TDecoder).name());
size_t chunk = 0;
int status = this_decoder_.process_bytes(input, length, &chunk);
input += chunk;
length -= chunk;
if (processed_bytes) (*processed_bytes) += chunk;
if (status)
return status;
if (!length)
return 0;
}
return subsequent_decoders_.process_bytes(input, length, processed_bytes);
}
size_t get_free_space()
{ return SIZE_MAX; } // TODO: deprecate
private:
TDecoder this_decoder_;
DecoderChain<TDecoders...> subsequent_decoders_;
};
template<typename ... TDecoders>
inline DecoderChain<TDecoders...> make_decoder_chain(TDecoders &&... decoders)
{
return DecoderChain<TDecoders...>(std::forward<TDecoders>(decoders)...);
}
#endif // __DECODERS_HPP

View File

@ -0,0 +1,388 @@
#ifndef __ENCODERS_HPP
#define __ENCODERS_HPP
#include "protocol.hpp"
#include "crc.hpp"
#include "cpp_utils.hpp"
#include <utility>
struct Request
{
endpoint_id_t endpoint_id;
size_t length;
};
/* Base classes --------------------------------------------------------------*/
// @brief Base class for all stream encoders
// A stream based encoder is an encoder that generates arbitrary length data blocks.
class StreamEncoder : public StreamSource
{
public:
// @brief Returns 0 if no error ocurred, otherwise a non-zero error code.
// Once get_bytes returned an error, subsequent calls to get_status must return the same error.
// If the encoder is in an error state, the behavior of get_available_bytes and get_bytes is undefined.
virtual int get_status() = 0;
// @brief Returns the minimum number of bytes that will still be generated by this encoder.
// If 0, the encoder is considered complete and any subsequent call to get_bytes must generate
// exactly 0 bytes.
// get_bytes() must always generate as many bytes as requested unless the encoder generates no more bytes
// afterwards
virtual size_t get_available_bytes() = 0;
};
// @brief Base class for an encoder that is fed in a block-wise fashion.
// This base class is provided for convenience when implementing certain types of encoders.
// A StreamEncoder can be obtained from a BlockEncoder by using StreamEncoder_from_BlockEncoder.
template<unsigned BLOCKSIZE>
class BlockEncoder
{
public:
typedef std::integral_constant<size_t, BLOCKSIZE> block_size;
virtual int get_status() = 0;
virtual size_t get_available_blocks() = 0;
virtual int get_block(uint8_t block[BLOCKSIZE]) = 0;
private:
};
// @brief Base class for an encoder that is fed in a byte-wise fashion
// This base class is provided for convenience when implementing certain types of encoders.
// A StreamEncoder can be obtained from a ByteEncoder by using StreamEncoder_from_ByteEncoder.
class ByteEncoder
{
public:
virtual int get_status() = 0;
virtual size_t get_available_bytes() = 0;
virtual int get_byte(uint8_t *output_byte) = 0;
};
/* Converter classes ---------------------------------------------------------*/
// @brief Encapsulates a BlockEncoder to make it look like a StreamEncoder
// @tparam T The encapsulated BlockEncoder type.
// Must inherit from to BlockEncoder.
template<typename T, ENABLE_IF(TypeChecker<T>::template all_are<BlockEncoder<T::block_size::value>>()) >
class StreamEncoder_from_BlockEncoder : public StreamEncoder
{
public:
// @brief Imitates the constructor signature of the encapsulated type.
template<typename ... Args, ENABLE_IF(
TypeChecker<Args...>::template first_is_not<StreamEncoder_from_BlockEncoder>()) >
explicit StreamEncoder_from_BlockEncoder(Args &&... args)
: block_encoder_(std::forward<Args>(args)...)
{
EXPECT_TYPE(T, BlockEncoder<T::block_size::value>);
}
inline int get_status() final
{
return buffered_bytes_ ? 0 : block_encoder_.get_status();
}
inline size_t get_available_bytes() final
{
size_t available_bytes = block_encoder_.get_available_blocks() * T::block_size::value;
return available_bytes + buffered_bytes_;
}
inline int get_bytes(uint8_t *buffer, size_t length, size_t *generated_bytes) final
{
while (!get_status() && get_available_bytes() && length)
{
// if the buffer is empty, retrieve a new block from the encode
if (!buffered_bytes_)
{
block_encoder_.get_block(buffer_);
buffered_bytes_ = T::block_size::value;
}
// hand the buffered bytes to the encoder
size_t n_copy = std::min(buffered_bytes_, length);
memcpy(buffer, buffer_ + T::block_size::value - n_copy, n_copy);
length -= n_copy;
buffer += n_copy;
if (generated_bytes) (*generated_bytes) += n_copy;
buffered_bytes_ -= n_copy;
}
return get_status();
}
private:
T block_encoder_;
size_t buffered_bytes_ = 0;
uint8_t buffer_[T::block_size::value];
};
// @brief Encapsulates a ByteEncoder to make it look like a BlockEncoder
// @tparam T The encapsulated ByteEncoder type.
// Must inherit from ByteEncoder.
template<typename T, ENABLE_IF(TypeChecker<T>::template all_are<ByteEncoder>()) >
class BlockEncoder_from_ByteEncoder : public BlockEncoder<1>
{
public:
// @brief Imitates the constructor signature of the encapsulated type.
template<typename ... Args, ENABLE_IF(
TypeChecker<Args...>::template first_is_not<BlockEncoder_from_ByteEncoder>()) >
BlockEncoder_from_ByteEncoder(Args &&... args)
: byte_encoder_(std::forward<Args>(args)...)
{
EXPECT_TYPE(T, ByteEncoder);
}
inline int get_status() final
{
return byte_encoder_.get_status();
}
inline size_t get_available_blocks() final
{
return byte_encoder_.get_available_bytes();
}
inline int get_block(uint8_t block[1]) final
{
int status = byte_encoder_.get_byte(*block);
return status;
}
private:
T byte_encoder_;
};
// @brief Encapsulates a ByteEncoder to make it look like a StreamEncoder
// @tparam T The encapsulated ByteEncoder type.
// Must inherit from ByteEncoder.
template<typename T, ENABLE_IF(TypeChecker<T>::template all_are<ByteEncoder>()) >
class StreamEncoder_from_ByteEncoder : public StreamEncoder
{
public:
// @brief Imitates the constructor signature of the encapsulated type.
template<typename ... Args, ENABLE_IF(
TypeChecker<Args...>::template first_is_not<StreamEncoder_from_ByteEncoder>()) >
StreamEncoder_from_ByteEncoder(Args &&... args)
: byte_encoder_(std::forward<Args>(args)...)
{
EXPECT_TYPE(T, ByteEncoder);
}
inline int get_status() final
{
return byte_encoder_.get_status();
}
inline size_t get_available_bytes() final
{
return byte_encoder_.get_available_bytes();
}
inline int get_bytes(uint8_t *buffer, size_t length, size_t *generated_bytes) final
{
while (!byte_encoder_.get_status() && byte_encoder_.get_available_bytes() && length)
{
length--;
if (generated_bytes) (*generated_bytes)++;
byte_encoder_.get_byte(buffer++);
}
return byte_encoder_.get_status();
}
private:
T byte_encoder_;
};
/* Encoder implementations ---------------------------------------------------*/
template<typename T>
class VarintByteEncoder : public ByteEncoder
{
public:
static constexpr T BIT_WIDTH = (CHAR_BIT * sizeof(T));
VarintByteEncoder(const T &state_variable) :
state_variable_(state_variable)
{}
size_t get_available_bytes() final
{
return done_ ? 0 : 1;
}
int get_status() final
{
return 0;
}
int get_byte(uint8_t *output_byte) final
{
if (bit_pos_ == 0)
LOG_FIBRE("start encoding varint, from pos %d\n", bit_pos_);
*output_byte = (state_variable_ >> bit_pos_) & 0x7f;
bit_pos_ += 7;
if (bit_pos_ < BIT_WIDTH && (state_variable_ >> bit_pos_))
{
LOG_FIBRE("remainder: %x\n", state_variable_ >> bit_pos_);
*output_byte |= 0x80;
} else
done_ = true;
return 0;
}
private:
const T &state_variable_;
size_t bit_pos_ = 0; // bit position
int status_ = 0;
bool done_ = false;
};
template<typename T>
using VarintStreamEncoder = StreamEncoder_from_ByteEncoder<VarintByteEncoder<T>>;
template<typename T>
VarintStreamEncoder<T> make_varint_encoder(const T &variable)
{
return VarintStreamEncoder<T>(variable);
}
VarintStreamEncoder<GET_TYPE_OF(&Request::endpoint_id)> make_endpoint_id_encoder(const Request &request)
{
return make_varint_encoder(request.endpoint_id);
}
VarintStreamEncoder<GET_TYPE_OF(&Request::length)> make_length_encoder(const Request &request)
{
return make_varint_encoder(request.length);
}
template<uint8_t INIT, uint8_t POLYNOMIAL, typename TEncoder,
ENABLE_IF(TypeChecker<TEncoder>::template all_are<StreamEncoder>()) >
class CRC8BlockEncoder : public BlockEncoder<CRC8_BLOCKSIZE>
{
public:
CRC8BlockEncoder(TEncoder &&inner_encoder)
: inner_encoder_(std::forward<TEncoder>(inner_encoder))
{}
int get_status() final
{
return status_;
}
size_t get_available_blocks() final
{
return (inner_encoder_.get_available_bytes() + CRC8_BLOCKSIZE - 2) / (CRC8_BLOCKSIZE - 1);
}
int get_block(uint8_t block[4]) final
{
size_t generated_bytes = 0;
status_ = inner_encoder_.get_bytes(block, CRC8_BLOCKSIZE - 1, &generated_bytes);
if (status_)
return status_;
// zero out unused end of the block
while (generated_bytes < CRC8_BLOCKSIZE)
block[generated_bytes++] = 0;
block[CRC8_BLOCKSIZE - 1] = current_crc_ = calc_crc8<POLYNOMIAL>(current_crc_, block, CRC8_BLOCKSIZE - 1);
return 0;
}
private:
TEncoder inner_encoder_;
int status_ = 0;
uint8_t current_crc_ = INIT;
};
template<unsigned INIT, unsigned POLYNOMIAL, typename TEncoder>
using CRC8StreamEncoder = StreamEncoder_from_BlockEncoder<CRC8BlockEncoder<INIT, POLYNOMIAL, TEncoder>>;
template<unsigned INIT, unsigned POLYNOMIAL, typename TEncoder>
CRC8StreamEncoder<INIT, POLYNOMIAL, TEncoder> make_crc8_encoder(TEncoder &&encoder)
{
return CRC8StreamEncoder<INIT, POLYNOMIAL, TEncoder>(std::forward<TEncoder>(encoder));
}
template<typename ... TEncoders>
class EncoderChain;
template<>
class EncoderChain<> : public StreamEncoder
{
public:
size_t get_available_bytes() final
{ return 0; }
int get_status() final
{ return 0; }
int get_bytes(uint8_t *output, size_t length, size_t *generated_bytes) final
{ return 0; }
};
template<typename TEncoder, typename ... TEncoders>
class EncoderChain<TEncoder, TEncoders...> : public StreamEncoder
{
public:
EncoderChain(TEncoder &&this_encoder, TEncoders &&... subsequent_encoders) :
this_encoder_(std::forward<TEncoder>(this_encoder)),
subsequent_encoders_(std::forward<TEncoders>(subsequent_encoders)...)
{
EXPECT_TYPE(TEncoder, StreamEncoder);
}
size_t get_available_bytes() final
{
return this_encoder_.get_available_bytes() + subsequent_encoders_.get_available_bytes();
}
int get_status() final
{
// If this encoder or any of the subsequent encoders failed, return error code.
int this_status = this_encoder_.get_status();
int subsequent_status = subsequent_encoders_.get_status();
if (this_status)
return this_status;
else if (subsequent_status)
return subsequent_status;
else
return 0;
}
int get_bytes(uint8_t *output, size_t length, size_t *generated_bytes) final
{
if (this_encoder_.get_available_bytes())
{
LOG_FIBRE("encoder chain: generate %zu bytes in segment %s\n", length, typeid(TEncoder).name());
size_t chunk = 0;
int status = this_encoder_.get_bytes(output, length, &chunk);
if (status)
return status;
output += chunk;
length -= chunk;
if (generated_bytes) *generated_bytes += chunk;
if (!length)
return 0;
}
return subsequent_encoders_.get_bytes(output, length, generated_bytes);
}
private:
TEncoder this_encoder_;
EncoderChain<TEncoders...> subsequent_encoders_;
};
template<typename ... TEncoders>
EncoderChain<TEncoders...> make_encoder_chain(TEncoders &&... encoders)
{
return EncoderChain<TEncoders...>(std::forward<TEncoders>(encoders)...);
}
#endif // __ENCODERS_HPP

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
tup.include('../tupfiles/build.lua')
fibre_package = define_package{
sources={'protocol.cpp', 'posix_tcp.cpp', 'posix_udp.cpp'},
libs={'pthread'},
headers={'include'}
}

View File

@ -0,0 +1,227 @@
/* Includes ------------------------------------------------------------------*/
#include <memory>
#include <stdlib.h>
#include <fibre/protocol.hpp>
#include <fibre/crc.hpp>
/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Global constant data ------------------------------------------------------*/
/* Global variables ----------------------------------------------------------*/
Endpoint** endpoint_list_ = nullptr; // initialized by calling fibre_publish
size_t n_endpoints_ = 0; // initialized by calling fibre_publish
uint16_t json_crc_; // initialized by calling fibre_publish
JSONDescriptorEndpoint json_file_endpoint_ = JSONDescriptorEndpoint();
EndpointProvider* application_endpoints_;
/* Private constant data -----------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void hexdump(const uint8_t* buf, size_t len);
static inline int write_string(const char* str, StreamSink* output);
/* Function implementations --------------------------------------------------*/
#if 0
void hexdump(const uint8_t* buf, size_t len) {
for (size_t pos = 0; pos < len; ++pos) {
printf(" %02x", buf[pos]);
if ((((pos + 1) % 16) == 0) || ((pos + 1) == len))
printf("\r\n");
osDelay(2);
}
}
#else
void hexdump(const uint8_t* buf, size_t len) {
(void) buf;
(void) len;
}
#endif
int StreamToPacketSegmenter::process_bytes(const uint8_t *buffer, size_t length, size_t* processed_bytes) {
int result = 0;
while (length--) {
if (header_index_ < sizeof(header_buffer_)) {
// Process header byte
header_buffer_[header_index_++] = *buffer;
if (header_index_ == 1 && header_buffer_[0] != CANONICAL_PREFIX) {
header_index_ = 0;
} else if (header_index_ == 2 && (header_buffer_[1] & 0x80)) {
header_index_ = 0; // TODO: support packets larger than 128 bytes
} else if (header_index_ == 3 && calc_crc8<CANONICAL_CRC8_POLYNOMIAL>(CANONICAL_CRC8_INIT, header_buffer_, 3)) {
header_index_ = 0;
} else if (header_index_ == 3) {
packet_length_ = header_buffer_[1] + 2;
}
} else if (packet_index_ < sizeof(packet_buffer_)) {
// Process payload byte
packet_buffer_[packet_index_++] = *buffer;
}
// If both header and packet are fully received, hand it on to the packet processor
if (header_index_ == 3 && packet_index_ == packet_length_) {
if (calc_crc16<CANONICAL_CRC16_POLYNOMIAL>(CANONICAL_CRC16_INIT, packet_buffer_, packet_length_) == 0) {
result |= output_.process_packet(packet_buffer_, packet_length_ - 2);
}
header_index_ = packet_index_ = packet_length_ = 0;
}
buffer++;
if (processed_bytes)
(*processed_bytes)++;
}
return result;
}
int StreamBasedPacketSink::process_packet(const uint8_t *buffer, size_t length) {
// TODO: support buffer size >= 128
if (length >= 128)
return -1;
LOG_FIBRE("send header\r\n");
uint8_t header[] = {
CANONICAL_PREFIX,
static_cast<uint8_t>(length),
0
};
header[2] = calc_crc8<CANONICAL_CRC8_POLYNOMIAL>(CANONICAL_CRC8_INIT, header, 2);
if (output_.process_bytes(header, sizeof(header), nullptr))
return -1;
LOG_FIBRE("send payload:\r\n");
hexdump(buffer, length);
if (output_.process_bytes(buffer, length, nullptr))
return -1;
LOG_FIBRE("send crc16\r\n");
uint16_t crc16 = calc_crc16<CANONICAL_CRC16_POLYNOMIAL>(CANONICAL_CRC16_INIT, buffer, length);
uint8_t crc16_buffer[] = {
(uint8_t)((crc16 >> 8) & 0xff),
(uint8_t)((crc16 >> 0) & 0xff)
};
if (output_.process_bytes(crc16_buffer, 2, nullptr))
return -1;
LOG_FIBRE("sent!\r\n");
return 0;
}
void JSONDescriptorEndpoint::write_json(size_t id, StreamSink* output) {
write_string("{\"name\":\"\",", output);
// write endpoint ID
write_string("\"id\":", output);
char id_buf[10];
snprintf(id_buf, sizeof(id_buf), "%u", (unsigned)id); // TODO: get rid of printf
write_string(id_buf, output);
write_string(",\"type\":\"json\",\"access\":\"r\"}", output);
}
void JSONDescriptorEndpoint::register_endpoints(Endpoint** list, size_t id, size_t length) {
if (id < length)
list[id] = this;
}
// Returns part of the JSON interface definition.
void JSONDescriptorEndpoint::handle(const uint8_t* input, size_t input_length, StreamSink* output) {
// The request must contain a 32 bit integer to specify an offset
if (input_length < 4)
return;
uint32_t offset = 0;
read_le<uint32_t>(&offset, input);
NullStreamSink output_with_offset = NullStreamSink(offset, *output);
size_t id = 0;
write_string("[", &output_with_offset);
json_file_endpoint_.write_json(id, &output_with_offset);
id += decltype(json_file_endpoint_)::endpoint_count;
write_string(",", &output_with_offset);
application_endpoints_->write_json(id, &output_with_offset);
write_string("]", &output_with_offset);
}
int BidirectionalPacketBasedChannel::process_packet(const uint8_t* buffer, size_t length) {
LOG_FIBRE("got packet of length %d: \r\n", length);
hexdump(buffer, length);
if (length < 4)
return -1;
uint16_t seq_no = read_le<uint16_t>(&buffer, &length);
if (seq_no & 0x8000) {
// TODO: ack handling
} else {
// TODO: think about some kind of ordering guarantees
// currently the seq_no is just used to associate a response with a request
uint16_t endpoint_id = read_le<uint16_t>(&buffer, &length);
bool expect_response = endpoint_id & 0x8000;
endpoint_id &= 0x7fff;
if (endpoint_id >= n_endpoints_)
return -1;
Endpoint* endpoint = endpoint_list_[endpoint_id];
if (!endpoint) {
LOG_FIBRE("critical: no endpoint at %d", endpoint_id);
return -1;
}
// Verify packet trailer. The expected trailer value depends on the selected endpoint.
// For endpoint 0 this is just the protocol version, for all other endpoints it's a
// CRC over the entire JSON descriptor tree (this may change in future versions).
uint16_t expected_trailer = endpoint_id ? json_crc_ : PROTOCOL_VERSION;
uint16_t actual_trailer = buffer[length - 2] | (buffer[length - 1] << 8);
if (expected_trailer != actual_trailer) {
LOG_FIBRE("trailer mismatch for endpoint %d: expected %04x, got %04x\r\n", endpoint_id, expected_trailer, actual_trailer);
return -1;
}
LOG_FIBRE("trailer ok for endpoint %d\r\n", endpoint_id);
// TODO: if more bytes than the MTU were requested, should we abort or just return as much as possible?
uint16_t expected_response_length = read_le<uint16_t>(&buffer, &length);
// Limit response length according to our local TX buffer size
if (expected_response_length > sizeof(tx_buf_) - 2)
expected_response_length = sizeof(tx_buf_) - 2;
MemoryStreamSink output(tx_buf_ + 2, expected_response_length);
endpoint->handle(buffer, length - 2, &output);
// Send response
if (expect_response) {
size_t actual_response_length = expected_response_length - output.get_free_space() + 2;
write_le<uint16_t>(seq_no | 0x8000, tx_buf_);
LOG_FIBRE("send packet:\r\n");
hexdump(tx_buf_, actual_response_length);
output_.process_packet(tx_buf_, actual_response_length);
}
}
return 0;
}
bool is_endpoint_ref_valid(endpoint_ref_t endpoint_ref) {
return (endpoint_ref.json_crc == json_crc_)
&& (endpoint_ref.endpoint_id < n_endpoints_);
}
Endpoint* get_endpoint(endpoint_ref_t endpoint_ref) {
if (is_endpoint_ref_valid(endpoint_ref))
return endpoint_list_[endpoint_ref.endpoint_id];
else
return nullptr;
}

View File

@ -0,0 +1,361 @@
/*
Print.cpp - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
Modified December 2014 by Ivan Grokhotkov
Modified May 2015 by Michael C. Miller - ESP31B progmem support
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <cstdarg>
#include "Print.h"
extern "C" {
#include "time.h"
}
// Public Methods //////////////////////////////////////////////////////////////
/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
size_t n = 0;
while(size--) {
n += write(*buffer++);
}
return n;
}
size_t Print::printf(const char *format, ...)
{
char loc_buf[64];
char * temp = loc_buf;
va_list arg;
va_list copy;
va_start(arg, format);
va_copy(copy, arg);
int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
va_end(copy);
if(len < 0) {
va_end(arg);
return 0;
};
if(len >= sizeof(loc_buf)){
temp = (char*) malloc(len+1);
if(temp == NULL) {
va_end(arg);
return 0;
}
len = vsnprintf(temp, len+1, format, arg);
}
va_end(arg);
len = write((uint8_t*)temp, len);
if(temp != loc_buf){
free(temp);
}
return len;
}
size_t Print::print(const __FlashStringHelper *ifsh)
{
return print(reinterpret_cast<const char *>(ifsh));
}
size_t Print::print(const String &s)
{
return write(s.c_str(), s.length());
}
size_t Print::print(const char str[])
{
return write(str);
}
size_t Print::print(char c)
{
return write(c);
}
size_t Print::print(unsigned char b, int base)
{
return print((unsigned long) b, base);
}
size_t Print::print(int n, int base)
{
return print((long) n, base);
}
size_t Print::print(unsigned int n, int base)
{
return print((unsigned long) n, base);
}
size_t Print::print(long n, int base)
{
int t = 0;
if (base == 10 && n < 0) {
t = print('-');
n = -n;
}
return printNumber(static_cast<unsigned long>(n), base) + t;
}
size_t Print::print(unsigned long n, int base)
{
if(base == 0) {
return write(n);
} else {
return printNumber(n, base);
}
}
size_t Print::print(long long n, int base)
{
int t = 0;
if (base == 10 && n < 0) {
t = print('-');
n = -n;
}
return printNumber(static_cast<unsigned long long>(n), base) + t;
}
size_t Print::print(unsigned long long n, int base)
{
if (base == 0) {
return write(n);
} else {
return printNumber(n, base);
}
}
size_t Print::print(double n, int digits)
{
return printFloat(n, digits);
}
size_t Print::println(const __FlashStringHelper *ifsh)
{
size_t n = print(ifsh);
n += println();
return n;
}
size_t Print::print(const Printable& x)
{
return x.printTo(*this);
}
size_t Print::println(void)
{
return print("\r\n");
}
size_t Print::println(const String &s)
{
size_t n = print(s);
n += println();
return n;
}
size_t Print::println(const char c[])
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(char c)
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(unsigned char b, int base)
{
size_t n = print(b, base);
n += println();
return n;
}
size_t Print::println(int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(long long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned long long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(double num, int digits)
{
size_t n = print(num, digits);
n += println();
return n;
}
size_t Print::println(const Printable& x)
{
size_t n = print(x);
n += println();
return n;
}
size_t Print::println(struct tm * timeinfo, const char * format)
{
size_t n = print(timeinfo, format);
n += println();
return n;
}
// Private Methods /////////////////////////////////////////////////////////////
size_t Print::printNumber(unsigned long n, uint8_t base)
{
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
char *str = &buf[sizeof(buf) - 1];
*str = '\0';
// prevent crash if called with base == 1
if(base < 2) {
base = 10;
}
do {
char c = n % base;
n /= base;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while (n);
return write(str);
}
size_t Print::printNumber(unsigned long long n, uint8_t base)
{
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
char* str = &buf[sizeof(buf) - 1];
*str = '\0';
// prevent crash if called with base == 1
if (base < 2) {
base = 10;
}
do {
auto m = n;
n /= base;
char c = m - base * n;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while (n);
return write(str);
}
size_t Print::printFloat(double number, uint8_t digits)
{
size_t n = 0;
if(isnan(number)) {
return print("nan");
}
if(isinf(number)) {
return print("inf");
}
if(number > 4294967040.0) {
return print("ovf"); // constant determined empirically
}
if(number < -4294967040.0) {
return print("ovf"); // constant determined empirically
}
// Handle negative numbers
if(number < 0.0) {
n += print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for(uint8_t i = 0; i < digits; ++i) {
rounding /= 10.0;
}
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long) number;
double remainder = number - (double) int_part;
n += print(int_part);
// Print the decimal point, but only if there are digits beyond
if(digits > 0) {
n += print(".");
}
// Extract digits from the remainder one at a time
while(digits-- > 0) {
remainder *= 10.0;
int toPrint = int(remainder);
n += print(toPrint);
remainder -= toPrint;
}
return n;
}

View File

@ -0,0 +1,113 @@
/*
Print.h - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Print_h
#define Print_h
#include <stdint.h>
#include <stddef.h>
#include "WString.h"
#include "Printable.h"
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
class Print
{
private:
int write_error;
size_t printNumber(unsigned long, uint8_t);
size_t printNumber(unsigned long long, uint8_t);
size_t printFloat(double, uint8_t);
protected:
void setWriteError(int err = 1)
{
write_error = err;
}
public:
Print() :
write_error(0)
{
}
virtual ~Print() {}
int getWriteError()
{
return write_error;
}
void clearWriteError()
{
setWriteError(0);
}
virtual size_t write(uint8_t) = 0;
size_t write(const char *str)
{
if(str == NULL) {
return 0;
}
return write((const uint8_t *) str, strlen(str));
}
virtual size_t write(const uint8_t *buffer, size_t size);
size_t write(const char *buffer, size_t size)
{
return write((const uint8_t *) buffer, size);
}
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
// add availableForWrite to make compatible with Arduino Print.h
// default to zero, meaning "a single write may block"
// should be overriden by subclasses with buffering
virtual int availableForWrite() { return 0; }
size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(long long, int = DEC);
size_t print(unsigned long long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
size_t print(struct tm * timeinfo, const char * format = NULL);
size_t println(const __FlashStringHelper *);
size_t println(const String &s);
size_t println(const char[]);
size_t println(char);
size_t println(unsigned char, int = DEC);
size_t println(int, int = DEC);
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(long long, int = DEC);
size_t println(unsigned long long, int = DEC);
size_t println(double, int = 2);
size_t println(const Printable&);
size_t println(struct tm * timeinfo, const char * format = NULL);
size_t println(void);
};
#endif

View File

@ -0,0 +1,41 @@
/*
Printable.h - Interface class that allows printing of complex types
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Printable_h
#define Printable_h
#include <stdlib.h>
class Print;
/** The Printable class provides a way for new classes to allow themselves to be printed.
By deriving from Printable and implementing the printTo method, it will then be possible
for users to print out instances of this class by passing them into the usual
Print::print and Print::println methods.
*/
class Printable
{
public:
virtual ~Printable() {}
virtual size_t printTo(Print& p) const = 0;
};
#endif

View File

@ -0,0 +1,595 @@
#ifndef U8G2LIB_HH
#define U8G2LIB_HH
#include <Print.h>
#include "U8x8lib.h"
#include "u8g2.h"
#include "soft_i2c.h"
extern I2C_HandleTypeDef *U8G2_I2C_HANDLE;
extern SPI_HandleTypeDef *U8G2_SPI_HANDLE;
class U8G2 : public Print
{
protected:
u8g2_t u8g2;
u8x8_char_cb cpp_next_cb; /* the cpp interface has its own decoding function for the Arduino print command */
public:
u8g2_uint_t tx, ty;
U8G2(void)
{
cpp_next_cb = u8x8_ascii_next;
home();
}
u8x8_t *getU8x8(void)
{ return u8g2_GetU8x8(&u8g2); }
u8g2_t *getU8g2(void)
{ return &u8g2; }
void sendF(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
u8x8_cad_vsendf(u8g2_GetU8x8(&u8g2), fmt, va);
va_end(va);
}
uint32_t getBusClock(void)
{ return u8g2_GetU8x8(&u8g2)->bus_clock; }
void setBusClock(uint32_t clock_speed)
{ u8g2_GetU8x8(&u8g2)->bus_clock = clock_speed; }
void setI2CAddress(uint8_t adr)
{ u8g2_SetI2CAddress(&u8g2, adr); }
void enableUTF8Print(void)
{ cpp_next_cb = u8x8_utf8_next; }
void disableUTF8Print(void)
{ cpp_next_cb = u8x8_ascii_next; }
/* u8x8 interface */
uint8_t getCols(void)
{ return u8x8_GetCols(u8g2_GetU8x8(&u8g2)); }
uint8_t getRows(void)
{ return u8x8_GetRows(u8g2_GetU8x8(&u8g2)); }
void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr)
{
u8x8_DrawTile(u8g2_GetU8x8(&u8g2), x, y, cnt, tile_ptr);
}
/* return 0 for no event or U8X8_MSG_GPIO_MENU_SELECT, */
/* U8X8_MSG_GPIO_MENU_NEXT, U8X8_MSG_GPIO_MENU_PREV, */
/* U8X8_MSG_GPIO_MENU_HOME */
uint8_t getMenuEvent(void)
{ return u8x8_GetMenuEvent(u8g2_GetU8x8(&u8g2)); }
void initDisplay(void)
{
u8g2_InitDisplay(&u8g2);
}
void clearDisplay(void)
{
u8g2_ClearDisplay(&u8g2);
}
void setPowerSave(uint8_t is_enable)
{
u8g2_SetPowerSave(&u8g2, is_enable);
}
void setFlipMode(uint8_t mode)
{
u8g2_SetFlipMode(&u8g2, mode);
}
void setContrast(uint8_t value)
{
u8g2_SetContrast(&u8g2, value);
}
void setDisplayRotation(const u8g2_cb_t *u8g2_cb)
{
u8g2_SetDisplayRotation(&u8g2, u8g2_cb);
}
bool Init()
{
if (U8G2_I2C_HANDLE->Instance == I2C_SOFT)
Soft_I2C_Init();
/* note: call to u8x8_utf8_init is not required here, this is done in the setup procedures before */
setPowerSave(1);
initDisplay();
clearDisplay();
clearBuffer();
setPowerSave(0);
return 1;
}
void beginSimple()
{
/* does not clear the display and does not wake up the display */
/* user is responsible for calling clearDisplay() and setPowerSave(0) */
initDisplay();
}
/* u8g2 */
#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT
void setMaxClipWindow()
{ u8g2_SetMaxClipWindow(&u8g2); }
void setClipWindow(u8g2_uint_t clip_x0, u8g2_uint_t clip_y0, u8g2_uint_t clip_x1, u8g2_uint_t clip_y1)
{
u8g2_SetClipWindow(&u8g2, clip_x0, clip_y0, clip_x1, clip_y1);
}
#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */
u8g2_uint_t getDisplayHeight(void)
{ return u8g2_GetDisplayHeight(&u8g2); }
u8g2_uint_t getDisplayWidth(void)
{ return u8g2_GetDisplayWidth(&u8g2); }
/* u8g2_buffer.c */
void sendBuffer(void)
{ u8g2_SendBuffer(&u8g2); }
void clearBuffer(void)
{ u8g2_ClearBuffer(&u8g2); }
void firstPage(void)
{ u8g2_FirstPage(&u8g2); }
uint8_t nextPage(void)
{ return u8g2_NextPage(&u8g2); }
uint8_t *getBufferPtr(void)
{ return u8g2_GetBufferPtr(&u8g2); }
uint8_t getBufferTileHeight(void)
{ return u8g2_GetBufferTileHeight(&u8g2); }
uint8_t getBufferTileWidth(void)
{ return u8g2_GetBufferTileWidth(&u8g2); }
uint8_t getPageCurrTileRow(void)
{ return u8g2_GetBufferCurrTileRow(&u8g2); } // obsolete
void setPageCurrTileRow(uint8_t row)
{ u8g2_SetBufferCurrTileRow(&u8g2, row); } // obsolete
uint8_t getBufferCurrTileRow(void)
{ return u8g2_GetBufferCurrTileRow(&u8g2); }
void setBufferCurrTileRow(uint8_t row)
{ u8g2_SetBufferCurrTileRow(&u8g2, row); }
// this should be renamed to setBufferAutoClear
void setAutoPageClear(uint8_t mode)
{ u8g2_SetAutoPageClear(&u8g2, mode); }
void updateDisplayArea(uint8_t tx, uint8_t ty, uint8_t tw, uint8_t th)
{ u8g2_UpdateDisplayArea(&u8g2, tx, ty, tw, th); }
void updateDisplay(void)
{ u8g2_UpdateDisplay(&u8g2); }
void refreshDisplay(void)
{ u8x8_RefreshDisplay(u8g2_GetU8x8(&u8g2)); }
/* clib/u8g2.hvline.c */
void setDrawColor(uint8_t color_index)
{ u8g2_SetDrawColor(&u8g2, color_index); }
uint8_t getDrawColor(void)
{ return u8g2_GetDrawColor(&u8g2); }
void drawPixel(u8g2_uint_t x, u8g2_uint_t y)
{ u8g2_DrawPixel(&u8g2, x, y); }
void drawHLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w)
{ u8g2_DrawHLine(&u8g2, x, y, w); }
void drawVLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t h)
{ u8g2_DrawVLine(&u8g2, x, y, h); }
void drawHVLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_DrawHVLine(&u8g2, x, y, len, dir);
}
/* u8g2_box.c */
void drawFrame(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
{ u8g2_DrawFrame(&u8g2, x, y, w, h); }
void drawRFrame(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)
{ u8g2_DrawRFrame(&u8g2, x, y, w, h, r); }
void drawBox(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
{ u8g2_DrawBox(&u8g2, x, y, w, h); }
void drawRBox(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)
{ u8g2_DrawRBox(&u8g2, x, y, w, h, r); }
/* u8g2_circle.c */
void drawCircle(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t opt = U8G2_DRAW_ALL)
{ u8g2_DrawCircle(&u8g2, x0, y0, rad, opt); }
void drawDisc(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t opt = U8G2_DRAW_ALL)
{ u8g2_DrawDisc(&u8g2, x0, y0, rad, opt); }
void drawEllipse(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t opt = U8G2_DRAW_ALL)
{ u8g2_DrawEllipse(&u8g2, x0, y0, rx, ry, opt); }
void drawFilledEllipse(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t opt = U8G2_DRAW_ALL)
{ u8g2_DrawFilledEllipse(&u8g2, x0, y0, rx, ry, opt); }
/* u8g2_line.c */
void drawLine(u8g2_uint_t x1, u8g2_uint_t y1, u8g2_uint_t x2, u8g2_uint_t y2)
{ u8g2_DrawLine(&u8g2, x1, y1, x2, y2); }
/* u8g2_bitmap.c */
void setBitmapMode(uint8_t is_transparent)
{ u8g2_SetBitmapMode(&u8g2, is_transparent); }
void drawBitmap(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t cnt, u8g2_uint_t h, const uint8_t *bitmap)
{ u8g2_DrawBitmap(&u8g2, x, y, cnt, h, bitmap); }
void drawXBM(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap)
{ u8g2_DrawXBM(&u8g2, x, y, w, h, bitmap); }
void drawXBMP(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap)
{ u8g2_DrawXBMP(&u8g2, x, y, w, h, bitmap); }
/* u8g2_polygon.c */
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
{ u8g2_DrawTriangle(&u8g2, x0, y0, x1, y1, x2, y2); }
/* u8log_u8g2.c */
void drawLog(u8g2_uint_t x, u8g2_uint_t y, class U8G2LOG &u8g2log);
/* u8g2_font.c */
void setFont(const uint8_t *font)
{ u8g2_SetFont(&u8g2, font); }
void setFontMode(uint8_t is_transparent)
{ u8g2_SetFontMode(&u8g2, is_transparent); }
void setFontDirection(uint8_t dir)
{ u8g2_SetFontDirection(&u8g2, dir); }
int8_t getAscent(void)
{ return u8g2_GetAscent(&u8g2); }
int8_t getDescent(void)
{ return u8g2_GetDescent(&u8g2); }
void setFontPosBaseline(void)
{ u8g2_SetFontPosBaseline(&u8g2); }
void setFontPosBottom(void)
{ u8g2_SetFontPosBottom(&u8g2); }
void setFontPosTop(void)
{ u8g2_SetFontPosTop(&u8g2); }
void setFontPosCenter(void)
{ u8g2_SetFontPosCenter(&u8g2); }
void setFontRefHeightText(void)
{ u8g2_SetFontRefHeightText(&u8g2); }
void setFontRefHeightExtendedText(void)
{ u8g2_SetFontRefHeightExtendedText(&u8g2); }
void setFontRefHeightAll(void)
{ u8g2_SetFontRefHeightAll(&u8g2); }
/*
uint8_t u8g2_IsGlyph(u8g2_t *u8g2, uint16_t requested_encoding);
int8_t u8g2_GetGlyphWidth(u8g2_t *u8g2, uint16_t requested_encoding);
u8g2_uint_t u8g2_GetStrWidth(u8g2_t *u8g2, const char *s);
u8g2_uint_t u8g2_GetUTF8Width(u8g2_t *u8g2, const char *str);
*/
u8g2_uint_t drawGlyph(u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding)
{ return u8g2_DrawGlyph(&u8g2, x, y, encoding); }
u8g2_uint_t drawStr(u8g2_uint_t x, u8g2_uint_t y, const char *s)
{ return u8g2_DrawStr(&u8g2, x, y, s); }
u8g2_uint_t drawUTF8(u8g2_uint_t x, u8g2_uint_t y, const char *s)
{ return u8g2_DrawUTF8(&u8g2, x, y, s); }
u8g2_uint_t drawExtUTF8(u8g2_uint_t x, u8g2_uint_t y, uint8_t to_left, const uint16_t *kerning_table, const char *s)
{ return u8g2_DrawExtUTF8(&u8g2, x, y, to_left, kerning_table, s); }
u8g2_uint_t getStrWidth(const char *s)
{ return u8g2_GetStrWidth(&u8g2, s); }
u8g2_uint_t getUTF8Width(const char *s)
{ return u8g2_GetUTF8Width(&u8g2, s); }
// not required any more, enable UTF8 for print
//void printUTF8(const char *s) { tx += u8g2_DrawUTF8(&u8g2, tx, ty, s); }
/* screenshot functions for full buffer mode */
/* vertical top lsb memory architecture */
void writeBufferPBM(Print &p);
void writeBufferXBM(Print &p);
/* horizontal right lsb memory architecture */
/* SH1122, LD7032, ST7920, ST7986, LC7981, T6963, SED1330, RA8835, MAX7219, LS0 */
void writeBufferPBM2(Print &p);
void writeBufferXBM2(Print &p);
/* virtual function for print base class */
size_t write(uint8_t v)
{
uint16_t e = cpp_next_cb(&(u8g2.u8x8), v);
if (e < 0x0fffe)
{
u8g2_uint_t delta = u8g2_DrawGlyph(&u8g2, tx, ty, e);
#ifdef U8G2_WITH_FONT_ROTATION
switch (u8g2.font_decode.dir)
{
case 0:
tx += delta;
break;
case 1:
ty += delta;
break;
case 2:
tx -= delta;
break;
case 3:
ty -= delta;
break;
}
// requires 10 bytes more on avr
//tx = u8g2_add_vector_x(tx, delta, 0, u8g2.font_decode.dir);
//ty = u8g2_add_vector_y(ty, delta, 0, u8g2.font_decode.dir);
#else
tx += delta;
#endif
}
return 1;
}
size_t write(const uint8_t *buffer, size_t size)
{
size_t cnt = 0;
while (size > 0)
{
cnt += write(*buffer++);
size--;
}
return cnt;
}
/* user interface */
/*
uint8_t u8g2_UserInterfaceSelectionList(u8g2_t *u8g2, const char *title, uint8_t start_pos, const char *sl);
uint8_t u8g2_UserInterfaceMessage(u8g2_t *u8g2, const char *title1, const char *title2, const char *title3, const char *buttons);
uint8_t u8g2_UserInterfaceInputValue(u8g2_t *u8g2, const char *title, const char *pre, uint8_t *value, uint8_t lo, uint8_t hi, uint8_t digits, const char *post);
*/
uint8_t userInterfaceSelectionList(const char *title, uint8_t start_pos, const char *sl)
{
return u8g2_UserInterfaceSelectionList(&u8g2, title, start_pos, sl);
}
uint8_t userInterfaceMessage(const char *title1, const char *title2, const char *title3, const char *buttons)
{
return u8g2_UserInterfaceMessage(&u8g2, title1, title2, title3, buttons);
}
uint8_t
userInterfaceInputValue(const char *title, const char *pre, uint8_t *value, uint8_t lo, uint8_t hi, uint8_t digits,
const char *post)
{
return u8g2_UserInterfaceInputValue(&u8g2, title, pre, value, lo, hi, digits, post);
}
/* LiquidCrystal compatible functions */
void home(void)
{
tx = 0;
ty = 0;
u8x8_utf8_init(u8g2_GetU8x8(&u8g2));
}
void clear(void)
{
home();
clearDisplay();
clearBuffer();
}
void noDisplay(void)
{ u8g2_SetPowerSave(&u8g2, 1); }
void display(void)
{ u8g2_SetPowerSave(&u8g2, 0); }
void setCursor(u8g2_uint_t x, u8g2_uint_t y)
{
tx = x;
ty = y;
}
/* u8glib compatible functions */
void sleepOn(void)
{ u8g2_SetPowerSave(&u8g2, 1); }
void sleepOff(void)
{ u8g2_SetPowerSave(&u8g2, 0); }
void setColorIndex(uint8_t color_index)
{ u8g2_SetDrawColor(&u8g2, color_index); }
uint8_t getColorIndex(void)
{ return u8g2_GetDrawColor(&u8g2); }
int8_t getFontAscent(void)
{ return u8g2_GetAscent(&u8g2); }
int8_t getFontDescent(void)
{ return u8g2_GetDescent(&u8g2); }
int8_t getMaxCharHeight(void)
{ return u8g2_GetMaxCharHeight(&u8g2); }
int8_t getMaxCharWidth(void)
{ return u8g2_GetMaxCharWidth(&u8g2); }
u8g2_uint_t getHeight()
{ return u8g2_GetDisplayHeight(&u8g2); }
u8g2_uint_t getWidth()
{ return u8g2_GetDisplayWidth(&u8g2); }
};
void u8g2_print_callback(const char *s); /* U8g2lib.cpp */
class U8G2LOG : public Print
{
public:
u8log_t u8log;
/* the constructor does nothing, use begin() instead */
U8G2LOG(void)
{}
/* connect to u8g2, draw to u8g2 whenever required */
bool begin(class U8G2 &u8g2, uint8_t width, uint8_t height, uint8_t *buf)
{
u8log_Init(&u8log, width, height, buf);
u8log_SetCallback(&u8log, u8log_u8g2_cb, u8g2.getU8g2());
return true;
}
/* disconnected version, manual redraw required */
bool begin(uint8_t width, uint8_t height, uint8_t *buf)
{
u8log_Init(&u8log, width, height, buf);
return true;
}
void setLineHeightOffset(int8_t line_height_offset)
{
u8log_SetLineHeightOffset(&u8log, line_height_offset);
}
void setRedrawMode(uint8_t is_redraw_line_for_each_char)
{
u8log_SetRedrawMode(&u8log, is_redraw_line_for_each_char);
}
/* virtual function for print base class */
size_t write(uint8_t v)
{
u8log_WriteChar(&u8log, v);
return 1;
}
size_t write(const uint8_t *buffer, size_t size)
{
size_t cnt = 0;
while (size > 0)
{
cnt += write(*buffer++);
size--;
}
return cnt;
}
void writeString(const char *s)
{ u8log_WriteString(&u8log, s); }
void writeChar(uint8_t c)
{ u8log_WriteChar(&u8log, c); }
void writeHex8(uint8_t b)
{ u8log_WriteHex8(&u8log, b); }
void writeHex16(uint16_t v)
{ u8log_WriteHex16(&u8log, v); }
void writeHex32(uint32_t v)
{ u8log_WriteHex32(&u8log, v); }
void writeDec8(uint8_t v, uint8_t d)
{ u8log_WriteDec8(&u8log, v, d); }
void writeDec16(uint8_t v, uint8_t d)
{ u8log_WriteDec16(&u8log, v, d); }
};
/* u8log_u8g2.c */
inline void U8G2::drawLog(u8g2_uint_t x, u8g2_uint_t y, class U8G2LOG &u8g2log)
{
u8g2_DrawLog(&u8g2, x, y, &(u8g2log.u8log));
}
class U8G2_BITMAP : public U8G2
{
public:
U8G2_BITMAP(uint16_t pixel_width, uint16_t pixel_height, const u8g2_cb_t *rotation)
{
u8g2_SetupBitmap(getU8g2(), rotation, pixel_width, pixel_height);
}
// This completely resets various settings, such as the
// font, so be sure to re-initialize things
void changeSize(uint16_t pixel_width, uint16_t pixel_height)
{
u8g2_SetupBitmap(getU8g2(), getU8g2()->cb, pixel_width, pixel_height);
}
};
class SSD1306 : public U8G2
{
private:
public:
explicit SSD1306(I2C_HandleTypeDef *_hi2c, const u8g2_cb_t *rotation = U8G2_R3) : U8G2()
{
U8G2_I2C_HANDLE = _hi2c;
u8g2_Setup_ssd1306_i2c_128x80_noname_f(&u8g2, rotation, u8x8_byte_stm32_hw_i2c, u8x8_stm32_gpio_and_delay);
}
};
#endif /* _U8G2LIB_HH */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,327 @@
#ifndef U8X8LIB_HH
#define U8X8LIB_HH
#include <Print.h>
#include "u8x8.h"
#define U8X8_HAVE_HW_I2C
/* Exported variables --------------------------------------------------------*/
extern "C" uint8_t u8x8_byte_stm32_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
extern "C" uint8_t u8x8_stm32_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, U8X8_UNUSED void *arg_ptr);
class U8X8 : public Print
{
protected:
u8x8_t u8x8;
public:
uint8_t tx, ty;
U8X8(void)
{ home(); }
u8x8_t *getU8x8(void)
{ return &u8x8; }
void sendF(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
u8x8_cad_vsendf(&u8x8, fmt, va);
va_end(va);
}
uint32_t getBusClock(void)
{ return u8x8.bus_clock; }
void setBusClock(uint32_t clock_speed)
{ u8x8.bus_clock = clock_speed; }
void setI2CAddress(uint8_t adr)
{ u8x8_SetI2CAddress(&u8x8, adr); }
uint8_t getCols(void)
{ return u8x8_GetCols(&u8x8); }
uint8_t getRows(void)
{ return u8x8_GetRows(&u8x8); }
void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr)
{
u8x8_DrawTile(&u8x8, x, y, cnt, tile_ptr);
}
void initDisplay(void)
{
u8x8_InitDisplay(&u8x8);
}
void clearDisplay(void)
{
u8x8_ClearDisplay(&u8x8);
}
void fillDisplay(void)
{
u8x8_FillDisplay(&u8x8);
}
void setPowerSave(uint8_t is_enable)
{
u8x8_SetPowerSave(&u8x8, is_enable);
}
bool begin(void)
{
initDisplay();
clearDisplay();
setPowerSave(0);
return 1;
}
void setFlipMode(uint8_t mode)
{
u8x8_SetFlipMode(&u8x8, mode);
}
void refreshDisplay(void)
{ // Dec 16: Only required for SSD1606
u8x8_RefreshDisplay(&u8x8);
}
void clearLine(uint8_t line)
{
u8x8_ClearLine(&u8x8, line);
}
void setContrast(uint8_t value)
{
u8x8_SetContrast(&u8x8, value);
}
void setInverseFont(uint8_t value)
{
u8x8_SetInverseFont(&u8x8, value);
}
void setFont(const uint8_t *font_8x8)
{
u8x8_SetFont(&u8x8, font_8x8);
}
void drawGlyph(uint8_t x, uint8_t y, uint8_t encoding)
{
u8x8_DrawGlyph(&u8x8, x, y, encoding);
}
void draw2x2Glyph(uint8_t x, uint8_t y, uint8_t encoding)
{
u8x8_Draw2x2Glyph(&u8x8, x, y, encoding);
}
void draw1x2Glyph(uint8_t x, uint8_t y, uint8_t encoding)
{
u8x8_Draw1x2Glyph(&u8x8, x, y, encoding);
}
void drawString(uint8_t x, uint8_t y, const char *s)
{
u8x8_DrawString(&u8x8, x, y, s);
}
void drawUTF8(uint8_t x, uint8_t y, const char *s)
{
u8x8_DrawUTF8(&u8x8, x, y, s);
}
void draw2x2String(uint8_t x, uint8_t y, const char *s)
{
u8x8_Draw2x2String(&u8x8, x, y, s);
}
void draw1x2String(uint8_t x, uint8_t y, const char *s)
{
u8x8_Draw1x2String(&u8x8, x, y, s);
}
void draw2x2UTF8(uint8_t x, uint8_t y, const char *s)
{
u8x8_Draw2x2UTF8(&u8x8, x, y, s);
}
void draw1x2UTF8(uint8_t x, uint8_t y, const char *s)
{
u8x8_Draw1x2UTF8(&u8x8, x, y, s);
}
uint8_t getUTF8Len(const char *s)
{
return u8x8_GetUTF8Len(&u8x8, s);
}
size_t write(uint8_t v);
/* code extended and moved to .cpp file, issue 74
size_t write(uint8_t v) {
u8x8_DrawGlyph(&u8x8, tx, ty, v);
tx++;
return 1;
}
*/
size_t write(const uint8_t *buffer, size_t size)
{
size_t cnt = 0;
while (size > 0)
{
cnt += write(*buffer++);
size--;
}
return cnt;
}
void inverse(void)
{ setInverseFont(1); }
void noInverse(void)
{ setInverseFont(0); }
/* return 0 for no event or U8X8_MSG_GPIO_MENU_SELECT, */
/* U8X8_MSG_GPIO_MENU_NEXT, U8X8_MSG_GPIO_MENU_PREV, */
/* U8X8_MSG_GPIO_MENU_HOME */
uint8_t getMenuEvent(void)
{ return u8x8_GetMenuEvent(&u8x8); }
uint8_t userInterfaceSelectionList(const char *title, uint8_t start_pos, const char *sl)
{
return u8x8_UserInterfaceSelectionList(&u8x8, title, start_pos, sl);
}
uint8_t userInterfaceMessage(const char *title1, const char *title2, const char *title3, const char *buttons)
{
return u8x8_UserInterfaceMessage(&u8x8, title1, title2, title3, buttons);
}
uint8_t
userInterfaceInputValue(const char *title, const char *pre, uint8_t *value, uint8_t lo, uint8_t hi, uint8_t digits,
const char *post)
{
return u8x8_UserInterfaceInputValue(&u8x8, title, pre, value, lo, hi, digits, post);
}
/* LiquidCrystal compatible functions */
void home(void)
{
tx = 0;
ty = 0;
}
void clear(void)
{
clearDisplay();
home();
}
void noDisplay(void)
{ u8x8_SetPowerSave(&u8x8, 1); }
void display(void)
{ u8x8_SetPowerSave(&u8x8, 0); }
void setCursor(uint8_t x, uint8_t y)
{
tx = x;
ty = y;
}
void drawLog(uint8_t x, uint8_t y, class U8X8LOG &u8x8log);
};
class U8X8LOG : public Print
{
public:
u8log_t u8log;
/* the constructor does nothing, use begin() instead */
U8X8LOG(void)
{}
/* connect to u8g2, draw to u8g2 whenever required */
bool begin(class U8X8 &u8x8, uint8_t width, uint8_t height, uint8_t *buf)
{
u8log_Init(&u8log, width, height, buf);
u8log_SetCallback(&u8log, u8log_u8x8_cb, u8x8.getU8x8());
return true;
}
/* disconnected version, manual redraw required */
bool begin(uint8_t width, uint8_t height, uint8_t *buf)
{
u8log_Init(&u8log, width, height, buf);
return true;
}
void setLineHeightOffset(int8_t line_height_offset)
{
u8log_SetLineHeightOffset(&u8log, line_height_offset);
}
void setRedrawMode(uint8_t is_redraw_line_for_each_char)
{
u8log_SetRedrawMode(&u8log, is_redraw_line_for_each_char);
}
/* virtual function for print base class */
size_t write(uint8_t v)
{
u8log_WriteChar(&u8log, v);
return 1;
}
size_t write(const uint8_t *buffer, size_t size)
{
size_t cnt = 0;
while (size > 0)
{
cnt += write(*buffer++);
size--;
}
return cnt;
}
void writeString(const char *s)
{ u8log_WriteString(&u8log, s); }
void writeChar(uint8_t c)
{ u8log_WriteChar(&u8log, c); }
void writeHex8(uint8_t b)
{ u8log_WriteHex8(&u8log, b); }
void writeHex16(uint16_t v)
{ u8log_WriteHex16(&u8log, v); }
void writeHex32(uint32_t v)
{ u8log_WriteHex32(&u8log, v); }
void writeDec8(uint8_t v, uint8_t d)
{ u8log_WriteDec8(&u8log, v, d); }
void writeDec16(uint8_t v, uint8_t d)
{ u8log_WriteDec16(&u8log, v, d); }
};
/* u8log_u8x8.c */
inline void U8X8::drawLog(uint8_t x, uint8_t y, class U8X8LOG &u8x8log)
{
u8x8_DrawLog(&u8x8, x, y, &(u8x8log.u8log));
}
#endif /* _U8X8LIB_HH */

View File

@ -0,0 +1,864 @@
/*
WString.cpp - String library for Wiring & Arduino
...mostly rewritten by Paul Stoffregen...
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
Copyright 2011, Paul Stoffregen, paul@pjrc.com
Modified by Ivan Grokhotkov, 2014 - esp8266 support
Modified by Michael C. Miller, 2015 - esp8266 progmem support
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <cstdio>
#include "WString.h"
#include "stdlib_noniso.h"
#include "pgmspace.h"
/*********************************************/
/* Constructors */
/*********************************************/
String::String(const char *cstr) {
init();
if (cstr)
copy(cstr, strlen(cstr));
}
String::String(const String &value) {
init();
*this = value;
}
String::String(const __FlashStringHelper *pstr) {
init();
*this = pstr; // see operator =
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String::String(String &&rval) {
init();
move(rval);
}
String::String(StringSumHelper &&rval) {
init();
move(rval);
}
#endif
String::String(char c) {
init();
char buf[2];
buf[0] = c;
buf[1] = 0;
*this = buf;
}
String::String(unsigned char value, unsigned char base) {
init();
char buf[1 + 8 * sizeof(unsigned char)];
utoa(value, buf, base);
*this = buf;
}
String::String(int value, unsigned char base) {
init();
char buf[2 + 8 * sizeof(int)];
if (base == 10) {
sprintf(buf, "%d", value);
} else {
itoa(value, buf, base);
}
*this = buf;
}
String::String(unsigned int value, unsigned char base) {
init();
char buf[1 + 8 * sizeof(unsigned int)];
utoa(value, buf, base);
*this = buf;
}
String::String(long value, unsigned char base) {
init();
char buf[2 + 8 * sizeof(long)];
if (base==10) {
sprintf(buf, "%ld", value);
} else {
ltoa(value, buf, base);
}
*this = buf;
}
String::String(unsigned long value, unsigned char base) {
init();
char buf[1 + 8 * sizeof(unsigned long)];
ultoa(value, buf, base);
*this = buf;
}
String::String(float value, unsigned char decimalPlaces) {
init();
char buf[33];
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}
String::String(double value, unsigned char decimalPlaces) {
init();
char buf[33];
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}
String::~String() {
invalidate();
}
// /*********************************************/
// /* Memory Management */
// /*********************************************/
inline void String::init(void) {
setSSO(false);
setBuffer(nullptr);
setCapacity(0);
setLen(0);
}
void String::invalidate(void) {
if(!isSSO() && wbuffer())
free(wbuffer());
init();
}
unsigned char String::reserve(unsigned int size) {
if(buffer() && capacity() >= size)
return 1;
if(changeBuffer(size)) {
if(len() == 0)
wbuffer()[0] = 0;
return 1;
}
return 0;
}
unsigned char String::changeBuffer(unsigned int maxStrLen) {
// Can we use SSO here to avoid allocation?
if (maxStrLen < sizeof(sso.buff) - 1) {
if (isSSO() || !buffer()) {
// Already using SSO, nothing to do
uint16_t oldLen = len();
setSSO(true);
setLen(oldLen);
return 1;
} else { // if bufptr && !isSSO()
// Using bufptr, need to shrink into sso.buff
char temp[sizeof(sso.buff)];
memcpy(temp, buffer(), maxStrLen);
free(wbuffer());
uint16_t oldLen = len();
setSSO(true);
memcpy(wbuffer(), temp, maxStrLen);
setLen(oldLen);
return 1;
}
}
// Fallthrough to normal allocator
size_t newSize = (maxStrLen + 16) & (~0xf);
// Make sure we can fit newsize in the buffer
if (newSize > CAPACITY_MAX) {
return false;
}
uint16_t oldLen = len();
char *newbuffer = (char *) realloc(isSSO() ? nullptr : wbuffer(), newSize);
if (newbuffer) {
size_t oldSize = capacity() + 1; // include NULL.
if (isSSO()) {
// Copy the SSO buffer into allocated space
memmove(newbuffer, sso.buff, sizeof(sso.buff));
}
if (newSize > oldSize)
{
memset(newbuffer + oldSize, 0, newSize - oldSize);
}
setSSO(false);
setCapacity(newSize - 1);
setBuffer(newbuffer);
setLen(oldLen); // Needed in case of SSO where len() never existed
return 1;
}
return 0;
}
// /*********************************************/
// /* Copy and Move */
// /*********************************************/
String & String::copy(const char *cstr, unsigned int length) {
if(!reserve(length)) {
invalidate();
return *this;
}
memmove(wbuffer(), cstr, length + 1);
setLen(length);
return *this;
}
String & String::copy(const __FlashStringHelper *pstr, unsigned int length) {
if (!reserve(length)) {
invalidate();
return *this;
}
memcpy_P(wbuffer(), (PGM_P)pstr, length + 1); // We know wbuffer() cannot ever be in PROGMEM, so memcpy safe here
setLen(length);
return *this;
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
void String::move(String &rhs) {
if(buffer()) {
if(capacity() >= rhs.len()) {
memmove(wbuffer(), rhs.buffer(), rhs.length() + 1);
setLen(rhs.len());
rhs.invalidate();
return;
} else {
if (!isSSO()) {
free(wbuffer());
setBuffer(nullptr);
}
}
}
if (rhs.isSSO()) {
setSSO(true);
memmove(sso.buff, rhs.sso.buff, sizeof(sso.buff));
} else {
setSSO(false);
setBuffer(rhs.wbuffer());
}
setCapacity(rhs.capacity());
setLen(rhs.len());
rhs.setSSO(false);
rhs.setCapacity(0);
rhs.setBuffer(nullptr);
rhs.setLen(0);
}
#endif
String & String::operator =(const String &rhs) {
if(this == &rhs)
return *this;
if(rhs.buffer())
copy(rhs.buffer(), rhs.len());
else
invalidate();
return *this;
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String & String::operator =(String &&rval) {
if(this != &rval)
move(rval);
return *this;
}
String & String::operator =(StringSumHelper &&rval) {
if(this != &rval)
move(rval);
return *this;
}
#endif
String & String::operator =(const char *cstr) {
if(cstr)
copy(cstr, strlen(cstr));
else
invalidate();
return *this;
}
String & String::operator = (const __FlashStringHelper *pstr)
{
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
else invalidate();
return *this;
}
// /*********************************************/
// /* concat */
// /*********************************************/
unsigned char String::concat(const String &s) {
// Special case if we're concatting ourself (s += s;) since we may end up
// realloc'ing the buffer and moving s.buffer in the method called
if (&s == this) {
unsigned int newlen = 2 * len();
if (!s.buffer())
return 0;
if (s.len() == 0)
return 1;
if (!reserve(newlen))
return 0;
memmove(wbuffer() + len(), buffer(), len());
setLen(newlen);
wbuffer()[len()] = 0;
return 1;
} else {
return concat(s.buffer(), s.len());
}
}
unsigned char String::concat(const char *cstr, unsigned int length) {
unsigned int newlen = len() + length;
if(!cstr)
return 0;
if(length == 0)
return 1;
if(!reserve(newlen))
return 0;
if (cstr >= wbuffer() && cstr < wbuffer() + len())
// compatible with SSO in ram #6155 (case "x += x.c_str()")
memmove(wbuffer() + len(), cstr, length + 1);
else
// compatible with source in flash #6367
memcpy_P(wbuffer() + len(), cstr, length + 1);
setLen(newlen);
return 1;
}
unsigned char String::concat(const char *cstr) {
if(!cstr)
return 0;
return concat(cstr, strlen(cstr));
}
unsigned char String::concat(char c) {
char buf[2];
buf[0] = c;
buf[1] = 0;
return concat(buf, 1);
}
unsigned char String::concat(unsigned char num) {
char buf[1 + 3 * sizeof(unsigned char)];
sprintf(buf, "%d", num);
return concat(buf, strlen(buf));
}
unsigned char String::concat(int num) {
char buf[2 + 3 * sizeof(int)];
sprintf(buf, "%d", num);
return concat(buf, strlen(buf));
}
unsigned char String::concat(unsigned int num) {
char buf[1 + 3 * sizeof(unsigned int)];
utoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(long num) {
char buf[2 + 3 * sizeof(long)];
sprintf(buf, "%ld", num);
return concat(buf, strlen(buf));
}
unsigned char String::concat(unsigned long num) {
char buf[1 + 3 * sizeof(unsigned long)];
ultoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(float num) {
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
unsigned char String::concat(double num) {
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
unsigned char String::concat(const __FlashStringHelper * str) {
if (!str) return 0;
int length = strlen_P((PGM_P)str);
if (length == 0) return 1;
unsigned int newlen = len() + length;
if (!reserve(newlen)) return 0;
memcpy_P(wbuffer() + len(), (PGM_P)str, length + 1);
setLen(newlen);
return 1;
}
/*********************************************/
/* Concatenate */
/*********************************************/
StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs) {
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if(!a.concat(rhs.buffer(), rhs.len()))
a.invalidate();
return a;
}
StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr) {
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if(!cstr || !a.concat(cstr, strlen(cstr)))
a.invalidate();
return a;
}
StringSumHelper & operator +(const StringSumHelper &lhs, char c) {
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if(!a.concat(c))
a.invalidate();
return a;
}
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num) {
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if(!a.concat(num))
a.invalidate();
return a;
}
StringSumHelper & operator +(const StringSumHelper &lhs, int num) {
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if(!a.concat(num))
a.invalidate();
return a;
}
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num) {
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if(!a.concat(num))
a.invalidate();
return a;
}
StringSumHelper & operator +(const StringSumHelper &lhs, long num) {
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if(!a.concat(num))
a.invalidate();
return a;
}
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num) {
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if(!a.concat(num))
a.invalidate();
return a;
}
StringSumHelper & operator +(const StringSumHelper &lhs, float num) {
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if(!a.concat(num))
a.invalidate();
return a;
}
StringSumHelper & operator +(const StringSumHelper &lhs, double num) {
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if(!a.concat(num))
a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(rhs))
a.invalidate();
return a;
}
// /*********************************************/
// /* Comparison */
// /*********************************************/
int String::compareTo(const String &s) const {
if(!buffer() || !s.buffer()) {
if(s.buffer() && s.len() > 0)
return 0 - *(unsigned char *) s.buffer();
if(buffer() && len() > 0)
return *(unsigned char *) buffer();
return 0;
}
return strcmp(buffer(), s.buffer());
}
unsigned char String::equals(const String &s2) const {
return (len() == s2.len() && compareTo(s2) == 0);
}
unsigned char String::equals(const char *cstr) const {
if(len() == 0)
return (cstr == NULL || *cstr == 0);
if(cstr == NULL)
return buffer()[0] == 0;
return strcmp(buffer(), cstr) == 0;
}
unsigned char String::operator<(const String &rhs) const {
return compareTo(rhs) < 0;
}
unsigned char String::operator>(const String &rhs) const {
return compareTo(rhs) > 0;
}
unsigned char String::operator<=(const String &rhs) const {
return compareTo(rhs) <= 0;
}
unsigned char String::operator>=(const String &rhs) const {
return compareTo(rhs) >= 0;
}
unsigned char String::equalsIgnoreCase(const String &s2) const {
if(this == &s2)
return 1;
if(len() != s2.len())
return 0;
if(len() == 0)
return 1;
const char *p1 = buffer();
const char *p2 = s2.buffer();
while(*p1) {
if(tolower(*p1++) != tolower(*p2++))
return 0;
}
return 1;
}
unsigned char String::equalsConstantTime(const String &s2) const {
// To avoid possible time-based attacks present function
// compares given strings in a constant time.
if(len() != s2.len())
return 0;
//at this point lengths are the same
if(len() == 0)
return 1;
//at this point lenghts are the same and non-zero
const char *p1 = buffer();
const char *p2 = s2.buffer();
unsigned int equalchars = 0;
unsigned int diffchars = 0;
while(*p1) {
if(*p1 == *p2)
++equalchars;
else
++diffchars;
++p1;
++p2;
}
//the following should force a constant time eval of the condition without a compiler "logical shortcut"
unsigned char equalcond = (equalchars == len());
unsigned char diffcond = (diffchars == 0);
return (equalcond & diffcond); //bitwise AND
}
unsigned char String::startsWith(const String &s2) const {
if(len() < s2.len())
return 0;
return startsWith(s2, 0);
}
unsigned char String::startsWith(const String &s2, unsigned int offset) const {
if(offset > (unsigned)(len() - s2.len()) || !buffer() || !s2.buffer())
return 0;
return strncmp(&buffer()[offset], s2.buffer(), s2.len()) == 0;
}
unsigned char String::endsWith(const String &s2) const {
if(len() < s2.len() || !buffer() || !s2.buffer())
return 0;
return strcmp(&buffer()[len() - s2.len()], s2.buffer()) == 0;
}
// /*********************************************/
// /* Character Access */
// /*********************************************/
char String::charAt(unsigned int loc) const {
return operator[](loc);
}
void String::setCharAt(unsigned int loc, char c) {
if(loc < len())
wbuffer()[loc] = c;
}
char & String::operator[](unsigned int index) {
static char dummy_writable_char;
if(index >= len() || !buffer()) {
dummy_writable_char = 0;
return dummy_writable_char;
}
return wbuffer()[index];
}
char String::operator[](unsigned int index) const {
if(index >= len() || !buffer())
return 0;
return buffer()[index];
}
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const {
if(!bufsize || !buf)
return;
if(index >= len()) {
buf[0] = 0;
return;
}
unsigned int n = bufsize - 1;
if(n > len() - index)
n = len() - index;
strncpy((char *) buf, buffer() + index, n);
buf[n] = 0;
}
// /*********************************************/
// /* Search */
// /*********************************************/
int String::indexOf(char c) const {
return indexOf(c, 0);
}
int String::indexOf(char ch, unsigned int fromIndex) const {
if(fromIndex >= len())
return -1;
const char* temp = strchr(buffer() + fromIndex, ch);
if(temp == NULL)
return -1;
return temp - buffer();
}
int String::indexOf(const String &s2) const {
return indexOf(s2, 0);
}
int String::indexOf(const String &s2, unsigned int fromIndex) const {
if(fromIndex >= len())
return -1;
const char *found = strstr(buffer() + fromIndex, s2.buffer());
if(found == NULL)
return -1;
return found - buffer();
}
int String::lastIndexOf(char theChar) const {
return lastIndexOf(theChar, len() - 1);
}
int String::lastIndexOf(char ch, unsigned int fromIndex) const {
if(fromIndex >= len())
return -1;
char tempchar = buffer()[fromIndex + 1];
wbuffer()[fromIndex + 1] = '\0';
char* temp = strrchr(wbuffer(), ch);
wbuffer()[fromIndex + 1] = tempchar;
if(temp == NULL)
return -1;
return temp - buffer();
}
int String::lastIndexOf(const String &s2) const {
return lastIndexOf(s2, len() - s2.len());
}
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const {
if(s2.len() == 0 || len() == 0 || s2.len() > len())
return -1;
if(fromIndex >= len())
fromIndex = len() - 1;
int found = -1;
for(char *p = wbuffer(); p <= wbuffer() + fromIndex; p++) {
p = strstr(p, s2.buffer());
if(!p)
break;
if((unsigned int) (p - wbuffer()) <= fromIndex)
found = p - buffer();
}
return found;
}
String String::substring(unsigned int left, unsigned int right) const {
if(left > right) {
unsigned int temp = right;
right = left;
left = temp;
}
String out;
if(left >= len())
return out;
if(right > len())
right = len();
char temp = buffer()[right]; // save the replaced character
wbuffer()[right] = '\0';
out = wbuffer() + left; // pointer arithmetic
wbuffer()[right] = temp; //restore character
return out;
}
// /*********************************************/
// /* Modification */
// /*********************************************/
void String::replace(char find, char replace) {
if(!buffer())
return;
for(char *p = wbuffer(); *p; p++) {
if(*p == find)
*p = replace;
}
}
void String::replace(const String& find, const String& replace) {
if(len() == 0 || find.len() == 0)
return;
int diff = replace.len() - find.len();
char *readFrom = wbuffer();
char *foundAt;
if(diff == 0) {
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
memmove(foundAt, replace.buffer(), replace.len());
readFrom = foundAt + replace.len();
}
} else if(diff < 0) {
char *writeTo = wbuffer();
unsigned int l = len();
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
unsigned int n = foundAt - readFrom;
memmove(writeTo, readFrom, n);
writeTo += n;
memmove(writeTo, replace.buffer(), replace.len());
writeTo += replace.len();
readFrom = foundAt + find.len();
l += diff;
}
memmove(writeTo, readFrom, strlen(readFrom)+1);
setLen(l);
} else {
unsigned int size = len(); // compute size needed for result
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
readFrom = foundAt + find.len();
size += diff;
}
if(size == len())
return;
if(size > capacity() && !changeBuffer(size))
return; // XXX: tell user!
int index = len() - 1;
while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
readFrom = wbuffer() + index + find.len();
memmove(readFrom + diff, readFrom, len() - (readFrom - buffer()));
int newLen = len() + diff;
memmove(wbuffer() + index, replace.buffer(), replace.len());
setLen(newLen);
wbuffer()[newLen] = 0;
index--;
}
}
}
void String::remove(unsigned int index) {
// Pass the biggest integer as the count. The remove method
// below will take care of truncating it at the end of the
// string.
remove(index, (unsigned int) -1);
}
void String::remove(unsigned int index, unsigned int count) {
if(index >= len()) {
return;
}
if(count <= 0) {
return;
}
if(count > len() - index) {
count = len() - index;
}
char *writeTo = wbuffer() + index;
unsigned int newlen = len() - count;
memmove(writeTo, wbuffer() + index + count, newlen - index);
setLen(newlen);
wbuffer()[newlen] = 0;
}
void String::toLowerCase(void) {
if(!buffer())
return;
for(char *p = wbuffer(); *p; p++) {
*p = tolower(*p);
}
}
void String::toUpperCase(void) {
if(!buffer())
return;
for(char *p = wbuffer(); *p; p++) {
*p = toupper(*p);
}
}
void String::trim(void) {
if(!buffer() || len() == 0)
return;
char *begin = wbuffer();
while(isspace(*begin))
begin++;
char *end = wbuffer() + len() - 1;
while(isspace(*end) && end >= begin)
end--;
unsigned int newlen = end + 1 - begin;
if(begin > buffer())
memmove(wbuffer(), begin, newlen);
setLen(newlen);
wbuffer()[newlen] = 0;
}
// /*********************************************/
// /* Parsing / Conversion */
// /*********************************************/
long String::toInt(void) const {
if (buffer())
return atol(buffer());
return 0;
}
float String::toFloat(void) const {
if (buffer())
return atof(buffer());
return 0;
}
double String::toDouble(void) const
{
if (buffer())
return atof(buffer());
return 0.0;
}
// global empty string to allow returning const String& with nothing
const String emptyString;

View File

@ -0,0 +1,371 @@
/*
WString.h - String library for Wiring & Arduino
...mostly rewritten by Paul Stoffregen...
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
Copyright 2011, Paul Stoffregen, paul@pjrc.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef String_class_h
#define String_class_h
#ifdef __cplusplus
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
// An inherited class for holding the result of a concatenation. These
// result objects are assumed to be writable by subsequent concatenations.
class StringSumHelper;
// an abstract class used as a means to proide a unique pointer type
// but really has no body
class __FlashStringHelper;
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
#define F(string_literal) (FPSTR(PSTR(string_literal)))
// The string class
class String {
// use a function pointer to allow for "if (s)" without the
// complications of an operator bool(). for more information, see:
// http://www.artima.com/cppsource/safebool.html
typedef void (String::*StringIfHelperType)() const;
void StringIfHelper() const {
}
public:
// constructors
// creates a copy of the initial value.
// if the initial value is null or invalid, or if memory allocation
// fails, the string will be marked as invalid (i.e. "if (s)" will
// be false).
String(const char *cstr = "");
String(const String &str);
String(const __FlashStringHelper *str);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String(String &&rval);
String(StringSumHelper &&rval);
#endif
explicit String(char c);
explicit String(unsigned char, unsigned char base = 10);
explicit String(int, unsigned char base = 10);
explicit String(unsigned int, unsigned char base = 10);
explicit String(long, unsigned char base = 10);
explicit String(unsigned long, unsigned char base = 10);
explicit String(float, unsigned char decimalPlaces = 2);
explicit String(double, unsigned char decimalPlaces = 2);
~String(void);
// memory management
// return true on success, false on failure (in which case, the string
// is left unchanged). reserve(0), if successful, will validate an
// invalid string (i.e., "if (s)" will be true afterwards)
unsigned char reserve(unsigned int size);
inline unsigned int length(void) const {
if(buffer()) {
return len();
} else {
return 0;
}
}
inline void clear(void) {
setLen(0);
}
inline bool isEmpty(void) const {
return length() == 0;
}
// creates a copy of the assigned value. if the value is null or
// invalid, or if the memory allocation fails, the string will be
// marked as invalid ("if (s)" will be false).
String & operator =(const String &rhs);
String & operator =(const char *cstr);
String & operator = (const __FlashStringHelper *str);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String & operator =(String &&rval);
String & operator =(StringSumHelper &&rval);
#endif
// concatenate (works w/ built-in types)
// returns true on success, false on failure (in which case, the string
// is left unchanged). if the argument is null or invalid, the
// concatenation is considered unsuccessful.
unsigned char concat(const String &str);
unsigned char concat(const char *cstr);
unsigned char concat(char c);
unsigned char concat(unsigned char c);
unsigned char concat(int num);
unsigned char concat(unsigned int num);
unsigned char concat(long num);
unsigned char concat(unsigned long num);
unsigned char concat(float num);
unsigned char concat(double num);
unsigned char concat(const __FlashStringHelper * str);
// if there's not enough memory for the concatenated value, the string
// will be left unchanged (but this isn't signalled in any way)
String & operator +=(const String &rhs) {
concat(rhs);
return (*this);
}
String & operator +=(const char *cstr) {
concat(cstr);
return (*this);
}
String & operator +=(char c) {
concat(c);
return (*this);
}
String & operator +=(unsigned char num) {
concat(num);
return (*this);
}
String & operator +=(int num) {
concat(num);
return (*this);
}
String & operator +=(unsigned int num) {
concat(num);
return (*this);
}
String & operator +=(long num) {
concat(num);
return (*this);
}
String & operator +=(unsigned long num) {
concat(num);
return (*this);
}
String & operator +=(float num) {
concat(num);
return (*this);
}
String & operator +=(double num) {
concat(num);
return (*this);
}
String & operator += (const __FlashStringHelper *str){
concat(str);
return (*this);
}
friend StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs);
friend StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr);
friend StringSumHelper & operator +(const StringSumHelper &lhs, char c);
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, int num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, long num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, float num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, double num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, const __FlashStringHelper *rhs);
// comparison (only works w/ Strings and "strings")
operator StringIfHelperType() const {
return buffer() ? &String::StringIfHelper : 0;
}
int compareTo(const String &s) const;
unsigned char equals(const String &s) const;
unsigned char equals(const char *cstr) const;
unsigned char operator ==(const String &rhs) const {
return equals(rhs);
}
unsigned char operator ==(const char *cstr) const {
return equals(cstr);
}
unsigned char operator !=(const String &rhs) const {
return !equals(rhs);
}
unsigned char operator !=(const char *cstr) const {
return !equals(cstr);
}
unsigned char operator <(const String &rhs) const;
unsigned char operator >(const String &rhs) const;
unsigned char operator <=(const String &rhs) const;
unsigned char operator >=(const String &rhs) const;
unsigned char equalsIgnoreCase(const String &s) const;
unsigned char equalsConstantTime(const String &s) const;
unsigned char startsWith(const String &prefix) const;
unsigned char startsWith(const char *prefix) const {
return this->startsWith(String(prefix));
}
unsigned char startsWith(const __FlashStringHelper *prefix) const {
return this->startsWith(String(prefix));
}
unsigned char startsWith(const String &prefix, unsigned int offset) const;
unsigned char endsWith(const String &suffix) const;
unsigned char endsWith(const char *suffix) const {
return this->endsWith(String(suffix));
}
unsigned char endsWith(const __FlashStringHelper * suffix) const {
return this->endsWith(String(suffix));
}
// character access
char charAt(unsigned int index) const;
void setCharAt(unsigned int index, char c);
char operator [](unsigned int index) const;
char& operator [](unsigned int index);
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index = 0) const;
void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const {
getBytes((unsigned char *) buf, bufsize, index);
}
const char* c_str() const { return buffer(); }
char* begin() { return wbuffer(); }
char* end() { return wbuffer() + length(); }
const char* begin() const { return c_str(); }
const char* end() const { return c_str() + length(); }
// search
int indexOf(char ch) const;
int indexOf(char ch, unsigned int fromIndex) const;
int indexOf(const String &str) const;
int indexOf(const String &str, unsigned int fromIndex) const;
int lastIndexOf(char ch) const;
int lastIndexOf(char ch, unsigned int fromIndex) const;
int lastIndexOf(const String &str) const;
int lastIndexOf(const String &str, unsigned int fromIndex) const;
String substring(unsigned int beginIndex) const {
return substring(beginIndex, len());
}
;
String substring(unsigned int beginIndex, unsigned int endIndex) const;
// modification
void replace(char find, char replace);
void replace(const String &find, const String &replace);
void replace(const char *find, const String &replace) {
this->replace(String(find), replace);
}
void replace(const __FlashStringHelper *find, const String &replace) {
this->replace(String(find), replace);
}
void replace(const char *find, const char *replace) {
this->replace(String(find), String(replace));
}
void replace(const __FlashStringHelper *find, const char *replace) {
this->replace(String(find), String(replace));
}
void replace(const __FlashStringHelper *find, const __FlashStringHelper *replace) {
this->replace(String(find), String(replace));
}
void remove(unsigned int index);
void remove(unsigned int index, unsigned int count);
void toLowerCase(void);
void toUpperCase(void);
void trim(void);
// parsing/conversion
long toInt(void) const;
float toFloat(void) const;
double toDouble(void) const;
protected:
// Contains the string info when we're not in SSO mode
struct _ptr {
char * buff;
uint16_t cap;
uint16_t len;
};
// This allows strings up up to 11 (10 + \0 termination) without any extra space.
enum { SSOSIZE = sizeof(struct _ptr) + 4 - 1 }; // Characters to allocate space for SSO, must be 12 or more
struct _sso {
char buff[SSOSIZE];
unsigned char len : 7; // Ensure only one byte is allocated by GCC for the bitfields
unsigned char isSSO : 1;
} __attribute__((packed)); // Ensure that GCC doesn't expand the flag byte to a 32-bit word for alignment issues
enum { CAPACITY_MAX = 65535 }; // If typeof(cap) changed from uint16_t, be sure to update this enum to the max value storable in the type
union {
struct _ptr ptr;
struct _sso sso;
};
// Accessor functions
inline bool isSSO() const { return sso.isSSO; }
inline unsigned int len() const { return isSSO() ? sso.len : ptr.len; }
inline unsigned int capacity() const { return isSSO() ? (unsigned int)SSOSIZE - 1 : ptr.cap; } // Size of max string not including terminal NUL
inline void setSSO(bool set) { sso.isSSO = set; }
inline void setLen(int len) {
if (isSSO()) {
sso.len = len;
sso.buff[len] = 0;
} else {
ptr.len = len;
if (ptr.buff) {
ptr.buff[len] = 0;
}
}
}
inline void setCapacity(int cap) { if (!isSSO()) ptr.cap = cap; }
inline void setBuffer(char *buff) { if (!isSSO()) ptr.buff = buff; }
// Buffer accessor functions
inline const char *buffer() const { return (const char *)(isSSO() ? sso.buff : ptr.buff); }
inline char *wbuffer() const { return isSSO() ? const_cast<char *>(sso.buff) : ptr.buff; } // Writable version of buffer
protected:
void init(void);
void invalidate(void);
unsigned char changeBuffer(unsigned int maxStrLen);
unsigned char concat(const char *cstr, unsigned int length);
// copy and move
String & copy(const char *cstr, unsigned int length);
String & copy(const __FlashStringHelper *pstr, unsigned int length);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
void move(String &rhs);
#endif
};
class StringSumHelper: public String {
public:
StringSumHelper(const String &s) :
String(s) {
}
StringSumHelper(const char *p) :
String(p) {
}
StringSumHelper(char c) :
String(c) {
}
StringSumHelper(unsigned char num) :
String(num) {
}
StringSumHelper(int num) :
String(num) {
}
StringSumHelper(unsigned int num) :
String(num) {
}
StringSumHelper(long num) :
String(num) {
}
StringSumHelper(unsigned long num) :
String(num) {
}
StringSumHelper(float num) :
String(num) {
}
StringSumHelper(double num) :
String(num) {
}
};
extern const String emptyString;
#endif // __cplusplus
#endif // String_class_h

View File

@ -0,0 +1,89 @@
/*
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the RaspberryPi core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PGMSPACE_INCLUDE
#define PGMSPACE_INCLUDE
typedef void prog_void;
typedef char prog_char;
typedef unsigned char prog_uchar;
typedef char prog_int8_t;
typedef unsigned char prog_uint8_t;
typedef short prog_int16_t;
typedef unsigned short prog_uint16_t;
typedef long prog_int32_t;
typedef unsigned long prog_uint32_t;
#define PROGMEM
#define PGM_P const char *
#define PGM_VOID_P const void *
#define PSTR(s) (s)
#define _SFR_BYTE(n) (n)
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) ({ \
typeof(addr) _addr = (addr); \
*(const unsigned short *)(_addr); \
})
#define pgm_read_dword(addr) ({ \
typeof(addr) _addr = (addr); \
*(const unsigned long *)(_addr); \
})
#define pgm_read_float(addr) ({ \
typeof(addr) _addr = (addr); \
*(const float *)(_addr); \
})
#define pgm_read_ptr(addr) ({ \
typeof(addr) _addr = (addr); \
*(void * const *)(_addr); \
})
#define pgm_get_far_address(x) ((uint32_t)(&(x)))
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)
#define memcmp_P memcmp
#define memccpy_P memccpy
#define memmem_P memmem
#define memcpy_P memcpy
#define strcpy_P strcpy
#define strncpy_P strncpy
#define strcat_P strcat
#define strncat_P strncat
#define strcmp_P strcmp
#define strncmp_P strncmp
#define strcasecmp_P strcasecmp
#define strncasecmp_P strncasecmp
#define strlen_P strlen
#define strnlen_P strnlen
#define strstr_P strstr
#define printf_P printf
#define sprintf_P sprintf
#define snprintf_P snprintf
#define vsnprintf_P vsnprintf
#endif

View File

@ -0,0 +1,161 @@
/*
core_esp8266_noniso.c - nonstandard (but usefull) conversion functions
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 03 April 2015 by Markus Sattler
*/
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <math.h>
#include "stdlib_noniso.h"
void reverse(char* begin, char* end) {
char *is = begin;
char *ie = end - 1;
while(is < ie) {
char tmp = *ie;
*ie = *is;
*is = tmp;
++is;
--ie;
}
}
char* ltoa(long value, char* result, int base) {
if(base < 2 || base > 16) {
*result = 0;
return result;
}
char* out = result;
long quotient = abs(value);
do {
const long tmp = quotient / base;
*out = "0123456789abcdef"[quotient - (tmp * base)];
++out;
quotient = tmp;
} while(quotient);
// Apply negative sign
if(value < 0)
*out++ = '-';
reverse(result, out);
*out = 0;
return result;
}
char* ultoa(unsigned long value, char* result, int base) {
if(base < 2 || base > 16) {
*result = 0;
return result;
}
char* out = result;
unsigned long quotient = value;
do {
const unsigned long tmp = quotient / base;
*out = "0123456789abcdef"[quotient - (tmp * base)];
++out;
quotient = tmp;
} while(quotient);
reverse(result, out);
*out = 0;
return result;
}
char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
bool negative = false;
if (isnan(number)) {
strcpy(s, "nan");
return s;
}
if (isinf(number)) {
strcpy(s, "inf");
return s;
}
char* out = s;
int fillme = width; // how many cells to fill for the integer part
if (prec > 0) {
fillme -= (prec+1);
}
// Handle negative numbers
if (number < 0.0) {
negative = true;
fillme--;
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
// I optimized out most of the divisions
double rounding = 2.0;
for (uint8_t i = 0; i < prec; ++i)
rounding *= 10.0;
rounding = 1.0 / rounding;
number += rounding;
// Figure out how big our number really is
double tenpow = 1.0;
int digitcount = 1;
while (number >= 10.0 * tenpow) {
tenpow *= 10.0;
digitcount++;
}
number /= tenpow;
fillme -= digitcount;
// Pad unused cells with spaces
while (fillme-- > 0) {
*out++ = ' ';
}
// Handle negative sign
if (negative) *out++ = '-';
// Print the digits, and if necessary, the decimal point
digitcount += prec;
int8_t digit = 0;
while (digitcount-- > 0) {
digit = (int8_t)number;
if (digit > 9) digit = 9; // insurance
*out++ = (char)('0' | digit);
if ((digitcount == prec) && (prec > 0)) {
*out++ = '.';
}
number -= digit;
number *= 10.0;
}
// make sure the string is terminated
*out = 0;
return s;
}

View File

@ -0,0 +1,49 @@
/*
stdlib_noniso.h - nonstandard (but usefull) conversion functions
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef STDLIB_NONISO_H
#define STDLIB_NONISO_H
#ifdef __cplusplus
extern "C" {
#endif
int atoi(const char *s);
long atol(const char* s);
double atof(const char* s);
char* itoa (int val, char *s, int radix);
char* ltoa (long val, char *s, int radix);
char* utoa (unsigned int val, char *s, int radix);
char* ultoa (unsigned long val, char *s, int radix);
char* dtostrf (double val, signed char width, unsigned char prec, char *s);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,218 @@
/*
u8g2_bitmap.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
void u8g2_SetBitmapMode(u8g2_t *u8g2, uint8_t is_transparent) {
u8g2->bitmap_transparency = is_transparent;
}
/*
x,y Position on the display
len Length of bitmap line in pixel. Note: This differs from u8glib which had a bytecount here.
b Pointer to the bitmap line.
Only draw pixels which are set.
*/
void u8g2_DrawHorizontalBitmap(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, const uint8_t *b)
{
uint8_t mask;
uint8_t color = u8g2->draw_color;
uint8_t ncolor = (color == 0 ? 1 : 0);
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+len, y+1) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
mask = 128;
while(len > 0)
{
if ( *b & mask ) {
u8g2->draw_color = color;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
} else if ( u8g2->bitmap_transparency == 0 ) {
u8g2->draw_color = ncolor;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
}
x++;
mask >>= 1;
if ( mask == 0 )
{
mask = 128;
b++;
}
len--;
}
u8g2->draw_color = color;
}
/* u8glib compatible bitmap draw function */
void u8g2_DrawBitmap(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t cnt, u8g2_uint_t h, const uint8_t *bitmap)
{
u8g2_uint_t w;
w = cnt;
w *= 8;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
while( h > 0 )
{
u8g2_DrawHorizontalBitmap(u8g2, x, y, w, bitmap);
bitmap += cnt;
y++;
h--;
}
}
void u8g2_DrawHXBM(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, const uint8_t *b)
{
uint8_t mask;
uint8_t color = u8g2->draw_color;
uint8_t ncolor = (color == 0 ? 1 : 0);
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+len, y+1) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
mask = 1;
while(len > 0) {
if ( *b & mask ) {
u8g2->draw_color = color;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
} else if ( u8g2->bitmap_transparency == 0 ) {
u8g2->draw_color = ncolor;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
}
x++;
mask <<= 1;
if ( mask == 0 )
{
mask = 1;
b++;
}
len--;
}
u8g2->draw_color = color;
}
void u8g2_DrawXBM(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap)
{
u8g2_uint_t blen;
blen = w;
blen += 7;
blen >>= 3;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
while( h > 0 )
{
u8g2_DrawHXBM(u8g2, x, y, w, bitmap);
bitmap += blen;
y++;
h--;
}
}
void u8g2_DrawHXBMP(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, const uint8_t *b)
{
uint8_t mask;
uint8_t color = u8g2->draw_color;
uint8_t ncolor = (color == 0 ? 1 : 0);
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+len, y+1) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
mask = 1;
while(len > 0)
{
if( u8x8_pgm_read(b) & mask ) {
u8g2->draw_color = color;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
} else if( u8g2->bitmap_transparency == 0 ) {
u8g2->draw_color = ncolor;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
}
x++;
mask <<= 1;
if ( mask == 0 )
{
mask = 1;
b++;
}
len--;
}
u8g2->draw_color = color;
}
void u8g2_DrawXBMP(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap)
{
u8g2_uint_t blen;
blen = w;
blen += 7;
blen >>= 3;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
while( h > 0 )
{
u8g2_DrawHXBMP(u8g2, x, y, w, bitmap);
bitmap += blen;
y++;
h--;
}
}

View File

@ -0,0 +1,210 @@
/*
u8g2_box.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/*
draw a filled box
restriction: does not work for w = 0 or h = 0
*/
void u8g2_DrawBox(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
{
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
while( h != 0 )
{
u8g2_DrawHVLine(u8g2, x, y, w, 0);
y++;
h--;
}
}
/*
draw a frame (empty box)
restriction: does not work for w = 0 or h = 0
*/
void u8g2_DrawFrame(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
{
u8g2_uint_t xtmp = x;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
u8g2_DrawHVLine(u8g2, x, y, w, 0);
if (h >= 2) {
h-=2;
y++;
if (h > 0) {
u8g2_DrawHVLine(u8g2, x, y, h, 1);
x+=w;
x--;
u8g2_DrawHVLine(u8g2, x, y, h, 1);
y+=h;
}
u8g2_DrawHVLine(u8g2, xtmp, y, w, 0);
}
}
void u8g2_DrawRBox(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)
{
u8g2_uint_t xl, yu;
u8g2_uint_t yl, xr;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
xl = x;
xl += r;
yu = y;
yu += r;
xr = x;
xr += w;
xr -= r;
xr -= 1;
yl = y;
yl += h;
yl -= r;
yl -= 1;
u8g2_DrawDisc(u8g2, xl, yu, r, U8G2_DRAW_UPPER_LEFT);
u8g2_DrawDisc(u8g2, xr, yu, r, U8G2_DRAW_UPPER_RIGHT);
u8g2_DrawDisc(u8g2, xl, yl, r, U8G2_DRAW_LOWER_LEFT);
u8g2_DrawDisc(u8g2, xr, yl, r, U8G2_DRAW_LOWER_RIGHT);
{
u8g2_uint_t ww, hh;
ww = w;
ww -= r;
ww -= r;
xl++;
yu++;
if ( ww >= 3 )
{
ww -= 2;
u8g2_DrawBox(u8g2, xl, y, ww, r+1);
u8g2_DrawBox(u8g2, xl, yl, ww, r+1);
}
hh = h;
hh -= r;
hh -= r;
//h--;
if ( hh >= 3 )
{
hh -= 2;
u8g2_DrawBox(u8g2, x, yu, w, hh);
}
}
}
void u8g2_DrawRFrame(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)
{
u8g2_uint_t xl, yu;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
xl = x;
xl += r;
yu = y;
yu += r;
{
u8g2_uint_t yl, xr;
xr = x;
xr += w;
xr -= r;
xr -= 1;
yl = y;
yl += h;
yl -= r;
yl -= 1;
u8g2_DrawCircle(u8g2, xl, yu, r, U8G2_DRAW_UPPER_LEFT);
u8g2_DrawCircle(u8g2, xr, yu, r, U8G2_DRAW_UPPER_RIGHT);
u8g2_DrawCircle(u8g2, xl, yl, r, U8G2_DRAW_LOWER_LEFT);
u8g2_DrawCircle(u8g2, xr, yl, r, U8G2_DRAW_LOWER_RIGHT);
}
{
u8g2_uint_t ww, hh;
ww = w;
ww -= r;
ww -= r;
hh = h;
hh -= r;
hh -= r;
xl++;
yu++;
if ( ww >= 3 )
{
ww -= 2;
h--;
u8g2_DrawHLine(u8g2, xl, y, ww);
u8g2_DrawHLine(u8g2, xl, y+h, ww);
}
if ( hh >= 3 )
{
hh -= 2;
w--;
u8g2_DrawVLine(u8g2, x, yu, hh);
u8g2_DrawVLine(u8g2, x+w, yu, hh);
}
}
}

View File

@ -0,0 +1,213 @@
/*
u8g2_buffer.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
#include <string.h>
/*============================================*/
void u8g2_ClearBuffer(u8g2_t *u8g2)
{
size_t cnt;
cnt = u8g2_GetU8x8(u8g2)->display_info->tile_width;
cnt *= u8g2->tile_buf_height;
cnt *= 8;
memset(u8g2->tile_buf_ptr, 0, cnt);
}
/*============================================*/
static void u8g2_send_tile_row(u8g2_t *u8g2, uint8_t src_tile_row, uint8_t dest_tile_row)
{
uint8_t *ptr;
uint16_t offset;
uint8_t w;
w = u8g2_GetU8x8(u8g2)->display_info->tile_width;
offset = src_tile_row;
ptr = u8g2->tile_buf_ptr;
offset *= w;
offset *= 8;
ptr += offset;
u8x8_DrawTile(u8g2_GetU8x8(u8g2), 0, dest_tile_row, w, ptr);
}
/*
write the buffer to the display RAM.
For most displays, this will make the content visible to the user.
Some displays (like the SSD1606) require a u8x8_RefreshDisplay()
*/
static void u8g2_send_buffer(u8g2_t *u8g2) U8X8_NOINLINE;
static void u8g2_send_buffer(u8g2_t *u8g2)
{
uint8_t src_row;
uint8_t src_max;
uint8_t dest_row;
uint8_t dest_max;
src_row = 0;
src_max = u8g2->tile_buf_height;
dest_row = u8g2->tile_curr_row;
dest_max = u8g2_GetU8x8(u8g2)->display_info->tile_height;
do
{
u8g2_send_tile_row(u8g2, src_row, dest_row);
src_row++;
dest_row++;
} while( src_row < src_max && dest_row < dest_max );
}
/* same as u8g2_send_buffer but also send the DISPLAY_REFRESH message (used by SSD1606) */
void u8g2_SendBuffer(u8g2_t *u8g2)
{
u8g2_send_buffer(u8g2);
u8x8_RefreshDisplay( u8g2_GetU8x8(u8g2) );
}
/*============================================*/
void u8g2_SetBufferCurrTileRow(u8g2_t *u8g2, uint8_t row)
{
u8g2->tile_curr_row = row;
u8g2->cb->update_dimension(u8g2);
u8g2->cb->update_page_win(u8g2);
}
void u8g2_FirstPage(u8g2_t *u8g2)
{
if ( u8g2->is_auto_page_clear )
{
u8g2_ClearBuffer(u8g2);
}
u8g2_SetBufferCurrTileRow(u8g2, 0);
}
uint8_t u8g2_NextPage(u8g2_t *u8g2)
{
uint8_t row;
u8g2_send_buffer(u8g2);
row = u8g2->tile_curr_row;
row += u8g2->tile_buf_height;
if ( row >= u8g2_GetU8x8(u8g2)->display_info->tile_height )
{
u8x8_RefreshDisplay( u8g2_GetU8x8(u8g2) );
return 0;
}
if ( u8g2->is_auto_page_clear )
{
u8g2_ClearBuffer(u8g2);
}
u8g2_SetBufferCurrTileRow(u8g2, row);
return 1;
}
/*============================================*/
/*
Description:
Update a sub area of the display, given by tile position, width and height.
The arguments are "tile" coordinates. Any u8g2 rotation is ignored.
This procedure only checks whether full buffer mode is active.
There is no error checking for the arguments: It is the responsibility of the
user to ensure, that the provided arguments are correct.
Limitations:
- Only available in full buffer mode (will not do anything in page mode)
- Tile positions and sizes (pixel position divided by 8)
- Any display rotation/mirror is ignored
- Only works with displays, which support U8x8 API
- Will not send the e-paper refresh message (will probably not work with e-paper devices)
*/
void u8g2_UpdateDisplayArea(u8g2_t *u8g2, uint8_t tx, uint8_t ty, uint8_t tw, uint8_t th)
{
uint16_t page_size;
uint8_t *ptr;
/* check, whether we are in full buffer mode */
if ( u8g2->tile_buf_height != u8g2_GetU8x8(u8g2)->display_info->tile_height )
return; /* not in full buffer mode, do nothing */
page_size = u8g2->pixel_buf_width; /* 8*u8g2->u8g2_GetU8x8(u8g2)->display_info->tile_width */
ptr = u8g2_GetBufferPtr(u8g2);
ptr += tx*8;
ptr += page_size*ty;
while( th > 0 )
{
u8x8_DrawTile( u8g2_GetU8x8(u8g2), tx, ty, tw, ptr );
ptr += page_size;
ty++;
th--;
}
}
/* same as sendBuffer, but does not send the ePaper refresh message */
void u8g2_UpdateDisplay(u8g2_t *u8g2)
{
u8g2_send_buffer(u8g2);
}
/*============================================*/
/* vertical_top memory architecture */
void u8g2_WriteBufferPBM(u8g2_t *u8g2, void (*out)(const char *s))
{
u8x8_capture_write_pbm_pre(u8g2_GetBufferTileWidth(u8g2), u8g2_GetBufferTileHeight(u8g2), out);
u8x8_capture_write_pbm_buffer(u8g2_GetBufferPtr(u8g2), u8g2_GetBufferTileWidth(u8g2), u8g2_GetBufferTileHeight(u8g2), u8x8_capture_get_pixel_1, out);
}
void u8g2_WriteBufferXBM(u8g2_t *u8g2, void (*out)(const char *s))
{
u8x8_capture_write_xbm_pre(u8g2_GetBufferTileWidth(u8g2), u8g2_GetBufferTileHeight(u8g2), out);
u8x8_capture_write_xbm_buffer(u8g2_GetBufferPtr(u8g2), u8g2_GetBufferTileWidth(u8g2), u8g2_GetBufferTileHeight(u8g2), u8x8_capture_get_pixel_1, out);
}
/* horizontal right memory architecture */
/* SH1122, LD7032, ST7920, ST7986, LC7981, T6963, SED1330, RA8835, MAX7219, LS0 */
void u8g2_WriteBufferPBM2(u8g2_t *u8g2, void (*out)(const char *s))
{
u8x8_capture_write_pbm_pre(u8g2_GetBufferTileWidth(u8g2), u8g2_GetBufferTileHeight(u8g2), out);
u8x8_capture_write_pbm_buffer(u8g2_GetBufferPtr(u8g2), u8g2_GetBufferTileWidth(u8g2), u8g2_GetBufferTileHeight(u8g2), u8x8_capture_get_pixel_2, out);
}
void u8g2_WriteBufferXBM2(u8g2_t *u8g2, void (*out)(const char *s))
{
u8x8_capture_write_xbm_pre(u8g2_GetBufferTileWidth(u8g2), u8g2_GetBufferTileHeight(u8g2), out);
u8x8_capture_write_xbm_buffer(u8g2_GetBufferPtr(u8g2), u8g2_GetBufferTileWidth(u8g2), u8g2_GetBufferTileHeight(u8g2), u8x8_capture_get_pixel_2, out);
}

View File

@ -0,0 +1,479 @@
/*
u8g2_circle.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/*==============================================*/
/* Circle */
static void u8g2_draw_circle_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option) U8G2_NOINLINE;
static void u8g2_draw_circle_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option)
{
/* upper right */
if ( option & U8G2_DRAW_UPPER_RIGHT )
{
u8g2_DrawPixel(u8g2, x0 + x, y0 - y);
u8g2_DrawPixel(u8g2, x0 + y, y0 - x);
}
/* upper left */
if ( option & U8G2_DRAW_UPPER_LEFT )
{
u8g2_DrawPixel(u8g2, x0 - x, y0 - y);
u8g2_DrawPixel(u8g2, x0 - y, y0 - x);
}
/* lower right */
if ( option & U8G2_DRAW_LOWER_RIGHT )
{
u8g2_DrawPixel(u8g2, x0 + x, y0 + y);
u8g2_DrawPixel(u8g2, x0 + y, y0 + x);
}
/* lower left */
if ( option & U8G2_DRAW_LOWER_LEFT )
{
u8g2_DrawPixel(u8g2, x0 - x, y0 + y);
u8g2_DrawPixel(u8g2, x0 - y, y0 + x);
}
}
static void u8g2_draw_circle(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t option)
{
u8g2_int_t f;
u8g2_int_t ddF_x;
u8g2_int_t ddF_y;
u8g2_uint_t x;
u8g2_uint_t y;
f = 1;
f -= rad;
ddF_x = 1;
ddF_y = 0;
ddF_y -= rad;
ddF_y *= 2;
x = 0;
y = rad;
u8g2_draw_circle_section(u8g2, x, y, x0, y0, option);
while ( x < y )
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
u8g2_draw_circle_section(u8g2, x, y, x0, y0, option);
}
}
void u8g2_DrawCircle(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t option)
{
/* check for bounding box */
#ifdef U8G2_WITH_INTERSECTION
{
if ( u8g2_IsIntersection(u8g2, x0-rad, y0-rad, x0+rad+1, y0+rad+1) == 0 )
return;
}
#endif /* U8G2_WITH_INTERSECTION */
/* draw circle */
u8g2_draw_circle(u8g2, x0, y0, rad, option);
}
/*==============================================*/
/* Disk */
static void u8g2_draw_disc_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option) U8G2_NOINLINE;
static void u8g2_draw_disc_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option)
{
/* upper right */
if ( option & U8G2_DRAW_UPPER_RIGHT )
{
u8g2_DrawVLine(u8g2, x0+x, y0-y, y+1);
u8g2_DrawVLine(u8g2, x0+y, y0-x, x+1);
}
/* upper left */
if ( option & U8G2_DRAW_UPPER_LEFT )
{
u8g2_DrawVLine(u8g2, x0-x, y0-y, y+1);
u8g2_DrawVLine(u8g2, x0-y, y0-x, x+1);
}
/* lower right */
if ( option & U8G2_DRAW_LOWER_RIGHT )
{
u8g2_DrawVLine(u8g2, x0+x, y0, y+1);
u8g2_DrawVLine(u8g2, x0+y, y0, x+1);
}
/* lower left */
if ( option & U8G2_DRAW_LOWER_LEFT )
{
u8g2_DrawVLine(u8g2, x0-x, y0, y+1);
u8g2_DrawVLine(u8g2, x0-y, y0, x+1);
}
}
static void u8g2_draw_disc(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t option)
{
u8g2_int_t f;
u8g2_int_t ddF_x;
u8g2_int_t ddF_y;
u8g2_uint_t x;
u8g2_uint_t y;
f = 1;
f -= rad;
ddF_x = 1;
ddF_y = 0;
ddF_y -= rad;
ddF_y *= 2;
x = 0;
y = rad;
u8g2_draw_disc_section(u8g2, x, y, x0, y0, option);
while ( x < y )
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
u8g2_draw_disc_section(u8g2, x, y, x0, y0, option);
}
}
void u8g2_DrawDisc(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t option)
{
/* check for bounding box */
#ifdef U8G2_WITH_INTERSECTION
{
if ( u8g2_IsIntersection(u8g2, x0-rad, y0-rad, x0+rad+1, y0+rad+1) == 0 )
return;
}
#endif /* U8G2_WITH_INTERSECTION */
/* draw disc */
u8g2_draw_disc(u8g2, x0, y0, rad, option);
}
/*==============================================*/
/* Ellipse */
/*
Source:
Foley, Computer Graphics, p 90
*/
static void u8g2_draw_ellipse_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option) U8G2_NOINLINE;
static void u8g2_draw_ellipse_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option)
{
/* upper right */
if ( option & U8G2_DRAW_UPPER_RIGHT )
{
u8g2_DrawPixel(u8g2, x0 + x, y0 - y);
}
/* upper left */
if ( option & U8G2_DRAW_UPPER_LEFT )
{
u8g2_DrawPixel(u8g2, x0 - x, y0 - y);
}
/* lower right */
if ( option & U8G2_DRAW_LOWER_RIGHT )
{
u8g2_DrawPixel(u8g2, x0 + x, y0 + y);
}
/* lower left */
if ( option & U8G2_DRAW_LOWER_LEFT )
{
u8g2_DrawPixel(u8g2, x0 - x, y0 + y);
}
}
static void u8g2_draw_ellipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t option)
{
u8g2_uint_t x, y;
u8g2_long_t xchg, ychg;
u8g2_long_t err;
u8g2_long_t rxrx2;
u8g2_long_t ryry2;
u8g2_long_t stopx, stopy;
rxrx2 = rx;
rxrx2 *= rx;
rxrx2 *= 2;
ryry2 = ry;
ryry2 *= ry;
ryry2 *= 2;
x = rx;
y = 0;
xchg = 1;
xchg -= rx;
xchg -= rx;
xchg *= ry;
xchg *= ry;
ychg = rx;
ychg *= rx;
err = 0;
stopx = ryry2;
stopx *= rx;
stopy = 0;
while( stopx >= stopy )
{
u8g2_draw_ellipse_section(u8g2, x, y, x0, y0, option);
y++;
stopy += rxrx2;
err += ychg;
ychg += rxrx2;
if ( 2*err+xchg > 0 )
{
x--;
stopx -= ryry2;
err += xchg;
xchg += ryry2;
}
}
x = 0;
y = ry;
xchg = ry;
xchg *= ry;
ychg = 1;
ychg -= ry;
ychg -= ry;
ychg *= rx;
ychg *= rx;
err = 0;
stopx = 0;
stopy = rxrx2;
stopy *= ry;
while( stopx <= stopy )
{
u8g2_draw_ellipse_section(u8g2, x, y, x0, y0, option);
x++;
stopx += ryry2;
err += xchg;
xchg += ryry2;
if ( 2*err+ychg > 0 )
{
y--;
stopy -= rxrx2;
err += ychg;
ychg += rxrx2;
}
}
}
void u8g2_DrawEllipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t option)
{
/* check for bounding box */
#ifdef U8G2_WITH_INTERSECTION
{
if ( u8g2_IsIntersection(u8g2, x0-rx, y0-ry, x0+rx+1, y0+ry+1) == 0 )
return;
}
#endif /* U8G2_WITH_INTERSECTION */
u8g2_draw_ellipse(u8g2, x0, y0, rx, ry, option);
}
/*==============================================*/
/* Filled Ellipse */
static void u8g2_draw_filled_ellipse_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option) U8G2_NOINLINE;
static void u8g2_draw_filled_ellipse_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option)
{
/* upper right */
if ( option & U8G2_DRAW_UPPER_RIGHT )
{
u8g2_DrawVLine(u8g2, x0+x, y0-y, y+1);
}
/* upper left */
if ( option & U8G2_DRAW_UPPER_LEFT )
{
u8g2_DrawVLine(u8g2, x0-x, y0-y, y+1);
}
/* lower right */
if ( option & U8G2_DRAW_LOWER_RIGHT )
{
u8g2_DrawVLine(u8g2, x0+x, y0, y+1);
}
/* lower left */
if ( option & U8G2_DRAW_LOWER_LEFT )
{
u8g2_DrawVLine(u8g2, x0-x, y0, y+1);
}
}
static void u8g2_draw_filled_ellipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t option)
{
u8g2_uint_t x, y;
u8g2_long_t xchg, ychg;
u8g2_long_t err;
u8g2_long_t rxrx2;
u8g2_long_t ryry2;
u8g2_long_t stopx, stopy;
rxrx2 = rx;
rxrx2 *= rx;
rxrx2 *= 2;
ryry2 = ry;
ryry2 *= ry;
ryry2 *= 2;
x = rx;
y = 0;
xchg = 1;
xchg -= rx;
xchg -= rx;
xchg *= ry;
xchg *= ry;
ychg = rx;
ychg *= rx;
err = 0;
stopx = ryry2;
stopx *= rx;
stopy = 0;
while( stopx >= stopy )
{
u8g2_draw_filled_ellipse_section(u8g2, x, y, x0, y0, option);
y++;
stopy += rxrx2;
err += ychg;
ychg += rxrx2;
if ( 2*err+xchg > 0 )
{
x--;
stopx -= ryry2;
err += xchg;
xchg += ryry2;
}
}
x = 0;
y = ry;
xchg = ry;
xchg *= ry;
ychg = 1;
ychg -= ry;
ychg -= ry;
ychg *= rx;
ychg *= rx;
err = 0;
stopx = 0;
stopy = rxrx2;
stopy *= ry;
while( stopx <= stopy )
{
u8g2_draw_filled_ellipse_section(u8g2, x, y, x0, y0, option);
x++;
stopx += ryry2;
err += xchg;
xchg += ryry2;
if ( 2*err+ychg > 0 )
{
y--;
stopy -= rxrx2;
err += ychg;
ychg += rxrx2;
}
}
}
void u8g2_DrawFilledEllipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t option)
{
/* check for bounding box */
#ifdef U8G2_WITH_INTERSECTION
{
if ( u8g2_IsIntersection(u8g2, x0-rx, y0-ry, x0+rx+1, y0+ry+1) == 0 )
return;
}
#endif /* U8G2_WITH_INTERSECTION */
u8g2_draw_filled_ellipse(u8g2, x0, y0, rx, ry, option);
}

View File

@ -0,0 +1,54 @@
/*
u8g2_cleardisplay.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/* Clear screen buffer & display reliable for all u8g2 displays. */
/* This is done with u8g2 picture loop, because we can not use the u8x8 function in all cases */
void u8g2_ClearDisplay(u8g2_t *u8g2)
{
u8g2_FirstPage(u8g2);
do {
} while ( u8g2_NextPage(u8g2) );
/*
This function is usually called during startup (u8g2.begin()).
However the user might want to use full buffer mode with clear and
send commands.
This will not work because the current tile row is modified by the picture
loop above. To fix this, reset the tile row to 0, issue #370
A workaround would be, that the user sets the current tile row to 0 manually.
*/
u8g2_SetBufferCurrTileRow(u8g2, 0);
}

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,255 @@
/*
u8g2_hvline.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Calltree
void u8g2_DrawHVLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
u8g2->cb->draw_l90
u8g2_draw_hv_line_2dir
u8g2->ll_hvline(u8g2, x, y, len, dir);
*/
#include "u8g2.h"
#include <assert.h>
/*==========================================================*/
/* intersection procedure */
/*
Description:
clip range from pos a (included) with line len (a+len excluded) agains c (included) to d (excluded)
Assumptions:
len > 0
c <= d (this is not checked)
will return 0 if there is no intersection and if a > b
*/
static uint8_t u8g2_clip_intersection2(u8g2_uint_t *ap, u8g2_uint_t *len, u8g2_uint_t c, u8g2_uint_t d)
{
u8g2_uint_t a = *ap;
u8g2_uint_t b;
b = a;
b += *len;
/*
Description:
clip range from a (included) to b (excluded) agains c (included) to d (excluded)
Assumptions:
a <= b (violation is checked and handled correctly)
c <= d (this is not checked)
will return 0 if there is no intersection and if a > b
optimized clipping: c is set to 0 --> 27 Oct 2018: again removed the c==0 assumption
replaced by uint8_t u8g2_clip_intersection2
*/
/* handle the a>b case correctly. If code and time is critical, this could */
/* be removed completly (be aware about memory curruption for wrong */
/* arguments) or return 0 for a>b (will lead to skipped lines for wrong */
/* arguments) */
/* removing the following if clause completly may lead to memory corruption of a>b */
if ( a > b )
{
/* replacing this if with a simple "return 0;" will not handle the case with negative a */
if ( a < d )
{
b = d;
b--;
}
else
{
a = c;
}
}
/* from now on, the asumption a <= b is ok */
if ( a >= d )
return 0;
if ( b <= c )
return 0;
if ( a < c )
a = c;
if ( b > d )
b = d;
*ap = a;
b -= a;
*len = b;
return 1;
}
/*==========================================================*/
/* draw procedures */
/*
x,y Upper left position of the line within the pixel buffer
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
This function first adjusts the y position to the local buffer. Then it
will clip the line and call u8g2_draw_low_level_hv_line()
*/
void u8g2_draw_hv_line_2dir(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
/* clipping happens before the display rotation */
/* transform to pixel buffer coordinates */
y -= u8g2->pixel_curr_row;
u8g2->ll_hvline(u8g2, x, y, len, dir);
}
/*
This is the toplevel function for the hv line draw procedures.
This function should be called by the user.
"dir" may have 4 directions: 0 (left to right), 1, 2, 3 (down up)
*/
void u8g2_DrawHVLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
/* Make a call to the callback function (e.g. u8g2_draw_l90_r0). */
/* The callback may rotate the hv line */
/* after rotation this will call u8g2_draw_hv_line_4dir() */
#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT
if ( u8g2->is_page_clip_window_intersection != 0 )
#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */
if ( len != 0 )
{
/* convert to two directions */
if ( len > 1 )
{
if ( dir == 2 )
{
x -= len;
x++;
}
else if ( dir == 3 )
{
y -= len;
y++;
}
}
dir &= 1;
/* clip against the user window */
if ( dir == 0 )
{
if ( y < u8g2->user_y0 )
return;
if ( y >= u8g2->user_y1 )
return;
if ( u8g2_clip_intersection2(&x, &len, u8g2->user_x0, u8g2->user_x1) == 0 )
return;
}
else
{
if ( x < u8g2->user_x0 )
return;
if ( x >= u8g2->user_x1 )
return;
if ( u8g2_clip_intersection2(&y, &len, u8g2->user_y0, u8g2->user_y1) == 0 )
return;
}
u8g2->cb->draw_l90(u8g2, x, y, len, dir);
}
}
void u8g2_DrawHLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len)
{
// #ifdef U8G2_WITH_INTERSECTION
// if ( u8g2_IsIntersection(u8g2, x, y, x+len, y+1) == 0 )
// return;
// #endif /* U8G2_WITH_INTERSECTION */
u8g2_DrawHVLine(u8g2, x, y, len, 0);
}
void u8g2_DrawVLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len)
{
// #ifdef U8G2_WITH_INTERSECTION
// if ( u8g2_IsIntersection(u8g2, x, y, x+1, y+len) == 0 )
// return;
// #endif /* U8G2_WITH_INTERSECTION */
u8g2_DrawHVLine(u8g2, x, y, len, 1);
}
void u8g2_DrawPixel(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y)
{
#ifdef U8G2_WITH_INTERSECTION
if ( y < u8g2->user_y0 )
return;
if ( y >= u8g2->user_y1 )
return;
if ( x < u8g2->user_x0 )
return;
if ( x >= u8g2->user_x1 )
return;
#endif /* U8G2_WITH_INTERSECTION */
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
}
/*
Assign the draw color for all drawing functions.
color may be 0 or 1. The actual color is defined by the display.
With color = 1 the drawing function will set the display memory to 1.
For OLEDs this ususally means, that the pixel is enabled and the LED
at the pixel is turned on.
On an LCD it usually means that the LCD segment of the pixel is enabled,
which absorbs the light.
For eInk/ePaper it means black ink.
7 Jan 2017: Allow color value 2 for XOR operation.
*/
void u8g2_SetDrawColor(u8g2_t *u8g2, uint8_t color)
{
u8g2->draw_color = color; /* u8g2_SetDrawColor: just assign the argument */
if ( color >= 3 )
u8g2->draw_color = 1; /* u8g2_SetDrawColor: make color as one if arg is invalid */
}

View File

@ -0,0 +1,150 @@
/*
u8g2_input_value.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/*
return:
0: value is not changed (HOME/Break Button pressed)
1: value has been updated
*/
uint8_t u8g2_UserInterfaceInputValue(u8g2_t *u8g2, const char *title, const char *pre, uint8_t *value, uint8_t lo, uint8_t hi, uint8_t digits, const char *post)
{
uint8_t line_height;
uint8_t height;
u8g2_uint_t pixel_height;
u8g2_uint_t y, yy;
u8g2_uint_t pixel_width;
u8g2_uint_t x, xx;
uint8_t local_value = *value;
//uint8_t r; /* not used ??? */
uint8_t event;
/* only horizontal strings are supported, so force this here */
u8g2_SetFontDirection(u8g2, 0);
/* force baseline position */
u8g2_SetFontPosBaseline(u8g2);
/* calculate line height */
line_height = u8g2_GetAscent(u8g2);
line_height -= u8g2_GetDescent(u8g2);
/* calculate overall height of the input value box */
height = 1; /* value input line */
height += u8x8_GetStringLineCnt(title);
/* calculate the height in pixel */
pixel_height = height;
pixel_height *= line_height;
/* calculate offset from top */
y = 0;
if ( pixel_height < u8g2_GetDisplayHeight(u8g2) )
{
y = u8g2_GetDisplayHeight(u8g2);
y -= pixel_height;
y /= 2;
}
/* calculate offset from left for the label */
x = 0;
pixel_width = u8g2_GetUTF8Width(u8g2, pre);
pixel_width += u8g2_GetUTF8Width(u8g2, "0") * digits;
pixel_width += u8g2_GetUTF8Width(u8g2, post);
if ( pixel_width < u8g2_GetDisplayWidth(u8g2) )
{
x = u8g2_GetDisplayWidth(u8g2);
x -= pixel_width;
x /= 2;
}
/* event loop */
for(;;)
{
u8g2_FirstPage(u8g2);
do
{
/* render */
yy = y;
yy += u8g2_DrawUTF8Lines(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), line_height, title);
xx = x;
xx += u8g2_DrawUTF8(u8g2, xx, yy, pre);
xx += u8g2_DrawUTF8(u8g2, xx, yy, u8x8_u8toa(local_value, digits));
u8g2_DrawUTF8(u8g2, xx, yy, post);
} while( u8g2_NextPage(u8g2) );
#ifdef U8G2_REF_MAN_PIC
return 0;
#endif
for(;;)
{
event = u8x8_GetMenuEvent(u8g2_GetU8x8(u8g2));
if ( event == U8X8_MSG_GPIO_MENU_SELECT )
{
*value = local_value;
return 1;
}
else if ( event == U8X8_MSG_GPIO_MENU_HOME )
{
return 0;
}
else if ( event == U8X8_MSG_GPIO_MENU_NEXT || event == U8X8_MSG_GPIO_MENU_UP )
{
if ( local_value >= hi )
local_value = lo;
else
local_value++;
break;
}
else if ( event == U8X8_MSG_GPIO_MENU_PREV || event == U8X8_MSG_GPIO_MENU_DOWN )
{
if ( local_value <= lo )
local_value = hi;
else
local_value--;
break;
}
}
}
/* never reached */
//return r;
}

View File

@ -0,0 +1,176 @@
/*
u8g2_intersection.c
Intersection calculation, code taken from u8g_clip.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
#ifdef __GNUC__
#define U8G2_ALWAYS_INLINE __inline__ __attribute__((always_inline))
#else
#define U8G2_ALWAYS_INLINE
#endif
#if defined(U8G2_WITH_INTERSECTION) || defined(U8G2_WITH_CLIP_WINDOW_SUPPORT)
#ifdef OLD_VERSION_WITH_SYMETRIC_BOUNDARIES
/*
intersection assumptions:
a1 <= a2 is always true
minimized version
---1----0 1 b1 <= a2 && b1 > b2
-----1--0 1 b2 >= a1 && b1 > b2
---1-1--- 1 b1 <= a2 && b2 >= a1
*/
/*
calculate the intersection between a0/a1 and v0/v1
The intersection check returns one if the range of a0/a1 has an intersection with v0/v1.
The intersection check includes the boundary values v1 and a1.
The following asserts will succeed:
assert( u8g2_is_intersection_decision_tree(4, 6, 7, 9) == 0 );
assert( u8g2_is_intersection_decision_tree(4, 6, 6, 9) != 0 );
assert( u8g2_is_intersection_decision_tree(6, 9, 4, 6) != 0 );
assert( u8g2_is_intersection_decision_tree(7, 9, 4, 6) == 0 );
*/
//static uint8_t U8G2_ALWAYS_INLINE u8g2_is_intersection_decision_tree(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1)
static uint8_t u8g2_is_intersection_decision_tree(u8g2_uint_t a0, u8g2_uint_t a1, u8g2_uint_t v0, u8g2_uint_t v1)
{
if ( v0 <= a1 )
{
if ( v1 >= a0 )
{
return 1;
}
else
{
if ( v0 > v1 )
{
return 1;
}
else
{
return 0;
}
}
}
else
{
if ( v1 >= a0 )
{
if ( v0 > v1 )
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
#endif /* OLD_VERSION_WITH_SYMETRIC_BOUNDARIES */
/*
version with asymetric boundaries.
a1 and v1 are excluded
v0 == v1 is not support end return 1
*/
uint8_t u8g2_is_intersection_decision_tree(u8g2_uint_t a0, u8g2_uint_t a1, u8g2_uint_t v0, u8g2_uint_t v1)
{
if ( v0 < a1 ) // v0 <= a1
{
if ( v1 > a0 ) // v1 >= a0
{
return 1;
}
else
{
if ( v0 > v1 ) // v0 > v1
{
return 1;
}
else
{
return 0;
}
}
}
else
{
if ( v1 > a0 ) // v1 >= a0
{
if ( v0 > v1 ) // v0 > v1
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
/* upper limits are not included (asymetric boundaries) */
uint8_t u8g2_IsIntersection(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t x1, u8g2_uint_t y1)
{
if ( u8g2_is_intersection_decision_tree(u8g2->user_y0, u8g2->user_y1, y0, y1) == 0 )
return 0;
return u8g2_is_intersection_decision_tree(u8g2->user_x0, u8g2->user_x1, x0, x1);
}
#endif /* U8G2_WITH_INTERSECTION */

View File

@ -0,0 +1,94 @@
/*
u8g2_kerning.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/* this function is used as "u8g2_get_kerning_cb" */
/*
uint8_t u8g2_GetNullKerning(u8g2_t *u8g2, uint16_t e1, uint16_t e2)
{
return 0;
}
*/
/* this function is used as "u8g2_get_kerning_cb" */
uint8_t u8g2_GetKerning(U8X8_UNUSED u8g2_t *u8g2, u8g2_kerning_t *kerning, uint16_t e1, uint16_t e2)
{
uint16_t i1, i2, cnt, end;
if ( kerning == NULL )
return 0;
/* search for the encoding in the first table */
cnt = kerning->first_table_cnt;
cnt--; /* ignore the last element of the table, which is 0x0ffff */
for( i1 = 0; i1 < cnt; i1++ )
{
if ( kerning->first_encoding_table[i1] == e1 )
break;
}
if ( i1 >= cnt )
return 0; /* e1 not part of the kerning table, return 0 */
/* get the upper index for i2 */
end = kerning->index_to_second_table[i1+1];
for( i2 = kerning->index_to_second_table[i1]; i2 < end; i2++ )
{
if ( kerning->second_encoding_table[i2] == e2 )
break;
}
if ( i2 >= end )
return 0; /* e2 not part of any pair with e1, return 0 */
return kerning->kerning_values[i2];
}
uint8_t u8g2_GetKerningByTable(U8X8_UNUSED u8g2_t *u8g2, const uint16_t *kt, uint16_t e1, uint16_t e2)
{
uint16_t i;
i = 0;
if ( kt == NULL )
return 0;
for(;;)
{
if ( kt[i] == 0x0ffff )
break;
if ( kt[i] == e1 && kt[i+1] == e2 )
return kt[i+2];
i+=3;
}
return 0;
}

View File

@ -0,0 +1,92 @@
/*
u8g2_box.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
void u8g2_DrawLine(u8g2_t *u8g2, u8g2_uint_t x1, u8g2_uint_t y1, u8g2_uint_t x2, u8g2_uint_t y2)
{
u8g2_uint_t tmp;
u8g2_uint_t x,y;
u8g2_uint_t dx, dy;
u8g2_int_t err;
u8g2_int_t ystep;
uint8_t swapxy = 0;
/* no intersection check at the moment, should be added... */
if ( x1 > x2 ) dx = x1-x2; else dx = x2-x1;
if ( y1 > y2 ) dy = y1-y2; else dy = y2-y1;
if ( dy > dx )
{
swapxy = 1;
tmp = dx; dx =dy; dy = tmp;
tmp = x1; x1 =y1; y1 = tmp;
tmp = x2; x2 =y2; y2 = tmp;
}
if ( x1 > x2 )
{
tmp = x1; x1 =x2; x2 = tmp;
tmp = y1; y1 =y2; y2 = tmp;
}
err = dx >> 1;
if ( y2 > y1 ) ystep = 1; else ystep = -1;
y = y1;
#ifndef U8G2_16BIT
if ( x2 == 255 )
x2--;
#else
if ( x2 == 0xffff )
x2--;
#endif
for( x = x1; x <= x2; x++ )
{
if ( swapxy == 0 )
u8g2_DrawPixel(u8g2, x, y);
else
u8g2_DrawPixel(u8g2, y, x);
err -= (uint8_t)dy;
if ( err < 0 )
{
y += (u8g2_uint_t)ystep;
err += (u8g2_uint_t)dx;
}
}
}

View File

@ -0,0 +1,371 @@
/*
u8g2_ll_hvline.c
low level hvline
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*ptr |= or_mask
*ptr ^= xor_mask
color = 0: or_mask = 1, xor_mask = 1
color = 1: or_mask = 1, xor_mask = 0
color = 2: or_mask = 0, xor_mask = 1
if ( color <= 1 )
or_mask = mask;
if ( color != 1 )
xor_mask = mask;
*/
#include "u8g2.h"
#include <assert.h>
/*=================================================*/
/*
u8g2_ll_hvline_vertical_top_lsb
SSD13xx
UC1701
*/
#ifdef U8G2_WITH_HVLINE_SPEED_OPTIMIZATION
/*
x,y Upper left position of the line within the local buffer (not the display!)
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
asumption:
all clipping done
*/
void u8g2_ll_hvline_vertical_top_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
uint16_t offset;
uint8_t *ptr;
uint8_t bit_pos, mask;
uint8_t or_mask, xor_mask;
#ifdef __unix
uint8_t *max_ptr = u8g2->tile_buf_ptr + u8g2_GetU8x8(u8g2)->display_info->tile_width*u8g2->tile_buf_height*8;
#endif
//assert(x >= u8g2->buf_x0);
//assert(x < u8g2_GetU8x8(u8g2)->display_info->tile_width*8);
//assert(y >= u8g2->buf_y0);
//assert(y < u8g2_GetU8x8(u8g2)->display_info->tile_height*8);
/* bytes are vertical, lsb on top (y=0), msb at bottom (y=7) */
bit_pos = y; /* overflow truncate is ok here... */
bit_pos &= 7; /* ... because only the lowest 3 bits are needed */
mask = 1;
mask <<= bit_pos;
or_mask = 0;
xor_mask = 0;
if ( u8g2->draw_color <= 1 )
or_mask = mask;
if ( u8g2->draw_color != 1 )
xor_mask = mask;
offset = y; /* y might be 8 or 16 bit, but we need 16 bit, so use a 16 bit variable */
offset &= ~7;
offset *= u8g2_GetU8x8(u8g2)->display_info->tile_width;
ptr = u8g2->tile_buf_ptr;
ptr += offset;
ptr += x;
if ( dir == 0 )
{
do
{
#ifdef __unix
assert(ptr < max_ptr);
#endif
*ptr |= or_mask;
*ptr ^= xor_mask;
ptr++;
len--;
} while( len != 0 );
}
else
{
do
{
#ifdef __unix
assert(ptr < max_ptr);
#endif
*ptr |= or_mask;
*ptr ^= xor_mask;
bit_pos++;
bit_pos &= 7;
len--;
if ( bit_pos == 0 )
{
ptr+=u8g2->pixel_buf_width; /* 6 Jan 17: Changed u8g2->width to u8g2->pixel_buf_width, issue #148 */
if ( u8g2->draw_color <= 1 )
or_mask = 1;
if ( u8g2->draw_color != 1 )
xor_mask = 1;
}
else
{
or_mask <<= 1;
xor_mask <<= 1;
}
} while( len != 0 );
}
}
#else /* U8G2_WITH_HVLINE_SPEED_OPTIMIZATION */
/*
x,y position within the buffer
*/
static void u8g2_draw_pixel_vertical_top_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y)
{
uint16_t offset;
uint8_t *ptr;
uint8_t bit_pos, mask;
//assert(x >= u8g2->buf_x0);
//assert(x < u8g2_GetU8x8(u8g2)->display_info->tile_width*8);
//assert(y >= u8g2->buf_y0);
//assert(y < u8g2_GetU8x8(u8g2)->display_info->tile_height*8);
/* bytes are vertical, lsb on top (y=0), msb at bottom (y=7) */
bit_pos = y; /* overflow truncate is ok here... */
bit_pos &= 7; /* ... because only the lowest 3 bits are needed */
mask = 1;
mask <<= bit_pos;
offset = y; /* y might be 8 or 16 bit, but we need 16 bit, so use a 16 bit variable */
offset &= ~7;
offset *= u8g2_GetU8x8(u8g2)->display_info->tile_width;
ptr = u8g2->tile_buf_ptr;
ptr += offset;
ptr += x;
if ( u8g2->draw_color <= 1 )
*ptr |= mask;
if ( u8g2->draw_color != 1 )
*ptr ^= mask;
}
/*
x,y Upper left position of the line within the local buffer (not the display!)
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
asumption:
all clipping done
*/
void u8g2_ll_hvline_vertical_top_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
if ( dir == 0 )
{
do
{
u8g2_draw_pixel_vertical_top_lsb(u8g2, x, y);
x++;
len--;
} while( len != 0 );
}
else
{
do
{
u8g2_draw_pixel_vertical_top_lsb(u8g2, x, y);
y++;
len--;
} while( len != 0 );
}
}
#endif /* U8G2_WITH_HVLINE_SPEED_OPTIMIZATION */
/*=================================================*/
/*
u8g2_ll_hvline_horizontal_right_lsb
ST7920
*/
#ifdef U8G2_WITH_HVLINE_SPEED_OPTIMIZATION
/*
x,y Upper left position of the line within the local buffer (not the display!)
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
asumption:
all clipping done
*/
/* SH1122, LD7032, ST7920, ST7986, LC7981, T6963, SED1330, RA8835, MAX7219, LS0 */
void u8g2_ll_hvline_horizontal_right_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
uint16_t offset;
uint8_t *ptr;
uint8_t bit_pos;
uint8_t mask;
uint8_t tile_width = u8g2_GetU8x8(u8g2)->display_info->tile_width;
bit_pos = x; /* overflow truncate is ok here... */
bit_pos &= 7; /* ... because only the lowest 3 bits are needed */
mask = 128;
mask >>= bit_pos;
offset = y; /* y might be 8 or 16 bit, but we need 16 bit, so use a 16 bit variable */
offset *= tile_width;
offset += x>>3;
ptr = u8g2->tile_buf_ptr;
ptr += offset;
if ( dir == 0 )
{
do
{
if ( u8g2->draw_color <= 1 )
*ptr |= mask;
if ( u8g2->draw_color != 1 )
*ptr ^= mask;
mask >>= 1;
if ( mask == 0 )
{
mask = 128;
ptr++;
}
//x++;
len--;
} while( len != 0 );
}
else
{
do
{
if ( u8g2->draw_color <= 1 )
*ptr |= mask;
if ( u8g2->draw_color != 1 )
*ptr ^= mask;
ptr += tile_width;
//y++;
len--;
} while( len != 0 );
}
}
#else /* U8G2_WITH_HVLINE_SPEED_OPTIMIZATION */
/*
x,y position within the buffer
*/
/* SH1122, LD7032, ST7920, ST7986, LC7981, T6963, SED1330, RA8835, MAX7219, LS0 */
static void u8g2_draw_pixel_horizontal_right_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y)
{
uint16_t offset;
uint8_t *ptr;
uint8_t bit_pos, mask;
//assert(x >= u8g2->buf_x0);
//assert(x < u8g2_GetU8x8(u8g2)->display_info->tile_width*8);
//assert(y >= u8g2->buf_y0);
//assert(y < u8g2_GetU8x8(u8g2)->display_info->tile_height*8);
/* bytes are vertical, lsb on top (y=0), msb at bottom (y=7) */
bit_pos = x; /* overflow truncate is ok here... */
bit_pos &= 7; /* ... because only the lowest 3 bits are needed */
mask = 128;
mask >>= bit_pos;
x >>= 3;
offset = y; /* y might be 8 or 16 bit, but we need 16 bit, so use a 16 bit variable */
offset *= u8g2_GetU8x8(u8g2)->display_info->tile_width;
offset += x;
ptr = u8g2->tile_buf_ptr;
ptr += offset;
if ( u8g2->draw_color <= 1 )
*ptr |= mask;
if ( u8g2->draw_color != 1 )
*ptr ^= mask;
}
/*
x,y Upper left position of the line within the local buffer (not the display!)
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
asumption:
all clipping done
*/
/* SH1122, LD7032, ST7920, ST7986, LC7981, T6963, SED1330, RA8835, MAX7219, LS0 */
void u8g2_ll_hvline_horizontal_right_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
if ( dir == 0 )
{
do
{
u8g2_draw_pixel_horizontal_right_lsb(u8g2, x, y);
x++;
len--;
} while( len != 0 );
}
else
{
do
{
u8g2_draw_pixel_horizontal_right_lsb(u8g2, x, y);
y++;
len--;
} while( len != 0 );
}
}
#endif /* U8G2_WITH_HVLINE_SPEED_OPTIMIZATION */

View File

@ -0,0 +1,197 @@
/*
u8g2_message.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
#define SPACE_BETWEEN_BUTTONS_IN_PIXEL 6
#define SPACE_BETWEEN_TEXT_AND_BUTTONS_IN_PIXEL 3
uint8_t u8g2_draw_button_line(u8g2_t *u8g2, u8g2_uint_t y, u8g2_uint_t w, uint8_t cursor, const char *s)
{
u8g2_uint_t button_line_width;
uint8_t i;
uint8_t cnt;
uint8_t is_invert;
u8g2_uint_t d;
u8g2_uint_t x;
cnt = u8x8_GetStringLineCnt(s);
/* calculate the width of the button line */
button_line_width = 0;
for( i = 0; i < cnt; i++ )
{
button_line_width += u8g2_GetUTF8Width(u8g2, u8x8_GetStringLineStart(i, s));
}
button_line_width += (cnt-1)*SPACE_BETWEEN_BUTTONS_IN_PIXEL; /* add some space between the buttons */
/* calculate the left offset */
d = 0;
if ( button_line_width < w )
{
d = w;
d -= button_line_width;
d /= 2;
}
/* draw the buttons */
x = d;
for( i = 0; i < cnt; i++ )
{
is_invert = 0;
if ( i == cursor )
is_invert = 1;
u8g2_DrawUTF8Line(u8g2, x, y, 0, u8x8_GetStringLineStart(i, s), 1, is_invert);
x += u8g2_GetUTF8Width(u8g2, u8x8_GetStringLineStart(i, s));
x += SPACE_BETWEEN_BUTTONS_IN_PIXEL;
}
/* return the number of buttons */
return cnt;
}
/*
title1: Multiple lines,separated by '\n'
title2: A single line/string which is terminated by '\0' or '\n' . "title2" accepts the return value from u8x8_GetStringLineStart()
title3: Multiple lines,separated by '\n'
buttons: one more more buttons separated by '\n' and terminated with '\0'
side effects:
u8g2_SetFontDirection(u8g2, 0);
u8g2_SetFontPosBaseline(u8g2);
*/
uint8_t u8g2_UserInterfaceMessage(u8g2_t *u8g2, const char *title1, const char *title2, const char *title3, const char *buttons)
{
uint8_t height;
uint8_t line_height;
u8g2_uint_t pixel_height;
u8g2_uint_t y, yy;
uint8_t cursor = 0;
uint8_t button_cnt;
uint8_t event;
/* only horizontal strings are supported, so force this here */
u8g2_SetFontDirection(u8g2, 0);
/* force baseline position */
u8g2_SetFontPosBaseline(u8g2);
/* calculate line height */
line_height = u8g2_GetAscent(u8g2);
line_height -= u8g2_GetDescent(u8g2);
/* calculate overall height of the message box in lines*/
height = 1; /* button line */
height += u8x8_GetStringLineCnt(title1);
if ( title2 != NULL )
height++;
height += u8x8_GetStringLineCnt(title3);
/* calculate the height in pixel */
pixel_height = height;
pixel_height *= line_height;
/* ... and add the space between the text and the buttons */
pixel_height +=SPACE_BETWEEN_TEXT_AND_BUTTONS_IN_PIXEL;
/* calculate offset from top */
y = 0;
if ( pixel_height < u8g2_GetDisplayHeight(u8g2) )
{
y = u8g2_GetDisplayHeight(u8g2);
y -= pixel_height;
y /= 2;
}
y += u8g2_GetAscent(u8g2);
for(;;)
{
u8g2_FirstPage(u8g2);
do
{
yy = y;
/* draw message box */
yy += u8g2_DrawUTF8Lines(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), line_height, title1);
if ( title2 != NULL )
{
u8g2_DrawUTF8Line(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), title2, 0, 0);
yy+=line_height;
}
yy += u8g2_DrawUTF8Lines(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), line_height, title3);
yy += SPACE_BETWEEN_TEXT_AND_BUTTONS_IN_PIXEL;
button_cnt = u8g2_draw_button_line(u8g2, yy, u8g2_GetDisplayWidth(u8g2), cursor, buttons);
} while( u8g2_NextPage(u8g2) );
#ifdef U8G2_REF_MAN_PIC
return 0;
#endif
for(;;)
{
event = u8x8_GetMenuEvent(u8g2_GetU8x8(u8g2));
if ( event == U8X8_MSG_GPIO_MENU_SELECT )
return cursor+1;
else if ( event == U8X8_MSG_GPIO_MENU_HOME )
return 0;
else if ( event == U8X8_MSG_GPIO_MENU_NEXT || event == U8X8_MSG_GPIO_MENU_DOWN )
{
cursor++;
if ( cursor >= button_cnt )
cursor = 0;
break;
}
else if ( event == U8X8_MSG_GPIO_MENU_PREV || event == U8X8_MSG_GPIO_MENU_UP )
{
if ( cursor == 0 )
cursor = button_cnt;
cursor--;
break;
}
}
}
/* never reached */
//return 0;
}

View File

@ -0,0 +1,346 @@
/*
u8g22_polygon.c
*/
#include "u8g2.h"
/*===========================================*/
/* local definitions */
typedef int16_t pg_word_t;
struct pg_point_struct
{
pg_word_t x;
pg_word_t y;
};
typedef struct _pg_struct pg_struct; /* forward declaration */
struct pg_edge_struct
{
pg_word_t x_direction; /* 1, if x2 is greater than x1, -1 otherwise */
pg_word_t height;
pg_word_t current_x_offset;
pg_word_t error_offset;
/* --- line loop --- */
pg_word_t current_y;
pg_word_t max_y;
pg_word_t current_x;
pg_word_t error;
/* --- outer loop --- */
uint8_t (*next_idx_fn)(pg_struct *pg, uint8_t i);
uint8_t curr_idx;
};
/* maximum number of points in the polygon */
/* can be redefined, but highest possible value is 254 */
#define PG_MAX_POINTS 6
/* index numbers for the pge structures below */
#define PG_LEFT 0
#define PG_RIGHT 1
struct _pg_struct
{
struct pg_point_struct list[PG_MAX_POINTS];
uint8_t cnt;
uint8_t is_min_y_not_flat;
pg_word_t total_scan_line_cnt;
struct pg_edge_struct pge[2]; /* left and right line draw structures */
};
/*===========================================*/
/* procedures, which should not be inlined (save as much flash ROM as possible */
#define PG_NOINLINE U8G2_NOINLINE
static uint8_t pge_Next(struct pg_edge_struct *pge) PG_NOINLINE;
static uint8_t pg_inc(pg_struct *pg, uint8_t i) PG_NOINLINE;
static uint8_t pg_dec(pg_struct *pg, uint8_t i) PG_NOINLINE;
static void pg_expand_min_y(pg_struct *pg, pg_word_t min_y, uint8_t pge_idx) PG_NOINLINE;
static void pg_line_init(pg_struct * const pg, uint8_t pge_index) PG_NOINLINE;
/*===========================================*/
/* line draw algorithm */
static uint8_t pge_Next(struct pg_edge_struct *pge)
{
if ( pge->current_y >= pge->max_y )
return 0;
pge->current_x += pge->current_x_offset;
pge->error += pge->error_offset;
if ( pge->error > 0 )
{
pge->current_x += pge->x_direction;
pge->error -= pge->height;
}
pge->current_y++;
return 1;
}
/* assumes y2 > y1 */
static void pge_Init(struct pg_edge_struct *pge, pg_word_t x1, pg_word_t y1, pg_word_t x2, pg_word_t y2)
{
pg_word_t dx = x2 - x1;
pg_word_t width;
pge->height = y2 - y1;
pge->max_y = y2;
pge->current_y = y1;
pge->current_x = x1;
if ( dx >= 0 )
{
pge->x_direction = 1;
width = dx;
pge->error = 0;
}
else
{
pge->x_direction = -1;
width = -dx;
pge->error = 1 - pge->height;
}
pge->current_x_offset = dx / pge->height;
pge->error_offset = width % pge->height;
}
/*===========================================*/
/* convex polygon algorithm */
static uint8_t pg_inc(pg_struct *pg, uint8_t i)
{
i++;
if ( i >= pg->cnt )
i = 0;
return i;
}
static uint8_t pg_dec(pg_struct *pg, uint8_t i)
{
i--;
if ( i >= pg->cnt )
i = pg->cnt-1;
return i;
}
static void pg_expand_min_y(pg_struct *pg, pg_word_t min_y, uint8_t pge_idx)
{
uint8_t i = pg->pge[pge_idx].curr_idx;
for(;;)
{
i = pg->pge[pge_idx].next_idx_fn(pg, i);
if ( pg->list[i].y != min_y )
break;
pg->pge[pge_idx].curr_idx = i;
}
}
static uint8_t pg_prepare(pg_struct *pg)
{
pg_word_t max_y;
pg_word_t min_y;
uint8_t i;
/* setup the next index procedures */
pg->pge[PG_RIGHT].next_idx_fn = pg_inc;
pg->pge[PG_LEFT].next_idx_fn = pg_dec;
/* search for highest and lowest point */
max_y = pg->list[0].y;
min_y = pg->list[0].y;
pg->pge[PG_LEFT].curr_idx = 0;
for( i = 1; i < pg->cnt; i++ )
{
if ( max_y < pg->list[i].y )
{
max_y = pg->list[i].y;
}
if ( min_y > pg->list[i].y )
{
pg->pge[PG_LEFT].curr_idx = i;
min_y = pg->list[i].y;
}
}
/* calculate total number of scan lines */
pg->total_scan_line_cnt = max_y;
pg->total_scan_line_cnt -= min_y;
/* exit if polygon height is zero */
if ( pg->total_scan_line_cnt == 0 )
return 0;
/* if the minimum y side is flat, try to find the lowest and highest x points */
pg->pge[PG_RIGHT].curr_idx = pg->pge[PG_LEFT].curr_idx;
pg_expand_min_y(pg, min_y, PG_RIGHT);
pg_expand_min_y(pg, min_y, PG_LEFT);
/* check if the min side is really flat (depends on the x values) */
pg->is_min_y_not_flat = 1;
if ( pg->list[pg->pge[PG_LEFT].curr_idx].x != pg->list[pg->pge[PG_RIGHT].curr_idx].x )
{
pg->is_min_y_not_flat = 0;
}
else
{
pg->total_scan_line_cnt--;
if ( pg->total_scan_line_cnt == 0 )
return 0;
}
return 1;
}
static void pg_hline(pg_struct *pg, u8g2_t *u8g2)
{
pg_word_t x1, x2, y;
x1 = pg->pge[PG_LEFT].current_x;
x2 = pg->pge[PG_RIGHT].current_x;
y = pg->pge[PG_RIGHT].current_y;
if ( y < 0 )
return;
if ( y >= u8g2_GetDisplayHeight(u8g2) ) // does not work for 256x64 display???
return;
if ( x1 < x2 )
{
if ( x2 < 0 )
return;
if ( x1 >= u8g2_GetDisplayWidth(u8g2) )
return;
if ( x1 < 0 )
x1 = 0;
if ( x2 >= u8g2_GetDisplayWidth(u8g2) )
x2 = u8g2_GetDisplayWidth(u8g2);
u8g2_DrawHLine(u8g2, x1, y, x2 - x1);
}
else
{
if ( x1 < 0 )
return;
if ( x2 >= u8g2_GetDisplayWidth(u8g2) )
return;
if ( x2 < 0 )
x1 = 0;
if ( x1 >= u8g2_GetDisplayWidth(u8g2) )
x1 = u8g2_GetDisplayWidth(u8g2);
u8g2_DrawHLine(u8g2, x2, y, x1 - x2);
}
}
static void pg_line_init(pg_struct * const pg, uint8_t pge_index)
{
struct pg_edge_struct *pge = pg->pge+pge_index;
uint8_t idx;
pg_word_t x1;
pg_word_t y1;
pg_word_t x2;
pg_word_t y2;
idx = pge->curr_idx;
y1 = pg->list[idx].y;
x1 = pg->list[idx].x;
idx = pge->next_idx_fn(pg, idx);
y2 = pg->list[idx].y;
x2 = pg->list[idx].x;
pge->curr_idx = idx;
pge_Init(pge, x1, y1, x2, y2);
}
static void pg_exec(pg_struct *pg, u8g2_t *u8g2)
{
pg_word_t i = pg->total_scan_line_cnt;
/* first line is skipped if the min y line is not flat */
pg_line_init(pg, PG_LEFT);
pg_line_init(pg, PG_RIGHT);
if ( pg->is_min_y_not_flat != 0 )
{
pge_Next(&(pg->pge[PG_LEFT]));
pge_Next(&(pg->pge[PG_RIGHT]));
}
do
{
pg_hline(pg, u8g2);
while ( pge_Next(&(pg->pge[PG_LEFT])) == 0 )
{
pg_line_init(pg, PG_LEFT);
}
while ( pge_Next(&(pg->pge[PG_RIGHT])) == 0 )
{
pg_line_init(pg, PG_RIGHT);
}
i--;
} while( i > 0 );
}
/*===========================================*/
/* API procedures */
static void pg_ClearPolygonXY(pg_struct *pg)
{
pg->cnt = 0;
}
static void pg_AddPolygonXY(pg_struct *pg, int16_t x, int16_t y)
{
if ( pg->cnt < PG_MAX_POINTS )
{
pg->list[pg->cnt].x = x;
pg->list[pg->cnt].y = y;
pg->cnt++;
}
}
static void pg_DrawPolygon(pg_struct *pg, u8g2_t *u8g2)
{
if ( pg_prepare(pg) == 0 )
return;
pg_exec(pg, u8g2);
}
pg_struct u8g2_pg;
void u8g2_ClearPolygonXY(void)
{
pg_ClearPolygonXY(&u8g2_pg);
}
void u8g2_AddPolygonXY(U8X8_UNUSED u8g2_t *u8g2, int16_t x, int16_t y)
{
pg_AddPolygonXY(&u8g2_pg, x, y);
}
void u8g2_DrawPolygon(u8g2_t *u8g2)
{
pg_DrawPolygon(&u8g2_pg, u8g2);
}
void u8g2_DrawTriangle(u8g2_t *u8g2, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
{
u8g2_ClearPolygonXY();
u8g2_AddPolygonXY(u8g2, x0, y0);
u8g2_AddPolygonXY(u8g2, x1, y1);
u8g2_AddPolygonXY(u8g2, x2, y2);
u8g2_DrawPolygon(u8g2);
}

View File

@ -0,0 +1,284 @@
/*
u8g2_selection_list.c
selection list with scroll option
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
#define MY_BORDER_SIZE 1
/*
Draw a string at x,y
Center string within w (left adjust if w < pixel len of s)
Side effects:
u8g2_SetFontDirection(u8g2, 0);
u8g2_SetFontPosBaseline(u8g2);
*/
void u8g2_DrawUTF8Line(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, const char *s, uint8_t border_size, uint8_t is_invert)
{
u8g2_uint_t d, str_width;
u8g2_uint_t fx, fy, fw, fh;
/* only horizontal strings are supported, so force this here */
u8g2_SetFontDirection(u8g2, 0);
/* revert y position back to baseline ref */
y += u8g2->font_calc_vref(u8g2);
/* calculate the width of the string in pixel */
str_width = u8g2_GetUTF8Width(u8g2, s);
/* calculate delta d within the box */
d = 0;
if ( str_width < w )
{
d = w;
d -=str_width;
d /= 2;
}
else
{
w = str_width;
}
/* caluclate text box */
fx = x;
fy = y - u8g2_GetAscent(u8g2) ;
fw = w;
fh = u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2) ;
/* draw the box, if inverted */
u8g2_SetDrawColor(u8g2, 1);
if ( is_invert )
{
u8g2_DrawBox(u8g2, fx, fy, fw, fh);
}
/* draw the frame */
while( border_size > 0 )
{
fx--;
fy--;
fw +=2;
fh +=2;
u8g2_DrawFrame(u8g2, fx, fy, fw, fh );
border_size--;
}
if ( is_invert )
{
u8g2_SetDrawColor(u8g2, 0);
}
else
{
u8g2_SetDrawColor(u8g2, 1);
}
/* draw the text */
u8g2_DrawUTF8(u8g2, x+d, y, s);
/* revert draw color */
u8g2_SetDrawColor(u8g2, 1);
}
/*
draw several lines at position x,y.
lines are stored in s and must be separated with '\n'.
lines can be centered with respect to "w"
if s == NULL nothing is drawn and 0 is returned
returns the number of lines in s multiplied with line_height
*/
u8g2_uint_t u8g2_DrawUTF8Lines(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t line_height, const char *s)
{
uint8_t i;
uint8_t cnt;
u8g2_uint_t yy = 0;
cnt = u8x8_GetStringLineCnt(s);
//printf("str=%s\n", s);
//printf("cnt=%d, y=%d, line_height=%d\n", cnt, y, line_height);
for( i = 0; i < cnt; i++ )
{
//printf(" i=%d, y=%d, line_height=%d\n", i, y, line_height);
u8g2_DrawUTF8Line(u8g2, x, y, w, u8x8_GetStringLineStart(i, s), 0, 0);
y+=line_height;
yy+=line_height;
}
return yy;
}
/*
selection list with string line
returns line height
*/
static u8g2_uint_t u8g2_draw_selection_list_line(u8g2_t *u8g2, u8sl_t *u8sl, u8g2_uint_t y, uint8_t idx, const char *s) U8G2_NOINLINE;
static u8g2_uint_t u8g2_draw_selection_list_line(u8g2_t *u8g2, u8sl_t *u8sl, u8g2_uint_t y, uint8_t idx, const char *s)
{
u8g2_uint_t yy;
uint8_t border_size = 0;
uint8_t is_invert = 0;
u8g2_uint_t line_height = u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2)+MY_BORDER_SIZE;
/* calculate offset from display upper border */
yy = idx;
yy -= u8sl->first_pos;
yy *= line_height;
yy += y;
/* check whether this is the current cursor line */
if ( idx == u8sl->current_pos )
{
border_size = MY_BORDER_SIZE;
is_invert = 1;
}
/* get the line from the array */
s = u8x8_GetStringLineStart(idx, s);
/* draw the line */
if ( s == NULL )
s = "";
u8g2_DrawUTF8Line(u8g2, MY_BORDER_SIZE, y, u8g2_GetDisplayWidth(u8g2)-2*MY_BORDER_SIZE, s, border_size, is_invert);
return line_height;
}
void u8g2_DrawSelectionList(u8g2_t *u8g2, u8sl_t *u8sl, u8g2_uint_t y, const char *s)
{
uint8_t i;
for( i = 0; i < u8sl->visible; i++ )
{
y += u8g2_draw_selection_list_line(u8g2, u8sl, y, i+u8sl->first_pos, s);
}
}
/*
title: NULL for no title, valid str for title line. Can contain mutliple lines, separated by '\n'
start_pos: default position for the cursor, first line is 1.
sl: string list (list of strings separated by \n)
returns 0 if user has pressed the home key
returns the selected line if user has pressed the select key
side effects:
u8g2_SetFontDirection(u8g2, 0);
u8g2_SetFontPosBaseline(u8g2);
*/
uint8_t u8g2_UserInterfaceSelectionList(u8g2_t *u8g2, const char *title, uint8_t start_pos, const char *sl)
{
u8sl_t u8sl;
u8g2_uint_t yy;
uint8_t event;
u8g2_uint_t line_height = u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2)+MY_BORDER_SIZE;
uint8_t title_lines = u8x8_GetStringLineCnt(title);
uint8_t display_lines;
if ( start_pos > 0 ) /* issue 112 */
start_pos--; /* issue 112 */
if ( title_lines > 0 )
{
display_lines = (u8g2_GetDisplayHeight(u8g2)-3) / line_height;
u8sl.visible = display_lines;
u8sl.visible -= title_lines;
}
else
{
display_lines = u8g2_GetDisplayHeight(u8g2) / line_height;
u8sl.visible = display_lines;
}
u8sl.total = u8x8_GetStringLineCnt(sl);
u8sl.first_pos = 0;
u8sl.current_pos = start_pos;
if ( u8sl.current_pos >= u8sl.total )
u8sl.current_pos = u8sl.total-1;
if ( u8sl.first_pos+u8sl.visible <= u8sl.current_pos )
u8sl.first_pos = u8sl.current_pos-u8sl.visible+1;
u8g2_SetFontPosBaseline(u8g2);
for(;;)
{
u8g2_FirstPage(u8g2);
do
{
yy = u8g2_GetAscent(u8g2);
if ( title_lines > 0 )
{
yy += u8g2_DrawUTF8Lines(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), line_height, title);
u8g2_DrawHLine(u8g2, 0, yy-line_height- u8g2_GetDescent(u8g2) + 1, u8g2_GetDisplayWidth(u8g2));
yy += 3;
}
u8g2_DrawSelectionList(u8g2, &u8sl, yy, sl);
} while( u8g2_NextPage(u8g2) );
#ifdef U8G2_REF_MAN_PIC
return 0;
#endif
for(;;)
{
event = u8x8_GetMenuEvent(u8g2_GetU8x8(u8g2));
if ( event == U8X8_MSG_GPIO_MENU_SELECT )
return u8sl.current_pos+1; /* +1, issue 112 */
else if ( event == U8X8_MSG_GPIO_MENU_HOME )
return 0; /* issue 112: return 0 instead of start_pos */
else if ( event == U8X8_MSG_GPIO_MENU_NEXT || event == U8X8_MSG_GPIO_MENU_DOWN )
{
u8sl_Next(&u8sl);
break;
}
else if ( event == U8X8_MSG_GPIO_MENU_PREV || event == U8X8_MSG_GPIO_MENU_UP )
{
u8sl_Prev(&u8sl);
break;
}
}
}
}

View File

@ -0,0 +1,468 @@
/*
u8g2_setup.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
#include <string.h>
#include <assert.h>
/*============================================*/
#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT
void u8g2_SetMaxClipWindow(u8g2_t *u8g2)
{
u8g2->clip_x0 = 0;
u8g2->clip_y0 = 0;
u8g2->clip_x1 = (u8g2_uint_t)~(u8g2_uint_t)0;
u8g2->clip_y1 = (u8g2_uint_t)~(u8g2_uint_t)0;
u8g2->cb->update_page_win(u8g2);
}
void u8g2_SetClipWindow(u8g2_t *u8g2, u8g2_uint_t clip_x0, u8g2_uint_t clip_y0, u8g2_uint_t clip_x1, u8g2_uint_t clip_y1 )
{
u8g2->clip_x0 = clip_x0;
u8g2->clip_y0 = clip_y0;
u8g2->clip_x1 = clip_x1;
u8g2->clip_y1 = clip_y1;
u8g2->cb->update_page_win(u8g2);
}
#endif
/*============================================*/
/*
This procedure is called after setting up the display (u8x8 structure).
--> This is the central init procedure for u8g2 object
*/
void u8g2_SetupBuffer(u8g2_t *u8g2, uint8_t *buf, uint8_t tile_buf_height, u8g2_draw_ll_hvline_cb ll_hvline_cb, const u8g2_cb_t *u8g2_cb)
{
u8g2->font = NULL;
//u8g2->kerning = NULL;
//u8g2->get_kerning_cb = u8g2_GetNullKerning;
//u8g2->ll_hvline = u8g2_ll_hvline_vertical_top_lsb;
u8g2->ll_hvline = ll_hvline_cb;
u8g2->tile_buf_ptr = buf;
u8g2->tile_buf_height = tile_buf_height;
u8g2->tile_curr_row = 0;
u8g2->font_decode.is_transparent = 0; /* issue 443 */
u8g2->bitmap_transparency = 0;
u8g2->draw_color = 1;
u8g2->is_auto_page_clear = 1;
u8g2->cb = u8g2_cb;
u8g2->cb->update_dimension(u8g2);
#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT
u8g2_SetMaxClipWindow(u8g2); /* assign a clip window and call the update() procedure */
#else
u8g2->cb->update_page_win(u8g2);
#endif
u8g2_SetFontPosBaseline(u8g2); /* issue 195 */
#ifdef U8G2_WITH_FONT_ROTATION
u8g2->font_decode.dir = 0;
#endif
}
/*
Usually the display rotation is set initially, but it could be done later also
u8g2_cb can be U8G2_R0..U8G2_R3
*/
void u8g2_SetDisplayRotation(u8g2_t *u8g2, const u8g2_cb_t *u8g2_cb)
{
u8g2->cb = u8g2_cb;
u8g2->cb->update_dimension(u8g2);
u8g2->cb->update_page_win(u8g2);
}
/*============================================*/
void u8g2_SendF(u8g2_t * u8g2, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
u8x8_cad_vsendf(u8g2_GetU8x8(u8g2), fmt, va);
va_end(va);
}
/*============================================*/
/*
update dimension:
calculate the following variables:
u8g2_uint_t buf_x0; left corner of the buffer
u8g2_uint_t buf_x1; right corner of the buffer (excluded)
u8g2_uint_t buf_y0;
u8g2_uint_t buf_y1;
*/
static void u8g2_update_dimension_common(u8g2_t *u8g2)
{
const u8x8_display_info_t *display_info = u8g2_GetU8x8(u8g2)->display_info;
u8g2_uint_t t;
t = u8g2->tile_buf_height;
t *= 8;
u8g2->pixel_buf_height = t;
t = display_info->tile_width;
#ifndef U8G2_16BIT
if ( t >= 32 )
t = 31;
#endif
t *= 8;
u8g2->pixel_buf_width = t;
t = u8g2->tile_curr_row;
t *= 8;
u8g2->pixel_curr_row = t;
t = u8g2->tile_buf_height;
/* handle the case, where the buffer is larger than the (remaining) part of the display */
if ( t + u8g2->tile_curr_row > display_info->tile_height )
t = display_info->tile_height - u8g2->tile_curr_row;
t *= 8;
u8g2->buf_y0 = u8g2->pixel_curr_row;
u8g2->buf_y1 = u8g2->buf_y0;
u8g2->buf_y1 += t;
#ifdef U8G2_16BIT
u8g2->width = display_info->pixel_width;
u8g2->height = display_info->pixel_height;
#else
u8g2->width = 240;
if ( display_info->pixel_width <= 240 )
u8g2->width = display_info->pixel_width;
u8g2->height = display_info->pixel_height;
#endif
}
/*==========================================================*/
/* apply clip window */
#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT
static void u8g2_apply_clip_window(u8g2_t *u8g2)
{
/* check aganst the current user_??? window */
if ( u8g2_IsIntersection(u8g2, u8g2->clip_x0, u8g2->clip_y0, u8g2->clip_x1, u8g2->clip_y1) == 0 )
{
u8g2->is_page_clip_window_intersection = 0;
}
else
{
u8g2->is_page_clip_window_intersection = 1;
if ( u8g2->user_x0 < u8g2->clip_x0 )
u8g2->user_x0 = u8g2->clip_x0;
if ( u8g2->user_x1 > u8g2->clip_x1 )
u8g2->user_x1 = u8g2->clip_x1;
if ( u8g2->user_y0 < u8g2->clip_y0 )
u8g2->user_y0 = u8g2->clip_y0;
if ( u8g2->user_y1 > u8g2->clip_y1 )
u8g2->user_y1 = u8g2->clip_y1;
}
}
#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */
/*==========================================================*/
void u8g2_update_dimension_r0(u8g2_t *u8g2)
{
u8g2_update_dimension_common(u8g2);
}
void u8g2_update_page_win_r0(u8g2_t *u8g2)
{
u8g2->user_x0 = 0;
u8g2->user_x1 = u8g2->width; /* pixel_buf_width replaced with width */
u8g2->user_y0 = u8g2->buf_y0;
u8g2->user_y1 = u8g2->buf_y1;
#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT
u8g2_apply_clip_window(u8g2);
#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */
}
void u8g2_update_dimension_r1(u8g2_t *u8g2)
{
u8g2_update_dimension_common(u8g2);
u8g2->height = u8g2_GetU8x8(u8g2)->display_info->pixel_width;
u8g2->width = u8g2_GetU8x8(u8g2)->display_info->pixel_height;
}
void u8g2_update_page_win_r1(u8g2_t *u8g2)
{
u8g2->user_x0 = u8g2->buf_y0;
u8g2->user_x1 = u8g2->buf_y1;
u8g2->user_y0 = 0;
u8g2->user_y1 = u8g2->height; /* pixel_buf_width replaced with height (which is the real pixel width) */
#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT
u8g2_apply_clip_window(u8g2);
#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */
}
void u8g2_update_dimension_r2(u8g2_t *u8g2)
{
u8g2_update_dimension_common(u8g2);
}
void u8g2_update_page_win_r2(u8g2_t *u8g2)
{
u8g2->user_x0 = 0;
u8g2->user_x1 = u8g2->width; /* pixel_buf_width replaced with width */
/* there are ases where the height is not a multiple of 8. */
/* in such a case u8g2->buf_y1 might be heigher than u8g2->height */
u8g2->user_y0 = 0;
if ( u8g2->height >= u8g2->buf_y1 )
u8g2->user_y0 = u8g2->height - u8g2->buf_y1;
u8g2->user_y1 = u8g2->height - u8g2->buf_y0;
#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT
u8g2_apply_clip_window(u8g2);
#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */
}
void u8g2_update_dimension_r3(u8g2_t *u8g2)
{
u8g2_update_dimension_common(u8g2);
u8g2->height = u8g2_GetU8x8(u8g2)->display_info->pixel_width;
u8g2->width = u8g2_GetU8x8(u8g2)->display_info->pixel_height;
}
void u8g2_update_page_win_r3(u8g2_t *u8g2)
{
/* there are ases where the height is not a multiple of 8. */
/* in such a case u8g2->buf_y1 might be heigher than u8g2->width */
u8g2->user_x0 = 0;
if ( u8g2->width >= u8g2->buf_y1 )
u8g2->user_x0 = u8g2->width - u8g2->buf_y1;
u8g2->user_x1 = u8g2->width - u8g2->buf_y0;
u8g2->user_y0 = 0;
u8g2->user_y1 = u8g2->height; /* pixel_buf_width replaced with height (pixel_width) */
#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT
u8g2_apply_clip_window(u8g2);
#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */
}
/*============================================*/
extern void u8g2_draw_hv_line_2dir(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir);
void u8g2_draw_l90_r0(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
#ifdef __unix
assert( dir <= 1 );
#endif
u8g2_draw_hv_line_2dir(u8g2, x, y, len, dir);
}
void u8g2_draw_l90_mirrorr_r0(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_uint_t xx;
xx = u8g2->width;
xx -= x;
if ( (dir & 1) == 0 )
{
xx -= len;
}
else
{
xx--;
}
u8g2_draw_hv_line_2dir(u8g2, xx, y, len, dir);
}
void u8g2_draw_mirror_vertical_r0(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_uint_t yy;
yy = u8g2->height;
yy -= y;
if ( (dir & 1) == 1 )
{
yy -= len;
}
else
{
yy--;
}
u8g2_draw_hv_line_2dir(u8g2, x, yy, len, dir);
}
/* dir = 0 or 1 */
void u8g2_draw_l90_r1(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_uint_t xx, yy;
#ifdef __unix
assert( dir <= 1 );
#endif
yy = x;
xx = u8g2->height;
xx -= y;
xx--;
dir ++;
if ( dir == 2 )
{
xx -= len;
xx++;
dir = 0;
}
u8g2_draw_hv_line_2dir(u8g2, xx, yy, len, dir);
}
void u8g2_draw_l90_r2(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_uint_t xx, yy;
/*
yy = u8g2->height;
yy -= y;
yy--;
xx = u8g2->width;
xx -= x;
xx--;
if ( dir == 0 )
{
xx -= len;
xx++;
}
else if ( dir == 1 )
{
yy -= len;
yy++;
}
*/
yy = u8g2->height;
yy -= y;
xx = u8g2->width;
xx -= x;
if ( dir == 0 )
{
yy--;
xx -= len;
}
else if ( dir == 1 )
{
xx--;
yy -= len;
}
u8g2_draw_hv_line_2dir(u8g2, xx, yy, len, dir);
}
void u8g2_draw_l90_r3(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_uint_t xx, yy;
xx = y;
yy = u8g2->width;
yy -= x;
if ( dir == 0 )
{
yy--;
yy -= len;
yy++;
dir = 1;
}
else
{
yy--;
dir = 0;
}
u8g2_draw_hv_line_2dir(u8g2, xx, yy, len, dir);
}
/*============================================*/
const u8g2_cb_t u8g2_cb_r0 = { u8g2_update_dimension_r0, u8g2_update_page_win_r0, u8g2_draw_l90_r0 };
const u8g2_cb_t u8g2_cb_r1 = { u8g2_update_dimension_r1, u8g2_update_page_win_r1, u8g2_draw_l90_r1 };
const u8g2_cb_t u8g2_cb_r2 = { u8g2_update_dimension_r2, u8g2_update_page_win_r2, u8g2_draw_l90_r2 };
const u8g2_cb_t u8g2_cb_r3 = { u8g2_update_dimension_r3, u8g2_update_page_win_r3, u8g2_draw_l90_r3 };
const u8g2_cb_t u8g2_cb_mirror = { u8g2_update_dimension_r0, u8g2_update_page_win_r0, u8g2_draw_l90_mirrorr_r0 };
const u8g2_cb_t u8g2_cb_mirror_vertical = { u8g2_update_dimension_r0, u8g2_update_page_win_r0, u8g2_draw_mirror_vertical_r0 };
/*============================================*/
/* setup for the null device */
/* setup for the null (empty) device */
void u8g2_Setup_null(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)
{
static uint8_t buf[8];
u8g2_SetupDisplay(u8g2, u8x8_d_null_cb, u8x8_cad_empty, byte_cb, gpio_and_delay_cb);
u8g2_SetupBuffer(u8g2, buf, 1, u8g2_ll_hvline_vertical_top_lsb, rotation);
}

View File

@ -0,0 +1,125 @@
#include <cmsis_os.h>
#include "stm32f4xx_hal.h"
#include "u8g2.h"
#include "soft_i2c.h"
#define DEVICE_ADDRESS 0x3C
#define TX_TIMEOUT 100
#define USE_I2C_INTERFACE
//#define USE_SPI_INTERFACE
/* SPI Interface */
SPI_HandleTypeDef *U8G2_SPI_HANDLE;
/* I2C Interface */
I2C_HandleTypeDef *U8G2_I2C_HANDLE;
uint8_t u8x8_stm32_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* STM32 supports HW SPI, Remove unused cases like U8X8_MSG_DELAY_XXX & U8X8_MSG_GPIO_XXX */
switch (msg)
{
case U8X8_MSG_GPIO_AND_DELAY_INIT:
/* Insert codes for initialization */
break;
case U8X8_MSG_DELAY_MILLI:
/* ms Delay */
osDelay(arg_int);
break;
#ifdef USE_SPI_INTERFACE
/* SPI Interface */
case U8X8_MSG_GPIO_CS:
/* Insert codes for SS pin control */
//HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, arg_int);
break;
case U8X8_MSG_GPIO_DC:
/* Insert codes for DC pin control */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, arg_int);
break;
case U8X8_MSG_GPIO_RESET:
/* Insert codes for RST pin control */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, arg_int);
break;
#endif
}
return 1;
}
#ifdef USE_SPI_INTERFACE
uint8_t u8x8_byte_stm32_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch (msg)
{
case U8X8_MSG_BYTE_SEND:
/* Insert codes to transmit data */
if (HAL_SPI_Transmit(&SPI_HANDLE, arg_ptr, arg_int, TX_TIMEOUT) != HAL_OK) return 0;
break;
case U8X8_MSG_BYTE_INIT:
/* Insert codes to begin SPI transmission */
break;
case U8X8_MSG_BYTE_SET_DC:
/* Control DC pin, U8X8_MSG_GPIO_DC will be called */
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
/* Select slave, U8X8_MSG_GPIO_CS will be called */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
osDelay(1);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
osDelay(1);
/* Insert codes to end SPI transmission */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
default:
return 0;
}
return 1;
}
#endif
#ifdef USE_I2C_INTERFACE
uint8_t u8x8_byte_stm32_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
static uint8_t buffer[32];
static uint8_t buf_idx;
uint8_t *data;
switch (msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *) arg_ptr;
while (arg_int > 0)
{
buffer[buf_idx++] = *data;
data++;
arg_int--;
}
break;
case U8X8_MSG_BYTE_INIT:
/* add your custom code to init i2c subsystem */
break;
case U8X8_MSG_BYTE_SET_DC:
break;
case U8X8_MSG_BYTE_START_TRANSFER:
buf_idx = 0;
break;
case U8X8_MSG_BYTE_END_TRANSFER:
if (U8G2_I2C_HANDLE->Instance == I2C_SOFT)
SOFT_I2C_Master_Transmit((DEVICE_ADDRESS << 1), buffer, buf_idx);
else
HAL_I2C_Master_Transmit(U8G2_I2C_HANDLE, (DEVICE_ADDRESS << 1), buffer, buf_idx, TX_TIMEOUT);
break;
default:
return 0;
}
return 1;
}
#endif

View File

@ -0,0 +1,260 @@
/*
u8log.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2018, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdint.h>
#include <string.h>
#include "u8x8.h"
/*
static uint8_t u8log_is_on_screen(u8log_t *u8log, uint8_t x, uint8_t y)
{
if ( x >= u8log->width )
return 0;
if ( y >= u8log->height )
return 0;
return 1;
}
*/
static void u8log_clear_screen(u8log_t *u8log)
{
uint8_t *dest = u8log->screen_buffer;
uint16_t cnt = u8log->height;
cnt *= u8log->width;
do
{
*dest++ = ' ';
cnt--;
} while( cnt > 0 );
}
/* scroll the content of the complete buffer, set redraw_line to 255 */
static void u8log_scroll_up(u8log_t *u8log)
{
uint8_t *dest = u8log->screen_buffer;
uint8_t *src = dest+u8log->width;
uint16_t cnt = u8log->height;
cnt--;
cnt *= u8log->width;
do
{
*dest++ = *src++;
cnt--;
} while( cnt > 0 );
cnt = u8log->width;
do
{
*dest++ = ' ';
cnt--;
} while(cnt > 0);
if ( u8log->is_redraw_line_for_each_char )
u8log->is_redraw_all = 1;
else
u8log->is_redraw_all_required_for_next_nl = 1;
}
/*
Place the cursor on the screen. This will also scroll, if required
*/
static void u8log_cursor_on_screen(u8log_t *u8log)
{
//printf("u8log_cursor_on_screen, cursor_y=%d\n", u8log->cursor_y);
if ( u8log->cursor_x >= u8log->width )
{
u8log->cursor_x = 0;
u8log->cursor_y++;
}
while ( u8log->cursor_y >= u8log->height )
{
u8log_scroll_up(u8log);
u8log->cursor_y--;
}
}
/*
Write a printable, single char on the screen, do any kind of scrolling
*/
static void u8log_write_to_screen(u8log_t *u8log, uint8_t c)
{
u8log_cursor_on_screen(u8log);
u8log->screen_buffer[u8log->cursor_y * u8log->width + u8log->cursor_x] = c;
u8log->cursor_x++;
if ( u8log->is_redraw_line_for_each_char )
{
u8log->is_redraw_line = 1;
u8log->redraw_line = u8log->cursor_y;
}
}
/*
Handle control codes or write the char to the screen.
Supported control codes are:
\n 10 Goto first position of the next line. Line is marked for redraw.
\r 13 Goto first position in the same line. Line is marked for redraw.
\t 9 Jump to the next tab position
\f 12 Clear the screen and mark redraw for whole screen
any other char Write char to screen. Line redraw mark depends on
is_redraw_line_for_each_char flag.
*/
void u8log_write_char(u8log_t *u8log, uint8_t c)
{
switch(c)
{
case '\n': // 10
u8log->is_redraw_line = 1;
u8log->redraw_line = u8log->cursor_y;
if ( u8log->is_redraw_all_required_for_next_nl )
u8log->is_redraw_all = 1;
u8log->is_redraw_all_required_for_next_nl = 0;
u8log->cursor_y++;
u8log->cursor_x = 0;
break;
case '\r': // 13
u8log->is_redraw_line = 1;
u8log->redraw_line = u8log->cursor_y;
u8log->cursor_x = 0;
break;
case '\t': // 9
u8log->cursor_x = (u8log->cursor_x + 8) & 0xf8;
break;
case '\f': // 12
u8log_clear_screen(u8log);
u8log->is_redraw_all = 1;
u8log->cursor_x = 0;
u8log->cursor_y = 0;
break;
default:
u8log_write_to_screen(u8log, c);
break;
}
}
void u8log_Init(u8log_t *u8log, uint8_t width, uint8_t height, uint8_t *buf)
{
memset(u8log, 0, sizeof(u8log_t));
u8log->width = width;
u8log->height = height;
u8log->screen_buffer = buf;
u8log_clear_screen(u8log);
}
void u8log_SetCallback(u8log_t *u8log, u8log_cb cb, void *aux_data)
{
u8log->cb = cb;
u8log->aux_data = aux_data;
}
void u8log_SetRedrawMode(u8log_t *u8log, uint8_t is_redraw_line_for_each_char)
{
u8log->is_redraw_line_for_each_char = is_redraw_line_for_each_char;
}
/* offset can be negative or positive, it is 0 by default */
void u8log_SetLineHeightOffset(u8log_t *u8log, int8_t line_height_offset)
{
u8log->line_height_offset = line_height_offset;
}
void u8log_WriteChar(u8log_t *u8log, uint8_t c)
{
u8log_write_char(u8log, c);
if ( u8log->is_redraw_line || u8log->is_redraw_all )
{
if ( u8log->cb != 0 )
{
u8log->cb(u8log);
}
u8log->is_redraw_line = 0;
u8log->is_redraw_all = 0;
}
}
void u8log_WriteString(u8log_t *u8log, const char *s)
{
while( *s != '\0' )
{
u8log_WriteChar(u8log, *s);
s++;
}
}
static void u8log_WriteHexHalfByte(u8log_t *u8log, uint8_t b) U8X8_NOINLINE;
static void u8log_WriteHexHalfByte(u8log_t *u8log, uint8_t b)
{
b &= 0x0f;
if ( b < 10 )
u8log_WriteChar(u8log, b+'0');
else
u8log_WriteChar(u8log, b+'a'-10);
}
void u8log_WriteHex8(u8log_t *u8log, uint8_t b)
{
u8log_WriteHexHalfByte(u8log, b >> 4);
u8log_WriteHexHalfByte(u8log, b);
}
void u8log_WriteHex16(u8log_t *u8log, uint16_t v)
{
u8log_WriteHex8(u8log, v>>8);
u8log_WriteHex8(u8log, v);
}
void u8log_WriteHex32(u8log_t *u8log, uint32_t v)
{
u8log_WriteHex16(u8log, v>>16);
u8log_WriteHex16(u8log, v);
}
/* v = value, d = number of digits (1..3) */
void u8log_WriteDec8(u8log_t *u8log, uint8_t v, uint8_t d)
{
u8log_WriteString(u8log, u8x8_u8toa(v, d));
}
/* v = value, d = number of digits (1..5) */
void u8log_WriteDec16(u8log_t *u8log, uint16_t v, uint8_t d)
{
u8log_WriteString(u8log, u8x8_u16toa(v, d));
}

View File

@ -0,0 +1,98 @@
/*
u8log_u8g2.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2018, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/*
Draw the u8log text at the specified x/y position.
x/y position is the reference position of the first char of the first line.
the line height is
u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2) + line_height_offset;
line_height_offset can be set with u8log_SetLineHeightOffset()
Use
u8g2_SetFontRefHeightText(u8g2_t *u8g2);
u8g2_SetFontRefHeightExtendedText(u8g2_t *u8g2);
u8g2_SetFontRefHeightAll(u8g2_t *u8g2);
to change the return values for u8g2_GetAscent and u8g2_GetDescent
*/
void u8g2_DrawLog(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8log_t *u8log)
{
u8g2_uint_t disp_x, disp_y;
uint8_t buf_x, buf_y;
uint8_t c;
disp_y = y;
u8g2_SetFontDirection(u8g2, 0);
for( buf_y = 0; buf_y < u8log->height; buf_y++ )
{
disp_x = x;
for( buf_x = 0; buf_x < u8log->width; buf_x++ )
{
c = u8log->screen_buffer[buf_y * u8log->width + buf_x];
disp_x += u8g2_DrawGlyph(u8g2, disp_x, disp_y, c);
}
disp_y += u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2);
disp_y += u8log->line_height_offset;
}
}
/*
u8lib callback for u8g2
Only font direction 0 is supported: u8g2_SetFontDirection(u8g2, 0)
Use
u8g2_SetFontRefHeightText(u8g2_t *u8g2);
u8g2_SetFontRefHeightExtendedText(u8g2_t *u8g2);
u8g2_SetFontRefHeightAll(u8g2_t *u8g2);
to change the top offset and the line height and
u8log_SetLineHeightOffset(u8log_t *u8log, int8_t line_height_offset)
to change the line height.
*/
void u8log_u8g2_cb(u8log_t * u8log)
{
u8g2_t *u8g2 = (u8g2_t *)(u8log->aux_data);
if ( u8log->is_redraw_line || u8log->is_redraw_all )
{
u8g2_FirstPage(u8g2);
do
{
u8g2_DrawLog( u8g2, 0, u8g2_GetAscent(u8g2), u8log);
}
while( u8g2_NextPage(u8g2) );
}
}

View File

@ -0,0 +1,75 @@
/*
u8log_u8x8.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2018, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static void u8x8_DrawLogLine(u8x8_t *u8x8, uint8_t disp_x, uint8_t disp_y, uint8_t buf_y, u8log_t *u8log) U8X8_NOINLINE;
static void u8x8_DrawLogLine(u8x8_t *u8x8, uint8_t disp_x, uint8_t disp_y, uint8_t buf_y, u8log_t *u8log)
{
uint8_t buf_x;
uint8_t c;
for( buf_x = 0; buf_x < u8log->width; buf_x++ )
{
c = u8log->screen_buffer[buf_y * u8log->width + buf_x];
u8x8_DrawGlyph(u8x8, disp_x, disp_y, c);
disp_x++;
}
}
void u8x8_DrawLog(u8x8_t *u8x8, uint8_t x, uint8_t y, u8log_t *u8log)
{
uint8_t buf_y;
for( buf_y = 0; buf_y < u8log->height; buf_y++ )
{
u8x8_DrawLogLine(u8x8, x, y, buf_y, u8log);
y++;
}
}
void u8log_u8x8_cb(u8log_t * u8log)
{
u8x8_t *u8x8 = (u8x8_t *)(u8log->aux_data);
if ( u8log->is_redraw_all )
{
u8x8_DrawLog(u8x8, 0, 0, u8log);
}
else if ( u8log->is_redraw_line )
{
u8x8_DrawLogLine(u8x8, 0, u8log->redraw_line, u8log->redraw_line, u8log);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,493 @@
/*
u8x8_8x8.c
font procedures, directly interfaces display procedures
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
#if defined(ESP8266)
uint8_t u8x8_pgm_read_esp(const uint8_t * addr)
{
uint32_t bytes;
bytes = *(uint32_t*)((uint32_t)addr & ~3);
return ((uint8_t*)&bytes)[(uint32_t)addr & 3];
}
#endif
void u8x8_SetFont(u8x8_t *u8x8, const uint8_t *font_8x8)
{
u8x8->font = font_8x8;
}
/*
Args:
u8x8: ptr to u8x8 structure
encoding: glyph for which the data is requested (must be between 0 and 255)
buf: pointer to 8 bytes
*/
static void u8x8_get_glyph_data(u8x8_t *u8x8, uint8_t encoding, uint8_t *buf, uint8_t tile_offset) U8X8_NOINLINE;
static void u8x8_get_glyph_data(u8x8_t *u8x8, uint8_t encoding, uint8_t *buf, uint8_t tile_offset)
{
uint8_t first, last, tiles, i;
uint16_t offset;
first = u8x8_pgm_read(u8x8->font+0);
last = u8x8_pgm_read(u8x8->font+1);
tiles = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
tiles *= u8x8_pgm_read(u8x8->font+3); /* new 2019 format */
/* get the glyph bitmap from the font */
if ( first <= encoding && encoding <= last )
{
offset = encoding;
offset -= first;
offset *= tiles; /* new 2019 format */
offset += tile_offset; /* new 2019 format */
offset *= 8;
offset +=4; /* changed from 2 to 4, new 2019 format */
for( i = 0; i < 8; i++ )
{
buf[i] = u8x8_pgm_read(u8x8->font+offset);
offset++;
}
}
else
{
for( i = 0; i < 8; i++ )
{
buf[i] = 0;
}
}
/* invert the bitmap if required */
if ( u8x8->is_font_inverse_mode )
{
for( i = 0; i < 8; i++ )
{
buf[i] ^= 255;
}
}
}
void u8x8_DrawGlyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
{
uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
uint8_t tv = u8x8_pgm_read(u8x8->font+3); /* new 2019 format */
uint8_t xx, tile;
uint8_t buf[8];
th += x;
tv += y;
tile = 0;
do
{
xx = x;
do
{
u8x8_get_glyph_data(u8x8, encoding, buf, tile);
u8x8_DrawTile(u8x8, xx, y, 1, buf);
tile++;
xx++;
} while( xx < th );
y++;
} while( y < tv );
}
/*
Source: http://graphics.stanford.edu/~seander/bithacks.html
Section: Interleave bits by Binary Magic Numbers
Original codes is here:
static const unsigned int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF};
static const unsigned int S[] = {1, 2, 4, 8};
unsigned int x; // Interleave lower 16 bits of x and y, so the bits of x
unsigned int y; // are in the even positions and bits from y in the odd;
unsigned int z; // z gets the resulting 32-bit Morton Number.
// x and y must initially be less than 65536.
x = (x | (x << S[3])) & B[3];
x = (x | (x << S[2])) & B[2];
x = (x | (x << S[1])) & B[1];
x = (x | (x << S[0])) & B[0];
y = (y | (y << S[3])) & B[3];
y = (y | (y << S[2])) & B[2];
y = (y | (y << S[1])) & B[1];
y = (y | (y << S[0])) & B[0];
z = x | (y << 1);
*/
uint16_t u8x8_upscale_byte(uint8_t x)
{
uint16_t y = x;
y |= (y << 4); // x = (x | (x << S[2])) & B[2];
y &= 0x0f0f;
y |= (y << 2); // x = (x | (x << S[1])) & B[1];
y &= 0x3333;
y |= (y << 1); // x = (x | (x << S[0])) & B[0];
y &= 0x5555;
y |= (y << 1); // z = x | (y << 1);
return y;
}
static void u8x8_upscale_buf(uint8_t *src, uint8_t *dest) U8X8_NOINLINE;
static void u8x8_upscale_buf(uint8_t *src, uint8_t *dest)
{
uint8_t i = 4;
do
{
*dest++ = *src;
*dest++ = *src++;
i--;
} while( i > 0 );
}
static void u8x8_draw_2x2_subglyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding, uint8_t tile)
{
uint8_t i;
uint16_t t;
uint8_t buf[8];
uint8_t buf1[8];
uint8_t buf2[8];
u8x8_get_glyph_data(u8x8, encoding, buf, tile);
for( i = 0; i < 8; i ++ )
{
t = u8x8_upscale_byte(buf[i]);
buf1[i] = t >> 8;
buf2[i] = t & 255;
}
u8x8_upscale_buf(buf2, buf);
u8x8_DrawTile(u8x8, x, y, 1, buf);
u8x8_upscale_buf(buf2+4, buf);
u8x8_DrawTile(u8x8, x+1, y, 1, buf);
u8x8_upscale_buf(buf1, buf);
u8x8_DrawTile(u8x8, x, y+1, 1, buf);
u8x8_upscale_buf(buf1+4, buf);
u8x8_DrawTile(u8x8, x+1, y+1, 1, buf);
}
void u8x8_Draw2x2Glyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
{
uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
uint8_t tv = u8x8_pgm_read(u8x8->font+3); /* new 2019 format */
uint8_t xx, tile;
th *= 2;
th += x;
tv *= 2;
tv += y;
tile = 0;
do
{
xx = x;
do
{
u8x8_draw_2x2_subglyph(u8x8, xx, y, encoding, tile);
tile++;
xx+=2;
} while( xx < th );
y+=2;
} while( y < tv );
}
/* https://github.com/olikraus/u8g2/issues/474 */
static void u8x8_draw_1x2_subglyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding, uint8_t tile)
{
uint8_t i;
uint16_t t;
uint8_t buf[8];
uint8_t buf1[8];
uint8_t buf2[8];
u8x8_get_glyph_data(u8x8, encoding, buf, tile);
for( i = 0; i < 8; i ++ )
{
t = u8x8_upscale_byte(buf[i]);
buf1[i] = t >> 8;
buf2[i] = t & 255;
}
u8x8_DrawTile(u8x8, x, y, 1, buf2);
u8x8_DrawTile(u8x8, x, y+1, 1, buf1);
}
void u8x8_Draw1x2Glyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
{
uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
uint8_t tv = u8x8_pgm_read(u8x8->font+3); /* new 2019 format */
uint8_t xx, tile;
th += x;
tv *= 2;
tv += y;
tile = 0;
do
{
xx = x;
do
{
u8x8_draw_1x2_subglyph(u8x8, xx, y, encoding, tile);
tile++;
xx++;
} while( xx < th );
y+=2;
} while( y < tv );
}
/*
source: https://en.wikipedia.org/wiki/UTF-8
Bits from to bytes Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
7 U+0000 U+007F 1 0xxxxxxx
11 U+0080 U+07FF 2 110xxxxx 10xxxxxx
16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
21 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
26 U+200000 U+3FFFFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
31 U+4000000 U+7FFFFFFF 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
*/
/* reset the internal state machine */
void u8x8_utf8_init(u8x8_t *u8x8)
{
u8x8->utf8_state = 0; /* also reset during u8x8_SetupDefaults() */
}
uint16_t u8x8_ascii_next(U8X8_UNUSED u8x8_t *u8x8, uint8_t b)
{
if ( b == 0 || b == '\n' ) /* '\n' terminates the string to support the string list procedures */
return 0x0ffff; /* end of string detected*/
return b;
}
/*
pass a byte from an utf8 encoded string to the utf8 decoder state machine
returns
0x0fffe: no glyph, just continue
0x0ffff: end of string
anything else: The decoded encoding
*/
uint16_t u8x8_utf8_next(u8x8_t *u8x8, uint8_t b)
{
if ( b == 0 || b == '\n' ) /* '\n' terminates the string to support the string list procedures */
return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
if ( u8x8->utf8_state == 0 )
{
if ( b >= 0xfc ) /* 6 byte sequence */
{
u8x8->utf8_state = 5;
b &= 1;
}
else if ( b >= 0xf8 )
{
u8x8->utf8_state = 4;
b &= 3;
}
else if ( b >= 0xf0 )
{
u8x8->utf8_state = 3;
b &= 7;
}
else if ( b >= 0xe0 )
{
u8x8->utf8_state = 2;
b &= 15;
}
else if ( b >= 0xc0 )
{
u8x8->utf8_state = 1;
b &= 0x01f;
}
else
{
/* do nothing, just use the value as encoding */
return b;
}
u8x8->encoding = b;
return 0x0fffe;
}
else
{
u8x8->utf8_state--;
/* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
u8x8->encoding<<=6;
b &= 0x03f;
u8x8->encoding |= b;
if ( u8x8->utf8_state != 0 )
return 0x0fffe; /* nothing to do yet */
}
return u8x8->encoding;
}
static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
uint16_t e;
uint8_t cnt = 0;
uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
u8x8_utf8_init(u8x8);
for(;;)
{
e = u8x8->next_cb(u8x8, (uint8_t)*s);
if ( e == 0x0ffff )
break;
s++;
if ( e != 0x0fffe )
{
u8x8_DrawGlyph(u8x8, x, y, e);
x+=th;
cnt++;
}
}
return cnt;
}
uint8_t u8x8_DrawString(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_ascii_next;
return u8x8_draw_string(u8x8, x, y, s);
}
uint8_t u8x8_DrawUTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_utf8_next;
return u8x8_draw_string(u8x8, x, y, s);
}
static uint8_t u8x8_draw_2x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
static uint8_t u8x8_draw_2x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
uint16_t e;
uint8_t cnt = 0;
uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
th <<= 1;
u8x8_utf8_init(u8x8);
for(;;)
{
e = u8x8->next_cb(u8x8, (uint8_t)*s);
if ( e == 0x0ffff )
break;
s++;
if ( e != 0x0fffe )
{
u8x8_Draw2x2Glyph(u8x8, x, y, e);
x+=th;
cnt++;
}
}
return cnt;
}
uint8_t u8x8_Draw2x2String(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_ascii_next;
return u8x8_draw_2x2_string(u8x8, x, y, s);
}
uint8_t u8x8_Draw2x2UTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_utf8_next;
return u8x8_draw_2x2_string(u8x8, x, y, s);
}
static uint8_t u8x8_draw_1x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
static uint8_t u8x8_draw_1x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
uint16_t e;
uint8_t cnt = 0;
uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
u8x8_utf8_init(u8x8);
for(;;)
{
e = u8x8->next_cb(u8x8, (uint8_t)*s);
if ( e == 0x0ffff )
break;
s++;
if ( e != 0x0fffe )
{
u8x8_Draw1x2Glyph(u8x8, x, y, e);
x+=th;
cnt++;
}
}
return cnt;
}
uint8_t u8x8_Draw1x2String(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_ascii_next;
return u8x8_draw_1x2_string(u8x8, x, y, s);
}
uint8_t u8x8_Draw1x2UTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_utf8_next;
return u8x8_draw_1x2_string(u8x8, x, y, s);
}
uint8_t u8x8_GetUTF8Len(u8x8_t *u8x8, const char *s)
{
uint16_t e;
uint8_t cnt = 0;
u8x8_utf8_init(u8x8);
for(;;)
{
e = u8x8_utf8_next(u8x8, *s);
if ( e == 0x0ffff )
break;
s++;
if ( e != 0x0fffe )
cnt++;
}
return cnt;
}

View File

@ -0,0 +1,666 @@
/*
u8x8_byte.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
uint8_t u8x8_byte_SetDC(u8x8_t *u8x8, uint8_t dc)
{
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_SET_DC, dc, NULL);
}
uint8_t u8x8_byte_SendBytes(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
{
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_SEND, cnt, (void *)data);
}
uint8_t u8x8_byte_SendByte(u8x8_t *u8x8, uint8_t byte)
{
return u8x8_byte_SendBytes(u8x8, 1, &byte);
}
uint8_t u8x8_byte_StartTransfer(u8x8_t *u8x8)
{
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_START_TRANSFER, 0, NULL);
}
uint8_t u8x8_byte_EndTransfer(u8x8_t *u8x8)
{
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_END_TRANSFER, 0, NULL);
}
/*=========================================*/
uint8_t u8x8_byte_empty(U8X8_UNUSED u8x8_t *u8x8, uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
case U8X8_MSG_BYTE_INIT:
case U8X8_MSG_BYTE_SET_DC:
case U8X8_MSG_BYTE_START_TRANSFER:
case U8X8_MSG_BYTE_END_TRANSFER:
break; /* do nothing */
}
return 1; /* always succeed */
}
/*=========================================*/
/*
Uses:
u8x8->display_info->sda_setup_time_ns
u8x8->display_info->sck_pulse_width_ns
u8x8->display_info->spi_mode
u8x8->display_info->chip_disable_level
u8x8->display_info->chip_enable_level
u8x8->display_info->post_chip_enable_wait_ns
u8x8->display_info->pre_chip_disable_wait_ns
Calls to GPIO and DELAY:
U8X8_MSG_DELAY_NANO
U8X8_MSG_GPIO_DC
U8X8_MSG_GPIO_CS
U8X8_MSG_GPIO_CLOCK
U8X8_MSG_GPIO_DATA
Handles:
U8X8_MSG_BYTE_INIT
U8X8_MSG_BYTE_SEND
U8X8_MSG_BYTE_SET_DC
U8X8_MSG_BYTE_START_TRANSFER
U8X8_MSG_BYTE_END_TRANSFER
*/
uint8_t u8x8_byte_4wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i, b;
uint8_t *data;
uint8_t takeover_edge = u8x8_GetSPIClockPhase(u8x8);
uint8_t not_takeover_edge = 1 - takeover_edge;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
data++;
arg_int--;
for( i = 0; i < 8; i++ )
{
if ( b & 128 )
u8x8_gpio_SetSPIData(u8x8, 1);
else
u8x8_gpio_SetSPIData(u8x8, 0);
b <<= 1;
u8x8_gpio_SetSPIClock(u8x8, not_takeover_edge);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sda_setup_time_ns);
u8x8_gpio_SetSPIClock(u8x8, takeover_edge);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sck_pulse_width_ns);
}
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* no wait required here */
/* for SPI: setup correct level of the clock signal */
u8x8_gpio_SetSPIClock(u8x8, u8x8_GetSPIClockPhase(u8x8));
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
default:
return 0;
}
return 1;
}
/*=========================================*/
uint8_t u8x8_byte_8bit_6800mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i, b;
uint8_t *data;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
data++;
arg_int--;
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
{
u8x8_gpio_call(u8x8, i, b&1);
b >>= 1;
}
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* ensure that the enable signal is high */
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
default:
return 0;
}
return 1;
}
uint8_t u8x8_byte_8bit_8080mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i, b;
uint8_t *data;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
data++;
arg_int--;
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
{
u8x8_gpio_call(u8x8, i, b&1);
b >>= 1;
}
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* ensure that the enable signal is high */
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
default:
return 0;
}
return 1;
}
/*=========================================*/
uint8_t u8x8_byte_3wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i;
uint8_t *data;
uint8_t takeover_edge = u8x8_GetSPIClockPhase(u8x8);
uint8_t not_takeover_edge = 1 - takeover_edge;
uint16_t b;
static uint8_t last_dc;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
if ( last_dc != 0 )
b |= 256;
data++;
arg_int--;
for( i = 0; i < 9; i++ )
{
if ( b & 256 )
u8x8_gpio_SetSPIData(u8x8, 1);
else
u8x8_gpio_SetSPIData(u8x8, 0);
b <<= 1;
u8x8_gpio_SetSPIClock(u8x8, not_takeover_edge);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sda_setup_time_ns);
u8x8_gpio_SetSPIClock(u8x8, takeover_edge);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sck_pulse_width_ns);
}
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* no wait required here */
/* for SPI: setup correct level of the clock signal */
u8x8_gpio_SetSPIClock(u8x8, u8x8_GetSPIClockPhase(u8x8));
break;
case U8X8_MSG_BYTE_SET_DC:
last_dc = arg_int;
break;
case U8X8_MSG_BYTE_START_TRANSFER:
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
default:
return 0;
}
return 1;
}
/*=========================================*/
void u8x8_byte_set_ks0108_cs(u8x8_t *u8x8, uint8_t arg)
{
u8x8_gpio_SetCS(u8x8, arg&1);
arg = arg >> 1;
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS1, arg&1);
arg = arg >> 1;
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS2, arg&1);
}
/* 6800 mode */
uint8_t u8x8_byte_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i, b;
uint8_t *data;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
data++;
arg_int--;
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
{
u8x8_gpio_call(u8x8, i, b&1);
b >>= 1;
}
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* ensure that the enable signal is low */
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
/* expects 3 bits in arg_int for the chip select lines */
u8x8_byte_set_ks0108_cs(u8x8, arg_int);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_byte_set_ks0108_cs(u8x8, arg_int);
break;
default:
return 0;
}
return 1;
}
/* sed1520 or sbn1661
U8X8_MSG_GPIO_E --> E1
U8X8_MSG_GPIO_CS --> E2
*/
uint8_t u8x8_byte_sed1520(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i, b;
uint8_t *data;
static uint8_t enable_pin;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
data++;
arg_int--;
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
{
u8x8_gpio_call(u8x8, i, b&1);
b >>= 1;
}
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
u8x8_gpio_call(u8x8, enable_pin, 1);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 200); /* KS0108 requires 450 ns, use 200 here */
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns); /* expect 250 here */
u8x8_gpio_call(u8x8, enable_pin, 0);
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* ensure that the enable signals are low */
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS, 0);
enable_pin = U8X8_MSG_GPIO_E;
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
/* cs lines are not supported for the SED1520/SBN1661 */
/* instead, this will select the E1 or E2 line */
enable_pin = U8X8_MSG_GPIO_E;
if ( arg_int != 0 )
enable_pin = U8X8_MSG_GPIO_CS;
break;
case U8X8_MSG_BYTE_END_TRANSFER:
break;
default:
return 0;
}
return 1;
}
/*=========================================*/
/*
software i2c,
ignores ACK response (which is anyway not provided by some displays)
also does not allow reading from the device
*/
static void i2c_delay(u8x8_t *u8x8) U8X8_NOINLINE;
static void i2c_delay(u8x8_t *u8x8)
{
//u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_10MICRO, u8x8->display_info->i2c_bus_clock_100kHz);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_I2C, u8x8->display_info->i2c_bus_clock_100kHz);
}
static void i2c_init(u8x8_t *u8x8)
{
u8x8_gpio_SetI2CClock(u8x8, 1);
u8x8_gpio_SetI2CData(u8x8, 1);
i2c_delay(u8x8);
}
/* actually, the scl line is not observed, so this procedure does not return a value */
static void i2c_read_scl_and_delay(u8x8_t *u8x8)
{
/* set as input (line will be high) */
u8x8_gpio_SetI2CClock(u8x8, 1);
i2c_delay(u8x8);
}
static void i2c_clear_scl(u8x8_t *u8x8)
{
u8x8_gpio_SetI2CClock(u8x8, 0);
}
static void i2c_read_sda(u8x8_t *u8x8)
{
/* set as input (line will be high) */
u8x8_gpio_SetI2CData(u8x8, 1);
}
static void i2c_clear_sda(u8x8_t *u8x8)
{
/* set open collector and drive low */
u8x8_gpio_SetI2CData(u8x8, 0);
}
static void i2c_start(u8x8_t *u8x8)
{
if ( u8x8->i2c_started != 0 )
{
/* if already started: do restart */
i2c_read_sda(u8x8); /* SDA = 1 */
i2c_delay(u8x8);
i2c_read_scl_and_delay(u8x8);
}
i2c_read_sda(u8x8);
/* send the start condition, both lines go from 1 to 0 */
i2c_clear_sda(u8x8);
i2c_delay(u8x8);
i2c_clear_scl(u8x8);
u8x8->i2c_started = 1;
}
static void i2c_stop(u8x8_t *u8x8)
{
/* set SDA to 0 */
i2c_clear_sda(u8x8);
i2c_delay(u8x8);
/* now release all lines */
i2c_read_scl_and_delay(u8x8);
/* set SDA to 1 */
i2c_read_sda(u8x8);
i2c_delay(u8x8);
u8x8->i2c_started = 0;
}
static void i2c_write_bit(u8x8_t *u8x8, uint8_t val)
{
if (val)
i2c_read_sda(u8x8);
else
i2c_clear_sda(u8x8);
i2c_delay(u8x8);
i2c_read_scl_and_delay(u8x8);
i2c_clear_scl(u8x8);
}
static void i2c_read_bit(u8x8_t *u8x8)
{
//uint8_t val;
/* do not drive SDA */
i2c_read_sda(u8x8);
i2c_delay(u8x8);
i2c_read_scl_and_delay(u8x8);
i2c_read_sda(u8x8);
i2c_delay(u8x8);
i2c_clear_scl(u8x8);
//return val;
}
static void i2c_write_byte(u8x8_t *u8x8, uint8_t b)
{
i2c_write_bit(u8x8, b & 128);
i2c_write_bit(u8x8, b & 64);
i2c_write_bit(u8x8, b & 32);
i2c_write_bit(u8x8, b & 16);
i2c_write_bit(u8x8, b & 8);
i2c_write_bit(u8x8, b & 4);
i2c_write_bit(u8x8, b & 2);
i2c_write_bit(u8x8, b & 1);
/* read ack from client */
/* 0: ack was given by client */
/* 1: nothing happend during ack cycle */
i2c_read_bit(u8x8);
}
uint8_t u8x8_byte_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *data;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
i2c_write_byte(u8x8, *data);
data++;
arg_int--;
}
break;
case U8X8_MSG_BYTE_INIT:
i2c_init(u8x8);
break;
case U8X8_MSG_BYTE_SET_DC:
break;
case U8X8_MSG_BYTE_START_TRANSFER:
i2c_start(u8x8);
i2c_write_byte(u8x8, u8x8_GetI2CAddress(u8x8));
//i2c_write_byte(u8x8, 0x078);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
i2c_stop(u8x8);
break;
default:
return 0;
}
return 1;
}
/*=========================================*/
/* alternative i2c byte procedure */
#ifdef ALTERNATIVE_I2C_BYTE_PROCEDURE
void i2c_transfer(u8x8_t *u8x8, uint8_t adr, uint8_t cnt, uint8_t *data)
{
uint8_t i;
i2c_start(u8x8);
i2c_write_byte(u8x8, adr);
for( i = 0; i < cnt; i++ )
i2c_write_byte(u8x8, data[i]);
i2c_stop(u8x8);
}
uint8_t u8x8_byte_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
static uint8_t buffer[32]; /* u8g2/u8x8 will never send more than 32 bytes */
static uint8_t buf_idx;
uint8_t *data;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
buffer[buf_idx++] = *data;
data++;
arg_int--;
}
break;
case U8X8_MSG_BYTE_INIT:
i2c_init(u8x8); /* init i2c communication */
break;
case U8X8_MSG_BYTE_SET_DC:
/* ignored for i2c */
break;
case U8X8_MSG_BYTE_START_TRANSFER:
buf_idx = 0;
break;
case U8X8_MSG_BYTE_END_TRANSFER:
i2c_transfer(u8x8, u8x8_GetI2CAddress(u8x8), buf_idx, buffer);
break;
default:
return 0;
}
return 1;
}
#endif

View File

@ -0,0 +1,749 @@
/*
u8x8_cad.c
"command arg data" interface to the graphics controller
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The following sequence must be used for any data, which is set to the display:
uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8)
any of the following calls
uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd)
uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg)
uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8)
*/
/*
uint8_t u8x8_cad_template(u8x8_t *u8x8, uint8_t msg, uint16_t arg_int, void *arg_ptr)
{
uint8_t i;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_mcd_byte_SetDC(mcd->next, 1);
u8x8_mcd_byte_Send(mcd->next, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_mcd_byte_SetDC(mcd->next, 1);
u8x8_mcd_byte_Send(mcd->next, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_mcd_byte_SetDC(mcd->next, 0);
for( i = 0; i < 8; i++ )
u8x8_mcd_byte_Send(mcd->next, ((uint8_t *)arg_ptr)[i]);
break;
case U8X8_MSG_CAD_RESET:
return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_END_TRANSFER:
return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
default:
break;
}
return 1;
}
*/
#include "u8x8.h"
uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd)
{
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_CMD, cmd, NULL);
}
uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg)
{
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_ARG, arg, NULL);
}
uint8_t u8x8_cad_SendMultipleArg(u8x8_t *u8x8, uint8_t cnt, uint8_t arg)
{
while( cnt > 0 )
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_ARG, arg, NULL);
cnt--;
}
return 1;
}
uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
{
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, cnt, data);
}
uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8)
{
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
}
uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8)
{
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
}
void u8x8_cad_vsendf(u8x8_t * u8x8, const char *fmt, va_list va)
{
uint8_t d;
u8x8_cad_StartTransfer(u8x8);
while( *fmt != '\0' )
{
d = (uint8_t)va_arg(va, int);
switch(*fmt)
{
case 'a': u8x8_cad_SendArg(u8x8, d); break;
case 'c': u8x8_cad_SendCmd(u8x8, d); break;
case 'd': u8x8_cad_SendData(u8x8, 1, &d); break;
}
fmt++;
}
u8x8_cad_EndTransfer(u8x8);
}
void u8x8_SendF(u8x8_t * u8x8, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
u8x8_cad_vsendf(u8x8, fmt, va);
va_end(va);
}
/*
21 c send command c
22 a send arg a
23 d send data d
24 CS on
25 CS off
254 milli delay by milliseconds
255 end of sequence
*/
void u8x8_cad_SendSequence(u8x8_t *u8x8, uint8_t const *data)
{
uint8_t cmd;
uint8_t v;
for(;;)
{
cmd = *data;
data++;
switch( cmd )
{
case U8X8_MSG_CAD_SEND_CMD:
case U8X8_MSG_CAD_SEND_ARG:
v = *data;
u8x8->cad_cb(u8x8, cmd, v, NULL);
data++;
break;
case U8X8_MSG_CAD_SEND_DATA:
v = *data;
u8x8_cad_SendData(u8x8, 1, &v);
data++;
break;
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
u8x8->cad_cb(u8x8, cmd, 0, NULL);
break;
case 0x0fe:
v = *data;
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_MILLI, v);
data++;
break;
default:
return;
}
}
}
uint8_t u8x8_cad_empty(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/*
convert to bytes by using
dc = 1 for commands and args and
dc = 0 for data
*/
uint8_t u8x8_cad_110(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SetDC(u8x8, 1);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SetDC(u8x8, 1);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_byte_SetDC(u8x8, 0);
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
//break;
/* fall through */
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/*
convert to bytes by using
dc = 1 for commands and args and
dc = 0 for data
t6963
*/
uint8_t u8x8_cad_100(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SetDC(u8x8, 1);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SetDC(u8x8, 0);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_byte_SetDC(u8x8, 0);
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
//break;
/* fall through */
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/*
convert to bytes by using
dc = 0 for commands and args and
dc = 1 for data
*/
uint8_t u8x8_cad_001(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SetDC(u8x8, 0);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SetDC(u8x8, 0);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_byte_SetDC(u8x8, 1);
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
//break;
/* fall through */
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/*
convert to bytes by using
dc = 0 for commands
dc = 1 for args and data
*/
uint8_t u8x8_cad_011(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SetDC(u8x8, 0);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SetDC(u8x8, 1);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_byte_SetDC(u8x8, 1);
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
//break;
/* fall through */
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/* cad procedure for the ST7920 in SPI mode */
/* u8x8_byte_SetDC is not used */
uint8_t u8x8_cad_st7920_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *data;
uint8_t b;
uint8_t i;
static uint8_t buf[16];
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SendByte(u8x8, 0x0f8);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
u8x8_byte_SendByte(u8x8, arg_int & 0x0f0);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
u8x8_byte_SendByte(u8x8, arg_int << 4);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SendByte(u8x8, 0x0f8);
u8x8_byte_SendByte(u8x8, arg_int & 0x0f0);
u8x8_byte_SendByte(u8x8, arg_int << 4);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_byte_SendByte(u8x8, 0x0fa);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
/* this loop should be optimized: multiple bytes should be sent */
/* u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr); */
data = (uint8_t *)arg_ptr;
/* the following loop increases speed by 20% */
while( arg_int >= 8 )
{
i = 8;
ptr = buf;
do
{
b = *data++;
*ptr++= b & 0x0f0;
b <<= 4;
*ptr++= b;
i--;
} while( i > 0 );
arg_int -= 8;
u8x8_byte_SendBytes(u8x8, 16, buf);
}
while( arg_int > 0 )
{
b = *data;
u8x8_byte_SendByte(u8x8, b & 0x0f0);
u8x8_byte_SendByte(u8x8, b << 4);
data++;
arg_int--;
}
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
break;
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/* cad procedure for the SSD13xx family in I2C mode */
/* this procedure is also used by the ST7588 */
/* u8x8_byte_SetDC is not used */
/* U8X8_MSG_BYTE_START_TRANSFER starts i2c transfer, U8X8_MSG_BYTE_END_TRANSFER stops transfer */
/* After transfer start, a full byte indicates command or data mode */
static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
{
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, 0x040);
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, arg_ptr);
u8x8_byte_EndTransfer(u8x8);
}
/* classic version: will put a start/stop condition around each command and arg */
uint8_t u8x8_cad_ssd13xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *p;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
case U8X8_MSG_CAD_SEND_ARG:
/* 7 Nov 2016: Can this be improved? */
//u8x8_byte_SetDC(u8x8, 0);
u8x8_byte_StartTransfer(u8x8);
//u8x8_byte_SendByte(u8x8, u8x8_GetI2CAddress(u8x8));
u8x8_byte_SendByte(u8x8, 0x000);
u8x8_byte_SendByte(u8x8, arg_int);
u8x8_byte_EndTransfer(u8x8);
break;
case U8X8_MSG_CAD_SEND_DATA:
//u8x8_byte_SetDC(u8x8, 1);
/* the FeatherWing OLED with the 32u4 transfer of long byte */
/* streams was not possible. This is broken down to */
/* smaller streams, 32 seems to be the limit... */
/* I guess this is related to the size of the Wire buffers in Arduino */
/* Unfortunately, this can not be handled in the byte level drivers, */
/* so this is done here. Even further, only 24 bytes will be sent, */
/* because there will be another byte (DC) required during the transfer */
p = arg_ptr;
while( arg_int > 24 )
{
u8x8_i2c_data_transfer(u8x8, 24, p);
arg_int-=24;
p+=24;
}
u8x8_i2c_data_transfer(u8x8, arg_int, p);
break;
case U8X8_MSG_CAD_INIT:
/* apply default i2c adr if required so that the start transfer msg can use this */
if ( u8x8->i2c_address == 255 )
u8x8->i2c_address = 0x078;
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
/* cad transfer commands are ignored */
break;
default:
return 0;
}
return 1;
}
/* fast version with reduced data start/stops, issue 735 */
uint8_t u8x8_cad_ssd13xx_fast_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
static uint8_t in_transfer = 0;
uint8_t *p;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
/* improved version, takeover from ld7032 */
/* assumes, that the args of a command is not longer than 31 bytes */
/* speed improvement is about 4% compared to the classic version */
if ( in_transfer != 0 )
u8x8_byte_EndTransfer(u8x8);
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, 0x000); /* cmd byte for ssd13xx controller */
u8x8_byte_SendByte(u8x8, arg_int);
in_transfer = 1;
/* lightning version: can replace the improved version from above */
/* the drawback of the lightning version is this: The complete init sequence */
/* must fit into the 32 byte Arduino Wire buffer, which might not always be the case */
/* speed improvement is about 6% compared to the classic version */
// if ( in_transfer == 0 )
// {
// u8x8_byte_StartTransfer(u8x8);
// u8x8_byte_SendByte(u8x8, 0x000); /* cmd byte for ssd13xx controller */
// in_transfer = 1;
// }
//u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
if ( in_transfer != 0 )
u8x8_byte_EndTransfer(u8x8);
/* the FeatherWing OLED with the 32u4 transfer of long byte */
/* streams was not possible. This is broken down to */
/* smaller streams, 32 seems to be the limit... */
/* I guess this is related to the size of the Wire buffers in Arduino */
/* Unfortunately, this can not be handled in the byte level drivers, */
/* so this is done here. Even further, only 24 bytes will be sent, */
/* because there will be another byte (DC) required during the transfer */
p = arg_ptr;
while( arg_int > 24 )
{
u8x8_i2c_data_transfer(u8x8, 24, p);
arg_int-=24;
p+=24;
}
u8x8_i2c_data_transfer(u8x8, arg_int, p);
in_transfer = 0;
break;
case U8X8_MSG_CAD_INIT:
/* apply default i2c adr if required so that the start transfer msg can use this */
if ( u8x8->i2c_address == 255 )
u8x8->i2c_address = 0x078;
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
in_transfer = 0;
break;
case U8X8_MSG_CAD_END_TRANSFER:
if ( in_transfer != 0 )
u8x8_byte_EndTransfer(u8x8);
in_transfer = 0;
break;
default:
return 0;
}
return 1;
}
/* the st75256 i2c driver is a copy of the ssd13xx driver, but with arg=1 */
/* modified from cad001 (ssd13xx) to cad011 */
uint8_t u8x8_cad_st75256_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *p;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, 0x000);
u8x8_byte_SendByte(u8x8, arg_int);
u8x8_byte_EndTransfer(u8x8);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, 0x040);
u8x8_byte_SendByte(u8x8, arg_int);
u8x8_byte_EndTransfer(u8x8);
break;
case U8X8_MSG_CAD_SEND_DATA:
/* see ssd13xx driver */
p = arg_ptr;
while( arg_int > 24 )
{
u8x8_i2c_data_transfer(u8x8, 24, p);
arg_int-=24;
p+=24;
}
u8x8_i2c_data_transfer(u8x8, arg_int, p);
break;
case U8X8_MSG_CAD_INIT:
/* apply default i2c adr if required so that the start transfer msg can use this */
if ( u8x8->i2c_address == 255 )
u8x8->i2c_address = 0x078; /* ST75256, often this is 0x07e */
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
/* cad transfer commands are ignored */
break;
default:
return 0;
}
return 1;
}
/* cad i2c procedure for the ld7032 controller */
/* Issue https://github.com/olikraus/u8g2/issues/865 mentiones, that I2C does not work */
/* Workaround is to remove the while loop (or increase the value in the condition) */
uint8_t u8x8_cad_ld7032_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
static uint8_t in_transfer = 0;
uint8_t *p;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
if ( in_transfer != 0 )
u8x8_byte_EndTransfer(u8x8);
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, arg_int);
in_transfer = 1;
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
//u8x8_byte_SetDC(u8x8, 1);
/* the FeatherWing OLED with the 32u4 transfer of long byte */
/* streams was not possible. This is broken down to */
/* smaller streams, 32 seems to be the limit... */
/* I guess this is related to the size of the Wire buffers in Arduino */
/* Unfortunately, this can not be handled in the byte level drivers, */
/* so this is done here. Even further, only 24 bytes will be sent, */
/* because there will be another byte (DC) required during the transfer */
p = arg_ptr;
while( arg_int > 24 )
{
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
arg_int-=24;
p+=24;
u8x8_byte_EndTransfer(u8x8);
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, 0x08); /* data write for LD7032 */
}
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
break;
case U8X8_MSG_CAD_INIT:
/* apply default i2c adr if required so that the start transfer msg can use this */
if ( u8x8->i2c_address == 255 )
u8x8->i2c_address = 0x060;
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
in_transfer = 0;
break;
case U8X8_MSG_CAD_END_TRANSFER:
if ( in_transfer != 0 )
u8x8_byte_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/* cad procedure for the UC16xx family in I2C mode */
/* u8x8_byte_SetDC is not used */
/* DC bit is encoded into the adr byte */
uint8_t u8x8_cad_uc16xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
static uint8_t in_transfer = 0;
static uint8_t is_data = 0;
uint8_t *p;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
case U8X8_MSG_CAD_SEND_ARG:
if ( in_transfer != 0 )
{
if ( is_data != 0 )
{
/* transfer mode is active, but data transfer */
u8x8_byte_EndTransfer(u8x8);
/* clear the lowest two bits of the adr */
u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
u8x8_byte_StartTransfer(u8x8);
}
}
else
{
/* clear the lowest two bits of the adr */
u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
u8x8_byte_StartTransfer(u8x8);
}
u8x8_byte_SendByte(u8x8, arg_int);
in_transfer = 1;
break;
case U8X8_MSG_CAD_SEND_DATA:
if ( in_transfer != 0 )
{
if ( is_data == 0 )
{
/* transfer mode is active, but data transfer */
u8x8_byte_EndTransfer(u8x8);
/* clear the lowest two bits of the adr */
u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
u8x8_byte_StartTransfer(u8x8);
}
}
else
{
/* clear the lowest two bits of the adr */
u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
u8x8_byte_StartTransfer(u8x8);
}
in_transfer = 1;
p = arg_ptr;
while( arg_int > 24 )
{
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
arg_int-=24;
p+=24;
u8x8_byte_EndTransfer(u8x8);
u8x8_byte_StartTransfer(u8x8);
}
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
break;
case U8X8_MSG_CAD_INIT:
/* apply default i2c adr if required so that the start transfer msg can use this */
if ( u8x8->i2c_address == 255 )
u8x8->i2c_address = 0x070;
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
in_transfer = 0;
/* actual start is delayed, because we do not whether this is data or cmd transfer */
break;
case U8X8_MSG_CAD_END_TRANSFER:
if ( in_transfer != 0 )
u8x8_byte_EndTransfer(u8x8);
in_transfer = 0;
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,254 @@
/*
u8x8_capture.c
Screen capture funcion
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/*========================================================*/
/* vertical top lsb memory architecture */
uint8_t u8x8_capture_get_pixel_1(uint16_t x, uint16_t y, uint8_t *dest_ptr, uint8_t tile_width)
{
//uint8_t *dest_ptr = capture->buffer;
//if ( dest_ptr == NULL )
//return 0;
//dest_ptr += (y/8)*capture->tile_width*8;
dest_ptr += (y/8)*tile_width*8;
y &= 7;
dest_ptr += x;
if ( (*dest_ptr & (1<<y)) == 0 )
return 0;
return 1;
}
/* horizontal right lsb memory architecture */
/* SH1122, LD7032, ST7920, ST7986, LC7981, T6963, SED1330, RA8835, MAX7219, LS0 */
uint8_t u8x8_capture_get_pixel_2(uint16_t x, uint16_t y, uint8_t *dest_ptr, uint8_t tile_width)
{
//uint8_t *dest_ptr = capture->buffer;
//if ( dest_ptr == NULL )
// return 0;
//dest_ptr += y*capture->tile_width;
y *= tile_width;
dest_ptr += y;
dest_ptr += x>>3;
if ( (*dest_ptr & (128>>(x&7))) == 0 )
return 0;
return 1;
}
void u8x8_capture_write_pbm_pre(uint8_t tile_width, uint8_t tile_height, void (*out)(const char *s))
{
out("P1\n");
out(u8x8_utoa((uint16_t)tile_width*8));
out("\n");
out(u8x8_utoa((uint16_t)tile_height*8));
out("\n");
}
void u8x8_capture_write_pbm_buffer(uint8_t *buffer, uint8_t tile_width, uint8_t tile_height, uint8_t (*get_pixel)(uint16_t x, uint16_t y, uint8_t *dest_ptr, uint8_t tile_width), void (*out)(const char *s))
{
uint16_t x, y;
uint16_t w, h;
w = tile_width;
w *= 8;
h = tile_height;
h *= 8;
for( y = 0; y < h; y++)
{
for( x = 0; x < w; x++)
{
if ( get_pixel(x, y, buffer, tile_width) )
out("1");
else
out("0");
}
out("\n");
}
}
void u8x8_capture_write_xbm_pre(uint8_t tile_width, uint8_t tile_height, void (*out)(const char *s))
{
out("#define xbm_width ");
out(u8x8_utoa((uint16_t)tile_width*8));
out("\n");
out("#define xbm_height ");
out(u8x8_utoa((uint16_t)tile_height*8));
out("\n");
out("static unsigned char xbm_bits[] = {\n");
}
void u8x8_capture_write_xbm_buffer(uint8_t *buffer, uint8_t tile_width, uint8_t tile_height, uint8_t (*get_pixel)(uint16_t x, uint16_t y, uint8_t *dest_ptr, uint8_t tile_width), void (*out)(const char *s))
{
uint16_t x, y;
uint16_t w, h;
uint8_t v, b;
char s[2];
s[1] = '\0';
w = tile_width;
w *= 8;
h = tile_height;
h *= 8;
y = 0;
for(;;)
{
x = 0;
for(;;)
{
v = 0;
for( b = 0; b < 8; b++ )
{
v <<= 1;
if ( get_pixel(x+7-b, y, buffer, tile_width) )
v |= 1;
}
out("0x");
s[0] = (v>>4);
if ( s[0] <= 9 )
s[0] += '0';
else
s[0] += 'a'-10;
out(s);
s[0] = (v&15);
if ( s[0] <= 9 )
s[0] += '0';
else
s[0] += 'a'-10;
out(s);
x += 8;
if ( x >= w )
break;
out(",");
}
y++;
if ( y >= h )
break;
out(",");
out("\n");
}
out("};\n");
}
/*========================================================*/
#ifdef NOT_YET_IMPLEMENTED_U8X8_SCREEN_CAPTURE
struct _u8x8_capture_struct
{
u8x8_msg_cb old_cb;
uint8_t *buffer; /* tile_width*tile_height*8 bytes */
uint8_t tile_width;
uint8_t tile_height;
};
typedef struct _u8x8_capture_struct u8x8_capture_t;
u8x8_capture_t u8x8_capture;
static void u8x8_capture_memory_copy(uint8_t *dest, uint8_t *src, uint16_t cnt)
{
while( cnt > 0 )
{
*dest++ = *src++;
cnt--;
}
}
static void u8x8_capture_DrawTiles(u8x8_capture_t *capture, uint8_t tx, uint8_t ty, uint8_t tile_cnt, uint8_t *tile_ptr)
{
uint8_t *dest_ptr = capture->buffer;
//printf("tile pos: %d %d, cnt=%d\n", tx, ty, tile_cnt);
if ( dest_ptr == NULL )
return;
dest_ptr += (uint16_t)ty*capture->tile_width*8;
dest_ptr += (uint16_t)tx*8;
u8x8_capture_memory_copy(dest_ptr, tile_ptr, tile_cnt*8);
}
uint8_t u8x8_d_capture(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_DRAW_TILE )
{
uint8_t x, y, c;
uint8_t *ptr;
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
y = ((u8x8_tile_t *)arg_ptr)->y_pos;
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_capture_DrawTiles(&u8x8_capture, x, y, c, ptr);
x += c;
arg_int--;
} while( arg_int > 0 );
}
return u8x8_capture.old_cb(u8x8, msg, arg_int, arg_ptr);
}
uint8_t u8x8_GetCaptureMemoryPixel(u8x8_t *u8x8, uint16_t x, uint16_t y)
{
return u8x8_capture_GetPixel(&u8x8_capture, x, y);
}
/* memory: tile_width*tile_height*8 bytes */
void u8x8_ConnectCapture(u8x8_t *u8x8, uint8_t tile_width, uint8_t tile_height, uint8_t *memory)
{
if ( u8x8->display_cb == u8x8_d_capture )
return; /* do nothing, capture already installed */
u8x8_capture.buffer = memory; /* tile_width*tile_height*8 bytes */
u8x8_capture.tile_width = tile_width;
u8x8_capture.tile_height = tile_height;
u8x8_capture.old_cb = u8x8->display_cb;
u8x8->display_cb = u8x8_d_capture;
return;
}
#endif

View File

@ -0,0 +1,182 @@
/*
u8x8_d_a2printer.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Use DC2 bitmap command of the A2 Micro panel termal printer
double stroke
*/
#include "u8x8.h"
#define LINE_MIN_DELAY_MS 15
/* higher values improve quality */
/* however if the value is too high (>=5) then form feed does not work any more */
#define LINE_EXTRA_8PIXEL_DELAY_MS 3
/* this must be a power of two and between 1 and 8 */
/* best quality only with 1 */
#define NO_OF_LINES_TO_SEND_WITHOUT_DELAY 1
/* calculates the delay, based on the number of black pixel */
/* actually only "none-zero" bytes are calculated which is, of course not so accurate, but should be good enough */
uint16_t get_delay_in_milliseconds(uint8_t cnt, uint8_t *data)
{
uint8_t i;
uint16_t time = LINE_MIN_DELAY_MS;
for ( i = 0; i < cnt; i++ )
if ( data[i] != 0 )
time += LINE_EXTRA_8PIXEL_DELAY_MS;
return time;
}
uint8_t u8x8_d_a2printer_common(u8x8_t *u8x8, uint8_t msg, U8X8_UNUSED uint8_t arg_int, void *arg_ptr)
{
uint8_t c, i, j;
uint8_t *ptr;
uint16_t delay_in_milliseconds;
switch(msg)
{
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
/*
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
// no setup required
// u8x8_cad_SendSequence(u8x8, u8x8_d_a2printer_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
// no powersave
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 27); /* ESC */
u8x8_cad_SendCmd(u8x8, 55 ); /* parameter command */
/* increasing the "max printing dots" requires a good power supply, but LINE_EXTRA_8PIXEL_DELAY_MS could be reduced then */
u8x8_cad_SendCmd(u8x8, 0); /* Max printing dots,Unit(8dots),Default:7(64 dots) 8*(x+1) ... lower values improve, probably my current supply is not sufficient */
u8x8_cad_SendCmd(u8x8, 200); /* 3-255 Heating time,Unit(10us),Default:80(800us) */
u8x8_cad_SendCmd(u8x8, 2); /* 0-255 Heating interval,Unit(10us),Default:2(20us) ... does not have much influence */
//c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
c = u8x8->display_info->tile_width;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
u8x8_cad_SendCmd(u8x8, 18); /* DC2 */
u8x8_cad_SendCmd(u8x8, 42 ); /* * */
u8x8_cad_SendCmd(u8x8, 8 ); /* height */
u8x8_cad_SendCmd(u8x8, c ); /* c, u8x8->display_info->tile_width */
for( j = 0; j < 8 / NO_OF_LINES_TO_SEND_WITHOUT_DELAY; j ++ )
{
delay_in_milliseconds = 0;
for( i = 0; i < NO_OF_LINES_TO_SEND_WITHOUT_DELAY; i++ )
{
u8x8_cad_SendData(u8x8, c, ptr); /* c, note: SendData can not handle more than 255 bytes, send one line of data */
delay_in_milliseconds += get_delay_in_milliseconds(c, ptr);
ptr += c;
}
while( delay_in_milliseconds > 200 )
{
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_MILLI, 200, NULL);
delay_in_milliseconds -= 200;
}
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_MILLI, delay_in_milliseconds, NULL);
}
/* set parameters back to their default values */
u8x8_cad_SendCmd(u8x8, 27); /* ESC */
u8x8_cad_SendCmd(u8x8, 55 ); /* parameter command */
u8x8_cad_SendCmd(u8x8, 7); /* Max printing dots,Unit(8dots),Default:7(64 dots) 8*(x+1)*/
u8x8_cad_SendCmd(u8x8, 80); /* 3-255 Heating time,Unit(10us),Default:80(800us) */
u8x8_cad_SendCmd(u8x8, 2); /* 0-255 Heating interval,Unit(10us),Default:2(20us)*/
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_a2printer_384x240_display_info =
{
/* most of the settings are not required, because this is a serial RS232 printer */
/* chip_enable_level = */ 1,
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 5,
/* pre_chip_disable_wait_ns = */ 5,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140,
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* old: sck_takeover_edge, new: active high (bit 1), rising edge (bit 0) */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30,
/* write_pulse_width_ns = */ 40,
/* tile_width = */ 48,
/* tile_hight = */ 30,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 384,
/* pixel_height = */ 240
};
uint8_t u8x8_d_a2printer_384x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_a2printer_384x240_display_info);
break;
default:
return u8x8_d_a2printer_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}

Some files were not shown because too many files have changed in this diff Show More