manual sync with SF

This commit is contained in:
rusefi 2014-06-28 14:38:08 -04:00
parent 102ee997cb
commit 0d87be6add
168 changed files with 4761 additions and 2057 deletions

View File

@ -50,6 +50,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/math}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/math}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/console_util}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/console_util}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation/test}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation/hw_layer}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation/hw_layer}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/flash}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/flash}&quot;"/>
@ -59,7 +60,10 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi/adc}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi/adc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/system}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/system}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/splib}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/splib}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/kernel/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/boards/ST_STM32F4_DISCOVERY}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/boards/ST_STM32F4_DISCOVERY}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/TIMv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/TIMv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/I2Cv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/I2Cv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32}&quot;"/>
@ -67,14 +71,11 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/OTGv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/OTGv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/GPIOv2}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/GPIOv2}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32F4xx}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32F4xx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/src}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/SPIv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/include}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/USARTv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/kernel/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/GCC/ARMCMx}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/GCC/ARMCMx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/GCC/ARMCMx/STM32F4xx}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/GCC/ARMCMx/STM32F4xx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/SPIv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/USARTv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx/CMSIS/include}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx/CMSIS/include}&quot;"/>
</option> </option>
<option id="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.other.otherflags.720321025" name="Other flags" superClass="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.other.otherflags" value="-fgnu89-inline -c -fmessage-length=0 -Werror=type-limits -Werror-implicit-function-declaration -Werror -Wno-error=pointer-sign -Wno-error=unused-function -Wno-error=unused-variable" valueType="string"/> <option id="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.other.otherflags.720321025" name="Other flags" superClass="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.other.otherflags" value="-fgnu89-inline -c -fmessage-length=0 -Werror=type-limits -Werror-implicit-function-declaration -Werror -Wno-error=pointer-sign -Wno-error=unused-function -Wno-error=unused-variable" valueType="string"/>
@ -110,6 +111,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/math}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/math}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/console_util}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/console_util}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation/test}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation/hw_layer}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation/hw_layer}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/flash}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/flash}&quot;"/>
@ -119,7 +121,10 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi/adc}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi/adc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/system}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/system}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/splib}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/splib}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/kernel/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/boards/ST_STM32F4_DISCOVERY}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/boards/ST_STM32F4_DISCOVERY}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/TIMv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/TIMv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/I2Cv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/I2Cv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32}&quot;"/>
@ -127,17 +132,14 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/OTGv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/OTGv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/GPIOv2}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/GPIOv2}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32F4xx}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32F4xx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/kernel/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/GCC/ARMCMx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/GCC/ARMCMx/STM32F4xx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/SPIv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/SPIv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/USARTv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/USARTv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/GCC/ARMCMx/STM32F4xx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/GCC/ARMCMx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx/CMSIS/include}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx/CMSIS/include}&quot;"/>
</option> </option>
<option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.other.otherflags.1439013659" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.other.otherflags" value="-c -fmessage-length=0 -std=c++11" valueType="string"/> <option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.other.otherflags.1439013659" name="Other flags" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.other.otherflags" value="-c -fmessage-length=0 -std=c++11 -Werror=write-strings" valueType="string"/>
<inputType id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input.1939416167" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input"/> <inputType id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input.1939416167" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input"/>
</tool> </tool>
<tool id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.debug.369587711" name="ARM Sourcery Windows GCC C Linker" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.debug"/> <tool id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.debug.369587711" name="ARM Sourcery Windows GCC C Linker" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.debug"/>
@ -188,13 +190,14 @@
<inputType id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.assembler.base.input.1359572999" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.assembler.base.input"/> <inputType id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.assembler.base.input.1359572999" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.assembler.base.input"/>
</tool> </tool>
<tool id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.compiler.release.431693497" name="ARM Sourcery Windows GCC C Compiler" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.compiler.release"> <tool id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.compiler.release.431693497" name="ARM Sourcery Windows GCC C Compiler" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.compiler.release">
<option id="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.optimization.level.329705686" name="Optimization level" superClass="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.optimization.level" value="org.eclipse.cdt.cross.arm.gnu.base.option.optimization.level.size" valueType="enumerated"/> <option id="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.optimization.level.329705686" name="Optimization level" superClass="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.optimization.level" value="org.eclipse.cdt.cross.arm.gnu.base.option.optimization.level.optimize" valueType="enumerated"/>
<option id="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.include.paths.1664205045" name="Include paths (-I)" superClass="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.include.paths" valueType="includePath"> <option id="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.include.paths.1664205045" name="Include paths (-I)" superClass="org.eclipse.cdt.cross.arm.gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/system}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/console/algo}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/console/algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/algo}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/algo}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/ext}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/ext_algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/util}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/util}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/engines}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/engines}&quot;"/>
@ -205,24 +208,25 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/math}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/math}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/sensors}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/sensors}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/core}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/system}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/trigger}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation/hw_layer}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation/hw_layer}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/linked/controllers}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/linked/controllers/math}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/lcd}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/serial_over_usb}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi/algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi/ckp}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi/adc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/splib}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/boards/ST_STM32F4_DISCOVERY}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/boards/ST_STM32F4_DISCOVERY}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/kernel/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/various}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/various}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/RTCv2}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/OTGv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/OTGv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/I2Cv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/GPIOv2}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/GPIOv2}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32F4xx}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32F4xx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/src}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/kernel/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/include}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/SPIv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/SPIv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/TIMv1}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/TIMv1}&quot;"/>
@ -242,8 +246,59 @@
<inputType id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.c.compiler.base.input.1479270851" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.c.compiler.base.input"/> <inputType id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.c.compiler.base.input.1479270851" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.c.compiler.base.input"/>
</tool> </tool>
<tool id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.cpp.compiler.release.487461954" name="ARM Sourcery Windows GCC C++ Compiler" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.cpp.compiler.release"> <tool id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.cpp.compiler.release.487461954" name="ARM Sourcery Windows GCC C++ Compiler" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.cpp.compiler.release">
<option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.optimization.level.74521503" name="Optimization level" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.optimization.level" value="org.eclipse.cdt.cross.arm.gnu.base.option.optimization.level.size" valueType="enumerated"/> <option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.optimization.level.74521503" name="Optimization level" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.optimization.level" value="org.eclipse.cdt.cross.arm.gnu.base.option.optimization.level.optimize" valueType="enumerated"/>
<option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.other.verbose.1350766121" name="Verbose (-v)" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.other.verbose" value="false" valueType="boolean"/> <option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.other.verbose.1350766121" name="Verbose (-v)" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.other.verbose" value="false" valueType="boolean"/>
<option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.include.paths.346409971" name="Include paths (-I)" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/serial_over_usb}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/lcd}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/ext}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/ext_algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/various}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/util}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/console}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/console/tunerstudio}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/engines}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/boards}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/core}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/trigger}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/sensors}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/system}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/math}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/console_util}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation/test}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/emulation/hw_layer}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/hw_layer/flash}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi/algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi/ckp}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/russianefi/adc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/system}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/splib}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/kernel/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/boards/ST_STM32F4_DISCOVERY}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/TIMv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/I2Cv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/RTCv2}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/OTGv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/GPIOv2}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32F4xx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/SPIv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/hal/platforms/STM32/USARTv1}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/GCC/ARMCMx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/GCC/ARMCMx/STM32F4xx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx/CMSIS/include}&quot;"/>
</option>
<inputType id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input.815685204" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input"/> <inputType id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input.815685204" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input"/>
</tool> </tool>
<tool id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.release.1692652942" name="ARM Sourcery Windows GCC C Linker" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.release"/> <tool id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.release.1692652942" name="ARM Sourcery Windows GCC C Linker" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.release"/>

View File

@ -18,7 +18,7 @@ endif
# C++ specific options here (added to USE_OPT). # C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),) ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -std=c++11 -fno-rtti -fno-exceptions -fno-use-cxa-atexit USE_CPPOPT = -std=c++11 -fno-rtti -fno-exceptions -fno-use-cxa-atexit -Werror=write-strings
endif endif
# Enable this if you want the linker to remove unused code and data # Enable this if you want the linker to remove unused code and data
@ -196,8 +196,9 @@ INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \
hw_layer/serial_over_usb \ hw_layer/serial_over_usb \
hw_layer/algo \ hw_layer/algo \
hw_layer/lcd \ hw_layer/lcd \
emulation/hw_layer \
emulation \ emulation \
emulation/hw_layer \
emulation/test \
controllers \ controllers \
controllers/sensors \ controllers/sensors \
controllers/system \ controllers/system \
@ -292,7 +293,7 @@ ULIBS = -lm
############################################################################## ##############################################################################
ifeq ($(USE_FPU),yes) ifeq ($(USE_FPU),yes)
USE_OPT += -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -fsingle-precision-constant USE_OPT += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant
DDEFS += -DCORTEX_USE_FPU=TRUE DDEFS += -DCORTEX_USE_FPU=TRUE
else else
DDEFS += -DCORTEX_USE_FPU=FALSE DDEFS += -DCORTEX_USE_FPU=FALSE

View File

@ -192,10 +192,11 @@ static void serve_interrupt(SerialDriver *sdp) {
/* Physical transmission end.*/ /* Physical transmission end.*/
if (sr & USART_SR_TC) { if (sr & USART_SR_TC) {
chSysLockFromIsr(); chSysLockFromIsr();
chnAddFlagsI(sdp, CHN_TRANSMISSION_END); if (chOQIsEmptyI(&sdp->oqueue))
chSysUnlockFromIsr(); chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
u->CR1 = cr1 & ~(USART_CR1_TXEIE | USART_CR1_TCIE); u->CR1 = cr1 & ~USART_CR1_TCIE;
u->SR = ~USART_SR_TC; u->SR = ~USART_SR_TC;
chSysUnlockFromIsr();
} }
} }

View File

@ -35,6 +35,28 @@
#include "ch.h" #include "ch.h"
extern stkalign_t __main_stack_base__;
int getRemainingStack(Thread *otp) {
#if CH_DBG_ENABLE_STACK_CHECK
register struct intctx *r13 asm ("r13");
otp->activeStack = r13;
int rs;
if (dbg_isr_cnt > 0) {
// ISR context
rs = (stkalign_t *) (r13 - 1) - &__main_stack_base__;
} else {
rs = (stkalign_t *) (r13 - 1) - otp->p_stklimit;
}
otp->remainingStack = rs;
return rs;
#else
return 99999;
#endif /* CH_DBG_ENABLE_STACK_CHECK */
}
/*===========================================================================*/ /*===========================================================================*/
/* Port interrupt handlers. */ /* Port interrupt handlers. */
/*===========================================================================*/ /*===========================================================================*/

View File

