updated printer profile
This commit is contained in:
parent
1eeb17bfa5
commit
0fdd5dcf9e
@ -1,122 +1,122 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="cdt.managedbuild.toolchain.gnu.cross.base.1504376676">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.cross.base.1504376676" moduleId="org.eclipse.cdt.core.settings" name="Default">
|
||||
<externalSettings>
|
||||
<externalSetting>
|
||||
<entry flags="RESOLVED" kind="includePath" name="C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\variants\nano_zero"/>
|
||||
<entry flags="RESOLVED" kind="includePath" name="C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\cores\arduino"/>
|
||||
</externalSetting>
|
||||
</externalSettings>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.cross.base.1504376676" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
|
||||
<folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.1504376676.350447049" name="/" resourcePath="">
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.515513271" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
|
||||
<option id="cdt.managedbuild.option.gnu.cross.prefix.582370251" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
|
||||
<option id="cdt.managedbuild.option.gnu.cross.path.231717393" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path"/>
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1339435354" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
||||
<builder id="cdt.managedbuild.builder.gnu.cross.241627781" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross">
|
||||
<outputEntries/>
|
||||
</builder>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.1805317535" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
||||
<option id="gnu.c.compiler.option.include.paths.1641555759" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\variants\nano_zero""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit_SSD1306-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit-GFX-Library-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\pio""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\instance""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\component""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\cores\arduino""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\TSTERN\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\libraries\SPI""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\CMSIS\include""/>
|
||||
</option>
|
||||
<option id="gnu.c.compiler.option.preprocessor.def.symbols.77778103" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="ARDUINO_SAMD_ZERO"/>
|
||||
<listOptionValue builtIn="false" value="__SAMD21G18A__"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1328245026" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1543385682" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
||||
<option id="gnu.cpp.compiler.option.include.paths.784350866" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\cores\arduino""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\variants\nano_zero""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit_SSD1306-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit-GFX-Library-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\pio""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\instance""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\component""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\TSTERN\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\libraries\SPI""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\CMSIS\include""/>
|
||||
</option>
|
||||
<option id="gnu.cpp.compiler.option.preprocessor.def.215333140" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="__SAMD21G18A__"/>
|
||||
<listOptionValue builtIn="false" value="ARDUINO_SAMD_ZERO"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1198492994" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1644022969" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.1373326859" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
|
||||
<option id="gnu.cpp.link.option.paths.1624146493" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths"/>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1257879712" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
</inputType>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.722380566" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.7579640" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
||||
<option id="gnu.both.asm.option.include.paths.2128933212" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\variants\nano_zero""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit_SSD1306-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit-GFX-Library-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\pio""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\instance""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\component""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\cores\arduino""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\TSTERN\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\libraries\SPI""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\CMSIS\Include""/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.474088881" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry excluding="Adafruit-GFX-Library-master|Adafruit_SSD1306-master" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
<storageModule moduleId="ilg.gnuarmeclipse.managedbuild.packs"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="NZS.null.440051529" name="NZS"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1504376676;cdt.managedbuild.toolchain.gnu.cross.base.1504376676.350447049;cdt.managedbuild.tool.gnu.cross.c.compiler.1805317535;cdt.managedbuild.tool.gnu.c.compiler.input.1328245026">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1504376676;cdt.managedbuild.toolchain.gnu.cross.base.1504376676.350447049;cdt.managedbuild.tool.gnu.cross.cpp.compiler.1543385682;cdt.managedbuild.tool.gnu.cpp.compiler.input.1198492994">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="refreshScope"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
</cproject>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="cdt.managedbuild.toolchain.gnu.cross.base.1504376676">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.cross.base.1504376676" moduleId="org.eclipse.cdt.core.settings" name="Default">
|
||||
<externalSettings>
|
||||
<externalSetting>
|
||||
<entry flags="RESOLVED" kind="includePath" name="C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\variants\nano_zero"/>
|
||||
<entry flags="RESOLVED" kind="includePath" name="C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\cores\arduino"/>
|
||||
</externalSetting>
|
||||
</externalSettings>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.cross.base.1504376676" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
|
||||
<folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.1504376676.350447049" name="/" resourcePath="">
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.515513271" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
|
||||
<option id="cdt.managedbuild.option.gnu.cross.prefix.582370251" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
|
||||
<option id="cdt.managedbuild.option.gnu.cross.path.231717393" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path"/>
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1339435354" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
||||
<builder id="cdt.managedbuild.builder.gnu.cross.241627781" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross">
|
||||
<outputEntries/>
|
||||
</builder>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.1805317535" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
||||
<option id="gnu.c.compiler.option.include.paths.1641555759" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\variants\nano_zero""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit_SSD1306-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit-GFX-Library-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\pio""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\instance""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\component""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\cores\arduino""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\TSTERN\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\libraries\SPI""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\CMSIS\include""/>
|
||||
</option>
|
||||
<option id="gnu.c.compiler.option.preprocessor.def.symbols.77778103" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="ARDUINO_SAMD_ZERO"/>
|
||||
<listOptionValue builtIn="false" value="__SAMD21G18A__"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1328245026" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1543385682" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
||||
<option id="gnu.cpp.compiler.option.include.paths.784350866" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\cores\arduino""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\variants\nano_zero""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit_SSD1306-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit-GFX-Library-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\pio""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\instance""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\component""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\TSTERN\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\libraries\SPI""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\CMSIS\include""/>
|
||||
</option>
|
||||
<option id="gnu.cpp.compiler.option.preprocessor.def.215333140" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="__SAMD21G18A__"/>
|
||||
<listOptionValue builtIn="false" value="ARDUINO_SAMD_ZERO"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1198492994" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1644022969" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.1373326859" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
|
||||
<option id="gnu.cpp.link.option.paths.1624146493" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths"/>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1257879712" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
</inputType>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.722380566" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.7579640" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
||||
<option id="gnu.both.asm.option.include.paths.2128933212" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\variants\nano_zero""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit_SSD1306-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\Documents\Arduino\libraries\Adafruit-GFX-Library-master""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\pio""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\instance""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\component""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\misfittech\hardware\samd\1.0.0\cores\arduino""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\TSTERN\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\libraries\SPI""/>
|
||||
<listOptionValue builtIn="false" value=""C:\Users\tstern\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\CMSIS\Include""/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.474088881" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry excluding="Adafruit-GFX-Library-master|Adafruit_SSD1306-master" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
<storageModule moduleId="ilg.gnuarmeclipse.managedbuild.packs"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="NZS.null.440051529" name="NZS"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1504376676;cdt.managedbuild.toolchain.gnu.cross.base.1504376676.350447049;cdt.managedbuild.tool.gnu.cross.c.compiler.1805317535;cdt.managedbuild.tool.gnu.c.compiler.input.1328245026">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1504376676;cdt.managedbuild.toolchain.gnu.cross.base.1504376676.350447049;cdt.managedbuild.tool.gnu.cross.cpp.compiler.1543385682;cdt.managedbuild.tool.gnu.cpp.compiler.input.1198492994">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="refreshScope"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
</cproject>
|
||||
|
@ -1,34 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>NZS</name>
|
||||
<comment></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.core.ccnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>arduino</name>
|
||||
<type>2</type>
|
||||
<location>C:/Users/tramp_000/AppData/Local/Arduino15/packages/arduino/hardware/samd/1.6.8/cores/arduino</location>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>NZS</name>
|
||||
<comment></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.core.ccnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>arduino</name>
|
||||
<type>2</type>
|
||||
<location>C:/Users/tramp_000/AppData/Local/Arduino15/packages/arduino/hardware/samd/1.6.8/cores/arduino</location>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
||||
|
@ -1,152 +1,152 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2019 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include <Arduino.h>
|
||||
#include "syslog.h"
|
||||
#include "A1333.h"
|
||||
#include "SPI.h"
|
||||
#include <stdio.h>
|
||||
#include "board.h"
|
||||
|
||||
|
||||
#define A1333_CMD_NOP (0x0000)
|
||||
#define A1333_ANG15 (0x3200)
|
||||
|
||||
SPISettings settingsA(500000, MSBFIRST, SPI_MODE3); ///400000, MSBFIRST, SPI_MODE1);
|
||||
|
||||
boolean A1333::begin(int csPin)
|
||||
{
|
||||
|
||||
digitalWrite(PIN_AS5047D_CS,LOW); //pull CS LOW by default (chip powered off)
|
||||
digitalWrite(PIN_MOSI,LOW);
|
||||
digitalWrite(PIN_SCK,LOW);
|
||||
digitalWrite(PIN_MISO,LOW);
|
||||
pinMode(PIN_MISO,OUTPUT);
|
||||
delay(1000);
|
||||
|
||||
|
||||
digitalWrite(PIN_AS5047D_CS,HIGH); //pull CS high
|
||||
|
||||
pinMode(PIN_MISO,INPUT);
|
||||
|
||||
|
||||
chipSelectPin=csPin;
|
||||
|
||||
LOG("csPin is %d",csPin);
|
||||
pinMode(chipSelectPin,OUTPUT);
|
||||
digitalWrite(chipSelectPin,HIGH); //pull CS high by default
|
||||
delay(1);
|
||||
|
||||
SPI.begin(); //AS5047D SPI uses mode=1 (CPOL=0, CPHA=1)
|
||||
|
||||
LOG("Begin A1333...");
|
||||
|
||||
LOG("Address is 0x%04X",readAddress(A1333_ANG15));
|
||||
}
|
||||
|
||||
|
||||
//read the encoders
|
||||
int16_t A1333::readAddress(uint16_t addr)
|
||||
{
|
||||
uint16_t data;
|
||||
//make sure it is a write by setting bit 14
|
||||
//addr=addr | 0x4000;
|
||||
|
||||
SPI.beginTransaction(settingsA);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
delayMicroseconds(1);
|
||||
//clock out the address to read
|
||||
//LOG("address 0x%04X",addr);
|
||||
SPI.transfer16(addr);
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
//clock out zeros to read in the data from address
|
||||
data=SPI.transfer16(0x00);
|
||||
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
SPI.endTransaction();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//read the encoders
|
||||
int16_t A1333::readEncoderAngle(void)
|
||||
{
|
||||
|
||||
return readAddress(A1333_ANG15)>>1;
|
||||
}
|
||||
|
||||
int16_t A1333::readEncoderAnglePipeLineRead(void)
|
||||
{
|
||||
static bool first=true;
|
||||
uint16_t addr = A1333_ANG15;
|
||||
uint16_t addr2;
|
||||
uint16_t data;
|
||||
|
||||
if (first)
|
||||
{
|
||||
//make sure it is a write by setting bit 14
|
||||
//addr2=addr | 0x4000;
|
||||
SPI.beginTransaction(settingsA);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
delayMicroseconds(1);
|
||||
//clock out the address to read
|
||||
SPI.transfer16(addr);
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
delayMicroseconds(1);
|
||||
//clock out zeros to read in the data from address
|
||||
data=SPI.transfer16(addr);
|
||||
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
SPI.endTransaction();
|
||||
first=false;
|
||||
return data>>1;
|
||||
}
|
||||
|
||||
SPI.beginTransaction(settingsA);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
delayMicroseconds(1);
|
||||
//clock out zeros to read in the data from address
|
||||
data=SPI.transfer16(addr);
|
||||
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
SPI.endTransaction();
|
||||
return data>>1;
|
||||
}
|
||||
/**********************************************************************
|
||||
Copyright (C) 2019 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include <Arduino.h>
|
||||
#include "syslog.h"
|
||||
#include "A1333.h"
|
||||
#include "SPI.h"
|
||||
#include <stdio.h>
|
||||
#include "board.h"
|
||||
|
||||
|
||||
#define A1333_CMD_NOP (0x0000)
|
||||
#define A1333_ANG15 (0x3200)
|
||||
|
||||
SPISettings settingsA(500000, MSBFIRST, SPI_MODE3); ///400000, MSBFIRST, SPI_MODE1);
|
||||
|
||||
boolean A1333::begin(int csPin)
|
||||
{
|
||||
|
||||
digitalWrite(PIN_AS5047D_CS,LOW); //pull CS LOW by default (chip powered off)
|
||||
digitalWrite(PIN_MOSI,LOW);
|
||||
digitalWrite(PIN_SCK,LOW);
|
||||
digitalWrite(PIN_MISO,LOW);
|
||||
pinMode(PIN_MISO,OUTPUT);
|
||||
delay(1000);
|
||||
|
||||
|
||||
digitalWrite(PIN_AS5047D_CS,HIGH); //pull CS high
|
||||
|
||||
pinMode(PIN_MISO,INPUT);
|
||||
|
||||
|
||||
chipSelectPin=csPin;
|
||||
|
||||
LOG("csPin is %d",csPin);
|
||||
pinMode(chipSelectPin,OUTPUT);
|
||||
digitalWrite(chipSelectPin,HIGH); //pull CS high by default
|
||||
delay(1);
|
||||
|
||||
SPI.begin(); //AS5047D SPI uses mode=1 (CPOL=0, CPHA=1)
|
||||
|
||||
LOG("Begin A1333...");
|
||||
|
||||
LOG("Address is 0x%04X",readAddress(A1333_ANG15));
|
||||
}
|
||||
|
||||
|
||||
//read the encoders
|
||||
int16_t A1333::readAddress(uint16_t addr)
|
||||
{
|
||||
uint16_t data;
|
||||
//make sure it is a write by setting bit 14
|
||||
//addr=addr | 0x4000;
|
||||
|
||||
SPI.beginTransaction(settingsA);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
delayMicroseconds(1);
|
||||
//clock out the address to read
|
||||
//LOG("address 0x%04X",addr);
|
||||
SPI.transfer16(addr);
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
//clock out zeros to read in the data from address
|
||||
data=SPI.transfer16(0x00);
|
||||
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
SPI.endTransaction();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//read the encoders
|
||||
int16_t A1333::readEncoderAngle(void)
|
||||
{
|
||||
|
||||
return readAddress(A1333_ANG15)>>1;
|
||||
}
|
||||
|
||||
int16_t A1333::readEncoderAnglePipeLineRead(void)
|
||||
{
|
||||
static bool first=true;
|
||||
uint16_t addr = A1333_ANG15;
|
||||
uint16_t addr2;
|
||||
uint16_t data;
|
||||
|
||||
if (first)
|
||||
{
|
||||
//make sure it is a write by setting bit 14
|
||||
//addr2=addr | 0x4000;
|
||||
SPI.beginTransaction(settingsA);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
delayMicroseconds(1);
|
||||
//clock out the address to read
|
||||
SPI.transfer16(addr);
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
delayMicroseconds(1);
|
||||
//clock out zeros to read in the data from address
|
||||
data=SPI.transfer16(addr);
|
||||
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
SPI.endTransaction();
|
||||
first=false;
|
||||
return data>>1;
|
||||
}
|
||||
|
||||
SPI.beginTransaction(settingsA);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
delayMicroseconds(1);
|
||||
//clock out zeros to read in the data from address
|
||||
data=SPI.transfer16(addr);
|
||||
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
SPI.endTransaction();
|
||||
return data>>1;
|
||||
}
|
||||
|
@ -1,59 +1,59 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2019 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef A1333_H_
|
||||
#define A1333_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define A1333_DEGREES_PER_BIT (360.0/(float)(0x7FFF))
|
||||
|
||||
class A1333 {
|
||||
private:
|
||||
int chipSelectPin;
|
||||
public:
|
||||
boolean begin(int csPin);
|
||||
int16_t readEncoderAngle(void);
|
||||
int16_t readAddress(uint16_t addr);
|
||||
int16_t readEncoderAnglePipeLineRead(void);
|
||||
void diagnostics(char *ptrStr) {return;};
|
||||
bool getError(void) {return false;};
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* A1333_H_ */
|
||||
/**********************************************************************
|
||||
Copyright (C) 2019 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef A1333_H_
|
||||
#define A1333_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define A1333_DEGREES_PER_BIT (360.0/(float)(0x7FFF))
|
||||
|
||||
class A1333 {
|
||||
private:
|
||||
int chipSelectPin;
|
||||
public:
|
||||
boolean begin(int csPin);
|
||||
int16_t readEncoderAngle(void);
|
||||
int16_t readAddress(uint16_t addr);
|
||||
int16_t readEncoderAnglePipeLineRead(void);
|
||||
void diagnostics(char *ptrStr) {return;};
|
||||
bool getError(void) {return false;};
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* A1333_H_ */
|
||||
|
@ -1,412 +1,412 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include "A4954.h"
|
||||
#include "wiring_private.h"
|
||||
#include "syslog.h"
|
||||
#include "angle.h"
|
||||
#include "Arduino.h"
|
||||
#include "sine.h"
|
||||
|
||||
static uint8_t pinState=0;
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-Ofast")
|
||||
|
||||
|
||||
|
||||
|
||||
#define DAC_MAX (0x01FFL)
|
||||
// Wait for synchronization of registers between the clock domains
|
||||
static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused));
|
||||
static void syncTCC(Tcc* TCCx) {
|
||||
//int32_t t0=1000;
|
||||
while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK)
|
||||
{
|
||||
// t0--;
|
||||
// if (t0==0)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void bridge1(int state)
|
||||
{
|
||||
if (state==0)
|
||||
{
|
||||
PORT->Group[g_APinDescription[PIN_A4954_IN1].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN1].ulPin].bit.PMUXEN = 0;
|
||||
GPIO_OUTPUT(PIN_A4954_IN1);//pinMode(PIN_A4954_IN1,OUTPUT);
|
||||
GPIO_OUTPUT(PIN_A4954_IN2);//pinMode(PIN_A4954_IN2,OUTPUT);
|
||||
GPIO_HIGH(PIN_A4954_IN1);// digitalWrite(PIN_A4954_IN1, HIGH);
|
||||
GPIO_LOW(PIN_A4954_IN2);//digitalWrite(PIN_A4954_IN2, LOW);
|
||||
//pinPeripheral(PIN_A4954_IN2, PIO_TIMER_ALT);
|
||||
pinState=(pinState & 0x0C) | 0x1;
|
||||
}
|
||||
if (state==1)
|
||||
{
|
||||
PORT->Group[g_APinDescription[PIN_A4954_IN2].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN2].ulPin].bit.PMUXEN = 0;
|
||||
GPIO_OUTPUT(PIN_A4954_IN2);//pinMode(PIN_A4954_IN2,OUTPUT);
|
||||
GPIO_OUTPUT(PIN_A4954_IN1);pinMode(PIN_A4954_IN1,OUTPUT);
|
||||
GPIO_LOW(PIN_A4954_IN1);//digitalWrite(PIN_A4954_IN1, LOW);
|
||||
GPIO_HIGH(PIN_A4954_IN2);//digitalWrite(PIN_A4954_IN2, HIGH);
|
||||
//pinPeripheral(PIN_A4954_IN1, PIO_TIMER);
|
||||
pinState=(pinState & 0x0C) | 0x2;
|
||||
}
|
||||
if (state==3)
|
||||
{
|
||||
GPIO_LOW(PIN_A4954_IN1);
|
||||
GPIO_LOW(PIN_A4954_IN2);
|
||||
//digitalWrite(PIN_A4954_IN1, LOW);
|
||||
//digitalWrite(PIN_A4954_IN2, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bridge2(int state)
|
||||
{
|
||||
if (state==0)
|
||||
{
|
||||
PORT->Group[g_APinDescription[PIN_A4954_IN3].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN3].ulPin].bit.PMUXEN = 0;
|
||||
GPIO_OUTPUT(PIN_A4954_IN3); //pinMode(PIN_A4954_IN3,OUTPUT);
|
||||
GPIO_OUTPUT(PIN_A4954_IN4);//pinMode(PIN_A4954_IN4,OUTPUT);
|
||||
GPIO_HIGH(PIN_A4954_IN3);//digitalWrite(PIN_A4954_IN3, HIGH);
|
||||
GPIO_LOW(PIN_A4954_IN4);//digitalWrite(PIN_A4954_IN4, LOW);
|
||||
//pinPeripheral(PIN_A4954_IN4, PIO_TIMER_ALT);
|
||||
pinState=(pinState & 0x03) | 0x4;
|
||||
}
|
||||
if (state==1)
|
||||
{
|
||||
PORT->Group[g_APinDescription[PIN_A4954_IN4].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN4].ulPin].bit.PMUXEN = 0;
|
||||
GPIO_OUTPUT(PIN_A4954_IN4);//pinMode(PIN_A4954_IN4,OUTPUT);
|
||||
GPIO_OUTPUT(PIN_A4954_IN3);//pinMode(PIN_A4954_IN3,OUTPUT);
|
||||
GPIO_LOW(PIN_A4954_IN3);//digitalWrite(PIN_A4954_IN3, LOW);
|
||||
GPIO_HIGH(PIN_A4954_IN4);//digitalWrite(PIN_A4954_IN4, HIGH);
|
||||
//pinPeripheral(PIN_A4954_IN3, PIO_TIMER_ALT);
|
||||
pinState=(pinState & 0x03) | 0x8;
|
||||
}
|
||||
if (state==3)
|
||||
{
|
||||
GPIO_LOW(PIN_A4954_IN3);
|
||||
GPIO_LOW(PIN_A4954_IN4);
|
||||
//digitalWrite(PIN_A4954_IN3, LOW);
|
||||
//digitalWrite(PIN_A4954_IN4, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
static void enableTCC0(uint8_t percent)
|
||||
{
|
||||
#ifdef MECHADUINO_HARDWARE
|
||||
return;
|
||||
#else
|
||||
Tcc* TCCx = TCC0 ;
|
||||
|
||||
|
||||
uint32_t ulValue=((uint32_t)(100-percent)*480)/100;
|
||||
//ERROR("Enable TCC0");
|
||||
|
||||
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
|
||||
|
||||
while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ;
|
||||
|
||||
//ERROR("Setting TCC %d %d",ulValue,ulPin);
|
||||
TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx as normal PWM
|
||||
TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx in waveform mode Normal PWM
|
||||
TCCx->CC[1].reg = (uint32_t)ulValue; //ch5 //IN3
|
||||
syncTCC(TCCx);
|
||||
|
||||
TCCx->CC[2].reg = (uint32_t)ulValue; //ch6 //IN4
|
||||
syncTCC(TCCx);
|
||||
|
||||
TCCx->CC[3].reg = (uint32_t)ulValue; //ch7 //IN2
|
||||
syncTCC(TCCx);
|
||||
|
||||
TCCx->CC[1].reg = (uint32_t)ulValue; //ch1 == ch5 //IN1
|
||||
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set PER to maximum counter value (resolution : 0xFF)
|
||||
TCCx->PER.reg = DAC_MAX;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Enable TCCx
|
||||
TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
|
||||
syncTCC(TCCx);
|
||||
//ERROR("Enable TCC0 DONE");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void setDAC(uint32_t DAC1, uint32_t DAC2)
|
||||
{
|
||||
TCC1->CC[1].reg = (uint32_t)DAC1; //D9 PA07 - VREF12
|
||||
syncTCC(TCC1);
|
||||
TCC1->CC[0].reg = (uint32_t)DAC2; //D4 - VREF34
|
||||
syncTCC(TCC1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void setupDAC(void)
|
||||
{
|
||||
Tcc* TCCx = TCC1 ;
|
||||
|
||||
|
||||
pinPeripheral(PIN_A4954_VREF34, PIO_TIMER_ALT);
|
||||
pinPeripheral(PIN_A4954_VREF12, PIO_TIMER);
|
||||
|
||||
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
|
||||
|
||||
while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ;
|
||||
|
||||
//ERROR("Setting TCC %d %d",ulValue,ulPin);
|
||||
TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx as normal PWM
|
||||
TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx in waveform mode Normal PWM
|
||||
TCCx->CC[1].reg = (uint32_t)0;
|
||||
syncTCC(TCCx);
|
||||
|
||||
TCCx->CC[0].reg = (uint32_t)0;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set PER to maximum counter value (resolution : 0xFFF = 12 bits)
|
||||
// =48e6/2^12=11kHz frequency
|
||||
TCCx->PER.reg = DAC_MAX;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Enable TCCx
|
||||
TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
|
||||
syncTCC(TCCx);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void A4954::begin()
|
||||
{
|
||||
//setup the A4954 pins
|
||||
digitalWrite(PIN_A4954_IN3,LOW);
|
||||
pinMode(PIN_A4954_IN3,OUTPUT);
|
||||
digitalWrite(PIN_A4954_IN4,LOW);
|
||||
pinMode(PIN_A4954_IN4,OUTPUT);
|
||||
digitalWrite(PIN_A4954_IN2,LOW);
|
||||
pinMode(PIN_A4954_IN2,OUTPUT);
|
||||
digitalWrite(PIN_A4954_IN1,LOW);
|
||||
pinMode(PIN_A4954_IN1,OUTPUT);
|
||||
|
||||
//setup the PWM for current on the A4954, set for low current
|
||||
digitalWrite(PIN_A4954_VREF12,LOW);
|
||||
digitalWrite(PIN_A4954_VREF34,LOW);
|
||||
pinMode(PIN_A4954_VREF34, OUTPUT);
|
||||
pinMode(PIN_A4954_VREF12, OUTPUT);
|
||||
|
||||
enabled=true;
|
||||
lastStepMicros=0;
|
||||
forwardRotation=true;
|
||||
|
||||
enableTCC0(90);
|
||||
setupDAC();
|
||||
//
|
||||
// int i=0;
|
||||
// bridge1(0);
|
||||
// bridge2(0);
|
||||
//while (1)
|
||||
// {
|
||||
// int32_t x;
|
||||
// WARNING("MA %d",i);
|
||||
// x=(int32_t)((int64_t)i*(DAC_MAX))/3300;
|
||||
// setDAC(x,x);
|
||||
// delay(1000);
|
||||
// i=i+10;
|
||||
// if (i>1000)
|
||||
// {
|
||||
// i=0;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
//
|
||||
// WARNING("Setting DAC for 500mA output");
|
||||
// setDAC((int32_t)((int64_t)1000*(DAC_MAX))/3300,(int32_t)((int64_t)1000*(DAC_MAX))/3300);
|
||||
// bridge1(0);
|
||||
// bridge2(0);
|
||||
// while(1)
|
||||
// {
|
||||
//
|
||||
// }
|
||||
return;
|
||||
}
|
||||
|
||||
void A4954::limitCurrent(uint8_t percent)
|
||||
{
|
||||
#ifdef MECHADUINO_HARDWARE
|
||||
return;
|
||||
#else
|
||||
//WARNING("current limit %d",percent);
|
||||
enableTCC0(percent);
|
||||
if (pinState & 0x01)
|
||||
{
|
||||
pinPeripheral(PIN_A4954_IN2, PIO_TIMER_ALT); //TCC0 WO[7]
|
||||
}
|
||||
if (pinState & 0x02)
|
||||
{
|
||||
pinPeripheral(PIN_A4954_IN1, PIO_TIMER); //TCC0 WO[1]
|
||||
}
|
||||
if (pinState & 0x04)
|
||||
{
|
||||
pinPeripheral(PIN_A4954_IN4, PIO_TIMER_ALT);
|
||||
}
|
||||
if (pinState & 0x08)
|
||||
{
|
||||
pinPeripheral(PIN_A4954_IN3, PIO_TIMER_ALT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void A4954::enable(bool enable)
|
||||
{
|
||||
enabled=enable;
|
||||
if (enabled == false)
|
||||
{
|
||||
WARNING("A4954 disabled");
|
||||
setDAC(0,0); //turn current off
|
||||
bridge1(3); //tri state bridge outputs
|
||||
bridge2(3); //tri state bridge outputs
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//this is precise move and modulo of A4954_NUM_MICROSTEPS is a full step.
|
||||
// stepAngle is in A4954_NUM_MICROSTEPS units..
|
||||
// The A4954 has no idea where the motor is, so the calling function has to
|
||||
// to tell the A4954 what phase to drive motor coils.
|
||||
// A4954_NUM_MICROSTEPS is 256 by default so stepAngle of 1024 is 360 degrees
|
||||
// Note you can only move up to +/-A4954_NUM_MICROSTEPS from where you
|
||||
// currently are.
|
||||
int32_t A4954::move(int32_t stepAngle, uint32_t mA)
|
||||
{
|
||||
uint16_t angle;
|
||||
int32_t cos,sin;
|
||||
int32_t dacSin,dacCos;
|
||||
//static int i=0;
|
||||
|
||||
if (enabled == false)
|
||||
{
|
||||
//WARNING("A4954 disabled");
|
||||
setDAC(0,0); //turn current off
|
||||
bridge1(3); //tri state bridge outputs
|
||||
bridge2(3); //tri state bridge outputs
|
||||
return stepAngle;
|
||||
}
|
||||
|
||||
//WARNING("move %d %d",stepAngle,mA);
|
||||
//handle roll overs, could do with modulo operator
|
||||
stepAngle=stepAngle%SINE_STEPS;
|
||||
|
||||
//figure out our sine Angle
|
||||
// note our SINE_STEPS is 4x of microsteps for a reason
|
||||
//angle=(stepAngle+(SINE_STEPS/8)) % SINE_STEPS;
|
||||
angle=(stepAngle);
|
||||
|
||||
//calculate the sine and cosine of our angle
|
||||
sin=sine(angle);
|
||||
cos=cosine(angle);
|
||||
|
||||
//if we are reverse swap the sign of one of the angels
|
||||
if (false == forwardRotation)
|
||||
{
|
||||
cos=-cos;
|
||||
}
|
||||
|
||||
//scale sine result by current(mA)
|
||||
dacSin=((int32_t)mA*(int64_t)abs(sin))/SINE_MAX;
|
||||
|
||||
//scale cosine result by current(mA)
|
||||
dacCos=((int32_t)mA*(int64_t)abs(cos))/SINE_MAX;
|
||||
|
||||
// if (i==0)
|
||||
// {
|
||||
// WARNING("dacs are %d %d",dacSin,dacCos);
|
||||
// }
|
||||
|
||||
//convert value into DAC scaled to 3300mA max
|
||||
dacCos=(int32_t)((int64_t)dacCos*(DAC_MAX))/3300;
|
||||
//convert value into DAC scaled to 3300mA max
|
||||
dacSin=(int32_t)((int64_t)dacSin*(DAC_MAX))/3300;
|
||||
|
||||
//WARNING("dacs are %d %d ",dacSin,dacCos);
|
||||
|
||||
setDAC(dacSin,dacCos);
|
||||
|
||||
if (sin>0)
|
||||
{
|
||||
bridge1(1);
|
||||
}else
|
||||
{
|
||||
bridge1(0);
|
||||
}
|
||||
if (cos>0)
|
||||
{
|
||||
bridge2(1);
|
||||
}else
|
||||
{
|
||||
bridge2(0);
|
||||
}
|
||||
|
||||
// if (i++>3000)
|
||||
// {
|
||||
// i=0;
|
||||
// }
|
||||
// YELLOW_LED(led);
|
||||
// led=(led+1) & 0x01;
|
||||
lastStepMicros=micros();
|
||||
return stepAngle;
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include "A4954.h"
|
||||
#include "wiring_private.h"
|
||||
#include "syslog.h"
|
||||
#include "angle.h"
|
||||
#include "Arduino.h"
|
||||
#include "sine.h"
|
||||
|
||||
static uint8_t pinState=0;
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-Ofast")
|
||||
|
||||
|
||||
|
||||
|
||||
#define DAC_MAX (0x01FFL)
|
||||
// Wait for synchronization of registers between the clock domains
|
||||
static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused));
|
||||
static void syncTCC(Tcc* TCCx) {
|
||||
//int32_t t0=1000;
|
||||
while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK)
|
||||
{
|
||||
// t0--;
|
||||
// if (t0==0)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void bridge1(int state)
|
||||
{
|
||||
if (state==0)
|
||||
{
|
||||
PORT->Group[g_APinDescription[PIN_A4954_IN1].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN1].ulPin].bit.PMUXEN = 0;
|
||||
GPIO_OUTPUT(PIN_A4954_IN1);//pinMode(PIN_A4954_IN1,OUTPUT);
|
||||
GPIO_OUTPUT(PIN_A4954_IN2);//pinMode(PIN_A4954_IN2,OUTPUT);
|
||||
GPIO_HIGH(PIN_A4954_IN1);// digitalWrite(PIN_A4954_IN1, HIGH);
|
||||
GPIO_LOW(PIN_A4954_IN2);//digitalWrite(PIN_A4954_IN2, LOW);
|
||||
//pinPeripheral(PIN_A4954_IN2, PIO_TIMER_ALT);
|
||||
pinState=(pinState & 0x0C) | 0x1;
|
||||
}
|
||||
if (state==1)
|
||||
{
|
||||
PORT->Group[g_APinDescription[PIN_A4954_IN2].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN2].ulPin].bit.PMUXEN = 0;
|
||||
GPIO_OUTPUT(PIN_A4954_IN2);//pinMode(PIN_A4954_IN2,OUTPUT);
|
||||
GPIO_OUTPUT(PIN_A4954_IN1);pinMode(PIN_A4954_IN1,OUTPUT);
|
||||
GPIO_LOW(PIN_A4954_IN1);//digitalWrite(PIN_A4954_IN1, LOW);
|
||||
GPIO_HIGH(PIN_A4954_IN2);//digitalWrite(PIN_A4954_IN2, HIGH);
|
||||
//pinPeripheral(PIN_A4954_IN1, PIO_TIMER);
|
||||
pinState=(pinState & 0x0C) | 0x2;
|
||||
}
|
||||
if (state==3)
|
||||
{
|
||||
GPIO_LOW(PIN_A4954_IN1);
|
||||
GPIO_LOW(PIN_A4954_IN2);
|
||||
//digitalWrite(PIN_A4954_IN1, LOW);
|
||||
//digitalWrite(PIN_A4954_IN2, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bridge2(int state)
|
||||
{
|
||||
if (state==0)
|
||||
{
|
||||
PORT->Group[g_APinDescription[PIN_A4954_IN3].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN3].ulPin].bit.PMUXEN = 0;
|
||||
GPIO_OUTPUT(PIN_A4954_IN3); //pinMode(PIN_A4954_IN3,OUTPUT);
|
||||
GPIO_OUTPUT(PIN_A4954_IN4);//pinMode(PIN_A4954_IN4,OUTPUT);
|
||||
GPIO_HIGH(PIN_A4954_IN3);//digitalWrite(PIN_A4954_IN3, HIGH);
|
||||
GPIO_LOW(PIN_A4954_IN4);//digitalWrite(PIN_A4954_IN4, LOW);
|
||||
//pinPeripheral(PIN_A4954_IN4, PIO_TIMER_ALT);
|
||||
pinState=(pinState & 0x03) | 0x4;
|
||||
}
|
||||
if (state==1)
|
||||
{
|
||||
PORT->Group[g_APinDescription[PIN_A4954_IN4].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN4].ulPin].bit.PMUXEN = 0;
|
||||
GPIO_OUTPUT(PIN_A4954_IN4);//pinMode(PIN_A4954_IN4,OUTPUT);
|
||||
GPIO_OUTPUT(PIN_A4954_IN3);//pinMode(PIN_A4954_IN3,OUTPUT);
|
||||
GPIO_LOW(PIN_A4954_IN3);//digitalWrite(PIN_A4954_IN3, LOW);
|
||||
GPIO_HIGH(PIN_A4954_IN4);//digitalWrite(PIN_A4954_IN4, HIGH);
|
||||
//pinPeripheral(PIN_A4954_IN3, PIO_TIMER_ALT);
|
||||
pinState=(pinState & 0x03) | 0x8;
|
||||
}
|
||||
if (state==3)
|
||||
{
|
||||
GPIO_LOW(PIN_A4954_IN3);
|
||||
GPIO_LOW(PIN_A4954_IN4);
|
||||
//digitalWrite(PIN_A4954_IN3, LOW);
|
||||
//digitalWrite(PIN_A4954_IN4, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
static void enableTCC0(uint8_t percent)
|
||||
{
|
||||
#ifdef MECHADUINO_HARDWARE
|
||||
return;
|
||||
#else
|
||||
Tcc* TCCx = TCC0 ;
|
||||
|
||||
|
||||
uint32_t ulValue=((uint32_t)(100-percent)*480)/100;
|
||||
//ERROR("Enable TCC0");
|
||||
|
||||
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
|
||||
|
||||
while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ;
|
||||
|
||||
//ERROR("Setting TCC %d %d",ulValue,ulPin);
|
||||
TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx as normal PWM
|
||||
TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx in waveform mode Normal PWM
|
||||
TCCx->CC[1].reg = (uint32_t)ulValue; //ch5 //IN3
|
||||
syncTCC(TCCx);
|
||||
|
||||
TCCx->CC[2].reg = (uint32_t)ulValue; //ch6 //IN4
|
||||
syncTCC(TCCx);
|
||||
|
||||
TCCx->CC[3].reg = (uint32_t)ulValue; //ch7 //IN2
|
||||
syncTCC(TCCx);
|
||||
|
||||
TCCx->CC[1].reg = (uint32_t)ulValue; //ch1 == ch5 //IN1
|
||||
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set PER to maximum counter value (resolution : 0xFF)
|
||||
TCCx->PER.reg = DAC_MAX;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Enable TCCx
|
||||
TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
|
||||
syncTCC(TCCx);
|
||||
//ERROR("Enable TCC0 DONE");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void setDAC(uint32_t DAC1, uint32_t DAC2)
|
||||
{
|
||||
TCC1->CC[1].reg = (uint32_t)DAC1; //D9 PA07 - VREF12
|
||||
syncTCC(TCC1);
|
||||
TCC1->CC[0].reg = (uint32_t)DAC2; //D4 - VREF34
|
||||
syncTCC(TCC1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void setupDAC(void)
|
||||
{
|
||||
Tcc* TCCx = TCC1 ;
|
||||
|
||||
|
||||
pinPeripheral(PIN_A4954_VREF34, PIO_TIMER_ALT);
|
||||
pinPeripheral(PIN_A4954_VREF12, PIO_TIMER);
|
||||
|
||||
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
|
||||
|
||||
while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ;
|
||||
|
||||
//ERROR("Setting TCC %d %d",ulValue,ulPin);
|
||||
TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx as normal PWM
|
||||
TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx in waveform mode Normal PWM
|
||||
TCCx->CC[1].reg = (uint32_t)0;
|
||||
syncTCC(TCCx);
|
||||
|
||||
TCCx->CC[0].reg = (uint32_t)0;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set PER to maximum counter value (resolution : 0xFFF = 12 bits)
|
||||
// =48e6/2^12=11kHz frequency
|
||||
TCCx->PER.reg = DAC_MAX;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Enable TCCx
|
||||
TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
|
||||
syncTCC(TCCx);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void A4954::begin()
|
||||
{
|
||||
//setup the A4954 pins
|
||||
digitalWrite(PIN_A4954_IN3,LOW);
|
||||
pinMode(PIN_A4954_IN3,OUTPUT);
|
||||
digitalWrite(PIN_A4954_IN4,LOW);
|
||||
pinMode(PIN_A4954_IN4,OUTPUT);
|
||||
digitalWrite(PIN_A4954_IN2,LOW);
|
||||
pinMode(PIN_A4954_IN2,OUTPUT);
|
||||
digitalWrite(PIN_A4954_IN1,LOW);
|
||||
pinMode(PIN_A4954_IN1,OUTPUT);
|
||||
|
||||
//setup the PWM for current on the A4954, set for low current
|
||||
digitalWrite(PIN_A4954_VREF12,LOW);
|
||||
digitalWrite(PIN_A4954_VREF34,LOW);
|
||||
pinMode(PIN_A4954_VREF34, OUTPUT);
|
||||
pinMode(PIN_A4954_VREF12, OUTPUT);
|
||||
|
||||
enabled=true;
|
||||
lastStepMicros=0;
|
||||
forwardRotation=true;
|
||||
|
||||
enableTCC0(90);
|
||||
setupDAC();
|
||||
//
|
||||
// int i=0;
|
||||
// bridge1(0);
|
||||
// bridge2(0);
|
||||
//while (1)
|
||||
// {
|
||||
// int32_t x;
|
||||
// WARNING("MA %d",i);
|
||||
// x=(int32_t)((int64_t)i*(DAC_MAX))/3300;
|
||||
// setDAC(x,x);
|
||||
// delay(1000);
|
||||
// i=i+10;
|
||||
// if (i>1000)
|
||||
// {
|
||||
// i=0;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
//
|
||||
// WARNING("Setting DAC for 500mA output");
|
||||
// setDAC((int32_t)((int64_t)1000*(DAC_MAX))/3300,(int32_t)((int64_t)1000*(DAC_MAX))/3300);
|
||||
// bridge1(0);
|
||||
// bridge2(0);
|
||||
// while(1)
|
||||
// {
|
||||
//
|
||||
// }
|
||||
return;
|
||||
}
|
||||
|
||||
void A4954::limitCurrent(uint8_t percent)
|
||||
{
|
||||
#ifdef MECHADUINO_HARDWARE
|
||||
return;
|
||||
#else
|
||||
//WARNING("current limit %d",percent);
|
||||
enableTCC0(percent);
|
||||
if (pinState & 0x01)
|
||||
{
|
||||
pinPeripheral(PIN_A4954_IN2, PIO_TIMER_ALT); //TCC0 WO[7]
|
||||
}
|
||||
if (pinState & 0x02)
|
||||
{
|
||||
pinPeripheral(PIN_A4954_IN1, PIO_TIMER); //TCC0 WO[1]
|
||||
}
|
||||
if (pinState & 0x04)
|
||||
{
|
||||
pinPeripheral(PIN_A4954_IN4, PIO_TIMER_ALT);
|
||||
}
|
||||
if (pinState & 0x08)
|
||||
{
|
||||
pinPeripheral(PIN_A4954_IN3, PIO_TIMER_ALT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void A4954::enable(bool enable)
|
||||
{
|
||||
enabled=enable;
|
||||
if (enabled == false)
|
||||
{
|
||||
WARNING("A4954 disabled");
|
||||
setDAC(0,0); //turn current off
|
||||
bridge1(3); //tri state bridge outputs
|
||||
bridge2(3); //tri state bridge outputs
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//this is precise move and modulo of A4954_NUM_MICROSTEPS is a full step.
|
||||
// stepAngle is in A4954_NUM_MICROSTEPS units..
|
||||
// The A4954 has no idea where the motor is, so the calling function has to
|
||||
// to tell the A4954 what phase to drive motor coils.
|
||||
// A4954_NUM_MICROSTEPS is 256 by default so stepAngle of 1024 is 360 degrees
|
||||
// Note you can only move up to +/-A4954_NUM_MICROSTEPS from where you
|
||||
// currently are.
|
||||
int32_t A4954::move(int32_t stepAngle, uint32_t mA)
|
||||
{
|
||||
uint16_t angle;
|
||||
int32_t cos,sin;
|
||||
int32_t dacSin,dacCos;
|
||||
//static int i=0;
|
||||
|
||||
if (enabled == false)
|
||||
{
|
||||
//WARNING("A4954 disabled");
|
||||
setDAC(0,0); //turn current off
|
||||
bridge1(3); //tri state bridge outputs
|
||||
bridge2(3); //tri state bridge outputs
|
||||
return stepAngle;
|
||||
}
|
||||
|
||||
//WARNING("move %d %d",stepAngle,mA);
|
||||
//handle roll overs, could do with modulo operator
|
||||
stepAngle=stepAngle%SINE_STEPS;
|
||||
|
||||
//figure out our sine Angle
|
||||
// note our SINE_STEPS is 4x of microsteps for a reason
|
||||
//angle=(stepAngle+(SINE_STEPS/8)) % SINE_STEPS;
|
||||
angle=(stepAngle);
|
||||
|
||||
//calculate the sine and cosine of our angle
|
||||
sin=sine(angle);
|
||||
cos=cosine(angle);
|
||||
|
||||
//if we are reverse swap the sign of one of the angels
|
||||
if (false == forwardRotation)
|
||||
{
|
||||
cos=-cos;
|
||||
}
|
||||
|
||||
//scale sine result by current(mA)
|
||||
dacSin=((int32_t)mA*(int64_t)abs(sin))/SINE_MAX;
|
||||
|
||||
//scale cosine result by current(mA)
|
||||
dacCos=((int32_t)mA*(int64_t)abs(cos))/SINE_MAX;
|
||||
|
||||
// if (i==0)
|
||||
// {
|
||||
// WARNING("dacs are %d %d",dacSin,dacCos);
|
||||
// }
|
||||
|
||||
//convert value into DAC scaled to 3300mA max
|
||||
dacCos=(int32_t)((int64_t)dacCos*(DAC_MAX))/3300;
|
||||
//convert value into DAC scaled to 3300mA max
|
||||
dacSin=(int32_t)((int64_t)dacSin*(DAC_MAX))/3300;
|
||||
|
||||
//WARNING("dacs are %d %d ",dacSin,dacCos);
|
||||
|
||||
setDAC(dacSin,dacCos);
|
||||
|
||||
if (sin>0)
|
||||
{
|
||||
bridge1(1);
|
||||
}else
|
||||
{
|
||||
bridge1(0);
|
||||
}
|
||||
if (cos>0)
|
||||
{
|
||||
bridge2(1);
|
||||
}else
|
||||
{
|
||||
bridge2(0);
|
||||
}
|
||||
|
||||
// if (i++>3000)
|
||||
// {
|
||||
// i=0;
|
||||
// }
|
||||
// YELLOW_LED(led);
|
||||
// led=(led+1) & 0x01;
|
||||
lastStepMicros=micros();
|
||||
return stepAngle;
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
|
@ -1,90 +1,90 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2019 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __A4954__H__
|
||||
#define __A4954__H__
|
||||
#include <Arduino.h>
|
||||
#include "board.h"
|
||||
#include "angle.h"
|
||||
#include "sine.h"
|
||||
|
||||
#define A4954_NUM_MICROSTEPS (256)
|
||||
#define A4954_MIN_TIME_BETWEEN_STEPS_MICROS (1000)
|
||||
|
||||
//prevent someone for making a mistake with the code
|
||||
#if ((A4954_NUM_MICROSTEPS*4) != SINE_STEPS)
|
||||
#error "SINE_STEPS must be 4x of Micro steps for the move function"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* When it comes to the stepper driver if we use angles
|
||||
* we will always have a rounding error. For example
|
||||
* a 0-65536(360) angle for 1.8 degree step is 327.68 so
|
||||
* if you increment 200 of these as 327 you have a 13.6 error
|
||||
* after one rotation.
|
||||
* If you use floating point the effect is the same but takes longer.
|
||||
*
|
||||
* The only error-less accumulation system is to use native units, ie full
|
||||
* steps and microsteps.
|
||||
*
|
||||
*/
|
||||
|
||||
class A4954
|
||||
{
|
||||
private:
|
||||
uint32_t lastStepMicros; // time in microseconds that last step happened
|
||||
bool forwardRotation=true;
|
||||
volatile bool enabled=true;
|
||||
|
||||
public:
|
||||
void begin(void);
|
||||
|
||||
//moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step.
|
||||
int32_t move(int32_t stepAngle, uint32_t mA);
|
||||
|
||||
uint32_t microsSinceStep(void) {return micros()-lastStepMicros;};
|
||||
void setRotationDirection(bool forward) {forwardRotation=forward;};
|
||||
|
||||
void enable(bool enable);
|
||||
void limitCurrent(uint8_t percent); //higher more current
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //__A4954__H__
|
||||
/**********************************************************************
|
||||
Copyright (C) 2019 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __A4954__H__
|
||||
#define __A4954__H__
|
||||
#include <Arduino.h>
|
||||
#include "board.h"
|
||||
#include "angle.h"
|
||||
#include "sine.h"
|
||||
|
||||
#define A4954_NUM_MICROSTEPS (256)
|
||||
#define A4954_MIN_TIME_BETWEEN_STEPS_MICROS (1000)
|
||||
|
||||
//prevent someone for making a mistake with the code
|
||||
#if ((A4954_NUM_MICROSTEPS*4) != SINE_STEPS)
|
||||
#error "SINE_STEPS must be 4x of Micro steps for the move function"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* When it comes to the stepper driver if we use angles
|
||||
* we will always have a rounding error. For example
|
||||
* a 0-65536(360) angle for 1.8 degree step is 327.68 so
|
||||
* if you increment 200 of these as 327 you have a 13.6 error
|
||||
* after one rotation.
|
||||
* If you use floating point the effect is the same but takes longer.
|
||||
*
|
||||
* The only error-less accumulation system is to use native units, ie full
|
||||
* steps and microsteps.
|
||||
*
|
||||
*/
|
||||
|
||||
class A4954
|
||||
{
|
||||
private:
|
||||
uint32_t lastStepMicros; // time in microseconds that last step happened
|
||||
bool forwardRotation=true;
|
||||
volatile bool enabled=true;
|
||||
|
||||
public:
|
||||
void begin(void);
|
||||
|
||||
//moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step.
|
||||
int32_t move(int32_t stepAngle, uint32_t mA);
|
||||
|
||||
uint32_t microsSinceStep(void) {return micros()-lastStepMicros;};
|
||||
void setRotationDirection(bool forward) {forwardRotation=forward;};
|
||||
|
||||
void enable(bool enable);
|
||||
void limitCurrent(uint8_t percent); //higher more current
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //__A4954__H__
|
||||
|
@ -1,337 +1,337 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
#include "A5995.h"
|
||||
#include "wiring_private.h"
|
||||
#include "syslog.h"
|
||||
#include "angle.h"
|
||||
#include "Arduino.h"
|
||||
#include "sine.h"
|
||||
|
||||
static uint8_t pinState=0;
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-Ofast")
|
||||
|
||||
|
||||
|
||||
|
||||
#define DAC_MAX (0x01FFL)
|
||||
// Wait for synchronization of registers between the clock domains
|
||||
static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused));
|
||||
static void syncTCC(Tcc* TCCx) {
|
||||
//int32_t t0=1000;
|
||||
while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK)
|
||||
{
|
||||
// t0--;
|
||||
// if (t0==0)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void setDAC(uint32_t DAC1, uint32_t DAC2)
|
||||
{
|
||||
TCC1->CC[1].reg = (uint32_t)DAC1; //D9 PA07 - VREF2
|
||||
syncTCC(TCC1);
|
||||
TCC1->CC[0].reg = (uint32_t)DAC2; //D4 - VREF1
|
||||
syncTCC(TCC1);
|
||||
|
||||
}
|
||||
|
||||
static void setupDAC(void)
|
||||
{
|
||||
Tcc* TCCx = TCC1 ;
|
||||
|
||||
|
||||
pinPeripheral(PIN_A5995_VREF1, PIO_TIMER_ALT);
|
||||
pinPeripheral(PIN_A5995_VREF2, PIO_TIMER);
|
||||
|
||||
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
|
||||
|
||||
while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ;
|
||||
|
||||
//ERROR("Setting TCC %d %d",ulValue,ulPin);
|
||||
TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx as normal PWM
|
||||
TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx in waveform mode Normal PWM
|
||||
TCCx->CC[1].reg = (uint32_t)0;
|
||||
syncTCC(TCCx);
|
||||
|
||||
TCCx->CC[0].reg = (uint32_t)0;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set PER to maximum counter value (resolution : 0xFFF = 12 bits)
|
||||
// =48e6/2^12=11kHz frequency
|
||||
TCCx->PER.reg = DAC_MAX;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Enable TCCx
|
||||
TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
|
||||
syncTCC(TCCx);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void A5995::begin()
|
||||
{
|
||||
//setup the A5995 pins
|
||||
digitalWrite(PIN_A5995_ENABLE1,LOW);
|
||||
pinMode(PIN_A5995_ENABLE1,OUTPUT);
|
||||
digitalWrite(PIN_A5995_ENABLE2,LOW);
|
||||
pinMode(PIN_A5995_ENABLE2,OUTPUT);
|
||||
digitalWrite(PIN_A5995_MODE1,LOW);
|
||||
pinMode(PIN_A5995_MODE1,OUTPUT);
|
||||
digitalWrite(PIN_A5995_MODE2,LOW);
|
||||
pinMode(PIN_A5995_MODE2,OUTPUT);
|
||||
digitalWrite(PIN_A5995_PHASE1,LOW);
|
||||
pinMode(PIN_A5995_PHASE1,OUTPUT);
|
||||
digitalWrite(PIN_A5995_PHASE2,LOW);
|
||||
pinMode(PIN_A5995_PHASE2,OUTPUT);
|
||||
|
||||
digitalWrite(PIN_A5995_SLEEPn,HIGH);
|
||||
pinMode(PIN_A5995_SLEEPn,OUTPUT);
|
||||
|
||||
|
||||
|
||||
//setup the PWM for current on the A4954, set for low current
|
||||
digitalWrite(PIN_A5995_VREF1,LOW);
|
||||
digitalWrite(PIN_A5995_VREF2,LOW);
|
||||
pinMode(PIN_A5995_VREF1, OUTPUT);
|
||||
pinMode(PIN_A5995_VREF2, OUTPUT);
|
||||
|
||||
enabled=true;
|
||||
lastStepMicros=0;
|
||||
forwardRotation=true;
|
||||
|
||||
setupDAC();
|
||||
|
||||
|
||||
//
|
||||
// GPIO_HIGH(PIN_A5995_ENABLE1);
|
||||
// GPIO_HIGH(PIN_A5995_ENABLE2);
|
||||
// GPIO_LOW(PIN_A5995_MODE1);
|
||||
// GPIO_LOW(PIN_A5995_MODE2);
|
||||
// GPIO_HIGH(PIN_A5995_PHASE1);
|
||||
// GPIO_HIGH(PIN_A5995_PHASE2);
|
||||
// int i=0;;
|
||||
// while (1)
|
||||
// {
|
||||
// int32_t x;
|
||||
// WARNING("MA %d",i);
|
||||
// x=(int32_t)((int64_t)i*(DAC_MAX))/3300;
|
||||
// setDAC(x,x);
|
||||
// delay(1000);
|
||||
// i=i+10;
|
||||
// if (i>1000)
|
||||
// {
|
||||
// i=0;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void A5995::enable(bool enable)
|
||||
{
|
||||
enabled=enable;
|
||||
if (enabled == false)
|
||||
{
|
||||
WARNING("A4954 disabled");
|
||||
setDAC(0,0); //turn current off
|
||||
GPIO_LOW(PIN_A5995_ENABLE1);
|
||||
GPIO_LOW(PIN_A5995_ENABLE2);
|
||||
GPIO_LOW(PIN_A5995_MODE1);
|
||||
GPIO_LOW(PIN_A5995_MODE2);
|
||||
GPIO_LOW(PIN_A5995_PHASE1);
|
||||
GPIO_LOW(PIN_A5995_PHASE2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//this is precise move and modulo of A4954_NUM_MICROSTEPS is a full step.
|
||||
// stepAngle is in A4954_NUM_MICROSTEPS units..
|
||||
// The A4954 has no idea where the motor is, so the calling function has to
|
||||
// to tell the A4954 what phase to drive motor coils.
|
||||
// A4954_NUM_MICROSTEPS is 256 by default so stepAngle of 1024 is 360 degrees
|
||||
// Note you can only move up to +/-A4954_NUM_MICROSTEPS from where you
|
||||
// currently are.
|
||||
int32_t A5995::move(int32_t stepAngle, uint32_t mA)
|
||||
{
|
||||
uint16_t angle;
|
||||
int32_t cos,sin;
|
||||
int32_t dacSin,dacCos;
|
||||
static int32_t lastSin=0,lastCos=0;
|
||||
static int i=1;
|
||||
|
||||
if (enabled == false)
|
||||
{
|
||||
WARNING("A4954 disabled");
|
||||
setDAC(0,0); //turn current off
|
||||
GPIO_LOW(PIN_A5995_ENABLE1);
|
||||
GPIO_LOW(PIN_A5995_ENABLE2);
|
||||
GPIO_LOW(PIN_A5995_MODE1);
|
||||
GPIO_LOW(PIN_A5995_MODE2);
|
||||
GPIO_LOW(PIN_A5995_PHASE1);
|
||||
GPIO_LOW(PIN_A5995_PHASE2);
|
||||
return stepAngle;
|
||||
}
|
||||
|
||||
//WARNING("move %d %d",stepAngle,mA);
|
||||
|
||||
stepAngle=(stepAngle) % SINE_STEPS;
|
||||
//figure out our sine Angle
|
||||
// note our SINE_STEPS is 4x of microsteps for a reason
|
||||
//angle=(stepAngle+(SINE_STEPS/8)) % SINE_STEPS;
|
||||
angle=stepAngle;
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
WARNING("angle %d ",angle);
|
||||
}
|
||||
//calculate the sine and cosine of our angle
|
||||
sin=sine(angle);
|
||||
cos=cosine(angle);
|
||||
|
||||
//if we are reverse swap the sign of one of the angels
|
||||
if (false == forwardRotation)
|
||||
{
|
||||
cos=-cos;
|
||||
}
|
||||
|
||||
//scale sine result by current(mA)
|
||||
dacSin=((int32_t)mA*(int64_t)(sin))/SINE_MAX;
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
WARNING("dacsine %d ",dacSin);
|
||||
}
|
||||
// if ((lastSin-dacSin)>100) //decreasing current
|
||||
// {
|
||||
// GPIO_LOW(PIN_A5995_MODE2); //fast decay
|
||||
// } else
|
||||
// {
|
||||
// GPIO_HIGH(PIN_A5995_MODE2); //slow decay
|
||||
// }
|
||||
lastSin=dacSin;
|
||||
|
||||
//convert value into DAC scaled to 3300mA max
|
||||
dacSin=(int32_t)((int64_t)abs(dacSin)*(DAC_MAX))/3300;
|
||||
|
||||
|
||||
//scale cosine result by current(mA)
|
||||
dacCos=((int32_t)mA*(int64_t)(cos))/SINE_MAX;
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
WARNING("daccos %d ",dacCos);
|
||||
}
|
||||
// if ((lastCos-dacCos)>100) //decreasing current
|
||||
// {
|
||||
// GPIO_LOW(PIN_A5995_MODE1); //fast decay
|
||||
// } else
|
||||
// {
|
||||
// GPIO_HIGH(PIN_A5995_MODE1); //slow decay
|
||||
// }
|
||||
lastCos=dacCos;
|
||||
|
||||
//convert value into DAC scaled to 3300mA max
|
||||
dacCos=(int32_t)((int64_t)abs(dacCos)*(DAC_MAX))/3300;
|
||||
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
WARNING("dacs are %d %d",dacSin,dacCos);
|
||||
}
|
||||
setDAC(dacSin,dacCos);
|
||||
|
||||
GPIO_HIGH(PIN_A5995_ENABLE1);
|
||||
GPIO_HIGH(PIN_A5995_ENABLE2);
|
||||
GPIO_LOW(PIN_A5995_MODE1);
|
||||
GPIO_LOW(PIN_A5995_MODE2);
|
||||
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
WARNING("sins are %d %d",sin,cos);
|
||||
}
|
||||
|
||||
if (sin>0)
|
||||
{
|
||||
GPIO_HIGH(PIN_A5995_PHASE2);
|
||||
}else
|
||||
{
|
||||
GPIO_LOW(PIN_A5995_PHASE2);
|
||||
|
||||
}
|
||||
if (cos>0)
|
||||
{
|
||||
GPIO_HIGH(PIN_A5995_PHASE1);
|
||||
|
||||
}else
|
||||
{
|
||||
GPIO_LOW(PIN_A5995_PHASE1);
|
||||
|
||||
}
|
||||
|
||||
// i++;
|
||||
// if (i>3000) i=0;
|
||||
// YELLOW_LED(led);
|
||||
// led=(led+1) & 0x01;
|
||||
lastStepMicros=micros();
|
||||
return stepAngle;
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
#include "A5995.h"
|
||||
#include "wiring_private.h"
|
||||
#include "syslog.h"
|
||||
#include "angle.h"
|
||||
#include "Arduino.h"
|
||||
#include "sine.h"
|
||||
|
||||
static uint8_t pinState=0;
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-Ofast")
|
||||
|
||||
|
||||
|
||||
|
||||
#define DAC_MAX (0x01FFL)
|
||||
// Wait for synchronization of registers between the clock domains
|
||||
static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused));
|
||||
static void syncTCC(Tcc* TCCx) {
|
||||
//int32_t t0=1000;
|
||||
while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK)
|
||||
{
|
||||
// t0--;
|
||||
// if (t0==0)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void setDAC(uint32_t DAC1, uint32_t DAC2)
|
||||
{
|
||||
TCC1->CC[1].reg = (uint32_t)DAC1; //D9 PA07 - VREF2
|
||||
syncTCC(TCC1);
|
||||
TCC1->CC[0].reg = (uint32_t)DAC2; //D4 - VREF1
|
||||
syncTCC(TCC1);
|
||||
|
||||
}
|
||||
|
||||
static void setupDAC(void)
|
||||
{
|
||||
Tcc* TCCx = TCC1 ;
|
||||
|
||||
|
||||
pinPeripheral(PIN_A5995_VREF1, PIO_TIMER_ALT);
|
||||
pinPeripheral(PIN_A5995_VREF2, PIO_TIMER);
|
||||
|
||||
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
|
||||
|
||||
while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ;
|
||||
|
||||
//ERROR("Setting TCC %d %d",ulValue,ulPin);
|
||||
TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx as normal PWM
|
||||
TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set TCx in waveform mode Normal PWM
|
||||
TCCx->CC[1].reg = (uint32_t)0;
|
||||
syncTCC(TCCx);
|
||||
|
||||
TCCx->CC[0].reg = (uint32_t)0;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Set PER to maximum counter value (resolution : 0xFFF = 12 bits)
|
||||
// =48e6/2^12=11kHz frequency
|
||||
TCCx->PER.reg = DAC_MAX;
|
||||
syncTCC(TCCx);
|
||||
|
||||
// Enable TCCx
|
||||
TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
|
||||
syncTCC(TCCx);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void A5995::begin()
|
||||
{
|
||||
//setup the A5995 pins
|
||||
digitalWrite(PIN_A5995_ENABLE1,LOW);
|
||||
pinMode(PIN_A5995_ENABLE1,OUTPUT);
|
||||
digitalWrite(PIN_A5995_ENABLE2,LOW);
|
||||
pinMode(PIN_A5995_ENABLE2,OUTPUT);
|
||||
digitalWrite(PIN_A5995_MODE1,LOW);
|
||||
pinMode(PIN_A5995_MODE1,OUTPUT);
|
||||
digitalWrite(PIN_A5995_MODE2,LOW);
|
||||
pinMode(PIN_A5995_MODE2,OUTPUT);
|
||||
digitalWrite(PIN_A5995_PHASE1,LOW);
|
||||
pinMode(PIN_A5995_PHASE1,OUTPUT);
|
||||
digitalWrite(PIN_A5995_PHASE2,LOW);
|
||||
pinMode(PIN_A5995_PHASE2,OUTPUT);
|
||||
|
||||
digitalWrite(PIN_A5995_SLEEPn,HIGH);
|
||||
pinMode(PIN_A5995_SLEEPn,OUTPUT);
|
||||
|
||||
|
||||
|
||||
//setup the PWM for current on the A4954, set for low current
|
||||
digitalWrite(PIN_A5995_VREF1,LOW);
|
||||
digitalWrite(PIN_A5995_VREF2,LOW);
|
||||
pinMode(PIN_A5995_VREF1, OUTPUT);
|
||||
pinMode(PIN_A5995_VREF2, OUTPUT);
|
||||
|
||||
enabled=true;
|
||||
lastStepMicros=0;
|
||||
forwardRotation=true;
|
||||
|
||||
setupDAC();
|
||||
|
||||
|
||||
//
|
||||
// GPIO_HIGH(PIN_A5995_ENABLE1);
|
||||
// GPIO_HIGH(PIN_A5995_ENABLE2);
|
||||
// GPIO_LOW(PIN_A5995_MODE1);
|
||||
// GPIO_LOW(PIN_A5995_MODE2);
|
||||
// GPIO_HIGH(PIN_A5995_PHASE1);
|
||||
// GPIO_HIGH(PIN_A5995_PHASE2);
|
||||
// int i=0;;
|
||||
// while (1)
|
||||
// {
|
||||
// int32_t x;
|
||||
// WARNING("MA %d",i);
|
||||
// x=(int32_t)((int64_t)i*(DAC_MAX))/3300;
|
||||
// setDAC(x,x);
|
||||
// delay(1000);
|
||||
// i=i+10;
|
||||
// if (i>1000)
|
||||
// {
|
||||
// i=0;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void A5995::enable(bool enable)
|
||||
{
|
||||
enabled=enable;
|
||||
if (enabled == false)
|
||||
{
|
||||
WARNING("A4954 disabled");
|
||||
setDAC(0,0); //turn current off
|
||||
GPIO_LOW(PIN_A5995_ENABLE1);
|
||||
GPIO_LOW(PIN_A5995_ENABLE2);
|
||||
GPIO_LOW(PIN_A5995_MODE1);
|
||||
GPIO_LOW(PIN_A5995_MODE2);
|
||||
GPIO_LOW(PIN_A5995_PHASE1);
|
||||
GPIO_LOW(PIN_A5995_PHASE2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//this is precise move and modulo of A4954_NUM_MICROSTEPS is a full step.
|
||||
// stepAngle is in A4954_NUM_MICROSTEPS units..
|
||||
// The A4954 has no idea where the motor is, so the calling function has to
|
||||
// to tell the A4954 what phase to drive motor coils.
|
||||
// A4954_NUM_MICROSTEPS is 256 by default so stepAngle of 1024 is 360 degrees
|
||||
// Note you can only move up to +/-A4954_NUM_MICROSTEPS from where you
|
||||
// currently are.
|
||||
int32_t A5995::move(int32_t stepAngle, uint32_t mA)
|
||||
{
|
||||
uint16_t angle;
|
||||
int32_t cos,sin;
|
||||
int32_t dacSin,dacCos;
|
||||
static int32_t lastSin=0,lastCos=0;
|
||||
static int i=1;
|
||||
|
||||
if (enabled == false)
|
||||
{
|
||||
WARNING("A4954 disabled");
|
||||
setDAC(0,0); //turn current off
|
||||
GPIO_LOW(PIN_A5995_ENABLE1);
|
||||
GPIO_LOW(PIN_A5995_ENABLE2);
|
||||
GPIO_LOW(PIN_A5995_MODE1);
|
||||
GPIO_LOW(PIN_A5995_MODE2);
|
||||
GPIO_LOW(PIN_A5995_PHASE1);
|
||||
GPIO_LOW(PIN_A5995_PHASE2);
|
||||
return stepAngle;
|
||||
}
|
||||
|
||||
//WARNING("move %d %d",stepAngle,mA);
|
||||
|
||||
stepAngle=(stepAngle) % SINE_STEPS;
|
||||
//figure out our sine Angle
|
||||
// note our SINE_STEPS is 4x of microsteps for a reason
|
||||
//angle=(stepAngle+(SINE_STEPS/8)) % SINE_STEPS;
|
||||
angle=stepAngle;
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
WARNING("angle %d ",angle);
|
||||
}
|
||||
//calculate the sine and cosine of our angle
|
||||
sin=sine(angle);
|
||||
cos=cosine(angle);
|
||||
|
||||
//if we are reverse swap the sign of one of the angels
|
||||
if (false == forwardRotation)
|
||||
{
|
||||
cos=-cos;
|
||||
}
|
||||
|
||||
//scale sine result by current(mA)
|
||||
dacSin=((int32_t)mA*(int64_t)(sin))/SINE_MAX;
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
WARNING("dacsine %d ",dacSin);
|
||||
}
|
||||
// if ((lastSin-dacSin)>100) //decreasing current
|
||||
// {
|
||||
// GPIO_LOW(PIN_A5995_MODE2); //fast decay
|
||||
// } else
|
||||
// {
|
||||
// GPIO_HIGH(PIN_A5995_MODE2); //slow decay
|
||||
// }
|
||||
lastSin=dacSin;
|
||||
|
||||
//convert value into DAC scaled to 3300mA max
|
||||
dacSin=(int32_t)((int64_t)abs(dacSin)*(DAC_MAX))/3300;
|
||||
|
||||
|
||||
//scale cosine result by current(mA)
|
||||
dacCos=((int32_t)mA*(int64_t)(cos))/SINE_MAX;
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
WARNING("daccos %d ",dacCos);
|
||||
}
|
||||
// if ((lastCos-dacCos)>100) //decreasing current
|
||||
// {
|
||||
// GPIO_LOW(PIN_A5995_MODE1); //fast decay
|
||||
// } else
|
||||
// {
|
||||
// GPIO_HIGH(PIN_A5995_MODE1); //slow decay
|
||||
// }
|
||||
lastCos=dacCos;
|
||||
|
||||
//convert value into DAC scaled to 3300mA max
|
||||
dacCos=(int32_t)((int64_t)abs(dacCos)*(DAC_MAX))/3300;
|
||||
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
WARNING("dacs are %d %d",dacSin,dacCos);
|
||||
}
|
||||
setDAC(dacSin,dacCos);
|
||||
|
||||
GPIO_HIGH(PIN_A5995_ENABLE1);
|
||||
GPIO_HIGH(PIN_A5995_ENABLE2);
|
||||
GPIO_LOW(PIN_A5995_MODE1);
|
||||
GPIO_LOW(PIN_A5995_MODE2);
|
||||
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
WARNING("sins are %d %d",sin,cos);
|
||||
}
|
||||
|
||||
if (sin>0)
|
||||
{
|
||||
GPIO_HIGH(PIN_A5995_PHASE2);
|
||||
}else
|
||||
{
|
||||
GPIO_LOW(PIN_A5995_PHASE2);
|
||||
|
||||
}
|
||||
if (cos>0)
|
||||
{
|
||||
GPIO_HIGH(PIN_A5995_PHASE1);
|
||||
|
||||
}else
|
||||
{
|
||||
GPIO_LOW(PIN_A5995_PHASE1);
|
||||
|
||||
}
|
||||
|
||||
// i++;
|
||||
// if (i>3000) i=0;
|
||||
// YELLOW_LED(led);
|
||||
// led=(led+1) & 0x01;
|
||||
lastStepMicros=micros();
|
||||
return stepAngle;
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
|
||||
|
||||
|
@ -1,92 +1,92 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef A5995_H_
|
||||
#define A5995_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "board.h"
|
||||
#include "angle.h"
|
||||
#include "sine.h"
|
||||
|
||||
#define A5995_NUM_MICROSTEPS (256)
|
||||
|
||||
|
||||
//prevent someone for making a mistake with the code
|
||||
#if ((A5995_NUM_MICROSTEPS*4) != SINE_STEPS)
|
||||
#error "SINE_STEPS must be 4x of Micro steps for the move function"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* When it comes to the stepper driver if we use angles
|
||||
* we will always have a rounding error. For example
|
||||
* a 0-65536(360) angle for 1.8 degree step is 327.68 so
|
||||
* if you increment 200 of these as 327 you have a 13.6 error
|
||||
* after one rotation.
|
||||
* If you use floating point the effect is the same but takes longer.
|
||||
*
|
||||
* The only error-less accumulation system is to use native units, ie full
|
||||
* steps and microsteps.
|
||||
*
|
||||
*/
|
||||
|
||||
class A5995
|
||||
{
|
||||
private:
|
||||
uint32_t lastStepMicros; // time in microseconds that last step happened
|
||||
bool forwardRotation=true;
|
||||
volatile bool enabled=true;
|
||||
|
||||
public:
|
||||
void begin(void);
|
||||
|
||||
//moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step.
|
||||
int32_t move(int32_t stepAngle, uint32_t mA);
|
||||
|
||||
uint32_t microsSinceStep(void) {return micros()-lastStepMicros;};
|
||||
void setRotationDirection(bool forward) {forwardRotation=forward;};
|
||||
|
||||
void enable(bool enable);
|
||||
void limitCurrent(uint8_t percent) {return;}; //Not used
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* A5995_H_ */
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef A5995_H_
|
||||
#define A5995_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "board.h"
|
||||
#include "angle.h"
|
||||
#include "sine.h"
|
||||
|
||||
#define A5995_NUM_MICROSTEPS (256)
|
||||
|
||||
|
||||
//prevent someone for making a mistake with the code
|
||||
#if ((A5995_NUM_MICROSTEPS*4) != SINE_STEPS)
|
||||
#error "SINE_STEPS must be 4x of Micro steps for the move function"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* When it comes to the stepper driver if we use angles
|
||||
* we will always have a rounding error. For example
|
||||
* a 0-65536(360) angle for 1.8 degree step is 327.68 so
|
||||
* if you increment 200 of these as 327 you have a 13.6 error
|
||||
* after one rotation.
|
||||
* If you use floating point the effect is the same but takes longer.
|
||||
*
|
||||
* The only error-less accumulation system is to use native units, ie full
|
||||
* steps and microsteps.
|
||||
*
|
||||
*/
|
||||
|
||||
class A5995
|
||||
{
|
||||
private:
|
||||
uint32_t lastStepMicros; // time in microseconds that last step happened
|
||||
bool forwardRotation=true;
|
||||
volatile bool enabled=true;
|
||||
|
||||
public:
|
||||
void begin(void);
|
||||
|
||||
//moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step.
|
||||
int32_t move(int32_t stepAngle, uint32_t mA);
|
||||
|
||||
uint32_t microsSinceStep(void) {return micros()-lastStepMicros;};
|
||||
void setRotationDirection(bool forward) {forwardRotation=forward;};
|
||||
|
||||
void enable(bool enable);
|
||||
void limitCurrent(uint8_t percent) {return;}; //Not used
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* A5995_H_ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,155 +1,155 @@
|
||||
#ifndef _ADAFRUIT_GFX_H
|
||||
#define _ADAFRUIT_GFX_H
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#include "Print.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include "gfxfont.h"
|
||||
|
||||
class Adafruit_GFX : public Print {
|
||||
|
||||
public:
|
||||
|
||||
Adafruit_GFX(int16_t w, int16_t h); // Constructor
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
|
||||
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void
|
||||
drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color),
|
||||
drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
|
||||
drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
|
||||
drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
|
||||
fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
|
||||
fillScreen(uint16_t color),
|
||||
invertDisplay(boolean i);
|
||||
|
||||
// These exist only with Adafruit_GFX (no subclass overrides)
|
||||
void
|
||||
drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
|
||||
drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
|
||||
uint16_t color),
|
||||
fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
|
||||
fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
|
||||
int16_t delta, uint16_t color),
|
||||
drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color),
|
||||
fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color),
|
||||
drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
|
||||
int16_t radius, uint16_t color),
|
||||
fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
|
||||
int16_t radius, uint16_t color),
|
||||
drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color),
|
||||
drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color, uint16_t bg),
|
||||
drawBitmap(int16_t x, int16_t y, uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color),
|
||||
drawBitmap(int16_t x, int16_t y, uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color, uint16_t bg),
|
||||
drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color),
|
||||
drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color,
|
||||
uint16_t bg, uint8_t size),
|
||||
setCursor(int16_t x, int16_t y),
|
||||
setTextColor(uint16_t c),
|
||||
setTextColor(uint16_t c, uint16_t bg),
|
||||
setTextSize(uint8_t s),
|
||||
setTextWrap(boolean w),
|
||||
setRotation(uint8_t r),
|
||||
cp437(boolean x=true),
|
||||
setFont(const GFXfont *f = NULL),
|
||||
getTextBounds(char *string, int16_t x, int16_t y,
|
||||
int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h),
|
||||
getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y,
|
||||
int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
|
||||
#if ARDUINO >= 100
|
||||
virtual size_t write(uint8_t);
|
||||
#else
|
||||
virtual void write(uint8_t);
|
||||
#endif
|
||||
|
||||
int16_t height(void) const;
|
||||
int16_t width(void) const;
|
||||
|
||||
uint8_t getRotation(void) const;
|
||||
|
||||
// get current cursor position (get rotation safe maximum values, using: width() for x, height() for y)
|
||||
int16_t getCursorX(void) const;
|
||||
int16_t getCursorY(void) const;
|
||||
|
||||
protected:
|
||||
const int16_t
|
||||
WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes
|
||||
int16_t
|
||||
_width, _height, // Display w/h as modified by current rotation
|
||||
cursor_x, cursor_y;
|
||||
uint16_t
|
||||
textcolor, textbgcolor;
|
||||
uint8_t
|
||||
textsize,
|
||||
rotation;
|
||||
boolean
|
||||
wrap, // If set, 'wrap' text at right edge of display
|
||||
_cp437; // If set, use correct CP437 charset (default is off)
|
||||
GFXfont
|
||||
*gfxFont;
|
||||
};
|
||||
|
||||
class Adafruit_GFX_Button {
|
||||
|
||||
public:
|
||||
Adafruit_GFX_Button(void);
|
||||
void initButton(Adafruit_GFX *gfx, int16_t x, int16_t y,
|
||||
uint8_t w, uint8_t h, uint16_t outline, uint16_t fill,
|
||||
uint16_t textcolor, char *label, uint8_t textsize);
|
||||
void drawButton(boolean inverted = false);
|
||||
boolean contains(int16_t x, int16_t y);
|
||||
|
||||
void press(boolean p);
|
||||
boolean isPressed();
|
||||
boolean justPressed();
|
||||
boolean justReleased();
|
||||
|
||||
private:
|
||||
Adafruit_GFX *_gfx;
|
||||
int16_t _x, _y;
|
||||
uint16_t _w, _h;
|
||||
uint8_t _textsize;
|
||||
uint16_t _outlinecolor, _fillcolor, _textcolor;
|
||||
char _label[10];
|
||||
|
||||
boolean currstate, laststate;
|
||||
};
|
||||
|
||||
class GFXcanvas1 : public Adafruit_GFX {
|
||||
|
||||
public:
|
||||
GFXcanvas1(uint16_t w, uint16_t h);
|
||||
~GFXcanvas1(void);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color),
|
||||
fillScreen(uint16_t color);
|
||||
uint8_t *getBuffer(void);
|
||||
private:
|
||||
uint8_t *buffer;
|
||||
};
|
||||
|
||||
class GFXcanvas16 : public Adafruit_GFX {
|
||||
GFXcanvas16(uint16_t w, uint16_t h);
|
||||
~GFXcanvas16(void);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color),
|
||||
fillScreen(uint16_t color);
|
||||
uint16_t *getBuffer(void);
|
||||
private:
|
||||
uint16_t *buffer;
|
||||
};
|
||||
|
||||
#endif // _ADAFRUIT_GFX_H
|
||||
#ifndef _ADAFRUIT_GFX_H
|
||||
#define _ADAFRUIT_GFX_H
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#include "Print.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include "gfxfont.h"
|
||||
|
||||
class Adafruit_GFX : public Print {
|
||||
|
||||
public:
|
||||
|
||||
Adafruit_GFX(int16_t w, int16_t h); // Constructor
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
|
||||
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void
|
||||
drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color),
|
||||
drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
|
||||
drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
|
||||
drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
|
||||
fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
|
||||
fillScreen(uint16_t color),
|
||||
invertDisplay(boolean i);
|
||||
|
||||
// These exist only with Adafruit_GFX (no subclass overrides)
|
||||
void
|
||||
drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
|
||||
drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
|
||||
uint16_t color),
|
||||
fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
|
||||
fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
|
||||
int16_t delta, uint16_t color),
|
||||
drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color),
|
||||
fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color),
|
||||
drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
|
||||
int16_t radius, uint16_t color),
|
||||
fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
|
||||
int16_t radius, uint16_t color),
|
||||
drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color),
|
||||
drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color, uint16_t bg),
|
||||
drawBitmap(int16_t x, int16_t y, uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color),
|
||||
drawBitmap(int16_t x, int16_t y, uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color, uint16_t bg),
|
||||
drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color),
|
||||
drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color,
|
||||
uint16_t bg, uint8_t size),
|
||||
setCursor(int16_t x, int16_t y),
|
||||
setTextColor(uint16_t c),
|
||||
setTextColor(uint16_t c, uint16_t bg),
|
||||
setTextSize(uint8_t s),
|
||||
setTextWrap(boolean w),
|
||||
setRotation(uint8_t r),
|
||||
cp437(boolean x=true),
|
||||
setFont(const GFXfont *f = NULL),
|
||||
getTextBounds(char *string, int16_t x, int16_t y,
|
||||
int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h),
|
||||
getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y,
|
||||
int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
|
||||
#if ARDUINO >= 100
|
||||
virtual size_t write(uint8_t);
|
||||
#else
|
||||
virtual void write(uint8_t);
|
||||
#endif
|
||||
|
||||
int16_t height(void) const;
|
||||
int16_t width(void) const;
|
||||
|
||||
uint8_t getRotation(void) const;
|
||||
|
||||
// get current cursor position (get rotation safe maximum values, using: width() for x, height() for y)
|
||||
int16_t getCursorX(void) const;
|
||||
int16_t getCursorY(void) const;
|
||||
|
||||
protected:
|
||||
const int16_t
|
||||
WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes
|
||||
int16_t
|
||||
_width, _height, // Display w/h as modified by current rotation
|
||||
cursor_x, cursor_y;
|
||||
uint16_t
|
||||
textcolor, textbgcolor;
|
||||
uint8_t
|
||||
textsize,
|
||||
rotation;
|
||||
boolean
|
||||
wrap, // If set, 'wrap' text at right edge of display
|
||||
_cp437; // If set, use correct CP437 charset (default is off)
|
||||
GFXfont
|
||||
*gfxFont;
|
||||
};
|
||||
|
||||
class Adafruit_GFX_Button {
|
||||
|
||||
public:
|
||||
Adafruit_GFX_Button(void);
|
||||
void initButton(Adafruit_GFX *gfx, int16_t x, int16_t y,
|
||||
uint8_t w, uint8_t h, uint16_t outline, uint16_t fill,
|
||||
uint16_t textcolor, char *label, uint8_t textsize);
|
||||
void drawButton(boolean inverted = false);
|
||||
boolean contains(int16_t x, int16_t y);
|
||||
|
||||
void press(boolean p);
|
||||
boolean isPressed();
|
||||
boolean justPressed();
|
||||
boolean justReleased();
|
||||
|
||||
private:
|
||||
Adafruit_GFX *_gfx;
|
||||
int16_t _x, _y;
|
||||
uint16_t _w, _h;
|
||||
uint8_t _textsize;
|
||||
uint16_t _outlinecolor, _fillcolor, _textcolor;
|
||||
char _label[10];
|
||||
|
||||
boolean currstate, laststate;
|
||||
};
|
||||
|
||||
class GFXcanvas1 : public Adafruit_GFX {
|
||||
|
||||
public:
|
||||
GFXcanvas1(uint16_t w, uint16_t h);
|
||||
~GFXcanvas1(void);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color),
|
||||
fillScreen(uint16_t color);
|
||||
uint8_t *getBuffer(void);
|
||||
private:
|
||||
uint8_t *buffer;
|
||||
};
|
||||
|
||||
class GFXcanvas16 : public Adafruit_GFX {
|
||||
GFXcanvas16(uint16_t w, uint16_t h);
|
||||
~GFXcanvas16(void);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color),
|
||||
fillScreen(uint16_t color);
|
||||
uint16_t *getBuffer(void);
|
||||
private:
|
||||
uint16_t *buffer;
|
||||
};
|
||||
|
||||
#endif // _ADAFRUIT_GFX_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,182 +1,182 @@
|
||||
/*********************************************************************
|
||||
This is a library for our Monochrome OLEDs based on SSD1306 drivers
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/category/63_98
|
||||
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information
|
||||
All text above, and the splash screen must be included in any redistribution
|
||||
*********************************************************************/
|
||||
#ifndef _Adafruit_SSD1306_H_
|
||||
#define _Adafruit_SSD1306_H_
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#define WIRE_WRITE Wire.write
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#define WIRE_WRITE Wire.send
|
||||
#endif
|
||||
|
||||
#if defined(__SAM3X8E__)
|
||||
typedef volatile RwReg PortReg;
|
||||
typedef uint32_t PortMask;
|
||||
#define HAVE_PORTREG
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
// not supported
|
||||
#elif defined(ESP8266) || defined(ARDUINO_STM32_FEATHER)
|
||||
typedef volatile uint32_t PortReg;
|
||||
typedef uint32_t PortMask;
|
||||
#else
|
||||
typedef volatile uint8_t PortReg;
|
||||
typedef uint8_t PortMask;
|
||||
#define HAVE_PORTREG
|
||||
#endif
|
||||
|
||||
#include <SPI.h>
|
||||
#include "Adafruit_GFX.h"
|
||||
|
||||
#define BLACK 0
|
||||
#define WHITE 1
|
||||
#define INVERSE 2
|
||||
|
||||
#define SSD1306_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D
|
||||
// Address for 128x32 is 0x3C
|
||||
// Address for 128x64 is 0x3D (default) or 0x3C (if SA0 is grounded)
|
||||
|
||||
/*=========================================================================
|
||||
SSD1306 Displays
|
||||
-----------------------------------------------------------------------
|
||||
The driver is used in multiple displays (128x64, 128x32, etc.).
|
||||
Select the appropriate display below to create an appropriately
|
||||
sized framebuffer, etc.
|
||||
|
||||
SSD1306_128_64 128x64 pixel display
|
||||
|
||||
SSD1306_128_32 128x32 pixel display
|
||||
|
||||
SSD1306_96_16
|
||||
|
||||
-----------------------------------------------------------------------*/
|
||||
#define SSD1306_128_64
|
||||
// #define SSD1306_128_32
|
||||
// #define SSD1306_96_16
|
||||
/*=========================================================================*/
|
||||
|
||||
#if defined SSD1306_128_64 && defined SSD1306_128_32
|
||||
#error "Only one SSD1306 display can be specified at once in SSD1306.h"
|
||||
#endif
|
||||
#if !defined SSD1306_128_64 && !defined SSD1306_128_32 && !defined SSD1306_96_16
|
||||
#error "At least one SSD1306 display must be specified in SSD1306.h"
|
||||
#endif
|
||||
|
||||
#if defined SSD1306_128_64
|
||||
#define SSD1306_LCDWIDTH 128
|
||||
#define SSD1306_LCDHEIGHT 64
|
||||
#endif
|
||||
#if defined SSD1306_128_32
|
||||
#define SSD1306_LCDWIDTH 128
|
||||
#define SSD1306_LCDHEIGHT 32
|
||||
#endif
|
||||
#if defined SSD1306_96_16
|
||||
#define SSD1306_LCDWIDTH 96
|
||||
#define SSD1306_LCDHEIGHT 16
|
||||
#endif
|
||||
|
||||
#define SSD1306_SETCONTRAST 0x81
|
||||
#define SSD1306_DISPLAYALLON_RESUME 0xA4
|
||||
#define SSD1306_DISPLAYALLON 0xA5
|
||||
#define SSD1306_NORMALDISPLAY 0xA6
|
||||
#define SSD1306_INVERTDISPLAY 0xA7
|
||||
#define SSD1306_DISPLAYOFF 0xAE
|
||||
#define SSD1306_DISPLAYON 0xAF
|
||||
|
||||
#define SSD1306_SETDISPLAYOFFSET 0xD3
|
||||
#define SSD1306_SETCOMPINS 0xDA
|
||||
|
||||
#define SSD1306_SETVCOMDETECT 0xDB
|
||||
|
||||
#define SSD1306_SETDISPLAYCLOCKDIV 0xD5
|
||||
#define SSD1306_SETPRECHARGE 0xD9
|
||||
|
||||
#define SSD1306_SETMULTIPLEX 0xA8
|
||||
|
||||
#define SSD1306_SETLOWCOLUMN 0x00
|
||||
#define SSD1306_SETHIGHCOLUMN 0x10
|
||||
|
||||
#define SSD1306_SETSTARTLINE 0x40
|
||||
|
||||
#define SSD1306_MEMORYMODE 0x20
|
||||
#define SSD1306_COLUMNADDR 0x21
|
||||
#define SSD1306_PAGEADDR 0x22
|
||||
|
||||
#define SSD1306_COMSCANINC 0xC0
|
||||
#define SSD1306_COMSCANDEC 0xC8
|
||||
|
||||
#define SSD1306_SEGREMAP 0xA0
|
||||
|
||||
#define SSD1306_CHARGEPUMP 0x8D
|
||||
|
||||
#define SSD1306_EXTERNALVCC 0x1
|
||||
#define SSD1306_SWITCHCAPVCC 0x2
|
||||
|
||||
// Scrolling #defines
|
||||
#define SSD1306_ACTIVATE_SCROLL 0x2F
|
||||
#define SSD1306_DEACTIVATE_SCROLL 0x2E
|
||||
#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3
|
||||
#define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26
|
||||
#define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27
|
||||
#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29
|
||||
#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A
|
||||
|
||||
class Adafruit_SSD1306 : public Adafruit_GFX {
|
||||
public:
|
||||
Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS);
|
||||
Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS);
|
||||
Adafruit_SSD1306(int8_t RST = -1);
|
||||
|
||||
bool begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = SSD1306_I2C_ADDRESS, bool reset=true);
|
||||
uint8_t ssd1306_command(uint8_t c);
|
||||
|
||||
void clearDisplay(void);
|
||||
void invertDisplay(uint8_t i);
|
||||
void display();
|
||||
|
||||
void startscrollright(uint8_t start, uint8_t stop);
|
||||
void startscrollleft(uint8_t start, uint8_t stop);
|
||||
|
||||
void startscrolldiagright(uint8_t start, uint8_t stop);
|
||||
void startscrolldiagleft(uint8_t start, uint8_t stop);
|
||||
void stopscroll(void);
|
||||
|
||||
void dim(boolean dim);
|
||||
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
|
||||
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
|
||||
private:
|
||||
int8_t _i2caddr, _vccstate, sid, sclk, dc, rst, cs;
|
||||
void fastSPIwrite(uint8_t c);
|
||||
|
||||
boolean hwSPI;
|
||||
#ifdef HAVE_PORTREG
|
||||
PortReg *mosiport, *clkport, *csport, *dcport;
|
||||
PortMask mosipinmask, clkpinmask, cspinmask, dcpinmask;
|
||||
#endif
|
||||
|
||||
inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline));
|
||||
inline void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) __attribute__((always_inline));
|
||||
|
||||
};
|
||||
|
||||
#endif /* _Adafruit_SSD1306_H_ */
|
||||
/*********************************************************************
|
||||
This is a library for our Monochrome OLEDs based on SSD1306 drivers
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/category/63_98
|
||||
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information
|
||||
All text above, and the splash screen must be included in any redistribution
|
||||
*********************************************************************/
|
||||
#ifndef _Adafruit_SSD1306_H_
|
||||
#define _Adafruit_SSD1306_H_
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#define WIRE_WRITE Wire.write
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#define WIRE_WRITE Wire.send
|
||||
#endif
|
||||
|
||||
#if defined(__SAM3X8E__)
|
||||
typedef volatile RwReg PortReg;
|
||||
typedef uint32_t PortMask;
|
||||
#define HAVE_PORTREG
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
// not supported
|
||||
#elif defined(ESP8266) || defined(ARDUINO_STM32_FEATHER)
|
||||
typedef volatile uint32_t PortReg;
|
||||
typedef uint32_t PortMask;
|
||||
#else
|
||||
typedef volatile uint8_t PortReg;
|
||||
typedef uint8_t PortMask;
|
||||
#define HAVE_PORTREG
|
||||
#endif
|
||||
|
||||
#include <SPI.h>
|
||||
#include "Adafruit_GFX.h"
|
||||
|
||||
#define BLACK 0
|
||||
#define WHITE 1
|
||||
#define INVERSE 2
|
||||
|
||||
#define SSD1306_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D
|
||||
// Address for 128x32 is 0x3C
|
||||
// Address for 128x64 is 0x3D (default) or 0x3C (if SA0 is grounded)
|
||||
|
||||
/*=========================================================================
|
||||
SSD1306 Displays
|
||||
-----------------------------------------------------------------------
|
||||
The driver is used in multiple displays (128x64, 128x32, etc.).
|
||||
Select the appropriate display below to create an appropriately
|
||||
sized framebuffer, etc.
|
||||
|
||||
SSD1306_128_64 128x64 pixel display
|
||||
|
||||
SSD1306_128_32 128x32 pixel display
|
||||
|
||||
SSD1306_96_16
|
||||
|
||||
-----------------------------------------------------------------------*/
|
||||
#define SSD1306_128_64
|
||||
// #define SSD1306_128_32
|
||||
// #define SSD1306_96_16
|
||||
/*=========================================================================*/
|
||||
|
||||
#if defined SSD1306_128_64 && defined SSD1306_128_32
|
||||
#error "Only one SSD1306 display can be specified at once in SSD1306.h"
|
||||
#endif
|
||||
#if !defined SSD1306_128_64 && !defined SSD1306_128_32 && !defined SSD1306_96_16
|
||||
#error "At least one SSD1306 display must be specified in SSD1306.h"
|
||||
#endif
|
||||
|
||||
#if defined SSD1306_128_64
|
||||
#define SSD1306_LCDWIDTH 128
|
||||
#define SSD1306_LCDHEIGHT 64
|
||||
#endif
|
||||
#if defined SSD1306_128_32
|
||||
#define SSD1306_LCDWIDTH 128
|
||||
#define SSD1306_LCDHEIGHT 32
|
||||
#endif
|
||||
#if defined SSD1306_96_16
|
||||
#define SSD1306_LCDWIDTH 96
|
||||
#define SSD1306_LCDHEIGHT 16
|
||||
#endif
|
||||
|
||||
#define SSD1306_SETCONTRAST 0x81
|
||||
#define SSD1306_DISPLAYALLON_RESUME 0xA4
|
||||
#define SSD1306_DISPLAYALLON 0xA5
|
||||
#define SSD1306_NORMALDISPLAY 0xA6
|
||||
#define SSD1306_INVERTDISPLAY 0xA7
|
||||
#define SSD1306_DISPLAYOFF 0xAE
|
||||
#define SSD1306_DISPLAYON 0xAF
|
||||
|
||||
#define SSD1306_SETDISPLAYOFFSET 0xD3
|
||||
#define SSD1306_SETCOMPINS 0xDA
|
||||
|
||||
#define SSD1306_SETVCOMDETECT 0xDB
|
||||
|
||||
#define SSD1306_SETDISPLAYCLOCKDIV 0xD5
|
||||
#define SSD1306_SETPRECHARGE 0xD9
|
||||
|
||||
#define SSD1306_SETMULTIPLEX 0xA8
|
||||
|
||||
#define SSD1306_SETLOWCOLUMN 0x00
|
||||
#define SSD1306_SETHIGHCOLUMN 0x10
|
||||
|
||||
#define SSD1306_SETSTARTLINE 0x40
|
||||
|
||||
#define SSD1306_MEMORYMODE 0x20
|
||||
#define SSD1306_COLUMNADDR 0x21
|
||||
#define SSD1306_PAGEADDR 0x22
|
||||
|
||||
#define SSD1306_COMSCANINC 0xC0
|
||||
#define SSD1306_COMSCANDEC 0xC8
|
||||
|
||||
#define SSD1306_SEGREMAP 0xA0
|
||||
|
||||
#define SSD1306_CHARGEPUMP 0x8D
|
||||
|
||||
#define SSD1306_EXTERNALVCC 0x1
|
||||
#define SSD1306_SWITCHCAPVCC 0x2
|
||||
|
||||
// Scrolling #defines
|
||||
#define SSD1306_ACTIVATE_SCROLL 0x2F
|
||||
#define SSD1306_DEACTIVATE_SCROLL 0x2E
|
||||
#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3
|
||||
#define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26
|
||||
#define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27
|
||||
#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29
|
||||
#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A
|
||||
|
||||
class Adafruit_SSD1306 : public Adafruit_GFX {
|
||||
public:
|
||||
Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS);
|
||||
Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS);
|
||||
Adafruit_SSD1306(int8_t RST = -1);
|
||||
|
||||
bool begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = SSD1306_I2C_ADDRESS, bool reset=true);
|
||||
uint8_t ssd1306_command(uint8_t c);
|
||||
|
||||
void clearDisplay(void);
|
||||
void invertDisplay(uint8_t i);
|
||||
void display();
|
||||
|
||||
void startscrollright(uint8_t start, uint8_t stop);
|
||||
void startscrollleft(uint8_t start, uint8_t stop);
|
||||
|
||||
void startscrolldiagright(uint8_t start, uint8_t stop);
|
||||
void startscrolldiagleft(uint8_t start, uint8_t stop);
|
||||
void stopscroll(void);
|
||||
|
||||
void dim(boolean dim);
|
||||
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
|
||||
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
|
||||
private:
|
||||
int8_t _i2caddr, _vccstate, sid, sclk, dc, rst, cs;
|
||||
void fastSPIwrite(uint8_t c);
|
||||
|
||||
boolean hwSPI;
|
||||
#ifdef HAVE_PORTREG
|
||||
PortReg *mosiport, *clkport, *csport, *dcport;
|
||||
PortMask mosipinmask, clkpinmask, cspinmask, dcpinmask;
|
||||
#endif
|
||||
|
||||
inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline));
|
||||
inline void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) __attribute__((always_inline));
|
||||
|
||||
};
|
||||
|
||||
#endif /* _Adafruit_SSD1306_H_ */
|
||||
|
@ -1,192 +1,192 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include "Flash.h"
|
||||
#include "syslog.h"
|
||||
|
||||
bool flashInit(void){
|
||||
if (NVMCTRL->PARAM.bit.PSZ != 3)
|
||||
{
|
||||
ERROR("FLASH PAGE SIZE is not 64 bytes");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void erase(const volatile void *flash_ptr)
|
||||
{
|
||||
NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2;
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
|
||||
while (!NVMCTRL->INTFLAG.bit.READY) { }
|
||||
}
|
||||
|
||||
bool flashErase(const volatile void *flash_ptr, uint32_t size)
|
||||
{
|
||||
const uint8_t *ptr = (const uint8_t *)flash_ptr;
|
||||
while (size > FLASH_ROW_SIZE) {
|
||||
erase(ptr);
|
||||
ptr += FLASH_ROW_SIZE;
|
||||
size -= FLASH_ROW_SIZE;
|
||||
}
|
||||
if (size>0)
|
||||
{
|
||||
erase(ptr);
|
||||
}
|
||||
return true; //TODO should verify the erase
|
||||
}
|
||||
|
||||
static inline uint32_t read_unaligned_uint32(const void *data)
|
||||
{
|
||||
union {
|
||||
uint32_t u32;
|
||||
uint8_t u8[4];
|
||||
} res;
|
||||
const uint8_t *d = (const uint8_t *)data;
|
||||
res.u8[0] = d[0];
|
||||
res.u8[1] = d[1];
|
||||
res.u8[2] = d[2];
|
||||
res.u8[3] = d[3];
|
||||
return res.u32;
|
||||
}
|
||||
|
||||
|
||||
void flashWrite(const volatile void *flash_ptr,const void *data, uint32_t size)
|
||||
{
|
||||
uint32_t *ptrPage;
|
||||
uint8_t *destPtr;
|
||||
uint8_t *srcPtr;
|
||||
uint32_t bytesInBlock;
|
||||
__attribute__((__aligned__(4))) uint8_t buffer[FLASH_ROW_SIZE];
|
||||
uint32_t offset;
|
||||
|
||||
destPtr=(uint8_t *)flash_ptr;
|
||||
srcPtr=(uint8_t *)data;
|
||||
|
||||
//LOG("flash write called");
|
||||
while(size>0)
|
||||
{
|
||||
uint32_t i,j;
|
||||
|
||||
//calculate the maximum number of bytes we can write in page
|
||||
offset=((uint32_t)destPtr)%(FLASH_ROW_SIZE); //offset into page
|
||||
bytesInBlock=FLASH_ROW_SIZE-offset; //this is how many bytes we need to overwrite in this page
|
||||
|
||||
//LOG("offset %d, bytesInBlock %d size %d", offset, bytesInBlock,size);
|
||||
//get pointer to start of page
|
||||
ptrPage=(uint32_t *) ((((uint32_t)destPtr)/(FLASH_ROW_SIZE)) * FLASH_ROW_SIZE);
|
||||
|
||||
//LOG("pointer to page %d(0x%08x) %d",(uint32_t)ptrPage,(uint32_t)ptrPage,destPtr);
|
||||
|
||||
//fill page buffer with data from flash
|
||||
memcpy(buffer,ptrPage,FLASH_ROW_SIZE);
|
||||
|
||||
//now fill buffer with new data that needs changing
|
||||
i=bytesInBlock;
|
||||
if (size<i)
|
||||
{
|
||||
i=size;
|
||||
}
|
||||
//LOG("changing %d bytes",i);
|
||||
memcpy(&buffer[offset],srcPtr,i);
|
||||
|
||||
//erase page
|
||||
flashErase(ptrPage,FLASH_ROW_SIZE);
|
||||
//write new data to flash
|
||||
flashWritePage(ptrPage,buffer,FLASH_ROW_SIZE);
|
||||
|
||||
uint32_t *ptr=(uint32_t *)buffer;
|
||||
for (j=0; j<FLASH_ROW_SIZE/4; j++)
|
||||
{
|
||||
if (*ptrPage != *ptr)
|
||||
{
|
||||
ERROR("write failed on byte %d %x %x",j,*ptrPage, *ptr);
|
||||
}
|
||||
ptrPage++;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
|
||||
size=size-i; //decrease number of bytes to write
|
||||
srcPtr+=i; //increase pointer to next bytes to read
|
||||
destPtr+=i; //increment destination pointer
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void flashWritePage(const volatile void *flash_ptr, const void *data, uint32_t size)
|
||||
{
|
||||
// Calculate data boundaries
|
||||
size = (size + 3) / 4; //convert bytes to words with rounding
|
||||
|
||||
volatile uint32_t *dst_addr = (volatile uint32_t *)flash_ptr;
|
||||
const uint8_t *src_addr = (uint8_t *)data;
|
||||
|
||||
if (0 != ((uint32_t)flash_ptr)%(FLASH_PAGE_SIZE))
|
||||
{
|
||||
ERROR("Flash page write must be on boundry");
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable automatic page write
|
||||
NVMCTRL->CTRLB.bit.MANW = 1;
|
||||
|
||||
// Do writes in pages
|
||||
while (size)
|
||||
{
|
||||
// Execute "PBC" Page Buffer Clear
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||
|
||||
// Fill page buffer
|
||||
uint32_t i;
|
||||
for (i=0; i<(FLASH_PAGE_SIZE/4) && size; i++) //we write 4 bytes at a time
|
||||
{
|
||||
*dst_addr = read_unaligned_uint32(src_addr);
|
||||
src_addr += 4;
|
||||
dst_addr++;
|
||||
size--; //size is set to number of 32bit words in first line above
|
||||
}
|
||||
|
||||
// Execute "WP" Write Page
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include "Flash.h"
|
||||
#include "syslog.h"
|
||||
|
||||
bool flashInit(void){
|
||||
if (NVMCTRL->PARAM.bit.PSZ != 3)
|
||||
{
|
||||
ERROR("FLASH PAGE SIZE is not 64 bytes");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void erase(const volatile void *flash_ptr)
|
||||
{
|
||||
NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2;
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
|
||||
while (!NVMCTRL->INTFLAG.bit.READY) { }
|
||||
}
|
||||
|
||||
bool flashErase(const volatile void *flash_ptr, uint32_t size)
|
||||
{
|
||||
const uint8_t *ptr = (const uint8_t *)flash_ptr;
|
||||
while (size > FLASH_ROW_SIZE) {
|
||||
erase(ptr);
|
||||
ptr += FLASH_ROW_SIZE;
|
||||
size -= FLASH_ROW_SIZE;
|
||||
}
|
||||
if (size>0)
|
||||
{
|
||||
erase(ptr);
|
||||
}
|
||||
return true; //TODO should verify the erase
|
||||
}
|
||||
|
||||
static inline uint32_t read_unaligned_uint32(const void *data)
|
||||
{
|
||||
union {
|
||||
uint32_t u32;
|
||||
uint8_t u8[4];
|
||||
} res;
|
||||
const uint8_t *d = (const uint8_t *)data;
|
||||
res.u8[0] = d[0];
|
||||
res.u8[1] = d[1];
|
||||
res.u8[2] = d[2];
|
||||
res.u8[3] = d[3];
|
||||
return res.u32;
|
||||
}
|
||||
|
||||
|
||||
void flashWrite(const volatile void *flash_ptr,const void *data, uint32_t size)
|
||||
{
|
||||
uint32_t *ptrPage;
|
||||
uint8_t *destPtr;
|
||||
uint8_t *srcPtr;
|
||||
uint32_t bytesInBlock;
|
||||
__attribute__((__aligned__(4))) uint8_t buffer[FLASH_ROW_SIZE];
|
||||
uint32_t offset;
|
||||
|
||||
destPtr=(uint8_t *)flash_ptr;
|
||||
srcPtr=(uint8_t *)data;
|
||||
|
||||
//LOG("flash write called");
|
||||
while(size>0)
|
||||
{
|
||||
uint32_t i,j;
|
||||
|
||||
//calculate the maximum number of bytes we can write in page
|
||||
offset=((uint32_t)destPtr)%(FLASH_ROW_SIZE); //offset into page
|
||||
bytesInBlock=FLASH_ROW_SIZE-offset; //this is how many bytes we need to overwrite in this page
|
||||
|
||||
//LOG("offset %d, bytesInBlock %d size %d", offset, bytesInBlock,size);
|
||||
//get pointer to start of page
|
||||
ptrPage=(uint32_t *) ((((uint32_t)destPtr)/(FLASH_ROW_SIZE)) * FLASH_ROW_SIZE);
|
||||
|
||||
//LOG("pointer to page %d(0x%08x) %d",(uint32_t)ptrPage,(uint32_t)ptrPage,destPtr);
|
||||
|
||||
//fill page buffer with data from flash
|
||||
memcpy(buffer,ptrPage,FLASH_ROW_SIZE);
|
||||
|
||||
//now fill buffer with new data that needs changing
|
||||
i=bytesInBlock;
|
||||
if (size<i)
|
||||
{
|
||||
i=size;
|
||||
}
|
||||
//LOG("changing %d bytes",i);
|
||||
memcpy(&buffer[offset],srcPtr,i);
|
||||
|
||||
//erase page
|
||||
flashErase(ptrPage,FLASH_ROW_SIZE);
|
||||
//write new data to flash
|
||||
flashWritePage(ptrPage,buffer,FLASH_ROW_SIZE);
|
||||
|
||||
uint32_t *ptr=(uint32_t *)buffer;
|
||||
for (j=0; j<FLASH_ROW_SIZE/4; j++)
|
||||
{
|
||||
if (*ptrPage != *ptr)
|
||||
{
|
||||
ERROR("write failed on byte %d %x %x",j,*ptrPage, *ptr);
|
||||
}
|
||||
ptrPage++;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
|
||||
size=size-i; //decrease number of bytes to write
|
||||
srcPtr+=i; //increase pointer to next bytes to read
|
||||
destPtr+=i; //increment destination pointer
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void flashWritePage(const volatile void *flash_ptr, const void *data, uint32_t size)
|
||||
{
|
||||
// Calculate data boundaries
|
||||
size = (size + 3) / 4; //convert bytes to words with rounding
|
||||
|
||||
volatile uint32_t *dst_addr = (volatile uint32_t *)flash_ptr;
|
||||
const uint8_t *src_addr = (uint8_t *)data;
|
||||
|
||||
if (0 != ((uint32_t)flash_ptr)%(FLASH_PAGE_SIZE))
|
||||
{
|
||||
ERROR("Flash page write must be on boundry");
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable automatic page write
|
||||
NVMCTRL->CTRLB.bit.MANW = 1;
|
||||
|
||||
// Do writes in pages
|
||||
while (size)
|
||||
{
|
||||
// Execute "PBC" Page Buffer Clear
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||
|
||||
// Fill page buffer
|
||||
uint32_t i;
|
||||
for (i=0; i<(FLASH_PAGE_SIZE/4) && size; i++) //we write 4 bytes at a time
|
||||
{
|
||||
*dst_addr = read_unaligned_uint32(src_addr);
|
||||
src_addr += 4;
|
||||
dst_addr++;
|
||||
size--; //size is set to number of 32bit words in first line above
|
||||
}
|
||||
|
||||
// Execute "WP" Write Page
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,68 +1,68 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __FLASH__H__
|
||||
#define __FLASH__H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "syslog.h"
|
||||
|
||||
|
||||
#define FLASH_PAGE_SIZE_NZS (64) //bytes
|
||||
#define FLASH_ROW_SIZE (FLASH_PAGE_SIZE_NZS*4) //defined in the datasheet as 4x page size
|
||||
#define FLASH_ERASE_VALUE (0xFF) //value of flash after an erase
|
||||
|
||||
#define FLASH_ALLOCATE(name, size) \
|
||||
__attribute__((__aligned__(FLASH_ROW_SIZE))) \
|
||||
const uint8_t name[(size+(FLASH_ROW_SIZE-1))/FLASH_ROW_SIZE*FLASH_ROW_SIZE] = { };
|
||||
|
||||
bool flashInit(void); //this checks that our assumptions are true
|
||||
|
||||
bool flashErase(const volatile void *flash_ptr, uint32_t size);
|
||||
void flashWrite(const volatile void *flash_ptr,const void *data,uint32_t size);
|
||||
void flashWritePage(const volatile void *flash_ptr, const void *data, uint32_t size);
|
||||
|
||||
//you can read by dereferencing pointer but we will add a read
|
||||
static inline int32_t flashRead(const volatile void *flash_ptr, void *data, uint32_t size)
|
||||
{
|
||||
memcpy(data, (const void *)flash_ptr, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //__FLASH__H__
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __FLASH__H__
|
||||
#define __FLASH__H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "syslog.h"
|
||||
|
||||
|
||||
#define FLASH_PAGE_SIZE_NZS (64) //bytes
|
||||
#define FLASH_ROW_SIZE (FLASH_PAGE_SIZE_NZS*4) //defined in the datasheet as 4x page size
|
||||
#define FLASH_ERASE_VALUE (0xFF) //value of flash after an erase
|
||||
|
||||
#define FLASH_ALLOCATE(name, size) \
|
||||
__attribute__((__aligned__(FLASH_ROW_SIZE))) \
|
||||
const uint8_t name[(size+(FLASH_ROW_SIZE-1))/FLASH_ROW_SIZE*FLASH_ROW_SIZE] = { };
|
||||
|
||||
bool flashInit(void); //this checks that our assumptions are true
|
||||
|
||||
bool flashErase(const volatile void *flash_ptr, uint32_t size);
|
||||
void flashWrite(const volatile void *flash_ptr,const void *data,uint32_t size);
|
||||
void flashWritePage(const volatile void *flash_ptr, const void *data, uint32_t size);
|
||||
|
||||
//you can read by dereferencing pointer but we will add a read
|
||||
static inline int32_t flashRead(const volatile void *flash_ptr, void *data, uint32_t size)
|
||||
{
|
||||
memcpy(data, (const void *)flash_ptr, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //__FLASH__H__
|
||||
|
@ -1,147 +1,147 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef ANGLE_H_
|
||||
#define ANGLE_H_
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#define ANGLE_STEPS (0x010000UL)
|
||||
#define ANGLE_MAX ((uint16_t)0x0FFFF)
|
||||
|
||||
#define ANGLE_FROM_DEGREES(x) ((int32_t) ( ((float)ANGLE_STEPS*(float)(x)+180.0)/360.0 ) )
|
||||
#define ANGLE_T0_DEGREES(x) ( (float) ((float(x)*360.0)/((float)ANGLE_STEPS) ))
|
||||
class Angle
|
||||
{
|
||||
private:
|
||||
uint16_t angle;
|
||||
public:
|
||||
Angle(void) {angle=0;}
|
||||
Angle(int32_t x) {angle=(uint16_t)x;}
|
||||
Angle(const Angle &x) {angle=x.angle;}
|
||||
|
||||
int16_t operator-( const Angle &a2)
|
||||
{
|
||||
int32_t x,y,dx;
|
||||
x=(int32_t)angle;
|
||||
y=(int32_t)a2.angle;
|
||||
dx=x-y;
|
||||
if (abs(x-y)>ANGLE_STEPS/2)
|
||||
{
|
||||
//we have a wrap condition
|
||||
if (x>y)
|
||||
{
|
||||
dx=x-(y+ANGLE_STEPS);
|
||||
}else if (x<y)
|
||||
{
|
||||
dx=(ANGLE_STEPS+x)-y;
|
||||
}
|
||||
}
|
||||
return (int16_t)dx;
|
||||
}
|
||||
//
|
||||
// int16_t operator-( const int32_t y)
|
||||
// {
|
||||
// int32_t x,y,dx;
|
||||
// x=(int32_t)angle;
|
||||
// while(y>ANGLE_MAX)
|
||||
// {
|
||||
// y=y-ANGLE_STEPS;
|
||||
// }
|
||||
// while(y<-ANGLE_MAX)
|
||||
// {
|
||||
// y=y+ANGLE_STEPS;
|
||||
// }
|
||||
//
|
||||
// dx=x-y;
|
||||
// if (abs(x-y)>ANGLE_STEPS/2)
|
||||
// {
|
||||
// //we have a wrap condition
|
||||
// if (x>y)
|
||||
// {
|
||||
// dx=x-(y+ANGLE_STEPS);
|
||||
// }else if (x<y)
|
||||
// {
|
||||
// dx=(ANGLE_STEPS+x)-y;
|
||||
// }
|
||||
// }
|
||||
// return (int16_t)dx;
|
||||
// }
|
||||
|
||||
Angle operator+(const Angle &y)
|
||||
{
|
||||
uint16_t a;
|
||||
a=angle+ (uint16_t)y.angle;
|
||||
return Angle(a);
|
||||
}
|
||||
Angle operator+(const long int x)
|
||||
{
|
||||
int32_t a;
|
||||
a=(int32_t)angle+ x;
|
||||
while (a>=ANGLE_STEPS)
|
||||
{
|
||||
a=a-ANGLE_STEPS;
|
||||
}
|
||||
while (a<0)
|
||||
{
|
||||
a=a+ANGLE_STEPS;
|
||||
}
|
||||
return Angle((uint16_t)a);
|
||||
}
|
||||
Angle operator+(const unsigned long int x)
|
||||
{
|
||||
uint32_t a;
|
||||
a=(uint32_t)angle+ x;
|
||||
while (a>=ANGLE_STEPS)
|
||||
{
|
||||
a=a-ANGLE_STEPS;
|
||||
}
|
||||
return Angle((uint16_t)a);
|
||||
}
|
||||
|
||||
operator uint16_t() const {return angle;}
|
||||
operator uint32_t() const {return (uint32_t)angle;}
|
||||
operator int32_t() const {return (int32_t)angle;}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* ANGLE_H_ */
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef ANGLE_H_
|
||||
#define ANGLE_H_
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#define ANGLE_STEPS (0x010000UL)
|
||||
#define ANGLE_MAX ((uint16_t)0x0FFFF)
|
||||
|
||||
#define ANGLE_FROM_DEGREES(x) ((int32_t) ( ((float)ANGLE_STEPS*(float)(x)+180.0)/360.0 ) )
|
||||
#define ANGLE_T0_DEGREES(x) ( (float) ((float(x)*360.0)/((float)ANGLE_STEPS) ))
|
||||
class Angle
|
||||
{
|
||||
private:
|
||||
uint16_t angle;
|
||||
public:
|
||||
Angle(void) {angle=0;}
|
||||
Angle(int32_t x) {angle=(uint16_t)x;}
|
||||
Angle(const Angle &x) {angle=x.angle;}
|
||||
|
||||
int16_t operator-( const Angle &a2)
|
||||
{
|
||||
int32_t x,y,dx;
|
||||
x=(int32_t)angle;
|
||||
y=(int32_t)a2.angle;
|
||||
dx=x-y;
|
||||
if (abs(x-y)>ANGLE_STEPS/2)
|
||||
{
|
||||
//we have a wrap condition
|
||||
if (x>y)
|
||||
{
|
||||
dx=x-(y+ANGLE_STEPS);
|
||||
}else if (x<y)
|
||||
{
|
||||
dx=(ANGLE_STEPS+x)-y;
|
||||
}
|
||||
}
|
||||
return (int16_t)dx;
|
||||
}
|
||||
//
|
||||
// int16_t operator-( const int32_t y)
|
||||
// {
|
||||
// int32_t x,y,dx;
|
||||
// x=(int32_t)angle;
|
||||
// while(y>ANGLE_MAX)
|
||||
// {
|
||||
// y=y-ANGLE_STEPS;
|
||||
// }
|
||||
// while(y<-ANGLE_MAX)
|
||||
// {
|
||||
// y=y+ANGLE_STEPS;
|
||||
// }
|
||||
//
|
||||
// dx=x-y;
|
||||
// if (abs(x-y)>ANGLE_STEPS/2)
|
||||
// {
|
||||
// //we have a wrap condition
|
||||
// if (x>y)
|
||||
// {
|
||||
// dx=x-(y+ANGLE_STEPS);
|
||||
// }else if (x<y)
|
||||
// {
|
||||
// dx=(ANGLE_STEPS+x)-y;
|
||||
// }
|
||||
// }
|
||||
// return (int16_t)dx;
|
||||
// }
|
||||
|
||||
Angle operator+(const Angle &y)
|
||||
{
|
||||
uint16_t a;
|
||||
a=angle+ (uint16_t)y.angle;
|
||||
return Angle(a);
|
||||
}
|
||||
Angle operator+(const long int x)
|
||||
{
|
||||
int32_t a;
|
||||
a=(int32_t)angle+ x;
|
||||
while (a>=ANGLE_STEPS)
|
||||
{
|
||||
a=a-ANGLE_STEPS;
|
||||
}
|
||||
while (a<0)
|
||||
{
|
||||
a=a+ANGLE_STEPS;
|
||||
}
|
||||
return Angle((uint16_t)a);
|
||||
}
|
||||
Angle operator+(const unsigned long int x)
|
||||
{
|
||||
uint32_t a;
|
||||
a=(uint32_t)angle+ x;
|
||||
while (a>=ANGLE_STEPS)
|
||||
{
|
||||
a=a-ANGLE_STEPS;
|
||||
}
|
||||
return Angle((uint16_t)a);
|
||||
}
|
||||
|
||||
operator uint16_t() const {return angle;}
|
||||
operator uint32_t() const {return (uint32_t)angle;}
|
||||
operator int32_t() const {return (int32_t)angle;}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* ANGLE_H_ */
|
||||
|
@ -1,322 +1,322 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include <Arduino.h>
|
||||
#include "syslog.h"
|
||||
#include "as5047d.h"
|
||||
#include "SPI.h"
|
||||
#include <stdio.h>
|
||||
#include "board.h"
|
||||
|
||||
#define AS5047D_CMD_NOP (0x0000)
|
||||
#define AS5047D_CMD_ERRFL (0x0001)
|
||||
#define AS5047D_CMD_PROG (0x0003)
|
||||
#define AS5047D_CMD_DIAAGC (0x3FFC)
|
||||
#define AS5047D_CMD_MAG (0x3FFD)
|
||||
#define AS5047D_CMD_ANGLEUNC (0x3FFE)
|
||||
#define AS5047D_CMD_ANGLECOM (0x3FFF)
|
||||
|
||||
|
||||
#define AS5048A_CMD_NOP (0x0000)
|
||||
#define AS5048A_CMD_ERRFL (0x0001)
|
||||
#define AS5048A_CMD_PROG (0x0003)
|
||||
#define AS5048A_CMD_DIAAGC (0x3FFD)
|
||||
#define AS5048A_CMD_MAG (0x3FFE)
|
||||
#define AS5048A_CMD_ANGLE (0x3FFF)
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-Ofast")
|
||||
|
||||
static int getBit(int16_t data, int bit)
|
||||
{
|
||||
return (data>>bit) & 0x01;
|
||||
}
|
||||
|
||||
static int getParity(uint16_t data)
|
||||
{
|
||||
int i,bits;
|
||||
data=data & 0x7FFF; //mask out upper bit
|
||||
|
||||
//count number of bits, brute force
|
||||
bits=0;
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
if (0 != (data & ((0x0001)<<i)))
|
||||
{
|
||||
bits++;
|
||||
}
|
||||
}
|
||||
return (bits & 0x01); //return 1 if odd
|
||||
}
|
||||
|
||||
boolean AS5047D::begin(int csPin)
|
||||
{
|
||||
#ifdef PIN_AS5047D_PWR
|
||||
digitalWrite(PIN_AS5047D_PWR,HIGH);
|
||||
#endif
|
||||
digitalWrite(PIN_AS5047D_CS,LOW); //pull CS LOW by default (chip powered off)
|
||||
digitalWrite(PIN_MOSI,LOW);
|
||||
digitalWrite(PIN_SCK,LOW);
|
||||
digitalWrite(PIN_MISO,LOW);
|
||||
pinMode(PIN_MISO,OUTPUT);
|
||||
delay(1000);
|
||||
|
||||
|
||||
digitalWrite(PIN_AS5047D_CS,HIGH); //pull CS high
|
||||
#ifdef PIN_AS5047D_PWR
|
||||
digitalWrite(PIN_AS5047D_PWR,LOW);
|
||||
#endif
|
||||
|
||||
pinMode(PIN_MISO,INPUT);
|
||||
|
||||
error=false;
|
||||
SPISettings settingsA(5000000, MSBFIRST, SPI_MODE1); ///400000, MSBFIRST, SPI_MODE1);
|
||||
chipSelectPin=csPin;
|
||||
|
||||
LOG("csPin is %d",csPin);
|
||||
pinMode(chipSelectPin,OUTPUT);
|
||||
digitalWrite(chipSelectPin,HIGH); //pull CS high by default
|
||||
delay(1);
|
||||
SPI.begin(); //AS5047D SPI uses mode=1 (CPOL=0, CPHA=1)
|
||||
LOG("Begin AS5047D...");
|
||||
|
||||
SPI.beginTransaction(settingsA);
|
||||
SPI.transfer16(AS5047D_CMD_NOP);
|
||||
delay(10);
|
||||
|
||||
//wait for the LF bit to be set
|
||||
uint16_t data=0,t0=100;
|
||||
while (getBit(data,8)==0 && t0>0)
|
||||
{
|
||||
delay(1);
|
||||
t0--;
|
||||
if (t0==0)
|
||||
{
|
||||
ERROR("LF bit not set");
|
||||
error=true;
|
||||
break;
|
||||
//return false;
|
||||
}
|
||||
LOG("AS5047D diag data is 0x%04X",data);
|
||||
data=readAddress(AS5047D_CMD_DIAAGC);
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
error=false;
|
||||
uint16_t data=0,t0=100;
|
||||
while (getBit(data,8)==0 && t0>0)
|
||||
{
|
||||
delay(1);
|
||||
t0--;
|
||||
if (t0==0)
|
||||
{
|
||||
ERROR("AS5048A OCF bit not set");
|
||||
error=true;
|
||||
return false;
|
||||
}
|
||||
data=readAddress(AS5048A_CMD_DIAAGC);
|
||||
LOG("AS5048A diag data is 0x%04X",data);
|
||||
}
|
||||
as5047d=false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef NZS_AS5047_PIPELINE
|
||||
//read encoder a few times to flush the pipeline
|
||||
readEncoderAnglePipeLineRead();
|
||||
readEncoderAnglePipeLineRead();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//read the encoders
|
||||
int16_t AS5047D::readAddress(uint16_t addr)
|
||||
{
|
||||
uint16_t data;
|
||||
error=false;
|
||||
//make sure it is a read by setting bit 14
|
||||
addr=addr | 0x4000;
|
||||
|
||||
//add the parity to the command
|
||||
if (1 == getParity(addr))
|
||||
{
|
||||
addr=(addr & 0x7FFF) | 0x8000; //add parity bit to make command even number of bits
|
||||
}
|
||||
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
delayMicroseconds(1);
|
||||
//clock out the address to read
|
||||
SPI.transfer16(addr);
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
//clock out zeros to read in the data from address
|
||||
data=SPI.transfer16(0x00);
|
||||
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
|
||||
if (data & (1<<14))
|
||||
{
|
||||
//if bit 14 is set then we have an error
|
||||
ERROR("read command 0x%04X failed",addr);
|
||||
error=true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data>>15 != getParity(data))
|
||||
{
|
||||
//parity did not match
|
||||
ERROR("read command parity error 0x%04X ",addr);
|
||||
error=true;
|
||||
return -2;
|
||||
}
|
||||
|
||||
data=data & 0x3FFF; //mask off the error and parity bits
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//read the encoders
|
||||
int16_t AS5047D::readEncoderAngle(void)
|
||||
{
|
||||
if (as5047d)
|
||||
{
|
||||
return readAddress(AS5047D_CMD_ANGLECOM);
|
||||
}
|
||||
return readAddress(AS5048A_CMD_ANGLE);
|
||||
}
|
||||
|
||||
//pipelined read of the encoder angle used for high speed reads, but value is always one read behind
|
||||
int16_t AS5047D::readEncoderAnglePipeLineRead(void)
|
||||
{
|
||||
|
||||
int16_t data;
|
||||
int error, t0=10;
|
||||
GPIO_LOW(chipSelectPin);//(chipSelectPin, LOW);
|
||||
//delayMicroseconds(1);
|
||||
do {
|
||||
|
||||
// doing two 8 bit transfers is faster than one 16 bit
|
||||
data =(uint16_t)SPI.transfer(0xFF)<<8 | ((uint16_t)SPI.transfer(0xFF) & 0x0FF);
|
||||
t0--;
|
||||
if (t0<=0)
|
||||
{
|
||||
ERROR("AS5047D problem");
|
||||
break;
|
||||
}
|
||||
//data=SPI.transfer16(0xFFFF); //to speed things up we know the parity and address for the read
|
||||
}while(data & (1<<14)); //while error bit is set
|
||||
|
||||
data=data & 0x3FFF; //mask off the error and parity bits
|
||||
GPIO_HIGH(chipSelectPin);
|
||||
//digitalWrite(chipSelectPin, HIGH);
|
||||
//TODO we really should check for errors and return a negative result or something
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void AS5047D::diagnostics(char *ptrStr)
|
||||
{
|
||||
int16_t data;
|
||||
int m,d;
|
||||
|
||||
if (as5047d)
|
||||
{
|
||||
|
||||
data=readAddress(AS5047D_CMD_DIAAGC);
|
||||
|
||||
if (NULL == ptrStr)
|
||||
{
|
||||
LOG("DIAAGC: 0x%04X", data);
|
||||
LOG("MAGL: %d", getBit(data,11));
|
||||
LOG("MAGH: %d", getBit(data,10));
|
||||
LOG("COF: %d", getBit(data,9));
|
||||
LOG("LFGL: %d", getBit(data,8));
|
||||
LOG("AGC: %d", data & 0x0FF);
|
||||
|
||||
data=readAddress(AS5047D_CMD_MAG);
|
||||
LOG("CMAG: 0x%04X(%d)",data,data);
|
||||
|
||||
data=readAddress(AS5047D_CMD_ANGLEUNC);
|
||||
m=(int)((float)data*AS5047D_DEGREES_PER_BIT);
|
||||
d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100);
|
||||
LOG("CORDICANG: 0x%04X(%d) %d.%02d deg(est)",data,data,m,d);
|
||||
|
||||
data=readAddress(AS5047D_CMD_ANGLECOM);
|
||||
m=(int)((float)data*AS5047D_DEGREES_PER_BIT);
|
||||
d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100);
|
||||
LOG("DAECANG: 0x%04X(%d) %d.%02d deg(est)",data,data,m,d);
|
||||
}else
|
||||
{
|
||||
sprintf(ptrStr,"DIAAGC: 0x%04X\n\r", data);
|
||||
sprintf(ptrStr,"%sMAGL: %d\n\r", ptrStr,getBit(data,11));
|
||||
sprintf(ptrStr,"%sMAGH: %d\n\r", ptrStr,getBit(data,10));
|
||||
sprintf(ptrStr,"%sCOF: %d\n\r", ptrStr, getBit(data,9));
|
||||
sprintf(ptrStr,"%sLFGL: %d\n\r", ptrStr, getBit(data,8));
|
||||
sprintf(ptrStr,"%sAGC: %d\n\r", ptrStr,data & 0x0FF);
|
||||
|
||||
data=readAddress(AS5047D_CMD_MAG);
|
||||
sprintf(ptrStr,"%sCMAG: 0x%04X(%d)\n\r", ptrStr,data,data);
|
||||
|
||||
data=readAddress(AS5047D_CMD_ANGLEUNC);
|
||||
m=(int)((float)data*AS5047D_DEGREES_PER_BIT);
|
||||
d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100);
|
||||
sprintf(ptrStr,"%sCORDICANG: 0x%04X(%d) %d.%02d deg(est)\n\r", ptrStr,data,data,m,d);
|
||||
|
||||
data=readAddress(AS5047D_CMD_ANGLECOM);
|
||||
m=(int)((float)data*AS5047D_DEGREES_PER_BIT);
|
||||
d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100);
|
||||
sprintf(ptrStr,"%sDAECANG: 0x%04X(%d) %d.%02d deg(est)\n\r", ptrStr,data,data,m,d);
|
||||
|
||||
}
|
||||
} else
|
||||
{
|
||||
data=readAddress(AS5048A_CMD_DIAAGC);
|
||||
sprintf(ptrStr,"AS5048A DIAAGC: 0x%04X\n\r", data);
|
||||
data=readAddress(AS5048A_CMD_MAG);
|
||||
sprintf(ptrStr,"%sMagnitude: %d\n\r", ptrStr,data);
|
||||
data=readAddress(AS5048A_CMD_ANGLE);
|
||||
sprintf(ptrStr,"%sAngle: %d\n\r", ptrStr,data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include <Arduino.h>
|
||||
#include "syslog.h"
|
||||
#include "as5047d.h"
|
||||
#include "SPI.h"
|
||||
#include <stdio.h>
|
||||
#include "board.h"
|
||||
|
||||
#define AS5047D_CMD_NOP (0x0000)
|
||||
#define AS5047D_CMD_ERRFL (0x0001)
|
||||
#define AS5047D_CMD_PROG (0x0003)
|
||||
#define AS5047D_CMD_DIAAGC (0x3FFC)
|
||||
#define AS5047D_CMD_MAG (0x3FFD)
|
||||
#define AS5047D_CMD_ANGLEUNC (0x3FFE)
|
||||
#define AS5047D_CMD_ANGLECOM (0x3FFF)
|
||||
|
||||
|
||||
#define AS5048A_CMD_NOP (0x0000)
|
||||
#define AS5048A_CMD_ERRFL (0x0001)
|
||||
#define AS5048A_CMD_PROG (0x0003)
|
||||
#define AS5048A_CMD_DIAAGC (0x3FFD)
|
||||
#define AS5048A_CMD_MAG (0x3FFE)
|
||||
#define AS5048A_CMD_ANGLE (0x3FFF)
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-Ofast")
|
||||
|
||||
static int getBit(int16_t data, int bit)
|
||||
{
|
||||
return (data>>bit) & 0x01;
|
||||
}
|
||||
|
||||
static int getParity(uint16_t data)
|
||||
{
|
||||
int i,bits;
|
||||
data=data & 0x7FFF; //mask out upper bit
|
||||
|
||||
//count number of bits, brute force
|
||||
bits=0;
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
if (0 != (data & ((0x0001)<<i)))
|
||||
{
|
||||
bits++;
|
||||
}
|
||||
}
|
||||
return (bits & 0x01); //return 1 if odd
|
||||
}
|
||||
|
||||
boolean AS5047D::begin(int csPin)
|
||||
{
|
||||
#ifdef PIN_AS5047D_PWR
|
||||
digitalWrite(PIN_AS5047D_PWR,HIGH);
|
||||
#endif
|
||||
digitalWrite(PIN_AS5047D_CS,LOW); //pull CS LOW by default (chip powered off)
|
||||
digitalWrite(PIN_MOSI,LOW);
|
||||
digitalWrite(PIN_SCK,LOW);
|
||||
digitalWrite(PIN_MISO,LOW);
|
||||
pinMode(PIN_MISO,OUTPUT);
|
||||
delay(1000);
|
||||
|
||||
|
||||
digitalWrite(PIN_AS5047D_CS,HIGH); //pull CS high
|
||||
#ifdef PIN_AS5047D_PWR
|
||||
digitalWrite(PIN_AS5047D_PWR,LOW);
|
||||
#endif
|
||||
|
||||
pinMode(PIN_MISO,INPUT);
|
||||
|
||||
error=false;
|
||||
SPISettings settingsA(5000000, MSBFIRST, SPI_MODE1); ///400000, MSBFIRST, SPI_MODE1);
|
||||
chipSelectPin=csPin;
|
||||
|
||||
LOG("csPin is %d",csPin);
|
||||
pinMode(chipSelectPin,OUTPUT);
|
||||
digitalWrite(chipSelectPin,HIGH); //pull CS high by default
|
||||
delay(1);
|
||||
SPI.begin(); //AS5047D SPI uses mode=1 (CPOL=0, CPHA=1)
|
||||
LOG("Begin AS5047D...");
|
||||
|
||||
SPI.beginTransaction(settingsA);
|
||||
SPI.transfer16(AS5047D_CMD_NOP);
|
||||
delay(10);
|
||||
|
||||
//wait for the LF bit to be set
|
||||
uint16_t data=0,t0=100;
|
||||
while (getBit(data,8)==0 && t0>0)
|
||||
{
|
||||
delay(1);
|
||||
t0--;
|
||||
if (t0==0)
|
||||
{
|
||||
ERROR("LF bit not set");
|
||||
error=true;
|
||||
break;
|
||||
//return false;
|
||||
}
|
||||
LOG("AS5047D diag data is 0x%04X",data);
|
||||
data=readAddress(AS5047D_CMD_DIAAGC);
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
error=false;
|
||||
uint16_t data=0,t0=100;
|
||||
while (getBit(data,8)==0 && t0>0)
|
||||
{
|
||||
delay(1);
|
||||
t0--;
|
||||
if (t0==0)
|
||||
{
|
||||
ERROR("AS5048A OCF bit not set");
|
||||
error=true;
|
||||
return false;
|
||||
}
|
||||
data=readAddress(AS5048A_CMD_DIAAGC);
|
||||
LOG("AS5048A diag data is 0x%04X",data);
|
||||
}
|
||||
as5047d=false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef NZS_AS5047_PIPELINE
|
||||
//read encoder a few times to flush the pipeline
|
||||
readEncoderAnglePipeLineRead();
|
||||
readEncoderAnglePipeLineRead();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//read the encoders
|
||||
int16_t AS5047D::readAddress(uint16_t addr)
|
||||
{
|
||||
uint16_t data;
|
||||
error=false;
|
||||
//make sure it is a read by setting bit 14
|
||||
addr=addr | 0x4000;
|
||||
|
||||
//add the parity to the command
|
||||
if (1 == getParity(addr))
|
||||
{
|
||||
addr=(addr & 0x7FFF) | 0x8000; //add parity bit to make command even number of bits
|
||||
}
|
||||
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
delayMicroseconds(1);
|
||||
//clock out the address to read
|
||||
SPI.transfer16(addr);
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(chipSelectPin, LOW);
|
||||
//clock out zeros to read in the data from address
|
||||
data=SPI.transfer16(0x00);
|
||||
|
||||
digitalWrite(chipSelectPin, HIGH);
|
||||
|
||||
if (data & (1<<14))
|
||||
{
|
||||
//if bit 14 is set then we have an error
|
||||
ERROR("read command 0x%04X failed",addr);
|
||||
error=true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data>>15 != getParity(data))
|
||||
{
|
||||
//parity did not match
|
||||
ERROR("read command parity error 0x%04X ",addr);
|
||||
error=true;
|
||||
return -2;
|
||||
}
|
||||
|
||||
data=data & 0x3FFF; //mask off the error and parity bits
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//read the encoders
|
||||
int16_t AS5047D::readEncoderAngle(void)
|
||||
{
|
||||
if (as5047d)
|
||||
{
|
||||
return readAddress(AS5047D_CMD_ANGLECOM);
|
||||
}
|
||||
return readAddress(AS5048A_CMD_ANGLE);
|
||||
}
|
||||
|
||||
//pipelined read of the encoder angle used for high speed reads, but value is always one read behind
|
||||
int16_t AS5047D::readEncoderAnglePipeLineRead(void)
|
||||
{
|
||||
|
||||
int16_t data;
|
||||
int error, t0=10;
|
||||
GPIO_LOW(chipSelectPin);//(chipSelectPin, LOW);
|
||||
//delayMicroseconds(1);
|
||||
do {
|
||||
|
||||
// doing two 8 bit transfers is faster than one 16 bit
|
||||
data =(uint16_t)SPI.transfer(0xFF)<<8 | ((uint16_t)SPI.transfer(0xFF) & 0x0FF);
|
||||
t0--;
|
||||
if (t0<=0)
|
||||
{
|
||||
ERROR("AS5047D problem");
|
||||
break;
|
||||
}
|
||||
//data=SPI.transfer16(0xFFFF); //to speed things up we know the parity and address for the read
|
||||
}while(data & (1<<14)); //while error bit is set
|
||||
|
||||
data=data & 0x3FFF; //mask off the error and parity bits
|
||||
GPIO_HIGH(chipSelectPin);
|
||||
//digitalWrite(chipSelectPin, HIGH);
|
||||
//TODO we really should check for errors and return a negative result or something
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void AS5047D::diagnostics(char *ptrStr)
|
||||
{
|
||||
int16_t data;
|
||||
int m,d;
|
||||
|
||||
if (as5047d)
|
||||
{
|
||||
|
||||
data=readAddress(AS5047D_CMD_DIAAGC);
|
||||
|
||||
if (NULL == ptrStr)
|
||||
{
|
||||
LOG("DIAAGC: 0x%04X", data);
|
||||
LOG("MAGL: %d", getBit(data,11));
|
||||
LOG("MAGH: %d", getBit(data,10));
|
||||
LOG("COF: %d", getBit(data,9));
|
||||
LOG("LFGL: %d", getBit(data,8));
|
||||
LOG("AGC: %d", data & 0x0FF);
|
||||
|
||||
data=readAddress(AS5047D_CMD_MAG);
|
||||
LOG("CMAG: 0x%04X(%d)",data,data);
|
||||
|
||||
data=readAddress(AS5047D_CMD_ANGLEUNC);
|
||||
m=(int)((float)data*AS5047D_DEGREES_PER_BIT);
|
||||
d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100);
|
||||
LOG("CORDICANG: 0x%04X(%d) %d.%02d deg(est)",data,data,m,d);
|
||||
|
||||
data=readAddress(AS5047D_CMD_ANGLECOM);
|
||||
m=(int)((float)data*AS5047D_DEGREES_PER_BIT);
|
||||
d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100);
|
||||
LOG("DAECANG: 0x%04X(%d) %d.%02d deg(est)",data,data,m,d);
|
||||
}else
|
||||
{
|
||||
sprintf(ptrStr,"DIAAGC: 0x%04X\n\r", data);
|
||||
sprintf(ptrStr,"%sMAGL: %d\n\r", ptrStr,getBit(data,11));
|
||||
sprintf(ptrStr,"%sMAGH: %d\n\r", ptrStr,getBit(data,10));
|
||||
sprintf(ptrStr,"%sCOF: %d\n\r", ptrStr, getBit(data,9));
|
||||
sprintf(ptrStr,"%sLFGL: %d\n\r", ptrStr, getBit(data,8));
|
||||
sprintf(ptrStr,"%sAGC: %d\n\r", ptrStr,data & 0x0FF);
|
||||
|
||||
data=readAddress(AS5047D_CMD_MAG);
|
||||
sprintf(ptrStr,"%sCMAG: 0x%04X(%d)\n\r", ptrStr,data,data);
|
||||
|
||||
data=readAddress(AS5047D_CMD_ANGLEUNC);
|
||||
m=(int)((float)data*AS5047D_DEGREES_PER_BIT);
|
||||
d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100);
|
||||
sprintf(ptrStr,"%sCORDICANG: 0x%04X(%d) %d.%02d deg(est)\n\r", ptrStr,data,data,m,d);
|
||||
|
||||
data=readAddress(AS5047D_CMD_ANGLECOM);
|
||||
m=(int)((float)data*AS5047D_DEGREES_PER_BIT);
|
||||
d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100);
|
||||
sprintf(ptrStr,"%sDAECANG: 0x%04X(%d) %d.%02d deg(est)\n\r", ptrStr,data,data,m,d);
|
||||
|
||||
}
|
||||
} else
|
||||
{
|
||||
data=readAddress(AS5048A_CMD_DIAAGC);
|
||||
sprintf(ptrStr,"AS5048A DIAAGC: 0x%04X\n\r", data);
|
||||
data=readAddress(AS5048A_CMD_MAG);
|
||||
sprintf(ptrStr,"%sMagnitude: %d\n\r", ptrStr,data);
|
||||
data=readAddress(AS5048A_CMD_ANGLE);
|
||||
sprintf(ptrStr,"%sAngle: %d\n\r", ptrStr,data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
|
@ -1,58 +1,58 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2019 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __AS5047D_H__
|
||||
#define __AS5047D_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#define AS5047D_DEGREES_PER_BIT (360.0/(float)(0x3FFF))
|
||||
|
||||
class AS5047D {
|
||||
private:
|
||||
int chipSelectPin;
|
||||
int16_t readAddress(uint16_t addr);
|
||||
bool error=false;
|
||||
bool as5047d=true;
|
||||
public:
|
||||
boolean begin(int csPin);
|
||||
int16_t readEncoderAngle(void);
|
||||
void diagnostics(char *ptrStr);
|
||||
int16_t readEncoderAnglePipeLineRead(void);
|
||||
bool getError(void) {return error;};
|
||||
};
|
||||
|
||||
#endif //__AS5047D_H__
|
||||
/**********************************************************************
|
||||
Copyright (C) 2019 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __AS5047D_H__
|
||||
#define __AS5047D_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#define AS5047D_DEGREES_PER_BIT (360.0/(float)(0x3FFF))
|
||||
|
||||
class AS5047D {
|
||||
private:
|
||||
int chipSelectPin;
|
||||
int16_t readAddress(uint16_t addr);
|
||||
bool error=false;
|
||||
bool as5047d=true;
|
||||
public:
|
||||
boolean begin(int csPin);
|
||||
int16_t readEncoderAngle(void);
|
||||
void diagnostics(char *ptrStr);
|
||||
int16_t readEncoderAnglePipeLineRead(void);
|
||||
bool getError(void) {return error;};
|
||||
};
|
||||
|
||||
#endif //__AS5047D_H__
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,104 +1,104 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __CALIBRAITON_H__
|
||||
#define __CALIBRAITON_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "syslog.h"
|
||||
#include "angle.h"
|
||||
|
||||
|
||||
//this file implements a table that is linearly interpolated circular calibration table
|
||||
// it is assumed the data wraps around, ie you interpolated 65536==0
|
||||
//we want this to be "whole" steps, for 1.8 degree motors this should be 200.
|
||||
// 200 will work for 0.9 degree too, but could be 400. However 400 is not good for 1.8 degree motors
|
||||
#define CALIBRATION_TABLE_SIZE (200)
|
||||
|
||||
#define CALIBRATION_STEPS ((uint32_t)ANGLE_STEPS) // this is one rotation ie 0-65535 aka 65536 steps is 0-360 degrees
|
||||
|
||||
#define CALIBRATION_ERROR_NOT_SET (-1) //indicated that the calibration value is not set.
|
||||
|
||||
#define CALIBRATION_UPDATE_RATE (32) //number of samples to keep 1 pole running average
|
||||
#define CALIBRATION_MIN_ERROR (4) //the minimal expected error on our calibration 4 ~=+/0.2 degrees
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t table[CALIBRATION_TABLE_SIZE];
|
||||
bool status;
|
||||
} FlashCalData_t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
Angle value; //cal value
|
||||
int16_t error; //error assuming it is constantly updated
|
||||
} CalData_t;
|
||||
|
||||
class CalibrationTable
|
||||
{
|
||||
private:
|
||||
CalData_t table[CALIBRATION_TABLE_SIZE];
|
||||
|
||||
bool fastCalVaild=false;
|
||||
void loadFromFlash(void);
|
||||
bool flashGood(void); //returns true if the flash copy of calibration is valid
|
||||
|
||||
void updateFastCal(void);
|
||||
void createFastCal(void);
|
||||
|
||||
public:
|
||||
void init(void);
|
||||
void saveToFlash(void); //saves the calibration to flash
|
||||
bool updateTableValue(int32_t index, int32_t value);
|
||||
void updateTable(Angle actualAngle, Angle encoderValue);
|
||||
int getValue(Angle actualAngle, CalData_t *ptrData);
|
||||
Angle getCal(Angle actualAngle);
|
||||
bool calValid(void);
|
||||
Angle reverseLookup(Angle encoderAngle); //this turns encoder angle into real angle
|
||||
void printCalTable(void);
|
||||
void smoothTable(void);
|
||||
|
||||
Angle fastReverseLookup(Angle encoderAngle);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //__CALIBRAITON_H__
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __CALIBRAITON_H__
|
||||
#define __CALIBRAITON_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "syslog.h"
|
||||
#include "angle.h"
|
||||
|
||||
|
||||
//this file implements a table that is linearly interpolated circular calibration table
|
||||
// it is assumed the data wraps around, ie you interpolated 65536==0
|
||||
//we want this to be "whole" steps, for 1.8 degree motors this should be 200.
|
||||
// 200 will work for 0.9 degree too, but could be 400. However 400 is not good for 1.8 degree motors
|
||||
#define CALIBRATION_TABLE_SIZE (200)
|
||||
|
||||
#define CALIBRATION_STEPS ((uint32_t)ANGLE_STEPS) // this is one rotation ie 0-65535 aka 65536 steps is 0-360 degrees
|
||||
|
||||
#define CALIBRATION_ERROR_NOT_SET (-1) //indicated that the calibration value is not set.
|
||||
|
||||
#define CALIBRATION_UPDATE_RATE (32) //number of samples to keep 1 pole running average
|
||||
#define CALIBRATION_MIN_ERROR (4) //the minimal expected error on our calibration 4 ~=+/0.2 degrees
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t table[CALIBRATION_TABLE_SIZE];
|
||||
bool status;
|
||||
} FlashCalData_t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
Angle value; //cal value
|
||||
int16_t error; //error assuming it is constantly updated
|
||||
} CalData_t;
|
||||
|
||||
class CalibrationTable
|
||||
{
|
||||
private:
|
||||
CalData_t table[CALIBRATION_TABLE_SIZE];
|
||||
|
||||
bool fastCalVaild=false;
|
||||
void loadFromFlash(void);
|
||||
bool flashGood(void); //returns true if the flash copy of calibration is valid
|
||||
|
||||
void updateFastCal(void);
|
||||
void createFastCal(void);
|
||||
|
||||
public:
|
||||
void init(void);
|
||||
void saveToFlash(void); //saves the calibration to flash
|
||||
bool updateTableValue(int32_t index, int32_t value);
|
||||
void updateTable(Angle actualAngle, Angle encoderValue);
|
||||
int getValue(Angle actualAngle, CalData_t *ptrData);
|
||||
Angle getCal(Angle actualAngle);
|
||||
bool calValid(void);
|
||||
Angle reverseLookup(Angle encoderAngle); //this turns encoder angle into real angle
|
||||
void printCalTable(void);
|
||||
void smoothTable(void);
|
||||
|
||||
Angle fastReverseLookup(Angle encoderAngle);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //__CALIBRAITON_H__
|
||||
|
@ -1,381 +1,381 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
|
||||
#include "command.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define ASCII_BACKSPACE 0x08
|
||||
#define ASCII_ESC 0x1B
|
||||
#define ASCII_UP_ARROW 0x9b
|
||||
//const char CMD_ANSI_UP[]= {ASCII_ESC,'[','A',0};
|
||||
|
||||
int strcicmp(char const *a, char const *b)
|
||||
{
|
||||
for (;; a++, b++) {
|
||||
int d = tolower(*a) - tolower(*b);
|
||||
if (d != 0 || !*a)
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
int CommandInit(sCmdUart *ptrUart, uint8_t (*kbhit)(void), uint8_t (*getch)(void),uint8_t (*putch)(char data),uint8_t (*puts)(uint8_t *buffer, uint8_t size) )
|
||||
{
|
||||
ptrUart->kbhit=kbhit;
|
||||
ptrUart->getch=getch;
|
||||
ptrUart->putch=putch;
|
||||
ptrUart->puts=puts;
|
||||
ptrUart->histIndex=0;
|
||||
ptrUart->buffIndex=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef PGM_P //check and see if the PGM_P is defined for the AVR
|
||||
|
||||
int CommandPrintf(sCmdUart *ptrUart, const char *fmt, ...)
|
||||
{
|
||||
int ret=0;
|
||||
char vastr[MAX_STRING]={0};
|
||||
//char str[MAX_STRING]={0};
|
||||
char *ptr;
|
||||
va_list ap;
|
||||
|
||||
//LOG("Command printf");
|
||||
memset(vastr,0,MAX_STRING);
|
||||
va_start(ap,fmt);
|
||||
ret=vsprintf(vastr,(const char *)fmt,ap);
|
||||
//ret=sprintf(vastr,"%s\r\n",str);
|
||||
//LOG("%s",vastr);
|
||||
if (ptrUart->puts!=NULL)
|
||||
{
|
||||
return ptrUart->puts((uint8_t *)vastr, (uint8_t)ret);
|
||||
}
|
||||
|
||||
if (ptrUart->putch!=NULL)
|
||||
{
|
||||
ptr=vastr;
|
||||
while(*ptr)
|
||||
{
|
||||
ptrUart->putch(*ptr++);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
int CommandPrintf(sCmdUart *ptrUart, char *fmt, ...)
|
||||
{
|
||||
int ret=0;
|
||||
char vastr[MAX_STRING]={0};
|
||||
char *ptr;
|
||||
va_list ap;
|
||||
|
||||
|
||||
memset(vastr,0,MAX_STRING);
|
||||
va_start(ap,fmt);
|
||||
ret=vsprintf(vastr,(char *)fmt,ap);
|
||||
if (ptrUart->puts!=NULL)
|
||||
{
|
||||
return ptrUart->puts((uint8_t *)vastr, (uint8_t)ret);
|
||||
}
|
||||
|
||||
if (ptrUart->putch!=NULL)
|
||||
{
|
||||
ptr=vastr;
|
||||
while(*ptr)
|
||||
{
|
||||
ptrUart->putch(*ptr++);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// the delimiter is command/parameter delimiter
|
||||
// by default a ' '0x20 is used but for the TDR with GUI a ':' was preferred, not sure why
|
||||
// set to ' '/0x20 if you want normal command parsing, like DOS
|
||||
unsigned int CommandParse(sCmdUart *ptrUart,sCommand *ptrCmds, char *str, char delimitor )
|
||||
{
|
||||
char *ptr;
|
||||
char *ptr2;
|
||||
unsigned int i;
|
||||
//char cmd[MAX_STRING];
|
||||
char buff[MAX_CMD_LENGTH];
|
||||
char argv[MAX_ARGS][MAX_ARG_LENGTH];
|
||||
char *ptrArgv[MAX_ARGS];
|
||||
unsigned int numArgs;
|
||||
int emptyArg=0;
|
||||
|
||||
sCommand cmd_list;
|
||||
|
||||
|
||||
while (*str==0x20 || *str=='\n' || *str=='\r' || *str=='\t') str++;
|
||||
//first we need find command and arguments
|
||||
ptr=strchr(str,delimitor); //find first char
|
||||
|
||||
//LOG("2parsing %s",str);
|
||||
|
||||
|
||||
if (ptr==0)
|
||||
{
|
||||
//we have two options, frist whole thing is command
|
||||
//second bad command
|
||||
if(strlen(str)>0)
|
||||
ptr=str+strlen(str);
|
||||
else
|
||||
return 0; //bad command
|
||||
}
|
||||
|
||||
//copy string to command buffer.
|
||||
i=0;
|
||||
ptr2=str;
|
||||
while(ptr!=0 && ptr!=ptr2 && i<(MAX_CMD_LENGTH-1))
|
||||
{
|
||||
//if (*ptr2!='\n' && *ptr2!='\r') //do not include newlines
|
||||
{
|
||||
buff[i++]=*ptr2;
|
||||
}
|
||||
ptr2++;
|
||||
}
|
||||
buff[i]=0;
|
||||
|
||||
//now buff contains the command let's get the args
|
||||
numArgs=0;
|
||||
while(*ptr!=0 && (*ptr==' ' || *ptr==delimitor))
|
||||
ptr++; //increment pointer past ' '
|
||||
if (*ptr!=0)
|
||||
{
|
||||
if (*ptr==34) // " char
|
||||
{
|
||||
ptr++;
|
||||
ptr2=strchr(ptr,34); //find match
|
||||
} else if (*ptr==39) // 'char
|
||||
{
|
||||
ptr++;
|
||||
ptr2=strchr(ptr,39); //find match
|
||||
} else
|
||||
{
|
||||
ptr2=strchr(ptr,delimitor);
|
||||
}
|
||||
if (ptr2==0)
|
||||
{
|
||||
//we have two options, frist whole thing is command
|
||||
//second bad command
|
||||
//LOG("strlen ptr is %d",strlen(ptr));
|
||||
if(strlen(ptr)>0)
|
||||
ptr2=ptr+strlen(ptr);
|
||||
}
|
||||
emptyArg=0;
|
||||
while((ptr2!=0 && numArgs<MAX_ARGS) || emptyArg==1)
|
||||
{
|
||||
int j;
|
||||
emptyArg=0;
|
||||
j=0;
|
||||
//LOG("arg %s",ptr);
|
||||
while (ptr2!=ptr && j<(MAX_ARG_LENGTH-1) && ptr2!=0)
|
||||
{
|
||||
argv[numArgs][j++]=*ptr++;
|
||||
}
|
||||
argv[numArgs][j++]=0;
|
||||
numArgs++;
|
||||
ptr2=0;
|
||||
if (*ptr!=0)
|
||||
{
|
||||
if (*ptr==34 || *ptr==39) ptr++;
|
||||
if (*ptr==delimitor && strlen(ptr)==1)
|
||||
{
|
||||
//LOG("Empty arg");
|
||||
emptyArg=1;
|
||||
}
|
||||
while(*ptr!=0 && (*ptr==' ' || *ptr==delimitor))//p || *ptr==34 || *ptr==39))
|
||||
ptr++; //increment pointer past ' '
|
||||
if (*ptr==34) // " char
|
||||
{
|
||||
ptr++;
|
||||
ptr2=strchr(ptr,34); //find match
|
||||
} else if (*ptr==39) // 'char
|
||||
{
|
||||
ptr++;
|
||||
ptr2=strchr(ptr,39); //find match
|
||||
} else
|
||||
{
|
||||
ptr2=strchr(ptr,delimitor);
|
||||
}
|
||||
if (ptr2==0)
|
||||
{
|
||||
//we have two options, frist whole thing is command
|
||||
//second bad command
|
||||
if(strlen(ptr)>0)
|
||||
ptr2=ptr+strlen(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<MAX_ARGS; i++)
|
||||
{
|
||||
ptrArgv[i]=argv[i];
|
||||
}
|
||||
|
||||
//now let's parse the command
|
||||
i=0;
|
||||
memcpy(&cmd_list, &ptrCmds[i], sizeof(sCommand));
|
||||
|
||||
|
||||
//LOG("command is %s %d",buff,numArgs);
|
||||
|
||||
while(cmd_list.function!=0)
|
||||
{
|
||||
/*char str[20];
|
||||
strcpy_P(str,cmd_list.name);
|
||||
LOG("checkign '%s' to '%s'",buff,str);
|
||||
LOG("comapre is %d",strcmp_P(buff,cmd_list.name));
|
||||
*/
|
||||
|
||||
//memcpy_P(&p, cmd_list.name, sizeof(PGM_P));
|
||||
#ifdef PGM_P //check and see if the PGM_P is defined for the AVR
|
||||
if (strlen(buff)==strlen_P(cmd_list.name))
|
||||
{
|
||||
if (strcicmp(buff,cmd_list.name)==0) //ignore device ID
|
||||
#else
|
||||
if (strlen(buff)==strlen(cmd_list.name))
|
||||
{
|
||||
if (strcicmp(buff,cmd_list.name)==0) //ignore device ID
|
||||
#endif
|
||||
{
|
||||
//LOG("calling function");
|
||||
//return 1;
|
||||
return (*cmd_list.function)(ptrUart,numArgs,ptrArgv);
|
||||
}
|
||||
}
|
||||
i=i+1;
|
||||
memcpy(&cmd_list, &ptrCmds[i], sizeof(sCommand));
|
||||
}
|
||||
CommandPrintf(ptrUart,PSTR("Unknown command (try 'help')\n\r"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
//This function will process commands from the UART
|
||||
int CommandProcess(sCmdUart *ptrUart,sCommand *ptrCmds, char delimitor, char *cmdPrompt)
|
||||
{
|
||||
if(ptrUart->kbhit())
|
||||
{
|
||||
ptrUart->data=ptrUart->getch();
|
||||
|
||||
//echo the data
|
||||
ptrUart->putch(ptrUart->data);
|
||||
|
||||
//if the data is the CR we need to process buffer
|
||||
if (ptrUart->data==0x0D)
|
||||
{
|
||||
ptrUart->putch(0x0A);
|
||||
if (strlen(ptrUart->buffer)>0)
|
||||
{
|
||||
if (ptrUart->lastChar!=ASCII_UP_ARROW)
|
||||
{
|
||||
strcpy(ptrUart->bufferHist[ptrUart->histIndex],ptrUart->buffer);
|
||||
ptrUart->histIndex=(ptrUart->histIndex+1) % CMD_HISTORY;
|
||||
}
|
||||
CommandParse(ptrUart,ptrCmds,ptrUart->buffer,delimitor);
|
||||
}
|
||||
|
||||
CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt);
|
||||
ptrUart->buffIndex=0;
|
||||
ptrUart->buffer[ptrUart->buffIndex]=0;
|
||||
}
|
||||
|
||||
if (ptrUart->data==ASCII_BACKSPACE) //backspace
|
||||
{
|
||||
if (ptrUart->buffIndex>0)
|
||||
{
|
||||
ptrUart->buffIndex--;
|
||||
ptrUart->buffer[ptrUart->buffIndex]='\0';
|
||||
//Echo the backspace
|
||||
ptrUart->putch(' ');
|
||||
ptrUart->putch(ASCII_BACKSPACE);
|
||||
}
|
||||
}else if (ptrUart->data != 0x0A && ptrUart->data !=0x0D && ptrUart->data<127)
|
||||
{
|
||||
ptrUart->buffer[ptrUart->buffIndex++]=ptrUart->data;
|
||||
ptrUart->buffer[ptrUart->buffIndex]=0;
|
||||
}
|
||||
if (ptrUart->buffIndex>=(MAX_CMD_LENGTH-1))
|
||||
{
|
||||
CommandPrintf(ptrUart,PSTR("\n\rERROR: Command buffer overflow\n\r"));\
|
||||
ERROR("Command buffer overflow");
|
||||
ptrUart->buffIndex=0;
|
||||
ptrUart->buffer[0]=0;
|
||||
CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (strstr(ptrUart->buffer,ANSI_UP)) //up arrow
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt);
|
||||
i=CMD_HISTORY-1;
|
||||
if (ptrUart->histIndex>0)
|
||||
{
|
||||
i=ptrUart->histIndex-1;
|
||||
}
|
||||
if (strlen(ptrUart->bufferHist[i])>0)
|
||||
{
|
||||
strcpy(ptrUart->buffer,ptrUart->bufferHist[i]);
|
||||
ptrUart->buffIndex=strlen(ptrUart->buffer);
|
||||
CommandPrintf(ptrUart,PSTR("%s"),ptrUart->buffer);
|
||||
}else
|
||||
{
|
||||
ptrUart->buffIndex=0;
|
||||
ptrUart->buffer[0]=0;
|
||||
}
|
||||
ptrUart->data=ASCII_UP_ARROW;
|
||||
}
|
||||
|
||||
|
||||
ptrUart->lastChar=ptrUart->data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
|
||||
#include "command.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define ASCII_BACKSPACE 0x08
|
||||
#define ASCII_ESC 0x1B
|
||||
#define ASCII_UP_ARROW 0x9b
|
||||
//const char CMD_ANSI_UP[]= {ASCII_ESC,'[','A',0};
|
||||
|
||||
int strcicmp(char const *a, char const *b)
|
||||
{
|
||||
for (;; a++, b++) {
|
||||
int d = tolower(*a) - tolower(*b);
|
||||
if (d != 0 || !*a)
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
int CommandInit(sCmdUart *ptrUart, uint8_t (*kbhit)(void), uint8_t (*getch)(void),uint8_t (*putch)(char data),uint8_t (*puts)(uint8_t *buffer, uint8_t size) )
|
||||
{
|
||||
ptrUart->kbhit=kbhit;
|
||||
ptrUart->getch=getch;
|
||||
ptrUart->putch=putch;
|
||||
ptrUart->puts=puts;
|
||||
ptrUart->histIndex=0;
|
||||
ptrUart->buffIndex=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef PGM_P //check and see if the PGM_P is defined for the AVR
|
||||
|
||||
int CommandPrintf(sCmdUart *ptrUart, const char *fmt, ...)
|
||||
{
|
||||
int ret=0;
|
||||
char vastr[MAX_STRING]={0};
|
||||
//char str[MAX_STRING]={0};
|
||||
char *ptr;
|
||||
va_list ap;
|
||||
|
||||
//LOG("Command printf");
|
||||
memset(vastr,0,MAX_STRING);
|
||||
va_start(ap,fmt);
|
||||
ret=vsprintf(vastr,(const char *)fmt,ap);
|
||||
//ret=sprintf(vastr,"%s\r\n",str);
|
||||
//LOG("%s",vastr);
|
||||
if (ptrUart->puts!=NULL)
|
||||
{
|
||||
return ptrUart->puts((uint8_t *)vastr, (uint8_t)ret);
|
||||
}
|
||||
|
||||
if (ptrUart->putch!=NULL)
|
||||
{
|
||||
ptr=vastr;
|
||||
while(*ptr)
|
||||
{
|
||||
ptrUart->putch(*ptr++);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
int CommandPrintf(sCmdUart *ptrUart, char *fmt, ...)
|
||||
{
|
||||
int ret=0;
|
||||
char vastr[MAX_STRING]={0};
|
||||
char *ptr;
|
||||
va_list ap;
|
||||
|
||||
|
||||
memset(vastr,0,MAX_STRING);
|
||||
va_start(ap,fmt);
|
||||
ret=vsprintf(vastr,(char *)fmt,ap);
|
||||
if (ptrUart->puts!=NULL)
|
||||
{
|
||||
return ptrUart->puts((uint8_t *)vastr, (uint8_t)ret);
|
||||
}
|
||||
|
||||
if (ptrUart->putch!=NULL)
|
||||
{
|
||||
ptr=vastr;
|
||||
while(*ptr)
|
||||
{
|
||||
ptrUart->putch(*ptr++);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// the delimiter is command/parameter delimiter
|
||||
// by default a ' '0x20 is used but for the TDR with GUI a ':' was preferred, not sure why
|
||||
// set to ' '/0x20 if you want normal command parsing, like DOS
|
||||
unsigned int CommandParse(sCmdUart *ptrUart,sCommand *ptrCmds, char *str, char delimitor )
|
||||
{
|
||||
char *ptr;
|
||||
char *ptr2;
|
||||
unsigned int i;
|
||||
//char cmd[MAX_STRING];
|
||||
char buff[MAX_CMD_LENGTH];
|
||||
char argv[MAX_ARGS][MAX_ARG_LENGTH];
|
||||
char *ptrArgv[MAX_ARGS];
|
||||
unsigned int numArgs;
|
||||
int emptyArg=0;
|
||||
|
||||
sCommand cmd_list;
|
||||
|
||||
|
||||
while (*str==0x20 || *str=='\n' || *str=='\r' || *str=='\t') str++;
|
||||
//first we need find command and arguments
|
||||
ptr=strchr(str,delimitor); //find first char
|
||||
|
||||
//LOG("2parsing %s",str);
|
||||
|
||||
|
||||
if (ptr==0)
|
||||
{
|
||||
//we have two options, frist whole thing is command
|
||||
//second bad command
|
||||
if(strlen(str)>0)
|
||||
ptr=str+strlen(str);
|
||||
else
|
||||
return 0; //bad command
|
||||
}
|
||||
|
||||
//copy string to command buffer.
|
||||
i=0;
|
||||
ptr2=str;
|
||||
while(ptr!=0 && ptr!=ptr2 && i<(MAX_CMD_LENGTH-1))
|
||||
{
|
||||
//if (*ptr2!='\n' && *ptr2!='\r') //do not include newlines
|
||||
{
|
||||
buff[i++]=*ptr2;
|
||||
}
|
||||
ptr2++;
|
||||
}
|
||||
buff[i]=0;
|
||||
|
||||
//now buff contains the command let's get the args
|
||||
numArgs=0;
|
||||
while(*ptr!=0 && (*ptr==' ' || *ptr==delimitor))
|
||||
ptr++; //increment pointer past ' '
|
||||
if (*ptr!=0)
|
||||
{
|
||||
if (*ptr==34) // " char
|
||||
{
|
||||
ptr++;
|
||||
ptr2=strchr(ptr,34); //find match
|
||||
} else if (*ptr==39) // 'char
|
||||
{
|
||||
ptr++;
|
||||
ptr2=strchr(ptr,39); //find match
|
||||
} else
|
||||
{
|
||||
ptr2=strchr(ptr,delimitor);
|
||||
}
|
||||
if (ptr2==0)
|
||||
{
|
||||
//we have two options, frist whole thing is command
|
||||
//second bad command
|
||||
//LOG("strlen ptr is %d",strlen(ptr));
|
||||
if(strlen(ptr)>0)
|
||||
ptr2=ptr+strlen(ptr);
|
||||
}
|
||||
emptyArg=0;
|
||||
while((ptr2!=0 && numArgs<MAX_ARGS) || emptyArg==1)
|
||||
{
|
||||
int j;
|
||||
emptyArg=0;
|
||||
j=0;
|
||||
//LOG("arg %s",ptr);
|
||||
while (ptr2!=ptr && j<(MAX_ARG_LENGTH-1) && ptr2!=0)
|
||||
{
|
||||
argv[numArgs][j++]=*ptr++;
|
||||
}
|
||||
argv[numArgs][j++]=0;
|
||||
numArgs++;
|
||||
ptr2=0;
|
||||
if (*ptr!=0)
|
||||
{
|
||||
if (*ptr==34 || *ptr==39) ptr++;
|
||||
if (*ptr==delimitor && strlen(ptr)==1)
|
||||
{
|
||||
//LOG("Empty arg");
|
||||
emptyArg=1;
|
||||
}
|
||||
while(*ptr!=0 && (*ptr==' ' || *ptr==delimitor))//p || *ptr==34 || *ptr==39))
|
||||
ptr++; //increment pointer past ' '
|
||||
if (*ptr==34) // " char
|
||||
{
|
||||
ptr++;
|
||||
ptr2=strchr(ptr,34); //find match
|
||||
} else if (*ptr==39) // 'char
|
||||
{
|
||||
ptr++;
|
||||
ptr2=strchr(ptr,39); //find match
|
||||
} else
|
||||
{
|
||||
ptr2=strchr(ptr,delimitor);
|
||||
}
|
||||
if (ptr2==0)
|
||||
{
|
||||
//we have two options, frist whole thing is command
|
||||
//second bad command
|
||||
if(strlen(ptr)>0)
|
||||
ptr2=ptr+strlen(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<MAX_ARGS; i++)
|
||||
{
|
||||
ptrArgv[i]=argv[i];
|
||||
}
|
||||
|
||||
//now let's parse the command
|
||||
i=0;
|
||||
memcpy(&cmd_list, &ptrCmds[i], sizeof(sCommand));
|
||||
|
||||
|
||||
//LOG("command is %s %d",buff,numArgs);
|
||||
|
||||
while(cmd_list.function!=0)
|
||||
{
|
||||
/*char str[20];
|
||||
strcpy_P(str,cmd_list.name);
|
||||
LOG("checkign '%s' to '%s'",buff,str);
|
||||
LOG("comapre is %d",strcmp_P(buff,cmd_list.name));
|
||||
*/
|
||||
|
||||
//memcpy_P(&p, cmd_list.name, sizeof(PGM_P));
|
||||
#ifdef PGM_P //check and see if the PGM_P is defined for the AVR
|
||||
if (strlen(buff)==strlen_P(cmd_list.name))
|
||||
{
|
||||
if (strcicmp(buff,cmd_list.name)==0) //ignore device ID
|
||||
#else
|
||||
if (strlen(buff)==strlen(cmd_list.name))
|
||||
{
|
||||
if (strcicmp(buff,cmd_list.name)==0) //ignore device ID
|
||||
#endif
|
||||
{
|
||||
//LOG("calling function");
|
||||
//return 1;
|
||||
return (*cmd_list.function)(ptrUart,numArgs,ptrArgv);
|
||||
}
|
||||
}
|
||||
i=i+1;
|
||||
memcpy(&cmd_list, &ptrCmds[i], sizeof(sCommand));
|
||||
}
|
||||
CommandPrintf(ptrUart,PSTR("Unknown command (try 'help')\n\r"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
//This function will process commands from the UART
|
||||
int CommandProcess(sCmdUart *ptrUart,sCommand *ptrCmds, char delimitor, char *cmdPrompt)
|
||||
{
|
||||
if(ptrUart->kbhit())
|
||||
{
|
||||
ptrUart->data=ptrUart->getch();
|
||||
|
||||
//echo the data
|
||||
ptrUart->putch(ptrUart->data);
|
||||
|
||||
//if the data is the CR we need to process buffer
|
||||
if (ptrUart->data==0x0D)
|
||||
{
|
||||
ptrUart->putch(0x0A);
|
||||
if (strlen(ptrUart->buffer)>0)
|
||||
{
|
||||
if (ptrUart->lastChar!=ASCII_UP_ARROW)
|
||||
{
|
||||
strcpy(ptrUart->bufferHist[ptrUart->histIndex],ptrUart->buffer);
|
||||
ptrUart->histIndex=(ptrUart->histIndex+1) % CMD_HISTORY;
|
||||
}
|
||||
CommandParse(ptrUart,ptrCmds,ptrUart->buffer,delimitor);
|
||||
}
|
||||
|
||||
CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt);
|
||||
ptrUart->buffIndex=0;
|
||||
ptrUart->buffer[ptrUart->buffIndex]=0;
|
||||
}
|
||||
|
||||
if (ptrUart->data==ASCII_BACKSPACE) //backspace
|
||||
{
|
||||
if (ptrUart->buffIndex>0)
|
||||
{
|
||||
ptrUart->buffIndex--;
|
||||
ptrUart->buffer[ptrUart->buffIndex]='\0';
|
||||
//Echo the backspace
|
||||
ptrUart->putch(' ');
|
||||
ptrUart->putch(ASCII_BACKSPACE);
|
||||
}
|
||||
}else if (ptrUart->data != 0x0A && ptrUart->data !=0x0D && ptrUart->data<127)
|
||||
{
|
||||
ptrUart->buffer[ptrUart->buffIndex++]=ptrUart->data;
|
||||
ptrUart->buffer[ptrUart->buffIndex]=0;
|
||||
}
|
||||
if (ptrUart->buffIndex>=(MAX_CMD_LENGTH-1))
|
||||
{
|
||||
CommandPrintf(ptrUart,PSTR("\n\rERROR: Command buffer overflow\n\r"));\
|
||||
ERROR("Command buffer overflow");
|
||||
ptrUart->buffIndex=0;
|
||||
ptrUart->buffer[0]=0;
|
||||
CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (strstr(ptrUart->buffer,ANSI_UP)) //up arrow
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt);
|
||||
i=CMD_HISTORY-1;
|
||||
if (ptrUart->histIndex>0)
|
||||
{
|
||||
i=ptrUart->histIndex-1;
|
||||
}
|
||||
if (strlen(ptrUart->bufferHist[i])>0)
|
||||
{
|
||||
strcpy(ptrUart->buffer,ptrUart->bufferHist[i]);
|
||||
ptrUart->buffIndex=strlen(ptrUart->buffer);
|
||||
CommandPrintf(ptrUart,PSTR("%s"),ptrUart->buffer);
|
||||
}else
|
||||
{
|
||||
ptrUart->buffIndex=0;
|
||||
ptrUart->buffer[0]=0;
|
||||
}
|
||||
ptrUart->data=ASCII_UP_ARROW;
|
||||
}
|
||||
|
||||
|
||||
ptrUart->lastChar=ptrUart->data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,179 +1,179 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __COMMAND_H
|
||||
#define __COMMAND_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdarg.h>
|
||||
#include "syslog.h"
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
#include <command.h>
|
||||
#include "uart_e0.h"
|
||||
|
||||
sCmdUart KeyfobCmdUart; // UART used for the keyfob command line interface
|
||||
|
||||
CMD_STR(help,"Displays this message");
|
||||
|
||||
//List of supported commands
|
||||
sCommand KeyfobCmds[] =
|
||||
{
|
||||
COMMAND(help),
|
||||
{"",0,""}, //End of list signal
|
||||
};
|
||||
|
||||
// print out the help strings for the commands
|
||||
static int help_cmd(sCmdUart *ptrUart,int argc, char * argv[])
|
||||
{
|
||||
sCommand cmd_list;
|
||||
int i;
|
||||
|
||||
//now let's parse the command
|
||||
i=0;
|
||||
memcpy(&cmd_list, &KeyfobCmds[i], sizeof(sCommand));
|
||||
while(cmd_list.function!=0)
|
||||
{
|
||||
|
||||
CommandPrintf(ptrUart,(cmd_list.name));
|
||||
CommandPrintf(ptrUart,PSTR(" - "));
|
||||
CommandPrintf(ptrUart,(cmd_list.help));
|
||||
CommandPrintf(ptrUart,PSTR("\n\r"));
|
||||
i=i+1;
|
||||
memcpy(&cmd_list, &KeyfobCmds[i], sizeof(sCommand));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t KeyfobCmdGetChar(void)
|
||||
{
|
||||
uint8_t c;
|
||||
if (UARTE0_getc(&c)!=0)
|
||||
{
|
||||
ERROR("Uart getchar failed");
|
||||
return 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
int KeyfobCmdInit(PIN tx_pin, PIN rx_pin, uint32_t baud)
|
||||
{
|
||||
LOG("UARTE0 init");
|
||||
UARTE0_Init(tx_pin, rx_pin, baud);
|
||||
CommandInit(&KeyfobCmdUart, UARTE0_kbhit, KeyfobCmdGetChar, UARTE0_putc,NULL); //set up the UART structure
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KeyfobCmdProcess(void)
|
||||
{
|
||||
return CommandProcess(&KeyfobCmdUart,KeyfobCmds,' ',KEYFOB_CMD_PROMPT);
|
||||
}
|
||||
|
||||
Advantages:
|
||||
1. You can actually have more than one UART/device connected to same command line interface.
|
||||
2. works with harvard machines to save SRAM space using the PSTR functionality
|
||||
3. You can swap out commands "on the fly"
|
||||
|
||||
|
||||
*/
|
||||
#define MAX_CMD_LENGTH 60
|
||||
#define MAX_ARGS 10
|
||||
#define MAX_ARG_LENGTH 40
|
||||
#define CMD_HISTORY 3 //number of commands in history buffer
|
||||
#define ASCII_BACKSPACE 0x08
|
||||
#define ASCII_ESC 0x1B
|
||||
#define ASCII_UP_ARROW 0x9b
|
||||
#define ANSI_UP "\x1B[A\0"
|
||||
|
||||
#define MAX_STRING 255
|
||||
//const char ANSI_UP[]= {ASCII_ESC,'[','A',0};
|
||||
|
||||
typedef struct {
|
||||
uint8_t (*kbhit)(void);
|
||||
uint8_t (*getch)(void);
|
||||
uint8_t (*putch)(char data);
|
||||
uint8_t (*puts)(uint8_t *buffer, uint8_t size);
|
||||
uint8_t data;
|
||||
char buffer[MAX_CMD_LENGTH];
|
||||
|
||||
char bufferHist[CMD_HISTORY][MAX_CMD_LENGTH];
|
||||
uint8_t histIndex;
|
||||
uint8_t buffIndex;
|
||||
uint8_t lastChar;
|
||||
}sCmdUart;
|
||||
|
||||
|
||||
#define COMMAND(NAME) { NAME ## _str, NAME ## _cmd, NAME ## _help}
|
||||
|
||||
|
||||
#ifdef PGM_P //check and see if the PGM_P is defined for the AVR
|
||||
|
||||
//If so then we use the strings in flash not SRAM
|
||||
#define CMD_STR(NAME,STR) static const char NAME ## _help[] PROGMEM = STR; static const char NAME ## _str[] PROGMEM = #NAME; static int NAME ##_cmd(sCmdUart *ptrUart,int, char **);
|
||||
//Command structure
|
||||
typedef struct
|
||||
{
|
||||
PGM_P name;
|
||||
int (*function) (sCmdUart *ptrUart,int, char **);
|
||||
PGM_P help;
|
||||
} sCommand;
|
||||
int CommandPrintf(sCmdUart *ptrUart, const char *fmt, ...);
|
||||
|
||||
#else
|
||||
|
||||
#define CMD_STR(NAME,STR) static char NAME ## _help[] = STR; static char NAME ## _str[] = #NAME; static int NAME ##_cmd(sCmdUart *ptrUart,int, char **);
|
||||
|
||||
//Command structure
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
int (*function) (sCmdUart *ptrUart,int, char **);
|
||||
char *help;
|
||||
} sCommand;
|
||||
|
||||
int CommandPrintf(sCmdUart *ptrUart, char *fmt, ...);
|
||||
#endif
|
||||
|
||||
|
||||
int CommandInit(sCmdUart *ptrUart, uint8_t (*kbhit)(void), uint8_t (*getch)(void),uint8_t (*putch)(char data),uint8_t (*puts)(uint8_t *buffer, uint8_t size));
|
||||
unsigned int CommandParse(sCmdUart *ptrUart,sCommand *ptrCmds, char *str, char delimitor);
|
||||
int CommandProcess(sCmdUart *ptrUart,sCommand *ptrCmds, char delimitor, char *cmdPrompt);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __COMMAND_H
|
||||
#define __COMMAND_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdarg.h>
|
||||
#include "syslog.h"
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
#include <command.h>
|
||||
#include "uart_e0.h"
|
||||
|
||||
sCmdUart KeyfobCmdUart; // UART used for the keyfob command line interface
|
||||
|
||||
CMD_STR(help,"Displays this message");
|
||||
|
||||
//List of supported commands
|
||||
sCommand KeyfobCmds[] =
|
||||
{
|
||||
COMMAND(help),
|
||||
{"",0,""}, //End of list signal
|
||||
};
|
||||
|
||||
// print out the help strings for the commands
|
||||
static int help_cmd(sCmdUart *ptrUart,int argc, char * argv[])
|
||||
{
|
||||
sCommand cmd_list;
|
||||
int i;
|
||||
|
||||
//now let's parse the command
|
||||
i=0;
|
||||
memcpy(&cmd_list, &KeyfobCmds[i], sizeof(sCommand));
|
||||
while(cmd_list.function!=0)
|
||||
{
|
||||
|
||||
CommandPrintf(ptrUart,(cmd_list.name));
|
||||
CommandPrintf(ptrUart,PSTR(" - "));
|
||||
CommandPrintf(ptrUart,(cmd_list.help));
|
||||
CommandPrintf(ptrUart,PSTR("\n\r"));
|
||||
i=i+1;
|
||||
memcpy(&cmd_list, &KeyfobCmds[i], sizeof(sCommand));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t KeyfobCmdGetChar(void)
|
||||
{
|
||||
uint8_t c;
|
||||
if (UARTE0_getc(&c)!=0)
|
||||
{
|
||||
ERROR("Uart getchar failed");
|
||||
return 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
int KeyfobCmdInit(PIN tx_pin, PIN rx_pin, uint32_t baud)
|
||||
{
|
||||
LOG("UARTE0 init");
|
||||
UARTE0_Init(tx_pin, rx_pin, baud);
|
||||
CommandInit(&KeyfobCmdUart, UARTE0_kbhit, KeyfobCmdGetChar, UARTE0_putc,NULL); //set up the UART structure
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KeyfobCmdProcess(void)
|
||||
{
|
||||
return CommandProcess(&KeyfobCmdUart,KeyfobCmds,' ',KEYFOB_CMD_PROMPT);
|
||||
}
|
||||
|
||||
Advantages:
|
||||
1. You can actually have more than one UART/device connected to same command line interface.
|
||||
2. works with harvard machines to save SRAM space using the PSTR functionality
|
||||
3. You can swap out commands "on the fly"
|
||||
|
||||
|
||||
*/
|
||||
#define MAX_CMD_LENGTH 60
|
||||
#define MAX_ARGS 10
|
||||
#define MAX_ARG_LENGTH 40
|
||||
#define CMD_HISTORY 3 //number of commands in history buffer
|
||||
#define ASCII_BACKSPACE 0x08
|
||||
#define ASCII_ESC 0x1B
|
||||
#define ASCII_UP_ARROW 0x9b
|
||||
#define ANSI_UP "\x1B[A\0"
|
||||
|
||||
#define MAX_STRING 255
|
||||
//const char ANSI_UP[]= {ASCII_ESC,'[','A',0};
|
||||
|
||||
typedef struct {
|
||||
uint8_t (*kbhit)(void);
|
||||
uint8_t (*getch)(void);
|
||||
uint8_t (*putch)(char data);
|
||||
uint8_t (*puts)(uint8_t *buffer, uint8_t size);
|
||||
uint8_t data;
|
||||
char buffer[MAX_CMD_LENGTH];
|
||||
|
||||
char bufferHist[CMD_HISTORY][MAX_CMD_LENGTH];
|
||||
uint8_t histIndex;
|
||||
uint8_t buffIndex;
|
||||
uint8_t lastChar;
|
||||
}sCmdUart;
|
||||
|
||||
|
||||
#define COMMAND(NAME) { NAME ## _str, NAME ## _cmd, NAME ## _help}
|
||||
|
||||
|
||||
#ifdef PGM_P //check and see if the PGM_P is defined for the AVR
|
||||
|
||||
//If so then we use the strings in flash not SRAM
|
||||
#define CMD_STR(NAME,STR) static const char NAME ## _help[] PROGMEM = STR; static const char NAME ## _str[] PROGMEM = #NAME; static int NAME ##_cmd(sCmdUart *ptrUart,int, char **);
|
||||
//Command structure
|
||||
typedef struct
|
||||
{
|
||||
PGM_P name;
|
||||
int (*function) (sCmdUart *ptrUart,int, char **);
|
||||
PGM_P help;
|
||||
} sCommand;
|
||||
int CommandPrintf(sCmdUart *ptrUart, const char *fmt, ...);
|
||||
|
||||
#else
|
||||
|
||||
#define CMD_STR(NAME,STR) static char NAME ## _help[] = STR; static char NAME ## _str[] = #NAME; static int NAME ##_cmd(sCmdUart *ptrUart,int, char **);
|
||||
|
||||
//Command structure
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
int (*function) (sCmdUart *ptrUart,int, char **);
|
||||
char *help;
|
||||
} sCommand;
|
||||
|
||||
int CommandPrintf(sCmdUart *ptrUart, char *fmt, ...);
|
||||
#endif
|
||||
|
||||
|
||||
int CommandInit(sCmdUart *ptrUart, uint8_t (*kbhit)(void), uint8_t (*getch)(void),uint8_t (*putch)(char data),uint8_t (*puts)(uint8_t *buffer, uint8_t size));
|
||||
unsigned int CommandParse(sCmdUart *ptrUart,sCommand *ptrCmds, char *str, char delimitor);
|
||||
int CommandProcess(sCmdUart *ptrUart,sCommand *ptrCmds, char delimitor, char *cmdPrompt);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,51 +1,51 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __COMMANDS_H__
|
||||
#define __COMMANDS_H__
|
||||
#include <Arduino.h>
|
||||
#include "stepper_controller.h"
|
||||
#include "nzs.h"
|
||||
|
||||
extern StepperCtrl stepperCtrl;
|
||||
extern eepromData_t PowerupEEPROM;
|
||||
|
||||
void commandsInit(void);
|
||||
int commandsProcess(void);
|
||||
void torqueSetToZeroSpecialBehaviour(void);
|
||||
|
||||
#endif //__COMMANDS_H__
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef __COMMANDS_H__
|
||||
#define __COMMANDS_H__
|
||||
#include <Arduino.h>
|
||||
#include "stepper_controller.h"
|
||||
#include "nzs.h"
|
||||
|
||||
extern StepperCtrl stepperCtrl;
|
||||
extern eepromData_t PowerupEEPROM;
|
||||
|
||||
void commandsInit(void);
|
||||
int commandsProcess(void);
|
||||
void torqueSetToZeroSpecialBehaviour(void);
|
||||
|
||||
#endif //__COMMANDS_H__
|
||||
|
@ -1,309 +1,309 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include "eeprom.h"
|
||||
#include "calibration.h"
|
||||
#include "Flash.h"
|
||||
#include "board.h" //for divide with rounding macro
|
||||
#include <Arduino.h>
|
||||
#include "syslog.h"
|
||||
|
||||
//since we will write the following structure into each page, we need to find our latest page
|
||||
// to do this we will use the header to contain a checksum and write counter.
|
||||
#define EEPROM_SIZE (FLASH_ROW_SIZE*2)
|
||||
|
||||
typedef struct {
|
||||
uint16_t checksum;
|
||||
uint16_t count;
|
||||
}eepromHeader_t;
|
||||
|
||||
#define EEPROM_DATA_SIZE (FLASH_PAGE_SIZE_NZS-sizeof(eepromHeader_t))
|
||||
typedef struct {
|
||||
eepromHeader_t header;
|
||||
uint8_t data[EEPROM_DATA_SIZE];
|
||||
} eepromData_t;
|
||||
|
||||
|
||||
|
||||
static eepromData_t EEPROMCache;
|
||||
|
||||
static int32_t NextPageWrite=-1;
|
||||
|
||||
//we need to reserve two pages for EEPROM
|
||||
__attribute__((__aligned__(FLASH_ROW_SIZE))) const uint8_t NVM_eeprom[EEPROM_SIZE]={0xFF};
|
||||
|
||||
|
||||
static uint16_t checksum(uint8_t *ptrData, uint32_t nBytes)
|
||||
{
|
||||
uint16_t sum=0;
|
||||
uint32_t i;
|
||||
i=0;
|
||||
//LOG("running checksum %d",nBytes);
|
||||
while(i<nBytes)
|
||||
{
|
||||
sum += ptrData[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static bool isPageGood(uint32_t page)
|
||||
{
|
||||
eepromData_t *ptrData;
|
||||
uint16_t cs;
|
||||
ptrData=(eepromData_t *)&NVM_eeprom[page];
|
||||
|
||||
cs=checksum(ptrData->data, EEPROM_DATA_SIZE);
|
||||
//LOG("checksum is %d %d",cs,ptrData->header.checksum);
|
||||
|
||||
if (cs==ptrData->header.checksum)
|
||||
{
|
||||
//LOG("Page good %d",page);
|
||||
return true;
|
||||
}
|
||||
//LOG("page bad %d",page);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void printEEPROM(uint32_t page)
|
||||
{
|
||||
eepromData_t *ptrData;
|
||||
int i;
|
||||
ptrData=(eepromData_t *)&NVM_eeprom[page];
|
||||
LOG("count %d", ptrData->header.count);
|
||||
LOG("checksum %d", ptrData->header.checksum);
|
||||
for (i=0; i<10; i++)
|
||||
{
|
||||
LOG("Data[%d]=%02X",i,ptrData->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t findLastGoodPage(void)
|
||||
{
|
||||
uint32_t lastGoodPage=0;
|
||||
uint32_t page;
|
||||
uint16_t lastCnt=0;
|
||||
eepromData_t *ptrData;
|
||||
|
||||
page=0;
|
||||
while(page < (EEPROM_SIZE))
|
||||
{
|
||||
//LOG("checking page %d",page);
|
||||
if (isPageGood(page))
|
||||
{
|
||||
ptrData=(eepromData_t *)&NVM_eeprom[page];
|
||||
|
||||
//check for roll over which is OK
|
||||
if (lastCnt==16534 && ptrData->header.count==1)
|
||||
{
|
||||
lastCnt=ptrData->header.count;
|
||||
lastGoodPage=page;
|
||||
}
|
||||
if (ptrData->header.count>lastCnt)
|
||||
{
|
||||
//make sure we have not rolled over.
|
||||
if ((ptrData->header.count-lastCnt)<(16534/2))
|
||||
{
|
||||
lastCnt=ptrData->header.count;
|
||||
lastGoodPage=page;
|
||||
}
|
||||
}
|
||||
}
|
||||
page=page + FLASH_PAGE_SIZE_NZS;
|
||||
}
|
||||
//LOG("last good page %d",lastGoodPage);
|
||||
return lastGoodPage;
|
||||
}
|
||||
|
||||
//find the next page to write
|
||||
static uint32_t eepromGetNextWritPage(void)
|
||||
{
|
||||
eepromHeader_t *ptrHeader;
|
||||
uint32_t page;
|
||||
uint32_t row;
|
||||
int blockCount;
|
||||
int done=0;
|
||||
|
||||
//start at first address:
|
||||
page=0;
|
||||
|
||||
while(page < (EEPROM_SIZE))
|
||||
{
|
||||
//LOG("checking page %d",page);
|
||||
ptrHeader=(eepromHeader_t *) &NVM_eeprom[page];
|
||||
if (ptrHeader->count == 0xFFFF)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t *ptrData;
|
||||
//uint8_t erasedByte=(uint8_t)ptrHeader->count;
|
||||
bool erased=true;
|
||||
|
||||
//verify page is erased
|
||||
ptrData= (uint8_t *)&NVM_eeprom[page];
|
||||
|
||||
for (i=0; i<FLASH_PAGE_SIZE_NZS; i++)
|
||||
{
|
||||
if (ptrData[i] != FLASH_ERASE_VALUE)
|
||||
{
|
||||
erased=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (erased)
|
||||
{
|
||||
//LOG("Found Page %d erased",page);
|
||||
return page;
|
||||
}
|
||||
}
|
||||
page=page+FLASH_PAGE_SIZE_NZS;
|
||||
}
|
||||
//if we get get here all the pages are full...
|
||||
// we need to find the page with last good data.
|
||||
page=findLastGoodPage();
|
||||
|
||||
//find which row the page is in
|
||||
row=page/FLASH_ROW_SIZE;
|
||||
|
||||
//increment to next row for erase
|
||||
row++;
|
||||
if ((row*FLASH_ROW_SIZE)>=EEPROM_SIZE)
|
||||
{
|
||||
row=0;
|
||||
//TODO we should make sure this not where good data is
|
||||
// however if it is what should we do?
|
||||
}
|
||||
|
||||
//now we need to erase that row
|
||||
//WARNING("Erasing page %d",row*FLASH_ROW_SIZE);
|
||||
flashErase(&NVM_eeprom[row*FLASH_ROW_SIZE],FLASH_ROW_SIZE);
|
||||
page=row*FLASH_ROW_SIZE;
|
||||
//LOG("Next free page is %d",page);
|
||||
return page;
|
||||
}
|
||||
|
||||
|
||||
eepromError_t eepromInit(void)
|
||||
{
|
||||
uint32_t page;
|
||||
|
||||
|
||||
//find the last good page offset in flash
|
||||
page=findLastGoodPage();
|
||||
LOG("EEPROM Init found page %d",page);
|
||||
if (isPageGood(page))
|
||||
{
|
||||
LOG("EEPROM page good %d",page);
|
||||
memcpy(&EEPROMCache, &NVM_eeprom[page], sizeof(EEPROMCache));
|
||||
|
||||
NextPageWrite=eepromGetNextWritPage();
|
||||
return EEPROM_OK;
|
||||
}
|
||||
//ERROR("page is bad");
|
||||
memset(&EEPROMCache, 0, sizeof(EEPROMCache));
|
||||
NextPageWrite=eepromGetNextWritPage();
|
||||
return EEPROM_CORRUPT;
|
||||
}
|
||||
|
||||
|
||||
int eepromWriteCache(uint8_t *ptrData, uint32_t size)
|
||||
{
|
||||
//LOG("Cache write %d",size);
|
||||
if (NextPageWrite==-1) //some one did not init the module
|
||||
{
|
||||
//lets handle gracefully and do it ourselves
|
||||
eepromInit();
|
||||
}
|
||||
if (size>EEPROM_DATA_SIZE)
|
||||
{
|
||||
size =EEPROM_DATA_SIZE;
|
||||
}
|
||||
memcpy(EEPROMCache.data, ptrData, size);
|
||||
EEPROMCache.header.checksum=checksum(EEPROMCache.data,EEPROM_DATA_SIZE);
|
||||
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int eepromRead(uint8_t *ptrData, uint32_t size) //returns number of bytes actually read, whcih could be less than size requested
|
||||
{
|
||||
if (NextPageWrite==-1) //some one did not init the module
|
||||
{
|
||||
//lets handle gracefully and do it ourselves
|
||||
eepromInit();
|
||||
}
|
||||
if (size>EEPROM_DATA_SIZE)
|
||||
{
|
||||
size =EEPROM_DATA_SIZE;
|
||||
}
|
||||
if (EEPROMCache.header.count == 0)
|
||||
{
|
||||
return 0; //cache is new/corrupt
|
||||
}
|
||||
memcpy(ptrData, EEPROMCache.data, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
eepromError_t eepromFlush(void) //flush the cache to flash memory
|
||||
{
|
||||
if (NextPageWrite==-1)
|
||||
{
|
||||
ERROR("EEPROM WRITE FAILED");
|
||||
return EEPROM_FAILED; //most likely no one has written to cache
|
||||
}
|
||||
EEPROMCache.header.count++;
|
||||
if (EEPROMCache.header.count>=16535)
|
||||
{
|
||||
EEPROMCache.header.count=1;
|
||||
}
|
||||
//WARNING("Writting to Page %d",NextPageWrite);
|
||||
flashWrite(&NVM_eeprom[NextPageWrite], &EEPROMCache, sizeof(EEPROMCache));
|
||||
|
||||
// printEEPROM(NextPageWrite);
|
||||
|
||||
if (!SYSCTRL->PCLKSR.bit.BOD33DET) //if not in brown out condition find next write location
|
||||
{
|
||||
//LOG("getting next page to write");
|
||||
NextPageWrite=eepromGetNextWritPage(); //find next write location and erase if needed
|
||||
} else
|
||||
{
|
||||
//LOG("BOD active");
|
||||
NextPageWrite=-1; //else we will just clear NextPageWrite location just in case we recover from brown out
|
||||
}
|
||||
return EEPROM_OK;
|
||||
}
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include "eeprom.h"
|
||||
#include "calibration.h"
|
||||
#include "Flash.h"
|
||||
#include "board.h" //for divide with rounding macro
|
||||
#include <Arduino.h>
|
||||
#include "syslog.h"
|
||||
|
||||
//since we will write the following structure into each page, we need to find our latest page
|
||||
// to do this we will use the header to contain a checksum and write counter.
|
||||
#define EEPROM_SIZE (FLASH_ROW_SIZE*2)
|
||||
|
||||
typedef struct {
|
||||
uint16_t checksum;
|
||||
uint16_t count;
|
||||
}eepromHeader_t;
|
||||
|
||||
#define EEPROM_DATA_SIZE (FLASH_PAGE_SIZE_NZS-sizeof(eepromHeader_t))
|
||||
typedef struct {
|
||||
eepromHeader_t header;
|
||||
uint8_t data[EEPROM_DATA_SIZE];
|
||||
} eepromData_t;
|
||||
|
||||
|
||||
|
||||
static eepromData_t EEPROMCache;
|
||||
|
||||
static int32_t NextPageWrite=-1;
|
||||
|
||||
//we need to reserve two pages for EEPROM
|
||||
__attribute__((__aligned__(FLASH_ROW_SIZE))) const uint8_t NVM_eeprom[EEPROM_SIZE]={0xFF};
|
||||
|
||||
|
||||
static uint16_t checksum(uint8_t *ptrData, uint32_t nBytes)
|
||||
{
|
||||
uint16_t sum=0;
|
||||
uint32_t i;
|
||||
i=0;
|
||||
//LOG("running checksum %d",nBytes);
|
||||
while(i<nBytes)
|
||||
{
|
||||
sum += ptrData[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static bool isPageGood(uint32_t page)
|
||||
{
|
||||
eepromData_t *ptrData;
|
||||
uint16_t cs;
|
||||
ptrData=(eepromData_t *)&NVM_eeprom[page];
|
||||
|
||||
cs=checksum(ptrData->data, EEPROM_DATA_SIZE);
|
||||
//LOG("checksum is %d %d",cs,ptrData->header.checksum);
|
||||
|
||||
if (cs==ptrData->header.checksum)
|
||||
{
|
||||
//LOG("Page good %d",page);
|
||||
return true;
|
||||
}
|
||||
//LOG("page bad %d",page);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void printEEPROM(uint32_t page)
|
||||
{
|
||||
eepromData_t *ptrData;
|
||||
int i;
|
||||
ptrData=(eepromData_t *)&NVM_eeprom[page];
|
||||
LOG("count %d", ptrData->header.count);
|
||||
LOG("checksum %d", ptrData->header.checksum);
|
||||
for (i=0; i<10; i++)
|
||||
{
|
||||
LOG("Data[%d]=%02X",i,ptrData->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t findLastGoodPage(void)
|
||||
{
|
||||
uint32_t lastGoodPage=0;
|
||||
uint32_t page;
|
||||
uint16_t lastCnt=0;
|
||||
eepromData_t *ptrData;
|
||||
|
||||
page=0;
|
||||
while(page < (EEPROM_SIZE))
|
||||
{
|
||||
//LOG("checking page %d",page);
|
||||
if (isPageGood(page))
|
||||
{
|
||||
ptrData=(eepromData_t *)&NVM_eeprom[page];
|
||||
|
||||
//check for roll over which is OK
|
||||
if (lastCnt==16534 && ptrData->header.count==1)
|
||||
{
|
||||
lastCnt=ptrData->header.count;
|
||||
lastGoodPage=page;
|
||||
}
|
||||
if (ptrData->header.count>lastCnt)
|
||||
{
|
||||
//make sure we have not rolled over.
|
||||
if ((ptrData->header.count-lastCnt)<(16534/2))
|
||||
{
|
||||
lastCnt=ptrData->header.count;
|
||||
lastGoodPage=page;
|
||||
}
|
||||
}
|
||||
}
|
||||
page=page + FLASH_PAGE_SIZE_NZS;
|
||||
}
|
||||
//LOG("last good page %d",lastGoodPage);
|
||||
return lastGoodPage;
|
||||
}
|
||||
|
||||
//find the next page to write
|
||||
static uint32_t eepromGetNextWritPage(void)
|
||||
{
|
||||
eepromHeader_t *ptrHeader;
|
||||
uint32_t page;
|
||||
uint32_t row;
|
||||
int blockCount;
|
||||
int done=0;
|
||||
|
||||
//start at first address:
|
||||
page=0;
|
||||
|
||||
while(page < (EEPROM_SIZE))
|
||||
{
|
||||
//LOG("checking page %d",page);
|
||||
ptrHeader=(eepromHeader_t *) &NVM_eeprom[page];
|
||||
if (ptrHeader->count == 0xFFFF)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t *ptrData;
|
||||
//uint8_t erasedByte=(uint8_t)ptrHeader->count;
|
||||
bool erased=true;
|
||||
|
||||
//verify page is erased
|
||||
ptrData= (uint8_t *)&NVM_eeprom[page];
|
||||
|
||||
for (i=0; i<FLASH_PAGE_SIZE_NZS; i++)
|
||||
{
|
||||
if (ptrData[i] != FLASH_ERASE_VALUE)
|
||||
{
|
||||
erased=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (erased)
|
||||
{
|
||||
//LOG("Found Page %d erased",page);
|
||||
return page;
|
||||
}
|
||||
}
|
||||
page=page+FLASH_PAGE_SIZE_NZS;
|
||||
}
|
||||
//if we get get here all the pages are full...
|
||||
// we need to find the page with last good data.
|
||||
page=findLastGoodPage();
|
||||
|
||||
//find which row the page is in
|
||||
row=page/FLASH_ROW_SIZE;
|
||||
|
||||
//increment to next row for erase
|
||||
row++;
|
||||
if ((row*FLASH_ROW_SIZE)>=EEPROM_SIZE)
|
||||
{
|
||||
row=0;
|
||||
//TODO we should make sure this not where good data is
|
||||
// however if it is what should we do?
|
||||
}
|
||||
|
||||
//now we need to erase that row
|
||||
//WARNING("Erasing page %d",row*FLASH_ROW_SIZE);
|
||||
flashErase(&NVM_eeprom[row*FLASH_ROW_SIZE],FLASH_ROW_SIZE);
|
||||
page=row*FLASH_ROW_SIZE;
|
||||
//LOG("Next free page is %d",page);
|
||||
return page;
|
||||
}
|
||||
|
||||
|
||||
eepromError_t eepromInit(void)
|
||||
{
|
||||
uint32_t page;
|
||||
|
||||
|
||||
//find the last good page offset in flash
|
||||
page=findLastGoodPage();
|
||||
LOG("EEPROM Init found page %d",page);
|
||||
if (isPageGood(page))
|
||||
{
|
||||
LOG("EEPROM page good %d",page);
|
||||
memcpy(&EEPROMCache, &NVM_eeprom[page], sizeof(EEPROMCache));
|
||||
|
||||
NextPageWrite=eepromGetNextWritPage();
|
||||
return EEPROM_OK;
|
||||
}
|
||||
//ERROR("page is bad");
|
||||
memset(&EEPROMCache, 0, sizeof(EEPROMCache));
|
||||
NextPageWrite=eepromGetNextWritPage();
|
||||
return EEPROM_CORRUPT;
|
||||
}
|
||||
|
||||
|
||||
int eepromWriteCache(uint8_t *ptrData, uint32_t size)
|
||||
{
|
||||
//LOG("Cache write %d",size);
|
||||
if (NextPageWrite==-1) //some one did not init the module
|
||||
{
|
||||
//lets handle gracefully and do it ourselves
|
||||
eepromInit();
|
||||
}
|
||||
if (size>EEPROM_DATA_SIZE)
|
||||
{
|
||||
size =EEPROM_DATA_SIZE;
|
||||
}
|
||||
memcpy(EEPROMCache.data, ptrData, size);
|
||||
EEPROMCache.header.checksum=checksum(EEPROMCache.data,EEPROM_DATA_SIZE);
|
||||
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int eepromRead(uint8_t *ptrData, uint32_t size) //returns number of bytes actually read, whcih could be less than size requested
|
||||
{
|
||||
if (NextPageWrite==-1) //some one did not init the module
|
||||
{
|
||||
//lets handle gracefully and do it ourselves
|
||||
eepromInit();
|
||||
}
|
||||
if (size>EEPROM_DATA_SIZE)
|
||||
{
|
||||
size =EEPROM_DATA_SIZE;
|
||||
}
|
||||
if (EEPROMCache.header.count == 0)
|
||||
{
|
||||
return 0; //cache is new/corrupt
|
||||
}
|
||||
memcpy(ptrData, EEPROMCache.data, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
eepromError_t eepromFlush(void) //flush the cache to flash memory
|
||||
{
|
||||
if (NextPageWrite==-1)
|
||||
{
|
||||
ERROR("EEPROM WRITE FAILED");
|
||||
return EEPROM_FAILED; //most likely no one has written to cache
|
||||
}
|
||||
EEPROMCache.header.count++;
|
||||
if (EEPROMCache.header.count>=16535)
|
||||
{
|
||||
EEPROMCache.header.count=1;
|
||||
}
|
||||
//WARNING("Writting to Page %d",NextPageWrite);
|
||||
flashWrite(&NVM_eeprom[NextPageWrite], &EEPROMCache, sizeof(EEPROMCache));
|
||||
|
||||
// printEEPROM(NextPageWrite);
|
||||
|
||||
if (!SYSCTRL->PCLKSR.bit.BOD33DET) //if not in brown out condition find next write location
|
||||
{
|
||||
//LOG("getting next page to write");
|
||||
NextPageWrite=eepromGetNextWritPage(); //find next write location and erase if needed
|
||||
} else
|
||||
{
|
||||
//LOG("BOD active");
|
||||
NextPageWrite=-1; //else we will just clear NextPageWrite location just in case we recover from brown out
|
||||
}
|
||||
return EEPROM_OK;
|
||||
}
|
||||
|
@ -1,62 +1,62 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef EEPROM_H_
|
||||
#define EEPROM_H_
|
||||
#include "Flash.h"
|
||||
#include "calibration.h"
|
||||
#include "board.h"
|
||||
|
||||
/*
|
||||
* This EEPROM implementation provides 60bytes of "eeprom space" (we reserve 4 bytes for overhead)
|
||||
* The EEPROM uses two rows of flash (256 bytes per row), which
|
||||
* for the SAMD21G18A this allows a minimual 200k writes, but typically 1200k
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
EEPROM_OK =0,
|
||||
EEPROM_FAILED=1,
|
||||
EEPROM_CORRUPT=2,
|
||||
} eepromError_t;
|
||||
|
||||
|
||||
eepromError_t eepromInit(void);
|
||||
int eepromWriteCache(uint8_t *ptrData, uint32_t size); //returns number bytes written to cache
|
||||
eepromError_t eepromFlush(void); //flush the cache to flash memory
|
||||
int eepromRead(uint8_t *ptrData, uint32_t size); //returns number of bytes actually read, whcih could be less than size requested
|
||||
|
||||
#endif /* EEPROM_H_ */
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#ifndef EEPROM_H_
|
||||
#define EEPROM_H_
|
||||
#include "Flash.h"
|
||||
#include "calibration.h"
|
||||
#include "board.h"
|
||||
|
||||
/*
|
||||
* This EEPROM implementation provides 60bytes of "eeprom space" (we reserve 4 bytes for overhead)
|
||||
* The EEPROM uses two rows of flash (256 bytes per row), which
|
||||
* for the SAMD21G18A this allows a minimual 200k writes, but typically 1200k
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
EEPROM_OK =0,
|
||||
EEPROM_FAILED=1,
|
||||
EEPROM_CORRUPT=2,
|
||||
} eepromError_t;
|
||||
|
||||
|
||||
eepromError_t eepromInit(void);
|
||||
int eepromWriteCache(uint8_t *ptrData, uint32_t size); //returns number bytes written to cache
|
||||
eepromError_t eepromFlush(void); //flush the cache to flash memory
|
||||
int eepromRead(uint8_t *ptrData, uint32_t size); //returns number of bytes actually read, whcih could be less than size requested
|
||||
|
||||
#endif /* EEPROM_H_ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,124 +1,124 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef FET_DRIVER_H_
|
||||
#define FET_DRIVER_H_
|
||||
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "board.h"
|
||||
#include "angle.h"
|
||||
#include "sine.h"
|
||||
|
||||
#ifdef NEMA_23_10A_HW
|
||||
#define FET_DRIVER_NUM_MICROSTEPS (SINE_STEPS/4) //number of steps to use for microstepping, default is 256
|
||||
#define FET_DRIVER_NUM_ZERO_AVG (100)
|
||||
|
||||
|
||||
#define FET_ADC_TO_MA(x) (((x)*2537)/1000)
|
||||
#define FET_MA_TO_ADC(x) (((x)*1000)/2537)
|
||||
//prvent someone for making a mistake with the code
|
||||
#if ((FET_DRIVER_NUM_MICROSTEPS*4) != SINE_STEPS)
|
||||
#error "SINE_STEPS must be 4x of Micro steps for the move function"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When it comes to the stepper driver if we use angles
|
||||
* we will always have a rounding error. For example
|
||||
* a 0-65536(360) angle for 1.8 degree step is 327.68 so
|
||||
* if you increment 200 of these as 327 you have a 13.6 error
|
||||
* after one rotation.
|
||||
* If you use floating point the effect is the same but takes longer.
|
||||
*
|
||||
* The only error-less accumulation system is to use native units, ie full
|
||||
* steps and microsteps.
|
||||
*
|
||||
*/
|
||||
|
||||
class FetDriver
|
||||
{
|
||||
static FetDriver *ptrInstance;
|
||||
private:
|
||||
uint32_t lastStepMicros; // time in microseconds that last step happened
|
||||
|
||||
int32_t PWM_Table_B[512];
|
||||
int32_t PWM_Table_A[512];
|
||||
|
||||
bool forwardRotation=true;
|
||||
volatile bool enabled=true;
|
||||
|
||||
volatile int32_t adc;
|
||||
|
||||
|
||||
volatile int32_t coilB_value=0;
|
||||
volatile int32_t coilB_Zero=-1;
|
||||
volatile int32_t coilB_SetPoint=100;
|
||||
volatile int32_t coilB_error=0;
|
||||
|
||||
volatile int32_t coilA_value=0;
|
||||
volatile int32_t coilA_Zero=-1;
|
||||
volatile int32_t coilA_SetPoint=200;
|
||||
volatile int32_t coilA_error=0;
|
||||
void ctrl_update(uint16_t channel, uint16_t value);
|
||||
void measureCoilB_zero(void);
|
||||
void measureCoilA_zero(void);
|
||||
void CalTableB(int32_t maxMA);
|
||||
void CalTableA(int32_t maxMA);
|
||||
int coilA_PWM(int32_t value);
|
||||
void coilB_PWM(int32_t value);
|
||||
int32_t getCoilB_mA(void);
|
||||
int32_t getCoilA_mA(void);
|
||||
public:
|
||||
|
||||
static void ADC_Callback(uint16_t channel, uint16_t value);
|
||||
void begin(void);
|
||||
|
||||
//moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step.
|
||||
int32_t move(int32_t stepAngle, uint32_t mA);
|
||||
|
||||
uint32_t microsSinceStep(void) {return micros()-lastStepMicros;};
|
||||
void setRotationDirection(bool forward) {forwardRotation=forward;};
|
||||
|
||||
void enable(bool enable) {enabled=enable;};
|
||||
void limitCurrent(uint8_t x) {return;};
|
||||
};
|
||||
|
||||
|
||||
#endif //#ifdef NEMA_23_10A_HW
|
||||
#endif /* FET_DRIVER_H_ */
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef FET_DRIVER_H_
|
||||
#define FET_DRIVER_H_
|
||||
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "board.h"
|
||||
#include "angle.h"
|
||||
#include "sine.h"
|
||||
|
||||
#ifdef NEMA_23_10A_HW
|
||||
#define FET_DRIVER_NUM_MICROSTEPS (SINE_STEPS/4) //number of steps to use for microstepping, default is 256
|
||||
#define FET_DRIVER_NUM_ZERO_AVG (100)
|
||||
|
||||
|
||||
#define FET_ADC_TO_MA(x) (((x)*2537)/1000)
|
||||
#define FET_MA_TO_ADC(x) (((x)*1000)/2537)
|
||||
//prvent someone for making a mistake with the code
|
||||
#if ((FET_DRIVER_NUM_MICROSTEPS*4) != SINE_STEPS)
|
||||
#error "SINE_STEPS must be 4x of Micro steps for the move function"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When it comes to the stepper driver if we use angles
|
||||
* we will always have a rounding error. For example
|
||||
* a 0-65536(360) angle for 1.8 degree step is 327.68 so
|
||||
* if you increment 200 of these as 327 you have a 13.6 error
|
||||
* after one rotation.
|
||||
* If you use floating point the effect is the same but takes longer.
|
||||
*
|
||||
* The only error-less accumulation system is to use native units, ie full
|
||||
* steps and microsteps.
|
||||
*
|
||||
*/
|
||||
|
||||
class FetDriver
|
||||
{
|
||||
static FetDriver *ptrInstance;
|
||||
private:
|
||||
uint32_t lastStepMicros; // time in microseconds that last step happened
|
||||
|
||||
int32_t PWM_Table_B[512];
|
||||
int32_t PWM_Table_A[512];
|
||||
|
||||
bool forwardRotation=true;
|
||||
volatile bool enabled=true;
|
||||
|
||||
volatile int32_t adc;
|
||||
|
||||
|
||||
volatile int32_t coilB_value=0;
|
||||
volatile int32_t coilB_Zero=-1;
|
||||
volatile int32_t coilB_SetPoint=100;
|
||||
volatile int32_t coilB_error=0;
|
||||
|
||||
volatile int32_t coilA_value=0;
|
||||
volatile int32_t coilA_Zero=-1;
|
||||
volatile int32_t coilA_SetPoint=200;
|
||||
volatile int32_t coilA_error=0;
|
||||
void ctrl_update(uint16_t channel, uint16_t value);
|
||||
void measureCoilB_zero(void);
|
||||
void measureCoilA_zero(void);
|
||||
void CalTableB(int32_t maxMA);
|
||||
void CalTableA(int32_t maxMA);
|
||||
int coilA_PWM(int32_t value);
|
||||
void coilB_PWM(int32_t value);
|
||||
int32_t getCoilB_mA(void);
|
||||
int32_t getCoilA_mA(void);
|
||||
public:
|
||||
|
||||
static void ADC_Callback(uint16_t channel, uint16_t value);
|
||||
void begin(void);
|
||||
|
||||
//moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step.
|
||||
int32_t move(int32_t stepAngle, uint32_t mA);
|
||||
|
||||
uint32_t microsSinceStep(void) {return micros()-lastStepMicros;};
|
||||
void setRotationDirection(bool forward) {forwardRotation=forward;};
|
||||
|
||||
void enable(bool enable) {enabled=enable;};
|
||||
void limitCurrent(uint8_t x) {return;};
|
||||
};
|
||||
|
||||
|
||||
#endif //#ifdef NEMA_23_10A_HW
|
||||
#endif /* FET_DRIVER_H_ */
|
||||
|
@ -1,193 +1,193 @@
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include "board.h"
|
||||
#include "ftoa.h"
|
||||
/*******************************************************************
|
||||
* FUNCTION: ftoa
|
||||
* AUTHOR = TRAMPAS STERN
|
||||
* FILE = strio.c
|
||||
* DATE = 2/6/2003 4:27:14 PM
|
||||
*
|
||||
* PARAMETERS: long,*str, int count
|
||||
*
|
||||
* DESCRIPTION: Convets an float to string
|
||||
* format 'f', 'E', or 'e'
|
||||
*
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* NOTE this code was found on the web and modified to actually work
|
||||
*******************************************************************/
|
||||
int ftoa (float x, char *str, char prec, char format)
|
||||
{
|
||||
|
||||
int ie, i, k, ndig, fstyle;
|
||||
double y;
|
||||
char *start;
|
||||
|
||||
start=str;
|
||||
|
||||
//based on percission set number digits
|
||||
ndig=prec+1;
|
||||
if (prec<0)
|
||||
ndig=7;
|
||||
if (prec>22)
|
||||
ndig=23;
|
||||
|
||||
fstyle = 0; //exponent 'e'
|
||||
if (format == 'f' || format == 'F')
|
||||
fstyle = 1; //normal 'f'
|
||||
if (format=='g' || format=='G')
|
||||
fstyle=2;
|
||||
|
||||
ie = 0;
|
||||
/* if x negative, write minus and reverse */
|
||||
if ( x < 0)
|
||||
{
|
||||
*str++ = '-';
|
||||
x = -x;
|
||||
}
|
||||
|
||||
//if (x<0.0) then increment by 10 till betwen 1.0 and 10.0
|
||||
if (x!=0.0)
|
||||
{
|
||||
while (x < 1.0)
|
||||
{
|
||||
x =x* 10.0;
|
||||
ie--;
|
||||
}
|
||||
}
|
||||
|
||||
//if x>10 then let's shift it down
|
||||
while (x >= 10.0)
|
||||
{
|
||||
x = x*(1.0/10.0);
|
||||
ie++;
|
||||
}
|
||||
|
||||
if (ABS(ie)>MAX_MANTISA)
|
||||
{
|
||||
if (fstyle==1)
|
||||
{
|
||||
fstyle=0;
|
||||
format='e';
|
||||
//ie=2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* in f format, number of digits is related to size */
|
||||
if (fstyle)
|
||||
ndig =ndig + ie;
|
||||
|
||||
if(prec==0 && ie>ndig && fstyle)
|
||||
{
|
||||
ndig=ie;
|
||||
}
|
||||
|
||||
/* round. x is between 1 and 10 and ndig will be printed to
|
||||
right of decimal point so rounding is ... */
|
||||
y=1;
|
||||
for (i = 1; i < ndig; i++) //find lest significant digit
|
||||
y = y *(1.0/10.0); //multiply by 1/10 is faster than divides
|
||||
|
||||
x = x+ y *(1.0/2.0); //add rounding
|
||||
|
||||
/* repair rounding disasters */
|
||||
if (x >= 10.0)
|
||||
{
|
||||
x = 1.0;
|
||||
ie++;
|
||||
ndig++;
|
||||
}
|
||||
|
||||
//check and see if the number is less than 1.0
|
||||
if (fstyle && ie<0)
|
||||
{
|
||||
*str++ = '0';
|
||||
if (prec!=0)
|
||||
*str++ = '.';
|
||||
if (ndig < 0)
|
||||
ie = ie-ndig; /* limit zeros if underflow */
|
||||
for (i = -1; i > ie; i--)
|
||||
*str++ = '0';
|
||||
}
|
||||
|
||||
//for each digit
|
||||
for (i=0; i < ndig; i++)
|
||||
{
|
||||
float b;
|
||||
k = x; //k = most significant digit
|
||||
*str++ = k + '0'; //output the char representation
|
||||
if (((!fstyle && i==0) || (fstyle && i==ie)) && prec!=0)
|
||||
*str++ = '.'; //output a decimal point
|
||||
b=(float)k;
|
||||
//multiply by 10 before subtraction to remove
|
||||
//errors from limited number of bits in float.
|
||||
b=b*10.0;
|
||||
x=x*10.0;
|
||||
x =x - b; //subtract k from x
|
||||
//b=x+b;
|
||||
//x =x* 10.0; //get next digit
|
||||
}
|
||||
|
||||
/* now, in estyle, put out exponent if not zero */
|
||||
if (!fstyle && ie != 0)
|
||||
{
|
||||
*str++ = format;
|
||||
if (ie < 0) //if number has negative exponent
|
||||
{
|
||||
ie = -ie;
|
||||
*str++ = '-';
|
||||
}
|
||||
|
||||
//now we need to convert the exponent to string
|
||||
for (k=1000; k>ie; k=k/10); //find the decade of exponent
|
||||
|
||||
for (; k > 0; k=k/10)
|
||||
{
|
||||
char t;
|
||||
t=DIV(ie,k);
|
||||
*str++ = t + '0';
|
||||
ie = ie -(t*k);
|
||||
}
|
||||
|
||||
}
|
||||
*str++ = '\0';
|
||||
return (str-start); //return string length
|
||||
}
|
||||
/**********************************************************************
|
||||
Copyright (C) 2018 MisfitTech LLC, All rights reserved.
|
||||
|
||||
MisfitTech uses a dual license model that allows the software to be used under
|
||||
a standard GPL open source license, or a commercial license. The standard GPL
|
||||
license requires that all software statically linked with MisfitTec Code is
|
||||
also distributed under the same GPL V2 license terms. Details of both license
|
||||
options follow:
|
||||
|
||||
- Open source licensing -
|
||||
MisfitTech is a free download and may be used, modified, evaluated and
|
||||
distributed without charge provided the user adheres to version two of the GNU
|
||||
General Public License (GPL) and does not remove the copyright notice or this
|
||||
text. The GPL V2 text is available on the gnu.org web site
|
||||
|
||||
- Commercial licensing -
|
||||
Businesses and individuals that for commercial or other reasons cannot comply
|
||||
with the terms of the GPL V2 license must obtain a low cost commercial license
|
||||
before incorporating MisfitTech code into proprietary software for distribution in
|
||||
any form. Commercial licenses can be purchased from www.misfittech.net
|
||||
and do not require any source files to be changed.
|
||||
|
||||
|
||||
This code is distributed in the hope that it will be useful. You cannot
|
||||
use MisfitTech's code unless you agree that you use the software 'as is'.
|
||||
MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied
|
||||
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they
|
||||
implied, expressed, or statutory.
|
||||
|
||||
|
||||
Written by Trampas Stern for MisfitTech.
|
||||
|
||||
Misfit Tech invests time and resources providing this open source code,
|
||||
please support MisfitTech and open-source hardware by purchasing
|
||||
products from MisfitTech, www.misifittech.net!
|
||||
*********************************************************************/
|
||||
#include "board.h"
|
||||
#include "ftoa.h"
|
||||
/*******************************************************************
|
||||
* FUNCTION: ftoa
|
||||
* AUTHOR = TRAMPAS STERN
|
||||
* FILE = strio.c
|
||||
* DATE = 2/6/2003 4:27:14 PM
|
||||
*
|
||||
* PARAMETERS: long,*str, int count
|
||||
*
|
||||
* DESCRIPTION: Convets an float to string
|
||||
* format 'f', 'E', or 'e'
|
||||
*
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* NOTE this code was found on the web and modified to actually work
|
||||
*******************************************************************/
|
||||
int ftoa (float x, char *str, char prec, char format)
|
||||
{
|
||||
|
||||
int ie, i, k, ndig, fstyle;
|
||||
double y;
|
||||
char *start;
|
||||
|
||||
start=str;
|
||||
|
||||
//based on percission set number digits
|
||||
ndig=prec+1;
|
||||
if (prec<0)
|
||||
ndig=7;
|
||||
if (prec>22)
|
||||
ndig=23;
|
||||
|
||||
fstyle = 0; //exponent 'e'
|
||||
if (format == 'f' || format == 'F')
|
||||
fstyle = 1; //normal 'f'
|
||||
if (format=='g' || format=='G')
|
||||
fstyle=2;
|
||||
|
||||
ie = 0;
|
||||
/* if x negative, write minus and reverse */
|
||||
if ( x < 0)
|
||||
{
|
||||
*str++ = '-';
|
||||
x = -x;
|
||||
}
|
||||
|
||||
//if (x<0.0) then increment by 10 till betwen 1.0 and 10.0
|
||||
if (x!=0.0)
|
||||
{
|
||||
while (x < 1.0)
|
||||
{
|
||||
x =x* 10.0;
|
||||
ie--;
|
||||
}
|
||||
}
|
||||
|
||||
//if x>10 then let's shift it down
|
||||
while (x >= 10.0)
|
||||
{
|
||||
x = x*(1.0/10.0);
|
||||
ie++;
|
||||
}
|
||||
|
||||
if (ABS(ie)>MAX_MANTISA)
|
||||
{
|
||||
if (fstyle==1)
|
||||
{
|
||||
fstyle=0< |