summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cproject772
-rw-r--r--.project2
-rw-r--r--Makefile43
-rw-r--r--README1
-rw-r--r--df10ch_common.h108
-rw-r--r--df10ch_usb_proto.h232
-rw-r--r--kicad/10ch_pwm_ctrl-solder-side.ps (renamed from kicad/10ch_pwm_ctrl-Lötseite.ps)0
-rw-r--r--pwm_appl/Makefile212
-rw-r--r--pwm_appl/df10ch_pwm_appl.c (renamed from pwm_appl/10ch_pwm_appl.c)2000
-rw-r--r--pwm_boot/Makefile204
-rw-r--r--pwm_boot/df10ch_pwm_boot.c (renamed from pwm_boot/10ch_pwm_boot.c)950
-rw-r--r--usb_appl/Makefile218
-rw-r--r--usb_appl/df10ch_usb_appl.c (renamed from usb_appl/10ch_usb_appl.c)1672
-rw-r--r--usb_appl/usbconfig.h58
-rw-r--r--usb_boot/Makefile212
-rw-r--r--usb_boot/df10ch_usb_boot.c (renamed from usb_boot/10ch_usb_boot.c)646
-rw-r--r--usb_boot/usbconfig.h60
17 files changed, 4103 insertions, 3287 deletions
diff --git a/.cproject b/.cproject
index 927156a..846b2b0 100644
--- a/.cproject
+++ b/.cproject
@@ -3091,6 +3091,778 @@
</scannerConfigBuildInfo>
</storageModule>
</cconfiguration>
+<cconfiguration id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.2018598583">
+<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.2018598583" moduleId="org.eclipse.cdt.core.settings" name="Dist">
+<externalSettings/>
+<extensions>
+<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+<extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+</extensions>
+</storageModule>
+<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+<configuration artifactName="df10ch" buildArtefactType="de.innot.avreclipse.buildArtefactType.app" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=de.innot.avreclipse.buildArtefactType.app" description="Build distribution tar files" id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.2018598583" name="Dist" parent="de.innot.avreclipse.configuration.app.release">
+<folderInfo id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.2018598583." name="/" resourcePath="">
+<toolChain id="de.innot.avreclipse.toolchain.winavr.app.release.875382578" name="AVR-GCC Toolchain" superClass="de.innot.avreclipse.toolchain.winavr.app.release">
+<option id="de.innot.avreclipse.toolchain.options.toolchain.objcopy.flash.app.release.132335879" name="Generate HEX file for Flash memory" superClass="de.innot.avreclipse.toolchain.options.toolchain.objcopy.flash.app.release"/>
+<option id="de.innot.avreclipse.toolchain.options.toolchain.objcopy.eeprom.app.release.565459104" name="Generate HEX file for EEPROM" superClass="de.innot.avreclipse.toolchain.options.toolchain.objcopy.eeprom.app.release"/>
+<option id="de.innot.avreclipse.toolchain.options.toolchain.objdump.app.release.1881506787" name="Generate Extended Listing (Source + generated Assembler)" superClass="de.innot.avreclipse.toolchain.options.toolchain.objdump.app.release"/>
+<option id="de.innot.avreclipse.toolchain.options.toolchain.size.app.release.457394486" name="Print Size" superClass="de.innot.avreclipse.toolchain.options.toolchain.size.app.release"/>
+<option id="de.innot.avreclipse.toolchain.options.toolchain.avrdude.app.release.315986556" name="AVRDude" superClass="de.innot.avreclipse.toolchain.options.toolchain.avrdude.app.release"/>
+<targetPlatform id="de.innot.avreclipse.targetplatform.winavr.app.release.1595620872" name="AVR Cross-Target" superClass="de.innot.avreclipse.targetplatform.winavr.app.release"/>
+<builder autoBuildTarget="all" buildPath="${workspace_loc:/df10ch}" cleanBuildTarget="clean" enableAutoBuild="false" enableCleanBuild="true" enabledIncrementalBuild="true" id="de.innot.avreclipse.target.builder.winavr.app.release.1996008277" incrementalBuildTarget="all" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="AVR GNU Make Builder" parallelizationNumber="1" superClass="de.innot.avreclipse.target.builder.winavr.app.release"/>
+<tool id="de.innot.avreclipse.tool.assembler.winavr.app.release.745346613" name="AVR Assembler" superClass="de.innot.avreclipse.tool.assembler.winavr.app.release">
+<option id="de.innot.avreclipse.assembler.option.debug.level.1432869194" name="Generate Debugging Info" superClass="de.innot.avreclipse.assembler.option.debug.level" value="de.innot.avreclipse.assembler.option.debug.level.none" valueType="enumerated"/>
+<inputType id="de.innot.avreclipse.tool.assembler.input.1515729474" superClass="de.innot.avreclipse.tool.assembler.input"/>
+</tool>
+<tool id="de.innot.avreclipse.tool.compiler.winavr.app.release.350201050" name="AVR Compiler" superClass="de.innot.avreclipse.tool.compiler.winavr.app.release">
+<option id="de.innot.avreclipse.compiler.option.debug.level.1060171330" name="Generate Debugging Info" superClass="de.innot.avreclipse.compiler.option.debug.level" value="de.innot.avreclipse.compiler.option.debug.level.none" valueType="enumerated"/>
+<option id="de.innot.avreclipse.compiler.option.optimize.805226225" name="Optimization Level" superClass="de.innot.avreclipse.compiler.option.optimize" value="de.innot.avreclipse.compiler.optimize.size" valueType="enumerated"/>
+<inputType id="de.innot.avreclipse.compiler.winavr.input.877869148" name="C Source Files" superClass="de.innot.avreclipse.compiler.winavr.input"/>
+</tool>
+<tool id="de.innot.avreclipse.tool.cppcompiler.app.release.323050956" name="AVR C++ Compiler" superClass="de.innot.avreclipse.tool.cppcompiler.app.release">
+<option id="de.innot.avreclipse.cppcompiler.option.debug.level.1365895551" name="Generate Debugging Info" superClass="de.innot.avreclipse.cppcompiler.option.debug.level" value="de.innot.avreclipse.cppcompiler.option.debug.level.none" valueType="enumerated"/>
+<option id="de.innot.avreclipse.cppcompiler.option.optimize.719458694" name="Optimization Level" superClass="de.innot.avreclipse.cppcompiler.option.optimize" value="de.innot.avreclipse.cppcompiler.optimize.size" valueType="enumerated"/>
+</tool>
+<tool id="de.innot.avreclipse.tool.linker.winavr.app.release.1977202192" name="AVR C Linker" superClass="de.innot.avreclipse.tool.linker.winavr.app.release"/>
+<tool id="de.innot.avreclipse.tool.cpplinker.app.release.494808977" name="AVR C++ Linker" superClass="de.innot.avreclipse.tool.cpplinker.app.release"/>
+<tool id="de.innot.avreclipse.tool.archiver.winavr.base.1545747385" name="AVR Archiver" superClass="de.innot.avreclipse.tool.archiver.winavr.base"/>
+<tool id="de.innot.avreclipse.tool.objdump.winavr.app.release.1996800465" name="AVR Create Extended Listing" superClass="de.innot.avreclipse.tool.objdump.winavr.app.release"/>
+<tool id="de.innot.avreclipse.tool.objcopy.flash.winavr.app.release.1495936083" name="AVR Create Flash image" superClass="de.innot.avreclipse.tool.objcopy.flash.winavr.app.release"/>
+<tool id="de.innot.avreclipse.tool.objcopy.eeprom.winavr.app.release.1717982836" name="AVR Create EEPROM image" superClass="de.innot.avreclipse.tool.objcopy.eeprom.winavr.app.release"/>
+<tool id="de.innot.avreclipse.tool.size.winavr.app.release.1354479871" name="Print Size" superClass="de.innot.avreclipse.tool.size.winavr.app.release"/>
+<tool id="de.innot.avreclipse.tool.avrdude.app.release.2033338174" name="AVRDude" superClass="de.innot.avreclipse.tool.avrdude.app.release"/>
+</toolChain>
+</folderInfo>
+</configuration>
+</storageModule>
+<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+<storageModule moduleId="scannerConfiguration">
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="makefileGenerator">
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="avr-gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="avr-g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<scannerConfigBuildInfo instanceId="de.innot.avreclipse.configuration.app.release.179373882.1868963946.1825585251;de.innot.avreclipse.configuration.app.release.179373882.1868963946.1825585251.;de.innot.avreclipse.tool.compiler.winavr.app.release.1911000040;de.innot.avreclipse.compiler.winavr.input.164012582">
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC"/>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="makefileGenerator">
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="avr-gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="avr-g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+</scannerConfigBuildInfo>
+<scannerConfigBuildInfo instanceId="de.innot.avreclipse.configuration.app.release.179373882;de.innot.avreclipse.configuration.app.release.179373882.;de.innot.avreclipse.tool.compiler.winavr.app.release.711426924;de.innot.avreclipse.compiler.winavr.input.1256057594">
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC"/>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="makefileGenerator">
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="avr-gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="avr-g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+</scannerConfigBuildInfo>
+<scannerConfigBuildInfo instanceId="de.innot.avreclipse.configuration.app.release.179373882.1868963946.1825585251;de.innot.avreclipse.configuration.app.release.179373882.1868963946.1825585251.">
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC"/>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="makefileGenerator">
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="avr-gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="avr-g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+</scannerConfigBuildInfo>
+<scannerConfigBuildInfo instanceId="de.innot.avreclipse.configuration.app.release.179373882;de.innot.avreclipse.configuration.app.release.179373882.">
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC"/>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="makefileGenerator">
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="avr-gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="avr-g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+</scannerConfigBuildInfo>
+<scannerConfigBuildInfo instanceId="de.innot.avreclipse.configuration.app.release.179373882.1868963946;de.innot.avreclipse.configuration.app.release.179373882.1868963946.">
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC"/>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="makefileGenerator">
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="avr-gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="avr-g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+</scannerConfigBuildInfo>
+<scannerConfigBuildInfo instanceId="de.innot.avreclipse.configuration.app.release.179373882.1868963946;de.innot.avreclipse.configuration.app.release.179373882.1868963946.;de.innot.avreclipse.tool.compiler.winavr.app.release.1459664685;de.innot.avreclipse.compiler.winavr.input.1731965849">
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC"/>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="makefileGenerator">
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="avr-gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileCPP">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="avr-g++" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+</scannerConfigBuildInfo>
+</storageModule>
+</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="df10ch.de.innot.avreclipse.project.winavr.elf_2.1.0.410483182" name="AVR Cross Target Application" projectType="de.innot.avreclipse.project.winavr.elf_2.1.0"/>
diff --git a/.project b/.project
index ac8d1ad..2ae3639 100644
--- a/.project
+++ b/.project
@@ -36,7 +36,7 @@
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildLocation</key>
- <value>${workspace_loc:/df10ch/pwm_appl}</value>
+ <value>${workspace_loc:/df10ch}</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..77cc950
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2010 Andreas Auras
+#
+# This file is part of the DF10CH Atmolight controller project.
+#
+# DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# DF10CH Atmolight controller is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+#
+# ################################
+# Build all distribution tar files
+# ################################
+
+all: clean
+ mkdir -p dist
+ mkdir -p build/firmware
+ python setup.py sdist
+ (cd usb_boot && make)
+ (cd usb_appl && make)
+ (cd pwm_boot && make)
+ (cd pwm_appl && make)
+ cp usb_appl/df10ch_usb_appl.dff build/firmware/df10ch_usb_appl.dff
+ cp pwm_appl/df10ch_pwm_appl.dff build/firmware/df10ch_pwm_appl.dff
+ (cd build && tar cvzf ../dist/df10ch_firmware.tar.gz firmware)
+
+## Clean target
+.PHONY: clean
+clean:
+ (cd usb_boot && make clean)
+ (cd usb_appl && make clean)
+ (cd pwm_boot && make clean)
+ (cd pwm_appl && make clean)
+ rm -rf build MANIFEST
diff --git a/README b/README
index 963cb90..63a5f5f 100644
--- a/README
+++ b/README
@@ -19,6 +19,7 @@ http://www.obdev.at/vusb/
This directory contains the firmware, DF10CH setup program and KiCad files of hardware design:
README The file you are currently reading
+Makfile Makefile for generating everything
df10ch_setup_pkg/ Python modules needed by the DF10CH setup program
pwm_appl/ Application firmware for PWM-Prozessor
pwm_boot/ Bootloader firmware for PWM-Prozessor
diff --git a/df10ch_common.h b/df10ch_common.h
index a723cd3..dfd04c3 100644
--- a/df10ch_common.h
+++ b/df10ch_common.h
@@ -1,54 +1,54 @@
-/*
- * Copyright (C) 2010 Andreas Auras
- *
- * This file is part of the DF10CH Atmolight controller project.
- *
- * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * DF10CH Atmolight controller is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- */
-
-// ---
-// Useful utility defines.
-//
-#define NOMEMINIT __attribute__((section(".noinit")))
-#define NORETURN __attribute__((noreturn))
-#define NOINLINE __attribute__((noinline))
-#define INLINE __attribute__((inline))
-#define nop() __asm__ __volatile__ ("nop" ::)
-#define FIX_POINTER(_ptr) __asm__ __volatile__("" : "=b" (_ptr) : "0" (_ptr))
-#define SIGNATURE_DATA uint8_t __signature[3] __attribute__((section(".signature")))
-
-#define set_bit(var, bit) var |= _BV(bit)
-#define clear_bit(var, bit) var &= ~_BV(bit)
-
-typedef union
-{
- uint16_t word;
- uint8_t bytes[2];
-} bytes_word_t;
-
-
-// Definitions for usb <--> pwm controller communication
-#define BAUD 125000UL
-
-#define REQ_HEADER_SIZE 8
-
-#define PWMRQ_DEVICE_TO_HOST 0x80
-#define PWMRQ_ID_MASK 0x3F
-#define PWMRP_KEEP_ALIVE 0x80
-#define PWMRP_HAS_PAYLOAD 0x40
-
-
-
+/*
+ * Copyright (C) 2010 Andreas Auras
+ *
+ * This file is part of the DF10CH Atmolight controller project.
+ *
+ * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DF10CH Atmolight controller is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ */
+
+// ---
+// Useful utility defines.
+//
+#define NOMEMINIT __attribute__((section(".noinit")))
+#define NORETURN __attribute__((noreturn))
+#define NOINLINE __attribute__((noinline))
+#define INLINE __attribute__((inline))
+#define nop() __asm__ __volatile__ ("nop" ::)
+#define FIX_POINTER(_ptr) __asm__ __volatile__("" : "=b" (_ptr) : "0" (_ptr))
+#define SIGNATURE_DATA uint8_t __signature[3] __attribute__((section(".signature")))
+
+#define set_bit(var, bit) var |= _BV(bit)
+#define clear_bit(var, bit) var &= ~_BV(bit)
+
+typedef union
+{
+ uint16_t word;
+ uint8_t bytes[2];
+} bytes_word_t;
+
+
+// Definitions for usb <--> pwm controller communication
+#define BAUD 125000UL
+
+#define REQ_HEADER_SIZE 8
+
+#define PWMRQ_DEVICE_TO_HOST 0x80
+#define PWMRQ_ID_MASK 0x3F
+#define PWMRP_KEEP_ALIVE 0x80
+#define PWMRP_HAS_PAYLOAD 0x40
+
+
+
diff --git a/df10ch_usb_proto.h b/df10ch_usb_proto.h
index cb10912..bbda480 100644
--- a/df10ch_usb_proto.h
+++ b/df10ch_usb_proto.h
@@ -1,116 +1,116 @@
-/*
- * Copyright (C) 2010 Andreas Auras
- *
- * This file is part of the DF10CH Atmolight controller project.
- *
- * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * DF10CH Atmolight controller is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- */
-
-/* ---
- * Communication protocol related defines for DF10CH Atmolight Controller.
- */
-
-#define REQ_USB_START 0 // Start of usb controller requests
-#define REQ_USB_BL_START 64 // Start of usb controller boot loader requests
-#define REQ_PWM_START 128 // Start of pwm controller requests
-#define REQ_PWM_BL_START 192 // Start of pwm controller boot loader requests
-
-enum
-{
- // usb controller requests
- REQ_START_BOOTLOADER = REQ_USB_START, // start boot loader of usb controller
- REQ_READ_EE_DATA, // read eeprom data (wLength: number of bytes, wIndex: eeprom start address)
- REQ_WRITE_EE_DATA, // write eeprom data (wLength: number of bytes, wIndex: eeprom start address)
-
- REQ_STOP_PWM_CTRL, // stop PWM controller
- REQ_RESET_PWM_CTRL, // reset PWM controller
- REQ_BOOTLOADER_RESET_PWM_CTRL, // reset PWM controller and signal bootloader start
-
- REQ_SET_REPLY_TIMEOUT, // set reply timeout values (wValue: start timeout [ms], wIndex: timeout [ms])
-
- REQ_GET_REPLY_ERR_STATUS, // get reply error status (COMM_ERR_...)
-
- // usb controller boot loader requests
- BL_REQ_WRITE_PAGE = REQ_USB_BL_START, // write flash page
- BL_REQ_LEAVE_BOOT, // leave boot loader and start application
- BL_REQ_GET_PAGE_SIZE, // return flash page size of device
- BL_REQ_READ_FLASH, // return flash contents
-
- // pwm controller requests
- PWM_REQ_GET_VERSION = REQ_PWM_START, // Get firmware version (returns 1 byte)
- PWM_REQ_SET_BRIGHTNESS, // Set channel brightness values (wLenght: number of bytes, wIndex: start channel)
- PWM_REQ_SET_BRIGHTNESS_SYNCED, // Same as above but wait until buffer flip
- PWM_REQ_GET_BRIGHTNESS,
-
- PWM_REQ_SET_CHANNEL_MAP, // Set channel to port mapping (wLength: number of bytes, wIndex: start channel)
- PWM_REQ_GET_CHANNEL_MAP,
-
- PWM_REQ_SET_COMMON_PWM, // Set common pwm value (wValue.low: pwm value)
- PWM_REQ_GET_COMMON_PWM,
-
- PWM_REQ_STORE_SETUP, // Store actual calibration values
- PWM_REQ_RESET_SETUP, // Reset calibration values to default
-
- PWM_REQ_GET_REQUEST_ERR_STATUS, // Get request error status (COMM_ERR_...)
-
- PWM_REQ_GET_MAX_PWM, // Get maximum internal PWM value
-
- PWM_REQ_SET_PWM_FREQ, // Set pwm frequency (wValue: frequency [hz])
- PWM_REQ_GET_PWM_FREQ, // Get pwm frequency (returns word)
-
- PWM_REQ_ECHO_TEST, // Reply 8 byte header
-
- // pwm controller boot loader requests
- BL_PWM_REQ_WRITE_PAGE = REQ_PWM_BL_START, // write flash page
- BL_PWM_REQ_GET_PAGE_SIZE, // return flash page size of device
- BL_PWM_REQ_READ_FLASH, // return flash contents
- BL_PWM_REQ_GET_REQUEST_ERR_STATUS // Get request error status (COMM_ERR_...)
-};
-
-// Data payload related
-#define MAX_REQ_PAYLOAD_SIZE 128
-#define MAX_REPLY_PAYLOAD_SIZE 128
-
-// Error flag definition for communication error's of usb and pwm controller
-#define COMM_ERR_OVERRUN 0
-#define COMM_ERR_FRAME 1
-#define COMM_ERR_TIMEOUT 2
-#define COMM_ERR_START 3
-#define COMM_ERR_OVERFLOW 4
-#define COMM_ERR_CRC 5
-#define COMM_ERR_DUPLICATE 6
-#define COMM_ERR_DEBUG 7
-
-// Port channel mapping related
-#define NCHANNELS 30 // Number of supported Channels
-
-#define NPORTS 4
-#define PA_IDX 0
-#define PB_IDX 1
-#define PC_IDX 2
-#define PD_IDX 3
-
-#define CM_CODE(port, channel) (((channel) << 2) | (port))
-#define CM_CHANNEL(code) ((code) >> 2)
-#define CM_PORT(code) ((code) & 0x03)
-
-// PWM frequency related
-#define MIN_PWM_FREQ 50
-#define MAX_PWM_FREQ 400
-
-// PWM controller version request related
-#define PWM_VERS_APPL 0 // Is application firmware
-#define PWM_VERS_BOOT 1 // Is bootloader firmware
+/*
+ * Copyright (C) 2010 Andreas Auras
+ *
+ * This file is part of the DF10CH Atmolight controller project.
+ *
+ * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DF10CH Atmolight controller is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ */
+
+/* ---
+ * Communication protocol related defines for DF10CH Atmolight Controller.
+ */
+
+#define REQ_USB_START 0 // Start of usb controller requests
+#define REQ_USB_BL_START 64 // Start of usb controller boot loader requests
+#define REQ_PWM_START 128 // Start of pwm controller requests
+#define REQ_PWM_BL_START 192 // Start of pwm controller boot loader requests
+
+enum
+{
+ // usb controller requests
+ REQ_START_BOOTLOADER = REQ_USB_START, // start boot loader of usb controller
+ REQ_READ_EE_DATA, // read eeprom data (wLength: number of bytes, wIndex: eeprom start address)
+ REQ_WRITE_EE_DATA, // write eeprom data (wLength: number of bytes, wIndex: eeprom start address)
+
+ REQ_STOP_PWM_CTRL, // stop PWM controller
+ REQ_RESET_PWM_CTRL, // reset PWM controller
+ REQ_BOOTLOADER_RESET_PWM_CTRL, // reset PWM controller and signal bootloader start
+
+ REQ_SET_REPLY_TIMEOUT, // set reply timeout values (wValue: start timeout [ms], wIndex: timeout [ms])
+
+ REQ_GET_REPLY_ERR_STATUS, // get reply error status (COMM_ERR_...)
+
+ // usb controller boot loader requests
+ BL_REQ_WRITE_PAGE = REQ_USB_BL_START, // write flash page
+ BL_REQ_LEAVE_BOOT, // leave boot loader and start application
+ BL_REQ_GET_PAGE_SIZE, // return flash page size of device
+ BL_REQ_READ_FLASH, // return flash contents
+
+ // pwm controller requests
+ PWM_REQ_GET_VERSION = REQ_PWM_START, // Get firmware version (returns 1 byte)
+ PWM_REQ_SET_BRIGHTNESS, // Set channel brightness values (wLenght: number of bytes, wIndex: start channel)
+ PWM_REQ_SET_BRIGHTNESS_SYNCED, // Same as above but wait until buffer flip
+ PWM_REQ_GET_BRIGHTNESS,
+
+ PWM_REQ_SET_CHANNEL_MAP, // Set channel to port mapping (wLength: number of bytes, wIndex: start channel)
+ PWM_REQ_GET_CHANNEL_MAP,
+
+ PWM_REQ_SET_COMMON_PWM, // Set common pwm value (wValue.low: pwm value)
+ PWM_REQ_GET_COMMON_PWM,
+
+ PWM_REQ_STORE_SETUP, // Store actual calibration values
+ PWM_REQ_RESET_SETUP, // Reset calibration values to default
+
+ PWM_REQ_GET_REQUEST_ERR_STATUS, // Get request error status (COMM_ERR_...)
+
+ PWM_REQ_GET_MAX_PWM, // Get maximum internal PWM value
+
+ PWM_REQ_SET_PWM_FREQ, // Set pwm frequency (wValue: frequency [hz])
+ PWM_REQ_GET_PWM_FREQ, // Get pwm frequency (returns word)
+
+ PWM_REQ_ECHO_TEST, // Reply 8 byte header
+
+ // pwm controller boot loader requests
+ BL_PWM_REQ_WRITE_PAGE = REQ_PWM_BL_START, // write flash page
+ BL_PWM_REQ_GET_PAGE_SIZE, // return flash page size of device
+ BL_PWM_REQ_READ_FLASH, // return flash contents
+ BL_PWM_REQ_GET_REQUEST_ERR_STATUS // Get request error status (COMM_ERR_...)
+};
+
+// Data payload related
+#define MAX_REQ_PAYLOAD_SIZE 128
+#define MAX_REPLY_PAYLOAD_SIZE 128
+
+// Error flag definition for communication error's of usb and pwm controller
+#define COMM_ERR_OVERRUN 0
+#define COMM_ERR_FRAME 1
+#define COMM_ERR_TIMEOUT 2
+#define COMM_ERR_START 3
+#define COMM_ERR_OVERFLOW 4
+#define COMM_ERR_CRC 5
+#define COMM_ERR_DUPLICATE 6
+#define COMM_ERR_DEBUG 7
+
+// Port channel mapping related
+#define NCHANNELS 30 // Number of supported Channels
+
+#define NPORTS 4
+#define PA_IDX 0
+#define PB_IDX 1
+#define PC_IDX 2
+#define PD_IDX 3
+
+#define CM_CODE(port, channel) (((channel) << 2) | (port))
+#define CM_CHANNEL(code) ((code) >> 2)
+#define CM_PORT(code) ((code) & 0x03)
+
+// PWM frequency related
+#define MIN_PWM_FREQ 50
+#define MAX_PWM_FREQ 400
+
+// PWM controller version request related
+#define PWM_VERS_APPL 0 // Is application firmware
+#define PWM_VERS_BOOT 1 // Is bootloader firmware
diff --git a/kicad/10ch_pwm_ctrl-Lötseite.ps b/kicad/10ch_pwm_ctrl-solder-side.ps
index e27450d..e27450d 100644
--- a/kicad/10ch_pwm_ctrl-Lötseite.ps
+++ b/kicad/10ch_pwm_ctrl-solder-side.ps
diff --git a/pwm_appl/Makefile b/pwm_appl/Makefile
index d9faba8..4824c29 100644
--- a/pwm_appl/Makefile
+++ b/pwm_appl/Makefile
@@ -1,106 +1,106 @@
-#
-# Copyright (C) 2010 Andreas Auras
-#
-# This file is part of the DF10CH Atmolight controller project.
-#
-# DF10CH Atmolight controller is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# DF10CH Atmolight controller is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-#
-#
-###############################################################################
-# Makefile for the application firmware of PWM processor
-###############################################################################
-
-## General Flags
-PROJECT = 10ch_pwm_appl
-MCU = atmega162
-TARGET = 10ch_pwm_appl.elf
-CC = avr-gcc
-AVRDUDE ?= avrdude -c stk500v2 -P avrdoper
-F_CPU ?= 16000000UL
-FIRMWARE_VERSION ?= 1
-
-## Options common to compile, link and assembly rules
-COMMON = -mmcu=$(MCU)
-
-## Compile options common for all C compilation units.
-CFLAGS = $(COMMON)
-CFLAGS += -Wall -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
-CFLAGS += -DF_CPU=$(F_CPU) -DFIRMWARE_VERSION=$(FIRMWARE_VERSION)
-
-## Assembly specific flags
-ASMFLAGS = $(COMMON)
-ASMFLAGS += $(CFLAGS)
-ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
-
-## Linker flags
-LDFLAGS = $(COMMON)
-LDFLAGS += -Wl,-Map=10ch_pwm_appl.map
-LDFLAGS += -Wl,-section-start=.eeprom=0x810001
-
-
-## Intel Hex file production flags
-HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
-
-HEX_EEPROM_FLAGS = -j .eeprom
-HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
-HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0x01 --no-change-warnings
-
-## Include Directories
-INCLUDES = -I. -I..
-
-## Objects that must be built in order to link
-OBJECTS = 10ch_pwm_appl.o
-
-## Objects explicitly added by the user
-LINKONLYOBJECTS =
-
-## Build
-all: $(TARGET) 10ch_pwm_appl.dff 10ch_pwm_appl.lss size
-
-10ch_pwm_appl.dff: 10ch_pwm_appl.hex
- echo "@DF10CH-PWM" $(FIRMWARE_VERSION) > $@
- cat 10ch_pwm_appl.hex >> $@
-
-prog: flash
- $(AVRDUDE) -p $(MCU) -u -Ulfuse:w:0xc0:m -Uhfuse:w:0xc9:m -Uefuse:w:0xf9:m -Ulock:w:0xef:m
-
-flash: 10ch_pwm_appl.hex
- $(AVRDUDE) -p $(MCU) -U flash:w:10ch_pwm_appl.hex:i
-
-## Compile
-10ch_pwm_appl.o: 10ch_pwm_appl.c ../df10ch_usb_proto.h ../df10ch_common.h
- $(CC) $(INCLUDES) $(CFLAGS) -c $<
-
-##Link
-$(TARGET): $(OBJECTS)
- $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
-
-%.hex: $(TARGET)
- avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
-
-%.eep: $(TARGET)
- -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
-
-%.lss: $(TARGET)
- avr-objdump -h -S $< > $@
-
-size: ${TARGET}
- @echo
- @avr-size -C --mcu=${MCU} ${TARGET}
-
-## Clean target
-.PHONY: clean
-clean:
- -rm -rf $(OBJECTS) 10ch_pwm_appl.elf 10ch_pwm_appl.dff 10ch_pwm_appl.hex 10ch_pwm_appl.eep 10ch_pwm_appl.lss 10ch_pwm_appl.map
+#
+# Copyright (C) 2010 Andreas Auras
+#
+# This file is part of the DF10CH Atmolight controller project.
+#
+# DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# DF10CH Atmolight controller is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+#
+#
+###############################################################################
+# Makefile for the application firmware of PWM processor
+###############################################################################
+
+## General Flags
+PROJECT = df10ch_pwm_appl
+MCU = atmega162
+TARGET = df10ch_pwm_appl.elf
+CC = avr-gcc
+AVRDUDE ?= avrdude -c stk500v2 -P avrdoper
+F_CPU ?= 16000000UL
+FIRMWARE_VERSION ?= 1
+
+## Options common to compile, link and assembly rules
+COMMON = -mmcu=$(MCU)
+
+## Compile options common for all C compilation units.
+CFLAGS = $(COMMON)
+CFLAGS += -Wall -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -DF_CPU=$(F_CPU) -DFIRMWARE_VERSION=$(FIRMWARE_VERSION)
+
+## Assembly specific flags
+ASMFLAGS = $(COMMON)
+ASMFLAGS += $(CFLAGS)
+ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
+
+## Linker flags
+LDFLAGS = $(COMMON)
+LDFLAGS += -Wl,-Map=df10ch_pwm_appl.map
+LDFLAGS += -Wl,-section-start=.eeprom=0x810001
+
+
+## Intel Hex file production flags
+HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
+
+HEX_EEPROM_FLAGS = -j .eeprom
+HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
+HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0x01 --no-change-warnings
+
+## Include Directories
+INCLUDES = -I. -I..
+
+## Objects that must be built in order to link
+OBJECTS = df10ch_pwm_appl.o
+
+## Objects explicitly added by the user
+LINKONLYOBJECTS =
+
+## Build
+all: $(TARGET) df10ch_pwm_appl.dff df10ch_pwm_appl.lss size
+
+df10ch_pwm_appl.dff: df10ch_pwm_appl.hex
+ echo "@DF10CH-PWM" $(FIRMWARE_VERSION) > $@
+ cat df10ch_pwm_appl.hex >> $@
+
+prog: flash
+ $(AVRDUDE) -p $(MCU) -u -Ulfuse:w:0xc0:m -Uhfuse:w:0xc9:m -Uefuse:w:0xf9:m -Ulock:w:0xef:m
+
+flash: df10ch_pwm_appl.hex
+ $(AVRDUDE) -p $(MCU) -U flash:w:df10ch_pwm_appl.hex:i
+
+## Compile
+df10ch_pwm_appl.o: df10ch_pwm_appl.c ../df10ch_usb_proto.h ../df10ch_common.h
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<
+
+##Link
+$(TARGET): $(OBJECTS)
+ $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
+
+%.hex: $(TARGET)
+ avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
+
+%.eep: $(TARGET)
+ -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
+
+%.lss: $(TARGET)
+ avr-objdump -h -S $< > $@
+
+size: ${TARGET}
+ @echo
+ @avr-size -C --mcu=${MCU} ${TARGET}
+
+## Clean target
+.PHONY: clean
+clean:
+ -rm -rf $(OBJECTS) df10ch_pwm_appl.elf df10ch_pwm_appl.dff df10ch_pwm_appl.hex df10ch_pwm_appl.eep df10ch_pwm_appl.lss df10ch_pwm_appl.map
diff --git a/pwm_appl/10ch_pwm_appl.c b/pwm_appl/df10ch_pwm_appl.c
index afb4350..f31240a 100644
--- a/pwm_appl/10ch_pwm_appl.c
+++ b/pwm_appl/df10ch_pwm_appl.c
@@ -1,1000 +1,1000 @@
-/*
- * Copyright (C) 2010 Andreas Auras
- *
- * This file is part of the DF10CH Atmolight controller project.
- *
- * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * DF10CH Atmolight controller is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- */
-
-// ======================================================================
-// Application firmware for PWM processor.
-//
-
-#include <stdint.h>
-#include <string.h>
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <avr/wdt.h>
-#include <avr/pgmspace.h>
-#include <avr/eeprom.h>
-
-#include "../df10ch_common.h"
-#include "../df10ch_usb_proto.h"
-
-
-// ---
-// Fuse-Bit settings for the flash programmer (ATmega 162):
-//
-// M161C=1
-// BODLEVEL2=1
-// BODLEVEL1=0
-// BODLEVEL0=0
-//
-// OCDEN=1
-// JTAGEN=1
-// SPIEN=0
-// WDTON=0
-// EESAVE=1
-// BOOTSZ1=0
-// BOOTSZ0=0
-// BOOTRST=1
-//
-// CKDIV8=1
-// CKOUT=1
-// SUT1=0
-// SUT0=1
-// CKSEL3=1
-// CKSEL2=1
-// CKSEL1=1
-// CKSEL0=1
-//
-// Memory-Lock Bits:
-// BLB12=1, BLB11=0, BLB02=1, BLB01=1, LB2=1, LB1=1
-//
-FUSES =
-{
- .low = (FUSE_SUT1),
- .high = (FUSE_SPIEN & FUSE_WDTON & FUSE_BOOTSZ1 & FUSE_BOOTSZ0),
- .extended = (FUSE_BODLEVEL1 & FUSE_BODLEVEL0),
-};
-LOCKBITS = (LB_MODE_1 & BLB0_MODE_1 & BLB1_MODE_2);
-//SIGNATURE_DATA = { SIGNATURE_2, SIGNATURE_1, SIGNATURE_0 } ;
-
-
-// ---
-// System clock related.
-// System clock is implemented with hardware timer 0
-//
-#define SYS_HWPRESCALE 64 // Hardware Prescaler
-#define SYS_PRESCALER 256 // Timer Prescaler
-
- // useconds <-> timer ticks conversation
-#define US2TICKS(t) ((uint16_t)((double)(t) * (double)F_CPU / (1000000.0 * (double)SYS_HWPRESCALE * (double)SYS_PRESCALER) + 0.5))
-#define TICKS2US(t) (((t) / (F_CPU / (1000000UL * SYS_HWPRESCALE * SYS_PRESCALER))))
-
-static uint16_t sys_clock;
-
-
-// ---
-// Keep alive reply related
-//
-#define MIN_KEEP_ALIVE_PAUSE US2TICKS(15000)
-
-static uint16_t last_keep_alive;
-
-
-// ---
-// Request parser related variables
-//
-typedef union
-{
- uint8_t bytes[REQ_HEADER_SIZE];
- struct
- {
- uint8_t request_type;
- uint8_t request;
- bytes_word_t value;
- bytes_word_t index;
- bytes_word_t length;
- };
-} pwm_request_t;
-
-static pwm_request_t actual_req;
-static uint8_t header_pos;
-static uint8_t payload_pos;
-static uint8_t payload_count;
-
-
-// ---
-// PWM generation related
-//
-#define DEF_F_PWM 100UL // Default PWM cycle frequency in Hz
-#define PWM_HWPRESCALE 16 // Hardware timer prescale
-#define PWM_PRESCALE 9 // require: (PWM_PRESCALE * PWM_HWPRESCALE) > (size of ISR for timer )
-
-#define DEF_MAX_PWM (F_CPU / (PWM_HWPRESCALE * PWM_PRESCALE * DEF_F_PWM) - 1) // Maximum internal resolution for pwm
-
-#define PWM_STEP_PAGE_SIZE (NCHANNELS + 2) // possible maximum steps: NCHANNELS + Pause + End of Table
-
-typedef struct pwm_step_s {
- uint8_t port_val[NPORTS]; // Values for Port A,B,C,D
- uint16_t timer_val; // Timer compare value
- struct pwm_step_s *next_step; // Pointer to next list entry
- } pwm_step_t;
-
- // One actual and one shadow page
-static pwm_step_t pwm_step_page1[PWM_STEP_PAGE_SIZE] NOMEMINIT;
-static pwm_step_t pwm_step_page2[PWM_STEP_PAGE_SIZE] NOMEMINIT;
-static pwm_step_t *shadow_pwm_page NOMEMINIT;
-static pwm_step_t *active_pwm_page NOMEMINIT;
-static pwm_step_t * volatile actual_pwm_step NOMEMINIT;
-static uint8_t update_pwm_page NOMEMINIT;
-
-
-// ---
-// RX buffer related variables
-//
-#define RXBUF_SIZE (REQ_HEADER_SIZE + MAX_REQ_PAYLOAD_SIZE + 1)
-#if RXBUF_SIZE == 256
-#define CHECK_RXBUF_END(pos)
-#else
-#define CHECK_RXBUF_END(pos) if ((pos) == RXBUF_SIZE) (pos) = 0
-#endif
-
-static uint8_t volatile rxrpos, rxwpos, rxspos, rx_err_status;
-static uint8_t rxbuf[RXBUF_SIZE] NOMEMINIT;
-
-
-// ---
-// Actual brightness values for each channel
-//
-static uint16_t bright_vals[NCHANNELS];
-
-
-// ---
-// Port channel mapping related variables
-//
-typedef struct { uint8_t code, port_bits; } channel_map_t;
-
-static channel_map_t default_channel_map[NCHANNELS] PROGMEM = {
- // J3
- { CM_CODE(PA_IDX, 0), _BV(2) },
- { CM_CODE(PA_IDX, 1), _BV(1) },
- { CM_CODE(PA_IDX, 2), _BV(0) },
-
- // J4
- { CM_CODE(PA_IDX, 3), _BV(5) },
- { CM_CODE(PA_IDX, 4), _BV(4) },
- { CM_CODE(PA_IDX, 5), _BV(3) },
-
- // J5
- { CM_CODE(PC_IDX, 6), _BV(7) },
- { CM_CODE(PA_IDX, 7), _BV(7) },
- { CM_CODE(PA_IDX, 8), _BV(6) },
-
- // J6
- { CM_CODE(PC_IDX, 9), _BV(4) },
- { CM_CODE(PC_IDX, 10), _BV(5) },
- { CM_CODE(PC_IDX, 11), _BV(6) },
-
- // J7
- { CM_CODE(PC_IDX, 12), _BV(1) },
- { CM_CODE(PC_IDX, 13), _BV(2) },
- { CM_CODE(PC_IDX, 14), _BV(3) },
-
- // J8
- { CM_CODE(PD_IDX, 15), _BV(6) },
- { CM_CODE(PD_IDX, 16), _BV(7) },
- { CM_CODE(PC_IDX, 17), _BV(0) },
-
- // J9
- { CM_CODE(PD_IDX, 18), _BV(3) },
- { CM_CODE(PD_IDX, 19), _BV(4) },
- { CM_CODE(PD_IDX, 20), _BV(5) },
-
- // J10
- { CM_CODE(PB_IDX, 21), _BV(6) },
- { CM_CODE(PB_IDX, 22), _BV(7) },
- { CM_CODE(PD_IDX, 23), _BV(2) },
-
- // J11
- { CM_CODE(PB_IDX, 24), _BV(3) },
- { CM_CODE(PB_IDX, 25), _BV(4) },
- { CM_CODE(PB_IDX, 26), _BV(5) },
-
- // J12
- { CM_CODE(PB_IDX, 27), _BV(0) },
- { CM_CODE(PB_IDX, 28), _BV(1) },
- { CM_CODE(PB_IDX, 29), _BV(2) }
-
- };
-
-
-// ---
-// Setup values that will be stored to eeprom.
-//
-
-typedef struct {
- uint16_t max_pwm;
- uint8_t common_pwm;
- channel_map_t channel_map[NCHANNELS];
- } setup_t;
-
-setup_t setup NOMEMINIT;
-
-#define EE_VALID_MARK 0xA5
-static uint8_t ee_valid EEMEM; // If eeprom content is valid this byte is EE_VALID_MARK
-static setup_t ee_setup EEMEM;
-
-
-// Status LED related
-#define STATUS_LED_PORT PORTE
-#define STATUS_LED_BIT 1
-
-// Common PWM channel related
-#define MAX_COMMON_PWM 255
-#define DEF_COMMON_PWM 255 // Default common pwm value
-
-#define COMMON_PWM_PORT PORTE
-#define COMMON_PWM_BIT 2
-
-
-// Input pin for enable/disable of bootloader
-#define BL_SENSE_PIN PINE
-#define BL_SENSE_BIT 0
-
-
-// ---
-// Definition of port direction and initial values.
-//
-#define PA_DDR 0xFF
-#define PA_INIT 0x00
-
-#define PB_DDR 0xFF
-#define PB_INIT 0x00
-
-#define PC_DDR 0xFF
-#define PC_INIT 0x00
-
-#define PD_DDR (_BV(1) | _BV(2) | _BV(3) | _BV(4) | _BV(5) | _BV(6) | _BV(7))
-#define PD_INIT _BV(1)
-
-#define PE_DDR (_BV(STATUS_LED_BIT) | _BV(COMMON_PWM_BIT))
-#define PE_INIT _BV(BL_SENSE_BIT)
-
-
-// ---
-// Catchup all unused interrupts and wait until watchdog resets device.
-// This ISR is only for unexpected interrupts.
-//
-ISR(BADISR_vect)
-{
- for (;;);
-}
-
-
-// ---
-// ISR for PWM generation.
-//
-ISR(TIMER3_COMPA_vect)
-{
- pwm_step_t *p = actual_pwm_step;
-
- // Optimized OCR3A = p->timer_val
- OCR3AH = ((uint8_t *)&(p->timer_val))[1];
- OCR3AL = ((uint8_t *)&(p->timer_val))[0];
-
- PORTA = p->port_val[PA_IDX];
- PORTB = p->port_val[PB_IDX];
- PORTC = p->port_val[PC_IDX];
- PORTD = p->port_val[PD_IDX];
-
- // Optimized actual_pwm_step = p->next_step
- ((uint8_t *)&(actual_pwm_step))[0] = ((uint8_t *)&(p->next_step))[0];
- ((uint8_t *)&(actual_pwm_step))[1] = ((uint8_t *)&(p->next_step))[1];
-}
-
-
-// ---
-// ISR for receiving data.
-//
-ISR(USART0_RXC_vect)
-{
- clear_bit(UCSR0B, RXCIE0);
- sei();
-
- do
- {
- uint8_t i = rxwpos;
- uint8_t p = i + 1;
- CHECK_RXBUF_END(p);
-
- if (bit_is_set(UCSR0A, FE0))
- set_bit(rx_err_status, COMM_ERR_FRAME);
- else if (bit_is_set(UCSR0A, DOR0))
- set_bit(rx_err_status, COMM_ERR_OVERRUN);
- else if (p == rxrpos)
- set_bit(rx_err_status, COMM_ERR_OVERFLOW);
- else
- {
- if (bit_is_set(UCSR0B, RXB80))
- rxspos = i; // save start of request message
- rxwpos = p; // set data valid
- }
- rxbuf[i] = UDR0; // read data
- }
- while (bit_is_set(UCSR0A, RXC0));
-
- cli();
- set_bit(UCSR0B, RXCIE0);
-}
-
-
-// ---
-// Processing while waiting for a event.
-//
-static void background_processing(void)
-{
- wdt_reset();
-
- // count system clock
- if (bit_is_set(TIFR, TOV0))
- {
- ++sys_clock;
- TIFR = _BV(TOV0);
- }
-}
-
-
-// ---
-// Put data into transmit buffer.
-//
-static void send_reply_data(uint8_t c)
-{
- // Wait until transmit buffer free
- while (bit_is_clear(UCSR0A, UDRE0))
- background_processing();
-
- UDR0 = c;
-}
-
-
-// ---
-// Send reply start.
-//
-static void send_reply_start(uint8_t len)
-{
- // Wait until transmit buffer free
- while (bit_is_clear(UCSR0A, UDRE0))
- background_processing();
-
- uint8_t id = actual_req.request_type & PWMRQ_ID_MASK;
- if (len)
- id |= PWMRP_HAS_PAYLOAD;
-
- set_bit(UCSR0B, TXB80); // Set 9th bit for start of reply
- UDR0 = id; // Send reply id
- clear_bit(UCSR0B, TXB80);
-
- if (len)
- send_reply_data(len); // Send reply length
-
- last_keep_alive = sys_clock;
-}
-
-
-// ---
-// Send keep alive reply.
-//
-static void send_keep_alive_reply(void)
-{
- background_processing();
- if ((sys_clock - last_keep_alive) > MIN_KEEP_ALIVE_PAUSE)
- {
- // Wait until transmit buffer free
- while (bit_is_clear(UCSR0A, UDRE0))
- background_processing();
-
- set_bit(UCSR0B, TXB80); // Set 9th bit for start of reply
- UDR0 = PWMRP_KEEP_ALIVE; // Send keep alive ID
- clear_bit(UCSR0B, TXB80);
-
- last_keep_alive = sys_clock;
- }
-}
-
-
-// ---
-// Set on time 'v' for port bits 'pb' of port 'pi' in shadow pwm page.
-//
-static void set_channel(uint8_t pi, uint8_t pb, uint16_t v)
-{
- pwm_step_t *p = shadow_pwm_page;
- pwm_step_t *l, *n;
-
- while (p->timer_val && v >= p->timer_val)
- {
- p->port_val[pi] |= pb;
- if (p->timer_val == v)
- return;
- l = p;
- p = l->next_step;
- }
-
- if (p->timer_val)
- {
- n = p;
- do
- {
- l = n;
- n = l->next_step;
- }
- while (n->timer_val);
-
- l->next_step = n->next_step;
- n[0] = p[0];
- p->next_step = n;
- }
- else
- {
- p->port_val[PA_IDX] = PA_INIT;
- p->port_val[PB_IDX] = PB_INIT;
- p->port_val[PC_IDX] = PC_INIT;
- p->port_val[PD_IDX] = PD_INIT;
- }
- p->timer_val = v;
- p->port_val[pi] |= pb;
-}
-
-
-// ---
-// Init shadow pwm page.
-//
-static uint8_t init_pwm_page(uint8_t do_init)
-{
- pwm_step_t *p = shadow_pwm_page;
- pwm_step_t *e = p + PWM_STEP_PAGE_SIZE;
-
- // Check if shadow page is deactivated
- cli();
- pwm_step_t *a = actual_pwm_step;
- sei();
- if (a >= p && a < e)
- return(0); // Shadow page is still active
-
- if (do_init)
- {
- while (p < e)
- {
- p->timer_val = 0;
- a = p + 1;
- p->next_step = a;
- p = a;
- }
- }
-
- return(1);
-}
-
-
-// ---
-// Finalize shadow pwm page and activate it.
-//
-static void activate_pwm_page(void)
-{
- pwm_step_t *p = shadow_pwm_page;
- pwm_step_t *l;
- uint16_t t = 0;
-
- // Calculate time steps
- while (p->timer_val)
- {
- uint16_t ts = p->timer_val - t;
- t = p->timer_val;
- p->timer_val = ts * PWM_PRESCALE;
- l = p;
- p = l->next_step;
- }
-
- // Add pause entry to reach a full cycle
- t = setup.max_pwm - t;
- if (t)
- {
- p->port_val[PA_IDX] = PA_INIT;
- p->port_val[PB_IDX] = PB_INIT;
- p->port_val[PC_IDX] = PC_INIT;
- p->port_val[PD_IDX] = PD_INIT;
- p->timer_val = t * PWM_PRESCALE;
- l = p;
- }
-
- // Make list cyclic
- p = shadow_pwm_page;
- l->next_step = p;
-
- // Install Link to shadow page in active page
- p = active_pwm_page;
- active_pwm_page = l;
- l = shadow_pwm_page;
- cli();
- p->next_step = l;
- sei();
-
- // Swap shadow page
- if (l == pwm_step_page1)
- p = pwm_step_page2;
- else
- p = pwm_step_page1;
- shadow_pwm_page = p;
-
- update_pwm_page = 0;
-}
-
-
-// ---
-// Calculate pwm page.
-//
-static void calc_pwm_page(void)
-{
- uint8_t c;
-
- c = NCHANNELS;
- while (c--)
- {
- uint8_t port_bits = setup.channel_map[c].port_bits;
- if (port_bits)
- {
- uint8_t code = setup.channel_map[c].code;
- uint16_t v = bright_vals[CM_CHANNEL(code)];
- if (v)
- {
- if (v > setup.max_pwm)
- v = setup.max_pwm;
- set_channel(CM_PORT(code), port_bits, v);
- }
- }
- }
-}
-
-
-// ---
-// Initialize pwm step table and start pwm timer.
-//
-static void init_pwm_step_tab(void)
-{
- // Set up pwm step table
- shadow_pwm_page = pwm_step_page1;
- active_pwm_page = pwm_step_page2;
- actual_pwm_step = pwm_step_page2;
- init_pwm_page(1);
- calc_pwm_page();
- activate_pwm_page();
- actual_pwm_step = active_pwm_page->next_step;
-
- TCNT3 = 0; // Reset timer counter
- OCR3A = PWM_PRESCALE; // Initial startup step
- TCCR3B = _BV(CS32) | _BV(CS31) | _BV(WGM32); // Start timer, Prescaler 16, CTC mode
-}
-
-
-// ---
-// Set default setup values.
-//
-static void init_setup_values(void)
-{
- setup.max_pwm = DEF_MAX_PWM;
- setup.common_pwm = DEF_COMMON_PWM;
-
- memcpy_P(&setup.channel_map, &default_channel_map, sizeof(setup.channel_map));
-}
-
-
-// ---
-// Read setup values from eeprom.
-//
-static void read_setup_values(void)
-{
- if (eeprom_read_byte(&ee_valid) == EE_VALID_MARK)
- eeprom_read_block(&setup, &ee_setup, sizeof(setup));
- else
- init_setup_values();
-}
-
-
-// ---
-// Store actual setup values into eeprom.
-//
-static void store_setup_values(void)
-{
- uint8_t i = sizeof(setup);
- uint8_t *src = (uint8_t *) (&setup);
- uint8_t *dst = (uint8_t *) (&ee_setup);
- while (i--)
- {
- if (eeprom_read_byte(dst) != *src)
- {
- eeprom_write_byte(dst, *src);
- while (!eeprom_is_ready())
- send_keep_alive_reply();
- }
- ++src;
- ++dst;
- }
- if (eeprom_read_byte(&ee_valid) != EE_VALID_MARK)
- {
- eeprom_write_byte(&ee_valid, EE_VALID_MARK);
- while (!eeprom_is_ready())
- send_keep_alive_reply();
- }
-}
-
-
-// ---
-// Set common pwm value.
-//
-static void set_common_pwm(void)
-{
- uint8_t v = setup.common_pwm;
-
- if (v == 0 || v == 255)
- {
- if (v)
- set_bit(COMMON_PWM_PORT, COMMON_PWM_BIT);
- else
- clear_bit(COMMON_PWM_PORT, COMMON_PWM_BIT);
- clear_bit(TCCR1A, COM1B1); // Normal port output
- }
- else
- {
- OCR1B = v;
- clear_bit(COMMON_PWM_PORT, COMMON_PWM_BIT);
- set_bit(TCCR1A, COM1B1); // pwm port output
- }
-}
-
-
-// ---
-// Send reply packet from ram memory.
-//
-static void send_reply_mem(uint8_t *data, uint16_t len)
-{
- pwm_request_t *r = &actual_req;
- FIX_POINTER(r);
-
- uint16_t p = r->index.word << 1;
- uint16_t n = r->length.word;
- if (p >= len)
- n = 0;
- if (n && (p + n) > len)
- n = len - p;
- if (n > MAX_REPLY_PAYLOAD_SIZE)
- n = 0; // Send nothing!
-
- send_reply_start(n);
-
- data += p;
- while (n)
- {
- send_reply_data(*data++);
- --n;
- }
-}
-
-
-// ---
-// Process set brightness value.
-//
-static void req_set_brightness(void)
-{
- pwm_request_t *r = &actual_req;
- FIX_POINTER(r);
-
- uint8_t p = payload_pos;
- uint16_t c = r->index.word;
- uint16_t len = r->length.word >> 1;
- while (len && c < NCHANNELS)
- {
- bytes_word_t v;
- v.bytes[0] = rxbuf[p++];
- CHECK_RXBUF_END(p);
- v.bytes[1] = rxbuf[p++];
- CHECK_RXBUF_END(p);
-
- if (bright_vals[c] != v.word)
- {
- bright_vals[c] = v.word;
- update_pwm_page = 1;
- }
-
- ++c;
- --len;
- }
-}
-
-
-// ---
-// Process set channel map request.
-//
-static void req_set_channel_map(void)
-{
- pwm_request_t *r = &actual_req;
- FIX_POINTER(r);
-
- uint8_t p = payload_pos;
- uint16_t c = r->index.word;
- uint16_t len = r->length.word >> 1;
- while (len && c < NCHANNELS)
- {
- uint8_t v = rxbuf[p++];
- CHECK_RXBUF_END(p);
-
- if (CM_CHANNEL(v) >= NCHANNELS)
- v = NCHANNELS - 1;
-
- if (setup.channel_map[c].code != v)
- {
- setup.channel_map[c].code = v;
- update_pwm_page = 1;
- }
-
- v = rxbuf[p++];
- CHECK_RXBUF_END(p);
-
- if (setup.channel_map[c].port_bits != v)
- {
- setup.channel_map[c].port_bits = v;
- update_pwm_page = 1;
- }
-
- ++c;
- --len;
- }
-}
-
-
-// ---
-// Process received request.
-//
-static void process_request(void)
-{
- pwm_request_t *r = &actual_req;
- FIX_POINTER(r);
-
- uint8_t req = r->request;
-
- if (req == PWM_REQ_SET_BRIGHTNESS)
- req_set_brightness();
- else if (req == PWM_REQ_SET_BRIGHTNESS_SYNCED)
- {
- req_set_brightness();
- if (update_pwm_page)
- {
- while (!init_pwm_page(0))
- background_processing();
- }
- }
- else if (req == PWM_REQ_GET_BRIGHTNESS)
- {
- send_reply_mem((uint8_t *)bright_vals, sizeof(bright_vals));
- return;
- }
- else if (req == PWM_REQ_SET_CHANNEL_MAP)
- req_set_channel_map();
- else if (req == PWM_REQ_GET_CHANNEL_MAP)
- {
- send_reply_mem((uint8_t *)&setup.channel_map, sizeof(setup.channel_map));
- return;
- }
- else if (req == PWM_REQ_STORE_SETUP)
- store_setup_values();
- else if (req == PWM_REQ_RESET_SETUP)
- {
- init_setup_values();
- update_pwm_page = 1;
- if (eeprom_read_byte(&ee_valid) == EE_VALID_MARK)
- eeprom_write_byte(&ee_valid, (uint8_t)(~EE_VALID_MARK)); // Invalidate eeprom values
- }
- else if (req == PWM_REQ_GET_REQUEST_ERR_STATUS)
- {
- send_reply_start(1);
- send_reply_data(rx_err_status);
- rx_err_status = 0;
- return;
- }
- else if (req == PWM_REQ_SET_COMMON_PWM)
- {
- setup.common_pwm = (r->value.word <= MAX_COMMON_PWM) ? r->value.bytes[0]: MAX_COMMON_PWM;
- set_common_pwm();
- }
- else if (req == PWM_REQ_GET_COMMON_PWM)
- {
- send_reply_start(2);
- send_reply_data(setup.common_pwm);
- send_reply_data(0);
- return;
- }
- else if (req == PWM_REQ_GET_MAX_PWM)
- {
- send_reply_start(4);
- send_reply_data((uint8_t)(setup.max_pwm & 0x00FF));
- send_reply_data((uint8_t)(setup.max_pwm >> 8));
- send_reply_data(MAX_COMMON_PWM);
- send_reply_data(0);
- return;
- }
- else if (req == PWM_REQ_SET_PWM_FREQ)
- {
- if (r->value.word >= MIN_PWM_FREQ && r->value.word <= MAX_PWM_FREQ)
- {
- setup.max_pwm = F_CPU / (PWM_HWPRESCALE * PWM_PRESCALE * (uint32_t)r->value.word) - 1;
- update_pwm_page = 1;
- }
- }
- else if (req == PWM_REQ_GET_PWM_FREQ)
- {
- uint16_t f = F_CPU / (((uint32_t)setup.max_pwm + 1) * PWM_HWPRESCALE * PWM_PRESCALE);
- send_reply_start(2);
- send_reply_data((uint8_t)(f & 0x00FF));
- send_reply_data((uint8_t)(f >> 8));
- return;
- }
- else if (req == PWM_REQ_GET_VERSION)
- {
- send_reply_start(2);
- send_reply_data(PWM_VERS_APPL);
- send_reply_data(FIRMWARE_VERSION);
- return;
- }
- else if (req == PWM_REQ_ECHO_TEST)
- {
- send_reply_start(8);
- send_reply_data(r->bytes[0]);
- send_reply_data(r->bytes[1]);
- send_reply_data(r->bytes[2]);
- send_reply_data(r->bytes[3]);
- send_reply_data(r->bytes[4]);
- send_reply_data(r->bytes[5]);
- send_reply_data(r->bytes[6]);
- send_reply_data(r->bytes[7]);
- return;
- }
-
- send_reply_start(0);
-}
-
-
-// ---
-// Decode data byte of received data.
-//
-static void read_data(void)
-{
- uint8_t p, c, is_req_start;
-
-
- // Read data from RX buffer
- p = rxrpos;
- is_req_start = (p == rxspos);
- c = rxbuf[p++];
- CHECK_RXBUF_END(p);
- rxrpos = p;
-
- p = header_pos;
- if (is_req_start)
- {
- if (p)
- set_bit(rx_err_status, COMM_ERR_TIMEOUT);
-
- p = 0;
- }
- else if (!p)
- return; // Discard garbage
-
- if (p < sizeof(pwm_request_t))
- {
- pwm_request_t *r = &actual_req;
- FIX_POINTER(r);
-
- r->bytes[p++] = c;
- header_pos = p;
-
- if (p < sizeof(pwm_request_t))
- return;
-
- // Header complete
- if (!(r->request_type & PWMRQ_DEVICE_TO_HOST) && r->length.word)
- {
- payload_pos = rxrpos;
- payload_count = r->length.word;
- return;
- }
- }
- else if (--payload_count)
- return; // Payload not complete
-
- last_keep_alive = sys_clock;
- process_request();
- header_pos = 0;
-}
-
-
-// ---
-// Device initialization and main program loop.
-//
-void main(void) NORETURN;
-void main(void)
-{
- wdt_enable(WDTO_30MS); // Set watchdog timeout
-
- // Port init, enable pull-up resistors for unused ports
- PORTA = PA_INIT;
- PORTB = PB_INIT;
- PORTC = PC_INIT;
- PORTD = PD_INIT;
- PORTE = PE_INIT;
- DDRA = PA_DDR;
- DDRB = PB_DDR;
- DDRC = PC_DDR;
- DDRD = PD_DDR;
- DDRE = PE_DDR;
-
- // USART init
- // 9 data bits, 1 stop bit, no parity, asynchron mode
- // Enable TX, RX and RX Interrupts
-#include <util/setbaud.h>
- UBRR0H = UBRRH_VALUE;
- UBRR0L = UBRRL_VALUE;
-#if USE_2X
- UCSR0A = _BV(U2X);
-#endif
- UCSR0C = _BV(URSEL0) | _BV(UCSZ01) | _BV(UCSZ00);
- UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) | _BV(UCSZ02);
-
- read_setup_values();
-
- // Timer 0 is used for system clock
- // Normal mode, Prescaler 64
- TCCR0 = _BV(CS01) | _BV(CS00);
-
- // Timer 1 is used for common PWM generation
- // Fast 8-Bit PWM mode, Prescaler 1, PWM output at OC1B Pin
- TCCR1A = _BV(WGM10);
- TCCR1B = _BV(WGM12) | _BV(CS10);
- set_common_pwm();
-
- // Timer 3 is used for PWM generation
- ETIMSK = _BV(OCIE3A); // Enable timer 3 compare a interrupt
- init_pwm_step_tab();
-
- // Main loop
- for (;;)
- {
- background_processing();
-
- if (rxrpos != rxwpos)
- read_data();
-
- if (update_pwm_page && init_pwm_page(1))
- {
- calc_pwm_page();
- activate_pwm_page();
- }
-
- if (update_pwm_page || header_pos)
- clear_bit(STATUS_LED_PORT, STATUS_LED_BIT); // We are processing a request
- else
- set_bit(STATUS_LED_PORT, STATUS_LED_BIT); // No request
- }
-}
+/*
+ * Copyright (C) 2010 Andreas Auras
+ *
+ * This file is part of the DF10CH Atmolight controller project.
+ *
+ * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DF10CH Atmolight controller is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ */
+
+// ======================================================================
+// Application firmware for PWM processor.
+//
+
+#include <stdint.h>
+#include <string.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <avr/pgmspace.h>
+#include <avr/eeprom.h>
+
+#include "../df10ch_common.h"
+#include "../df10ch_usb_proto.h"
+
+
+// ---
+// Fuse-Bit settings for the flash programmer (ATmega 162):
+//
+// M161C=1
+// BODLEVEL2=1
+// BODLEVEL1=0
+// BODLEVEL0=0
+//
+// OCDEN=1
+// JTAGEN=1
+// SPIEN=0
+// WDTON=0
+// EESAVE=1
+// BOOTSZ1=0
+// BOOTSZ0=0
+// BOOTRST=1
+//
+// CKDIV8=1
+// CKOUT=1
+// SUT1=0
+// SUT0=1
+// CKSEL3=1
+// CKSEL2=1
+// CKSEL1=1
+// CKSEL0=1
+//
+// Memory-Lock Bits:
+// BLB12=1, BLB11=0, BLB02=1, BLB01=1, LB2=1, LB1=1
+//
+FUSES =
+{
+ .low = (FUSE_SUT1),
+ .high = (FUSE_SPIEN & FUSE_WDTON & FUSE_BOOTSZ1 & FUSE_BOOTSZ0),
+ .extended = (FUSE_BODLEVEL1 & FUSE_BODLEVEL0),
+};
+LOCKBITS = (LB_MODE_1 & BLB0_MODE_1 & BLB1_MODE_2);
+//SIGNATURE_DATA = { SIGNATURE_2, SIGNATURE_1, SIGNATURE_0 } ;
+
+
+// ---
+// System clock related.
+// System clock is implemented with hardware timer 0
+//
+#define SYS_HWPRESCALE 64 // Hardware Prescaler
+#define SYS_PRESCALER 256 // Timer Prescaler
+
+ // useconds <-> timer ticks conversation
+#define US2TICKS(t) ((uint16_t)((double)(t) * (double)F_CPU / (1000000.0 * (double)SYS_HWPRESCALE * (double)SYS_PRESCALER) + 0.5))
+#define TICKS2US(t) (((t) / (F_CPU / (1000000UL * SYS_HWPRESCALE * SYS_PRESCALER))))
+
+static uint16_t sys_clock;
+
+
+// ---
+// Keep alive reply related
+//
+#define MIN_KEEP_ALIVE_PAUSE US2TICKS(15000)
+
+static uint16_t last_keep_alive;
+
+
+// ---
+// Request parser related variables
+//
+typedef union
+{
+ uint8_t bytes[REQ_HEADER_SIZE];
+ struct
+ {
+ uint8_t request_type;
+ uint8_t request;
+ bytes_word_t value;
+ bytes_word_t index;
+ bytes_word_t length;
+ };
+} pwm_request_t;
+
+static pwm_request_t actual_req;
+static uint8_t header_pos;
+static uint8_t payload_pos;
+static uint8_t payload_count;
+
+
+// ---
+// PWM generation related
+//
+#define DEF_F_PWM 100UL // Default PWM cycle frequency in Hz
+#define PWM_HWPRESCALE 16 // Hardware timer prescale
+#define PWM_PRESCALE 9 // require: (PWM_PRESCALE * PWM_HWPRESCALE) > (size of ISR for timer )
+
+#define DEF_MAX_PWM (F_CPU / (PWM_HWPRESCALE * PWM_PRESCALE * DEF_F_PWM) - 1) // Maximum internal resolution for pwm
+
+#define PWM_STEP_PAGE_SIZE (NCHANNELS + 2) // possible maximum steps: NCHANNELS + Pause + End of Table
+
+typedef struct pwm_step_s {
+ uint8_t port_val[NPORTS]; // Values for Port A,B,C,D
+ uint16_t timer_val; // Timer compare value
+ struct pwm_step_s *next_step; // Pointer to next list entry
+ } pwm_step_t;
+
+ // One actual and one shadow page
+static pwm_step_t pwm_step_page1[PWM_STEP_PAGE_SIZE] NOMEMINIT;
+static pwm_step_t pwm_step_page2[PWM_STEP_PAGE_SIZE] NOMEMINIT;
+static pwm_step_t *shadow_pwm_page NOMEMINIT;
+static pwm_step_t *active_pwm_page NOMEMINIT;
+static pwm_step_t * volatile actual_pwm_step NOMEMINIT;
+static uint8_t update_pwm_page NOMEMINIT;
+
+
+// ---
+// RX buffer related variables
+//
+#define RXBUF_SIZE (REQ_HEADER_SIZE + MAX_REQ_PAYLOAD_SIZE + 1)
+#if RXBUF_SIZE == 256
+#define CHECK_RXBUF_END(pos)
+#else
+#define CHECK_RXBUF_END(pos) if ((pos) == RXBUF_SIZE) (pos) = 0
+#endif
+
+static uint8_t volatile rxrpos, rxwpos, rxspos, rx_err_status;
+static uint8_t rxbuf[RXBUF_SIZE] NOMEMINIT;
+
+
+// ---
+// Actual brightness values for each channel
+//
+static uint16_t bright_vals[NCHANNELS];
+
+
+// ---
+// Port channel mapping related variables
+//
+typedef struct { uint8_t code, port_bits; } channel_map_t;
+
+static channel_map_t default_channel_map[NCHANNELS] PROGMEM = {
+ // J3
+ { CM_CODE(PA_IDX, 0), _BV(2) },
+ { CM_CODE(PA_IDX, 1), _BV(1) },
+ { CM_CODE(PA_IDX, 2), _BV(0) },
+
+ // J4
+ { CM_CODE(PA_IDX, 3), _BV(5) },
+ { CM_CODE(PA_IDX, 4), _BV(4) },
+ { CM_CODE(PA_IDX, 5), _BV(3) },
+
+ // J5
+ { CM_CODE(PC_IDX, 6), _BV(7) },
+ { CM_CODE(PA_IDX, 7), _BV(7) },
+ { CM_CODE(PA_IDX, 8), _BV(6) },
+
+ // J6
+ { CM_CODE(PC_IDX, 9), _BV(4) },
+ { CM_CODE(PC_IDX, 10), _BV(5) },
+ { CM_CODE(PC_IDX, 11), _BV(6) },
+
+ // J7
+ { CM_CODE(PC_IDX, 12), _BV(1) },
+ { CM_CODE(PC_IDX, 13), _BV(2) },
+ { CM_CODE(PC_IDX, 14), _BV(3) },
+
+ // J8
+ { CM_CODE(PD_IDX, 15), _BV(6) },
+ { CM_CODE(PD_IDX, 16), _BV(7) },
+ { CM_CODE(PC_IDX, 17), _BV(0) },
+
+ // J9
+ { CM_CODE(PD_IDX, 18), _BV(3) },
+ { CM_CODE(PD_IDX, 19), _BV(4) },
+ { CM_CODE(PD_IDX, 20), _BV(5) },
+
+ // J10
+ { CM_CODE(PB_IDX, 21), _BV(6) },
+ { CM_CODE(PB_IDX, 22), _BV(7) },
+ { CM_CODE(PD_IDX, 23), _BV(2) },
+
+ // J11
+ { CM_CODE(PB_IDX, 24), _BV(3) },
+ { CM_CODE(PB_IDX, 25), _BV(4) },
+ { CM_CODE(PB_IDX, 26), _BV(5) },
+
+ // J12
+ { CM_CODE(PB_IDX, 27), _BV(0) },
+ { CM_CODE(PB_IDX, 28), _BV(1) },
+ { CM_CODE(PB_IDX, 29), _BV(2) }
+
+ };
+
+
+// ---
+// Setup values that will be stored to eeprom.
+//
+
+typedef struct {
+ uint16_t max_pwm;
+ uint8_t common_pwm;
+ channel_map_t channel_map[NCHANNELS];
+ } setup_t;
+
+setup_t setup NOMEMINIT;
+
+#define EE_VALID_MARK 0xA5
+static uint8_t ee_valid EEMEM; // If eeprom content is valid this byte is EE_VALID_MARK
+static setup_t ee_setup EEMEM;
+
+
+// Status LED related
+#define STATUS_LED_PORT PORTE
+#define STATUS_LED_BIT 1
+
+// Common PWM channel related
+#define MAX_COMMON_PWM 255
+#define DEF_COMMON_PWM 255 // Default common pwm value
+
+#define COMMON_PWM_PORT PORTE
+#define COMMON_PWM_BIT 2
+
+
+// Input pin for enable/disable of bootloader
+#define BL_SENSE_PIN PINE
+#define BL_SENSE_BIT 0
+
+
+// ---
+// Definition of port direction and initial values.
+//
+#define PA_DDR 0xFF
+#define PA_INIT 0x00
+
+#define PB_DDR 0xFF
+#define PB_INIT 0x00
+
+#define PC_DDR 0xFF
+#define PC_INIT 0x00
+
+#define PD_DDR (_BV(1) | _BV(2) | _BV(3) | _BV(4) | _BV(5) | _BV(6) | _BV(7))
+#define PD_INIT _BV(1)
+
+#define PE_DDR (_BV(STATUS_LED_BIT) | _BV(COMMON_PWM_BIT))
+#define PE_INIT _BV(BL_SENSE_BIT)
+
+
+// ---
+// Catchup all unused interrupts and wait until watchdog resets device.
+// This ISR is only for unexpected interrupts.
+//
+ISR(BADISR_vect)
+{
+ for (;;);
+}
+
+
+// ---
+// ISR for PWM generation.
+//
+ISR(TIMER3_COMPA_vect)
+{
+ pwm_step_t *p = actual_pwm_step;
+
+ // Optimized OCR3A = p->timer_val
+ OCR3AH = ((uint8_t *)&(p->timer_val))[1];
+ OCR3AL = ((uint8_t *)&(p->timer_val))[0];
+
+ PORTA = p->port_val[PA_IDX];
+ PORTB = p->port_val[PB_IDX];
+ PORTC = p->port_val[PC_IDX];
+ PORTD = p->port_val[PD_IDX];
+
+ // Optimized actual_pwm_step = p->next_step
+ ((uint8_t *)&(actual_pwm_step))[0] = ((uint8_t *)&(p->next_step))[0];
+ ((uint8_t *)&(actual_pwm_step))[1] = ((uint8_t *)&(p->next_step))[1];
+}
+
+
+// ---
+// ISR for receiving data.
+//
+ISR(USART0_RXC_vect)
+{
+ clear_bit(UCSR0B, RXCIE0);
+ sei();
+
+ do
+ {
+ uint8_t i = rxwpos;
+ uint8_t p = i + 1;
+ CHECK_RXBUF_END(p);
+
+ if (bit_is_set(UCSR0A, FE0))
+ set_bit(rx_err_status, COMM_ERR_FRAME);
+ else if (bit_is_set(UCSR0A, DOR0))
+ set_bit(rx_err_status, COMM_ERR_OVERRUN);
+ else if (p == rxrpos)
+ set_bit(rx_err_status, COMM_ERR_OVERFLOW);
+ else
+ {
+ if (bit_is_set(UCSR0B, RXB80))
+ rxspos = i; // save start of request message
+ rxwpos = p; // set data valid
+ }
+ rxbuf[i] = UDR0; // read data
+ }
+ while (bit_is_set(UCSR0A, RXC0));
+
+ cli();
+ set_bit(UCSR0B, RXCIE0);
+}
+
+
+// ---
+// Processing while waiting for a event.
+//
+static void background_processing(void)
+{
+ wdt_reset();
+
+ // count system clock
+ if (bit_is_set(TIFR, TOV0))
+ {
+ ++sys_clock;
+ TIFR = _BV(TOV0);
+ }
+}
+
+
+// ---
+// Put data into transmit buffer.
+//
+static void send_reply_data(uint8_t c)
+{
+ // Wait until transmit buffer free
+ while (bit_is_clear(UCSR0A, UDRE0))
+ background_processing();
+
+ UDR0 = c;
+}
+
+
+// ---
+// Send reply start.
+//
+static void send_reply_start(uint8_t len)
+{
+ // Wait until transmit buffer free
+ while (bit_is_clear(UCSR0A, UDRE0))
+ background_processing();
+
+ uint8_t id = actual_req.request_type & PWMRQ_ID_MASK;
+ if (len)
+ id |= PWMRP_HAS_PAYLOAD;
+
+ set_bit(UCSR0B, TXB80); // Set 9th bit for start of reply
+ UDR0 = id; // Send reply id
+ clear_bit(UCSR0B, TXB80);
+
+ if (len)
+ send_reply_data(len); // Send reply length
+
+ last_keep_alive = sys_clock;
+}
+
+
+// ---
+// Send keep alive reply.
+//
+static void send_keep_alive_reply(void)
+{
+ background_processing();
+ if ((sys_clock - last_keep_alive) > MIN_KEEP_ALIVE_PAUSE)
+ {
+ // Wait until transmit buffer free
+ while (bit_is_clear(UCSR0A, UDRE0))
+ background_processing();
+
+ set_bit(UCSR0B, TXB80); // Set 9th bit for start of reply
+ UDR0 = PWMRP_KEEP_ALIVE; // Send keep alive ID
+ clear_bit(UCSR0B, TXB80);
+
+ last_keep_alive = sys_clock;
+ }
+}
+
+
+// ---
+// Set on time 'v' for port bits 'pb' of port 'pi' in shadow pwm page.
+//
+static void set_channel(uint8_t pi, uint8_t pb, uint16_t v)
+{
+ pwm_step_t *p = shadow_pwm_page;
+ pwm_step_t *l, *n;
+
+ while (p->timer_val && v >= p->timer_val)
+ {
+ p->port_val[pi] |= pb;
+ if (p->timer_val == v)
+ return;
+ l = p;
+ p = l->next_step;
+ }
+
+ if (p->timer_val)
+ {
+ n = p;
+ do
+ {
+ l = n;
+ n = l->next_step;
+ }
+ while (n->timer_val);
+
+ l->next_step = n->next_step;
+ n[0] = p[0];
+ p->next_step = n;
+ }
+ else
+ {
+ p->port_val[PA_IDX] = PA_INIT;
+ p->port_val[PB_IDX] = PB_INIT;
+ p->port_val[PC_IDX] = PC_INIT;
+ p->port_val[PD_IDX] = PD_INIT;
+ }
+ p->timer_val = v;
+ p->port_val[pi] |= pb;
+}
+
+
+// ---
+// Init shadow pwm page.
+//
+static uint8_t init_pwm_page(uint8_t do_init)
+{
+ pwm_step_t *p = shadow_pwm_page;
+ pwm_step_t *e = p + PWM_STEP_PAGE_SIZE;
+
+ // Check if shadow page is deactivated
+ cli();
+ pwm_step_t *a = actual_pwm_step;
+ sei();
+ if (a >= p && a < e)
+ return(0); // Shadow page is still active
+
+ if (do_init)
+ {
+ while (p < e)
+ {
+ p->timer_val = 0;
+ a = p + 1;
+ p->next_step = a;
+ p = a;
+ }
+ }
+
+ return(1);
+}
+
+
+// ---
+// Finalize shadow pwm page and activate it.
+//
+static void activate_pwm_page(void)
+{
+ pwm_step_t *p = shadow_pwm_page;
+ pwm_step_t *l;
+ uint16_t t = 0;
+
+ // Calculate time steps
+ while (p->timer_val)
+ {
+ uint16_t ts = p->timer_val - t;
+ t = p->timer_val;
+ p->timer_val = ts * PWM_PRESCALE;
+ l = p;
+ p = l->next_step;
+ }
+
+ // Add pause entry to reach a full cycle
+ t = setup.max_pwm - t;
+ if (t)
+ {
+ p->port_val[PA_IDX] = PA_INIT;
+ p->port_val[PB_IDX] = PB_INIT;
+ p->port_val[PC_IDX] = PC_INIT;
+ p->port_val[PD_IDX] = PD_INIT;
+ p->timer_val = t * PWM_PRESCALE;
+ l = p;
+ }
+
+ // Make list cyclic
+ p = shadow_pwm_page;
+ l->next_step = p;
+
+ // Install Link to shadow page in active page
+ p = active_pwm_page;
+ active_pwm_page = l;
+ l = shadow_pwm_page;
+ cli();
+ p->next_step = l;
+ sei();
+
+ // Swap shadow page
+ if (l == pwm_step_page1)
+ p = pwm_step_page2;
+ else
+ p = pwm_step_page1;
+ shadow_pwm_page = p;
+
+ update_pwm_page = 0;
+}
+
+
+// ---
+// Calculate pwm page.
+//
+static void calc_pwm_page(void)
+{
+ uint8_t c;
+
+ c = NCHANNELS;
+ while (c--)
+ {
+ uint8_t port_bits = setup.channel_map[c].port_bits;
+ if (port_bits)
+ {
+ uint8_t code = setup.channel_map[c].code;
+ uint16_t v = bright_vals[CM_CHANNEL(code)];
+ if (v)
+ {
+ if (v > setup.max_pwm)
+ v = setup.max_pwm;
+ set_channel(CM_PORT(code), port_bits, v);
+ }
+ }
+ }
+}
+
+
+// ---
+// Initialize pwm step table and start pwm timer.
+//
+static void init_pwm_step_tab(void)
+{
+ // Set up pwm step table
+ shadow_pwm_page = pwm_step_page1;
+ active_pwm_page = pwm_step_page2;
+ actual_pwm_step = pwm_step_page2;
+ init_pwm_page(1);
+ calc_pwm_page();
+ activate_pwm_page();
+ actual_pwm_step = active_pwm_page->next_step;
+
+ TCNT3 = 0; // Reset timer counter
+ OCR3A = PWM_PRESCALE; // Initial startup step
+ TCCR3B = _BV(CS32) | _BV(CS31) | _BV(WGM32); // Start timer, Prescaler 16, CTC mode
+}
+
+
+// ---
+// Set default setup values.
+//
+static void init_setup_values(void)
+{
+ setup.max_pwm = DEF_MAX_PWM;
+ setup.common_pwm = DEF_COMMON_PWM;
+
+ memcpy_P(&setup.channel_map, &default_channel_map, sizeof(setup.channel_map));
+}
+
+
+// ---
+// Read setup values from eeprom.
+//
+static void read_setup_values(void)
+{
+ if (eeprom_read_byte(&ee_valid) == EE_VALID_MARK)
+ eeprom_read_block(&setup, &ee_setup, sizeof(setup));
+ else
+ init_setup_values();
+}
+
+
+// ---
+// Store actual setup values into eeprom.
+//
+static void store_setup_values(void)
+{
+ uint8_t i = sizeof(setup);
+ uint8_t *src = (uint8_t *) (&setup);
+ uint8_t *dst = (uint8_t *) (&ee_setup);
+ while (i--)
+ {
+ if (eeprom_read_byte(dst) != *src)
+ {
+ eeprom_write_byte(dst, *src);
+ while (!eeprom_is_ready())
+ send_keep_alive_reply();
+ }
+ ++src;
+ ++dst;
+ }
+ if (eeprom_read_byte(&ee_valid) != EE_VALID_MARK)
+ {
+ eeprom_write_byte(&ee_valid, EE_VALID_MARK);
+ while (!eeprom_is_ready())
+ send_keep_alive_reply();
+ }
+}
+
+
+// ---
+// Set common pwm value.
+//
+static void set_common_pwm(void)
+{
+ uint8_t v = setup.common_pwm;
+
+ if (v == 0 || v == 255)
+ {
+ if (v)
+ set_bit(COMMON_PWM_PORT, COMMON_PWM_BIT);
+ else
+ clear_bit(COMMON_PWM_PORT, COMMON_PWM_BIT);
+ clear_bit(TCCR1A, COM1B1); // Normal port output
+ }
+ else
+ {
+ OCR1B = v;
+ clear_bit(COMMON_PWM_PORT, COMMON_PWM_BIT);
+ set_bit(TCCR1A, COM1B1); // pwm port output
+ }
+}
+
+
+// ---
+// Send reply packet from ram memory.
+//
+static void send_reply_mem(uint8_t *data, uint16_t len)
+{
+ pwm_request_t *r = &actual_req;
+ FIX_POINTER(r);
+
+ uint16_t p = r->index.word << 1;
+ uint16_t n = r->length.word;
+ if (p >= len)
+ n = 0;
+ if (n && (p + n) > len)
+ n = len - p;
+ if (n > MAX_REPLY_PAYLOAD_SIZE)
+ n = 0; // Send nothing!
+
+ send_reply_start(n);
+
+ data += p;
+ while (n)
+ {
+ send_reply_data(*data++);
+ --n;
+ }
+}
+
+
+// ---
+// Process set brightness value.
+//
+static void req_set_brightness(void)
+{
+ pwm_request_t *r = &actual_req;
+ FIX_POINTER(r);
+
+ uint8_t p = payload_pos;
+ uint16_t c = r->index.word;
+ uint16_t len = r->length.word >> 1;
+ while (len && c < NCHANNELS)
+ {
+ bytes_word_t v;
+ v.bytes[0] = rxbuf[p++];
+ CHECK_RXBUF_END(p);
+ v.bytes[1] = rxbuf[p++];
+ CHECK_RXBUF_END(p);
+
+ if (bright_vals[c] != v.word)
+ {
+ bright_vals[c] = v.word;
+ update_pwm_page = 1;
+ }
+
+ ++c;
+ --len;
+ }
+}
+
+
+// ---
+// Process set channel map request.
+//
+static void req_set_channel_map(void)
+{
+ pwm_request_t *r = &actual_req;
+ FIX_POINTER(r);
+
+ uint8_t p = payload_pos;
+ uint16_t c = r->index.word;
+ uint16_t len = r->length.word >> 1;
+ while (len && c < NCHANNELS)
+ {
+ uint8_t v = rxbuf[p++];
+ CHECK_RXBUF_END(p);
+
+ if (CM_CHANNEL(v) >= NCHANNELS)
+ v = NCHANNELS - 1;
+
+ if (setup.channel_map[c].code != v)
+ {
+ setup.channel_map[c].code = v;
+ update_pwm_page = 1;
+ }
+
+ v = rxbuf[p++];
+ CHECK_RXBUF_END(p);
+
+ if (setup.channel_map[c].port_bits != v)
+ {
+ setup.channel_map[c].port_bits = v;
+ update_pwm_page = 1;
+ }
+
+ ++c;
+ --len;
+ }
+}
+
+
+// ---
+// Process received request.
+//
+static void process_request(void)
+{
+ pwm_request_t *r = &actual_req;
+ FIX_POINTER(r);
+
+ uint8_t req = r->request;
+
+ if (req == PWM_REQ_SET_BRIGHTNESS)
+ req_set_brightness();
+ else if (req == PWM_REQ_SET_BRIGHTNESS_SYNCED)
+ {
+ req_set_brightness();
+ if (update_pwm_page)
+ {
+ while (!init_pwm_page(0))
+ background_processing();
+ }
+ }
+ else if (req == PWM_REQ_GET_BRIGHTNESS)
+ {
+ send_reply_mem((uint8_t *)bright_vals, sizeof(bright_vals));
+ return;
+ }
+ else if (req == PWM_REQ_SET_CHANNEL_MAP)
+ req_set_channel_map();
+ else if (req == PWM_REQ_GET_CHANNEL_MAP)
+ {
+ send_reply_mem((uint8_t *)&setup.channel_map, sizeof(setup.channel_map));
+ return;
+ }
+ else if (req == PWM_REQ_STORE_SETUP)
+ store_setup_values();
+ else if (req == PWM_REQ_RESET_SETUP)
+ {
+ init_setup_values();
+ update_pwm_page = 1;
+ if (eeprom_read_byte(&ee_valid) == EE_VALID_MARK)
+ eeprom_write_byte(&ee_valid, (uint8_t)(~EE_VALID_MARK)); // Invalidate eeprom values
+ }
+ else if (req == PWM_REQ_GET_REQUEST_ERR_STATUS)
+ {
+ send_reply_start(1);
+ send_reply_data(rx_err_status);
+ rx_err_status = 0;
+ return;
+ }
+ else if (req == PWM_REQ_SET_COMMON_PWM)
+ {
+ setup.common_pwm = (r->value.word <= MAX_COMMON_PWM) ? r->value.bytes[0]: MAX_COMMON_PWM;
+ set_common_pwm();
+ }
+ else if (req == PWM_REQ_GET_COMMON_PWM)
+ {
+ send_reply_start(2);
+ send_reply_data(setup.common_pwm);
+ send_reply_data(0);
+ return;
+ }
+ else if (req == PWM_REQ_GET_MAX_PWM)
+ {
+ send_reply_start(4);
+ send_reply_data((uint8_t)(setup.max_pwm & 0x00FF));
+ send_reply_data((uint8_t)(setup.max_pwm >> 8));
+ send_reply_data(MAX_COMMON_PWM);
+ send_reply_data(0);
+ return;
+ }
+ else if (req == PWM_REQ_SET_PWM_FREQ)
+ {
+ if (r->value.word >= MIN_PWM_FREQ && r->value.word <= MAX_PWM_FREQ)
+ {
+ setup.max_pwm = F_CPU / (PWM_HWPRESCALE * PWM_PRESCALE * (uint32_t)r->value.word) - 1;
+ update_pwm_page = 1;
+ }
+ }
+ else if (req == PWM_REQ_GET_PWM_FREQ)
+ {
+ uint16_t f = F_CPU / (((uint32_t)setup.max_pwm + 1) * PWM_HWPRESCALE * PWM_PRESCALE);
+ send_reply_start(2);
+ send_reply_data((uint8_t)(f & 0x00FF));
+ send_reply_data((uint8_t)(f >> 8));
+ return;
+ }
+ else if (req == PWM_REQ_GET_VERSION)
+ {
+ send_reply_start(2);
+ send_reply_data(PWM_VERS_APPL);
+ send_reply_data(FIRMWARE_VERSION);
+ return;
+ }
+ else if (req == PWM_REQ_ECHO_TEST)
+ {
+ send_reply_start(8);
+ send_reply_data(r->bytes[0]);
+ send_reply_data(r->bytes[1]);
+ send_reply_data(r->bytes[2]);
+ send_reply_data(r->bytes[3]);
+ send_reply_data(r->bytes[4]);
+ send_reply_data(r->bytes[5]);
+ send_reply_data(r->bytes[6]);
+ send_reply_data(r->bytes[7]);
+ return;
+ }
+
+ send_reply_start(0);
+}
+
+
+// ---
+// Decode data byte of received data.
+//
+static void read_data(void)
+{
+ uint8_t p, c, is_req_start;
+
+
+ // Read data from RX buffer
+ p = rxrpos;
+ is_req_start = (p == rxspos);
+ c = rxbuf[p++];
+ CHECK_RXBUF_END(p);
+ rxrpos = p;
+
+ p = header_pos;
+ if (is_req_start)
+ {
+ if (p)
+ set_bit(rx_err_status, COMM_ERR_TIMEOUT);
+
+ p = 0;
+ }
+ else if (!p)
+ return; // Discard garbage
+
+ if (p < sizeof(pwm_request_t))
+ {
+ pwm_request_t *r = &actual_req;
+ FIX_POINTER(r);
+
+ r->bytes[p++] = c;
+ header_pos = p;
+
+ if (p < sizeof(pwm_request_t))
+ return;
+
+ // Header complete
+ if (!(r->request_type & PWMRQ_DEVICE_TO_HOST) && r->length.word)
+ {
+ payload_pos = rxrpos;
+ payload_count = r->length.word;
+ return;
+ }
+ }
+ else if (--payload_count)
+ return; // Payload not complete
+
+ last_keep_alive = sys_clock;
+ process_request();
+ header_pos = 0;
+}
+
+
+// ---
+// Device initialization and main program loop.
+//
+void main(void) NORETURN;
+void main(void)
+{
+ wdt_enable(WDTO_30MS); // Set watchdog timeout
+
+ // Port init, enable pull-up resistors for unused ports
+ PORTA = PA_INIT;
+ PORTB = PB_INIT;
+ PORTC = PC_INIT;
+ PORTD = PD_INIT;
+ PORTE = PE_INIT;
+ DDRA = PA_DDR;
+ DDRB = PB_DDR;
+ DDRC = PC_DDR;
+ DDRD = PD_DDR;
+ DDRE = PE_DDR;
+
+ // USART init
+ // 9 data bits, 1 stop bit, no parity, asynchron mode
+ // Enable TX, RX and RX Interrupts
+#include <util/setbaud.h>
+ UBRR0H = UBRRH_VALUE;
+ UBRR0L = UBRRL_VALUE;
+#if USE_2X
+ UCSR0A = _BV(U2X);
+#endif
+ UCSR0C = _BV(URSEL0) | _BV(UCSZ01) | _BV(UCSZ00);
+ UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) | _BV(UCSZ02);
+
+ read_setup_values();
+
+ // Timer 0 is used for system clock
+ // Normal mode, Prescaler 64
+ TCCR0 = _BV(CS01) | _BV(CS00);
+
+ // Timer 1 is used for common PWM generation
+ // Fast 8-Bit PWM mode, Prescaler 1, PWM output at OC1B Pin
+ TCCR1A = _BV(WGM10);
+ TCCR1B = _BV(WGM12) | _BV(CS10);
+ set_common_pwm();
+
+ // Timer 3 is used for PWM generation
+ ETIMSK = _BV(OCIE3A); // Enable timer 3 compare a interrupt
+ init_pwm_step_tab();
+
+ // Main loop
+ for (;;)
+ {
+ background_processing();
+
+ if (rxrpos != rxwpos)
+ read_data();
+
+ if (update_pwm_page && init_pwm_page(1))
+ {
+ calc_pwm_page();
+ activate_pwm_page();
+ }
+
+ if (update_pwm_page || header_pos)
+ clear_bit(STATUS_LED_PORT, STATUS_LED_BIT); // We are processing a request
+ else
+ set_bit(STATUS_LED_PORT, STATUS_LED_BIT); // No request
+ }
+}
diff --git a/pwm_boot/Makefile b/pwm_boot/Makefile
index 1a98f84..fb401ea 100644
--- a/pwm_boot/Makefile
+++ b/pwm_boot/Makefile
@@ -1,102 +1,102 @@
-#
-# Copyright (C) 2010 Andreas Auras
-#
-# This file is part of the DF10CH Atmolight controller project.
-#
-# DF10CH Atmolight controller is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# DF10CH Atmolight controller is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-#
-#
-###############################################################################
-# Makefile for the bootloader firmware of PWM processor
-###############################################################################
-
-## General Flags
-PROJECT = 10ch_pwm_boot
-MCU = atmega162
-TARGET = 10ch_pwm_boot.elf
-CC = avr-gcc
-AVRDUDE ?= avrdude -c stk500v2 -P avrdoper
-F_CPU ?= 16000000UL
-FIRMWARE_VERSION ?= 1
-
-## Options common to compile, link and assembly rules
-COMMON = -mmcu=$(MCU)
-
-## Compile options common for all C compilation units.
-CFLAGS = $(COMMON)
-CFLAGS += -Wall -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
-CFLAGS += -DF_CPU=$(F_CPU) -DFIRMWARE_VERSION=$(FIRMWARE_VERSION)
-
-## Assembly specific flags
-ASMFLAGS = $(COMMON)
-ASMFLAGS += $(CFLAGS)
-ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
-
-## Linker flags
-LDFLAGS = $(COMMON)
-LDFLAGS += -Wl,-Map=10ch_pwm_boot.map
-LDFLAGS += -Wl,-section-start=.text=0x3800
-
-
-## Intel Hex file production flags
-HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
-
-HEX_EEPROM_FLAGS = -j .eeprom
-HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
-
-## Include Directories
-INCLUDES = -I. -I..
-
-## Objects that must be built in order to link
-OBJECTS = 10ch_pwm_boot.o
-
-## Objects explicitly added by the user
-LINKONLYOBJECTS =
-
-## Build
-all: $(TARGET) 10ch_pwm_boot.hex 10ch_pwm_boot.lss size
-
-prog: flash
- $(AVRDUDE) -p $(MCU) -u -Ulfuse:w:0xc0:m -Uhfuse:w:0xc8:m -Uefuse:w:0xf9:m -Ulock:w:0xef:m
-
-flash: 10ch_pwm_boot.hex
- $(AVRDUDE) -p $(MCU) -Uflash:w:10ch_pwm_boot.hex:i
-
-
-## Compile
-10ch_pwm_boot.o: 10ch_pwm_boot.c ../df10ch_usb_proto.h ../df10ch_common.h
- $(CC) $(INCLUDES) $(CFLAGS) -c $<
-
-##Link
-$(TARGET): $(OBJECTS)
- $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
-
-%.hex: $(TARGET)
- avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
-
-%.eep: $(TARGET)
- -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
-
-%.lss: $(TARGET)
- avr-objdump -h -S $< > $@
-
-size: ${TARGET}
- @echo
- @avr-size -C --mcu=${MCU} ${TARGET}
-
-## Clean target
-.PHONY: clean
-clean:
- -rm -rf $(OBJECTS) 10ch_pwm_boot.elf 10ch_pwm_boot.hex 10ch_pwm_boot.eep 10ch_pwm_boot.lss 10ch_pwm_boot.map
+#
+# Copyright (C) 2010 Andreas Auras
+#
+# This file is part of the DF10CH Atmolight controller project.
+#
+# DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# DF10CH Atmolight controller is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+#
+#
+###############################################################################
+# Makefile for the bootloader firmware of PWM processor
+###############################################################################
+
+## General Flags
+PROJECT = df10ch_pwm_boot
+MCU = atmega162
+TARGET = df10ch_pwm_boot.elf
+CC = avr-gcc
+AVRDUDE ?= avrdude -c stk500v2 -P avrdoper
+F_CPU ?= 16000000UL
+FIRMWARE_VERSION ?= 1
+
+## Options common to compile, link and assembly rules
+COMMON = -mmcu=$(MCU)
+
+## Compile options common for all C compilation units.
+CFLAGS = $(COMMON)
+CFLAGS += -Wall -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -DF_CPU=$(F_CPU) -DFIRMWARE_VERSION=$(FIRMWARE_VERSION)
+
+## Assembly specific flags
+ASMFLAGS = $(COMMON)
+ASMFLAGS += $(CFLAGS)
+ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
+
+## Linker flags
+LDFLAGS = $(COMMON)
+LDFLAGS += -Wl,-Map=df10ch_pwm_boot.map
+LDFLAGS += -Wl,-section-start=.text=0x3800
+
+
+## Intel Hex file production flags
+HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
+
+HEX_EEPROM_FLAGS = -j .eeprom
+HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
+
+## Include Directories
+INCLUDES = -I. -I..
+
+## Objects that must be built in order to link
+OBJECTS = df10ch_pwm_boot.o
+
+## Objects explicitly added by the user
+LINKONLYOBJECTS =
+
+## Build
+all: $(TARGET) df10ch_pwm_boot.hex df10ch_pwm_boot.lss size
+
+prog: flash
+ $(AVRDUDE) -p $(MCU) -u -Ulfuse:w:0xc0:m -Uhfuse:w:0xc8:m -Uefuse:w:0xf9:m -Ulock:w:0xef:m
+
+flash: df10ch_pwm_boot.hex
+ $(AVRDUDE) -p $(MCU) -Uflash:w:df10ch_pwm_boot.hex:i
+
+
+## Compile
+df10ch_pwm_boot.o: df10ch_pwm_boot.c ../df10ch_usb_proto.h ../df10ch_common.h
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<
+
+##Link
+$(TARGET): $(OBJECTS)
+ $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
+
+%.hex: $(TARGET)
+ avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
+
+%.eep: $(TARGET)
+ -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
+
+%.lss: $(TARGET)
+ avr-objdump -h -S $< > $@
+
+size: ${TARGET}
+ @echo
+ @avr-size -C --mcu=${MCU} ${TARGET}
+
+## Clean target
+.PHONY: clean
+clean:
+ -rm -rf $(OBJECTS) df10ch_pwm_boot.elf df10ch_pwm_boot.hex df10ch_pwm_boot.eep df10ch_pwm_boot.lss df10ch_pwm_boot.map
diff --git a/pwm_boot/10ch_pwm_boot.c b/pwm_boot/df10ch_pwm_boot.c
index 787f5df..8795a5c 100644
--- a/pwm_boot/10ch_pwm_boot.c
+++ b/pwm_boot/df10ch_pwm_boot.c
@@ -1,475 +1,475 @@
-/*
- * Copyright (C) 2010 Andreas Auras
- *
- * This file is part of the DF10CH Atmolight controller project.
- *
- * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * DF10CH Atmolight controller is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- */
-
-// ======================================================================
-// Bootloader firmware for PWM processor.
-//
-
-#include <stdint.h>
-#include <string.h>
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <avr/wdt.h>
-#include <avr/pgmspace.h>
-#include <avr/eeprom.h>
-#include <avr/boot.h>
-
-#include "../df10ch_common.h"
-#include "../df10ch_usb_proto.h"
-
-
-// ---
-// Fuse-Bit settings for the flash programmer (Atmega 162):
-//
-// M161C=1
-// BODLEVEL2=1
-// BODLEVEL1=0
-// BODLEVEL0=0
-//
-// OCDEN=1
-// JTAGEN=1
-// SPIEN=0
-// WDTON=0
-// EESAVE=1
-// BOOTSZ1=0
-// BOOTSZ0=0
-// BOOTRST=0
-//
-// CKDIV8=1
-// CKOUT=1
-// SUT1=0
-// SUT0=1
-// CKSEL3=1
-// CKSEL2=1
-// CKSEL1=1
-// CKSEL0=1
-//
-// Memory-Lock Bits:
-// BLB12=1, BLB11=0, BLB02=1, BLB01=1, LB2=1, LB1=1
-//
-FUSES =
-{
- .low = (FUSE_SUT1),
- .high = (FUSE_SPIEN & FUSE_WDTON & FUSE_BOOTSZ1 & FUSE_BOOTSZ0 & FUSE_BOOTRST),
- .extended = (FUSE_BODLEVEL1 & FUSE_BODLEVEL0),
-};
-LOCKBITS = (LB_MODE_1 & BLB0_MODE_1 & BLB1_MODE_2);
-//SIGNATURE_DATA = { SIGNATURE_2, SIGNATURE_1, SIGNATURE_0 } ;
-
-
-// ---
-// System clock related.
-// System clock is implemented with hardware timer 0
-//
-#define SYS_HWPRESCALE 64 // Hardware Prescaler
-#define SYS_PRESCALER 256 // Timer Prescaler
-
- // useconds <-> timer ticks conversation
-#define US2TICKS(t) ((uint16_t)((double)(t) * (double)F_CPU / (1000000.0 * (double)SYS_HWPRESCALE * (double)SYS_PRESCALER) + 0.5))
-#define TICKS2US(t) (((t) / (F_CPU / (1000000UL * SYS_HWPRESCALE * SYS_PRESCALER))))
-
-static uint16_t sys_clock;
-
-
-// ---
-// Keep alive reply related
-//
-#define MIN_KEEP_ALIVE_PAUSE US2TICKS(15000)
-
-static uint16_t last_keep_alive;
-
-
-// ---
-// Request parser related variables
-//
-typedef union
-{
- uint8_t bytes[REQ_HEADER_SIZE];
- struct
- {
- uint8_t request_type;
- uint8_t request;
- bytes_word_t value;
- bytes_word_t index;
- bytes_word_t length;
- };
-} pwm_request_t;
-
-static pwm_request_t actual_req;
-static uint8_t header_pos;
-static uint8_t payload_pos;
-static uint8_t payload_count;
-
-
-// ---
-// RX buffer related variables
-//
-#define RXBUF_SIZE (REQ_HEADER_SIZE + MAX_REQ_PAYLOAD_SIZE + 1)
-#if RXBUF_SIZE == 256
-#define CHECK_RXBUF_END(pos)
-#else
-#define CHECK_RXBUF_END(pos) if ((pos) == RXBUF_SIZE) (pos) = 0
-#endif
-
-static uint8_t volatile rxrpos, rxwpos, rxspos, rx_err_status;
-static uint8_t rxbuf[RXBUF_SIZE] NOMEMINIT;
-
-
-// Status LED related
-#define STATUS_LED_PORT PORTE
-#define STATUS_LED_BIT 1
-
-// Input pin for enable/disable of bootloader
-#define BL_SENSE_PIN PINE
-#define BL_SENSE_BIT 0
-
-#define APPL_START_VECT 0x0000
-
-// ---
-// Definition of port direction and initial values.
-//
-#define PE_DDR _BV(STATUS_LED_BIT)
-#define PE_INIT _BV(BL_SENSE_BIT)
-
-
-// ---
-// ISR handler for IRQ's that do not have a dedicated handler.
-//
-EMPTY_INTERRUPT(BADISR_vect)
-
-
-// ---
-// ISR for receiving data.
-//
-ISR(USART0_RXC_vect)
-{
- do
- {
- uint8_t i = rxwpos;
- uint8_t p = i + 1;
- CHECK_RXBUF_END(p);
-
- if (bit_is_set(UCSR0A, FE0))
- set_bit(rx_err_status, COMM_ERR_FRAME);
- else if (bit_is_set(UCSR0A, DOR0))
- set_bit(rx_err_status, COMM_ERR_OVERRUN);
- else if (p == rxrpos)
- set_bit(rx_err_status, COMM_ERR_OVERFLOW);
- else
- {
- if (bit_is_set(UCSR0B, RXB80))
- rxspos = i; // save start of request message
- rxwpos = p; // set data valid
- }
- rxbuf[i] = UDR0; // read data
- }
- while (bit_is_set(UCSR0A, RXC0));
-}
-
-
-// ---
-// Processing while waiting for a event.
-//
-static void background_processing(void)
-{
- wdt_reset();
-
- // count system clock
- if (bit_is_set(TIFR, TOV0))
- {
- ++sys_clock;
- TIFR = _BV(TOV0);
- }
-}
-
-
-// ---
-// Put data into transmit buffer.
-//
-static void send_reply_data(uint8_t c)
-{
- // Wait until transmit buffer free
- while (bit_is_clear(UCSR0A, UDRE0))
- background_processing();
-
- UDR0 = c;
-}
-
-
-// ---
-// Send reply start.
-//
-static void send_reply_start(uint8_t len)
-{
- // Wait until transmit buffer free
- while (bit_is_clear(UCSR0A, UDRE0))
- background_processing();
-
- uint8_t id = actual_req.request_type & PWMRQ_ID_MASK;
- if (len)
- id |= PWMRP_HAS_PAYLOAD;
-
- set_bit(UCSR0B, TXB80); // Set 9th bit for start of reply
- UDR0 = id; // Send reply id
- clear_bit(UCSR0B, TXB80);
-
- if (len)
- send_reply_data(len); // Send reply length
-
- last_keep_alive = sys_clock;
-}
-
-
-// ---
-// Send keep alive reply.
-//
-static void send_keep_alive_reply(void)
-{
- background_processing();
- if ((sys_clock - last_keep_alive) > MIN_KEEP_ALIVE_PAUSE)
- {
- // Wait until transmit buffer free
- while (bit_is_clear(UCSR0A, UDRE0))
- background_processing();
-
- set_bit(UCSR0B, TXB80); // Set 9th bit for start of reply
- UDR0 = PWMRP_KEEP_ALIVE; // Send keep alive ID
- clear_bit(UCSR0B, TXB80);
-
- last_keep_alive = sys_clock;
- }
-}
-
-
-// ---
-// Send reply packet from flash memory.
-//
-static void send_reply_read_flash(PGM_P p, uint16_t n)
-{
- if (n > MAX_REPLY_PAYLOAD_SIZE)
- n = 0; // Send nothing!
-
- send_reply_start((uint8_t)n);
-
- while (n)
- {
- send_reply_data(pgm_read_byte(p));
- ++p;
- --n;
- }
-}
-
-
-// ---
-// Process write flash page request.
-//
-static void req_write_flash_page(uint16_t page_address, uint16_t len)
-{
- while (!eeprom_is_ready())
- send_keep_alive_reply();
-
- cli();
- boot_page_erase(page_address);
- sei();
-
- while (boot_spm_busy())
- send_keep_alive_reply();
-
- uint8_t page_offset = 0;
- uint8_t p = payload_pos;
- while (len > 1 && page_offset < SPM_PAGESIZE)
- {
- bytes_word_t v;
- v.bytes[0] = rxbuf[p++];
- CHECK_RXBUF_END(p);
- v.bytes[1] = rxbuf[p++];
- CHECK_RXBUF_END(p);
-
- cli();
- boot_page_fill(page_address + page_offset, v.word);
- sei();
-
- page_offset += 2;
- len -= 2;
- }
-
- cli();
- boot_page_write(page_address);
- sei();
-
- while (boot_spm_busy())
- send_keep_alive_reply();
-
- if (boot_rww_busy())
- boot_rww_enable();
-}
-
-
-// ---
-// Process received request.
-//
-static void process_request(void)
-{
- pwm_request_t *r = &actual_req;
- FIX_POINTER(r);
-
- uint8_t req = r->request;
-
- if (req == BL_PWM_REQ_WRITE_PAGE)
- req_write_flash_page(r->index.word, r->length.word);
- else if (req == BL_PWM_REQ_READ_FLASH)
- {
- send_reply_read_flash((PGM_P) r->index.word, r->length.word);
- return;
- }
- else if (req == BL_PWM_REQ_GET_PAGE_SIZE)
- {
- send_reply_start(2);
- send_reply_data(SPM_PAGESIZE & 0xFF);
- send_reply_data(SPM_PAGESIZE >> 8);
- return;
- }
- else if (req == BL_PWM_REQ_GET_REQUEST_ERR_STATUS)
- {
- send_reply_start(1);
- send_reply_data(rx_err_status);
- rx_err_status = 0;
- return;
- }
- else if (req == PWM_REQ_GET_VERSION)
- {
- send_reply_start(2);
- send_reply_data(PWM_VERS_BOOT);
- send_reply_data(FIRMWARE_VERSION);
- return;
- }
-
- send_reply_start(0);
-}
-
-
-// ---
-// Decode data byte of received data.
-//
-static void read_data(void)
-{
- uint8_t p, c, is_req_start;
-
- // Read data from RX buffer
- p = rxrpos;
- is_req_start = (p == rxspos);
- c = rxbuf[p++];
- CHECK_RXBUF_END(p);
- rxrpos = p;
-
- p = header_pos;
- if (is_req_start)
- {
- if (p)
- set_bit(rx_err_status, COMM_ERR_TIMEOUT);
-
- p = 0;
- }
- else if (!p)
- return; // Discard garbage
-
- if (p < sizeof(pwm_request_t))
- {
- pwm_request_t *r = &actual_req;
- FIX_POINTER(r);
-
- r->bytes[p++] = c;
- header_pos = p;
-
- if (p < sizeof(pwm_request_t))
- return;
-
- // Header complete
- if (!(r->request_type & PWMRQ_DEVICE_TO_HOST) && r->length.word)
- {
- payload_pos = rxrpos;
- payload_count = r->length.word;
- return;
- }
- }
- else if (--payload_count)
- return; // Payload not complete
-
- last_keep_alive = sys_clock;
- process_request();
- header_pos = 0;
-}
-
-
-// ---
-// Device initialization and main program loop.
-//
-void main(void) NORETURN;
-void main(void)
-{
- wdt_enable(WDTO_30MS); // Set watchdog timeout
-
- // Port init, enable pull-up resistors for unused ports
- PORTE = PE_INIT;
- DDRE = PE_DDR;
-
- if ((pgm_read_word(APPL_START_VECT) != 0xFFFF) && // Application reset vector programmed?
- bit_is_set(BL_SENSE_PIN, BL_SENSE_BIT))
- { // boot loader disabled -> start application
- void (*jump_to_app)(void) = APPL_START_VECT / 2; // Need flash word address!
- jump_to_app();
- }
-
- GICR = _BV(IVCE); // enable change of interrupt vectors
- GICR = _BV(IVSEL); // move interrupts to boot flash section
-
- // USART init
- // 9 data bits, 1 stop bit, no parity, asynchron mode
- // Enable TX, RX and RX Interrupts
-#include <util/setbaud.h>
- UBRR0H = UBRRH_VALUE;
- UBRR0L = UBRRL_VALUE;
-#if USE_2X
- UCSR0A = _BV(U2X);
-#endif
- UCSR0C = _BV(URSEL0) | _BV(UCSZ01) | _BV(UCSZ00);
- UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) | _BV(UCSZ02);
-
- // Timer 0 is used for system clock
- // Normal mode, Prescaler 64
- TCCR0 = _BV(CS01) | _BV(CS00);
-
- sei();
-
- // Main loop
- for (;;)
- {
- background_processing();
-
- if (rxrpos != rxwpos)
- read_data();
-
- if (header_pos)
- clear_bit(STATUS_LED_PORT, STATUS_LED_BIT); // We are processing a request
- else
- set_bit(STATUS_LED_PORT, STATUS_LED_BIT); // No request
- }
-}
+/*
+ * Copyright (C) 2010 Andreas Auras
+ *
+ * This file is part of the DF10CH Atmolight controller project.
+ *
+ * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DF10CH Atmolight controller is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ */
+
+// ======================================================================
+// Bootloader firmware for PWM processor.
+//
+
+#include <stdint.h>
+#include <string.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <avr/pgmspace.h>
+#include <avr/eeprom.h>
+#include <avr/boot.h>
+
+#include "../df10ch_common.h"
+#include "../df10ch_usb_proto.h"
+
+
+// ---
+// Fuse-Bit settings for the flash programmer (Atmega 162):
+//
+// M161C=1
+// BODLEVEL2=1
+// BODLEVEL1=0
+// BODLEVEL0=0
+//
+// OCDEN=1
+// JTAGEN=1
+// SPIEN=0
+// WDTON=0
+// EESAVE=1
+// BOOTSZ1=0
+// BOOTSZ0=0
+// BOOTRST=0
+//
+// CKDIV8=1
+// CKOUT=1
+// SUT1=0
+// SUT0=1
+// CKSEL3=1
+// CKSEL2=1
+// CKSEL1=1
+// CKSEL0=1
+//
+// Memory-Lock Bits:
+// BLB12=1, BLB11=0, BLB02=1, BLB01=1, LB2=1, LB1=1
+//
+FUSES =
+{
+ .low = (FUSE_SUT1),
+ .high = (FUSE_SPIEN & FUSE_WDTON & FUSE_BOOTSZ1 & FUSE_BOOTSZ0 & FUSE_BOOTRST),
+ .extended = (FUSE_BODLEVEL1 & FUSE_BODLEVEL0),
+};
+LOCKBITS = (LB_MODE_1 & BLB0_MODE_1 & BLB1_MODE_2);
+//SIGNATURE_DATA = { SIGNATURE_2, SIGNATURE_1, SIGNATURE_0 } ;
+
+
+// ---
+// System clock related.
+// System clock is implemented with hardware timer 0
+//
+#define SYS_HWPRESCALE 64 // Hardware Prescaler
+#define SYS_PRESCALER 256 // Timer Prescaler
+
+ // useconds <-> timer ticks conversation
+#define US2TICKS(t) ((uint16_t)((double)(t) * (double)F_CPU / (1000000.0 * (double)SYS_HWPRESCALE * (double)SYS_PRESCALER) + 0.5))
+#define TICKS2US(t) (((t) / (F_CPU / (1000000UL * SYS_HWPRESCALE * SYS_PRESCALER))))
+
+static uint16_t sys_clock;
+
+
+// ---
+// Keep alive reply related
+//
+#define MIN_KEEP_ALIVE_PAUSE US2TICKS(15000)
+
+static uint16_t last_keep_alive;
+
+
+// ---
+// Request parser related variables
+//
+typedef union
+{
+ uint8_t bytes[REQ_HEADER_SIZE];
+ struct
+ {
+ uint8_t request_type;
+ uint8_t request;
+ bytes_word_t value;
+ bytes_word_t index;
+ bytes_word_t length;
+ };
+} pwm_request_t;
+
+static pwm_request_t actual_req;
+static uint8_t header_pos;
+static uint8_t payload_pos;
+static uint8_t payload_count;
+
+
+// ---
+// RX buffer related variables
+//
+#define RXBUF_SIZE (REQ_HEADER_SIZE + MAX_REQ_PAYLOAD_SIZE + 1)
+#if RXBUF_SIZE == 256
+#define CHECK_RXBUF_END(pos)
+#else
+#define CHECK_RXBUF_END(pos) if ((pos) == RXBUF_SIZE) (pos) = 0
+#endif
+
+static uint8_t volatile rxrpos, rxwpos, rxspos, rx_err_status;
+static uint8_t rxbuf[RXBUF_SIZE] NOMEMINIT;
+
+
+// Status LED related
+#define STATUS_LED_PORT PORTE
+#define STATUS_LED_BIT 1
+
+// Input pin for enable/disable of bootloader
+#define BL_SENSE_PIN PINE
+#define BL_SENSE_BIT 0
+
+#define APPL_START_VECT 0x0000
+
+// ---
+// Definition of port direction and initial values.
+//
+#define PE_DDR _BV(STATUS_LED_BIT)
+#define PE_INIT _BV(BL_SENSE_BIT)
+
+
+// ---
+// ISR handler for IRQ's that do not have a dedicated handler.
+//
+EMPTY_INTERRUPT(BADISR_vect)
+
+
+// ---
+// ISR for receiving data.
+//
+ISR(USART0_RXC_vect)
+{
+ do
+ {
+ uint8_t i = rxwpos;
+ uint8_t p = i + 1;
+ CHECK_RXBUF_END(p);
+
+ if (bit_is_set(UCSR0A, FE0))
+ set_bit(rx_err_status, COMM_ERR_FRAME);
+ else if (bit_is_set(UCSR0A, DOR0))
+ set_bit(rx_err_status, COMM_ERR_OVERRUN);
+ else if (p == rxrpos)
+ set_bit(rx_err_status, COMM_ERR_OVERFLOW);
+ else
+ {
+ if (bit_is_set(UCSR0B, RXB80))
+ rxspos = i; // save start of request message
+ rxwpos = p; // set data valid
+ }
+ rxbuf[i] = UDR0; // read data
+ }
+ while (bit_is_set(UCSR0A, RXC0));
+}
+
+
+// ---
+// Processing while waiting for a event.
+//
+static void background_processing(void)
+{
+ wdt_reset();
+
+ // count system clock
+ if (bit_is_set(TIFR, TOV0))
+ {
+ ++sys_clock;
+ TIFR = _BV(TOV0);
+ }
+}
+
+
+// ---
+// Put data into transmit buffer.
+//
+static void send_reply_data(uint8_t c)
+{
+ // Wait until transmit buffer free
+ while (bit_is_clear(UCSR0A, UDRE0))
+ background_processing();
+
+ UDR0 = c;
+}
+
+
+// ---
+// Send reply start.
+//
+static void send_reply_start(uint8_t len)
+{
+ // Wait until transmit buffer free
+ while (bit_is_clear(UCSR0A, UDRE0))
+ background_processing();
+
+ uint8_t id = actual_req.request_type & PWMRQ_ID_MASK;
+ if (len)
+ id |= PWMRP_HAS_PAYLOAD;
+
+ set_bit(UCSR0B, TXB80); // Set 9th bit for start of reply
+ UDR0 = id; // Send reply id
+ clear_bit(UCSR0B, TXB80);
+
+ if (len)
+ send_reply_data(len); // Send reply length
+
+ last_keep_alive = sys_clock;
+}
+
+
+// ---
+// Send keep alive reply.
+//
+static void send_keep_alive_reply(void)
+{
+ background_processing();
+ if ((sys_clock - last_keep_alive) > MIN_KEEP_ALIVE_PAUSE)
+ {
+ // Wait until transmit buffer free
+ while (bit_is_clear(UCSR0A, UDRE0))
+ background_processing();
+
+ set_bit(UCSR0B, TXB80); // Set 9th bit for start of reply
+ UDR0 = PWMRP_KEEP_ALIVE; // Send keep alive ID
+ clear_bit(UCSR0B, TXB80);
+
+ last_keep_alive = sys_clock;
+ }
+}
+
+
+// ---
+// Send reply packet from flash memory.
+//
+static void send_reply_read_flash(PGM_P p, uint16_t n)
+{
+ if (n > MAX_REPLY_PAYLOAD_SIZE)
+ n = 0; // Send nothing!
+
+ send_reply_start((uint8_t)n);
+
+ while (n)
+ {
+ send_reply_data(pgm_read_byte(p));
+ ++p;
+ --n;
+ }
+}
+
+
+// ---
+// Process write flash page request.
+//
+static void req_write_flash_page(uint16_t page_address, uint16_t len)
+{
+ while (!eeprom_is_ready())
+ send_keep_alive_reply();
+
+ cli();
+ boot_page_erase(page_address);
+ sei();
+
+ while (boot_spm_busy())
+ send_keep_alive_reply();
+
+ uint8_t page_offset = 0;
+ uint8_t p = payload_pos;
+ while (len > 1 && page_offset < SPM_PAGESIZE)
+ {
+ bytes_word_t v;
+ v.bytes[0] = rxbuf[p++];
+ CHECK_RXBUF_END(p);
+ v.bytes[1] = rxbuf[p++];
+ CHECK_RXBUF_END(p);
+
+ cli();
+ boot_page_fill(page_address + page_offset, v.word);
+ sei();
+
+ page_offset += 2;
+ len -= 2;
+ }
+
+ cli();
+ boot_page_write(page_address);
+ sei();
+
+ while (boot_spm_busy())
+ send_keep_alive_reply();
+
+ if (boot_rww_busy())
+ boot_rww_enable();
+}
+
+
+// ---
+// Process received request.
+//
+static void process_request(void)
+{
+ pwm_request_t *r = &actual_req;
+ FIX_POINTER(r);
+
+ uint8_t req = r->request;
+
+ if (req == BL_PWM_REQ_WRITE_PAGE)
+ req_write_flash_page(r->index.word, r->length.word);
+ else if (req == BL_PWM_REQ_READ_FLASH)
+ {
+ send_reply_read_flash((PGM_P) r->index.word, r->length.word);
+ return;
+ }
+ else if (req == BL_PWM_REQ_GET_PAGE_SIZE)
+ {
+ send_reply_start(2);
+ send_reply_data(SPM_PAGESIZE & 0xFF);
+ send_reply_data(SPM_PAGESIZE >> 8);
+ return;
+ }
+ else if (req == BL_PWM_REQ_GET_REQUEST_ERR_STATUS)
+ {
+ send_reply_start(1);
+ send_reply_data(rx_err_status);
+ rx_err_status = 0;
+ return;
+ }
+ else if (req == PWM_REQ_GET_VERSION)
+ {
+ send_reply_start(2);
+ send_reply_data(PWM_VERS_BOOT);
+ send_reply_data(FIRMWARE_VERSION);
+ return;
+ }
+
+ send_reply_start(0);
+}
+
+
+// ---
+// Decode data byte of received data.
+//
+static void read_data(void)
+{
+ uint8_t p, c, is_req_start;
+
+ // Read data from RX buffer
+ p = rxrpos;
+ is_req_start = (p == rxspos);
+ c = rxbuf[p++];
+ CHECK_RXBUF_END(p);
+ rxrpos = p;
+
+ p = header_pos;
+ if (is_req_start)
+ {
+ if (p)
+ set_bit(rx_err_status, COMM_ERR_TIMEOUT);
+
+ p = 0;
+ }
+ else if (!p)
+ return; // Discard garbage
+
+ if (p < sizeof(pwm_request_t))
+ {
+ pwm_request_t *r = &actual_req;
+ FIX_POINTER(r);
+
+ r->bytes[p++] = c;
+ header_pos = p;
+
+ if (p < sizeof(pwm_request_t))
+ return;
+
+ // Header complete
+ if (!(r->request_type & PWMRQ_DEVICE_TO_HOST) && r->length.word)
+ {
+ payload_pos = rxrpos;
+ payload_count = r->length.word;
+ return;
+ }
+ }
+ else if (--payload_count)
+ return; // Payload not complete
+
+ last_keep_alive = sys_clock;
+ process_request();
+ header_pos = 0;
+}
+
+
+// ---
+// Device initialization and main program loop.
+//
+void main(void) NORETURN;
+void main(void)
+{
+ wdt_enable(WDTO_30MS); // Set watchdog timeout
+
+ // Port init, enable pull-up resistors for unused ports
+ PORTE = PE_INIT;
+ DDRE = PE_DDR;
+
+ if ((pgm_read_word(APPL_START_VECT) != 0xFFFF) && // Application reset vector programmed?
+ bit_is_set(BL_SENSE_PIN, BL_SENSE_BIT))
+ { // boot loader disabled -> start application
+ void (*jump_to_app)(void) = APPL_START_VECT / 2; // Need flash word address!
+ jump_to_app();
+ }
+
+ GICR = _BV(IVCE); // enable change of interrupt vectors
+ GICR = _BV(IVSEL); // move interrupts to boot flash section
+
+ // USART init
+ // 9 data bits, 1 stop bit, no parity, asynchron mode
+ // Enable TX, RX and RX Interrupts
+#include <util/setbaud.h>
+ UBRR0H = UBRRH_VALUE;
+ UBRR0L = UBRRL_VALUE;
+#if USE_2X
+ UCSR0A = _BV(U2X);
+#endif
+ UCSR0C = _BV(URSEL0) | _BV(UCSZ01) | _BV(UCSZ00);
+ UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) | _BV(UCSZ02);
+
+ // Timer 0 is used for system clock
+ // Normal mode, Prescaler 64
+ TCCR0 = _BV(CS01) | _BV(CS00);
+
+ sei();
+
+ // Main loop
+ for (;;)
+ {
+ background_processing();
+
+ if (rxrpos != rxwpos)
+ read_data();
+
+ if (header_pos)
+ clear_bit(STATUS_LED_PORT, STATUS_LED_BIT); // We are processing a request
+ else
+ set_bit(STATUS_LED_PORT, STATUS_LED_BIT); // No request
+ }
+}
diff --git a/usb_appl/Makefile b/usb_appl/Makefile
index 03ca6d8..97fad42 100644
--- a/usb_appl/Makefile
+++ b/usb_appl/Makefile
@@ -1,109 +1,109 @@
-#
-# Copyright (C) 2010 Andreas Auras
-#
-# This file is part of the DF10CH Atmolight controller project.
-#
-# DF10CH Atmolight controller is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# DF10CH Atmolight controller is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-#
-#
-###############################################################################
-# Makefile for the application firmware of USB processor
-###############################################################################
-
-## General Flags
-PROJECT = 10ch_usb_appl
-MCU = atmega8
-TARGET = 10ch_usb_appl.elf
-CC = avr-gcc
-AVRDUDE ?= avrdude -c stk500v2 -P avrdoper
-USBDRV ?= ../usbdrv
-F_CPU ?= 16000000UL
-FIRMWARE_VERSION ?= 1
-
-## Options common to compile, link and assembly rules
-COMMON = -mmcu=$(MCU)
-
-## Compile options common for all C compilation units.
-CFLAGS = $(COMMON)
-CFLAGS += -Wall -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
-CFLAGS += -DF_CPU=$(F_CPU) -DFIRMWARE_VERSION=$(FIRMWARE_VERSION)
-
-## Assembly specific flags
-ASMFLAGS = $(COMMON)
-ASMFLAGS += $(CFLAGS)
-ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
-
-## Linker flags
-LDFLAGS = $(COMMON)
-LDFLAGS += -Wl,-Map=10ch_usb_appl.map
-
-
-## Intel Hex file production flags
-HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
-
-HEX_EEPROM_FLAGS = -j .eeprom
-HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
-
-## Include Directories
-INCLUDES = -I. -I.. -I$(USBDRV)
-
-## Objects that must be built in order to link
-OBJECTS = 10ch_usb_appl.o usbdrvasm.o
-
-## Objects explicitly added by the user
-LINKONLYOBJECTS =
-
-## Build
-all: $(TARGET) 10ch_usb_appl.dff 10ch_usb_appl.lss size
-
-10ch_usb_appl.dff: 10ch_usb_appl.hex
- echo "@DF10CH-USB" $(FIRMWARE_VERSION) > $@
- cat 10ch_usb_appl.hex >> $@
-
-prog: flash
- $(AVRDUDE) -p $(MCU) -u -Ulfuse:w:0x1F:m -Uhfuse:w:0xC9:m -Ulock:w:0xEF:m
-
-flash: 10ch_usb_appl.hex
- $(AVRDUDE) -p $(MCU) -Uflash:w:10ch_usb_appl.hex:i
-
-
-## Compile
-usbdrvasm.o: $(USBDRV)/usbdrvasm.S usbconfig.h
- $(CC) $(INCLUDES) $(ASMFLAGS) -c $<
-
-10ch_usb_appl.o: 10ch_usb_appl.c usbconfig.h ../df10ch_usb_proto.h ../df10ch_common.h
- $(CC) $(INCLUDES) $(CFLAGS) -c $<
-
-##Link
-$(TARGET): $(OBJECTS)
- $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
-
-%.hex: $(TARGET)
- avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
-
-%.eep: $(TARGET)
- -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
-
-%.lss: $(TARGET)
- avr-objdump -h -S $< > $@
-
-size: ${TARGET}
- @echo
- @avr-size -C --mcu=${MCU} ${TARGET}
-
-## Clean target
-.PHONY: clean
-clean:
- -rm -rf $(OBJECTS) 10ch_usb_appl.elf 10ch_usb_appl.dff 10ch_usb_appl.hex 10ch_usb_appl.eep 10ch_usb_appl.lss 10ch_usb_appl.map
+#
+# Copyright (C) 2010 Andreas Auras
+#
+# This file is part of the DF10CH Atmolight controller project.
+#
+# DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# DF10CH Atmolight controller is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+#
+#
+###############################################################################
+# Makefile for the application firmware of USB processor
+###############################################################################
+
+## General Flags
+PROJECT = df10ch_usb_appl
+MCU = atmega8
+TARGET = df10ch_usb_appl.elf
+CC = avr-gcc
+AVRDUDE ?= avrdude -c stk500v2 -P avrdoper
+USBDRV ?= ../usbdrv
+F_CPU ?= 16000000UL
+FIRMWARE_VERSION ?= 1
+
+## Options common to compile, link and assembly rules
+COMMON = -mmcu=$(MCU)
+
+## Compile options common for all C compilation units.
+CFLAGS = $(COMMON)
+CFLAGS += -Wall -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -DF_CPU=$(F_CPU) -DFIRMWARE_VERSION=$(FIRMWARE_VERSION)
+
+## Assembly specific flags
+ASMFLAGS = $(COMMON)
+ASMFLAGS += $(CFLAGS)
+ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
+
+## Linker flags
+LDFLAGS = $(COMMON)
+LDFLAGS += -Wl,-Map=df10ch_usb_appl.map
+
+
+## Intel Hex file production flags
+HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
+
+HEX_EEPROM_FLAGS = -j .eeprom
+HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
+
+## Include Directories
+INCLUDES = -I. -I.. -I$(USBDRV)
+
+## Objects that must be built in order to link
+OBJECTS = df10ch_usb_appl.o usbdrvasm.o
+
+## Objects explicitly added by the user
+LINKONLYOBJECTS =
+
+## Build
+all: $(TARGET) df10ch_usb_appl.dff df10ch_usb_appl.lss size
+
+df10ch_usb_appl.dff: df10ch_usb_appl.hex
+ echo "@DF10CH-USB" $(FIRMWARE_VERSION) > $@
+ cat df10ch_usb_appl.hex >> $@
+
+prog: flash
+ $(AVRDUDE) -p $(MCU) -u -Ulfuse:w:0x1F:m -Uhfuse:w:0xC9:m -Ulock:w:0xEF:m
+
+flash: df10ch_usb_appl.hex
+ $(AVRDUDE) -p $(MCU) -Uflash:w:df10ch_usb_appl.hex:i
+
+
+## Compile
+usbdrvasm.o: $(USBDRV)/usbdrvasm.S usbconfig.h
+ $(CC) $(INCLUDES) $(ASMFLAGS) -c $<
+
+df10ch_usb_appl.o: df10ch_usb_appl.c usbconfig.h ../df10ch_usb_proto.h ../df10ch_common.h
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<
+
+##Link
+$(TARGET): $(OBJECTS)
+ $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
+
+%.hex: $(TARGET)
+ avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
+
+%.eep: $(TARGET)
+ -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
+
+%.lss: $(TARGET)
+ avr-objdump -h -S $< > $@
+
+size: ${TARGET}
+ @echo
+ @avr-size -C --mcu=${MCU} ${TARGET}
+
+## Clean target
+.PHONY: clean
+clean:
+ -rm -rf $(OBJECTS) df10ch_usb_appl.elf df10ch_usb_appl.dff df10ch_usb_appl.hex df10ch_usb_appl.eep df10ch_usb_appl.lss df10ch_usb_appl.map
diff --git a/usb_appl/10ch_usb_appl.c b/usb_appl/df10ch_usb_appl.c
index 3728c55..ba0d2c8 100644
--- a/usb_appl/10ch_usb_appl.c
+++ b/usb_appl/df10ch_usb_appl.c
@@ -1,838 +1,838 @@
-/*
- * Copyright (C) 2010 Andreas Auras
- *
- * This file is part of the DF10CH Atmolight controller project.
- *
- * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * DF10CH Atmolight controller is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- */
-
-// ======================================================================
-// Application firmware for USB processor.
-//
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <avr/wdt.h>
-#include <avr/eeprom.h>
-#include <avr/sleep.h>
-
-#include "../df10ch_common.h"
-#include "../df10ch_usb_proto.h"
-#include "usbconfig.h"
-
-
-// ---
-// Fuse-Bit settings for the flash programmer (ATmega8):
-// RSTDISBL=1
-// WDTON=1
-// SPIEN=0
-// CKOPT=0
-// EESAVE=1
-// BOOTSZ1=0
-// BOOTSZ0=0
-// BOOTRST=1
-//
-// BODLEVEL=0
-// BODEN=0
-// SUT1=0
-// SUT0=1
-// CKSEL3=1
-// CKSEL2=1
-// CKSEL1=1
-// CKSEL0=1
-//
-// Memory-Lock Bits:
-// BL12=1, BL11=0, BL02=1, BL01=1, LB2=1, LB1=1
-//
-FUSES =
-{
- .low = (FUSE_BODLEVEL & FUSE_BODEN & FUSE_SUT1),
- .high = (FUSE_SPIEN & FUSE_CKOPT & FUSE_BOOTSZ1 & FUSE_BOOTSZ0)
-};
-LOCKBITS = (LB_MODE_1 & BLB0_MODE_1 & BLB1_MODE_2);
-//SIGNATURE_DATA = { SIGNATURE_2, SIGNATURE_1, SIGNATURE_0 } ;
-
-
-#define EE_MEM_SIZE (E2END + 1)
-
-
-// ---
-// System clock related.
-// System clock ist implemented with hardware timer 1
-//
-#define SYS_HWPRESCALE 1024 // Hardware Prescaler
-
- // useconds <-> timer ticks conversation
-#define US2TICKS(t) ((uint16_t)((double)(t) * (double)F_CPU / (1000000.0 * (double)SYS_HWPRESCALE) + 0.5))
-#define TICKS2US(t) ((uint16_t)((t) / (F_CPU / (1000000UL * SYS_HWPRESCALE))))
-
-
-// ---
-// pwm controller reset related.
-//
-#define RESET_TIME US2TICKS(128UL)
-#define STARTUP_TIME US2TICKS(10000UL)
-
- // Output pin for PWM controller reset
-#define RESET_PORT PORTB
-#define RESET_BIT 4
-
- // Output pin for enabling PWM controller bootloader
-#define BOOTLOADER_PORT PORTB
-#define BOOTLOADER_BIT 3
-
-
-// ---
-// bootloader related.
-//
-#define BL_START_VECT 0x1800
-
-// Input/Output pin for bootloader startup
-#define BL_SENSE_DDR DDRB
-#define BL_SENSE_PORT PORTB
-#define BL_SENSE_PIN PINB
-#define BL_SENSE_BIT 0
-
-#define BL_START_DELAY_TIME US2TICKS(30000UL)
-
-static uint8_t bl_start;
-static uint16_t bl_time;
-
-
-// ---
-// USB related.
-//
-#define USB_SLEEP_TIMEOUT US2TICKS(5000UL)
-#define USB_DISCONNECT_TIME US2TICKS(500000UL)
-#define USB_INITIALIZE_TIMEOUT US2TICKS(1750000UL)
-#define USB_STALL_RC 0xFF
-
+/*
+ * Copyright (C) 2010 Andreas Auras
+ *
+ * This file is part of the DF10CH Atmolight controller project.
+ *
+ * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DF10CH Atmolight controller is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ */
+
+// ======================================================================
+// Application firmware for USB processor.
+//
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <avr/eeprom.h>
+#include <avr/sleep.h>
+
+#include "../df10ch_common.h"
+#include "../df10ch_usb_proto.h"
+#include "usbconfig.h"
+
+
+// ---
+// Fuse-Bit settings for the flash programmer (ATmega8):
+// RSTDISBL=1
+// WDTON=1
+// SPIEN=0
+// CKOPT=0
+// EESAVE=1
+// BOOTSZ1=0
+// BOOTSZ0=0
+// BOOTRST=1
+//
+// BODLEVEL=0
+// BODEN=0
+// SUT1=0
+// SUT0=1
+// CKSEL3=1
+// CKSEL2=1
+// CKSEL1=1
+// CKSEL0=1
+//
+// Memory-Lock Bits:
+// BL12=1, BL11=0, BL02=1, BL01=1, LB2=1, LB1=1
+//
+FUSES =
+{
+ .low = (FUSE_BODLEVEL & FUSE_BODEN & FUSE_SUT1),
+ .high = (FUSE_SPIEN & FUSE_CKOPT & FUSE_BOOTSZ1 & FUSE_BOOTSZ0)
+};
+LOCKBITS = (LB_MODE_1 & BLB0_MODE_1 & BLB1_MODE_2);
+//SIGNATURE_DATA = { SIGNATURE_2, SIGNATURE_1, SIGNATURE_0 } ;
+
+
+#define EE_MEM_SIZE (E2END + 1)
+
+
+// ---
+// System clock related.
+// System clock ist implemented with hardware timer 1
+//
+#define SYS_HWPRESCALE 1024 // Hardware Prescaler
+
+ // useconds <-> timer ticks conversation
+#define US2TICKS(t) ((uint16_t)((double)(t) * (double)F_CPU / (1000000.0 * (double)SYS_HWPRESCALE) + 0.5))
+#define TICKS2US(t) ((uint16_t)((t) / (F_CPU / (1000000UL * SYS_HWPRESCALE))))
+
+
+// ---
+// pwm controller reset related.
+//
+#define RESET_TIME US2TICKS(128UL)
+#define STARTUP_TIME US2TICKS(10000UL)
+
+ // Output pin for PWM controller reset
+#define RESET_PORT PORTB
+#define RESET_BIT 4
+
+ // Output pin for enabling PWM controller bootloader
+#define BOOTLOADER_PORT PORTB
+#define BOOTLOADER_BIT 3
+
+
+// ---
+// bootloader related.
+//
+#define BL_START_VECT 0x1800
+
+// Input/Output pin for bootloader startup
+#define BL_SENSE_DDR DDRB
+#define BL_SENSE_PORT PORTB
+#define BL_SENSE_PIN PINB
+#define BL_SENSE_BIT 0
+
+#define BL_START_DELAY_TIME US2TICKS(30000UL)
+
+static uint8_t bl_start;
+static uint16_t bl_time;
+
+
+// ---
+// USB related.
+//
+#define USB_SLEEP_TIMEOUT US2TICKS(5000UL)
+#define USB_DISCONNECT_TIME US2TICKS(500000UL)
+#define USB_INITIALIZE_TIMEOUT US2TICKS(1750000UL)
+#define USB_STALL_RC 0xFF
+
volatile uint16_t usb_sof_time; // Time of last USB start of frame IRQ
-static uint8_t usb_is_resetting; // Is true while reset condition on USB bus happen
-static uint8_t usb_is_initialized; // Is true after USB address has been set
-static uint8_t usb_last_data_token; // Token PID of last usb packet received
-static uint8_t usb_last_rc; // Return status of last payload packet
-static uint8_t payload_req; // ID of actual proccessed USB request
-static uint16_t payload_pos; // Position of actual payload read/write
-static uint16_t payload_count; // Number of bytes left of actual payload read/write
-
-
-
-// ---
-// RX buffer related.
-//
-#define RXBUF_SIZE 256
-#if RXBUF_SIZE == 256
-#define CHECK_RXBUF_END(pos)
-#else
-#define CHECK_RXBUF_END(pos) if ((pos) == RXBUF_SIZE) (pos) = 0
-#endif
-
-static volatile uint8_t rxrpos, rxwpos;
-static volatile uint8_t rxspos; // Start position of reply
-static uint8_t rxbuf[RXBUF_SIZE] NOMEMINIT;
-
-
-// ---
-// TX buffer related.
-//
-#define TXBUF_SIZE 256
-#if TXBUF_SIZE == 256
-#define CHECK_TXBUF_END(pos)
-#else
-#define CHECK_TXBUF_END(pos) if ((pos) == TXBUF_SIZE) (pos) = 0
-#endif
-
-static uint8_t txrpos, txwpos;
-static uint8_t txbuf[TXBUF_SIZE] NOMEMINIT;
-
-
-// ---
-// PWM controller communication related.
-//
-#define REPLY_START_TIMEOUT US2TICKS(50000UL)
-#define REPLY_TIMEOUT US2TICKS(10000UL)
-
-static uint8_t actual_req_id;
-static uint8_t reply_start;
-static uint8_t reply_count;
-static volatile uint8_t reply_err_status;
-static uint16_t reply_start_timeout = REPLY_START_TIMEOUT;
-static uint16_t reply_timeout = REPLY_TIMEOUT;
-
-
-// ---
-// Port setup related.
-//
-#define PORTB_INIT (_BV(BL_SENSE_BIT) | _BV(BOOTLOADER_BIT) | _BV(1) | _BV(2) | _BV(5))
-#define DDRB_INIT (_BV(BOOTLOADER_BIT) | _BV(RESET_BIT))
-
-#define PORTC_INIT (0xFF)
-#define DDRC_INIT (0)
-
-#define PORTD_INIT (_BV(1) | _BV(5) | _BV(6) | _BV(7))
-#define DDRD_INIT (_BV(1))
-
-
-#include <usbdrv.c>
-
-
-// ---
-// ISR handler for IRQ's that do not have a dedicated handler.
-//
-ISR(BADISR_vect)
-{
- for (;;); // wait until watchdog resets device
-}
-
-
-// ---
-// ISR for receiving data.
-//
-ISR(USART_RXC_vect)
-{
- clear_bit(UCSRB, RXCIE);
- sei();
-
- do
- {
- uint8_t i = rxwpos;
- uint8_t p = i + 1;
- CHECK_RXBUF_END(p);
-
- if (bit_is_set(UCSRA, DOR))
- set_bit(reply_err_status, COMM_ERR_OVERRUN);
- else if (bit_is_set(UCSRA, FE))
- set_bit(reply_err_status, COMM_ERR_FRAME);
- else if (p == rxrpos)
- set_bit(reply_err_status, COMM_ERR_OVERFLOW);
- else
- {
- if (bit_is_set(UCSRB, RXB8))
- rxspos = i; // save reply start position
- rxwpos = p; // set data valid
- }
- rxbuf[i] = UDR; // read data
- }
- while (bit_is_set(UCSRA, RXC));
-
- cli();
- set_bit(UCSRB, RXCIE);
-}
-
-
-// ---
-// Read actual system clock counter.
-// Note: Counter is also read inside USB irq handler -> we need save read!
-//
-static uint16_t get_sys_clock(void)
-{
- uint8_t sreg = SREG;
- cli();
- uint16_t t = TCNT1;
- SREG = sreg;
- nop();
- return t;
-}
-
-
-// ---
-// Calculate timer ticks from milliseconds.
-//
-static uint16_t ms_to_ticks(uint16_t ms)
-{
- uint32_t t = F_CPU / SYS_HWPRESCALE;
- t *= ms;
- t /= 1000;
- return (uint16_t) t;
-}
-
-
-// ---
-// Processing while waiting for a event.
-//
-static void background_processing(void)
-{
- wdt_reset();
-
- // Write data from transmit buffer to USART
- while (bit_is_set(UCSRA, UDRE))
- {
- uint8_t p = txrpos;
- if (p == txwpos)
- break;
-
- UDR = txbuf[p++];
- CHECK_TXBUF_END(p);
- txrpos = p;
- }
-}
-
-
-// ---
-// Timer based delay.
-//
-static void timer_delay(uint16_t d)
-{
- uint16_t t = get_sys_clock();
- while ((get_sys_clock() - t) < d)
- background_processing();
-}
-
-
-// ---
-// Put data into transmit buffer.
-//
-static void send_data(uint8_t c)
-{
- uint8_t p = txwpos + 1;
- CHECK_TXBUF_END(p);
-
- // Wait until space available
- while (p == txrpos)
- background_processing();
-
- txbuf[txwpos] = c;
- txwpos = p;
-
- background_processing();
-}
-
-
-// ---
-// Send command request for PWM controller.
-//
-static void send_request(uint8_t req_type)
-{
- // Wait until transmit buffers are empty
- while (txrpos != txwpos || bit_is_clear(UCSRA, UDRE))
- background_processing();
-
- rxspos = rxwpos - 1; // Reset start reply position
-
- ++actual_req_id;
- actual_req_id &= PWMRQ_ID_MASK;
-
- set_bit(UCSRB, TXB8); // Set 9th bit for start of request
- UDR = req_type | actual_req_id; // Send request type and id unbuffered
- clear_bit(UCSRB, TXB8);
-}
-
-
-// ---
-// Read reply data.
-//
-static uint8_t read_data(void)
-{
- uint8_t p = rxrpos;
- uint8_t c = rxbuf[p++];
- CHECK_RXBUF_END(p);
- rxrpos = p;
- return c;
-}
-
-
-// ---
-// Wait for reply data from PWM controller.
-//
-static uint8_t wait_for_reply(void)
-{
- uint16_t t = get_sys_clock();
- uint16_t d = reply_timeout;
-
- while ((get_sys_clock() - t) < d)
- {
- background_processing();
-
- if (rxwpos != rxrpos)
- {
- if (reply_start == rxspos) // Check for same reply
- return 1;
- set_bit(reply_err_status, COMM_ERR_START);
- return 0;
- }
- }
-
- set_bit(reply_err_status, COMM_ERR_TIMEOUT);
- return 0;
-}
-
-
-// ---
-// Wait for start of reply data from PWM controller.
-//
-static uint8_t wait_for_reply_start(void)
-{
- uint16_t t = get_sys_clock();
- uint16_t d = reply_start_timeout;
-
- while ((get_sys_clock() - t) < d)
- {
- background_processing();
-
- uint8_t p = rxrpos;
- if (rxwpos != p)
- {
- if (rxspos == p)
- { // reply start detected
- uint8_t id = read_data();
- if (id == PWMRP_KEEP_ALIVE)
- { // keep alive reply
- t = get_sys_clock();
- continue;
- }
- if ((id & PWMRQ_ID_MASK) == actual_req_id)
- { // reply is for actual request
- reply_start = p;
- if (!(id & PWMRP_HAS_PAYLOAD))
- {
- reply_count = 0;
- return 1;
- }
- if (wait_for_reply())
- {
- reply_count = read_data();
- return 1;
- }
- return 0;
- }
- }
- // drop garbagge
- ++p;
- CHECK_RXBUF_END(p);
- rxrpos = p;
- }
-
- if (bit_is_clear(UCSRA, TXC))
- t = get_sys_clock();
- }
-
- set_bit(reply_err_status, COMM_ERR_TIMEOUT);
- return 0;
-}
-
-
-// ---
-// Stop PWM controller.
-//
-static void stop_pwm_ctrl(void)
-{
- clear_bit(UCSRB, RXEN); // Disable USART RX
- clear_bit(RESET_PORT, RESET_BIT);
-}
-
-
-// ---
-// Reset PWM controller.
-//
-static void reset_pwm_ctrl(void)
-{
- stop_pwm_ctrl();
- timer_delay(RESET_TIME);
-
- set_bit(RESET_PORT, RESET_BIT);
- timer_delay(STARTUP_TIME);
-
- rxwpos = rxrpos = 0; // Flush reply buffer
- reply_err_status = 0;
-
- set_bit(UCSRB, RXEN); // Enable USART RX
-}
-
-
-// ---
-// Send PWM controller request payload data.
-//
-static uint8_t send_payload_data(uint8_t *data, uint8_t len)
-{
- if(len > payload_count)
- len = payload_count;
- payload_count -= len;
-
- uint8_t i = 0;
- while (i < len)
- send_data(data[i++]);
-
- if (!payload_count)
- {
- if (wait_for_reply_start()) // Wait for ACK
- return 1; // all done successfull
- return USB_STALL_RC; // error happen
- }
-
- return 0; // next packet
-}
-
-
-// ---
-// Read PWM controller request payload data.
-//
-static uint8_t read_payload_data(uint8_t *data, uint8_t len)
-{
- if (len > reply_count)
- len = reply_count;
- if(len > payload_count)
- len = payload_count;
- reply_count -= len;
- payload_count -= len;
-
- uint8_t i = 0;
- while (i < len && wait_for_reply())
- data[i++] = read_data();
-
- if (i < len)
- return USB_STALL_RC; // error happen
-
- return i;
-}
-
-
-// ---
-// Write EE prom data.
-//
-static uint8_t write_ee_data(uint8_t *data, uint8_t len)
-{
- if(len > payload_count)
- len = payload_count;
- payload_count -= len;
-
- uint8_t i = 0;
- while (i < len && payload_pos < EE_MEM_SIZE)
- {
- uint8_t old_data = eeprom_read_byte((uint8_t *)payload_pos);
- uint8_t new_data = data[i];
- if (old_data != new_data)
- {
- eeprom_write_byte((uint8_t *)payload_pos, new_data);
-
- while (!eeprom_is_ready())
- background_processing();
-
- old_data = eeprom_read_byte((uint8_t *)payload_pos);
- if (old_data != new_data)
- return USB_STALL_RC; // write error
- }
- ++i;
- ++payload_pos;
- }
-
- return payload_count == 0;
-}
-
-
-// ---
-// Read EE prom data.
-//
-static uint8_t read_ee_data(uint8_t *data, uint8_t len)
-{
- if(len > payload_count)
- len = payload_count;
- payload_count -= len;
-
- uint8_t i = 0;
- while (i < len && payload_pos < EE_MEM_SIZE)
- {
- data[i] = eeprom_read_byte((uint8_t *)payload_pos);
- ++i;
- ++payload_pos;
- }
-
- return i;
-}
-
-
-// ---
-// Write request payload data.
-//
-USB_PUBLIC uint8_t usbFunctionWrite(uint8_t *data, uint8_t len)
-{
- uint8_t rc = USB_STALL_RC;
-
- if (usb_last_rc != USB_STALL_RC)
- {
- if (len != 8 || usbCrc16(data, 8) == ((uint16_t *)data)[4])
- {
- if (usbCurrentDataToken == usb_last_data_token)
- {
- set_bit(reply_err_status, COMM_ERR_DUPLICATE);
- return usb_last_rc; // Ignore packet
- }
-
- if (payload_req >= REQ_PWM_START)
- rc = send_payload_data(data, len);
- else if (payload_req == REQ_WRITE_EE_DATA)
- rc = write_ee_data(data, len);
- }
- else
- set_bit(reply_err_status, COMM_ERR_CRC);
- }
-
- usb_last_data_token = usbCurrentDataToken;
- usb_last_rc = rc;
-
- return rc;
-}
-
-
-// ---
-// Read request payload data.
-//
-USB_PUBLIC uint8_t usbFunctionRead(uint8_t *data, uint8_t len)
-{
- uint8_t rc = USB_STALL_RC;
-
- if (usb_last_rc != USB_STALL_RC)
- {
- if (payload_req >= REQ_PWM_START)
- rc = read_payload_data(data, len);
- else if (payload_req == REQ_READ_EE_DATA)
- rc = read_ee_data(data, len);
- }
-
- usb_last_rc = rc;
-
- return rc;
-}
-
-
-// ---
-// Handle a non-standard USB SETUP packet.
-//
-USB_PUBLIC usbMsgLen_t usbFunctionSetup(uint8_t data[8])
-{
- usbRequest_t *r = (usbRequest_t *) data;
- static uint8_t reply[1];
-
- usb_last_data_token = USBPID_SETUP;
- usb_last_rc = USB_STALL_RC;
- uint8_t rc = USB_NO_MSG;
-
- if (usbCrc16(data, 8) != ((uint16_t *)data)[4])
- {
- set_bit(reply_err_status, COMM_ERR_CRC);
- return rc;
- }
-
- uint8_t req = r->bRequest;
-
- if (req >= REQ_PWM_START)
- {
- if (bit_is_clear (RESET_PORT, RESET_BIT))
- reset_pwm_ctrl();
-
- uint8_t req_type = (r->bmRequestType & USBRQ_DIR_MASK) == USBRQ_DIR_DEVICE_TO_HOST ? PWMRQ_DEVICE_TO_HOST: 0;
- if (r->wLength.word <= MAX_REQ_PAYLOAD_SIZE)
- {
- send_request(req_type);
- send_data(req);
- send_data(r->wValue.bytes[0]);
- send_data(r->wValue.bytes[1]);
- send_data(r->wIndex.bytes[0]);
- send_data(r->wIndex.bytes[1]);
- send_data(r->wLength.bytes[0]);
- send_data(r->wLength.bytes[1]);
-
- payload_req = req;
- payload_count = r->wLength.word;
-
- if (req_type == PWMRQ_DEVICE_TO_HOST || !r->wLength.word)
- {
- if (wait_for_reply_start())
- {
- if (reply_count && r->wLength.word)
- usb_last_rc = 0;
- else
- rc = 0;
- }
- }
- else
- usb_last_rc = 0;
- }
- }
- else if (req == REQ_READ_EE_DATA || req == REQ_WRITE_EE_DATA)
- {
- if (r->wLength.word)
- {
- payload_pos = r->wIndex.word;
- payload_req = req;
- payload_count = r->wLength.word;
- usb_last_rc = 0;
- }
- else
- rc = 0;
- }
- else if (req == REQ_STOP_PWM_CTRL)
- {
- set_bit(BOOTLOADER_PORT, BOOTLOADER_BIT);
- stop_pwm_ctrl();
- rc = 0;
- }
- else if (req == REQ_RESET_PWM_CTRL)
- {
- set_bit(BOOTLOADER_PORT, BOOTLOADER_BIT);
- reset_pwm_ctrl();
- rc = 0;
- }
- else if (req == REQ_BOOTLOADER_RESET_PWM_CTRL)
- {
- clear_bit(BOOTLOADER_PORT, BOOTLOADER_BIT);
- reset_pwm_ctrl();
- rc = 0;
- }
- else if (req == REQ_GET_REPLY_ERR_STATUS)
- {
- reply[0] = reply_err_status;
- reply_err_status = 0;
- usbMsgPtr = reply;
- rc = 1;
- }
- else if (req == REQ_SET_REPLY_TIMEOUT)
- {
- reply_start_timeout = ms_to_ticks(r->wValue.word);
- reply_timeout = ms_to_ticks(r->wIndex.word);
- rc = 0;
- }
- else if (req == REQ_START_BOOTLOADER)
- {
- bl_start = 1;
- bl_time = get_sys_clock();
- rc = 0;
- }
-
- return rc;
-}
-
-
-// ----
-// Main
-//
-void main(void) NORETURN;
-void main(void)
-{
- wdt_enable(WDTO_120MS); // Set watchdog timeout
-
- // Initialize Ports
- PORTB = PORTB_INIT;
- DDRB = DDRB_INIT;
- PORTC = PORTC_INIT;
- DDRC = DDRC_INIT;
- PORTD = PORTD_INIT;
- DDRD = DDRD_INIT;
-
- usbDeviceDisconnect();
-
- set_bit(ACSR, ACD); // Disable analog comparator saving some power
-
- // Initialize Timer 1
- TCNT1 = 0;
- TCCR1B = _BV(CS12) | _BV(CS10); // Start timer 1, Prescaler 1024
-
- // Initialize USART
-#include <util/setbaud.h>
- UBRRH = UBRRH_VALUE;
- UBRRL = UBRRL_VALUE;
-#if USE_2X
- UCSRA = _BV(U2X);
-#endif
- UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // 9 data bits, 1 stop bit, no parity, asynchron mode
- UCSRB = _BV(TXEN) | _BV(UCSZ2) | _BV(RXCIE); // Enable TX and RX IRQ
-
- reset_pwm_ctrl();
-
- timer_delay(USB_DISCONNECT_TIME);
- usbDeviceConnect();
- usbInit();
-
- sei();
-
- // Main loop
- for (;;)
- {
- background_processing();
-
- usbPoll(); // process USB requests
-
- if ((bit_is_clear(BL_SENSE_PIN, BL_SENSE_BIT) ||
- (bl_start && (get_sys_clock() - bl_time) > BL_START_DELAY_TIME)) &&
- pgm_read_word(BL_START_VECT) != 0xFFFF)
- {
- cli();
- stop_pwm_ctrl();
- clear_bit(USB_INTR_ENABLE, USB_INTR_ENABLE_BIT); // Stop USB
- UCSRB = 0; // Stop USART
+static uint8_t usb_is_resetting; // Is true while reset condition on USB bus happen
+static uint8_t usb_is_initialized; // Is true after USB address has been set
+static uint8_t usb_last_data_token; // Token PID of last usb packet received
+static uint8_t usb_last_rc; // Return status of last payload packet
+static uint8_t payload_req; // ID of actual proccessed USB request
+static uint16_t payload_pos; // Position of actual payload read/write
+static uint16_t payload_count; // Number of bytes left of actual payload read/write
+
+
+
+// ---
+// RX buffer related.
+//
+#define RXBUF_SIZE 256
+#if RXBUF_SIZE == 256
+#define CHECK_RXBUF_END(pos)
+#else
+#define CHECK_RXBUF_END(pos) if ((pos) == RXBUF_SIZE) (pos) = 0
+#endif
+
+static volatile uint8_t rxrpos, rxwpos;
+static volatile uint8_t rxspos; // Start position of reply
+static uint8_t rxbuf[RXBUF_SIZE] NOMEMINIT;
+
+
+// ---
+// TX buffer related.
+//
+#define TXBUF_SIZE 256
+#if TXBUF_SIZE == 256
+#define CHECK_TXBUF_END(pos)
+#else
+#define CHECK_TXBUF_END(pos) if ((pos) == TXBUF_SIZE) (pos) = 0
+#endif
+
+static uint8_t txrpos, txwpos;
+static uint8_t txbuf[TXBUF_SIZE] NOMEMINIT;
+
+
+// ---
+// PWM controller communication related.
+//
+#define REPLY_START_TIMEOUT US2TICKS(50000UL)
+#define REPLY_TIMEOUT US2TICKS(10000UL)
+
+static uint8_t actual_req_id;
+static uint8_t reply_start;
+static uint8_t reply_count;
+static volatile uint8_t reply_err_status;
+static uint16_t reply_start_timeout = REPLY_START_TIMEOUT;
+static uint16_t reply_timeout = REPLY_TIMEOUT;
+
+
+// ---
+// Port setup related.
+//
+#define PORTB_INIT (_BV(BL_SENSE_BIT) | _BV(BOOTLOADER_BIT) | _BV(1) | _BV(2) | _BV(5))
+#define DDRB_INIT (_BV(BOOTLOADER_BIT) | _BV(RESET_BIT))
+
+#define PORTC_INIT (0xFF)
+#define DDRC_INIT (0)
+
+#define PORTD_INIT (_BV(1) | _BV(5) | _BV(6) | _BV(7))
+#define DDRD_INIT (_BV(1))
+
+
+#include <usbdrv.c>
+
+
+// ---
+// ISR handler for IRQ's that do not have a dedicated handler.
+//
+ISR(BADISR_vect)
+{
+ for (;;); // wait until watchdog resets device
+}
+
+
+// ---
+// ISR for receiving data.
+//
+ISR(USART_RXC_vect)
+{
+ clear_bit(UCSRB, RXCIE);
+ sei();
+
+ do
+ {
+ uint8_t i = rxwpos;
+ uint8_t p = i + 1;
+ CHECK_RXBUF_END(p);
+
+ if (bit_is_set(UCSRA, DOR))
+ set_bit(reply_err_status, COMM_ERR_OVERRUN);
+ else if (bit_is_set(UCSRA, FE))
+ set_bit(reply_err_status, COMM_ERR_FRAME);
+ else if (p == rxrpos)
+ set_bit(reply_err_status, COMM_ERR_OVERFLOW);
+ else
+ {
+ if (bit_is_set(UCSRB, RXB8))
+ rxspos = i; // save reply start position
+ rxwpos = p; // set data valid
+ }
+ rxbuf[i] = UDR; // read data
+ }
+ while (bit_is_set(UCSRA, RXC));
+
+ cli();
+ set_bit(UCSRB, RXCIE);
+}
+
+
+// ---
+// Read actual system clock counter.
+// Note: Counter is also read inside USB irq handler -> we need save read!
+//
+static uint16_t get_sys_clock(void)
+{
+ uint8_t sreg = SREG;
+ cli();
+ uint16_t t = TCNT1;
+ SREG = sreg;
+ nop();
+ return t;
+}
+
+
+// ---
+// Calculate timer ticks from milliseconds.
+//
+static uint16_t ms_to_ticks(uint16_t ms)
+{
+ uint32_t t = F_CPU / SYS_HWPRESCALE;
+ t *= ms;
+ t /= 1000;
+ return (uint16_t) t;
+}
+
+
+// ---
+// Processing while waiting for a event.
+//
+static void background_processing(void)
+{
+ wdt_reset();
+
+ // Write data from transmit buffer to USART
+ while (bit_is_set(UCSRA, UDRE))
+ {
+ uint8_t p = txrpos;
+ if (p == txwpos)
+ break;
+
+ UDR = txbuf[p++];
+ CHECK_TXBUF_END(p);
+ txrpos = p;
+ }
+}
+
+
+// ---
+// Timer based delay.
+//
+static void timer_delay(uint16_t d)
+{
+ uint16_t t = get_sys_clock();
+ while ((get_sys_clock() - t) < d)
+ background_processing();
+}
+
+
+// ---
+// Put data into transmit buffer.
+//
+static void send_data(uint8_t c)
+{
+ uint8_t p = txwpos + 1;
+ CHECK_TXBUF_END(p);
+
+ // Wait until space available
+ while (p == txrpos)
+ background_processing();
+
+ txbuf[txwpos] = c;
+ txwpos = p;
+
+ background_processing();
+}
+
+
+// ---
+// Send command request for PWM controller.
+//
+static void send_request(uint8_t req_type)
+{
+ // Wait until transmit buffers are empty
+ while (txrpos != txwpos || bit_is_clear(UCSRA, UDRE))
+ background_processing();
+
+ rxspos = rxwpos - 1; // Reset start reply position
+
+ ++actual_req_id;
+ actual_req_id &= PWMRQ_ID_MASK;
+
+ set_bit(UCSRB, TXB8); // Set 9th bit for start of request
+ UDR = req_type | actual_req_id; // Send request type and id unbuffered
+ clear_bit(UCSRB, TXB8);
+}
+
+
+// ---
+// Read reply data.
+//
+static uint8_t read_data(void)
+{
+ uint8_t p = rxrpos;
+ uint8_t c = rxbuf[p++];
+ CHECK_RXBUF_END(p);
+ rxrpos = p;
+ return c;
+}
+
+
+// ---
+// Wait for reply data from PWM controller.
+//
+static uint8_t wait_for_reply(void)
+{
+ uint16_t t = get_sys_clock();
+ uint16_t d = reply_timeout;
+
+ while ((get_sys_clock() - t) < d)
+ {
+ background_processing();
+
+ if (rxwpos != rxrpos)
+ {
+ if (reply_start == rxspos) // Check for same reply
+ return 1;
+ set_bit(reply_err_status, COMM_ERR_START);
+ return 0;
+ }
+ }
+
+ set_bit(reply_err_status, COMM_ERR_TIMEOUT);
+ return 0;
+}
+
+
+// ---
+// Wait for start of reply data from PWM controller.
+//
+static uint8_t wait_for_reply_start(void)
+{
+ uint16_t t = get_sys_clock();
+ uint16_t d = reply_start_timeout;
+
+ while ((get_sys_clock() - t) < d)
+ {
+ background_processing();
+
+ uint8_t p = rxrpos;
+ if (rxwpos != p)
+ {
+ if (rxspos == p)
+ { // reply start detected
+ uint8_t id = read_data();
+ if (id == PWMRP_KEEP_ALIVE)
+ { // keep alive reply
+ t = get_sys_clock();
+ continue;
+ }
+ if ((id & PWMRQ_ID_MASK) == actual_req_id)
+ { // reply is for actual request
+ reply_start = p;
+ if (!(id & PWMRP_HAS_PAYLOAD))
+ {
+ reply_count = 0;
+ return 1;
+ }
+ if (wait_for_reply())
+ {
+ reply_count = read_data();
+ return 1;
+ }
+ return 0;
+ }
+ }
+ // drop garbagge
+ ++p;
+ CHECK_RXBUF_END(p);
+ rxrpos = p;
+ }
+
+ if (bit_is_clear(UCSRA, TXC))
+ t = get_sys_clock();
+ }
+
+ set_bit(reply_err_status, COMM_ERR_TIMEOUT);
+ return 0;
+}
+
+
+// ---
+// Stop PWM controller.
+//
+static void stop_pwm_ctrl(void)
+{
+ clear_bit(UCSRB, RXEN); // Disable USART RX
+ clear_bit(RESET_PORT, RESET_BIT);
+}
+
+
+// ---
+// Reset PWM controller.
+//
+static void reset_pwm_ctrl(void)
+{
+ stop_pwm_ctrl();
+ timer_delay(RESET_TIME);
+
+ set_bit(RESET_PORT, RESET_BIT);
+ timer_delay(STARTUP_TIME);
+
+ rxwpos = rxrpos = 0; // Flush reply buffer
+ reply_err_status = 0;
+
+ set_bit(UCSRB, RXEN); // Enable USART RX
+}
+
+
+// ---
+// Send PWM controller request payload data.
+//
+static uint8_t send_payload_data(uint8_t *data, uint8_t len)
+{
+ if(len > payload_count)
+ len = payload_count;
+ payload_count -= len;
+
+ uint8_t i = 0;
+ while (i < len)
+ send_data(data[i++]);
+
+ if (!payload_count)
+ {
+ if (wait_for_reply_start()) // Wait for ACK
+ return 1; // all done successfull
+ return USB_STALL_RC; // error happen
+ }
+
+ return 0; // next packet
+}
+
+
+// ---
+// Read PWM controller request payload data.
+//
+static uint8_t read_payload_data(uint8_t *data, uint8_t len)
+{
+ if (len > reply_count)
+ len = reply_count;
+ if(len > payload_count)
+ len = payload_count;
+ reply_count -= len;
+ payload_count -= len;
+
+ uint8_t i = 0;
+ while (i < len && wait_for_reply())
+ data[i++] = read_data();
+
+ if (i < len)
+ return USB_STALL_RC; // error happen
+
+ return i;
+}
+
+
+// ---
+// Write EE prom data.
+//
+static uint8_t write_ee_data(uint8_t *data, uint8_t len)
+{
+ if(len > payload_count)
+ len = payload_count;
+ payload_count -= len;
+
+ uint8_t i = 0;
+ while (i < len && payload_pos < EE_MEM_SIZE)
+ {
+ uint8_t old_data = eeprom_read_byte((uint8_t *)payload_pos);
+ uint8_t new_data = data[i];
+ if (old_data != new_data)
+ {
+ eeprom_write_byte((uint8_t *)payload_pos, new_data);
+
+ while (!eeprom_is_ready())
+ background_processing();
+
+ old_data = eeprom_read_byte((uint8_t *)payload_pos);
+ if (old_data != new_data)
+ return USB_STALL_RC; // write error
+ }
+ ++i;
+ ++payload_pos;
+ }
+
+ return payload_count == 0;
+}
+
+
+// ---
+// Read EE prom data.
+//
+static uint8_t read_ee_data(uint8_t *data, uint8_t len)
+{
+ if(len > payload_count)
+ len = payload_count;
+ payload_count -= len;
+
+ uint8_t i = 0;
+ while (i < len && payload_pos < EE_MEM_SIZE)
+ {
+ data[i] = eeprom_read_byte((uint8_t *)payload_pos);
+ ++i;
+ ++payload_pos;
+ }
+
+ return i;
+}
+
+
+// ---
+// Write request payload data.
+//
+USB_PUBLIC uint8_t usbFunctionWrite(uint8_t *data, uint8_t len)
+{
+ uint8_t rc = USB_STALL_RC;
+
+ if (usb_last_rc != USB_STALL_RC)
+ {
+ if (len != 8 || usbCrc16(data, 8) == ((uint16_t *)data)[4])
+ {
+ if (usbCurrentDataToken == usb_last_data_token)
+ {
+ set_bit(reply_err_status, COMM_ERR_DUPLICATE);
+ return usb_last_rc; // Ignore packet
+ }
+
+ if (payload_req >= REQ_PWM_START)
+ rc = send_payload_data(data, len);
+ else if (payload_req == REQ_WRITE_EE_DATA)
+ rc = write_ee_data(data, len);
+ }
+ else
+ set_bit(reply_err_status, COMM_ERR_CRC);
+ }
+
+ usb_last_data_token = usbCurrentDataToken;
+ usb_last_rc = rc;
+
+ return rc;
+}
+
+
+// ---
+// Read request payload data.
+//
+USB_PUBLIC uint8_t usbFunctionRead(uint8_t *data, uint8_t len)
+{
+ uint8_t rc = USB_STALL_RC;
+
+ if (usb_last_rc != USB_STALL_RC)
+ {
+ if (payload_req >= REQ_PWM_START)
+ rc = read_payload_data(data, len);
+ else if (payload_req == REQ_READ_EE_DATA)
+ rc = read_ee_data(data, len);
+ }
+
+ usb_last_rc = rc;
+
+ return rc;
+}
+
+
+// ---
+// Handle a non-standard USB SETUP packet.
+//
+USB_PUBLIC usbMsgLen_t usbFunctionSetup(uint8_t data[8])
+{
+ usbRequest_t *r = (usbRequest_t *) data;
+ static uint8_t reply[1];
+
+ usb_last_data_token = USBPID_SETUP;
+ usb_last_rc = USB_STALL_RC;
+ uint8_t rc = USB_NO_MSG;
+
+ if (usbCrc16(data, 8) != ((uint16_t *)data)[4])
+ {
+ set_bit(reply_err_status, COMM_ERR_CRC);
+ return rc;
+ }
+
+ uint8_t req = r->bRequest;
+
+ if (req >= REQ_PWM_START)
+ {
+ if (bit_is_clear (RESET_PORT, RESET_BIT))
+ reset_pwm_ctrl();
+
+ uint8_t req_type = (r->bmRequestType & USBRQ_DIR_MASK) == USBRQ_DIR_DEVICE_TO_HOST ? PWMRQ_DEVICE_TO_HOST: 0;
+ if (r->wLength.word <= MAX_REQ_PAYLOAD_SIZE)
+ {
+ send_request(req_type);
+ send_data(req);
+ send_data(r->wValue.bytes[0]);
+ send_data(r->wValue.bytes[1]);
+ send_data(r->wIndex.bytes[0]);
+ send_data(r->wIndex.bytes[1]);
+ send_data(r->wLength.bytes[0]);
+ send_data(r->wLength.bytes[1]);
+
+ payload_req = req;
+ payload_count = r->wLength.word;
+
+ if (req_type == PWMRQ_DEVICE_TO_HOST || !r->wLength.word)
+ {
+ if (wait_for_reply_start())
+ {
+ if (reply_count && r->wLength.word)
+ usb_last_rc = 0;
+ else
+ rc = 0;
+ }
+ }
+ else
+ usb_last_rc = 0;
+ }
+ }
+ else if (req == REQ_READ_EE_DATA || req == REQ_WRITE_EE_DATA)
+ {
+ if (r->wLength.word)
+ {
+ payload_pos = r->wIndex.word;
+ payload_req = req;
+ payload_count = r->wLength.word;
+ usb_last_rc = 0;
+ }
+ else
+ rc = 0;
+ }
+ else if (req == REQ_STOP_PWM_CTRL)
+ {
+ set_bit(BOOTLOADER_PORT, BOOTLOADER_BIT);
+ stop_pwm_ctrl();
+ rc = 0;
+ }
+ else if (req == REQ_RESET_PWM_CTRL)
+ {
+ set_bit(BOOTLOADER_PORT, BOOTLOADER_BIT);
+ reset_pwm_ctrl();
+ rc = 0;
+ }
+ else if (req == REQ_BOOTLOADER_RESET_PWM_CTRL)
+ {
+ clear_bit(BOOTLOADER_PORT, BOOTLOADER_BIT);
+ reset_pwm_ctrl();
+ rc = 0;
+ }
+ else if (req == REQ_GET_REPLY_ERR_STATUS)
+ {
+ reply[0] = reply_err_status;
+ reply_err_status = 0;
+ usbMsgPtr = reply;
+ rc = 1;
+ }
+ else if (req == REQ_SET_REPLY_TIMEOUT)
+ {
+ reply_start_timeout = ms_to_ticks(r->wValue.word);
+ reply_timeout = ms_to_ticks(r->wIndex.word);
+ rc = 0;
+ }
+ else if (req == REQ_START_BOOTLOADER)
+ {
+ bl_start = 1;
+ bl_time = get_sys_clock();
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
+// ----
+// Main
+//
+void main(void) NORETURN;
+void main(void)
+{
+ wdt_enable(WDTO_120MS); // Set watchdog timeout
+
+ // Initialize Ports
+ PORTB = PORTB_INIT;
+ DDRB = DDRB_INIT;
+ PORTC = PORTC_INIT;
+ DDRC = DDRC_INIT;
+ PORTD = PORTD_INIT;
+ DDRD = DDRD_INIT;
+
+ usbDeviceDisconnect();
+
+ set_bit(ACSR, ACD); // Disable analog comparator saving some power
+
+ // Initialize Timer 1
+ TCNT1 = 0;
+ TCCR1B = _BV(CS12) | _BV(CS10); // Start timer 1, Prescaler 1024
+
+ // Initialize USART
+#include <util/setbaud.h>
+ UBRRH = UBRRH_VALUE;
+ UBRRL = UBRRL_VALUE;
+#if USE_2X
+ UCSRA = _BV(U2X);
+#endif
+ UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // 9 data bits, 1 stop bit, no parity, asynchron mode
+ UCSRB = _BV(TXEN) | _BV(UCSZ2) | _BV(RXCIE); // Enable TX and RX IRQ
+
+ reset_pwm_ctrl();
+
+ timer_delay(USB_DISCONNECT_TIME);
+ usbDeviceConnect();
+ usbInit();
+
+ sei();
+
+ // Main loop
+ for (;;)
+ {
+ background_processing();
+
+ usbPoll(); // process USB requests
+
+ if ((bit_is_clear(BL_SENSE_PIN, BL_SENSE_BIT) ||
+ (bl_start && (get_sys_clock() - bl_time) > BL_START_DELAY_TIME)) &&
+ pgm_read_word(BL_START_VECT) != 0xFFFF)
+ {
+ cli();
+ stop_pwm_ctrl();
+ clear_bit(USB_INTR_ENABLE, USB_INTR_ENABLE_BIT); // Stop USB
+ UCSRB = 0; // Stop USART
TCCR1B = 0; // Stop Timer
-
- // enable boot loader by setting sense pin to 0
- clear_bit(BL_SENSE_PORT, BL_SENSE_BIT);
- set_bit(BL_SENSE_DDR, BL_SENSE_BIT);
-
- // start bootloader
- void (*jump_to_bl)(void) = BL_START_VECT / 2; // Need flash word address for jump!
- jump_to_bl();
- }
-
-
-#if 0
- if (!usb_is_initialized && get_sys_clock() > USB_INITIALIZE_TIMEOUT)
- { // request USB device enumeration
- cli();
- usb_is_initialized = 1;
- usbDeviceDisconnect();
- timer_delay(USB_DISCONNECT_TIME);
- usbDeviceConnect();
- usbInit();
- sei();
- }
-#endif
-
- // Check for standby state
- if (usb_is_resetting)
- { // ongoing USB reset -> reset activity timeout
- cli();
- usb_sof_time = TCNT1;
- sei();
- }
- else
- {
- cli();
- uint16_t t = usb_sof_time;
- sei();
- if ((get_sys_clock() - t) > USB_SLEEP_TIMEOUT)
- { // no USB activity -> go sleeping
- cli();
- stop_pwm_ctrl();
- set_sleep_mode(SLEEP_MODE_PWR_DOWN);
- USB_INTR_CFG &= ~USB_INTR_CFG_SET; // set low level triggered IRQ for wakeup
- USB_INTR_PENDING = _BV(USB_INTR_PENDING_BIT); // reset pending IRQ
- wdt_disable();
- sleep_enable();
- sei();
- sleep_cpu();
- sleep_disable();
- wdt_enable(WDTO_30MS);
- cli();
- TCNT1 = 0;
- usb_sof_time = 0;
- sei();
- reset_pwm_ctrl();
- }
- }
- }
-}
+
+ // enable boot loader by setting sense pin to 0
+ clear_bit(BL_SENSE_PORT, BL_SENSE_BIT);
+ set_bit(BL_SENSE_DDR, BL_SENSE_BIT);
+
+ // start bootloader
+ void (*jump_to_bl)(void) = BL_START_VECT / 2; // Need flash word address for jump!
+ jump_to_bl();
+ }
+
+
+#if 0
+ if (!usb_is_initialized && get_sys_clock() > USB_INITIALIZE_TIMEOUT)
+ { // request USB device enumeration
+ cli();
+ usb_is_initialized = 1;
+ usbDeviceDisconnect();
+ timer_delay(USB_DISCONNECT_TIME);
+ usbDeviceConnect();
+ usbInit();
+ sei();
+ }
+#endif
+
+ // Check for standby state
+ if (usb_is_resetting)
+ { // ongoing USB reset -> reset activity timeout
+ cli();
+ usb_sof_time = TCNT1;
+ sei();
+ }
+ else
+ {
+ cli();
+ uint16_t t = usb_sof_time;
+ sei();
+ if ((get_sys_clock() - t) > USB_SLEEP_TIMEOUT)
+ { // no USB activity -> go sleeping
+ cli();
+ stop_pwm_ctrl();
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+ USB_INTR_CFG &= ~USB_INTR_CFG_SET; // set low level triggered IRQ for wakeup
+ USB_INTR_PENDING = _BV(USB_INTR_PENDING_BIT); // reset pending IRQ
+ wdt_disable();
+ sleep_enable();
+ sei();
+ sleep_cpu();
+ sleep_disable();
+ wdt_enable(WDTO_30MS);
+ cli();
+ TCNT1 = 0;
+ usb_sof_time = 0;
+ sei();
+ reset_pwm_ctrl();
+ }
+ }
+ }
+}
diff --git a/usb_appl/usbconfig.h b/usb_appl/usbconfig.h
index 0744d16..0d5e4af 100644
--- a/usb_appl/usbconfig.h
+++ b/usb_appl/usbconfig.h
@@ -183,18 +183,18 @@ section at the end of this file).
* Please note that Start Of Frame detection works only if D- is wired to the
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
*/
-
-/* Save timestamp of sof */
-#ifdef __ASSEMBLER__
-macro customSofHook
+/* Save timestamp of sof */
+
+#ifdef __ASSEMBLER__
+macro customSofHook
in YL, TCNT1L
sts usb_sof_time, YL
in YL, TCNT1H
sts usb_sof_time+1, YL
endm
#endif
-
+
#define USB_CFG_CHECK_DATA_TOGGLING 1
/* define this macro to 1 if you want to filter out duplicate data packets
* sent by the host. Duplicates occur only as a consequence of communication
@@ -207,15 +207,15 @@ endm
/* define this macro to 1 if you want the function usbMeasureFrameLength()
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
*/
-#define USB_USE_FAST_CRC 1
-/* The assembler module has two implementations for the CRC algorithm. One is
- * faster, the other is smaller. This CRC routine is only used for transmitted
- * messages where timing is not critical. The faster routine needs 31 cycles
- * per byte while the smaller one needs 61 to 69 cycles. The faster routine
- * may be worth the 32 bytes bigger code size if you transmit lots of data and
- * run the AVR close to its limit.
- */
-
+#define USB_USE_FAST_CRC 1
+/* The assembler module has two implementations for the CRC algorithm. One is
+ * faster, the other is smaller. This CRC routine is only used for transmitted
+ * messages where timing is not critical. The faster routine needs 31 cycles
+ * per byte while the smaller one needs 61 to 69 cycles. The faster routine
+ * may be worth the 32 bytes bigger code size if you transmit lots of data and
+ * run the AVR close to its limit.
+ */
+
/* -------------------------- Device Description --------------------------- */
#define USB_CFG_VENDOR_ID 0xc0, 0x16
@@ -361,9 +361,9 @@ endm
*/
#define USB_INTR_CFG MCUCR
#if defined(USB_COUNT_SOF) || defined(USB_SOF_HOOK)
-#define USB_INTR_CFG_SET ((1 << ISC11))
+#define USB_INTR_CFG_SET ((1 << ISC11))
#else
-#define USB_INTR_CFG_SET ((1 << ISC10) | (1 << ISC11))
+#define USB_INTR_CFG_SET ((1 << ISC10) | (1 << ISC11))
#endif
/* #define USB_INTR_CFG_CLR 0 */
/* #define USB_INTR_ENABLE GIMSK */
@@ -371,22 +371,22 @@ endm
/* #define USB_INTR_PENDING GIFR */
#define USB_INTR_PENDING_BIT INTF1
#define USB_INTR_VECTOR SIG_INTERRUPT1
-
-
-/* This is a new macro that is executed and the beginning of the usb irq handler.
- * This needs a patch in the corresponding clock dependend assembler file of VUSB!!!
- * It is save to use register YH here
- */
-#define USB_START_IRQ_HOOK customTriggerHook
-
-
+
+
+/* This is a new macro that is executed and the beginning of the usb irq handler.
+ * This needs a patch in the corresponding clock dependend assembler file of VUSB!!!
+ * It is save to use register YH here
+ */
+#define USB_START_IRQ_HOOK customTriggerHook
+
+
/* Reinstall edge level interrupt triggering (after sleep) */
#ifdef __ASSEMBLER__
-macro customTriggerHook
- in YH, USB_INTR_CFG
+macro customTriggerHook
+ in YH, USB_INTR_CFG
ori YH, USB_INTR_CFG_SET
out USB_INTR_CFG, YH
-endm
+endm
#endif
-
+
#endif /* __usbconfig_h_included__ */
diff --git a/usb_boot/Makefile b/usb_boot/Makefile
index 6f63ffa..db3beb5 100644
--- a/usb_boot/Makefile
+++ b/usb_boot/Makefile
@@ -1,106 +1,106 @@
-#
-# Copyright (C) 2010 Andreas Auras
-#
-# This file is part of the DF10CH Atmolight controller project.
-#
-# DF10CH Atmolight controller is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# DF10CH Atmolight controller is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-#
-#
-###############################################################################
-# Makefile for the bootloader firmware of USB processor
-###############################################################################
-
-## General Flags
-PROJECT = 10ch_usb_boot
-MCU = atmega8
-TARGET = 10ch_usb_boot.elf
-CC = avr-gcc
-AVRDUDE ?= avrdude -c stk500v2 -P avrdoper
-USBDRV ?= ../usbdrv
-F_CPU ?= 16000000UL
-FIRMWARE_VERSION ?= 1
-
-## Options common to compile, link and assembly rules
-COMMON = -mmcu=$(MCU)
-
-## Compile options common for all C compilation units.
-CFLAGS = $(COMMON)
-CFLAGS += -Wall -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
-CFLAGS += -DF_CPU=$(F_CPU) -DFIRMWARE_VERSION=$(FIRMWARE_VERSION)
-
-## Assembly specific flags
-ASMFLAGS = $(COMMON)
-ASMFLAGS += $(CFLAGS)
-ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
-
-## Linker flags
-LDFLAGS = $(COMMON)
-LDFLAGS += -Wl,-Map=10ch_usb_boot.map
-LDFLAGS += -Wl,-section-start=.text=0x1800
-
-
-## Intel Hex file production flags
-HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
-
-HEX_EEPROM_FLAGS = -j .eeprom
-HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
-
-## Include Directories
-INCLUDES = -I. -I.. -I$(USBDRV)
-
-## Objects that must be built in order to link
-OBJECTS = 10ch_usb_boot.o usbdrvasm.o
-
-## Objects explicitly added by the user
-LINKONLYOBJECTS =
-
-## Build
-all: $(TARGET) 10ch_usb_boot.hex 10ch_usb_boot.lss size
-
-prog: flash
- $(AVRDUDE) -p $(MCU) -u -Ulfuse:w:0x1F:m -Uhfuse:w:0xC8:m -Ulock:w:0xEF:m
-
-flash: 10ch_usb_boot.hex
- $(AVRDUDE) -p $(MCU) -Uflash:w:10ch_usb_boot.hex:i
-
-
-## Compile
-usbdrvasm.o: $(USBDRV)/usbdrvasm.S usbconfig.h
- $(CC) $(INCLUDES) $(ASMFLAGS) -c $<
-
-10ch_usb_boot.o: 10ch_usb_boot.c usbconfig.h ../df10ch_usb_proto.h ../df10ch_common.h
- $(CC) $(INCLUDES) $(CFLAGS) -c $<
-
-##Link
-$(TARGET): $(OBJECTS)
- $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
-
-%.hex: $(TARGET)
- avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
-
-%.eep: $(TARGET)
- -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
-
-%.lss: $(TARGET)
- avr-objdump -h -S $< > $@
-
-size: ${TARGET}
- @echo
- @avr-size -C --mcu=${MCU} ${TARGET}
-
-## Clean target
-.PHONY: clean
-clean:
- -rm -rf $(OBJECTS) 10ch_usb_boot.elf 10ch_usb_boot.hex 10ch_usb_boot.eep 10ch_usb_boot.lss 10ch_usb_boot.map
+#
+# Copyright (C) 2010 Andreas Auras
+#
+# This file is part of the DF10CH Atmolight controller project.
+#
+# DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# DF10CH Atmolight controller is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+#
+#
+###############################################################################
+# Makefile for the bootloader firmware of USB processor
+###############################################################################
+
+## General Flags
+PROJECT = df10ch_usb_boot
+MCU = atmega8
+TARGET = df10ch_usb_boot.elf
+CC = avr-gcc
+AVRDUDE ?= avrdude -c stk500v2 -P avrdoper
+USBDRV ?= ../usbdrv
+F_CPU ?= 16000000UL
+FIRMWARE_VERSION ?= 1
+
+## Options common to compile, link and assembly rules
+COMMON = -mmcu=$(MCU)
+
+## Compile options common for all C compilation units.
+CFLAGS = $(COMMON)
+CFLAGS += -Wall -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -DF_CPU=$(F_CPU) -DFIRMWARE_VERSION=$(FIRMWARE_VERSION)
+
+## Assembly specific flags
+ASMFLAGS = $(COMMON)
+ASMFLAGS += $(CFLAGS)
+ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
+
+## Linker flags
+LDFLAGS = $(COMMON)
+LDFLAGS += -Wl,-Map=df10ch_usb_boot.map
+LDFLAGS += -Wl,-section-start=.text=0x1800
+
+
+## Intel Hex file production flags
+HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
+
+HEX_EEPROM_FLAGS = -j .eeprom
+HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
+
+## Include Directories
+INCLUDES = -I. -I.. -I$(USBDRV)
+
+## Objects that must be built in order to link
+OBJECTS = df10ch_usb_boot.o usbdrvasm.o
+
+## Objects explicitly added by the user
+LINKONLYOBJECTS =
+
+## Build
+all: $(TARGET) df10ch_usb_boot.hex df10ch_usb_boot.lss size
+
+prog: flash
+ $(AVRDUDE) -p $(MCU) -u -Ulfuse:w:0x1F:m -Uhfuse:w:0xC8:m -Ulock:w:0xEF:m
+
+flash: df10ch_usb_boot.hex
+ $(AVRDUDE) -p $(MCU) -Uflash:w:df10ch_usb_boot.hex:i
+
+
+## Compile
+usbdrvasm.o: $(USBDRV)/usbdrvasm.S usbconfig.h
+ $(CC) $(INCLUDES) $(ASMFLAGS) -c $<
+
+df10ch_usb_boot.o: df10ch_usb_boot.c usbconfig.h ../df10ch_usb_proto.h ../df10ch_common.h
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<
+
+##Link
+$(TARGET): $(OBJECTS)
+ $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
+
+%.hex: $(TARGET)
+ avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
+
+%.eep: $(TARGET)
+ -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
+
+%.lss: $(TARGET)
+ avr-objdump -h -S $< > $@
+
+size: ${TARGET}
+ @echo
+ @avr-size -C --mcu=${MCU} ${TARGET}
+
+## Clean target
+.PHONY: clean
+clean:
+ -rm -rf $(OBJECTS) df10ch_usb_boot.elf df10ch_usb_boot.hex df10ch_usb_boot.eep df10ch_usb_boot.lss df10ch_usb_boot.map
diff --git a/usb_boot/10ch_usb_boot.c b/usb_boot/df10ch_usb_boot.c
index 4d90a4a..9e72810 100644
--- a/usb_boot/10ch_usb_boot.c
+++ b/usb_boot/df10ch_usb_boot.c
@@ -1,323 +1,323 @@
-/*
- * Copyright (C) 2010 Andreas Auras
- *
- * This file is part of the DF10CH Atmolight controller project.
- *
- * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * DF10CH Atmolight controller is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- */
-
-// ======================================================================
-// Bootloader firmware for USB processor.
-//
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <avr/wdt.h>
-#include <avr/eeprom.h>
-#include <avr/boot.h>
-#include <avr/pgmspace.h>
-
-#include "../df10ch_common.h"
-#include "../df10ch_usb_proto.h"
-#include "usbconfig.h"
-
-
-// ---
-// Fuse-Bit settings for the flash programmer (ATmega8):
-// RSTDISBL=1
-// WDTON=1
-// SPIEN=0
-// CKOPT=0
-// EESAVE=1
-// BOOTSZ1=0
-// BOOTSZ0=0
-// BOOTRST=0
-//
-// BODLEVEL=0
-// BODEN=0
-// SUT1=0
-// SUT0=1
-// CKSEL3=1
-// CKSEL2=1
-// CKSEL1=1
-// CKSEL0=1
-//
-// Memory-Lock Bits:
-// BL12=1, BL11=0, BL02=1, BL01=1, LB2=1, LB1=1
-//
-FUSES =
-{
- .low = (FUSE_BODLEVEL & FUSE_BODEN & FUSE_SUT1),
- .high = (FUSE_SPIEN & FUSE_CKOPT & FUSE_BOOTSZ1 & FUSE_BOOTSZ0 & FUSE_BOOTRST)
-};
-LOCKBITS = (LB_MODE_1 & BLB0_MODE_1 & BLB1_MODE_2);
-//SIGNATURE_DATA = { SIGNATURE_2, SIGNATURE_1, SIGNATURE_0 } ;
-
-
-// ---
-// System clock related.
-// System clock ist implemented with hardware timer 1
-//
-#define SYS_HWPRESCALE 1024 // Hardware Prescaler
-
- // useconds <-> timer ticks conversation
-#define US2TICKS(t) ((uint16_t)((double)(t) * (double)F_CPU / (1000000.0 * (double)SYS_HWPRESCALE) + 0.5))
-#define TICKS2US(t) ((uint16_t)((t) / (F_CPU / (1000000UL * SYS_HWPRESCALE))))
-
-
- // Input pin (Jumper) for enable/disable of bootloader
- // Enabled when Jumper set -> 0, Disabled if Jumper is away -> 1
-#define BL_SENSE_DDR DDRB
-#define BL_SENSE_PORT PORTB
-#define BL_SENSE_PIN PINB
-#define BL_SENSE_BIT 0
-
-#define APPL_START_VECT 0x0000
-
-static uint8_t leave_state; // Is true when bootloader should be leaved
-
-
-// ---
-// USB related.
-//
-#define USB_DISCONNECT_TIME US2TICKS(500000UL)
-#define USB_STALL_RC 0xFF
-
-static uint8_t usb_last_data_token NOMEMINIT; // Token PID of last usb packet received
-static uint8_t usb_last_rc = USB_STALL_RC; // Return status of last payload packet
-static uint8_t payload_req NOMEMINIT; // ID of actual proccessed USB request
-
-// ---
-// flash programming related.
-//
-static uint16_t page_address NOMEMINIT; // actual page address
-static uint8_t page_offset NOMEMINIT; // actual offset into page
-static uint8_t page_size_reply[2] = { (SPM_PAGESIZE & 0xFF), (SPM_PAGESIZE >> 8) };
-
-#include <usbdrv.c>
-
-
-// ---
-// ISR handler for IRQ's that do not have a dedicated handler.
-//
-EMPTY_INTERRUPT(BADISR_vect)
-
-
-// ---
-// Write request payload data.
-//
-USB_PUBLIC uint8_t usbFunctionWrite(uint8_t *data, uint8_t len)
-{
- uint8_t rc = USB_STALL_RC;
-
- if (usb_last_rc != USB_STALL_RC)
- {
- if (len != 8 || usbCrc16(data, 8) == ((uint16_t *)data)[4])
- {
- if (usbCurrentDataToken == usb_last_data_token)
- return usb_last_rc; // Ignore packet
-
- if (payload_req == BL_REQ_WRITE_PAGE)
- {
- rc = 0;
- while (len > 1)
- {
- bytes_word_t code;
- code.bytes[0] = *data++;
- code.bytes[1] = *data++;
-
- cli();
- boot_page_fill(page_address + page_offset, code.word);
- sei();
-
- page_offset += 2;
- len -= 2;
- if (page_offset >= SPM_PAGESIZE)
- {
- cli();
- boot_page_write(page_address);
- sei();
-
- while (boot_spm_busy())
- wdt_reset();
-
- rc = 1;
- }
- }
- }
- }
- }
-
- if (rc)
- usb_last_rc = USB_STALL_RC;
- usb_last_data_token = usbCurrentDataToken;
-
- return rc;
-}
-
-
-// ---
-// Read request payload data.
-//
-USB_PUBLIC uint8_t usbFunctionRead(uint8_t *data, uint8_t len)
-{
- uint8_t rc = USB_STALL_RC;
-
- if (usb_last_rc != USB_STALL_RC)
- {
- if (payload_req == BL_REQ_READ_FLASH)
- {
- if (len > page_offset)
- len = page_offset;
- rc = len;
- if (len)
- {
- page_offset -= len;
- PGM_P p = (PGM_P) page_address;
- page_address += len;
- memcpy_P(data, p, len);
- }
- }
-
- if (rc != 8)
- usb_last_rc = USB_STALL_RC;
- }
-
- return rc;
-}
-
-
-// ---
-// Handle a non-standard USB SETUP packet.
-//
-USB_PUBLIC usbMsgLen_t usbFunctionSetup(uint8_t data[8])
-{
- usbRequest_t *r = (usbRequest_t *) data;
-
- usb_last_data_token = USBPID_SETUP;
- usb_last_rc = USB_STALL_RC;
- uint8_t rc = USB_NO_MSG;
-
- if (leave_state || usbCrc16(data, 8) != ((uint16_t *)data)[4])
- return rc;
-
- uint8_t req = r->bRequest;
- payload_req = req;
-
- if (req == BL_REQ_WRITE_PAGE)
- {
- page_address = r->wIndex.word;
- page_offset = 0;
-
- while (!eeprom_is_ready())
- wdt_reset();
-
- cli();
- boot_page_erase(page_address);
- sei();
-
- while (boot_spm_busy())
- wdt_reset();
-
- usb_last_rc = 0;
- }
- else if (req == BL_REQ_LEAVE_BOOT)
- {
- if (boot_rww_busy())
- boot_rww_enable();
- leave_state = 1;
- rc = 0;
- }
- else if (req == BL_REQ_GET_PAGE_SIZE)
- {
- usbMsgPtr = page_size_reply;
- rc = sizeof(page_size_reply);
- }
- else if (req == BL_REQ_READ_FLASH)
- {
- if (boot_rww_busy())
- boot_rww_enable();
- page_address = r->wIndex.word;
- page_offset = r->wLength.bytes[0];
- usb_last_rc = 0;
- }
-
- return rc;
-}
-
-
-// ----
-// Main
-//
-void main(void) NORETURN;
-void main(void)
-{
- cli();
-
- wdt_enable(WDTO_120MS); // Set watchdog timeout
-
- // Note: If application calls bootloader it must set the enable pin to output and low level
- if (bit_is_clear(BL_SENSE_DDR, BL_SENSE_BIT))
- set_bit(BL_SENSE_PORT, BL_SENSE_BIT); // activate pullup
-
- if ((pgm_read_word(APPL_START_VECT) != 0xFFFF) && // Application reset vector programmed?
- bit_is_set(BL_SENSE_PIN, BL_SENSE_BIT))
- { // boot loader disabled -> start application
- void (*jump_to_app)(void) = APPL_START_VECT / 2; // Need flash word address!
- jump_to_app();
- }
-
- GICR = _BV(IVCE); // enable change of interrupt vectors
- GICR = _BV(IVSEL); // move interrupts to boot flash section
-
- // initialize boot loader disable pin: input + pullup
- clear_bit(BL_SENSE_DDR, BL_SENSE_BIT);
- set_bit(BL_SENSE_PORT, BL_SENSE_BIT);
-
- usbDeviceDisconnect();
-
- // Initialize Timer 1
- TIMSK = 0;
- TCCR1A = 0;
- TCCR1B = 0;
- TCNT1 = 0;
- TCCR1B = _BV(CS12) | _BV(CS10); // Start timer 1, Prescaler 1024
-
- while (TCNT1 < USB_DISCONNECT_TIME)
- wdt_reset();
-
- TCCR1B = 0; // Stop timer 1
-
- usbDeviceConnect();
- usbInit();
-
- sei();
-
- // Main loop
- for (;;)
- {
- // Note: Delayed boot loader exit is done via watchdog timer reset
- if (!leave_state)
- wdt_reset();
-
- usbPoll(); // process USB requests
- }
-}
-
+/*
+ * Copyright (C) 2010 Andreas Auras
+ *
+ * This file is part of the DF10CH Atmolight controller project.
+ *
+ * DF10CH Atmolight controller is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DF10CH Atmolight controller is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ */
+
+// ======================================================================
+// Bootloader firmware for USB processor.
+//
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <avr/eeprom.h>
+#include <avr/boot.h>
+#include <avr/pgmspace.h>
+
+#include "../df10ch_common.h"
+#include "../df10ch_usb_proto.h"
+#include "usbconfig.h"
+
+
+// ---
+// Fuse-Bit settings for the flash programmer (ATmega8):
+// RSTDISBL=1
+// WDTON=1
+// SPIEN=0
+// CKOPT=0
+// EESAVE=1
+// BOOTSZ1=0
+// BOOTSZ0=0
+// BOOTRST=0
+//
+// BODLEVEL=0
+// BODEN=0
+// SUT1=0
+// SUT0=1
+// CKSEL3=1
+// CKSEL2=1
+// CKSEL1=1
+// CKSEL0=1
+//
+// Memory-Lock Bits:
+// BL12=1, BL11=0, BL02=1, BL01=1, LB2=1, LB1=1
+//
+FUSES =
+{
+ .low = (FUSE_BODLEVEL & FUSE_BODEN & FUSE_SUT1),
+ .high = (FUSE_SPIEN & FUSE_CKOPT & FUSE_BOOTSZ1 & FUSE_BOOTSZ0 & FUSE_BOOTRST)
+};
+LOCKBITS = (LB_MODE_1 & BLB0_MODE_1 & BLB1_MODE_2);
+//SIGNATURE_DATA = { SIGNATURE_2, SIGNATURE_1, SIGNATURE_0 } ;
+
+
+// ---
+// System clock related.
+// System clock ist implemented with hardware timer 1
+//
+#define SYS_HWPRESCALE 1024 // Hardware Prescaler
+
+ // useconds <-> timer ticks conversation
+#define US2TICKS(t) ((uint16_t)((double)(t) * (double)F_CPU / (1000000.0 * (double)SYS_HWPRESCALE) + 0.5))
+#define TICKS2US(t) ((uint16_t)((t) / (F_CPU / (1000000UL * SYS_HWPRESCALE))))
+
+
+ // Input pin (Jumper) for enable/disable of bootloader
+ // Enabled when Jumper set -> 0, Disabled if Jumper is away -> 1
+#define BL_SENSE_DDR DDRB
+#define BL_SENSE_PORT PORTB
+#define BL_SENSE_PIN PINB
+#define BL_SENSE_BIT 0
+
+#define APPL_START_VECT 0x0000
+
+static uint8_t leave_state; // Is true when bootloader should be leaved
+
+
+// ---
+// USB related.
+//
+#define USB_DISCONNECT_TIME US2TICKS(500000UL)
+#define USB_STALL_RC 0xFF
+
+static uint8_t usb_last_data_token NOMEMINIT; // Token PID of last usb packet received
+static uint8_t usb_last_rc = USB_STALL_RC; // Return status of last payload packet
+static uint8_t payload_req NOMEMINIT; // ID of actual proccessed USB request
+
+// ---
+// flash programming related.
+//
+static uint16_t page_address NOMEMINIT; // actual page address
+static uint8_t page_offset NOMEMINIT; // actual offset into page
+static uint8_t page_size_reply[2] = { (SPM_PAGESIZE & 0xFF), (SPM_PAGESIZE >> 8) };
+
+#include <usbdrv.c>
+
+
+// ---
+// ISR handler for IRQ's that do not have a dedicated handler.
+//
+EMPTY_INTERRUPT(BADISR_vect)
+
+
+// ---
+// Write request payload data.
+//
+USB_PUBLIC uint8_t usbFunctionWrite(uint8_t *data, uint8_t len)
+{
+ uint8_t rc = USB_STALL_RC;
+
+ if (usb_last_rc != USB_STALL_RC)
+ {
+ if (len != 8 || usbCrc16(data, 8) == ((uint16_t *)data)[4])
+ {
+ if (usbCurrentDataToken == usb_last_data_token)
+ return usb_last_rc; // Ignore packet
+
+ if (payload_req == BL_REQ_WRITE_PAGE)
+ {
+ rc = 0;
+ while (len > 1)
+ {
+ bytes_word_t code;
+ code.bytes[0] = *data++;
+ code.bytes[1] = *data++;
+
+ cli();
+ boot_page_fill(page_address + page_offset, code.word);
+ sei();
+
+ page_offset += 2;
+ len -= 2;
+ if (page_offset >= SPM_PAGESIZE)
+ {
+ cli();
+ boot_page_write(page_address);
+ sei();
+
+ while (boot_spm_busy())
+ wdt_reset();
+
+ rc = 1;
+ }
+ }
+ }
+ }
+ }
+
+ if (rc)
+ usb_last_rc = USB_STALL_RC;
+ usb_last_data_token = usbCurrentDataToken;
+
+ return rc;
+}
+
+
+// ---
+// Read request payload data.
+//
+USB_PUBLIC uint8_t usbFunctionRead(uint8_t *data, uint8_t len)
+{
+ uint8_t rc = USB_STALL_RC;
+
+ if (usb_last_rc != USB_STALL_RC)
+ {
+ if (payload_req == BL_REQ_READ_FLASH)
+ {
+ if (len > page_offset)
+ len = page_offset;
+ rc = len;
+ if (len)
+ {
+ page_offset -= len;
+ PGM_P p = (PGM_P) page_address;
+ page_address += len;
+ memcpy_P(data, p, len);
+ }
+ }
+
+ if (rc != 8)
+ usb_last_rc = USB_STALL_RC;
+ }
+
+ return rc;
+}
+
+
+// ---
+// Handle a non-standard USB SETUP packet.
+//
+USB_PUBLIC usbMsgLen_t usbFunctionSetup(uint8_t data[8])
+{
+ usbRequest_t *r = (usbRequest_t *) data;
+
+ usb_last_data_token = USBPID_SETUP;
+ usb_last_rc = USB_STALL_RC;
+ uint8_t rc = USB_NO_MSG;
+
+ if (leave_state || usbCrc16(data, 8) != ((uint16_t *)data)[4])
+ return rc;
+
+ uint8_t req = r->bRequest;
+ payload_req = req;
+
+ if (req == BL_REQ_WRITE_PAGE)
+ {
+ page_address = r->wIndex.word;
+ page_offset = 0;
+
+ while (!eeprom_is_ready())
+ wdt_reset();
+
+ cli();
+ boot_page_erase(page_address);
+ sei();
+
+ while (boot_spm_busy())
+ wdt_reset();
+
+ usb_last_rc = 0;
+ }
+ else if (req == BL_REQ_LEAVE_BOOT)
+ {
+ if (boot_rww_busy())
+ boot_rww_enable();
+ leave_state = 1;
+ rc = 0;
+ }
+ else if (req == BL_REQ_GET_PAGE_SIZE)
+ {
+ usbMsgPtr = page_size_reply;
+ rc = sizeof(page_size_reply);
+ }
+ else if (req == BL_REQ_READ_FLASH)
+ {
+ if (boot_rww_busy())
+ boot_rww_enable();
+ page_address = r->wIndex.word;
+ page_offset = r->wLength.bytes[0];
+ usb_last_rc = 0;
+ }
+
+ return rc;
+}
+
+
+// ----
+// Main
+//
+void main(void) NORETURN;
+void main(void)
+{
+ cli();
+
+ wdt_enable(WDTO_120MS); // Set watchdog timeout
+
+ // Note: If application calls bootloader it must set the enable pin to output and low level
+ if (bit_is_clear(BL_SENSE_DDR, BL_SENSE_BIT))
+ set_bit(BL_SENSE_PORT, BL_SENSE_BIT); // activate pullup
+
+ if ((pgm_read_word(APPL_START_VECT) != 0xFFFF) && // Application reset vector programmed?
+ bit_is_set(BL_SENSE_PIN, BL_SENSE_BIT))
+ { // boot loader disabled -> start application
+ void (*jump_to_app)(void) = APPL_START_VECT / 2; // Need flash word address!
+ jump_to_app();
+ }
+
+ GICR = _BV(IVCE); // enable change of interrupt vectors
+ GICR = _BV(IVSEL); // move interrupts to boot flash section
+
+ // initialize boot loader disable pin: input + pullup
+ clear_bit(BL_SENSE_DDR, BL_SENSE_BIT);
+ set_bit(BL_SENSE_PORT, BL_SENSE_BIT);
+
+ usbDeviceDisconnect();
+
+ // Initialize Timer 1
+ TIMSK = 0;
+ TCCR1A = 0;
+ TCCR1B = 0;
+ TCNT1 = 0;
+ TCCR1B = _BV(CS12) | _BV(CS10); // Start timer 1, Prescaler 1024
+
+ while (TCNT1 < USB_DISCONNECT_TIME)
+ wdt_reset();
+
+ TCCR1B = 0; // Stop timer 1
+
+ usbDeviceConnect();
+ usbInit();
+
+ sei();
+
+ // Main loop
+ for (;;)
+ {
+ // Note: Delayed boot loader exit is done via watchdog timer reset
+ if (!leave_state)
+ wdt_reset();
+
+ usbPoll(); // process USB requests
+ }
+}
+
diff --git a/usb_boot/usbconfig.h b/usb_boot/usbconfig.h
index e9899b7..70f76f1 100644
--- a/usb_boot/usbconfig.h
+++ b/usb_boot/usbconfig.h
@@ -183,17 +183,17 @@ section at the end of this file).
* Please note that Start Of Frame detection works only if D- is wired to the
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
*/
-
-/* Save timestamp of sof */
-#ifdef __ASSEMBLER__
-macro customSofHook
- ldi YL, 0
+/* Save timestamp of sof */
+
+#ifdef __ASSEMBLER__
+macro customSofHook
+ ldi YL, 0
out TCNT1H, YL
out TCNT1L, YL
endm
#endif
-
+
#define USB_CFG_CHECK_DATA_TOGGLING 1
/* define this macro to 1 if you want to filter out duplicate data packets
* sent by the host. Duplicates occur only as a consequence of communication
@@ -206,15 +206,15 @@ endm
/* define this macro to 1 if you want the function usbMeasureFrameLength()
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
*/
-#define USB_USE_FAST_CRC 1
-/* The assembler module has two implementations for the CRC algorithm. One is
- * faster, the other is smaller. This CRC routine is only used for transmitted
- * messages where timing is not critical. The faster routine needs 31 cycles
- * per byte while the smaller one needs 61 to 69 cycles. The faster routine
- * may be worth the 32 bytes bigger code size if you transmit lots of data and
- * run the AVR close to its limit.
- */
-
+#define USB_USE_FAST_CRC 1
+/* The assembler module has two implementations for the CRC algorithm. One is
+ * faster, the other is smaller. This CRC routine is only used for transmitted
+ * messages where timing is not critical. The faster routine needs 31 cycles
+ * per byte while the smaller one needs 61 to 69 cycles. The faster routine
+ * may be worth the 32 bytes bigger code size if you transmit lots of data and
+ * run the AVR close to its limit.
+ */
+
/* -------------------------- Device Description --------------------------- */
#define USB_CFG_VENDOR_ID 0xc0, 0x16
@@ -360,9 +360,9 @@ endm
*/
#define USB_INTR_CFG MCUCR
#if defined(USB_COUNT_SOF) || defined(USB_SOF_HOOK) || 1
-#define USB_INTR_CFG_SET ((1 << ISC11))
+#define USB_INTR_CFG_SET ((1 << ISC11))
#else
-#define USB_INTR_CFG_SET ((1 << ISC10) | (1 << ISC11))
+#define USB_INTR_CFG_SET ((1 << ISC10) | (1 << ISC11))
#endif
/* #define USB_INTR_CFG_CLR 0 */
/* #define USB_INTR_ENABLE GIMSK */
@@ -370,22 +370,22 @@ endm
/* #define USB_INTR_PENDING GIFR */
#define USB_INTR_PENDING_BIT INTF1
#define USB_INTR_VECTOR SIG_INTERRUPT1
-
-
-/* This is a new macro that is executed and the beginning of the usb irq handler.
- * This needs a patch in the corresponding clock dependend assembler file of VUSB!!!
- * It is save to use register YH here
- */
-/*#define USB_START_IRQ_HOOK customTriggerHook*/
-
-
+
+
+/* This is a new macro that is executed and the beginning of the usb irq handler.
+ * This needs a patch in the corresponding clock dependend assembler file of VUSB!!!
+ * It is save to use register YH here
+ */
+/*#define USB_START_IRQ_HOOK customTriggerHook*/
+
+
/* Reinstall edge level interrupt triggering (after sleep) */
#ifdef __ASSEMBLER__
-macro customTriggerHook
- in YH, USB_INTR_CFG
+macro customTriggerHook
+ in YH, USB_INTR_CFG
ori YH, USB_INTR_CFG_SET
out USB_INTR_CFG, YH
-endm
+endm
#endif
-
+
#endif /* __usbconfig_h_included__ */