@ -490,6 +490,8 @@ struct context {
void chDbgStackOverflowPanic(Thread *otp); void chDbgStackOverflowPanic(Thread *otp);
int getRemainingStack(Thread *otp);
/** /**
* @brief Performs a context switch between two threads. * @brief Performs a context switch between two threads.
* @details This is the most critical code in any port, this function * @details This is the most critical code in any port, this function
@ -504,8 +506,7 @@ void chDbgStackOverflowPanic(Thread *otp);
#define port_switch(ntp, otp) _port_switch(ntp, otp) #define port_switch(ntp, otp) _port_switch(ntp, otp)
#else #else
#define port_switch(ntp, otp) { \ #define port_switch(ntp, otp) { \
register struct intctx *r13 asm ("r13"); \ if (getRemainingStack(otp) < 0) \
if ((stkalign_t *)(r13 - 1) < otp->p_stklimit) \
chDbgStackOverflowPanic(otp); \ chDbgStackOverflowPanic(otp); \
_port_switch(ntp, otp); \ _port_switch(ntp, otp); \
} }

View File

@ -39,6 +39,21 @@
/* Port interrupt handlers. */ /* Port interrupt handlers. */
/*===========================================================================*/ /*===========================================================================*/
int getRemainingStack(Thread *otp) {
#if CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__)
int remainingStack;
if (dbg_isr_cnt > 0) {
remainingStack = 999; // todo
} else {
remainingStack = (stkalign_t *)(__get_SP() - sizeof(struct intctx)) - otp->p_stklimit;
}
otp->remainingStack = remainingStack;
return remainingStack;
#else
return 999999;
#endif
}
/** /**
* @brief System Timer vector. * @brief System Timer vector.
* @details This interrupt is used as system tick. * @details This interrupt is used as system tick.

View File

@ -470,6 +470,8 @@ struct context {
#define port_wait_for_interrupt() #define port_wait_for_interrupt()
#endif #endif
int getRemainingStack(Thread *otp);
/** /**
* @brief Performs a context switch between two threads. * @brief Performs a context switch between two threads.
* @details This is the most critical code in any port, this function * @details This is the most critical code in any port, this function
@ -484,7 +486,7 @@ struct context {
#define port_switch(ntp, otp) _port_switch(ntp, otp) #define port_switch(ntp, otp) _port_switch(ntp, otp)
#else #else
#define port_switch(ntp, otp) { \ #define port_switch(ntp, otp) { \
if ((stkalign_t *)(__get_SP() - sizeof(struct intctx)) < otp->p_stklimit) \ if (getRemainingStack(otp) < 0) \
chDbgPanic("stack overflow"); \ chDbgPanic("stack overflow"); \
_port_switch(ntp, otp); \ _port_switch(ntp, otp); \
} }

View File

@ -205,8 +205,8 @@
#define TS_SERIAL_RX_PIN 11 #define TS_SERIAL_RX_PIN 11
#define TS_SERIAL_AF 7 #define TS_SERIAL_AF 7
#define LED_CRANKING_STATUS_PORT GPIOD #define LED_WARNING_PORT GPIOD
#define LED_CRANKING_STATUS_PIN GPIOD_LED3 #define LED_WARNING_PIN GPIOD_LED3
#define LED_RUNNING_STATUS_PORT GPIOD #define LED_RUNNING_STATUS_PORT GPIOD
#define LED_RUNNING_STATUS_PIN GPIOD_LED4 #define LED_RUNNING_STATUS_PIN GPIOD_LED4

View File

@ -10,15 +10,17 @@
#ifndef EFIFEATURES_H_ #ifndef EFIFEATURES_H_
#define EFIFEATURES_H_ #define EFIFEATURES_H_
#define EFI_USE_CCM TRUE
//#define EFI_UART_ECHO_TEST_MODE TRUE
#define EFI_USE_UART_FOR_CONSOLE FALSE
/** /**
* Build-in logic analyzer support. Logic analyzer viewer is one of the java console panes. * Build-in logic analyzer support. Logic analyzer viewer is one of the java console panes.
*/ */
#define EFI_WAVE_ANALYZER TRUE #define EFI_WAVE_ANALYZER TRUE
#define EFI_WAVE_CHART TRUE
#define EFI_ANALOG_CHART TRUE
//#define SERIAL_SPEED (8 * 115200) //#define SERIAL_SPEED (8 * 115200)
//#define SERIAL_SPEED (2 * 115200) //#define SERIAL_SPEED (2 * 115200)
#define SERIAL_SPEED 115200 #define SERIAL_SPEED 115200
@ -28,10 +30,6 @@
*/ */
#define EFI_TUNER_STUDIO TRUE #define EFI_TUNER_STUDIO TRUE
#define EFI_SERIAL_OVER_USB TRUE
#define EFI_SERIAL_OVER_UART FALSE
//#define EFI_TUNER_STUDIO_OVER_USB TRUE
/** /**
* TunerStudio debug output * TunerStudio debug output
*/ */
@ -82,19 +80,6 @@
#define EFI_ENGINE_EMULATOR TRUE #define EFI_ENGINE_EMULATOR TRUE
#define EFI_EMULATE_POSITION_SENSORS TRUE #define EFI_EMULATE_POSITION_SENSORS TRUE
#if EFI_TUNER_STUDIO
#if EFI_SERIAL_OVER_USB
#if EFI_TUNER_STUDIO_OVER_USB
#pragma "Cannot be EFI_SERIAL_OVER_USB and EFI_TUNER_STUDIO_OVER_USB at the same time"
#endif
#else
#if EFI_TUNER_STUDIO_OVER_USB
#else
#pragma "Cannot be serial over USART and TUNER_STUDIO over USART at the same time"
#endif
#endif /* EFI_TUNER_STUDIO */
#endif /* EFI_SERIAL_OVER_USB */
/** /**
* This macros is used to hide pieces of the code from unit tests, so it only makes sense in folders exposed to the tests project. * This macros is used to hide pieces of the code from unit tests, so it only makes sense in folders exposed to the tests project.
* This macros is NOT about taking out logging in general. * This macros is NOT about taking out logging in general.
@ -120,7 +105,18 @@
#define EFI_SUPPORT_NISSAN_PRIMERA TRUE #define EFI_SUPPORT_NISSAN_PRIMERA TRUE
#define EFI_SUPPORT_1995_FORD_INLINE_6 TRUE #define EFI_SUPPORT_1995_FORD_INLINE_6 TRUE
#if defined __GNUC__
#define EFI_PERF_METRICS TRUE #define EFI_PERF_METRICS TRUE
#define EFI_ANALOG_CHART TRUE
#define EFI_WAVE_CHART TRUE
#define DL_OUTPUT_BUFFER 9000
#else
// todo: CCM usage for IAR?
#define EFI_PERF_METRICS FALSE
#define EFI_ANALOG_CHART FALSE
#define EFI_WAVE_CHART FALSE
#define DL_OUTPUT_BUFFER 6000
#endif
/** /**
* Do we need GPS logic? * Do we need GPS logic?

View File

@ -1,5 +1,5 @@
/** /**
* @file GY6_139QMB.c * @file GY6_139QMB.cpp
* @brief 139qmb default engine configuration * @brief 139qmb default engine configuration
* *
* @date Feb 13, 2014 * @date Feb 13, 2014
@ -7,6 +7,7 @@
* @author Andrey Belomutskiy, (c) 2012-2014 * @author Andrey Belomutskiy, (c) 2012-2014
*/ */
#include "main.h"
#include "GY6_139QMB.h" #include "GY6_139QMB.h"
void setGy6139qmbDefaultEngineConfiguration(engine_configuration_s *engineConfiguration) { void setGy6139qmbDefaultEngineConfiguration(engine_configuration_s *engineConfiguration) {
@ -17,7 +18,7 @@ void setGy6139qmbDefaultEngineConfiguration(engine_configuration_s *engineConfig
engineConfiguration->globalTriggerAngleOffset = 15; engineConfiguration->globalTriggerAngleOffset = 15;
engineConfiguration->analogChartMode = AC_MAP; engineConfiguration->analogChartMode = AC_MAP;
engineConfiguration->cylindersCount = 1; engineConfiguration->cylindersCount = 1;
engineConfiguration->rpmMultiplier = 1; setOperationMode(engineConfiguration, FOUR_STROKE_CRANK_SENSOR);
engineConfiguration->firingOrder = FO_ONE_CYLINDER; engineConfiguration->firingOrder = FO_ONE_CYLINDER;

View File

@ -1,5 +1,5 @@
/** /**
* @file audi_aan.c * @file audi_aan.cpp
* @brief Audo AAN default engine configuration * @brief Audo AAN default engine configuration
* *
* @date Nov 24, 2013 * @date Nov 24, 2013

View File

@ -1,5 +1,5 @@
/** /**
* @file dodge_neon.c * @file dodge_neon.cpp
* *
* DODGE_NEON_1995 = 2 * DODGE_NEON_1995 = 2
* *
@ -18,6 +18,7 @@
void setDodgeNeonEngineConfiguration(engine_configuration_s *engineConfiguration, void setDodgeNeonEngineConfiguration(engine_configuration_s *engineConfiguration,
board_configuration_s *boardConfiguration) { board_configuration_s *boardConfiguration) {
engineConfiguration->triggerConfig.triggerType = TT_DODGE_NEON; engineConfiguration->triggerConfig.triggerType = TT_DODGE_NEON;
engineConfiguration->engineLoadMode = LM_TPS; engineConfiguration->engineLoadMode = LM_TPS;
@ -39,10 +40,8 @@ void setDodgeNeonEngineConfiguration(engine_configuration_s *engineConfiguration
// set_whole_fuel_map 3 // set_whole_fuel_map 3
setWholeFuelMap(engineConfiguration, 3); setWholeFuelMap(engineConfiguration, 3);
engineConfiguration->triggerConfig.syncRatioFrom = 0.72 * 0.8; setTriggerSynchronizationGap(engineConfiguration, 0.72);
engineConfiguration->triggerConfig.syncRatioTo = 0.72 * 1.3;
engineConfiguration->triggerConfig.isSynchronizationNeeded = TRUE;
engineConfiguration->triggerConfig.useRiseEdge = FALSE; engineConfiguration->triggerConfig.useRiseEdge = FALSE;
engineConfiguration->needSecondTriggerInput = TRUE; engineConfiguration->needSecondTriggerInput = TRUE;

View File

@ -1,15 +0,0 @@
/**
* @file engines.h
*
* @date Aug 30, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef ENGINE_H_
#define ENGINE_H_
#include "boards.h"
#include "efifeatures.h"
#include "rusefi_enums.h"
#endif /* ENGINE_H_ */

View File

@ -14,5 +14,6 @@ ENGINES_SRC_CPP = $(PROJECT_DIR)/config/engines/ford_aspire.cpp \
$(PROJECT_DIR)/config/engines/honda_accord.cpp \ $(PROJECT_DIR)/config/engines/honda_accord.cpp \
$(PROJECT_DIR)/config/engines/snow_blower.cpp \ $(PROJECT_DIR)/config/engines/snow_blower.cpp \
$(PROJECT_DIR)/config/engines/GY6_139QMB.cpp \ $(PROJECT_DIR)/config/engines/GY6_139QMB.cpp \
$(PROJECT_DIR)/config/engines/rover_v8.cpp \
$(PROJECT_DIR)/config/engines/mazda_323.cpp \ $(PROJECT_DIR)/config/engines/mazda_323.cpp \
$(PROJECT_DIR)/config/engines/saturn_ion.cpp $(PROJECT_DIR)/config/engines/saturn_ion.cpp

View File

@ -1,5 +1,5 @@
/** /**
* @file ford_1995_inline_6.c * @file ford_1995_inline_6.cpp
* @brief Default engine configuration for a 1995 Ford inline 6 engine * @brief Default engine configuration for a 1995 Ford inline 6 engine
* *
* http://rusefi.com/forum/viewtopic.php?f=3&t=469 * http://rusefi.com/forum/viewtopic.php?f=3&t=469
@ -23,10 +23,7 @@
void setFordInline6(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) { void setFordInline6(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
engineConfiguration->cylindersCount = 6; engineConfiguration->cylindersCount = 6;
/** setOperationMode(engineConfiguration, FOUR_STROKE_CAM_SENSOR);
* 0.5 means primary position sensor is on a camshaft
*/
engineConfiguration->rpmMultiplier = 0.5;
engineConfiguration->ignitionMode = IM_ONE_COIL; engineConfiguration->ignitionMode = IM_ONE_COIL;
engineConfiguration->firingOrder = FO_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4; engineConfiguration->firingOrder = FO_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4;
@ -41,6 +38,7 @@ void setFordInline6(engine_configuration_s *engineConfiguration, board_configura
/** /**
* We treat the trigger as 6/0 toothed wheel * We treat the trigger as 6/0 toothed wheel
*/ */
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
engineConfiguration->triggerConfig.totalToothCount = 6; engineConfiguration->triggerConfig.totalToothCount = 6;
engineConfiguration->triggerConfig.skippedToothCount = 0; engineConfiguration->triggerConfig.skippedToothCount = 0;
engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE; engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;

View File

@ -13,7 +13,6 @@
#include "ford_aspire.h" #include "ford_aspire.h"
#include "allsensors.h" #include "allsensors.h"
#include "engines.h"
#include "engine_math.h" #include "engine_math.h"
#include "advance_map.h" #include "advance_map.h"
#include "engine_configuration.h" #include "engine_configuration.h"
@ -103,6 +102,10 @@ void setFordAspireEngineConfiguration(engine_configuration_s *engineConfiguratio
// engineConfiguration->ignitionPinMode = OM_INVERTED; // engineConfiguration->ignitionPinMode = OM_INVERTED;
engineConfiguration->cylindersCount = 4; engineConfiguration->cylindersCount = 4;
engineConfiguration->displacement = 1.3;
// Denso 195500-2110
engineConfiguration->injectorFlow = 119.8;
engineConfiguration->firingOrder = FO_1_THEN_3_THEN_4_THEN2; engineConfiguration->firingOrder = FO_1_THEN_3_THEN_4_THEN2;
engineConfiguration->globalTriggerAngleOffset = 175; engineConfiguration->globalTriggerAngleOffset = 175;
engineConfiguration->ignitionOffset = 98 - 11; engineConfiguration->ignitionOffset = 98 - 11;

View File

@ -1,5 +1,5 @@
/** /**
* @file ford_fiesta.c * @file ford_fiesta.cpp
* @brief European 1990 Ford Fiesta * @brief European 1990 Ford Fiesta
* *
* FORD_FIESTA = 4 * FORD_FIESTA = 4
@ -18,8 +18,7 @@
void setFordFiestaDefaultEngineConfiguration(engine_configuration_s *engineConfiguration) { void setFordFiestaDefaultEngineConfiguration(engine_configuration_s *engineConfiguration) {
engineConfiguration->rpmHardLimit = 7000; engineConfiguration->rpmHardLimit = 7000;
// only crankshaft sensor so far setOperationMode(engineConfiguration, FOUR_STROKE_CRANK_SENSOR);
engineConfiguration->rpmMultiplier = 1;
engineConfiguration->triggerConfig.totalToothCount = 36; engineConfiguration->triggerConfig.totalToothCount = 36;
engineConfiguration->triggerConfig.skippedToothCount = 1; engineConfiguration->triggerConfig.skippedToothCount = 1;

View File

@ -1,5 +1,5 @@
/** /**
* @file honda_accord.c * @file honda_accord.cpp
* *
* @date Jan 12, 2014 * @date Jan 12, 2014
* @author Andrey Belomutskiy, (c) 2012-2014 * @author Andrey Belomutskiy, (c) 2012-2014

View File

@ -1,5 +1,5 @@
/** /**
* @file mazda_323.c * @file mazda_323.cpp
* *
* @date Mar 8, 2014 * @date Mar 8, 2014
* @author Andrey Belomutskiy, (c) 2012-2014 * @author Andrey Belomutskiy, (c) 2012-2014
@ -8,7 +8,8 @@
#include "mazda_323.h" #include "mazda_323.h"
void setMazda323EngineConfiguration(engine_configuration_s *engineConfiguration) { void setMazda323EngineConfiguration(engine_configuration_s *engineConfiguration) {
engineConfiguration->cylindersCount = 6; engineConfiguration->cylindersCount = 4;
engineConfiguration->displacement = 1.6;
engineConfiguration->ignitionMode = IM_ONE_COIL; engineConfiguration->ignitionMode = IM_ONE_COIL;

View File

@ -1,5 +1,5 @@
/** /**
* @file mazda_miata_nb.c * @file mazda_miata_nb.cpp
* *
* MAZDA_MIATA_NB = 9 * MAZDA_MIATA_NB = 9
* *
@ -16,10 +16,8 @@ void setMazdaMiataNbEngineConfiguration(engine_configuration_s *engineConfigurat
engineConfiguration->rpmHardLimit = 3000; // yes, 3k. let's play it safe for now engineConfiguration->rpmHardLimit = 3000; // yes, 3k. let's play it safe for now
engineConfiguration->triggerConfig.triggerType = TT_MAZDA_MIATA_NB; engineConfiguration->triggerConfig.triggerType = TT_MAZDA_MIATA_NB;
engineConfiguration->triggerConfig.isSynchronizationNeeded = TRUE;
engineConfiguration->triggerConfig.syncRatioFrom = 0.11 * 0.7; setTriggerSynchronizationGap(engineConfiguration, 0.11);
engineConfiguration->triggerConfig.syncRatioTo = 0.11 * 1.3;
engineConfiguration->triggerConfig.useRiseEdge = FALSE; engineConfiguration->triggerConfig.useRiseEdge = FALSE;
engineConfiguration->globalTriggerAngleOffset = 276; engineConfiguration->globalTriggerAngleOffset = 276;

View File

@ -1,5 +1,7 @@
/** /**
* @file nissan_primera.c * @file nissan_primera.cpp
*
* engine_type 5
* *
* @date Oct 14, 2013 * @date Oct 14, 2013
* @author Andrey Belomutskiy, (c) 2012-2014 * @author Andrey Belomutskiy, (c) 2012-2014

View File

@ -0,0 +1,70 @@
/**
* @file rover_v8.cpp
*
* V8, firing order 18436572
*
* ROVER_V8 = 10
*
* @date Jun 27, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "main.h"
#include "rover_v8.h"
void setRoverv8(engine_configuration_s *engineConfiguration,
board_configuration_s *boardConfiguration) {
setOperationMode(engineConfiguration, FOUR_STROKE_CRANK_SENSOR);
engineConfiguration->triggerConfig.totalToothCount = 36;
engineConfiguration->triggerConfig.skippedToothCount = 1;
// todo: displacement? 4 liters?
engineConfiguration->displacement = 4;
engineConfiguration->cylindersCount = 8;
engineConfiguration->firingOrder = FO_1_8_4_3_6_5_7_2;
// set_rpm_hard_limit 4000
engineConfiguration->rpmHardLimit = 4000; // yes, 4k. let's play it safe for now
// set_cranking_rpm 550
engineConfiguration->crankingSettings.crankingRpm = 550;
// set_whole_fuel_map 3
setWholeFuelMap(engineConfiguration, 3);
// set_cranking_injection_mode 0
engineConfiguration->crankingInjectionMode = IM_SEQUENTIAL;
// set_injection_mode 1
engineConfiguration->injectionMode = IM_SEQUENTIAL;
// set_ignition_mode 2
engineConfiguration->ignitionMode = IM_WASTED_SPARK;
// Frankenstein: low side - inj #1: PC14
// Frankenstein: low side - inj #2: PC15
// Frankenstein: low side - inj #3: PE6
// Frankenstein: low side - inj #4: PC13
// Frankenstein: low side - inj #5: PE4
// Frankenstein: low side - inj #6: PE5
// Frankenstein: low side - inj #7: PE2
// Frankenstein: low side - inj #8: PE3
// Frankenstein: low side - inj #9: PE0
// Frankenstein: low side - inj #10: PE1
// Frankenstein: low side - inj #11: PB8
// Frankenstein: low side - inj #12: PB9
boardConfiguration->injectionPins[0] = GPIOB_9; // Frankenstein: low side - inj #12
boardConfiguration->injectionPins[1] = GPIOB_8; // Frankenstein: low side - inj #11
boardConfiguration->injectionPins[2] = GPIOE_3; // Frankenstein: low side - inj #8
boardConfiguration->injectionPins[3] = GPIOE_5; // Frankenstein: low side - inj #6
boardConfiguration->fuelPumpPin = GPIOC_13; // Frankenstein: low side - inj #4
boardConfiguration->fuelPumpPinMode = OM_DEFAULT;
// set_injection_pin_mode 0
boardConfiguration->injectionPinMode = OM_DEFAULT;
}

View File

@ -0,0 +1,15 @@
/**
* @file rover_v8.h
*
* @date Jun 27, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef ROVER_V8_H_
#define ROVER_V8_H_
#include "engine_configuration.h"
void setRoverv8(engine_configuration_s *engineConfiguration,
board_configuration_s *boardConfiguration);
#endif /* ROVER_V8_H_ */

View File

@ -1,5 +1,5 @@
/** /**
* @file snow_blower.c * @file snow_blower.cpp
* @brief Default configuration of a single-cylinder engine * @brief Default configuration of a single-cylinder engine
* *
* @date Sep 9, 2013 * @date Sep 9, 2013
@ -7,8 +7,3 @@
*/ */
#include "main.h" #include "main.h"
#if EFI_ENGINE_SNOW_BLOWER
#endif

View File

@ -28,8 +28,8 @@
/* /*
* ST32F407xG memory setup. * ST32F407xG memory setup.
*/ */
__main_stack_size__ = 0x0400; __main_stack_size__ = 0x0600;
__process_stack_size__ = 0x0400; __process_stack_size__ = 0x0600;
MEMORY MEMORY
{ {
@ -127,7 +127,7 @@ SECTIONS
__main_thread_stack_end__ = .; __main_thread_stack_end__ = .;
} > ram } > ram
.ccm : .ccm (NOLOAD) :
{ {
PROVIDE(_cmm_start = .); PROVIDE(_cmm_start = .);
. = ALIGN(4); . = ALIGN(4);

View File

@ -45,11 +45,11 @@
} }
#define PORT_IDLE_THREAD_STACK_SIZE 256 #define PORT_IDLE_THREAD_STACK_SIZE 1024
#define PORT_INT_REQUIRED_STACK 128 #define PORT_INT_REQUIRED_STACK 768
#define CHPRINTF_USE_FLOAT TRUE #define CHPRINTF_USE_FLOAT TRUE
/** /**
* number of ticks per second * number of ticks per second
@ -480,6 +480,8 @@
*/ */
#if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__) #if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
#define THREAD_EXT_FIELDS \ #define THREAD_EXT_FIELDS \
void *activeStack; \
int remainingStack; \
/* Add threads custom fields here.*/ /* Add threads custom fields here.*/
#endif #endif

View File

@ -30,7 +30,9 @@
#define STM32F4xx_MCUCONF #define STM32F4xx_MCUCONF
#include "engines.h" #include "boards.h"
#include "efifeatures.h"
#include "rusefi_enums.h"
/* /*
* HAL driver system settings. * HAL driver system settings.

View File

@ -22,12 +22,19 @@
#include "console_io.h" #include "console_io.h"
#if EFI_PROD_CODE #if EFI_PROD_CODE
extern SerialUSBDriver SDU1;
#include "usbcfg.h"
#include "usbconsole.h" #include "usbconsole.h"
#endif #endif
#include "rfiutil.h" #include "rfiutil.h"
int lastWriteSize;
int lastWriteActual;
static bool_t isSerialConsoleStarted = FALSE; static bool_t isSerialConsoleStarted = FALSE;
static EventListener consoleEventListener;
/** /**
* @brief Reads a whole line from the input channel. * @brief Reads a whole line from the input channel.
* *
@ -38,7 +45,7 @@ static bool_t isSerialConsoleStarted = FALSE;
* @retval TRUE the channel was reset or CTRL-D pressed. * @retval TRUE the channel was reset or CTRL-D pressed.
* @retval FALSE operation successful. * @retval FALSE operation successful.
*/ */
static bool_t getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size) { static bool getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size) {
char *p = line; char *p = line;
while (TRUE) { while (TRUE) {
@ -49,6 +56,30 @@ static bool_t getConsoleLine(BaseSequentialStream *chp, char *line, unsigned siz
} }
short c = (short) chSequentialStreamGet(chp); short c = (short) chSequentialStreamGet(chp);
if (isSerialOverUart()) {
uint32_t flags;
chSysLock()
;
flags = chEvtGetAndClearFlagsI(&consoleEventListener);
chSysUnlock()
;
if (flags & SD_OVERRUN_ERROR) {
// firmwareError("serial overrun");
}
}
#if EFI_UART_ECHO_TEST_MODE
/**
* That's test code - let's test connectivity
*/
consolePutChar((uint8_t) c);
continue;
#endif
if (c < 0) if (c < 0)
return TRUE; return TRUE;
if (c == 4) { if (c == 4) {
@ -84,13 +115,19 @@ static char consoleInput[] = "
void (*console_line_callback)(char *); void (*console_line_callback)(char *);
static WORKING_AREA(consoleThreadStack, 2 * UTILITY_THREAD_STACK_SIZE); static bool is_serial_over_uart;
bool isSerialOverUart(void) {
return is_serial_over_uart;
}
static THD_WORKING_AREA(consoleThreadStack, 2 * UTILITY_THREAD_STACK_SIZE);
static msg_t consoleThreadThreadEntryPoint(void *arg) { static msg_t consoleThreadThreadEntryPoint(void *arg) {
(void) arg; (void) arg;
chRegSetThreadName("console thread"); chRegSetThreadName("console thread");
while (TRUE) { while (TRUE) {
bool_t end = getConsoleLine((BaseSequentialStream *) CONSOLE_CHANNEL, consoleInput, sizeof(consoleInput)); bool end = getConsoleLine((BaseSequentialStream*) getConsoleChannel(), consoleInput, sizeof(consoleInput));
if (end) { if (end) {
// firmware simulator is the only case when this happens // firmware simulator is the only case when this happens
continue; continue;
@ -103,47 +140,68 @@ static msg_t consoleThreadThreadEntryPoint(void *arg) {
#endif #endif
} }
#if EFI_SERIAL_OVER_USB #if EFI_PROD_CODE
#else
#if EFI_SERIAL_OVER_UART
static SerialConfig serialConfig = {SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0};
#endif /* EFI_SERIAL_OVER_UART */
#endif /* EFI_SERIAL_OVER_USB */
#if ! EFI_SERIAL_OVER_USB && ! EFI_SIMULATOR static SerialConfig serialConfig = { SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 };
int isConsoleReady(void) {
return isSerialConsoleStarted; SerialDriver * getConsoleChannel(void) {
if (isSerialOverUart()) {
return (SerialDriver *) EFI_CONSOLE_UART_DEVICE;
} else {
return (SerialDriver *) &SDU1;
}
} }
#endif
int isConsoleReady(void) {
if (isSerialOverUart()) {
return isSerialConsoleStarted;
} else {
return is_usb_serial_ready();
}
}
#endif /* EFI_PROD_CODE */
void consolePutChar(int x) { void consolePutChar(int x) {
chSequentialStreamPut(CONSOLE_CHANNEL, (uint8_t )(x)); chSequentialStreamPut(getConsoleChannel(), (uint8_t )(x));
} }
// 10 seconds
#define CONSOLE_WRITE_TIMEOUT 10000
void consoleOutputBuffer(const int8_t *buf, int size) { void consoleOutputBuffer(const int8_t *buf, int size) {
chSequentialStreamWrite(CONSOLE_CHANNEL, buf, size); lastWriteSize = size;
#if !EFI_UART_ECHO_TEST_MODE
lastWriteActual = chnWriteTimeout(getConsoleChannel(), buf, size, CONSOLE_WRITE_TIMEOUT);
// if (r != size)
// firmwareError("Partial console write");
#endif /* EFI_UART_ECHO_TEST_MODE */
} }
void startConsole(void (*console_line_callback_p)(char *)) { void startConsole(void (*console_line_callback_p)(char *)) {
console_line_callback = console_line_callback_p; console_line_callback = console_line_callback_p;
#if EFI_SERIAL_OVER_USB
usb_serial_start();
#else #if EFI_PROD_CODE
#if EFI_SERIAL_OVER_UART is_serial_over_uart = palReadPad(GPIOA, GPIOA_BUTTON) != EFI_USE_UART_FOR_CONSOLE;
/*
* Activates the serial using the driver default configuration (that's 38400)
* it is important to set 'NONE' as flow control! in terminal application on the PC
*/
sdStart(CONSOLE_CHANNEL, &serialConfig);
// cannot use pin repository here because pin repository prints to console if (isSerialOverUart()) {
palSetPadMode(EFI_CONSOLE_RX_PORT, EFI_CONSOLE_RX_PIN, PAL_MODE_ALTERNATE(EFI_CONSOLE_AF)); /*
palSetPadMode(EFI_CONSOLE_TX_PORT, EFI_CONSOLE_TX_PIN, PAL_MODE_ALTERNATE(EFI_CONSOLE_AF)); * Activates the serial using the driver default configuration (that's 38400)
* it is important to set 'NONE' as flow control! in terminal application on the PC
*/
sdStart(EFI_CONSOLE_UART_DEVICE, &serialConfig);
isSerialConsoleStarted = TRUE; // cannot use pin repository here because pin repository prints to console
#endif /* EFI_SERIAL_OVER_UART */ palSetPadMode(EFI_CONSOLE_RX_PORT, EFI_CONSOLE_RX_PIN, PAL_MODE_ALTERNATE(EFI_CONSOLE_AF));
#endif /* EFI_SERIAL_OVER_USB */ palSetPadMode(EFI_CONSOLE_TX_PORT, EFI_CONSOLE_TX_PIN, PAL_MODE_ALTERNATE(EFI_CONSOLE_AF));
isSerialConsoleStarted = TRUE;
chEvtRegisterMask((EventSource *) chnGetEventSource(EFI_CONSOLE_UART_DEVICE), &consoleEventListener, 1);
} else {
usb_serial_start();
}
#endif /* EFI_PROD_CODE */
chThdCreateStatic(consoleThreadStack, sizeof(consoleThreadStack), NORMALPRIO, consoleThreadThreadEntryPoint, NULL); chThdCreateStatic(consoleThreadStack, sizeof(consoleThreadStack), NORMALPRIO, consoleThreadThreadEntryPoint, NULL);
} }
@ -152,7 +210,7 @@ extern cnt_t dbg_isr_cnt;
/** /**
* @return TRUE if already in locked context * @return TRUE if already in locked context
*/ */
bool_t lockAnyContext(void) { bool lockAnyContext(void) {
int alreadyLocked = isLocked(); int alreadyLocked = isLocked();
if (alreadyLocked) if (alreadyLocked)
return TRUE; return TRUE;

View File

@ -21,23 +21,18 @@
#include "efifeatures.h" #include "efifeatures.h"
#include "boards.h" #include "boards.h"
#if EFI_SERIAL_OVER_USB
#include "usbcfg.h"
extern SerialUSBDriver SDU1;
#define CONSOLE_CHANNEL (&SDU1)
#else
#define CONSOLE_CHANNEL EFI_CONSOLE_UART_DEVICE
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
#endif /* __cplusplus */ #endif /* __cplusplus */
SerialDriver * getConsoleChannel(void);
void consolePutChar(int x); void consolePutChar(int x);
void consoleOutputBuffer(const int8_t *buf, int size); void consoleOutputBuffer(const int8_t *buf, int size);
void startConsole(void (*console_line_callback_p)(char *)); void startConsole(void (*console_line_callback_p)(char *));
int isConsoleReady(void); int isConsoleReady(void);
bool isSerialOverUart(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -46,6 +46,10 @@ static void myfatal(void) {
chDbgCheck(0, "my fatal"); chDbgCheck(0, "my fatal");
} }
static void myerror(void) {
firmwareError("firmwareError: %d", getRusEfiVersion());
}
static void sayHello(void) { static void sayHello(void) {
printMsg(&logger, "*** rusEFI (c) Andrey Belomutskiy, 2012-2014. All rights reserved."); printMsg(&logger, "*** rusEFI (c) Andrey Belomutskiy, 2012-2014. All rights reserved.");
printMsg(&logger, "rusEFI v%d@%d", getRusEfiVersion(), SVN_VERSION); printMsg(&logger, "rusEFI v%d@%d", getRusEfiVersion(), SVN_VERSION);
@ -69,6 +73,9 @@ static void sayHello(void) {
printMsg(&logger, "STM32_PCLK2=%d", STM32_PCLK2); printMsg(&logger, "STM32_PCLK2=%d", STM32_PCLK2);
#endif #endif
printMsg(&logger, "PORT_IDLE_THREAD_STACK_SIZE=%d", PORT_IDLE_THREAD_STACK_SIZE);
printMsg(&logger, "CH_DBG_ENABLE_ASSERTS=%d", CH_DBG_ENABLE_ASSERTS); printMsg(&logger, "CH_DBG_ENABLE_ASSERTS=%d", CH_DBG_ENABLE_ASSERTS);
printMsg(&logger, "CH_DBG_ENABLED=%d", CH_DBG_ENABLED); printMsg(&logger, "CH_DBG_ENABLED=%d", CH_DBG_ENABLED);
printMsg(&logger, "CH_DBG_SYSTEM_STATE_CHECK=%d", CH_DBG_SYSTEM_STATE_CHECK); printMsg(&logger, "CH_DBG_SYSTEM_STATE_CHECK=%d", CH_DBG_SYSTEM_STATE_CHECK);
@ -91,19 +98,8 @@ static void sayHello(void) {
printMsg(&logger, "EFI_SIGNAL_EXECUTOR_HW_TIMER=%d", EFI_SIGNAL_EXECUTOR_HW_TIMER); printMsg(&logger, "EFI_SIGNAL_EXECUTOR_HW_TIMER=%d", EFI_SIGNAL_EXECUTOR_HW_TIMER);
#endif #endif
#ifdef EFI_TUNER_STUDIO_OVER_USB
printMsg(&logger, "EFI_TUNER_STUDIO_OVER_USB=%d", EFI_TUNER_STUDIO_OVER_USB);
#else
printMsg(&logger, "EFI_TUNER_STUDIO_OVER_USB=%d", 0);
#endif
#ifdef EFI_SHAFT_POSITION_INPUT
printMsg(&logger, "EFI_SHAFT_POSITION_INPUT=%d", EFI_SHAFT_POSITION_INPUT); printMsg(&logger, "EFI_SHAFT_POSITION_INPUT=%d", EFI_SHAFT_POSITION_INPUT);
#endif
#ifdef EFI_INTERNAL_ADC
printMsg(&logger, "EFI_INTERNAL_ADC=%d", EFI_INTERNAL_ADC); printMsg(&logger, "EFI_INTERNAL_ADC=%d", EFI_INTERNAL_ADC);
#endif
// printSimpleMsg(&logger, "", ); // printSimpleMsg(&logger, "", );
// printSimpleMsg(&logger, "", ); // printSimpleMsg(&logger, "", );
@ -119,6 +115,7 @@ static void sayHello(void) {
* This methods prints all threads and their total times * This methods prints all threads and their total times
*/ */
static void cmd_threads(void) { static void cmd_threads(void) {
#if CH_DBG_THREADS_PROFILING || defined(__DOXYGEN__)
static const char *states[] = { THD_STATE_NAMES }; static const char *states[] = { THD_STATE_NAMES };
Thread *tp; Thread *tp;
@ -130,6 +127,7 @@ static void cmd_threads(void) {
states[tp->p_state], (uint32_t) tp->p_time, tp->p_name); states[tp->p_state], (uint32_t) tp->p_time, tp->p_name);
tp = chRegNextThread(tp); tp = chRegNextThread(tp);
} while (tp != NULL ); } while (tp != NULL );
#endif
} }
void sendOutConfirmation(char *value, int i) { void sendOutConfirmation(char *value, int i) {
@ -140,12 +138,14 @@ void sendOutConfirmation(char *value, int i) {
* This methods prints the message to whatever is configured as our primary console * This methods prints the message to whatever is configured as our primary console
*/ */
void print(const char *format, ...) { void print(const char *format, ...) {
#if !EFI_UART_ECHO_TEST_MODE
if (!isConsoleReady()) if (!isConsoleReady())
return; return;
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
chvprintf((BaseSequentialStream *)CONSOLE_CHANNEL, format, ap); chvprintf((BaseSequentialStream*)getConsoleChannel(), format, ap);
va_end(ap); va_end(ap);
#endif /* EFI_UART_ECHO_TEST_MODE */
} }
void initializeConsole() { void initializeConsole() {
@ -163,5 +163,6 @@ void initializeConsole() {
#endif #endif
addConsoleAction("fatal", myfatal); addConsoleAction("fatal", myfatal);
addConsoleAction("error", myerror);
addConsoleAction("threadsinfo", cmd_threads); addConsoleAction("threadsinfo", cmd_threads);
} }

View File

@ -38,10 +38,8 @@
#include "io_pins.h" #include "io_pins.h"
#include "mmc_card.h" #include "mmc_card.h"
#include "console_io.h" #include "console_io.h"
#include "malfunction_central.h"
#define PRINT_FIRMWARE_ONCE TRUE #include "speed_density.h"
static bool_t firmwareErrorReported = FALSE;
#include "advance_map.h" #include "advance_map.h"
#if EFI_TUNER_STUDIO #if EFI_TUNER_STUDIO
@ -57,6 +55,7 @@ static bool_t firmwareErrorReported = FALSE;
#include "engine_configuration.h" #include "engine_configuration.h"
#include "rfiutil.h" #include "rfiutil.h"
#include "svnversion.h" #include "svnversion.h"
#include "engine.h"
#if EFI_PROD_CODE #if EFI_PROD_CODE
// todo: move this logic to algo folder! // todo: move this logic to algo folder!
@ -65,6 +64,8 @@ static bool_t firmwareErrorReported = FALSE;
#include "rusefi.h" #include "rusefi.h"
#endif #endif
extern Engine engine;
// this 'true' value is needed for simulator // this 'true' value is needed for simulator
static volatile int fullLog = TRUE; static volatile int fullLog = TRUE;
int warningEnabled = TRUE; int warningEnabled = TRUE;
@ -72,6 +73,7 @@ int warningEnabled = TRUE;
extern engine_configuration_s * engineConfiguration; extern engine_configuration_s * engineConfiguration;
extern engine_configuration2_s * engineConfiguration2; extern engine_configuration2_s * engineConfiguration2;
extern board_configuration_s *boardConfiguration;
#define FULL_LOGGING_KEY "fl" #define FULL_LOGGING_KEY "fl"
#if EFI_PROD_CODE || EFI_SIMULATOR #if EFI_PROD_CODE || EFI_SIMULATOR
@ -97,7 +99,7 @@ static void reportSensorF(const char *caption, float value, int precision) {
#endif /* EFI_FILE_LOGGING */ #endif /* EFI_FILE_LOGGING */
} }
static void reportSensorI(char *caption, int value) { static void reportSensorI(const char *caption, int value) {
#if EFI_PROD_CODE || EFI_SIMULATOR #if EFI_PROD_CODE || EFI_SIMULATOR
debugInt(&logger, caption, value); debugInt(&logger, caption, value);
#endif /* EFI_PROD_CODE || EFI_SIMULATOR */ #endif /* EFI_PROD_CODE || EFI_SIMULATOR */
@ -154,6 +156,7 @@ void printSensors(void) {
} }
void printState(int currentCkpEventCounter) { void printState(int currentCkpEventCounter) {
#if EFI_SHAFT_POSITION_INPUT
printSensors(); printSensors();
int rpm = getRpm(); int rpm = getRpm();
@ -177,6 +180,7 @@ void printState(int currentCkpEventCounter) {
// float fuel = getDefaultFuel(rpm, map); // float fuel = getDefaultFuel(rpm, map);
// debugFloat(&logger, "d_fuel", fuel, 2); // debugFloat(&logger, "d_fuel", fuel, 2);
#endif /* EFI_SHAFT_POSITION_INPUT */
} }
#define INITIAL_FULL_LOG TRUE #define INITIAL_FULL_LOG TRUE
@ -201,32 +205,31 @@ static void printStatus(void) {
// return getTCharge(getCurrentRpm(), tps, cltK, iatK); // return getTCharge(getCurrentRpm(), tps, cltK, iatK);
//} //}
#if EFI_CUSTOM_PANIC_METHOD //#if EFI_CUSTOM_PANIC_METHOD
extern char *dbg_panic_file; //extern char *dbg_panic_file;
extern int dbg_panic_line; //extern int dbg_panic_line;
#endif //#endif
bool_t hasFatalError(void) { //static void checkIfShouldHalt(void) {
return dbg_panic_msg != NULL; //#if CH_DBG_ENABLED
} // if (hasFatalError()) {
// /**
static void checkIfShouldHalt(void) { // * low-level function is used here to reduce stack usage
#if CH_DBG_ENABLED // */
if (hasFatalError()) { // palWritePad(LED_ERROR_PORT, LED_ERROR_PIN, 1);
setOutputPinValue(LED_ERROR, 1); //#if EFI_CUSTOM_PANIC_METHOD
#if EFI_CUSTOM_PANIC_METHOD // print("my FATAL [%s] at %s:%d\r\n", dbg_panic_msg, dbg_panic_file, dbg_panic_line);
print("my FATAL [%s] at %s:%d\r\n", dbg_panic_msg, dbg_panic_file, dbg_panic_line); //#else
#else // print("my FATAL [%s] at %s:%d\r\n", dbg_panic_msg);
print("my FATAL [%s] at %s:%d\r\n", dbg_panic_msg); //#endif
#endif // chThdSleepSeconds(1);
chThdSleepSeconds(1); // // todo: figure out how we halt exactly
// todo: figure out how we halt exactly // while (TRUE) {
while (TRUE) { // }
} // chSysHalt();
chSysHalt(); // }
} //#endif
#endif //}
}
/** /**
* Time when the firmware version was reported last time, in seconds * Time when the firmware version was reported last time, in seconds
@ -253,14 +256,14 @@ extern char errorMessageBuffer[200];
void updateDevConsoleState(void) { void updateDevConsoleState(void) {
if (!isConsoleReady()) if (!isConsoleReady())
return; return;
checkIfShouldHalt(); // looks like this is not needed anymore
// checkIfShouldHalt();
printPending(); printPending();
if (hasFirmwareError()) { if (hasFirmwareError()) {
if (!firmwareErrorReported || !PRINT_FIRMWARE_ONCE) printMsg(&logger, "firmware error: %s", errorMessageBuffer);
printMsg(&logger, "firmware error: %s", errorMessageBuffer);
firmwareErrorReported = TRUE;
warningEnabled = FALSE; warningEnabled = FALSE;
chThdSleepMilliseconds(200);
return; return;
} }
@ -324,7 +327,7 @@ void updateHD44780lcd(void) {
lcd_HD44780_print_char('R'); lcd_HD44780_print_char('R');
lcd_HD44780_set_position(0, 10); lcd_HD44780_set_position(0, 10);
char * ptr = itoa10((uint8_t*) buffer, getRpm()); char * ptr = itoa10(buffer, getRpm());
ptr[0] = 0; ptr[0] = 0;
int len = ptr - buffer; int len = ptr - buffer;
for (int i = 0; i < 6 - len; i++) for (int i = 0; i < 6 - len; i++)
@ -346,7 +349,7 @@ void updateHD44780lcd(void) {
} }
#endif /* EFI_PROD_CODE */ #endif /* EFI_PROD_CODE */
static WORKING_AREA(lcdThreadStack, UTILITY_THREAD_STACK_SIZE); static THD_WORKING_AREA(lcdThreadStack, UTILITY_THREAD_STACK_SIZE);
static void lcdThread(void *arg) { static void lcdThread(void *arg) {
chRegSetThreadName("lcd"); chRegSetThreadName("lcd");
@ -354,20 +357,49 @@ static void lcdThread(void *arg) {
#if EFI_HD44780_LCD #if EFI_HD44780_LCD
updateHD44780lcd(); updateHD44780lcd();
#endif #endif
chThdSleepMilliseconds(50); chThdSleepMilliseconds(boardConfiguration->lcdThreadPeriod);
} }
} }
static WORKING_AREA(tsThreadStack, UTILITY_THREAD_STACK_SIZE); static THD_WORKING_AREA(tsThreadStack, UTILITY_THREAD_STACK_SIZE);
#if EFI_TUNER_STUDIO
extern TunerStudioOutputChannels tsOutputChannels;
void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels) {
#if EFI_SHAFT_POSITION_INPUT
int rpm = getRpm();
#else
int rpm = 0;
#endif
float tps = getTPS();
float coolant = getCoolantTemperature();
float intake = getIntakeAirTemperature();
tsOutputChannels->rpm = rpm;
tsOutputChannels->coolant_temperature = coolant;
tsOutputChannels->intake_air_temperature = intake;
tsOutputChannels->throttle_positon = tps;
tsOutputChannels->mass_air_flow = getMaf();
tsOutputChannels->air_fuel_ratio = getAfr();
tsOutputChannels->v_batt = getVBatt();
tsOutputChannels->tpsADC = getTPS10bitAdc();
tsOutputChannels->atmospherePressure = getBaroPressure();
tsOutputChannels->manifold_air_pressure = getMap();
tsOutputChannels->checkEngine = hasErrorCodes();
tsOutputChannels->tCharge = getTCharge(rpm, tps, coolant, intake);
}
#endif /* EFI_TUNER_STUDIO */
static void tsStatusThread(void *arg) { static void tsStatusThread(void *arg) {
chRegSetThreadName("tuner s"); chRegSetThreadName("tuner s");
while (true) { while (true) {
#if EFI_TUNER_STUDIO #if EFI_TUNER_STUDIO
// sensor state for EFI Analytics Tuner Studio // sensor state for EFI Analytics Tuner Studio
updateTunerStudioState(); updateTunerStudioState(&tsOutputChannels);
#endif /* EFI_TUNER_STUDIO */ #endif /* EFI_TUNER_STUDIO */
chThdSleepMilliseconds(50); chThdSleepMilliseconds(boardConfiguration->tunerStudioThreadPeriod);
} }
} }

View File

@ -37,13 +37,37 @@
#include "tunerstudio_configuration.h" #include "tunerstudio_configuration.h"
#include "malfunction_central.h" #include "malfunction_central.h"
#include "wave_math.h" #include "wave_math.h"
#include "console_io.h"
#include "crc.h"
#if EFI_TUNER_STUDIO #if EFI_TUNER_STUDIO
#define MAX_PAGE_ID 5
#define PAGE_0_SIZE 1356
// in MS, that's 10 seconds
#define TS_READ_TIMEOUT 10000
#define TS_SERIAL_UART_DEVICE &SD3
//#define TS_SERIAL_SPEED 115200
#define TS_SERIAL_SPEED 38400
#define PROTOCOL "001"
extern SerialUSBDriver SDU1;
BaseChannel * getTsSerialDevice(void) {
if (isSerialOverUart()) {
// if console uses UART then TS uses USB
return (BaseChannel *) &SDU1;
} else {
return (BaseChannel *) TS_SERIAL_UART_DEVICE;
}
}
static Logging logger; static Logging logger;
extern engine_configuration_s *engineConfiguration; extern engine_configuration_s *engineConfiguration;
extern board_configuration_s *boardConfiguration;
extern persistent_config_s configWorkingCopy; extern persistent_config_s configWorkingCopy;
extern persistent_config_container_s persistentState; extern persistent_config_container_s persistentState;
@ -52,47 +76,49 @@ extern SerialUSBDriver SDU1;
static efitimems_t previousWriteReportMs = 0; static efitimems_t previousWriteReportMs = 0;
#if EFI_TUNER_STUDIO_OVER_USB static int ts_serail_ready(void) {
#define ts_serail_ready() is_usb_serial_ready() if (isSerialOverUart()) {
#else // TS uses USB when console uses serial
#define ts_serail_ready() TRUE return is_usb_serial_ready();
static SerialConfig tsSerialConfig = { TS_SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 }; } else {
#endif /* EFI_TUNER_STUDIO_OVER_USB */ // TS uses serial when console uses USB
return TRUE;
}
}
static WORKING_AREA(TS_WORKING_AREA, UTILITY_THREAD_STACK_SIZE); static SerialConfig tsSerialConfig = { TS_SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 };
static THD_WORKING_AREA(TS_WORKING_AREA, UTILITY_THREAD_STACK_SIZE);
static int tsCounter = 0; static int tsCounter = 0;
static int writeCounter = 0;
static short pageId; //static TunerStudioWriteValueRequest writeValueRequest;
//static TunerStudioWriteChunkRequest writeChunkRequest;
static TunerStudioWriteRequest writeRequest;
extern TunerStudioOutputChannels tsOutputChannels; extern TunerStudioOutputChannels tsOutputChannels;
//char *constantsAsPtr = (char *) &configWorkingCopy;
extern TunerStudioState tsState; extern TunerStudioState tsState;
static void printStats(void) { static void printStats(void) {
#if EFI_TUNER_STUDIO_OVER_USB if (!isSerialOverUart()) {
#else scheduleMsg(&logger, "TS RX on %s%d", portname(TS_SERIAL_RX_PORT), TS_SERIAL_RX_PIN);
scheduleMsg(&logger, "TS RX on %s%d", portname(TS_SERIAL_RX_PORT), TS_SERIAL_RX_PIN); scheduleMsg(&logger, "TS TX on %s%d", portname(TS_SERIAL_TX_PORT), TS_SERIAL_TX_PIN);
scheduleMsg(&logger, "TS TX on %s%d", portname(TS_SERIAL_TX_PORT), TS_SERIAL_TX_PIN); }
#endif /* EFI_TUNER_STUDIO_OVER_USB */
scheduleMsg(&logger, "TunerStudio total/error counter=%d/%d", tsCounter, tsState.errorCounter); scheduleMsg(&logger, "TunerStudio total/error counter=%d/%d", tsCounter, tsState.errorCounter);
scheduleMsg(&logger, "TunerStudio H counter=%d", tsState.queryCommandCounter); scheduleMsg(&logger, "TunerStudio H counter=%d", tsState.queryCommandCounter);
scheduleMsg(&logger, "TunerStudio O counter=%d size=%d", tsState.outputChannelsCommandCounter, scheduleMsg(&logger, "TunerStudio O counter=%d size=%d", tsState.outputChannelsCommandCounter,
sizeof(tsOutputChannels)); sizeof(tsOutputChannels));
scheduleMsg(&logger, "TunerStudio C counter=%d", tsState.readPageCommandsCounter); scheduleMsg(&logger, "TunerStudio P counter=%d", tsState.readPageCommandsCounter);
scheduleMsg(&logger, "TunerStudio B counter=%d", tsState.burnCommandCounter); scheduleMsg(&logger, "TunerStudio B counter=%d", tsState.burnCommandCounter);
scheduleMsg(&logger, "TunerStudio W counter=%d", writeCounter); scheduleMsg(&logger, "TunerStudio W counter=%d", tsState.writeValueCommandCounter);
scheduleMsg(&logger, "TunerStudio C counter=%d", tsState.writeChunkCommandCounter);
scheduleMsg(&logger, "TunerStudio P counter=%d current page %d", tsState.pageCommandCounter, tsState.currentPageId);
scheduleMsg(&logger, "page 0 size=%d", getTunerStudioPageSize(0)); scheduleMsg(&logger, "page 0 size=%d", getTunerStudioPageSize(0));
scheduleMsg(&logger, "page 1 size=%d", getTunerStudioPageSize(1)); scheduleMsg(&logger, "page 1 size=%d", getTunerStudioPageSize(1));
} }
void tunerStudioWriteData(const uint8_t * buffer, int size) { void tunerStudioWriteData(const uint8_t * buffer, int size) {
chSequentialStreamWrite(TS_SERIAL_DEVICE, buffer, size); chSequentialStreamWrite(getTsSerialDevice(), buffer, size);
} }
void tunerStudioDebug(char *msg) { void tunerStudioDebug(char *msg) {
@ -108,6 +134,11 @@ char *getWorkingPageAddr(int pageIndex) {
return (char*) &configWorkingCopy.engineConfiguration; return (char*) &configWorkingCopy.engineConfiguration;
case 1: case 1:
return (char*) &configWorkingCopy.boardConfiguration; return (char*) &configWorkingCopy.boardConfiguration;
case 2: // fuelTable
case 3: // ignitionTable
case 4: // veTable
case 5: // afrTable
return (char*) &configWorkingCopy.engineConfiguration + PAGE_0_SIZE + (pageIndex - 2) * 1024;
} }
return NULL; return NULL;
} }
@ -115,86 +146,143 @@ char *getWorkingPageAddr(int pageIndex) {
int getTunerStudioPageSize(int pageIndex) { int getTunerStudioPageSize(int pageIndex) {
switch (pageIndex) { switch (pageIndex) {
case 0: case 0:
return sizeof(configWorkingCopy.engineConfiguration); return PAGE_0_SIZE;
case 1: case 1:
return sizeof(configWorkingCopy.boardConfiguration); return sizeof(configWorkingCopy.boardConfiguration);
case 2:
case 3:
case 4:
return 1024;
} }
return 0; return 0;
}
void handlePageSelectCommand(uint16_t pageId) {
tsState.pageCommandCounter++;
tsState.currentPageId = pageId;
scheduleMsg(&logger, "page %d selected", tsState.currentPageId);
tunerStudioWriteCrcPacket(TS_RESPONSE_OK, NULL, 0);
}
/**
* This command is needed to make the whole transfer a bit faster
* @note See also handleWriteValueCommand
*/
void handleWriteChunkCommand(short offset, short count, void *content) {
tsState.writeChunkCommandCounter++;
scheduleMsg(&logger, "receiving page %d chunk offset %d size %d", tsState.currentPageId, offset, count);
if (offset > getTunerStudioPageSize(tsState.currentPageId)) {
scheduleMsg(&logger, "ERROR offset %d", offset);
// out of range
tsState.errorCounter++;
offset = 0;
}
if (count > getTunerStudioPageSize(tsState.currentPageId)) {
scheduleMsg(&logger, "ERROR count %d", count);
// out of range
tsState.errorCounter++;
count = 0;
}
uint8_t * addr = (uint8_t *) (getWorkingPageAddr(tsState.currentPageId) + offset);
// memcpy(addr, content, count);
tunerStudioWriteCrcPacket(TS_RESPONSE_OK, NULL, 0);
} }
/** /**
* 'Write' command receives a single value at a given offset * 'Write' command receives a single value at a given offset
* @note Writing values one by one is pretty slow
*/ */
void handleValueWriteCommand(void) { void handleWriteValueCommand(uint16_t page, uint16_t offset, uint8_t value) {
writeCounter++; tsState.writeValueCommandCounter++;
//tunerStudioDebug("got W (Write)"); // we can get a lot of these tsState.currentPageId = page;
//tunerStudioDebug("got W (Write)"); // we can get a lot of these
int recieved = chSequentialStreamRead(TS_SERIAL_DEVICE, (uint8_t *)&pageId, 2);
if (recieved != 2) {
tsState.errorCounter++;
return;
}
#if EFI_TUNER_STUDIO_VERBOSE #if EFI_TUNER_STUDIO_VERBOSE
// scheduleMsg(&logger, "Page number %d\r\n", pageId); // we can get a lot of these // scheduleMsg(&logger, "Page number %d\r\n", pageId); // we can get a lot of these
#endif #endif
int size = sizeof(TunerStudioWriteRequest); int size = sizeof(TunerStudioWriteValueRequest);
// scheduleMsg(&logger, "Reading %d\r\n", size); // scheduleMsg(&logger, "Reading %d\r\n", size);
recieved = chSequentialStreamRead(TS_SERIAL_DEVICE, (uint8_t *)&writeRequest, size); if (offset > getTunerStudioPageSize(tsState.currentPageId)) {
// scheduleMsg(&logger, "got %d", recieved); scheduleMsg(&logger, "ERROR offset %d", offset);
// out of range
// unsigned char offset = writeBuffer[0]; tsState.errorCounter++;
// unsigned char value = writeBuffer[1]; offset = 0;
// return;
}
efitimems_t nowMs = currentTimeMillis(); efitimems_t nowMs = currentTimeMillis();
if (nowMs - previousWriteReportMs > 5) { if (nowMs - previousWriteReportMs > 5) {
previousWriteReportMs = nowMs; previousWriteReportMs = nowMs;
// scheduleMsg(&logger, "page %d offset %d: value=%d", pageId, writeRequest.offset, writeRequest.value); scheduleMsg(&logger, "page %d offset %d: value=%d", tsState.currentPageId, offset, value);
} }
getWorkingPageAddr(pageId)[writeRequest.offset] = writeRequest.value; getWorkingPageAddr(tsState.currentPageId)[offset] = value;
// scheduleMsg(&logger, "va=%d", configWorkingCopy.boardConfiguration.idleValvePin); // scheduleMsg(&logger, "va=%d", configWorkingCopy.boardConfiguration.idleValvePin);
} }
void handlePageReadCommand(void) { static void sendErrorCode(void) {
tunerStudioWriteCrcPacket(TS_RESPONSE_CRC_FAILURE, NULL, 0);
}
void handlePageReadCommand(uint16_t pageId, uint16_t offset, uint16_t count) {
tsState.readPageCommandsCounter++; tsState.readPageCommandsCounter++;
tunerStudioDebug("got C (Constants)"); tunerStudioDebug("got R (Read page)");
int recieved = chSequentialStreamRead(TS_SERIAL_DEVICE, (uint8_t *)&pageId, 2); tsState.currentPageId = pageId;
if (recieved != 2) {
#if EFI_TUNER_STUDIO_VERBOSE
scheduleMsg(&logger, "Page requested: page %d offset=%d count=%d", tsState.currentPageId, offset, count);
#endif
if (tsState.currentPageId > MAX_PAGE_ID) {
scheduleMsg(&logger, "invalid Page number %x", tsState.currentPageId);
// something is not right here
tsState.currentPageId = 0;
tsState.errorCounter++; tsState.errorCounter++;
return; return;
} }
int size = getTunerStudioPageSize(tsState.currentPageId);
if (size < offset + count) {
scheduleMsg(&logger, "invalid offset/count %d/%d", offset, count);
sendErrorCode();
return;
}
const uint8_t *addr = (const uint8_t *) (getWorkingPageAddr(tsState.currentPageId) + offset);
tunerStudioWriteCrcPacket(TS_RESPONSE_OK, addr, count);
#if EFI_TUNER_STUDIO_VERBOSE #if EFI_TUNER_STUDIO_VERBOSE
scheduleMsg(&logger, "Page number %d", pageId); scheduleMsg(&logger, "Sending %d done", size);
#endif #endif
tunerStudioWriteData((const uint8_t *) getWorkingPageAddr(pageId), getTunerStudioPageSize(pageId));
} }
/** /**
* 'Burn' command is a command to commit the changes * 'Burn' command is a command to commit the changes
*/ */
void handleBurnCommand(void) { void handleBurnCommand(uint16_t page) {
tsState.burnCommandCounter++; tsState.burnCommandCounter++;
tunerStudioDebug("got B (Burn)"); tunerStudioDebug("got B (Burn)");
int recieved = chSequentialStreamRead(TS_SERIAL_DEVICE, (uint8_t *)&pageId, 2); tsState.currentPageId = page;
if (recieved != 2) {
tsState.errorCounter++;
return;
}
#if EFI_TUNER_STUDIO_VERBOSE #if EFI_TUNER_STUDIO_VERBOSE
scheduleMsg(&logger, "Page number %d\r\n", pageId); scheduleMsg(&logger, "Page number %d\r\n", tsState.currentPageId);
#endif #endif
// todo: how about some multi-threading? // todo: how about some multi-threading?
memcpy(&persistentState.persistentConfiguration, &configWorkingCopy, sizeof(persistent_config_s)); memcpy(&persistentState.persistentConfiguration, &configWorkingCopy, sizeof(persistent_config_s));
scheduleMsg(&logger, "va1=%d", configWorkingCopy.boardConfiguration.idleValvePin); scheduleMsg(&logger, "va1=%d", configWorkingCopy.boardConfiguration.idleValvePin);
@ -202,8 +290,15 @@ void handleBurnCommand(void) {
writeToFlash(); writeToFlash();
incrementGlobalConfigurationVersion(); incrementGlobalConfigurationVersion();
tunerStudioWriteCrcPacket(TS_RESPONSE_BURN_OK, NULL, 0);
} }
static uint8_t firstByte;
static uint8_t secondByte;
// todo: reduce TS page size so that we can reduce buffer size
static char crcIoBuffer[4096];
static msg_t tsThreadEntryPoint(void *arg) { static msg_t tsThreadEntryPoint(void *arg) {
(void) arg; (void) arg;
chRegSetThreadName("tunerstudio thread"); chRegSetThreadName("tunerstudio thread");
@ -216,41 +311,128 @@ static msg_t tsThreadEntryPoint(void *arg) {
wasReady = FALSE; wasReady = FALSE;
continue; continue;
} }
if (!wasReady) { if (!wasReady) {
wasReady = TRUE; wasReady = TRUE;
// scheduleSimpleMsg(&logger, "ts channel is now ready ", hTimeNow()); // scheduleSimpleMsg(&logger, "ts channel is now ready ", hTimeNow());
} }
short command = (short) chSequentialStreamGet(TS_SERIAL_DEVICE);
int success = tunerStudioHandleCommand(command);
if (!success && command != 0)
print("got unexpected TunerStudio command %c:%d\r\n", command, command);
tsCounter++; tsCounter++;
int recieved = chSequentialStreamRead(getTsSerialDevice(), &firstByte, 1);
if (recieved != 1) {
tsState.errorCounter++;
continue;
}
// scheduleMsg(&logger, "Got first=%x=[%c]", firstByte, firstByte);
if (firstByte == TS_HELLO_COMMAND) {
scheduleMsg(&logger, "Got naked Query command");
handleQueryCommand(FALSE);
continue;
} else if (firstByte == 't' || firstByte == 'T') {
handleTestCommand();
continue;
} else if (firstByte == TS_READ_COMMAND) {
scheduleMsg(&logger, "Got naked READ PAGE???");
continue;
} else if (firstByte == TS_OUTPUT_COMMAND) {
scheduleMsg(&logger, "Got naked Channels???");
continue;
} else if (firstByte == 'F') {
tunerStudioDebug("not ignoring F");
tunerStudioWriteData((const uint8_t *) PROTOCOL, strlen(PROTOCOL));
continue;
}
recieved = chSequentialStreamRead(getTsSerialDevice(), &secondByte, 1);
if (recieved != 1) {
tsState.errorCounter++;
continue;
}
// scheduleMsg(&logger, "Got secondByte=%x=[%c]", secondByte, secondByte);
int incomingPacketSize = firstByte * 256 + secondByte;
if (incomingPacketSize == 0 || incomingPacketSize > sizeof(crcIoBuffer)) {
scheduleMsg(&logger, "TunerStudio: invalid size: %d", incomingPacketSize);
tsState.errorCounter++;
sendErrorCode();
continue;
}
recieved = chnReadTimeout(getTsSerialDevice(), crcIoBuffer, 1, MS2ST(TS_READ_TIMEOUT));
if (recieved != 1) {
scheduleMsg(&logger, "did not receive command");
tsState.errorCounter++;
continue;
}
char command = crcIoBuffer[0];
if (command != TS_HELLO_COMMAND && command != TS_READ_COMMAND && command != TS_OUTPUT_COMMAND
&& command != TS_PAGE_COMMAND && command != TS_BURN_COMMAND && command != TS_SINGLE_WRITE_COMMAND
&& command != TS_CHUNK_WRITE_COMMAND) {
scheduleMsg(&logger, "unexpected command %x", command);
sendErrorCode();
continue;
}
// scheduleMsg(&logger, "TunerStudio: reading %d+4 bytes(s)", incomingPacketSize);
recieved = chnReadTimeout(getTsSerialDevice(), (void * ) (crcIoBuffer + 1), incomingPacketSize + 4 - 1,
MS2ST(TS_READ_TIMEOUT));
if (recieved != incomingPacketSize + 4 - 1) {
scheduleMsg(&logger, "got ONLY %d", recieved);
tsState.errorCounter++;
continue;
}
uint32_t expectedCrc = *(uint32_t*) (crcIoBuffer + incomingPacketSize);
expectedCrc = SWAP_UINT32(expectedCrc);
int actualCrc = crc32(crcIoBuffer, incomingPacketSize);
if (actualCrc != expectedCrc) {
scheduleMsg(&logger, "TunerStudio: CRC %x %x %x %x", crcIoBuffer[incomingPacketSize + 0],
crcIoBuffer[incomingPacketSize + 1], crcIoBuffer[incomingPacketSize + 2],
crcIoBuffer[incomingPacketSize + 3]);
scheduleMsg(&logger, "TunerStudio: command %c actual CRC %x/expected %x", crcIoBuffer[0], actualCrc,
expectedCrc);
tsState.errorCounter++;
continue;
}
// scheduleMsg(&logger, "TunerStudio: P00-07 %x %x %x %x %x %x %x %x", crcIoBuffer[0], crcIoBuffer[1],
// crcIoBuffer[2], crcIoBuffer[3], crcIoBuffer[4], crcIoBuffer[5], crcIoBuffer[6], crcIoBuffer[7]);
int success = tunerStudioHandleCommand(crcIoBuffer, incomingPacketSize);
if (!success)
print("got unexpected TunerStudio command %x:%c\r\n", command, command);
} }
#if defined __GNUC__ #if defined __GNUC__
return 0; return 0;
#endif #endif
} }
extern engine_configuration_s *engineConfiguration;
void syncTunerStudioCopy(void) { void syncTunerStudioCopy(void) {
memcpy(&configWorkingCopy, &persistentState.persistentConfiguration, sizeof(persistent_config_s)); memcpy(&configWorkingCopy, &persistentState.persistentConfiguration, sizeof(persistent_config_s));
} }
void startTunerStudioConnectivity(void) { void startTunerStudioConnectivity(void) {
initLogging(&logger, "tuner studio"); initLogging(&logger, "tuner studio");
#if EFI_TUNER_STUDIO_OVER_USB memset(&tsState, 0, sizeof(tsState));
print("TunerStudio over USB serial"); if (isSerialOverUart()) {
usb_serial_start(); print("TunerStudio over USB serial");
#else usb_serial_start();
print("TunerStudio over USART"); } else {
mySetPadMode("tunerstudio rx", TS_SERIAL_RX_PORT, TS_SERIAL_RX_PIN, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
mySetPadMode("tunerstudio tx", TS_SERIAL_TX_PORT, TS_SERIAL_TX_PIN, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
sdStart(TS_SERIAL_DEVICE, &tsSerialConfig); print("TunerStudio over USART");
#endif mySetPadMode("tunerstudio rx", TS_SERIAL_RX_PORT, TS_SERIAL_RX_PIN, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
mySetPadMode("tunerstudio tx", TS_SERIAL_TX_PORT, TS_SERIAL_TX_PIN, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
sdStart(TS_SERIAL_UART_DEVICE, &tsSerialConfig);
}
syncTunerStudioCopy(); syncTunerStudioCopy();
@ -259,18 +441,22 @@ void startTunerStudioConnectivity(void) {
chThdCreateStatic(TS_WORKING_AREA, sizeof(TS_WORKING_AREA), NORMALPRIO, tsThreadEntryPoint, NULL); chThdCreateStatic(TS_WORKING_AREA, sizeof(TS_WORKING_AREA), NORMALPRIO, tsThreadEntryPoint, NULL);
} }
void updateTunerStudioState() { /**
tsOutputChannels.rpm = getRpm(); * Adds size to the beginning of a packet and a crc32 at the end. Then send the packet.
tsOutputChannels.coolant_temperature = getCoolantTemperature(); */
tsOutputChannels.intake_air_temperature = getIntakeAirTemperature(); void tunerStudioWriteCrcPacket(const uint8_t command, const void *buf, const uint16_t size) {
tsOutputChannels.throttle_positon = getTPS(); // todo: max size validation
tsOutputChannels.mass_air_flow = getMaf(); *(uint16_t *) crcIoBuffer = SWAP_UINT16(size + 1); // packet size including command
tsOutputChannels.air_fuel_ratio = getAfr(); *(uint8_t *) (crcIoBuffer + 2) = command;
tsOutputChannels.v_batt = getVBatt(); if (size != 0)
tsOutputChannels.tpsADC = getTPS10bitAdc(); memcpy(crcIoBuffer + 3, buf, size);
tsOutputChannels.atmospherePressure = getBaroPressure(); // CRC on whole packet
tsOutputChannels.manifold_air_pressure = getMap(); uint32_t crc = crc32((void *) (crcIoBuffer + 2), (uint32_t) (size + 1));
tsOutputChannels.checkEngine = hasErrorCodes(); *(uint32_t *) (crcIoBuffer + 2 + 1 + size) = SWAP_UINT32(crc);
// scheduleMsg(&logger, "TunerStudio: CRC command %x size %d", command, size);
tunerStudioWriteData(crcIoBuffer, size + 2 + 1 + 4); // with size, command and CRC
} }
#endif /* EFI_TUNER_STUDIO */ #endif /* EFI_TUNER_STUDIO */

View File

@ -8,13 +8,18 @@
#ifndef TUNERSTUDIO_H_ #ifndef TUNERSTUDIO_H_
#define TUNERSTUDIO_H_ #define TUNERSTUDIO_H_
#if EFI_TUNER_STUDIO_OVER_USB #include "tunerstudio_configuration.h"
#define TS_SERIAL_DEVICE (&SDU1)
#else
#define TS_SERIAL_DEVICE &SD3
#define TS_SERIAL_SPEED 115200
#endif /* EFI_TUNER_STUDIO_OVER_USB */ #if defined __GNUC__
typedef struct
__attribute__((packed)) {
#else
typedef __packed struct {
#endif
short int offset;
short int count;
} TunerStudioWriteChunkRequest;
#if defined __GNUC__ #if defined __GNUC__
typedef struct typedef struct
@ -25,19 +30,19 @@ typedef struct
short int offset; short int offset;
unsigned char value; unsigned char value;
} TunerStudioWriteRequest; } TunerStudioWriteValueRequest;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif /* __cplusplus */ #endif /* __cplusplus */
void startTunerStudioConnectivity(void); void startTunerStudioConnectivity(void);
void syncTunerStudioCopy(void); void syncTunerStudioCopy(void);
void updateTunerStudioState(void); void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels);
void tunerStudioWriteCrcPacket(const uint8_t command, const void *buf, const uint16_t size);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif /* TUNERSTUDIO_H_ */ #endif /* TUNERSTUDIO_H_ */

View File

@ -2,6 +2,8 @@
* @file tunerstudio_algo.c * @file tunerstudio_algo.c
* @brief Tuner Studio plain protocol implementation * @brief Tuner Studio plain protocol implementation
* *
* This implementation would not happen without the documentation
* provided by Jon Zeeff (jon@zeeff.com)
* *
* Tuner Studio has a really simple protocol, a minimal implementation * Tuner Studio has a really simple protocol, a minimal implementation
* capable of displaying current engine state on the gauges would * capable of displaying current engine state on the gauges would
@ -63,17 +65,34 @@ TunerStudioOutputChannels tsOutputChannels;
*/ */
persistent_config_s configWorkingCopy; persistent_config_s configWorkingCopy;
int tunerStudioHandleCommand(short command) { int tunerStudioHandleCommand(char *data, int incomingPacketSize) {
if (command == 'H') { char command = data[0];
handleQueryCommand(); data++;
} else if (command == 'O') { if (command == TS_HELLO_COMMAND) {
tunerStudioDebug("got CRC Query");
handleQueryCommand(TRUE);
} else if (command == TS_OUTPUT_COMMAND) {
handleOutputChannelsCommand(); handleOutputChannelsCommand();
} else if (command == 'W') { } else if (command == TS_PAGE_COMMAND) {
handleValueWriteCommand(); uint16_t page = *(uint16_t *) data;
} else if (command == 'B') { handlePageSelectCommand(page);
handleBurnCommand(); } else if (command == TS_CHUNK_WRITE_COMMAND) {
} else if (command == 'C') { uint16_t offset = *(uint16_t *) data;
handlePageReadCommand(); uint16_t count = *(uint16_t *) (data + 2);
handleWriteChunkCommand(offset, count, data + 4);
} else if (command == TS_SINGLE_WRITE_COMMAND) {
uint16_t page = *(uint16_t *) data;
uint16_t offset = *(uint16_t *) (data + 2);
uint8_t value = data[4];
handleWriteValueCommand(page, offset, value);
} else if (command == TS_BURN_COMMAND) {
uint16_t page = *(uint16_t *) data;
handleBurnCommand(page);
} else if (command == TS_READ_COMMAND) {
uint16_t page = *(uint16_t *) data;
uint16_t offset = *(uint16_t *) (data + 2);
uint16_t count = *(uint16_t *) (data + 4);
handlePageReadCommand(page, offset, count);
} else if (command == 't' || command == 'T') { } else if (command == 't' || command == 'T') {
handleTestCommand(); handleTestCommand();
} else if (command == 'F') { } else if (command == 'F') {
@ -86,23 +105,23 @@ int tunerStudioHandleCommand(short command) {
* Currently on some firmware versions the F command is not used and is just ignored by the firmware as a unknown command." * Currently on some firmware versions the F command is not used and is just ignored by the firmware as a unknown command."
*/ */
} else { } else {
#if EFI_TUNER_STUDIO_OVER_USB tunerStudioDebug("ignoring unexpected");
/**
* With TTL there is a real chance of corrupted messages.
* With serial-over-USB we are not expecting communication errors
*/
// fatal("unexpected TunerStudio command in USB mode");
#endif /* EFI_TUNER_STUDIO_OVER_USB */
tsState.errorCounter++; tsState.errorCounter++;
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
void handleQueryCommand(void) { void handleQueryCommand(int needCrc) {
tsState.queryCommandCounter++; tsState.queryCommandCounter++;
tunerStudioDebug("got H (queryCommand)"); tunerStudioDebug("got H (queryCommand)");
tunerStudioWriteData((const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1); if (needCrc) {
// Query with CRC takes place while re-establishing connection
tunerStudioWriteCrcPacket(TS_RESPONSE_OK, (const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1);
} else {
// Query without CRC takes place on TunerStudio startup
tunerStudioWriteData((const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1);
}
} }
/** /**
@ -111,7 +130,7 @@ void handleQueryCommand(void) {
void handleOutputChannelsCommand(void) { void handleOutputChannelsCommand(void) {
tsState.outputChannelsCommandCounter++; tsState.outputChannelsCommandCounter++;
// this method is invoked too often to print any debug information // this method is invoked too often to print any debug information
tunerStudioWriteData((const uint8_t *) &tsOutputChannels, sizeof(TunerStudioOutputChannels)); tunerStudioWriteCrcPacket(TS_RESPONSE_OK, (const uint8_t *) &tsOutputChannels, sizeof(TunerStudioOutputChannels));
} }
void handleTestCommand(void) { void handleTestCommand(void) {
@ -119,6 +138,6 @@ void handleTestCommand(void) {
* this is NOT a standard TunerStudio command, this is my own * this is NOT a standard TunerStudio command, this is my own
* extension of the protocol to simplify troubleshooting * extension of the protocol to simplify troubleshooting
*/ */
tunerStudioDebug("got T (Test)\r\n"); tunerStudioDebug("got T (Test)");
tunerStudioWriteData((const uint8_t *) "alive\r\n", 7); tunerStudioWriteData((const uint8_t *) "alive\r\n", 7);
} }

View File

@ -12,27 +12,55 @@
#include <stdint.h> #include <stdint.h>
// http://en.wikipedia.org/wiki/Endianness
#define SWAP_UINT16(x) ((x) << 8) | ((x) >> 8)
#define SWAP_UINT32(x) (((x) >> 24) & 0xff) | (((x) << 8) & 0xff0000) | (((x) >> 8) & 0xff00) | (((x) << 24) & 0xff000000)
// response codes
#define TS_RESPONSE_OK 0x00
#define TS_RESPONSE_BURN_OK 0x04
#define TS_RESPONSE_CRC_FAILURE 0x82
typedef struct { typedef struct {
int queryCommandCounter; int queryCommandCounter;
int outputChannelsCommandCounter; int outputChannelsCommandCounter;
int readPageCommandsCounter; int readPageCommandsCounter;
int burnCommandCounter; int burnCommandCounter;
int pageCommandCounter;
int writeValueCommandCounter;
int writeChunkCommandCounter;
int errorCounter; int errorCounter;
// this field is in the end to simply aligning situation
short currentPageId;
} TunerStudioState; } TunerStudioState;
int tunerStudioHandleCommand(short command); int tunerStudioHandleCommand(char *data, int incomingPacketSize);
void handleTestCommand(void); void handleTestCommand(void);
void handleQueryCommand(void); void handleQueryCommand(int needCrc);
void handleOutputChannelsCommand(void); void handleOutputChannelsCommand(void);
char *getWorkingPageAddr(int pageIndex); char *getWorkingPageAddr(int pageIndex);
int getTunerStudioPageSize(int pageIndex); int getTunerStudioPageSize(int pageIndex);
void handleValueWriteCommand(void); void handleWriteValueCommand(uint16_t page, uint16_t offset, uint8_t value);
void handlePageReadCommand(void); void handleWriteChunkCommand(short offset, short count, void *content);
void handleBurnCommand(void); void handlePageSelectCommand(uint16_t pageId);
void handlePageReadCommand(uint16_t pageId, uint16_t offset, uint16_t count);
void handleBurnCommand(uint16_t page);
void tunerStudioWriteData(const uint8_t * buffer, int size); void tunerStudioWriteData(const uint8_t * buffer, int size);
void tunerStudioDebug(char *msg); void tunerStudioDebug(char *msg);
#define TS_HELLO_COMMAND 'H'
#define TS_OUTPUT_COMMAND 'O'
#define TS_READ_COMMAND 'R'
#define TS_PAGE_COMMAND 'P'
#define TS_SINGLE_WRITE_COMMAND 'W'
#define TS_CHUNK_WRITE_COMMAND 'C'
#define TS_BURN_COMMAND 'B'
#endif /* TUNERSTUDIO_ALGO_H_ */ #endif /* TUNERSTUDIO_ALGO_H_ */

View File

@ -29,6 +29,7 @@ typedef struct {
float atmospherePressure; // size 4, offset 36 float atmospherePressure; // size 4, offset 36
float manifold_air_pressure; // size 4, offset 40 float manifold_air_pressure; // size 4, offset 40
int checkEngine; // size 4, offset 44 int checkEngine; // size 4, offset 44
float tCharge;
} TunerStudioOutputChannels; } TunerStudioOutputChannels;
#endif /* TUNERSTUDIO_CONFIGURATION_H_ */ #endif /* TUNERSTUDIO_CONFIGURATION_H_ */

View File

@ -38,7 +38,6 @@
#include "memstreams.h" #include "memstreams.h"
#include "console_io.h" #include "console_io.h"
#define OUTPUT_BUFFER 9000
/** /**
* This is the size of the MemoryStream used by chvprintf * This is the size of the MemoryStream used by chvprintf
*/ */
@ -50,18 +49,15 @@
/** /**
* This is the buffer into which all the data providers write * This is the buffer into which all the data providers write
*/ */
#if defined __GNUC__ static char pendingBuffer[DL_OUTPUT_BUFFER] CCM_OPTIONAL;
static char pendingBuffer[OUTPUT_BUFFER] __attribute__((section(".ccm")));
#else
static char pendingBuffer[OUTPUT_BUFFER];
#endif
/** /**
* We copy all the pending data into this buffer once we are ready to push it out * We copy all the pending data into this buffer once we are ready to push it out
*/ */
static char outputBuffer[OUTPUT_BUFFER]; static char outputBuffer[DL_OUTPUT_BUFFER];
static MemoryStream intermediateLoggingBuffer; static MemoryStream intermediateLoggingBuffer;
static uint8_t intermediateLoggingBufferData[INTERMEDIATE_LOGGING_BUFFER_SIZE]; //todo define max-printf-buffer static uint8_t intermediateLoggingBufferData[INTERMEDIATE_LOGGING_BUFFER_SIZE] CCM_OPTIONAL; //todo define max-printf-buffer
static bool intermediateLoggingBufferInited = FALSE; static bool intermediateLoggingBufferInited = FALSE;
static int validateBuffer(Logging *logging, int extraLen, const char *text) { static int validateBuffer(Logging *logging, int extraLen, const char *text) {
@ -76,7 +72,7 @@ static int validateBuffer(Logging *logging, int extraLen, const char *text) {
strcat(logging->SMALL_BUFFER, logging->name); strcat(logging->SMALL_BUFFER, logging->name);
strcat(logging->SMALL_BUFFER, "/"); strcat(logging->SMALL_BUFFER, "/");
strcat(logging->SMALL_BUFFER, text); strcat(logging->SMALL_BUFFER, text);
fatal(logging->SMALL_BUFFER); firmwareError(logging->SMALL_BUFFER);
// unlockOutputBuffer(); // unlockOutputBuffer();
// resetLogging(logging); // resetLogging(logging);
return TRUE; return TRUE;
@ -85,7 +81,7 @@ static int validateBuffer(Logging *logging, int extraLen, const char *text) {
} }
void append(Logging *logging, const char *text) { void append(Logging *logging, const char *text) {
chDbgCheck(text!=NULL, "append NULL"); efiAssertVoid(text != NULL, "append NULL");
int extraLen = strlen(text); int extraLen = strlen(text);
int errcode = validateBuffer(logging, extraLen, text); int errcode = validateBuffer(logging, extraLen, text);
if (errcode) if (errcode)
@ -102,8 +98,9 @@ static void vappendPrintfI(Logging *logging, const char *fmt, va_list arg) {
} }
void vappendPrintf(Logging *logging, const char *fmt, va_list arg) { void vappendPrintf(Logging *logging, const char *fmt, va_list arg) {
efiAssertVoid(getRemainingStack(chThdSelf()) > 16, "stack#5b");
if (!intermediateLoggingBufferInited) { if (!intermediateLoggingBufferInited) {
fatal("intermediateLoggingBufferInited not inited!"); firmwareError("intermediateLoggingBufferInited not inited!");
return; return;
} }
int is_locked = isLocked(); int is_locked = isLocked();
@ -128,6 +125,7 @@ void vappendPrintf(Logging *logging, const char *fmt, va_list arg) {
} }
void appendPrintf(Logging *logging, const char *fmt, ...) { void appendPrintf(Logging *logging, const char *fmt, ...) {
efiAssertVoid(getRemainingStack(chThdSelf()) > 16, "stack#4");
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
vappendPrintf(logging, fmt, ap); vappendPrintf(logging, fmt, ap);
@ -154,7 +152,7 @@ char* getCaption(LoggingPoints loggingPoint) {
case LP_MAP_RAW: case LP_MAP_RAW:
return "MAP_R"; return "MAP_R";
} }
fatal("No such loggingPoint"); firmwareError("No such loggingPoint");
return NULL; return NULL;
} }
@ -176,7 +174,7 @@ static char* get2ndCaption(int loggingPoint) {
case LP_MAF: case LP_MAF:
return "MAF"; return "MAF";
} }
fatal("No such loggingPoint"); firmwareError("No such loggingPoint");
return NULL; return NULL;
} }
@ -204,7 +202,11 @@ void debugInt(Logging *logging, const char *caption, int value) {
} }
void appendFloat(Logging *logging, float value, int precision) { void appendFloat(Logging *logging, float value, int precision) {
// todo: this implementation is less than perfect /**
* todo: #1 this implementation is less than perfect
* todo: #2 The only way to avoid double promotion would probably be using *float instead of float
* See also http://stackoverflow.com/questions/5522051/printing-a-float-in-c-while-avoiding-variadic-parameter-promotion-to-double
*/
switch (precision) { switch (precision) {
case 1: case 1:
appendPrintf(logging, "%..10f", value); appendPrintf(logging, "%..10f", value);
@ -324,7 +326,7 @@ void scheduleMsg(Logging *logging, const char *fmt, ...) {
} }
// todo: remove this method, replace with 'scheduleMsg' // todo: remove this method, replace with 'scheduleMsg'
void scheduleIntValue(Logging *logging, char *msg, int value) { void scheduleIntValue(Logging *logging, const char *msg, int value) {
resetLogging(logging); resetLogging(logging);
append(logging, msg); append(logging, msg);
@ -339,10 +341,10 @@ void scheduleLogging(Logging *logging) {
// this could be done without locking // this could be done without locking
int newLength = strlen(logging->buffer); int newLength = strlen(logging->buffer);
bool_t alreadyLocked = lockOutputBuffer(); bool alreadyLocked = lockOutputBuffer();
// I hope this is fast enough to operate under sys lock // I hope this is fast enough to operate under sys lock
int curLength = strlen(pendingBuffer); int curLength = strlen(pendingBuffer);
if (curLength + newLength >= OUTPUT_BUFFER) { if (curLength + newLength >= DL_OUTPUT_BUFFER) {
/** /**
* if no one is consuming the data we have to drop it * if no one is consuming the data we have to drop it
* this happens in case of serial-over-USB, todo: find a better solution * this happens in case of serial-over-USB, todo: find a better solution

View File

@ -81,7 +81,7 @@ void append(Logging *logging, const char *text);
void scheduleLogging(Logging *logging); void scheduleLogging(Logging *logging);
void scheduleIntValue(Logging *logging, char *msg, int value); void scheduleIntValue(Logging *logging, const char *msg, int value);
/** /**
* this should only be invoked by the 'main' thread in order to keep the console safe * this should only be invoked by the 'main' thread in order to keep the console safe

View File

@ -22,6 +22,8 @@
#include <string.h> #include <string.h>
#include "rfiutil.h" #include "rfiutil.h"
/*
not used, not sure if we still need it. I guess we will remove it in 2015
int mylog10(int param) { int mylog10(int param) {
if (param < 10) if (param < 10)
return 0; return 0;
@ -39,49 +41,10 @@ int mylog10(int param) {
return 6; return 6;
if (param < 100000000) if (param < 100000000)
return 7; return 7;
#warning This would be better without recursion
return mylog10(param / 10) + 1; return mylog10(param / 10) + 1;
} }
*/
static char *ltoa_internal(char *p, long num, unsigned radix) {
int i;
char *q;
q = p + _MAX_FILLER;
do {
i = (int) (num % radix);
i += '0';
if (i > '9')
i += 'A' - '0' - 10;
*--q = i;
} while ((num /= radix) != 0);
i = (int) (p + _MAX_FILLER - q);
do
*p++ = *q++;
while (--i);
return p;
}
static char* itoa_signed(uint8_t *p, int num, unsigned radix) {
if (num < 0) {
*p++ = '-';
char *end = ltoa_internal(p, -num, radix);
*end = 0;
return end;
}
char *end = ltoa_internal(p, num, radix);
*end = 0;
return end;
}
/**
* Integer to string
*/
char* itoa10(uint8_t *p, int num) {
// todo: unit test
return itoa_signed(p, num, 10);
}
char hexChar(int v) { char hexChar(int v) {
v = v & 0xF; v = v & 0xF;
@ -103,11 +66,15 @@ int isLocked(void) {
return dbg_lock_cnt > 0; return dbg_lock_cnt > 0;
} }
void chVTSetAny(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par) { void chVTSetAny(virtual_timer_t *vtp, systime_t time, vtfunc_t vtfunc, void *par) {
if (isIsrContext()) { if (isIsrContext()) {
chSysLockFromIsr() chSysLockFromIsr()
; ;
/**
* todo: this could be simplified once we migrate to ChibiOS 3.0
* See http://www.chibios.org/dokuwiki/doku.php?id=chibios:howtos:porting_from_2_to_3
*/
if (chVTIsArmedI(vtp)) if (chVTIsArmedI(vtp))
chVTResetI(vtp); chVTResetI(vtp);

View File

@ -13,23 +13,15 @@
#include "histogram.h" #include "histogram.h"
#include "datalogging.h" #include "datalogging.h"
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define _MAX_FILLER 11
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
#endif /* __cplusplus */ #endif /* __cplusplus */
char* itoa10(uint8_t *p, int num);
char hexC(int v); char hexC(int v);
int isIsrContext(void); int isIsrContext(void);
int isLocked(void); int isLocked(void);
void chVTSetAny(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par); void chVTSetAny(virtual_timer_t *vtp, systime_t time, vtfunc_t vtfunc, void *par);
void printHistogram(Logging *logging, histogram_s *histogram); void printHistogram(Logging *logging, histogram_s *histogram);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -15,18 +15,7 @@
static Logging logger; static Logging logger;
static float _switchTimes[2]; static SimplePwm pwmTest[5];
// todo: extract helper for simple PWM?
static int pinStates[2];
static single_wave_s wave(pinStates);
static single_wave_s sr[1] = { wave };
static PwmConfig pwmTest[5] = { PwmConfig(_switchTimes, sr),
PwmConfig(_switchTimes, sr),
PwmConfig(_switchTimes, sr),
PwmConfig(_switchTimes, sr),
PwmConfig(_switchTimes, sr)};
extern board_configuration_s *boardConfiguration; extern board_configuration_s *boardConfiguration;
@ -34,20 +23,15 @@ static void startPwmTest(int freq) {
scheduleMsg(&logger, "running pwm test @%d", freq); scheduleMsg(&logger, "running pwm test @%d", freq);
// PD13, GPIO_NONE because pin is initialized elsewhere already // PD13, GPIO_NONE because pin is initialized elsewhere already
startSimplePwm(&pwmTest[0], "tester", GPIO_NONE, startSimplePwm(&pwmTest[0], "tester", LED_WARNING, 10, 0.5);
LED_CRANKING, 0.5, 10, FALSE); // currently this is PB9 by default - see boardConfiguration->injectionPins
// currently this is PB9 by default startSimplePwm(&pwmTest[1], "tester", INJECTOR_1_OUTPUT, freq / 1.3333333333, 0.5);
startSimplePwm(&pwmTest[1], "tester", boardConfiguration->injectionPins[0],
INJECTOR_1_OUTPUT, 0.5, freq / 1.3333333333, FALSE);
// currently this is PB8 by default // currently this is PB8 by default
startSimplePwm(&pwmTest[2], "tester", GPIO_NONE, startSimplePwm(&pwmTest[2], "tester", INJECTOR_2_OUTPUT, freq / 1000, 0.5);
INJECTOR_2_OUTPUT, 0.5, freq / 1000, FALSE);
// currently this is PE3 by default // currently this is PE3 by default
startSimplePwm(&pwmTest[3], "tester", GPIO_NONE, startSimplePwm(&pwmTest[3], "tester", INJECTOR_3_OUTPUT, freq, 0.5);
INJECTOR_3_OUTPUT, 0.5, freq, FALSE);
// currently this is PE5 by default // currently this is PE5 by default
startSimplePwm(&pwmTest[4], "tester", GPIO_NONE, startSimplePwm(&pwmTest[4], "tester", INJECTOR_4_OUTPUT, freq / 33.33333333333, 0.5);
INJECTOR_4_OUTPUT, 0.5, freq / 33.33333333333, FALSE);
} }
void initPwmTester(void) { void initPwmTester(void) {

View File

@ -18,25 +18,30 @@ extern engine_configuration_s *engineConfiguration;
static AccelEnrichmemnt instance; static AccelEnrichmemnt instance;
void AccelEnrichmemnt::updateDiffEnrichment(engine_configuration_s *engineConfiguration, float engineLoad) { void AccelEnrichmemnt::updateDiffEnrichment(engine_configuration_s *engineConfiguration, float engineLoad) {
for (int i = 1; i < 4; i++) { for (int i = 3; i == 1; i--)
engineLoadD[i] = engineLoadD[i - 1]; engineLoadD[i] = engineLoadD[i - 1];
}
engineLoadD[0] = engineLoad; engineLoadD[0] = engineLoad;
float Dcurr = engineLoadD[0] - engineLoadD[1];
float Dold = engineLoadD[2] - engineLoadD[3]; diffEnrichment = ((3 * (engineLoadD[0] - engineLoadD[1]) + (engineLoadD[2] - engineLoadD[3])) / 4)
diffEnrichment = ((3 * Dcurr + Dold) / 4) * (engineConfiguration->diffLoadEnrichmentCoef); * (engineConfiguration->diffLoadEnrichmentCoef);
} }
float AccelEnrichmemnt::getDiffEnrichment() { float AccelEnrichmemnt::getDiffEnrichment() {
return diffEnrichment; return diffEnrichment;
} }
AccelEnrichmemnt::AccelEnrichmemnt() {
for (int i = 0; i < 4; i++)
engineLoadD[i] = 0;
diffEnrichment = 0;
}
float getAccelEnrichment(void) { float getAccelEnrichment(void) {
return instance.getDiffEnrichment(); return instance.getDiffEnrichment();
} }
#if EFI_PROD_CODE #if EFI_PROD_CODE
static WORKING_AREA(aeThreadStack, UTILITY_THREAD_STACK_SIZE); static THD_WORKING_AREA(aeThreadStack, UTILITY_THREAD_STACK_SIZE);
static msg_t DiffEnrichmentThread(int param) { static msg_t DiffEnrichmentThread(int param) {
chRegSetThreadName("Diff Enrichment"); chRegSetThreadName("Diff Enrichment");
@ -54,3 +59,4 @@ void initDiffEnrichment(void) {
} }
#endif #endif

View File

@ -14,14 +14,18 @@
class AccelEnrichmemnt { class AccelEnrichmemnt {
public: public:
void updateDiffEnrichment(engine_configuration_s *engineConfiguration, float engineLoad); AccelEnrichmemnt();
void updateDiffEnrichment(engine_configuration_s *engineConfiguration,
float engineLoad);
float getDiffEnrichment(void); float getDiffEnrichment(void);
private: private:
float engineLoadD[5]; float engineLoadD[4];
float diffEnrichment; float diffEnrichment;
}; };
void initDiffEnrichment(void); void initDiffEnrichment(void);
float getAccelEnrichment(void); float getAccelEnrichment(void);
#endif /* ACC_ENRICHMENT_H_ */ #endif /* ACC_ENRICHMENT_H_ */

View File

@ -18,6 +18,7 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "main.h"
#include "advance_map.h" #include "advance_map.h"
#include "interpolation.h" #include "interpolation.h"
// that's for 'max' function // that's for 'max' function
@ -29,16 +30,13 @@
extern engine_configuration_s *engineConfiguration; extern engine_configuration_s *engineConfiguration;
//extern engine_configuration2_s *engineConfiguration2; //extern engine_configuration2_s *engineConfiguration2;
static float *timing_ptrs[AD_LOAD_COUNT]; static Map3D1616 advanceMap;
static int initialized = FALSE;
float getBaseAdvance(int rpm, float engineLoad) { float getBaseAdvance(int rpm, float engineLoad) {
chDbgAssert(initialized, "fuel map initialized", NULL); efiAssert(!cisnan(engineLoad), "invalid el", NAN);
efiAssert(!cisnan(engineLoad), "invalid el"); efiAssert(!cisnan(engineLoad), "invalid rpm", NAN);
efiAssert(!cisnan(engineLoad), "invalid rpm"); return advanceMap.getValue(engineLoad, engineConfiguration->ignitionLoadBins, rpm,
return interpolate3d(engineLoad, engineConfiguration->ignitionLoadBins, AD_LOAD_COUNT, rpm, engineConfiguration->ignitionRpmBins);
engineConfiguration->ignitionRpmBins,
AD_RPM_COUNT, timing_ptrs);
} }
float getAdvance(int rpm, float engineLoad) { float getAdvance(int rpm, float engineLoad) {
@ -52,7 +50,5 @@ float getAdvance(int rpm, float engineLoad) {
} }
void prepareTimingMap(void) { void prepareTimingMap(void) {
for (int k = 0; k < AD_LOAD_COUNT; k++) advanceMap.init(engineConfiguration->ignitionTable);
timing_ptrs[k] = engineConfiguration->ignitionTable[k];
initialized = TRUE;
} }

View File

@ -1,5 +1,5 @@
/* /*
* advance.h * @file advance_map.h
* *
* @date Mar 27, 2013 * @date Mar 27, 2013
* @author Andrey Belomutskiy, (c) 2012-2014 * @author Andrey Belomutskiy, (c) 2012-2014

View File

@ -1,16 +1,17 @@
CONTROLLERS_ALGO_SRC = $(PROJECT_DIR)/controllers/algo/map_adjuster.c \ CONTROLLERS_ALGO_SRC = $(PROJECT_DIR)/controllers/algo/map_adjuster.c \
$(PROJECT_DIR)/controllers/algo/advance_map.c \
$(PROJECT_DIR)/controllers/algo/signal_executor.c \ $(PROJECT_DIR)/controllers/algo/signal_executor.c \
$(PROJECT_DIR)/controllers/algo/malfunction_central.c \ $(PROJECT_DIR)/controllers/algo/malfunction_central.c \
$(PROJECT_DIR)/controllers/algo/event_registry.c \
$(PROJECT_DIR)/controllers/algo/idle_controller.c \ $(PROJECT_DIR)/controllers/algo/idle_controller.c \
$(PROJECT_DIR)/controllers/algo/wave_chart.c \ $(PROJECT_DIR)/controllers/algo/wave_chart.c \
$(PROJECT_DIR)/controllers/algo/nmea.c $(PROJECT_DIR)/controllers/algo/nmea.c
CONTROLLERS_ALGO_SRC_CPP = $(PROJECT_DIR)/controllers/algo/OutputSignalArray.cpp \ CONTROLLERS_ALGO_SRC_CPP = $(PROJECT_DIR)/controllers/algo/OutputSignalArray.cpp \
$(PROJECT_DIR)/controllers/algo/advance_map.cpp \
$(PROJECT_DIR)/controllers/algo/fuel_math.cpp \ $(PROJECT_DIR)/controllers/algo/fuel_math.cpp \
$(PROJECT_DIR)/controllers/algo/accel_enrichment.cpp \ $(PROJECT_DIR)/controllers/algo/accel_enrichment.cpp \
$(PROJECT_DIR)/controllers/algo/engine_configuration.cpp \ $(PROJECT_DIR)/controllers/algo/engine_configuration.cpp \
$(PROJECT_DIR)/controllers/algo/engine.cpp \
$(PROJECT_DIR)/controllers/algo/event_registry.cpp \
$(PROJECT_DIR)/controllers/algo/algo.cpp $(PROJECT_DIR)/controllers/algo/algo.cpp

View File

@ -13,8 +13,19 @@
#define EC2_H_ #define EC2_H_
#include "engine_configuration.h" #include "engine_configuration.h"
#include "event_registry.h"
#include "trigger_structure.h" #include "trigger_structure.h"
/**
* @brief Here we store information about which injector or spark should be fired when.
*/
typedef struct {
ActuatorEventList crankingInjectionEvents;
ActuatorEventList injectionEvents;
IgnitionEventList ignitionEvents[2];
} EventHandlerConfiguration;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
@ -42,15 +53,26 @@ public:
EventHandlerConfiguration engineEventConfiguration; EventHandlerConfiguration engineEventConfiguration;
int isInjectionEnabledFlag; int isInjectionEnabledFlag;
/**
* This coefficient translates ADC value directly into voltage adjusted according to
* voltage divider configuration.
*/
float adcToVoltageInputDividerCoefficient;
}; };
typedef struct {
engine_configuration_s *engineConfiguration;
engine_configuration2_s *engineConfiguration2;
} configuration_s;
void prepareOutputSignals(engine_configuration_s *engineConfiguration, void prepareOutputSignals(engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2); engine_configuration2_s *engineConfiguration2);
void initializeIgnitionActions(float baseAngle, engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2, float dwellMs, ActuatorEventList *list); void initializeIgnitionActions(float advance, float dwellAngle, engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2, IgnitionEventList *list);
void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *engineConfiguration2, ActuatorEventList *list, injection_mode_e mode); void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *engineConfiguration2, ActuatorEventList *list, injection_mode_e mode);
void registerActuatorEventExt(engine_configuration_s const *engineConfiguration, trigger_shape_s * s, ActuatorEventList *list, OutputSignal *actuator, float angleOffset); void registerActuatorEventExt(engine_configuration_s const *engineConfiguration, trigger_shape_s * s, ActuatorEvent *e, OutputSignal *actuator, float angleOffset);
void resetConfigurationExt(Logging * logger, engine_type_e engineType, void resetConfigurationExt(Logging * logger, engine_type_e engineType,
engine_configuration_s *engineConfiguration, engine_configuration_s *engineConfiguration,

View File

@ -0,0 +1,13 @@
/**
* @file engine.cpp
*
*
* This might be a http://en.wikipedia.org/wiki/God_object but that's best way I can
* express myself in C/C++. I am open for suggestions :)
*
* @date May 21, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/

View File

@ -0,0 +1,21 @@
/**
* @file engine.h
*
* @date May 21, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef ENGINE_H_
#define ENGINE_H_
#include "main.h"
#include "engine_configuration.h"
class RpmCalculator;
class Engine {
public:
RpmCalculator *rpmCalculator;
engine_configuration_s *engineConfiguration;
};
#endif /* ENGINE_H_ */

View File

@ -1,5 +1,5 @@
/** /**
* @file engine_controller.c * @file engine_configuration.cpp
* @brief Utility method related to the engine configuration data structure. * @brief Utility method related to the engine configuration data structure.
* *
* @date Nov 22, 2013 * @date Nov 22, 2013
@ -46,6 +46,7 @@
#include "MiniCooperR50.h" #include "MiniCooperR50.h"
#include "ford_escort_gt.h" #include "ford_escort_gt.h"
#include "citroenBerlingoTU3JP.h" #include "citroenBerlingoTU3JP.h"
#include "rover_v8.h"
static volatile int globalConfigurationVersion = 0; static volatile int globalConfigurationVersion = 0;
@ -77,6 +78,14 @@ void initBpsxD1Sensor(afr_sensor_s *sensor) {
sensor->value2 = 19; sensor->value2 = 19;
} }
void setWholeVEMap(engine_configuration_s *engineConfiguration, float value) {
// for (int l = 0; l < VE_LOAD_COUNT; l++) {
// for (int r = 0; r < VE_RPM_COUNT; r++) {
// engineConfiguration->veTable[l][r] = value;
// }
// }
}
void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value) { void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value) {
for (int l = 0; l < FUEL_LOAD_COUNT; l++) { for (int l = 0; l < FUEL_LOAD_COUNT; l++) {
for (int r = 0; r < FUEL_RPM_COUNT; r++) { for (int r = 0; r < FUEL_RPM_COUNT; r++) {
@ -85,6 +94,13 @@ void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value) {
} }
} }
void setTriggerSynchronizationGap(engine_configuration_s *engineConfiguration, float synchGap) {
engineConfiguration->triggerConfig.isSynchronizationNeeded = TRUE;
engineConfiguration->triggerConfig.syncRatioFrom = synchGap * 0.75;
engineConfiguration->triggerConfig.syncRatioTo = synchGap * 1.25;
}
/** /**
* @brief Global default engine configuration * @brief Global default engine configuration
* This method sets the default global engine configuration. These values are later overridden by engine-specific defaults * This method sets the default global engine configuration. These values are later overridden by engine-specific defaults
@ -192,20 +208,20 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->canReadEnabled = TRUE; engineConfiguration->canReadEnabled = TRUE;
engineConfiguration->canWriteEnabled = FALSE; engineConfiguration->canWriteEnabled = FALSE;
/** setOperationMode(engineConfiguration, FOUR_STROKE_CAM_SENSOR);
* 0.5 means primary position sensor is on a camshaft
*/
engineConfiguration->rpmMultiplier = 0.5;
engineConfiguration->cylindersCount = 4; engineConfiguration->cylindersCount = 4;
engineConfiguration->displacement = 2;
/**
* By the way http://users.erols.com/srweiss/tableifc.htm has a LOT of data
*/
engineConfiguration->injectorFlow = 200;
engineConfiguration->displayMode = DM_HD44780; engineConfiguration->displayMode = DM_HD44780;
engineConfiguration->logFormat = LF_NATIVE; engineConfiguration->logFormat = LF_NATIVE;
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL; engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
engineConfiguration->triggerConfig.syncRatioFrom = 1.5; setTriggerSynchronizationGap(engineConfiguration, 2);
engineConfiguration->triggerConfig.syncRatioTo = 3;
engineConfiguration->triggerConfig.isSynchronizationNeeded = TRUE;
engineConfiguration->triggerConfig.useRiseEdge = TRUE; engineConfiguration->triggerConfig.useRiseEdge = TRUE;
engineConfiguration->HD44780width = 16; engineConfiguration->HD44780width = 16;
@ -291,6 +307,13 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->primaryLogicAnalyzerPin = GPIOA_8; boardConfiguration->primaryLogicAnalyzerPin = GPIOA_8;
boardConfiguration->secondaryLogicAnalyzerPin = GPIOE_7; boardConfiguration->secondaryLogicAnalyzerPin = GPIOE_7;
boardConfiguration->idleThreadPeriod = 100;
boardConfiguration->consoleLoopPeriod = 200;
boardConfiguration->lcdThreadPeriod = 300;
boardConfiguration->tunerStudioThreadPeriod = 300;
boardConfiguration->generalPeriodicThreadPeriod = 200;
boardConfiguration->tunerStudioSerialSpeed = 38400;
} }
void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfiguration2) { void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfiguration2) {
@ -363,6 +386,10 @@ void resetConfigurationExt(Logging * logger, engine_type_e engineType, engine_co
case CITROEN_TU3JP: case CITROEN_TU3JP:
setCitroenBerlingoTU3JPConfiguration(engineConfiguration, boardConfiguration); setCitroenBerlingoTU3JPConfiguration(engineConfiguration, boardConfiguration);
break; break;
case ROVER_V8:
setRoverv8(engineConfiguration, boardConfiguration);
break;
default: default:
firmwareError("Unexpected engine type: %d", engineType); firmwareError("Unexpected engine type: %d", engineType);
@ -398,6 +425,22 @@ void applyNonPersistentConfiguration(Logging * logger, engine_configuration_s *e
prepareOutputSignals(engineConfiguration, engineConfiguration2); prepareOutputSignals(engineConfiguration, engineConfiguration2);
// todo: looks like this is here only for unit tests. todo: remove // todo: looks like this is here only for unit tests. todo: remove
initializeIgnitionActions(0, engineConfiguration, engineConfiguration2, 0, &engineConfiguration2->engineEventConfiguration.ignitionEvents[0]); initializeIgnitionActions(0, 0, engineConfiguration, engineConfiguration2,
&engineConfiguration2->engineEventConfiguration.ignitionEvents[0]);
}
void setOperationMode(engine_configuration_s *engineConfiguration, operation_mode_e mode) {
if (mode == FOUR_STROKE_CAM_SENSOR) {
engineConfiguration->rpmMultiplier = 0.5;
} else if (mode == FOUR_STROKE_CRANK_SENSOR) {
engineConfiguration->rpmMultiplier = 1;
}
}
operation_mode_e getOperationMode( engine_configuration_s const *engineConfiguration) {
if(engineConfiguration->rpmMultiplier == 1)
return FOUR_STROKE_CRANK_SENSOR;
return FOUR_STROKE_CAM_SENSOR;
} }

View File

@ -13,7 +13,6 @@
#include "crc.h" #include "crc.h"
#include "sensor_types.h" #include "sensor_types.h"
#include "can_header.h" #include "can_header.h"
#include "event_registry.h"
#include "rusefi_enums.h" #include "rusefi_enums.h"
typedef struct { typedef struct {
@ -29,17 +28,12 @@ typedef struct {
short int crankingRpm; short int crankingRpm;
} cranking_parameters_s; } cranking_parameters_s;
/**
* @brief Here we store information about which injector or spark should be fired when.
*/
typedef struct {
ActuatorEventList crankingInjectionEvents;
ActuatorEventList injectionEvents;
ActuatorEventList ignitionEvents[2];
} EventHandlerConfiguration;
#define FUEL_RPM_COUNT 16 #define FUEL_RPM_COUNT 16
#define FUEL_LOAD_COUNT 16 #define FUEL_LOAD_COUNT 16
#define VE_RPM_COUNT 16
#define VE_LOAD_COUNT 16
#define AFR_RPM_COUNT 16
#define AFR_LOAD_COUNT 16
#define CLT_CURVE_SIZE 16 #define CLT_CURVE_SIZE 16
#define IAT_CURVE_SIZE 16 #define IAT_CURVE_SIZE 16
@ -115,6 +109,14 @@ typedef struct {
*/ */
typedef struct { typedef struct {
float injectorLag; // size 4, offset 0 float injectorLag; // size 4, offset 0
/**
* cc/min, cubic centimeter per minute
*
* By the way, g/s = 0.125997881 * (lb/hr)
* g/s = 0.125997881 * (cc/min)/10.5
* g/s = 0.0119997981 * cc/min
*
*/
float injectorFlow; // size 4, offset 4 float injectorFlow; // size 4, offset 4
float battInjectorLagCorrBins[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 8 float battInjectorLagCorrBins[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 8
float battInjectorLagCorr[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 40 float battInjectorLagCorr[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 40
@ -145,9 +147,8 @@ typedef struct {
float sparkDwellBins[DWELL_COUNT]; // offset 580 float sparkDwellBins[DWELL_COUNT]; // offset 580
float sparkDwell[DWELL_COUNT]; float sparkDwell[DWELL_COUNT];
float ignitionTable[IGN_LOAD_COUNT][IGN_RPM_COUNT]; float ignitionLoadBins[IGN_LOAD_COUNT];
float ignitionLoadBins[IGN_LOAD_COUNT]; // offset 3450 float ignitionRpmBins[IGN_RPM_COUNT];
float ignitionRpmBins[IGN_RPM_COUNT]; // offset 3542
/** /**
* this value could be used to offset the whole ignition timing table by a constant * this value could be used to offset the whole ignition timing table by a constant
@ -170,12 +171,16 @@ typedef struct {
// WARNING: by default, our small enums are ONE BYTE. but if the are surrounded by non-enums - alignments do the trick // WARNING: by default, our small enums are ONE BYTE. but if the are surrounded by non-enums - alignments do the trick
engine_type_e engineType; engine_type_e engineType;
float fuelTable[FUEL_LOAD_COUNT][FUEL_RPM_COUNT]; // size 1024, offset 1816 float fuelLoadBins[FUEL_LOAD_COUNT]; //
float fuelLoadBins[FUEL_LOAD_COUNT]; // offset 2840
// RPM is float and not integer in order to use unified methods for interpolation // RPM is float and not integer in order to use unified methods for interpolation
float fuelRpmBins[FUEL_RPM_COUNT]; // offset 3542 float fuelRpmBins[FUEL_RPM_COUNT]; //
int unused[3]; /**
* Engine displacement, in liters
* see also cylindersCount
*/
float displacement;
int unused[2];
injection_mode_e crankingInjectionMode; injection_mode_e crankingInjectionMode;
injection_mode_e injectionMode; injection_mode_e injectionMode;
@ -270,8 +275,24 @@ typedef struct {
float diffLoadEnrichmentCoef; float diffLoadEnrichmentCoef;
air_pressure_sensor_config_s baroSensor; air_pressure_sensor_config_s baroSensor;
float veLoadBins[VE_LOAD_COUNT];
float veRpmBins[VE_RPM_COUNT];
float afrLoadBins[AFR_LOAD_COUNT];
float afrRpmBins[AFR_RPM_COUNT];
// the large tables are always in the end - that's related to TunerStudio paging implementation
float fuelTable[FUEL_LOAD_COUNT][FUEL_RPM_COUNT]; // size 1024
float ignitionTable[IGN_LOAD_COUNT][IGN_RPM_COUNT]; // size 1024
float veTable[VE_LOAD_COUNT][VE_RPM_COUNT]; // size 1024
float afrTable[AFR_LOAD_COUNT][AFR_RPM_COUNT]; // size 1024
} engine_configuration_s; } engine_configuration_s;
void setOperationMode(engine_configuration_s *engineConfiguration, operation_mode_e mode);
operation_mode_e getOperationMode(engine_configuration_s const *engineConfiguration);
#define HW_MAX_ADC_INDEX 16 #define HW_MAX_ADC_INDEX 16
typedef struct { typedef struct {
@ -326,6 +347,14 @@ typedef struct {
brain_pin_e primaryLogicAnalyzerPin; brain_pin_e primaryLogicAnalyzerPin;
brain_pin_e secondaryLogicAnalyzerPin; brain_pin_e secondaryLogicAnalyzerPin;
int idleThreadPeriod;
int consoleLoopPeriod;
int lcdThreadPeriod;
int tunerStudioThreadPeriod;
int generalPeriodicThreadPeriod;
int tunerStudioSerialSpeed;
} board_configuration_s; } board_configuration_s;
typedef struct { typedef struct {
@ -350,6 +379,7 @@ void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value);
void setConstantDwell(engine_configuration_s *engineConfiguration, float dwellMs); void setConstantDwell(engine_configuration_s *engineConfiguration, float dwellMs);
void printFloatArray(const char *prefix, float array[], int size); void printFloatArray(const char *prefix, float array[], int size);
void setTriggerSynchronizationGap(engine_configuration_s *engineConfiguration, float synchGap);
void incrementGlobalConfigurationVersion(void); void incrementGlobalConfigurationVersion(void);
int getGlobalConfigurationVersion(void); int getGlobalConfigurationVersion(void);

View File

@ -28,11 +28,17 @@ int warning(obd_code_e code, const char *fmt, ...);
* todo: better method name? * todo: better method name?
*/ */
void firmwareError(const char *fmt, ...); void firmwareError(const char *fmt, ...);
bool_t hasFirmwareError(void); bool hasFirmwareError(void);
bool_t hasFatalError(void); /**
void fatal3(char *msg, char *file, int line); * declared as a macro so that this code does not use stack
#define fatal(x) (fatal3(x, __FILE__, __LINE__)); * so that it would not crash the error handler in case of stack issues
*/
#if CH_DBG_SYSTEM_STATE_CHECK
#define hasFatalError() (dbg_panic_msg != NULL)
#else
#define hasFatalError() (FALSE)
#endif
void chDbgPanic3(const char *msg, const char * file, int line); void chDbgPanic3(const char *msg, const char * file, int line);
@ -45,7 +51,10 @@ int getRusEfiVersion(void);
* @deprecated Global panic is inconvenient because it's hard to deliver the error message while whole instance * @deprecated Global panic is inconvenient because it's hard to deliver the error message while whole instance
* is stopped. Please use firmwareWarning() instead * is stopped. Please use firmwareWarning() instead
*/ */
#define efiAssert(x, y) chDbgAssert(x, y, NULL) #define efiAssert(condition, message, result) { if (!(condition)) { firmwareError(message); return result; } }
#define efiAssertVoid(condition, message) { if (!(condition)) { firmwareError(message); return; } }
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,61 +0,0 @@
/**
* @file event_registry.c
* @brief This data structure knows when to do what
*
* @date Nov 27, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*
*
* This file is part of rusEfi - see http://rusefi.com
*
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "event_registry.h"
#include "main.h"
#include "engine_math.h"
extern engine_configuration_s *engineConfiguration;
//extern engine_configuration2_s *engineConfiguration2;
void resetEventList(ActuatorEventList *list) {
list->size = 0;
}
static void copyActuatorEvent(ActuatorEvent *source, ActuatorEvent*target) {
target->eventIndex = source->eventIndex;
target->actuator = source->actuator;
target->angleOffset = source->angleOffset;
}
void registerActuatorEvent(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset) {
if (list->size == MAX_EVENT_COUNT) {
fatal("registerActuatorEvent() too many events");
return;
}
ActuatorEvent *e = &list->events[list->size++];
e->eventIndex = eventIndex;
e->actuator = actuator;
e->angleOffset = angleOffset;
}
void findEvents(int eventIndex, ActuatorEventList *source, ActuatorEventList *target) {
resetEventList(target);
// todo: implement something faster
for (int i = 0; i < source->size; i++) {
ActuatorEvent *s = &source->events[i];
if (s->eventIndex != eventIndex)
continue;
// todo: migrate to pointers instead of copying an object?
copyActuatorEvent(s, &target->events[target->size++]);
}
}

View File

@ -0,0 +1,34 @@
/**
* @file event_registry.cpp
* @brief This data structure knows when to do what
*
* @date Nov 27, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*
*
* This file is part of rusEfi - see http://rusefi.com
*
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "event_registry.h"
#include "main.h"
#include "engine_math.h"
void registerActuatorEvent(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset) {
ActuatorEvent *e = list->getNextActuatorEvent();
if (e == NULL)
return; // error already reported
e->position.eventIndex = eventIndex;
e->actuator = actuator;
e->position.angleOffset = angleOffset;
}

View File

@ -13,24 +13,60 @@
#define MAX_EVENT_COUNT 40 #define MAX_EVENT_COUNT 40
/**
* This structure defines an angle position within the trigger
*/
typedef struct { typedef struct {
/**
* That's trigger event index
*/
int eventIndex; int eventIndex;
OutputSignal *actuator; float eventAngle;
/**
* Angle offset from the trigger event
*/
float angleOffset; float angleOffset;
} event_trigger_position_s;
typedef struct {
event_trigger_position_s position;
OutputSignal *actuator;
scheduling_s signalTimer;
} ActuatorEvent; } ActuatorEvent;
typedef struct { typedef struct IgnitionEvent_struct IgnitionEvent;
struct IgnitionEvent_struct {
ActuatorEvent actuator;
float advance;
event_trigger_position_s sparkPosition;
IgnitionEvent *next;
char *name;
};
template <class Type, int Dimention>
class ArrayList {
public:
int size; int size;
ActuatorEvent events[MAX_EVENT_COUNT]; Type events[Dimention];
} ActuatorEventList; void resetEventList(void);
Type *getNextActuatorEvent(void);
};
#ifdef __cplusplus template <class Type, int Dimention>
extern "C" void ArrayList< Type, Dimention>::resetEventList(void) {
{ size = 0;
#endif /* __cplusplus */ }
template <class Type, int Dimention>
Type * ArrayList< Type, Dimention>::getNextActuatorEvent(void) {
efiAssert(size < Dimention, "registerActuatorEvent() too many events", NULL);
return &events[size++];
}
void resetEventList(ActuatorEventList *list); typedef ArrayList<ActuatorEvent, MAX_EVENT_COUNT> ActuatorEventList;
typedef ArrayList<IgnitionEvent, MAX_EVENT_COUNT> IgnitionEventList;
/** /**
* this is an intermediate implementation of flexible event handling. * this is an intermediate implementation of flexible event handling.
@ -42,11 +78,4 @@ void resetEventList(ActuatorEventList *list);
*/ */
void registerActuatorEvent(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset); void registerActuatorEvent(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset);
void findEvents(int eventIndex, ActuatorEventList *source, ActuatorEventList *target);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* EVENT_REGISTRY_H_ */ #endif /* EVENT_REGISTRY_H_ */

View File

@ -40,19 +40,17 @@
#include "accel_enrichment.h" #include "accel_enrichment.h"
#endif /* EFI_ACCEL_ENRICHMENT */ #endif /* EFI_ACCEL_ENRICHMENT */
static float *fuel_ptrs[FUEL_LOAD_COUNT];
static int initialized = FALSE;
extern engine_configuration_s *engineConfiguration; extern engine_configuration_s *engineConfiguration;
static Map3D1616 fuelMap;
/** /**
* @brief Initialize fuel map data structure * @brief Initialize fuel map data structure
* @note this method has nothing to do with fuel map VALUES - it's job * @note this method has nothing to do with fuel map VALUES - it's job
* is to prepare the fuel map data structure for 3d interpolation * is to prepare the fuel map data structure for 3d interpolation
*/ */
void prepareFuelMap(void) { void prepareFuelMap(void) {
for (int k = 0; k < FUEL_LOAD_COUNT; k++) fuelMap.init(engineConfiguration->fuelTable);
fuel_ptrs[k] = engineConfiguration->fuelTable[k];
initialized = TRUE;
} }
/** /**
@ -86,11 +84,9 @@ float getInjectorLag(float vBatt) {
} }
float getBaseFuel(int rpm, float engineLoad) { float getBaseFuel(int rpm, float engineLoad) {
chDbgCheck(initialized, "fuel map initialized"); efiAssert(!cisnan(engineLoad), "invalid el", NAN);
efiAssert(!cisnan(engineLoad), "invalid el"); return fuelMap.getValue(engineLoad, engineConfiguration->fuelLoadBins, rpm,
efiAssert(!cisnan(engineLoad), "invalid rpm"); engineConfiguration->fuelRpmBins);
return interpolate3d(engineLoad, engineConfiguration->fuelLoadBins, FUEL_LOAD_COUNT, rpm,
engineConfiguration->fuelRpmBins, FUEL_RPM_COUNT, fuel_ptrs);
} }
float getCrankingFuel(void) { float getCrankingFuel(void) {
@ -157,7 +153,7 @@ inline static int getElectricalValue1(pin_output_mode_e mode) {
// todo: this method is here for unit test visibility. todo: move to a bette place! // todo: this method is here for unit test visibility. todo: move to a bette place!
int getElectricalValue(int logicalValue, pin_output_mode_e mode) { int getElectricalValue(int logicalValue, pin_output_mode_e mode) {
chDbgCheck(mode <= OM_OPENDRAIN_INVERTED, "invalid pin_output_mode_e"); efiAssert(mode <= OM_OPENDRAIN_INVERTED, "invalid pin_output_mode_e", -1);
return logicalValue ? getElectricalValue1(mode) : getElectricalValue0(mode); return logicalValue ? getElectricalValue1(mode) : getElectricalValue0(mode);
} }

View File

@ -13,7 +13,7 @@
#define GPIO_NULL NULL #define GPIO_NULL NULL
typedef enum { typedef enum {
LED_CRANKING, // Orange on-board LED LED_WARNING, // Orange on-board LED
LED_RUNNING, // Green on-board LED LED_RUNNING, // Green on-board LED
LED_ERROR, // Red on-board LED LED_ERROR, // Red on-board LED
LED_COMMUNICATION_1, // Blue on-board LED LED_COMMUNICATION_1, // Blue on-board LED

View File

@ -15,14 +15,31 @@
#define MAX_INJECTOR_COUNT 12 #define MAX_INJECTOR_COUNT 12
#define MAX_IGNITER_COUNT 4 #define MAX_IGNITER_COUNT 4
#ifdef __cplusplus
#include "engine_configuration.h"
#include "ec2.h"
#include "event_registry.h"
class MainTriggerCallback {
public:
// MainTriggerCallback();
void init(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
engine_configuration_s *engineConfiguration;
engine_configuration2_s *engineConfiguration2;
};
void initMainEventListener(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
void onTriggerEvent(trigger_event_e ckpSignalType, int eventIndex, MainTriggerCallback *mainTriggerCallback);
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
#endif /* __cplusplus */ #endif /* __cplusplus */
#include "event_registry.h"
void initMainEventListener(void);
void showMainHistogram(void); void showMainHistogram(void);
void onEveryMillisecondTimerSignal(void); void onEveryMillisecondTimerSignal(void);
int isIgnitionTimingError(void); int isIgnitionTimingError(void);

View File

@ -55,6 +55,6 @@ void getErrorCodes(error_codes_set_s * copy) {
copy->error_codes[i] = error_codes_set.error_codes[i]; copy->error_codes[i] = error_codes_set.error_codes[i];
} }
bool_t hasErrorCodes(void) { bool hasErrorCodes(void) {
return error_codes_set.count > 0; return error_codes_set.count > 0;
} }

View File

@ -48,11 +48,10 @@ void setError(int flag, obd_code_e errorCode);
*/ */
void getErrorCodes(error_codes_set_s * buffer); void getErrorCodes(error_codes_set_s * buffer);
bool_t hasErrorCodes(void); bool hasErrorCodes(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif /* MALFUNCTION_CENTRAL_H_ */ #endif /* MALFUNCTION_CENTRAL_H_ */

View File

@ -97,7 +97,7 @@ typedef enum {
SHAFT_PRIMARY_DOWN = 1, SHAFT_PRIMARY_DOWN = 1,
SHAFT_SECONDARY_UP = 2, SHAFT_SECONDARY_UP = 2,
SHAFT_SECONDARY_DOWN = 3, SHAFT_SECONDARY_DOWN = 3,
} ShaftEvents; } trigger_event_e;
/** /**
* This enum is used to select your desired Engine Load calculation algorithm * This enum is used to select your desired Engine Load calculation algorithm
@ -179,6 +179,14 @@ typedef enum {
Internal_ForceMyEnumIntSize_firing_order = ENUM_SIZE_HACK, Internal_ForceMyEnumIntSize_firing_order = ENUM_SIZE_HACK,
} firing_order_e; } firing_order_e;
// todo: better enum name
typedef enum {
FOUR_STROKE_CRANK_SENSOR = 0,
FOUR_STROKE_CAM_SENSOR = 1,
Internal_ForceMyEnumIntSize_operation_mode_e = ENUM_SIZE_HACK,
} operation_mode_e;
/** /**
* @brief Ignition Mode * @brief Ignition Mode
*/ */

View File

@ -56,12 +56,10 @@ void initOutputSignal(OutputSignal *signal, io_pin_e ioPin) {
} }
void initOutputSignalBase(OutputSignal *signal) { void initOutputSignalBase(OutputSignal *signal) {
signal->status = IDLE;
// signal->last_scheduling_time = 0;
signal->initialized = TRUE; signal->initialized = TRUE;
} }
static void turnHigh(OutputSignal *signal) { void turnPinHigh(OutputSignal *signal) {
#if EFI_DEFAILED_LOGGING #if EFI_DEFAILED_LOGGING
// signal->hi_time = hTimeNow(); // signal->hi_time = hTimeNow();
#endif /* EFI_DEFAILED_LOGGING */ #endif /* EFI_DEFAILED_LOGGING */
@ -85,7 +83,7 @@ static void turnHigh(OutputSignal *signal) {
#endif /* EFI_WAVE_ANALYZER */ #endif /* EFI_WAVE_ANALYZER */
} }
static void turnLow(OutputSignal *signal) { void turnPinLow(OutputSignal *signal) {
// turn off the output // turn off the output
// todo: this XOR should go inside the setOutputPinValue method // todo: this XOR should go inside the setOutputPinValue method
setOutputPinValue(signal->io_pin, FALSE); setOutputPinValue(signal->io_pin, FALSE);
@ -126,8 +124,8 @@ void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs) {
scheduling_s * sUp = &signal->signalTimerUp[index]; scheduling_s * sUp = &signal->signalTimerUp[index];
scheduling_s * sDown = &signal->signalTimerDown[index]; scheduling_s * sDown = &signal->signalTimerDown[index];
scheduleTask(sUp, (int)MS2US(delayMs), (schfunc_t) &turnHigh, (void *) signal); scheduleTask(sUp, (int)MS2US(delayMs), (schfunc_t) &turnPinHigh, (void *) signal);
scheduleTask(sDown, (int)MS2US(delayMs + durationMs), (schfunc_t) &turnLow, (void*) signal); scheduleTask(sDown, (int)MS2US(delayMs + durationMs), (schfunc_t) &turnPinLow, (void*) signal);
// signal->last_scheduling_time = now; // signal->last_scheduling_time = now;
} }
@ -137,7 +135,7 @@ void scheduleOutputBase(OutputSignal *signal, float delayMs, float durationMs) {
* it's better to check for the exact 'TRUE' value since otherwise * it's better to check for the exact 'TRUE' value since otherwise
* we would accept any memory garbage * we would accept any memory garbage
*/ */
chDbgCheck(signal->initialized == TRUE, "Signal not initialized"); efiAssertVoid(signal->initialized == TRUE, "Signal not initialized");
// signal->offset = offset; // signal->offset = offset;
// signal->duration = duration; // signal->duration = duration;
} }

View File

@ -23,10 +23,6 @@
#include "signal_executor_sleep.h" #include "signal_executor_sleep.h"
#endif /* EFI_SIGNAL_EXECUTOR_SLEEP */ #endif /* EFI_SIGNAL_EXECUTOR_SLEEP */
typedef enum {
IDLE = 0, ACTIVE
} executor_status_t;
/** /**
* @brief Asynchronous output signal data structure * @brief Asynchronous output signal data structure
*/ */
@ -40,19 +36,14 @@ struct OutputSignal_struct {
int initialized; int initialized;
/** /**
* We are alternating instances so that events which extend into next revolution are not overriden while * We are alternating instances so that events which extend into next revolution are not reused while
* scheduling next revolution events * scheduling next revolution events
*/ */
scheduling_s signalTimerUp[2]; scheduling_s signalTimerUp[2];
scheduling_s signalTimerDown[2]; scheduling_s signalTimerDown[2];
executor_status_t status; scheduling_s triggerEvent;
float angleOffsetParam;
#if EFI_SIGNAL_EXECUTOR_HW_TIMER
// todo
#endif
// OutputSignal *next;
}; };
#ifdef __cplusplus #ifdef __cplusplus
@ -65,6 +56,9 @@ void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs);
void initOutputSignalBase(OutputSignal *signal); void initOutputSignalBase(OutputSignal *signal);
void scheduleOutputBase(OutputSignal *signal, float delayMs, float durationMs); void scheduleOutputBase(OutputSignal *signal, float delayMs, float durationMs);
void turnPinHigh(OutputSignal *signal);
void turnPinLow(OutputSignal *signal);
void initSignalExecutor(void); void initSignalExecutor(void);
void initSignalExecutorImpl(void); void initSignalExecutorImpl(void);
void scheduleByAngle(scheduling_s *timer, float angle, schfunc_t callback, void *param); void scheduleByAngle(scheduling_s *timer, float angle, schfunc_t callback, void *param);

View File

@ -40,9 +40,11 @@
*/ */
#if EFI_PROD_CODE #if EFI_PROD_CODE
static volatile int chartSize = 100; static volatile int chartSize = 100;
#define WAVE_LOGGING_SIZE 5000
#else #else
// need more events for automated test // need more events for automated test
static volatile int chartSize = 200; static volatile int chartSize = 400;
#define WAVE_LOGGING_SIZE 35000
#endif #endif
static int isChartActive = TRUE; static int isChartActive = TRUE;
@ -65,11 +67,7 @@ void resetWaveChart(WaveChart *chart) {
appendPrintf(&chart->logging, "wave_chart%s", DELIMETER); appendPrintf(&chart->logging, "wave_chart%s", DELIMETER);
} }
#if defined __GNUC__ static char WAVE_LOGGING_BUFFER[WAVE_LOGGING_SIZE] CCM_OPTIONAL;
static char WAVE_LOGGING_BUFFER[5000] __attribute__((section(".ccm")));
#else
static char WAVE_LOGGING_BUFFER[5000];
#endif
static void printStatus(void) { static void printStatus(void) {
scheduleIntValue(&logger, "chart", isChartActive); scheduleIntValue(&logger, "chart", isChartActive);
@ -113,13 +111,13 @@ void publishChart(WaveChart *chart) {
* @brief Register a change in sniffed signal * @brief Register a change in sniffed signal
*/ */
void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, const char * msg2) { void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, const char * msg2) {
chDbgCheck(chart->isInitialized, "chart not initialized"); efiAssertVoid(chart->isInitialized, "chart not initialized");
#if DEBUG_WAVE #if DEBUG_WAVE
scheduleSimpleMsg(&debugLogging, "current", chart->counter); scheduleSimpleMsg(&debugLogging, "current", chart->counter);
#endif #endif
if (isWaveChartFull(chart)) if (isWaveChartFull(chart))
return; return;
bool_t alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer bool alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer
appendPrintf(&chart->logging, "%s%s%s%s", name, CHART_DELIMETER, msg, CHART_DELIMETER); appendPrintf(&chart->logging, "%s%s%s%s", name, CHART_DELIMETER, msg, CHART_DELIMETER);
int time100 = getTimeNowUs() / 10; int time100 = getTimeNowUs() / 10;
appendPrintf(&chart->logging, "%d%s%s", time100, msg2, CHART_DELIMETER); appendPrintf(&chart->logging, "%d%s%s", time100, msg2, CHART_DELIMETER);

View File

@ -24,7 +24,7 @@ extern board_configuration_s *boardConfiguration;
static PwmConfig alternatorControl; static PwmConfig alternatorControl;
static WORKING_AREA(ivThreadStack, UTILITY_THREAD_STACK_SIZE); static THD_WORKING_AREA(ivThreadStack, UTILITY_THREAD_STACK_SIZE);
static msg_t AltCtrlThread(int param) { static msg_t AltCtrlThread(int param) {
chRegSetThreadName("AlternatorController"); chRegSetThreadName("AlternatorController");

View File

@ -2,12 +2,12 @@
CONTROLLERSSRC = \ CONTROLLERSSRC = \
controllers/ignition_central.c \ controllers/ignition_central.c \
$(PROJECT_DIR)/controllers/malfunction_indicator.c \ $(PROJECT_DIR)/controllers/malfunction_indicator.c \
$(PROJECT_DIR)/controllers/error_handling.c \ $(PROJECT_DIR)/controllers/error_handling.c
controllers/map_averaging.c \
controllers/map_multiplier_thread.c
CONTROLLERS_SRC_CPP = $(PROJECT_DIR)/controllers/settings.cpp \ CONTROLLERS_SRC_CPP = $(PROJECT_DIR)/controllers/settings.cpp \
controllers/electronic_throttle.cpp \ controllers/electronic_throttle.cpp \
controllers/map_averaging.cpp \
controllers/map_multiplier_thread.cpp \
controllers/flash_main.cpp \ controllers/flash_main.cpp \
controllers/injector_central.cpp \ controllers/injector_central.cpp \
controllers/idle_thread.cpp \ controllers/idle_thread.cpp \

View File

@ -7,6 +7,7 @@
#include "main.h" #include "main.h"
#include "EfiWave.h" #include "EfiWave.h"
#include "trigger_structure.h"
single_wave_s::single_wave_s() { single_wave_s::single_wave_s() {
init(NULL); init(NULL);
@ -20,16 +21,40 @@ void single_wave_s::init(int *pinStates) {
this->pinStates = pinStates; this->pinStates = pinStates;
} }
multi_wave_s::multi_wave_s() {
}
multi_wave_s::multi_wave_s(float *switchTimes, single_wave_s *waves) { multi_wave_s::multi_wave_s(float *switchTimes, single_wave_s *waves) {
init(switchTimes, waves);
}
void multi_wave_s::init(float *switchTimes, single_wave_s *waves) {
this->switchTimes = switchTimes; this->switchTimes = switchTimes;
this->waves = waves; this->waves = waves;
} }
void multi_wave_s::reset(void) { void multi_wave_s::reset(void) {
phaseCount = 0;
waveCount = 0; waveCount = 0;
} }
float multi_wave_s::getAngle(int index, engine_configuration_s const *engineConfiguration, trigger_shape_s * s) const {
if (getOperationMode(engineConfiguration) == FOUR_STROKE_CAM_SENSOR)
return getSwitchTime(index) * 720.0;
/**
* FOUR_STROKE_CRANK_SENSOR magic:
* We have two crank shaft revolutions for each engine cycle
* See also trigger_central.cpp
* See also getEngineCycleEventCount()
*/
int triggerEventCounter = s->getSize();
if (index < triggerEventCounter) {
return getSwitchTime(index) * 360.0;
} else {
return 360 + getSwitchTime(index - triggerEventCounter) * 360.0;
}
}
float multi_wave_s::getSwitchTime(int index) const { float multi_wave_s::getSwitchTime(int index) const {
return switchTimes[index]; return switchTimes[index];
} }

View File

@ -7,7 +7,9 @@
#ifndef EFI_WAVE_H_ #ifndef EFI_WAVE_H_
#define EFI_WAVE_H_ #define EFI_WAVE_H_
#define PWM_PHASE_MAX_COUNT 150 #include "engine_configuration.h"
#define PWM_PHASE_MAX_COUNT 250
#define PWM_PHASE_MAX_WAVE_PER_PWM 2 #define PWM_PHASE_MAX_WAVE_PER_PWM 2
/** /**
@ -21,18 +23,19 @@ public:
int *pinStates; int *pinStates;
}; };
class trigger_shape_s;
class multi_wave_s { class multi_wave_s {
public: public:
multi_wave_s();
multi_wave_s(float *st, single_wave_s *waves); multi_wave_s(float *st, single_wave_s *waves);
void init(float *st, single_wave_s *waves);
void reset(void); void reset(void);
float getSwitchTime(int phaseIndex) const; float getSwitchTime(int phaseIndex) const;
float getAngle(int phaseIndex, engine_configuration_s const *engineConfiguration, trigger_shape_s * s) const;
void setSwitchTime(int phaseIndex, float value); void setSwitchTime(int phaseIndex, float value);
void checkSwitchTimes(int size); void checkSwitchTimes(int size);
int getChannelState(int channelIndex, int phaseIndex) const; int getChannelState(int channelIndex, int phaseIndex) const;
/**
* Number of events in the cycle
*/
int phaseCount;
/** /**
* Number of signal wires * Number of signal wires
*/ */

View File

@ -1,6 +1,6 @@
CONTROLLERS_CORE_SRC = $(PROJECT_DIR)/controllers/core/interpolation.c \ CONTROLLERS_CORE_SRC = $(PROJECT_DIR)/controllers/core/avg_values.c
$(PROJECT_DIR)/controllers/core/avg_values.c
CONTROLLERS_CORE_SRC_CPP = $(PROJECT_DIR)/controllers/core/EfiWave.cpp CONTROLLERS_CORE_SRC_CPP = $(PROJECT_DIR)/controllers/core/EfiWave.cpp \
$(PROJECT_DIR)/controllers/core/interpolation.cpp \

View File

@ -1,5 +1,5 @@
/** /**
* @file interpolation.c * @file interpolation.cpp
* @brief Linear interpolation algorithms * @brief Linear interpolation algorithms
* *
* @date Oct 17, 2013 * @date Oct 17, 2013
@ -14,12 +14,30 @@
#include "main.h" #include "main.h"
#include "interpolation.h" #include "interpolation.h"
//#include "engine_math.h"
#define INTERPOLATION_A(x1, y1, x2, y2) ((y1 - y2) / (x1 - x2)) #define INTERPOLATION_A(x1, y1, x2, y2) ((y1 - y2) / (x1 - x2))
int needInterpolationLogging = TRUE; int needInterpolationLogging = TRUE;
FastInterpolation::FastInterpolation(float x1, float y1, float x2, float y2) {
init(x1, y1, x2, y2);
}
void FastInterpolation::init(float x1, float y1, float x2, float y2) {
if (x1 == x2) {
firmwareError("Same x1 and x2 in interpolate: %f/%f", x1, x2);
return;
}
a = INTERPOLATION_A(x1, y1, x2, y2);
b = y1 - a * x1;
}
float FastInterpolation::getValue(float x) {
return a * x + b;
}
/** @brief Linear interpolation by two points /** @brief Linear interpolation by two points
* *
* @param x1 key of the first point * @param x1 key of the first point
@ -39,7 +57,7 @@ float interpolate(float x1, float y1, float x2, float y2, float x) {
// a*x1 + b = y1 // a*x1 + b = y1
// a*x2 + b = y2 // a*x2 + b = y2
// chDbgCheck(x1 != x2, "no way we can interpolate"); // efiAssertVoid(x1 != x2, "no way we can interpolate");
float a = INTERPOLATION_A(x1, y1, x2, y2); float a = INTERPOLATION_A(x1, y1, x2, y2);
float b = y1 - a * x1; float b = y1 - a * x1;
float result = a * x + b; float result = a * x + b;
@ -55,8 +73,7 @@ float interpolate(float x1, float y1, float x2, float y2, float x) {
* @note If the parameter is smaller than the first element of the array, -1 is returned. * @note If the parameter is smaller than the first element of the array, -1 is returned.
*/ */
int findIndex(float array[], int size, float value) { int findIndex(float array[], int size, float value) {
if (cisnan(value)) efiAssert(!cisnan(value), "NaN in findIndex", 0);
fatal("NaN in findIndex\r\n");
if (value < array[0]) if (value < array[0])
return -1; return -1;
@ -67,7 +84,7 @@ int findIndex(float array[], int size, float value) {
while (1) { while (1) {
if (size-- == 0) if (size-- == 0)
fatal("Unexpected state in binary search."); efiAssert(FALSE, "Unexpected state in binary search", 0);
middle = (left + right) / 2; middle = (left + right) / 2;

View File

@ -8,19 +8,19 @@
#ifndef INTERPOLATION_3D_H_ #ifndef INTERPOLATION_3D_H_
#define INTERPOLATION_3D_H_ #define INTERPOLATION_3D_H_
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
int findIndex(float array[], int size, float value); int findIndex(float array[], int size, float value);
float interpolate(float x1, float y1, float x2, float y2, float x); float interpolate(float x1, float y1, float x2, float y2, float x);
float interpolate2d(float value, float bin[], float values[], int size); float interpolate2d(float value, float bin[], float values[], int size);
float interpolate3d(float x, float xBin[], int xBinSize, float y, float yBin[], int yBinSize, float* map[]); float interpolate3d(float x, float xBin[], int xBinSize, float y, float yBin[], int yBinSize, float* map[]);
void setTableValue(float bins[], float values[], int size, float key, float value); void setTableValue(float bins[], float values[], int size, float key, float value);
#ifdef __cplusplus class FastInterpolation {
} public:
#endif /* __cplusplus */ FastInterpolation(float x1, float y1, float x2, float y2);
void init(float x1, float y1, float x2, float y2);
float getValue(float x);
private:
float a, b;
};
#endif /* INTERPOLATION_3D_H_ */ #endif /* INTERPOLATION_3D_H_ */

View File

@ -38,11 +38,11 @@ static Logging logger;
/** /**
* @brief Control Thread stack * @brief Control Thread stack
*/ */
static WORKING_AREA(etbTreadStack, UTILITY_THREAD_STACK_SIZE); static THD_WORKING_AREA(etbTreadStack, UTILITY_THREAD_STACK_SIZE);
/** /**
* @brief Pulse-Width Modulation state * @brief Pulse-Width Modulation state
*/ */
static PwmConfig etbPwm; static SimplePwm etbPwm;
static float prevTps; static float prevTps;
@ -69,7 +69,7 @@ static msg_t etbThread(void *arg) {
static void setThrottleConsole(int level) { static void setThrottleConsole(int level) {
scheduleMsg(&logger, "setting throttle=%d", level); scheduleMsg(&logger, "setting throttle=%d", level);
etbPwm.multiWave.switchTimes[0] = 0.01 + (min(level, 98)) / 100.0; etbPwm.multiWave.switchTimes[0] = 0.01 + (minI(level, 98)) / 100.0;
print("st = %f\r\n", etbPwm.multiWave.switchTimes[0]); print("st = %f\r\n", etbPwm.multiWave.switchTimes[0]);
} }
@ -84,11 +84,11 @@ void initElectronicThrottle(void) {
// outputPinRegister("etb2", ELECTRONIC_THROTTLE_CONTROL_2, ETB_CONTROL_LINE_2_PORT, ETB_CONTROL_LINE_2_PIN); // outputPinRegister("etb2", ELECTRONIC_THROTTLE_CONTROL_2, ETB_CONTROL_LINE_2_PORT, ETB_CONTROL_LINE_2_PIN);
// this line used for PWM // this line used for PWM
startSimplePwm(&etbPwm, "etb", startSimplePwmExt(&etbPwm, "etb",
boardConfiguration->electronicThrottlePin1, boardConfiguration->electronicThrottlePin1,
ELECTRONIC_THROTTLE_CONTROL_1, ELECTRONIC_THROTTLE_CONTROL_1,
0.80, 500,
500); 0.80);
addConsoleActionI("e", setThrottleConsole); addConsoleActionI("e", setThrottleConsole);
chThdCreateStatic(etbTreadStack, sizeof(etbTreadStack), NORMALPRIO, (tfunc_t) etbThread, NULL); chThdCreateStatic(etbTreadStack, sizeof(etbTreadStack), NORMALPRIO, (tfunc_t) etbThread, NULL);

View File

@ -50,15 +50,11 @@
#include "efilib2.h" #include "efilib2.h"
#include "ec2.h" #include "ec2.h"
#include "PwmTester.h" #include "PwmTester.h"
#include "engine.h"
extern board_configuration_s *boardConfiguration;
#define _10_MILLISECONDS (10 * TICKS_IN_MS) persistent_config_container_s persistentState CCM_OPTIONAL;
#if defined __GNUC__
persistent_config_container_s persistentState __attribute__((section(".ccm")));
#else
persistent_config_container_s persistentState;
#endif
engine_configuration_s *engineConfiguration = &persistentState.persistentConfiguration.engineConfiguration; engine_configuration_s *engineConfiguration = &persistentState.persistentConfiguration.engineConfiguration;
board_configuration_s *boardConfiguration = &persistentState.persistentConfiguration.boardConfiguration; board_configuration_s *boardConfiguration = &persistentState.persistentConfiguration.boardConfiguration;
@ -73,11 +69,18 @@ static VirtualTimer fuelPumpTimer;
static Logging logger; static Logging logger;
static engine_configuration2_s ec2; static engine_configuration2_s ec2 CCM_OPTIONAL;
engine_configuration2_s * engineConfiguration2 = &ec2; engine_configuration2_s * engineConfiguration2 = &ec2;
static configuration_s cfg = {&persistentState.persistentConfiguration.engineConfiguration, &ec2};
configuration_s * configuration = &cfg;
Engine engine;
static msg_t csThread(void) { static msg_t csThread(void) {
chRegSetThreadName("status"); chRegSetThreadName("status");
#if EFI_SHAFT_POSITION_INPUT
while (TRUE) { while (TRUE) {
int is_cranking = isCranking(); int is_cranking = isCranking();
int is_running = getRpm() > 0 && !is_cranking; int is_running = getRpm() > 0 && !is_cranking;
@ -93,6 +96,8 @@ static msg_t csThread(void) {
chThdSleepMilliseconds(100); chThdSleepMilliseconds(100);
} }
} }
#endif /* EFI_SHAFT_POSITION_INPUT */
return -1;
} }
static void updateErrorCodes(void) { static void updateErrorCodes(void) {
@ -129,14 +134,12 @@ static void fanRelayControl(void) {
Overflow64Counter halTime; Overflow64Counter halTime;
uint64_t getTimeNowUs(void) { uint64_t getTimeNowUs(void) {
// todo: synchronization? multi-threading? return halTime.get(hal_lld_get_counter_value(), false) / (CORE_CLOCK / 1000000);
halTime.offer(hal_lld_get_counter_value());
return halTime.get() / (CORE_CLOCK / 1000000);
} }
uint64_t getHalTimer(void) { //uint64_t getHalTimer(void) {
return halTime.get(); // return halTime.get();
} //}
efitimems_t currentTimeMillis(void) { efitimems_t currentTimeMillis(void) {
// todo: migrate to getTimeNowUs? or not? // todo: migrate to getTimeNowUs? or not?
@ -147,23 +150,23 @@ int getTimeNowSeconds(void) {
return chTimeNow() / CH_FREQUENCY; return chTimeNow() / CH_FREQUENCY;
} }
static void onEveny10Milliseconds(void *arg) { static void onEvenyGeneralMilliseconds(void *arg) {
/** /**
* We need to push current value into the 64 bit counter often enough so that we do not miss an overflow * We need to push current value into the 64 bit counter often enough so that we do not miss an overflow
*/ */
halTime.offer(hal_lld_get_counter_value()); halTime.get(hal_lld_get_counter_value(), true);
updateErrorCodes(); updateErrorCodes();
fanRelayControl(); fanRelayControl();
// schedule next invocation // schedule next invocation
chVTSetAny(&everyMsTimer, _10_MILLISECONDS, &onEveny10Milliseconds, 0); chVTSetAny(&everyMsTimer, boardConfiguration->generalPeriodicThreadPeriod * TICKS_IN_MS, &onEvenyGeneralMilliseconds, 0);
} }
static void initPeriodicEvents(void) { static void initPeriodicEvents(void) {
// schedule first invocation // schedule first invocation
chVTSetAny(&everyMsTimer, _10_MILLISECONDS, &onEveny10Milliseconds, 0); chVTSetAny(&everyMsTimer, boardConfiguration->generalPeriodicThreadPeriod * TICKS_IN_MS, &onEvenyGeneralMilliseconds, 0);
} }
static void fuelPumpOff(void *arg) { static void fuelPumpOff(void *arg) {
@ -173,7 +176,7 @@ static void fuelPumpOff(void *arg) {
turnOutputPinOff(FUEL_PUMP_RELAY); turnOutputPinOff(FUEL_PUMP_RELAY);
} }
static void fuelPumpOn(ShaftEvents signal, int index) { static void fuelPumpOn(trigger_event_e signal, int index, void *arg) {
if (index != 0) if (index != 0)
return; // let's not abuse the timer - one time per revolution would be enough return; // let's not abuse the timer - one time per revolution would be enough
// todo: the check about GPIO_NONE should be somewhere else! // todo: the check about GPIO_NONE should be somewhere else!
@ -191,26 +194,27 @@ static void fuelPumpOn(ShaftEvents signal, int index) {
} }
static void initFuelPump(void) { static void initFuelPump(void) {
addTriggerEventListener(&fuelPumpOn, "fuel pump"); addTriggerEventListener(&fuelPumpOn, "fuel pump", NULL);
fuelPumpOn(SHAFT_PRIMARY_UP, 0); fuelPumpOn(SHAFT_PRIMARY_UP, 0, NULL);
} }
char * getPinNameByAdcChannel(int hwChannel, uint8_t *buffer) { char * getPinNameByAdcChannel(int hwChannel, char *buffer) {
strcpy((char*) buffer, portname(getAdcChannelPort(hwChannel))); strcpy((char*) buffer, portname(getAdcChannelPort(hwChannel)));
itoa10(&buffer[2], getAdcChannelPin(hwChannel)); itoa10(&buffer[2], getAdcChannelPin(hwChannel));
return (char*) buffer; return (char*) buffer;
} }
static uint8_t pinNameBuffer[16]; static char pinNameBuffer[16];
static void printAnalogChannelInfoExt(const char *name, int hwChannel, static void printAnalogChannelInfoExt(const char *name, int hwChannel,
float voltage) { float adcVoltage) {
scheduleMsg(&logger, "%s ADC%d %s value=%fv", name, hwChannel, float voltage = adcVoltage * engineConfiguration->analogInputDividerCoefficient;
getPinNameByAdcChannel(hwChannel, pinNameBuffer), voltage); scheduleMsg(&logger, "%s ADC%d %s rawValue=%f/divided=%fv", name, hwChannel,
getPinNameByAdcChannel(hwChannel, pinNameBuffer), adcVoltage, voltage);
} }
static void printAnalogChannelInfo(const char *name, int hwChannel) { static void printAnalogChannelInfo(const char *name, int hwChannel) {
printAnalogChannelInfoExt(name, hwChannel, getVoltageDivided(hwChannel)); printAnalogChannelInfoExt(name, hwChannel, getVoltage(hwChannel));
} }
static void printAnalogInfo(void) { static void printAnalogInfo(void) {
@ -225,7 +229,7 @@ static void printAnalogInfo(void) {
getVBatt()); getVBatt());
} }
static WORKING_AREA(csThreadStack, UTILITY_THREAD_STACK_SIZE);// declare thread stack static THD_WORKING_AREA(csThreadStack, UTILITY_THREAD_STACK_SIZE);// declare thread stack
void initEngineContoller(void) { void initEngineContoller(void) {
if (hasFirmwareError()) if (hasFirmwareError())
@ -246,11 +250,13 @@ void initEngineContoller(void) {
initWaveAnalyzer(); initWaveAnalyzer();
#endif /* EFI_WAVE_ANALYZER */ #endif /* EFI_WAVE_ANALYZER */
#if EFI_SHAFT_POSITION_INPUT
/** /**
* there is an implicit dependency on the fact that 'tachometer' listener is the 1st listener - this case * there is an implicit dependency on the fact that 'tachometer' listener is the 1st listener - this case
* other listeners can access current RPM value * other listeners can access current RPM value
*/ */
initRpmCalculator(); initRpmCalculator();
#endif /* EFI_SHAFT_POSITION_INPUT */
#if EFI_TUNER_STUDIO #if EFI_TUNER_STUDIO
startTunerStudioConnectivity(); startTunerStudioConnectivity();
@ -283,7 +289,7 @@ void initEngineContoller(void) {
/** /**
* This method initialized the main listener which actually runs injectors & ignition * This method initialized the main listener which actually runs injectors & ignition
*/ */
initMainEventListener(); initMainEventListener(engineConfiguration, engineConfiguration2);
#endif /* EFI_ENGINE_CONTROL */ #endif /* EFI_ENGINE_CONTROL */
#if EFI_IDLE_CONTROL #if EFI_IDLE_CONTROL

View File

@ -18,7 +18,7 @@ extern "C"
{ {
#endif /* __cplusplus */ #endif /* __cplusplus */
char * getPinNameByAdcChannel(int hwChannel, uint8_t *buffer); char * getPinNameByAdcChannel(int hwChannel, char *buffer);
void initEngineContoller(void); void initEngineContoller(void);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -27,10 +27,14 @@ void chDbgPanic3(const char *msg, const char * file, int line) {
return; return;
dbg_panic_file = file; dbg_panic_file = file;
dbg_panic_line = line; dbg_panic_line = line;
#if CH_DBG_SYSTEM_STATE_CHECK
dbg_panic_msg = msg; dbg_panic_msg = msg;
#endif /* CH_DBG_SYSTEM_STATE_CHECK */
/**
setOutputPinValue(LED_ERROR, 1); * low-level function is used here to reduce stack usage
*/
palWritePad(LED_ERROR_PORT, LED_ERROR_PIN, 1);
#if EFI_HD44780_LCD #if EFI_HD44780_LCD
lcdShowFatalMessage((char *) msg); lcdShowFatalMessage((char *) msg);
#endif /* EFI_HD44780_LCD */ #endif /* EFI_HD44780_LCD */

View File

@ -1,5 +1,5 @@
/** /**
* @file flash_main.c * @file flash_main.cpp
* @brief Higher-level logic of saving data into internal flash memory * @brief Higher-level logic of saving data into internal flash memory
* *
* *
@ -52,6 +52,7 @@ crc_t flashStateCrc(persistent_config_container_s *state) {
} }
void writeToFlash(void) { void writeToFlash(void) {
#if EFI_INTERNAL_FLASH
persistentState.size = PERSISTENT_SIZE; persistentState.size = PERSISTENT_SIZE;
persistentState.version = FLASH_DATA_VERSION; persistentState.version = FLASH_DATA_VERSION;
scheduleMsg(&logger, "FLASH_DATA_VERSION=%d", persistentState.version); scheduleMsg(&logger, "FLASH_DATA_VERSION=%d", persistentState.version);
@ -64,6 +65,7 @@ void writeToFlash(void) {
result = flashWrite(FLASH_ADDR, (const char *) &persistentState, PERSISTENT_SIZE); result = flashWrite(FLASH_ADDR, (const char *) &persistentState, PERSISTENT_SIZE);
scheduleMsg(&logger, "Flash programmed in (ms): %d", currentTimeMillis() - nowMs); scheduleMsg(&logger, "Flash programmed in (ms): %d", currentTimeMillis() - nowMs);
scheduleMsg(&logger, "Flashed: %d", result); scheduleMsg(&logger, "Flashed: %d", result);
#endif /* EFI_INTERNAL_FLASH */
} }
static int isValidCrc(persistent_config_container_s *state) { static int isValidCrc(persistent_config_container_s *state) {

View File

@ -11,7 +11,7 @@
#include "engine_configuration.h" #include "engine_configuration.h"
#define FLASH_DATA_VERSION 3002 #define FLASH_DATA_VERSION 3601
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"

View File

@ -31,10 +31,11 @@
#include "idle_thread.h" #include "idle_thread.h"
#include "pin_repository.h" #include "pin_repository.h"
#include "engine_configuration.h" #include "engine_configuration.h"
#include "engine.h"
#define IDLE_AIR_CONTROL_VALVE_PWM_FREQUENCY 200 #define IDLE_AIR_CONTROL_VALVE_PWM_FREQUENCY 200
static WORKING_AREA(ivThreadStack, UTILITY_THREAD_STACK_SIZE); static THD_WORKING_AREA(ivThreadStack, UTILITY_THREAD_STACK_SIZE);
static volatile int isIdleControlActive = EFI_IDLE_CONTROL; static volatile int isIdleControlActive = EFI_IDLE_CONTROL;
extern board_configuration_s *boardConfiguration; extern board_configuration_s *boardConfiguration;
@ -45,15 +46,9 @@ extern board_configuration_s *boardConfiguration;
static volatile int idleSwitchState; static volatile int idleSwitchState;
static Logging logger; static Logging logger;
extern Engine engine;
static float _switchTimes[PWM_PHASE_MAX_COUNT]; static SimplePwm idleValve;
// todo: extract helper for simple PWM?
static int pinStates[2];
static single_wave_s wave(pinStates);
static single_wave_s sr[1] = {wave};
static PwmConfig idleValve(_switchTimes, sr);
/** /**
* Idle level calculation algorithm lives in idle_controller.c * Idle level calculation algorithm lives in idle_controller.c
@ -80,10 +75,10 @@ static void setIdleValvePwm(int value) {
return; return;
scheduleMsg(&logger, "setting idle valve PWM %d", value); scheduleMsg(&logger, "setting idle valve PWM %d", value);
/** /**
* currently IDEL level is an integer per mil (0-1000 range), and PWM takes a fioat in the 0..1 range * currently idle level is an integer per mil (0-1000 range), and PWM takes a float in the 0..1 range
* todo: unify? * todo: unify?
*/ */
setSimplePwmDutyCycle(&idleValve, 0.001 * value); idleValve.setSimplePwmDutyCycle(0.001 * value);
} }
static msg_t ivThread(int param) { static msg_t ivThread(int param) {
@ -91,7 +86,7 @@ static msg_t ivThread(int param) {
int currentIdleValve = -1; int currentIdleValve = -1;
while (TRUE) { while (TRUE) {
chThdSleepMilliseconds(100); chThdSleepMilliseconds(boardConfiguration->idleThreadPeriod);
// this value is not used yet // this value is not used yet
idleSwitchState = palReadPad(getHwPort(boardConfiguration->idleSwitchPin), getHwPin(boardConfiguration->idleSwitchPin)); idleSwitchState = palReadPad(getHwPort(boardConfiguration->idleSwitchPin), getHwPin(boardConfiguration->idleSwitchPin));
@ -122,12 +117,11 @@ static void setIdleRpmAction(int value) {
void startIdleThread() { void startIdleThread() {
initLogging(&logger, "Idle Valve Control"); initLogging(&logger, "Idle Valve Control");
startSimplePwm(&idleValve, "Idle Valve", startSimplePwmExt(&idleValve, "Idle Valve",
boardConfiguration->idleValvePin, boardConfiguration->idleValvePin,
IDLE_VALVE, IDLE_VALVE,
0.5,
IDLE_AIR_CONTROL_VALVE_PWM_FREQUENCY, IDLE_AIR_CONTROL_VALVE_PWM_FREQUENCY,
TRUE); 0.5);
idleInit(&idle); idleInit(&idle);
scheduleMsg(&logger, "initial idle %d", idle.value); scheduleMsg(&logger, "initial idle %d", idle.value);

View File

@ -1,5 +1,5 @@
/** /**
* @file injector_central.c * @file injector_central.cpp
* @brief Utility methods related to fuel injection. * @brief Utility methods related to fuel injection.
* *
* *
@ -22,7 +22,6 @@
#include "injector_central.h" #include "injector_central.h"
#include "main.h" #include "main.h"
#include "engines.h"
#include "io_pins.h" #include "io_pins.h"
#include "signal_executor.h" #include "signal_executor.h"
#include "main_trigger_callback.h" #include "main_trigger_callback.h"
@ -38,17 +37,13 @@ extern board_configuration_s *boardConfiguration;
static int is_injector_enabled[MAX_INJECTOR_COUNT]; static int is_injector_enabled[MAX_INJECTOR_COUNT];
int isInjectionEnabled(void) { void assertCylinderId(int cylinderId, const char *msg) {
return engineConfiguration2->isInjectionEnabledFlag;
}
void assertCylinderId(int cylinderId, char *msg) {
int isValid = cylinderId >= 1 && cylinderId <= engineConfiguration->cylindersCount; int isValid = cylinderId >= 1 && cylinderId <= engineConfiguration->cylindersCount;
if (!isValid) { if (!isValid) {
// we are here only in case of a fatal issue - at this point it is fine to make some blocking i-o // we are here only in case of a fatal issue - at this point it is fine to make some blocking i-o
//scheduleSimpleMsg(&logger, "cid=", cylinderId); //scheduleSimpleMsg(&logger, "cid=", cylinderId);
print("ERROR [%s] cid=%d\r\n", msg, cylinderId); print("ERROR [%s] cid=%d\r\n", msg, cylinderId);
chDbgAssert(TRUE, "Cylinder ID", null); efiAssertVoid(FALSE, "Cylinder ID");
} }
} }
@ -76,7 +71,7 @@ static void printStatus(void) {
} }
static void setInjectorEnabled(int id, int value) { static void setInjectorEnabled(int id, int value) {
chDbgCheck(id >= 0 && id < engineConfiguration->cylindersCount, "injector id"); efiAssertVoid(id >= 0 && id < engineConfiguration->cylindersCount, "injector id");
is_injector_enabled[id] = value; is_injector_enabled[id] = value;
printStatus(); printStatus();
} }
@ -121,14 +116,14 @@ static void sparkbench(char * onStr, char *offStr, char *countStr) {
needToRunBench = TRUE; needToRunBench = TRUE;
} }
static WORKING_AREA(benchThreadStack, UTILITY_THREAD_STACK_SIZE); static THD_WORKING_AREA(benchThreadStack, UTILITY_THREAD_STACK_SIZE);
static msg_t benchThread(int param) { static msg_t benchThread(int param) {
chRegSetThreadName("BenchThread"); chRegSetThreadName("BenchThread");
while (TRUE) { while (TRUE) {
while (!needToRunBench) { while (!needToRunBench) {
chThdSleepMilliseconds(50); chThdSleepMilliseconds(200);
} }
needToRunBench = FALSE; needToRunBench = FALSE;
runBench(brainPin, pin, onTime, offTime, count); runBench(brainPin, pin, onTime, offTime, count);

View File

@ -19,9 +19,8 @@ extern "C"
#endif /* __cplusplus */ #endif /* __cplusplus */
void initInjectorCentral(void); void initInjectorCentral(void);
int isInjectionEnabled(void);
int isInjectorEnabled(int cylinderId); int isInjectorEnabled(int cylinderId);
void assertCylinderId(int cylinderId, char *msg); void assertCylinderId(int cylinderId, const char *msg);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -37,7 +37,7 @@
#define MFI_BLINK_SEPARATOR 400 #define MFI_BLINK_SEPARATOR 400
#define MFI_CHECKENGINE_LIGHT 10000 #define MFI_CHECKENGINE_LIGHT 10000
static WORKING_AREA(mfiThreadStack, UTILITY_THREAD_STACK_SIZE); // declare thread static THD_WORKING_AREA(mfiThreadStack, UTILITY_THREAD_STACK_SIZE); // declare thread
static void blink_digits(int digit, int duration) { static void blink_digits(int digit, int duration) {
for (int iter = 0; iter < digit; iter++) { for (int iter = 0; iter < digit; iter++) {

View File

@ -1,5 +1,5 @@
/** /**
* @file map_averaging.c * @file map_averaging.cpp
* *
* @date Dec 11, 2013 * @date Dec 11, 2013
* @author Andrey Belomutskiy, (c) 2012-2014 * @author Andrey Belomutskiy, (c) 2012-2014
@ -20,16 +20,18 @@
#include "main.h" #include "main.h"
#include "map.h"
#if EFI_MAP_AVERAGING #if EFI_MAP_AVERAGING
#include "map_averaging.h" #include "map_averaging.h"
#include "trigger_central.h" #include "trigger_central.h"
#include "adc_inputs.h" #include "adc_inputs.h"
#include "map.h"
#include "engine_state.h" #include "engine_state.h"
#include "engine_configuration.h" #include "engine_configuration.h"
#include "interpolation.h" #include "interpolation.h"
#include "signal_executor.h" #include "signal_executor.h"
#include "engine.h"
#if EFI_ANALOG_CHART #if EFI_ANALOG_CHART
#include "analog_chart.h" #include "analog_chart.h"
@ -58,13 +60,13 @@ static volatile float v_mapAccumulator = 0;
*/ */
static volatile int mapMeasurementsCounter = 0; static volatile int mapMeasurementsCounter = 0;
static float currentMaxPressure;
/** /**
* v_ for Voltage * v_ for Voltage
*/ */
static float v_averagedMapValue; static float v_averagedMapValue;
extern Engine engine;
extern engine_configuration_s *engineConfiguration; extern engine_configuration_s *engineConfiguration;
static scheduling_s startTimer[2]; static scheduling_s startTimer[2];
@ -81,7 +83,9 @@ static void startAveraging(void*arg) {
} }
/** /**
* This method is invoked from ADC callback * This method is invoked from ADC callback.
* @note This method is invoked OFTEN, this method is a potential bottle-next - the implementation should be
* as fast as possible
*/ */
void mapAveragingCallback(adcsample_t value) { void mapAveragingCallback(adcsample_t value) {
/* Calculates the average values from the ADC samples.*/ /* Calculates the average values from the ADC samples.*/
@ -90,11 +94,11 @@ void mapAveragingCallback(adcsample_t value) {
float voltage = adcToVoltsDivided(value); float voltage = adcToVoltsDivided(value);
float currentPressure = getMapByVoltage(voltage); float currentPressure = getMapByVoltage(voltage);
#if EFI_ANALOG_CHART
if (engineConfiguration->analogChartMode == AC_MAP) if (engineConfiguration->analogChartMode == AC_MAP)
if (perRevolutionCounter % FAST_MAP_CHART_SKIP_FACTOR == 0) if (perRevolutionCounter % FAST_MAP_CHART_SKIP_FACTOR == 0)
acAddData(getCrankshaftAngle(getTimeNowUs()), currentPressure); acAddData(getCrankshaftAngle(getTimeNowUs()), currentPressure);
#endif /* EFI_ANALOG_CHART */
currentMaxPressure = maxF(currentMaxPressure, currentPressure);
chSysLockFromIsr() chSysLockFromIsr()
; ;
@ -118,7 +122,7 @@ static void endAveraging(void *arg) {
/** /**
* Shaft Position callback used to schedule start and end of MAP averaging * Shaft Position callback used to schedule start and end of MAP averaging
*/ */
static void shaftPositionCallback(ShaftEvents ckpEventType, int index) { static void shaftPositionCallback(trigger_event_e ckpEventType, int index, void *arg) {
// this callback is invoked on interrupt thread // this callback is invoked on interrupt thread
if (index != 0) if (index != 0)
@ -131,8 +135,6 @@ static void shaftPositionCallback(ShaftEvents ckpEventType, int index) {
perRevolution = perRevolutionCounter; perRevolution = perRevolutionCounter;
perRevolutionCounter = 0; perRevolutionCounter = 0;
currentMaxPressure = 0;
MAP_sensor_config_s * config = &engineConfiguration->map; MAP_sensor_config_s * config = &engineConfiguration->map;
float startAngle = interpolate2d(rpm, config->samplingAngleBins, config->samplingAngle, MAP_ANGLE_SIZE); float startAngle = interpolate2d(rpm, config->samplingAngleBins, config->samplingAngle, MAP_ANGLE_SIZE);
@ -153,11 +155,12 @@ float getMapVoltage(void) {
} }
/** /**
* because of MAP window averaging, MAP is only available while engine is spinning * Because of MAP window averaging, MAP is only available while engine is spinning
* @return Manifold Absolute Pressure, in kPa
*/ */
float getMap(void) { float getMap(void) {
if (getRpm() == 0) if (getRpm() == 0)
return getRawMap(); // maybe return NaN and have a return getRawMap(); // maybe return NaN in case of stopped engine?
return getMapByVoltage(v_averagedMapValue); return getMapByVoltage(v_averagedMapValue);
} }
@ -170,7 +173,7 @@ void initMapAveraging(void) {
endTimer[1].name = "map end1"; endTimer[1].name = "map end1";
addTriggerEventListener(&shaftPositionCallback, "rpm reporter"); addTriggerEventListener(&shaftPositionCallback, "rpm reporter", NULL);
addConsoleAction("faststat", showMapStats); addConsoleAction("faststat", showMapStats);
} }

View File

@ -2,7 +2,7 @@
* @brief dead code * @brief dead code
* *
* *
* map_multiplier.c * map_multiplier.cpp
* *
* @date Jul 23, 2013 * @date Jul 23, 2013
* @author Andrey Belomutskiy, (c) 2012-2014 * @author Andrey Belomutskiy, (c) 2012-2014
@ -16,12 +16,15 @@
#include "wave_math.h" #include "wave_math.h"
#include "allsensors.h" #include "allsensors.h"
#include "engine_math.h" #include "engine_math.h"
#include "engine.h"
extern engine_configuration_s *engineConfiguration; extern engine_configuration_s *engineConfiguration;
static Logging logger; static Logging logger;
static WORKING_AREA(maThreadStack, UTILITY_THREAD_STACK_SIZE); extern Engine engine;
static THD_WORKING_AREA(maThreadStack, UTILITY_THREAD_STACK_SIZE);
static void mapCallback(int rpm, float key, float value) { static void mapCallback(int rpm, float key, float value) {
Logging *logging = &logger; Logging *logging = &logger;

View File

@ -19,14 +19,15 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "engine_math.h"
#include "main.h" #include "main.h"
#include "engine_math.h"
#include "engine_configuration.h" #include "engine_configuration.h"
#include "interpolation.h" #include "interpolation.h"
#include "allsensors.h" #include "allsensors.h"
#include "io_pins.h" #include "io_pins.h"
#include "OutputSignalList.h" #include "OutputSignalList.h"
#include "trigger_decoder.h" #include "trigger_decoder.h"
#include "event_registry.h"
/* /*
* default Volumetric Efficiency * default Volumetric Efficiency
@ -36,42 +37,21 @@
// return interpolate(5000, 1.1, 8000, 1, rpm); // return interpolate(5000, 1.1, 8000, 1, rpm);
// return interpolate(500, 0.5, 5000, 1.1, rpm); // return interpolate(500, 0.5, 5000, 1.1, rpm);
//} //}
//#define K_AT_MIN_RPM_MIN_TPS 0.25
//#define K_AT_MIN_RPM_MAX_TPS 0.25
//#define K_AT_MAX_RPM_MIN_TPS 0.25
//#define K_AT_MAX_RPM_MAX_TPS 0.9
//
//#define rpmMin 500
//#define rpmMax 8000
//
//#define tpMin 0
//#define tpMax 100
//
// http://rusefi.com/math/t_charge.html
// /
//float getTCharge(int rpm, int tps, float coolantTemp, float airTemp) {
// float minRpmKcurrentTPS = interpolate(tpMin, K_AT_MIN_RPM_MIN_TPS, tpMax,
// K_AT_MIN_RPM_MAX_TPS, tps);
// float maxRpmKcurrentTPS = interpolate(tpMin, K_AT_MAX_RPM_MIN_TPS, tpMax,
// K_AT_MAX_RPM_MAX_TPS, tps);
//
// float Tcharge_coff = interpolate(rpmMin, minRpmKcurrentTPS, rpmMax,
// maxRpmKcurrentTPS, rpm);
//
// float Tcharge = coolantTemp * (1 - Tcharge_coff) + airTemp * Tcharge_coff;
//
// return Tcharge;
//}
#define MAX_STARTING_FUEL 15
#define MIN_STARTING_FUEL 8
/** /**
* @return time needed to rotate crankshaft by one degree, in milliseconds. * @return time needed to rotate crankshaft by one degree, in milliseconds.
* @deprecated
*/ */
float getOneDegreeTimeMs(int rpm) { float getOneDegreeTimeMs(int rpm) {
return 1000.0 * 60 / 360 / rpm; return 1000.0 * 60 / 360 / rpm;
} }
/**
* @return time needed to rotate crankshaft by one degree, in microseconds.
*/
float getOneDegreeTimeUs(int rpm) {
return 1000000.0 * 60 / 360 / rpm;
}
/** /**
* @return number of milliseconds in one crankshaft revolution * @return number of milliseconds in one crankshaft revolution
*/ */
@ -136,34 +116,39 @@ int isCrankingRT(engine_configuration_s *engineConfiguration, int rpm) {
OutputSignalList ignitionSignals; OutputSignalList ignitionSignals;
OutputSignalList injectonSignals; OutputSignalList injectonSignals;
static void registerSparkEvent(engine_configuration_s const *engineConfiguration, trigger_shape_s * s, static void registerSparkEvent(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
ActuatorEventList *list, OutputSignal *actuator, float angleOffset) { IgnitionEventList *list, OutputSignal *actuator, float localAdvance, float dwell) {
registerActuatorEventExt(engineConfiguration, s, list, IgnitionEvent *event = list->getNextActuatorEvent();
actuator, angleOffset); if (event == NULL)
return; // error already reported
event->advance = localAdvance;
registerActuatorEventExt(engineConfiguration, s, &event->actuator, actuator, localAdvance - dwell);
} }
void initializeIgnitionActions(float baseAngle, engine_configuration_s *engineConfiguration, void initializeIgnitionActions(float advance, float dwellAngle, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2, float dwellMs, ActuatorEventList *list) { engine_configuration2_s *engineConfiguration2, IgnitionEventList *list) {
chDbgCheck(engineConfiguration->cylindersCount > 0, "cylindersCount");
efiAssertVoid(engineConfiguration->cylindersCount > 0, "cylindersCount");
ignitionSignals.clear(); ignitionSignals.clear();
resetEventList(list); list->resetEventList();
switch (engineConfiguration->ignitionMode) { switch (engineConfiguration->ignitionMode) {
case IM_ONE_COIL: case IM_ONE_COIL:
for (int i = 0; i < engineConfiguration->cylindersCount; i++) { for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
// todo: extract method // todo: extract method
float angle = baseAngle + 720.0 * i / engineConfiguration->cylindersCount; float localAdvance = advance + 720.0 * i / engineConfiguration->cylindersCount;
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list,
ignitionSignals.add(SPARKOUT_1_OUTPUT), angle); ignitionSignals.add(SPARKOUT_1_OUTPUT), localAdvance, dwellAngle);
} }
break; break;
case IM_WASTED_SPARK: case IM_WASTED_SPARK:
for (int i = 0; i < engineConfiguration->cylindersCount; i++) { for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
float angle = baseAngle + 720.0 * i / engineConfiguration->cylindersCount; float localAdvance = advance + 720.0 * i / engineConfiguration->cylindersCount;
int wastedIndex = i % (engineConfiguration->cylindersCount / 2); int wastedIndex = i % (engineConfiguration->cylindersCount / 2);
@ -171,18 +156,18 @@ void initializeIgnitionActions(float baseAngle, engine_configuration_s *engineCo
io_pin_e ioPin = (io_pin_e) (SPARKOUT_1_OUTPUT + id); io_pin_e ioPin = (io_pin_e) (SPARKOUT_1_OUTPUT + id);
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list,
ignitionSignals.add(ioPin), angle); ignitionSignals.add(ioPin), localAdvance, dwellAngle);
} }
break; break;
case IM_INDIVIDUAL_COILS: case IM_INDIVIDUAL_COILS:
for (int i = 0; i < engineConfiguration->cylindersCount; i++) { for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
float angle = baseAngle + 720.0 * i / engineConfiguration->cylindersCount; float localAdvance = advance + 720.0 * i / engineConfiguration->cylindersCount;
io_pin_e pin = (io_pin_e) ((int) SPARKOUT_1_OUTPUT + getCylinderId(engineConfiguration->firingOrder, i) - 1); io_pin_e pin = (io_pin_e) ((int) SPARKOUT_1_OUTPUT + getCylinderId(engineConfiguration->firingOrder, i) - 1);
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, ignitionSignals.add(pin),
ignitionSignals.add(pin), angle); localAdvance, dwellAngle);
} }
break; break;
@ -193,7 +178,7 @@ void initializeIgnitionActions(float baseAngle, engine_configuration_s *engineCo
void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *engineConfiguration2, void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *engineConfiguration2,
ActuatorEventList *list, injection_mode_e mode) { ActuatorEventList *list, injection_mode_e mode) {
resetEventList(list); list->resetEventList();
trigger_shape_s *s = &engineConfiguration2->triggerShape; trigger_shape_s *s = &engineConfiguration2->triggerShape;
@ -204,7 +189,7 @@ void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *eng
for (int i = 0; i < e->cylindersCount; i++) { for (int i = 0; i < e->cylindersCount; i++) {
io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + getCylinderId(e->firingOrder, i) - 1); io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + getCylinderId(e->firingOrder, i) - 1);
float angle = baseAngle + i * 720.0 / e->cylindersCount; float angle = baseAngle + i * 720.0 / e->cylindersCount;
registerActuatorEventExt(e, s, list, injectonSignals.add(pin), angle); registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
} }
break; break;
case IM_SIMULTANEOUS: case IM_SIMULTANEOUS:
@ -213,7 +198,7 @@ void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *eng
for (int j = 0; j < e->cylindersCount; j++) { for (int j = 0; j < e->cylindersCount; j++) {
io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + j); io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + j);
registerActuatorEventExt(e, s, list, injectonSignals.add(pin), angle); registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
} }
} }
break; break;
@ -221,7 +206,7 @@ void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *eng
for (int i = 0; i < e->cylindersCount; i++) { for (int i = 0; i < e->cylindersCount; i++) {
io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + (i % 2)); io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + (i % 2));
float angle = baseAngle + i * 720.0 / e->cylindersCount; float angle = baseAngle + i * 720.0 / e->cylindersCount;
registerActuatorEventExt(e, s, list, injectonSignals.add(pin), angle); registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
} }
break; break;
default: default:
@ -238,53 +223,76 @@ float getSparkDwellMsT(engine_configuration_s *engineConfiguration, int rpm) {
float angle = engineConfiguration->crankingChargeAngle; float angle = engineConfiguration->crankingChargeAngle;
return getOneDegreeTimeMs(rpm) * angle; return getOneDegreeTimeMs(rpm) * angle;
} }
efiAssert(!cisnan(rpm), "invalid rpm"); efiAssert(!cisnan(rpm), "invalid rpm", NAN);
return interpolate2d(rpm, engineConfiguration->sparkDwellBins, engineConfiguration->sparkDwell, DWELL_CURVE_SIZE); return interpolate2d(rpm, engineConfiguration->sparkDwellBins, engineConfiguration->sparkDwell, DWELL_CURVE_SIZE);
} }
void registerActuatorEventExt(engine_configuration_s const *engineConfiguration, trigger_shape_s * s, /**
ActuatorEventList *list, OutputSignal *actuator, float angleOffset) { * Trigger event count equals engine cycle event count if we have a cam sensor.
chDbgCheck(s->getSize() > 0, "uninitialized trigger_shape_s"); * Two trigger cycles make one engine cycle in case of a four stroke engine If we only have a cranksensor.
*/
int getEngineCycleEventCount(engine_configuration_s const *engineConfiguration, trigger_shape_s * s) {
return getOperationMode(engineConfiguration) == FOUR_STROKE_CAM_SENSOR ? s->getSize() : 2 * s->getSize();
}
void findTriggerPosition(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
event_trigger_position_s *position, float angleOffset) {
angleOffset = fixAngle(angleOffset + engineConfiguration->globalTriggerAngleOffset); angleOffset = fixAngle(angleOffset + engineConfiguration->globalTriggerAngleOffset);
int triggerIndexOfZeroEvent = s->triggerShapeSynchPointIndex;
// todo: migrate to crankAngleRange? // todo: migrate to crankAngleRange?
float firstAngle = s->wave.getSwitchTime(triggerIndexOfZeroEvent) * 720; float firstAngle = s->wave.getAngle(s->triggerShapeSynchPointIndex, engineConfiguration, s);
int engineCycleEventCount = getEngineCycleEventCount(engineConfiguration, s);
// let's find the last trigger angle which is less or equal to the desired angle // let's find the last trigger angle which is less or equal to the desired angle
int i; int i;
for (i = 0; i < s->getSize() - 1; i++) { for (i = 0; i < engineCycleEventCount - 1; i++) {
// todo: we need binary search here // todo: we need binary search here
float angle = fixAngle( float angle = fixAngle(
s->wave.getSwitchTime((triggerIndexOfZeroEvent + i + 1) % s->getSize()) * 720 - firstAngle); s->wave.getAngle((s->triggerShapeSynchPointIndex + i + 1) % engineCycleEventCount, engineConfiguration, s)
- firstAngle);
if (angle > angleOffset) if (angle > angleOffset)
break; break;
} }
// explicit check for zero to avoid issues where logical zero is not exactly zero due to float nature // explicit check for zero to avoid issues where logical zero is not exactly zero due to float nature
float angle = float eventAngle;
i == 0 ? if (i == 0) {
0 : eventAngle = 0;
fixAngle(s->wave.getSwitchTime((triggerIndexOfZeroEvent + i) % s->getSize()) * 720 - firstAngle); } else {
eventAngle = fixAngle(
s->wave.getAngle((s->triggerShapeSynchPointIndex + i) % engineCycleEventCount, engineConfiguration, s)
- firstAngle);
}
if (angleOffset < angle) { if (angleOffset < eventAngle) {
firmwareError("angle constraint violation in registerActuatorEventExt(): %f/%f", angleOffset, angle); firmwareError("angle constraint violation in registerActuatorEventExt(): %f/%f", angleOffset, eventAngle);
return; return;
} }
registerActuatorEvent(list, i, actuator, angleOffset - angle); position->eventIndex = i;
position->eventAngle = eventAngle;
position->angleOffset = angleOffset - eventAngle;
} }
//float getTriggerEventAngle(int triggerEventIndex) { void registerActuatorEventExt(engine_configuration_s const *engineConfiguration, trigger_shape_s * s, ActuatorEvent *e,
// return 0; OutputSignal *actuator, float angleOffset) {
//} efiAssertVoid(s->getSize() > 0, "uninitialized trigger_shape_s");
if (e == NULL)
return; // error already reported
e->actuator = actuator;
findTriggerPosition(engineConfiguration, s, &e->position, angleOffset);
}
static int order_1_THEN_3_THEN_4_THEN2[] = { 1, 3, 4, 2 }; static int order_1_THEN_3_THEN_4_THEN2[] = { 1, 3, 4, 2 };
static int order_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4[] = { 1, 5, 3, 6, 2, 4 }; static int order_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4[] = { 1, 5, 3, 6, 2, 4 };
static int order_1_8_4_3_6_5_7_2[] = {1, 8, 4, 3, 6, 5, 7, 2};
/** /**
* @param index from zero to cylindersCount - 1 * @param index from zero to cylindersCount - 1
* @return cylinderId from one to cylindersCount * @return cylinderId from one to cylindersCount
@ -298,6 +306,8 @@ int getCylinderId(firing_order_e firingOrder, int index) {
return order_1_THEN_3_THEN_4_THEN2[index]; return order_1_THEN_3_THEN_4_THEN2[index];
case FO_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4: case FO_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4:
return order_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4[index]; return order_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4[index];
case FO_1_8_4_3_6_5_7_2:
return order_1_8_4_3_6_5_7_2[index];
default: default:
firmwareError("getCylinderId not supported for %d", firingOrder); firmwareError("getCylinderId not supported for %d", firingOrder);
@ -320,8 +330,13 @@ void prepareOutputSignals(engine_configuration_s *engineConfiguration, engine_co
} }
void setTableBin(float array[], int size, float l, float r) { void setTableBin(float array[], int size, float l, float r) {
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++) {
array[i] = interpolate(0, l, size - 1, r, i); float value = interpolate(0, l, size - 1, r, i);
/**
* rounded values look nicer, also we want to avoid precision mismatch with Tuner Studio
*/
array[i] = efiRound(value, 0.01);
}
} }
void setFuelRpmBin(engine_configuration_s *engineConfiguration, float l, float r) { void setFuelRpmBin(engine_configuration_s *engineConfiguration, float l, float r) {
@ -339,3 +354,7 @@ void setTimingRpmBin(engine_configuration_s *engineConfiguration, float l, float
void setTimingLoadBin(engine_configuration_s *engineConfiguration, float l, float r) { void setTimingLoadBin(engine_configuration_s *engineConfiguration, float l, float r) {
setTableBin(engineConfiguration->ignitionLoadBins, IGN_LOAD_COUNT, l, r); setTableBin(engineConfiguration->ignitionLoadBins, IGN_LOAD_COUNT, l, r);
} }
int isInjectionEnabled(engine_configuration2_s const *engineConfiguration2) {
return engineConfiguration2->isInjectionEnabledFlag;
}

View File

@ -10,6 +10,54 @@
#include "engine_configuration.h" #include "engine_configuration.h"
#ifdef __cplusplus
#include "ec2.h"
#include "trigger_structure.h"
void findTriggerPosition(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
event_trigger_position_s *position, float angleOffset);
int isInjectionEnabled(engine_configuration2_s const *engineConfiguration2);
// 'random' value to be sure we are not treating any non-zero trash as TRUE
#define MAGIC_TRUE_VALUE 153351512
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
class Map3D {
public:
void init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]);
float getValue(float x, float xBin[], float y, float yBin[]);
void setAll(float value);
private:
float *pointers[LOAD_BIN_SIZE];
int initialized;
};
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
void Map3D<RPM_BIN_SIZE, LOAD_BIN_SIZE>::init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]) {
for (int k = 0; k < LOAD_BIN_SIZE; k++)
pointers[k] = table[k];
initialized = MAGIC_TRUE_VALUE;
}
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
float Map3D<RPM_BIN_SIZE, LOAD_BIN_SIZE>::getValue(float x, float xBin[], float y, float yBin[]) {
efiAssert(initialized == MAGIC_TRUE_VALUE, "fuel map initialized", NAN);
return interpolate3d(x, xBin, LOAD_BIN_SIZE, y, yBin, RPM_BIN_SIZE, pointers);
}
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
void Map3D<RPM_BIN_SIZE, LOAD_BIN_SIZE>::setAll(float value) {
for (int l = 0; l < LOAD_BIN_SIZE; l++) {
for (int r = 0; r < RPM_BIN_SIZE; r++) {
pointers[l][r] = value;
}
}
}
typedef Map3D<16, 16> Map3D1616;
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
@ -18,9 +66,9 @@ extern "C"
//float getDefaultVE(int rpm); //float getDefaultVE(int rpm);
float getDefaultFuel(int rpm, float map); float getDefaultFuel(int rpm, float map);
//float getTCharge(int rpm, int tps, float coolantTemp, float airTemp);
float getOneDegreeTimeMs(int rpm); float getOneDegreeTimeMs(int rpm);
float getOneDegreeTimeUs(int rpm);
float getCrankshaftRevolutionTimeMs(int rpm); float getCrankshaftRevolutionTimeMs(int rpm);
int isCrankingRT(engine_configuration_s *engineConfiguration, int rpm); int isCrankingRT(engine_configuration_s *engineConfiguration, int rpm);
@ -35,6 +83,7 @@ float getEngineLoadT(engine_configuration_s *engineConfiguration);
float getSparkDwellMsT(engine_configuration_s *engineConfiguration, int rpm); float getSparkDwellMsT(engine_configuration_s *engineConfiguration, int rpm);
#define getSparkDwellMs(rpm) getSparkDwellMsT(engineConfiguration, rpm) #define getSparkDwellMs(rpm) getSparkDwellMsT(engineConfiguration, rpm)
int getCylinderId(firing_order_e firingOrder, int index); int getCylinderId(firing_order_e firingOrder, int index);
void setTableBin(float array[], int size, float l, float r); void setTableBin(float array[], int size, float l, float r);

View File

@ -1,4 +1,5 @@
CONTROLLERS_MATH_SRC = CONTROLLERS_MATH_SRC =
CONTROLLERS_MATH_SRC_CPP = $(PROJECT_DIR)/controllers/math/engine_math.cpp CONTROLLERS_MATH_SRC_CPP = $(PROJECT_DIR)/controllers/math/engine_math.cpp \
$(PROJECT_DIR)/controllers/math/speed_density.cpp

View File

@ -0,0 +1,78 @@
/**
* @file speed_density.cpp
*
* @date May 29, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "main.h"
#include "speed_density.h"
#include "interpolation.h"
#include "engine.h"
#include "rpm_calculator.h"
#include "engine_math.h"
#include "engine_state.h"
#define K_AT_MIN_RPM_MIN_TPS 0.25
#define K_AT_MIN_RPM_MAX_TPS 0.25
#define K_AT_MAX_RPM_MIN_TPS 0.25
#define K_AT_MAX_RPM_MAX_TPS 0.9
#define rpmMin 500
#define rpmMax 8000
static Map3D1616 veMap;
static Map3D1616 afrMap;
#define tpMin 0
#define tpMax 100
// http://rusefi.com/math/t_charge.html
float getTCharge(int rpm, int tps, float coolantTemp, float airTemp) {
float minRpmKcurrentTPS = interpolate(tpMin, K_AT_MIN_RPM_MIN_TPS, tpMax,
K_AT_MIN_RPM_MAX_TPS, tps);
float maxRpmKcurrentTPS = interpolate(tpMin, K_AT_MAX_RPM_MIN_TPS, tpMax,
K_AT_MAX_RPM_MAX_TPS, tps);
float Tcharge_coff = interpolate(rpmMin, minRpmKcurrentTPS, rpmMax, maxRpmKcurrentTPS, rpm);
float Tcharge = coolantTemp * (1 - Tcharge_coff) + airTemp * Tcharge_coff;
return Tcharge;
}
/**
* is J/g*K
*/
#define GAS_R 0.28705
float sdMath(engine_configuration_s *engineConfiguration, float VE, float MAP, float AFR, float temp) {
float injectorFlowRate = cc_minute_to_gramm_second(engineConfiguration->injectorFlow);
float Vol = engineConfiguration->displacement / engineConfiguration->cylindersCount;
return (Vol * VE * MAP) / (AFR * injectorFlowRate * GAS_R * temp);
}
float getSpeedDensityFuel(Engine *engine) {
int rpm = engine->rpmCalculator->rpm();
float tps = getTPS();
float coolantC = getCoolantTemperature();
float intakeC = getIntakeAirTemperature();
float tChargeK = convertCelciusToKelvin(getTCharge(rpm, tps, coolantC, intakeC));
float MAP = getMap();
float VE = 0.8;//veMap.getValue(rpm)
float AFR = 14.7;
return sdMath(engine->engineConfiguration, VE, MAP, AFR, tChargeK);
}
void setDetaultVETable(engine_configuration_s *engineConfiguration) {
setTableBin(engineConfiguration->veRpmBins, FUEL_RPM_COUNT, 800, 7000);
veMap.setAll(0.8);
}
void initSpeedDensity(configuration_s *config) {
veMap.init(config->engineConfiguration->veTable);
afrMap.init(config->engineConfiguration->afrTable);
}

View File

@ -0,0 +1,23 @@
/**
* @file speed_density.h
*
* @date May 29, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef SPEED_DENSITY_H_
#define SPEED_DENSITY_H_
#include "engine_configuration.h"
#include "ec2.h"
float getTCharge(int rpm, int tps, float coolantTemp, float airTemp);
void setDetaultVETable(engine_configuration_s *engineConfiguration);
float sdMath(engine_configuration_s *engineConfiguration, float VE, float MAP, float AFR, float temp);
#define gramm_second_to_cc_minute(gs) ((gs) / 0.0119997981)
#define cc_minute_to_gramm_second(ccm) ((ccm) * 0.0119997981)
void initSpeedDensity(configuration_s *config);
#endif /* SPEED_DENSITY_H_ */

View File

@ -12,15 +12,6 @@
#include "main.h" #include "main.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
float getAfr(void); float getAfr(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif #endif

View File

@ -16,22 +16,19 @@ extern engine_configuration_s * engineConfiguration;
* *
* @returns kPa value * @returns kPa value
*/ */
float getMAPValueHonda_Denso183(float voltage) { static FastInterpolation denso183(0, -6.64, 5, 182.78);
return interpolate(0, -6.64, 5, 182.78, voltage);
}
float getMAPValueMPX_4250(float voltage) { static FastInterpolation mpx4250(0, 8, 5, 260);
return interpolate(0, 8, 5, 260, voltage);
}
float decodePressure(float voltage, air_pressure_sensor_config_s * config) { float decodePressure(float voltage, air_pressure_sensor_config_s * config) {
switch (config->sensorType) { switch (config->sensorType) {
case MT_CUSTOM: case MT_CUSTOM:
// todo: introduce 'FastInterpolation customMap'
return interpolate(0, config->Min, 5, config->Max, voltage); return interpolate(0, config->Min, 5, config->Max, voltage);
case MT_DENSO183: case MT_DENSO183:
return getMAPValueHonda_Denso183(voltage); return denso183.getValue(voltage);
case MT_MPX4250: case MT_MPX4250:
return getMAPValueMPX_4250(voltage); return mpx4250.getValue(voltage);
default: default:
firmwareError("Unknown MAP type: %d", config->sensorType); firmwareError("Unknown MAP type: %d", config->sensorType);
return NAN; return NAN;
@ -47,6 +44,9 @@ float getMapByVoltage(float voltage) {
return decodePressure(voltage, config); return decodePressure(voltage, config);
} }
/**
* @return Manifold Absolute Pressure, in kPa
*/
float getRawMap(void) { float getRawMap(void) {
float voltage = getVoltageDivided(engineConfiguration->map.sensor.hwChannel); float voltage = getVoltageDivided(engineConfiguration->map.sensor.hwChannel);
return getMapByVoltage(voltage); return getMapByVoltage(voltage);

View File

@ -6,6 +6,8 @@ extern "C"
{ {
#endif /* __cplusplus */ #endif /* __cplusplus */
#include "sensor_types.h"
/** /**
* @return Raw MAP sensor value right now * @return Raw MAP sensor value right now
*/ */
@ -17,8 +19,7 @@ float getBaroPressure(void);
float getMap(void); float getMap(void);
float getMapVoltage(void); float getMapVoltage(void);
float getMapByVoltage(float voltage); float getMapByVoltage(float voltage);
float getMAPValueHonda_Denso183(float volts); float decodePressure(float voltage, air_pressure_sensor_config_s * config);
float getMAPValueMPX_4250(float volts);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -14,6 +14,9 @@
#include "rusefi_enums.h" #include "rusefi_enums.h"
typedef struct { typedef struct {
/**
* kPa value at zero volts
*/
float Min; float Min;
float Max; float Max;
air_pressure_sensor_type_e sensorType; air_pressure_sensor_type_e sensorType;

View File

@ -1,9 +1,9 @@
CONTROLLERS_SENSORS_SRC = $(PROJECT_DIR)/controllers/sensors/tps.c \ CONTROLLERS_SENSORS_SRC = $(PROJECT_DIR)/controllers/sensors/allsensors.c \
$(PROJECT_DIR)/controllers/sensors/allsensors.c \
$(PROJECT_DIR)/controllers/sensors/maf.c \ $(PROJECT_DIR)/controllers/sensors/maf.c \
$(PROJECT_DIR)/controllers/sensors/map.c \
$(PROJECT_DIR)/controllers/sensors/ego.c \
$(PROJECT_DIR)/controllers/sensors/voltage.c $(PROJECT_DIR)/controllers/sensors/voltage.c
CONTROLLERS_SENSORS_SRC_CPP = $(PROJECT_DIR)/controllers/sensors/thermistors.cpp CONTROLLERS_SENSORS_SRC_CPP = $(PROJECT_DIR)/controllers/sensors/thermistors.cpp \
$(PROJECT_DIR)/controllers/sensors/map.cpp \
$(PROJECT_DIR)/controllers/sensors/tps.cpp \
$(PROJECT_DIR)/controllers/sensors/ego.cpp

View File

@ -52,7 +52,7 @@ float convertKelvinToC(float tempK) {
return tempK - KELV; return tempK - KELV;
} }
float convertCelciustoKelvin(float tempC) { float convertCelciusToKelvin(float tempC) {
return tempC + KELV; return tempC + KELV;
} }
@ -81,7 +81,7 @@ float getKelvinTemperature(float resistance, ThermistorConf *thermistor) {
float getResistance(Thermistor *thermistor) { float getResistance(Thermistor *thermistor) {
float voltage = getVoltageDivided(thermistor->channel); float voltage = getVoltageDivided(thermistor->channel);
chDbgCheck(thermistor->config != NULL, "config is null"); efiAssert(thermistor->config != NULL, "config is null", NAN);
float resistance = getR2InVoltageDividor(voltage, _5_VOLTS, thermistor->config->bias_resistor); float resistance = getR2InVoltageDividor(voltage, _5_VOLTS, thermistor->config->bias_resistor);
return resistance; return resistance;
} }

View File

@ -29,7 +29,7 @@ float getTempK(float resistance);
* converts Kelvin temperature into Celcius temperature * converts Kelvin temperature into Celcius temperature
*/ */
float convertKelvinToCelcius(float tempK); float convertKelvinToCelcius(float tempK);
float convertCelciustoKelvin(float tempC); float convertCelciusToKelvin(float tempC);
float convertCelciustoF(float tempC); float convertCelciustoF(float tempC);
float convertFtoCelcius(float tempF); float convertFtoCelcius(float tempF);

View File

@ -93,7 +93,7 @@ static float getPrimatyRawTPS(void) {
/* /*
* In case of dual TPS this function would return logical TPS position * In case of dual TPS this function would return logical TPS position
* *
* @return Current TPS position. 0 means idle and 100 means Wide Open Throttle * @return Current TPS position, percent of WOT. 0 means idle and 100 means Wide Open Throttle
*/ */
float getTPS(void) { float getTPS(void) {
// todo: if (config->isDualTps) // todo: if (config->isDualTps)

View File

@ -12,11 +12,6 @@
#include "global.h" #include "global.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
float getTPS(void); float getTPS(void);
int convertVoltageTo10bitADC(float voltage); int convertVoltageTo10bitADC(float voltage);
int getTPS10bitAdc(void); int getTPS10bitAdc(void);
@ -39,8 +34,4 @@ typedef struct {
void saveTpsState(time_t now, float curValue); void saveTpsState(time_t now, float curValue);
float getTpsRateOfChange(void); float getTpsRateOfChange(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif #endif

View File

@ -1,5 +1,5 @@
/** /**
* @file settings.c * @file settings.cpp
* @brief This file is about configuring engine via the human-readable protocol * @brief This file is about configuring engine via the human-readable protocol
* *
* @date Dec 30, 2012 * @date Dec 30, 2012
@ -18,6 +18,7 @@
#include "tps.h" #include "tps.h"
#include "ec2.h" #include "ec2.h"
#include "map.h" #include "map.h"
#include "trigger_decoder.h"
#if EFI_PROD_CODE #if EFI_PROD_CODE
#include "rusefi.h" #include "rusefi.h"
@ -91,11 +92,32 @@ const char* getConfigurationName(engine_configuration_s *engineConfiguration) {
return "Ford Escort GT"; return "Ford Escort GT";
case CITROEN_TU3JP: case CITROEN_TU3JP:
return "Citroen TU3JP"; return "Citroen TU3JP";
case ROVER_V8:
return "Rover v8";
default: default:
return NULL; return NULL;
} }
} }
static const char * pinModeToString(pin_output_mode_e mode) {
switch (mode) {
case OM_DEFAULT:
return "default";
case OM_INVERTED:
return "inverted";
case OM_OPENDRAIN:
return "open drain";
case OM_OPENDRAIN_INVERTED:
return "open drain inverted";
default:
return "unexpected";
}
}
static const char * boolToString(bool_t value) {
return value ? "Yes" : "No";
}
/** /**
* @brief Prints current engine configuration to human-readable console. * @brief Prints current engine configuration to human-readable console.
*/ */
@ -147,38 +169,41 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
// scheduleMsg(&logger, "crankingRpm: %d", engineConfiguration->crankingSettings.crankingRpm); // scheduleMsg(&logger, "crankingRpm: %d", engineConfiguration->crankingSettings.crankingRpm);
scheduleMsg(&logger, "idlePinMode: %d", boardConfiguration->idleValvePinMode); scheduleMsg(&logger, "idlePinMode: %s", pinModeToString(boardConfiguration->idleValvePinMode));
scheduleMsg(&logger, "malfunctionIndicatorPinMode: %d", boardConfiguration->malfunctionIndicatorPinMode); scheduleMsg(&logger, "malfunctionIndicatorPinMode: %s", pinModeToString(boardConfiguration->malfunctionIndicatorPinMode));
scheduleMsg(&logger, "analogInputDividerCoefficient: %f", engineConfiguration->analogInputDividerCoefficient); scheduleMsg(&logger, "analogInputDividerCoefficient: %f", engineConfiguration->analogInputDividerCoefficient);
scheduleMsg(&logger, "needSecondTriggerInput: %d", engineConfiguration->needSecondTriggerInput); scheduleMsg(&logger, "needSecondTriggerInput: %s", boolToString(engineConfiguration->needSecondTriggerInput));
#if EFI_PROD_CODE #if EFI_PROD_CODE
scheduleMsg(&logger, "idleValvePin: %s", hwPortname(boardConfiguration->idleValvePin)); scheduleMsg(&logger, "idleValvePin: %s", hwPortname(boardConfiguration->idleValvePin));
scheduleMsg(&logger, "fuelPumpPin: mode %d @ %s", boardConfiguration->fuelPumpPinMode, scheduleMsg(&logger, "fuelPumpPin: mode %s @ %s", pinModeToString(boardConfiguration->fuelPumpPinMode),
hwPortname(boardConfiguration->fuelPumpPin)); hwPortname(boardConfiguration->fuelPumpPin));
scheduleMsg(&logger, "injectionPins: mode %d", boardConfiguration->injectionPinMode); scheduleMsg(&logger, "injectionPins: mode %s", pinModeToString(boardConfiguration->injectionPinMode));
for (int i = 0; i < engineConfiguration->cylindersCount; i++) { for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
brain_pin_e brainPin = boardConfiguration->injectionPins[i]; brain_pin_e brainPin = boardConfiguration->injectionPins[i];
scheduleMsg(&logger, "injection %d @ %s", i, hwPortname(brainPin)); scheduleMsg(&logger, "injection %d @ %s", i, hwPortname(brainPin));
} }
scheduleMsg(&logger, "ignitionPins: mode %d", boardConfiguration->ignitionPinMode); scheduleMsg(&logger, "ignitionPins: mode %s", pinModeToString(boardConfiguration->ignitionPinMode));
// todo: calculate coils count based on ignition mode // todo: calculate coils count based on ignition mode
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
brain_pin_e brainPin = boardConfiguration->ignitionPins[i]; brain_pin_e brainPin = boardConfiguration->ignitionPins[i];
scheduleMsg(&logger, "ignition %d @ %s", i, hwPortname(brainPin)); scheduleMsg(&logger, "ignition %d @ %s", i, hwPortname(brainPin));
} }
scheduleMsg(&logger, "primary trigger simulator: %s %d", hwPortname(boardConfiguration->triggerSimulatorPins[0]), scheduleMsg(&logger, "primary trigger simulator: %s %s", hwPortname(boardConfiguration->triggerSimulatorPins[0]),
boardConfiguration->triggerSimulatorPinModes[0]); pinModeToString(boardConfiguration->triggerSimulatorPinModes[0]));
scheduleMsg(&logger, "secondary trigger simulator: %s %d", hwPortname(boardConfiguration->triggerSimulatorPins[1]), scheduleMsg(&logger, "secondary trigger simulator: %s %s", hwPortname(boardConfiguration->triggerSimulatorPins[1]),
boardConfiguration->triggerSimulatorPinModes[1]); pinModeToString(boardConfiguration->triggerSimulatorPinModes[1]));
scheduleMsg(&logger, "primary trigger input: %s", hwPortname(boardConfiguration->primaryTriggerInputPin));
#endif /* EFI_PROD_CODE */ #endif /* EFI_PROD_CODE */
scheduleMsg(&logger, "isInjectionEnabledFlag %d", engineConfiguration2->isInjectionEnabledFlag); scheduleMsg(&logger, "isInjectionEnabledFlag %s", boolToString(engineConfiguration2->isInjectionEnabledFlag));
// appendPrintf(&logger, DELIMETER); // appendPrintf(&logger, DELIMETER);
// scheduleLogging(&logger); // scheduleLogging(&logger);
@ -197,8 +222,9 @@ static void setTimingMode(int value) {
} }
void setEngineType(int value) { void setEngineType(int value) {
engineConfiguration->engineType = (engine_type_e)value; engineConfiguration->engineType = (engine_type_e) value;
resetConfigurationExt(&logger, (engine_type_e) value, engineConfiguration, engineConfiguration2, boardConfiguration); resetConfigurationExt(&logger, (engine_type_e) value, engineConfiguration, engineConfiguration2,
boardConfiguration);
#if EFI_INTERNAL_FLASH #if EFI_INTERNAL_FLASH
writeToFlash(); writeToFlash();
// scheduleReset(); // scheduleReset();
@ -259,9 +285,9 @@ static void setRpmMultiplier(int value) {
doPrintConfiguration(); doPrintConfiguration();
} }
static uint8_t pinNameBuffer[16]; static char pinNameBuffer[16];
static void printThermistor(char *msg, Thermistor *thermistor) { static void printThermistor(const char *msg, Thermistor *thermistor) {
int adcChannel = thermistor->channel; int adcChannel = thermistor->channel;
float voltage = getVoltageDivided(adcChannel); float voltage = getVoltageDivided(adcChannel);
float r = getResistance(thermistor); float r = getResistance(thermistor);
@ -278,17 +304,15 @@ static void printThermistor(char *msg, Thermistor *thermistor) {
static void printMAPInfo(void) { static void printMAPInfo(void) {
#if EFI_PROD_CODE #if EFI_PROD_CODE
scheduleMsg(&logger, "map type=%d raw=%f MAP=%f", engineConfiguration->map.sensor.sensorType, getRawMap(), getMap()); scheduleMsg(&logger, "map type=%d raw=%f MAP=%f", engineConfiguration->map.sensor.sensorType, getRawMap(),
getMap());
if (engineConfiguration->map.sensor.sensorType == MT_CUSTOM) { if (engineConfiguration->map.sensor.sensorType == MT_CUSTOM) {
scheduleMsg(&logger, "min=%f max=%f", engineConfiguration->map.sensor.Min, scheduleMsg(&logger, "min=%f max=%f", engineConfiguration->map.sensor.Min, engineConfiguration->map.sensor.Max);
engineConfiguration->map.sensor.Max);
} }
scheduleMsg(&logger, "baro type=%d value=%f", engineConfiguration->baroSensor.sensorType, getBaroPressure()); scheduleMsg(&logger, "baro type=%d value=%f", engineConfiguration->baroSensor.sensorType, getBaroPressure());
if (engineConfiguration->baroSensor.sensorType == MT_CUSTOM) { if (engineConfiguration->baroSensor.sensorType == MT_CUSTOM) {
scheduleMsg(&logger, "min=%f max=%f", engineConfiguration->baroSensor.Min, scheduleMsg(&logger, "min=%f max=%f", engineConfiguration->baroSensor.Min, engineConfiguration->baroSensor.Max);
engineConfiguration->baroSensor.Max);
} }
#endif #endif
} }
@ -388,6 +412,13 @@ static void setIgnitionMode(int value) {
doPrintConfiguration(); doPrintConfiguration();
} }
static void setTotalToothCount(int value) {
engineConfiguration->triggerConfig.totalToothCount = value;
initializeTriggerShape(&logger, engineConfiguration, engineConfiguration2);
incrementGlobalConfigurationVersion();
doPrintConfiguration();
}
static void setCrankingChargeAngle(float value) { static void setCrankingChargeAngle(float value) {
engineConfiguration->crankingChargeAngle = value; engineConfiguration->crankingChargeAngle = value;
incrementGlobalConfigurationVersion(); incrementGlobalConfigurationVersion();
@ -500,5 +531,6 @@ void initSettings(void) {
addConsoleAction("enable_injection", enableInjection); addConsoleAction("enable_injection", enableInjection);
addConsoleAction("disable_injection", disableInjection); addConsoleAction("disable_injection", disableInjection);
addConsoleActionI("set_total_tooth_count", setTotalToothCount);
} }

View File

@ -17,9 +17,6 @@ extern "C"
void initSettings(void); void initSettings(void);
void pokeControl(void); void pokeControl(void);
void setEngineType(int value); void setEngineType(int value);
int getInjectionPeriod(void);
int getInjectionOffset(void);
int getInjectionDivider(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

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