From fb2d080fbbcea3a91e598b4ea8837a230de6a319 Mon Sep 17 00:00:00 2001 From: Shlomo Hecht Date: Tue, 6 Mar 2018 12:09:02 +0200 Subject: A new forlder for embedded software in our common structure --- Software/Embedded_SW/Embedded/.ccsproject | 15 + Software/Embedded_SW/Embedded/.cproject | 283 ++ Software/Embedded_SW/Embedded/.project | 34 + .../.settings/org.eclipse.cdt.codan.core.prefs | 3 + .../.settings/org.eclipse.cdt.debug.core.prefs | 2 + Software/Embedded_SW/Embedded/.xdchelp | 0 .../Embedded/Common/Software_CRC/sw_crc.c | 723 ++++ .../Embedded/Common/Software_CRC/sw_crc.h | 40 + .../Common/Sys_PinOut_Config/MCU_MAIN_pinout.c | 996 ++++++ .../Common/Sys_PinOut_Config/MCU_MAIN_pinout.h | 74 + .../Embedded/Common/Sys_PinOut_Config/Pin.c | 621 ++++ .../Embedded/Common/Sys_PinOut_Config/Pin.h | 43 + .../Embedded/Common/Sys_PinOut_Config/Pin_config.c | 51 + .../Embedded/Common/Sys_PinOut_Config/Pin_config.h | 14 + .../Embedded_SW/Embedded/Common/Utilities/Update.c | 98 + .../Embedded_SW/Embedded/Common/Utilities/Utils.c | 245 ++ .../Embedded_SW/Embedded/Common/Utilities/Utils.h | 33 + .../Embedded/Common/Utilities/ustdlib.c | 1825 ++++++++++ .../Embedded/Common/protobuf-c/person-pb-c.c | 227 ++ .../Embedded/Common/protobuf-c/person-pb-c.h | 112 + .../Embedded/Common/protobuf-c/protobuf-c.c | 3642 ++++++++++++++++++++ .../Embedded/Common/protobuf-c/protobuf-c.h | 1106 ++++++ .../Embedded/Common/report/distributor.c | 851 +++++ .../Embedded/Common/report/distributor.h | 94 + .../Embedded_SW/Embedded/Common/report/filter.c | 526 +++ .../Embedded_SW/Embedded/Common/report/filter.h | 74 + .../Embedded_SW/Embedded/Common/report/report.h | 593 ++++ .../Embedded/Common/report/reportInit.c | 161 + .../Embedded/Drivers/ADC_Sampling/ADC.c | 317 ++ .../Embedded/Drivers/ADC_Sampling/ADC.h | 49 + .../Embedded/Drivers/Flash_Memory/Flash_Memory.c | 488 +++ .../Embedded/Drivers/Flash_Memory/Flash_Memory.h | 6 + .../Embedded_SW/Embedded/Drivers/Heater/Heater.c | 60 + .../Embedded_SW/Embedded/Drivers/Heater/Heater.h | 7 + .../Embedded/Drivers/I2C_Communication/I2C.c | 127 + .../Embedded/Drivers/I2C_Communication/I2C.h | 31 + .../Embedded/Drivers/On_Chip_Flash/Flashstore.c | 655 ++++ .../Embedded/Drivers/On_Chip_Flash/Flashstore.h | 136 + .../Embedded/Drivers/Peripheral_GPIO/GPIO.c | 130 + .../Embedded/Drivers/Peripheral_GPIO/GPIO.h | 37 + .../Embedded/Drivers/twine_graphicslib/.ccsproject | 13 + .../Embedded/Drivers/twine_graphicslib/.cproject | 141 + .../Embedded/Drivers/twine_graphicslib/.project | 45 + .../.settings/org.eclipse.cdt.codan.core.prefs | 3 + .../.settings/org.eclipse.cdt.debug.core.prefs | 2 + .../.settings/org.eclipse.core.resources.prefs | 8 + .../Drivers/twine_graphicslib/graphics_adapter.c | 109 + .../Drivers/twine_graphicslib/graphics_adapter.h | 32 + .../Embedded/Drivers/twine_usblib/.ccsproject | 14 + .../Embedded/Drivers/twine_usblib/.cproject | 147 + .../Embedded/Drivers/twine_usblib/.project | 40 + .../.settings/org.eclipse.cdt.codan.core.prefs | 3 + .../.settings/org.eclipse.cdt.debug.core.prefs | 2 + .../.settings/org.eclipse.core.resources.prefs | 8 + .../Drivers/twine_usblib/usb_serial_adapter.c | 542 +++ .../Drivers/twine_usblib/usb_serial_adapter.h | 73 + .../Drivers/twine_usblib/usb_serial_buffer.c | 32 + .../Drivers/twine_usblib/usb_serial_buffer.h | 20 + .../Drivers/twine_usblib/usb_serial_structs.c | 211 ++ .../Drivers/twine_usblib/usb_serial_structs.h | 49 + Software/Embedded_SW/Embedded/Embedded.cfg | 205 ++ Software/Embedded_SW/Embedded/Include.h | 53 + Software/Embedded_SW/Embedded/Main.c | 92 + .../Embedded_SW/Embedded/Modules/Control/PIDAlgo.c | 39 + .../Embedded_SW/Embedded/Modules/Control/PIDAlgo.h | 18 + .../Embedded_SW/Embedded/Modules/Control/control.c | 333 ++ .../Embedded_SW/Embedded/Modules/Control/control.h | 30 + .../Embedded/Modules/General/GeneralHardware.c | 348 ++ .../Embedded/Modules/General/GeneralHardware.h | 313 ++ .../Embedded_SW/Embedded/Modules/General/process.c | 121 + .../Embedded_SW/Embedded/Modules/General/process.h | 16 + .../Embedded_SW/Embedded/Modules/Heaters/Heaters.h | 62 + .../Embedded/Modules/Heaters/Heaters_bit.c | 0 .../Embedded/Modules/Heaters/Heaters_ex.h | 9 + .../Embedded/Modules/Heaters/Heaters_init.c | 154 + .../Embedded/Modules/Heaters/Heaters_maint.c | 0 .../Embedded/Modules/Heaters/Heaters_print.c | 247 ++ Software/Embedded_SW/Embedded/Modules/IDS/IDS.h | 25 + .../Embedded_SW/Embedded/Modules/IDS/IDS_BIT.c | 0 Software/Embedded_SW/Embedded/Modules/IDS/IDS_ex.h | 0 .../Embedded_SW/Embedded/Modules/IDS/IDS_init.c | 46 + .../Embedded_SW/Embedded/Modules/IDS/IDS_maint.c | 0 .../Embedded_SW/Embedded/Modules/IDS/IDS_print.c | 43 + .../Embedded/Modules/IDS/MixerHandler.c | 37 + .../Embedded/Modules/IDS/MixerHandler.h | 17 + .../Embedded/Modules/Stubs_Handler/Calculate.c | 39 + .../Embedded/Modules/Stubs_Handler/Calculate.h | 8 + .../Embedded/Modules/Stubs_Handler/Container.c | 125 + .../Embedded/Modules/Stubs_Handler/Container.h | 7 + .../Embedded/Modules/Stubs_Handler/DataDef.h | 71 + .../Embedded/Modules/Stubs_Handler/Progress.c | 48 + .../Embedded/Modules/Stubs_Handler/Progress.h | 7 + .../Modules/Stubs_Handler/Stub_Cartridge.c | 128 + .../Modules/Stubs_Handler/Stub_Cartridge.h | 9 + .../Modules/Stubs_Handler/Stub_Dispenser.c | 72 + .../Modules/Stubs_Handler/Stub_Dispenser.h | 9 + .../Embedded/Modules/Stubs_Handler/Stub_ExtFlash.c | 160 + .../Embedded/Modules/Stubs_Handler/Stub_ExtFlash.h | 8 + .../Embedded/Modules/Stubs_Handler/Stub_GPIO.c | 947 +++++ .../Embedded/Modules/Stubs_Handler/Stub_GPIO.h | 12 + .../Embedded/Modules/Stubs_Handler/Stub_Heater.c | 74 + .../Embedded/Modules/Stubs_Handler/Stub_Heater.h | 6 + .../Modules/Stubs_Handler/Stub_MotorEncoder.c | 84 + .../Modules/Stubs_Handler/Stub_MotorEncoder.h | 6 + .../Modules/Stubs_Handler/Stub_OptLimitSwitch.c | 70 + .../Modules/Stubs_Handler/Stub_OptLimitSwitch.h | 6 + .../Embedded/Modules/Stubs_Handler/Stub_Status.c | 58 + .../Embedded/Modules/Stubs_Handler/Stub_Status.h | 3 + .../Modules/Stubs_Handler/Stub_SteperMotor.c | 79 + .../Modules/Stubs_Handler/Stub_SteperMotor.h | 7 + .../Embedded/Modules/Stubs_Handler/Stub_Valve.c | 60 + .../Embedded/Modules/Stubs_Handler/Stub_Valve.h | 6 + .../Embedded/Modules/Stubs_Handler/User_Leds.c | 68 + .../Embedded/Modules/Stubs_Handler/User_Leds.h | 23 + .../Embedded_SW/Embedded/Modules/Thread/Thread.h | 55 + .../Embedded/Modules/Thread/Thread_BIT.c | 0 .../Embedded/Modules/Thread/Thread_ex.h | 0 .../Embedded/Modules/Thread/Thread_init.c | 94 + .../Embedded/Modules/Thread/Thread_maint.c | 0 .../Embedded/Modules/Thread/Thread_print.c | 326 ++ .../Embedded_SW/Embedded/Modules/Waste/Waste.h | 0 .../Embedded_SW/Embedded/Modules/Waste/Waste_BIT.c | 0 .../Embedded_SW/Embedded/Modules/Waste/Waste_ex.h | 0 .../Embedded/Modules/Waste/Waste_init.c | 0 .../Embedded/Modules/Waste/Waste_maint.c | 0 .../Embedded/Modules/Waste/Waste_print.c | 0 .../Embedded/StateMachines/Printing/JobSTM.c | 341 ++ .../Embedded/StateMachines/Printing/PrintingSTM.c | 274 ++ .../Embedded/StateMachines/Printing/PrintingSTM.h | 97 + Software/Embedded_SW/Embedded/src/.exclude | 1 + Software/Embedded_SW/Embedded/src/makefile.libs | 62 + Software/Embedded_SW/Embedded/src/sysbios/makefile | 96 + .../Embedded_SW/Embedded/src/sysbios/sysbios.aem4f | Bin 0 -> 1751322 bytes .../targetConfigs/Tiva TM4C129XNCZAD.ccxml | 13 + .../Embedded_SW/Embedded/targetConfigs/readme.txt | 9 + Software/Embedded_SW/Embedded/tm4c129xnczad.cmd | 45 + 136 files changed, 21844 insertions(+) create mode 100644 Software/Embedded_SW/Embedded/.ccsproject create mode 100644 Software/Embedded_SW/Embedded/.cproject create mode 100644 Software/Embedded_SW/Embedded/.project create mode 100644 Software/Embedded_SW/Embedded/.settings/org.eclipse.cdt.codan.core.prefs create mode 100644 Software/Embedded_SW/Embedded/.settings/org.eclipse.cdt.debug.core.prefs create mode 100644 Software/Embedded_SW/Embedded/.xdchelp create mode 100644 Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.c create mode 100644 Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.h create mode 100644 Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.c create mode 100644 Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.h create mode 100644 Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.c create mode 100644 Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.h create mode 100644 Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.c create mode 100644 Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.h create mode 100644 Software/Embedded_SW/Embedded/Common/Utilities/Update.c create mode 100644 Software/Embedded_SW/Embedded/Common/Utilities/Utils.c create mode 100644 Software/Embedded_SW/Embedded/Common/Utilities/Utils.h create mode 100644 Software/Embedded_SW/Embedded/Common/Utilities/ustdlib.c create mode 100644 Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.c create mode 100644 Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.h create mode 100644 Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.c create mode 100644 Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.h create mode 100644 Software/Embedded_SW/Embedded/Common/report/distributor.c create mode 100644 Software/Embedded_SW/Embedded/Common/report/distributor.h create mode 100644 Software/Embedded_SW/Embedded/Common/report/filter.c create mode 100644 Software/Embedded_SW/Embedded/Common/report/filter.h create mode 100644 Software/Embedded_SW/Embedded/Common/report/report.h create mode 100644 Software/Embedded_SW/Embedded/Common/report/reportInit.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/ADC_Sampling/ADC.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/ADC_Sampling/ADC.h create mode 100644 Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.h create mode 100644 Software/Embedded_SW/Embedded/Drivers/Heater/Heater.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/Heater/Heater.h create mode 100644 Software/Embedded_SW/Embedded/Drivers/I2C_Communication/I2C.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/I2C_Communication/I2C.h create mode 100644 Software/Embedded_SW/Embedded/Drivers/On_Chip_Flash/Flashstore.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/On_Chip_Flash/Flashstore.h create mode 100644 Software/Embedded_SW/Embedded/Drivers/Peripheral_GPIO/GPIO.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/Peripheral_GPIO/GPIO.h create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.ccsproject create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.cproject create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.project create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.cdt.codan.core.prefs create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.cdt.debug.core.prefs create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.core.resources.prefs create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/graphics_adapter.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/graphics_adapter.h create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/.ccsproject create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/.cproject create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/.project create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.cdt.codan.core.prefs create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.cdt.debug.core.prefs create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.core.resources.prefs create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_adapter.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_adapter.h create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_buffer.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_buffer.h create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_structs.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_structs.h create mode 100644 Software/Embedded_SW/Embedded/Embedded.cfg create mode 100644 Software/Embedded_SW/Embedded/Include.h create mode 100644 Software/Embedded_SW/Embedded/Main.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Control/PIDAlgo.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Control/PIDAlgo.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Control/control.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Control/control.h create mode 100644 Software/Embedded_SW/Embedded/Modules/General/GeneralHardware.c create mode 100644 Software/Embedded_SW/Embedded/Modules/General/GeneralHardware.h create mode 100644 Software/Embedded_SW/Embedded/Modules/General/process.c create mode 100644 Software/Embedded_SW/Embedded/Modules/General/process.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Heaters/Heaters.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_bit.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_ex.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_init.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_maint.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_print.c create mode 100644 Software/Embedded_SW/Embedded/Modules/IDS/IDS.h create mode 100644 Software/Embedded_SW/Embedded/Modules/IDS/IDS_BIT.c create mode 100644 Software/Embedded_SW/Embedded/Modules/IDS/IDS_ex.h create mode 100644 Software/Embedded_SW/Embedded/Modules/IDS/IDS_init.c create mode 100644 Software/Embedded_SW/Embedded/Modules/IDS/IDS_maint.c create mode 100644 Software/Embedded_SW/Embedded/Modules/IDS/IDS_print.c create mode 100644 Software/Embedded_SW/Embedded/Modules/IDS/MixerHandler.c create mode 100644 Software/Embedded_SW/Embedded/Modules/IDS/MixerHandler.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Calculate.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Calculate.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Container.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Container.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/DataDef.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Progress.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Progress.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Cartridge.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Cartridge.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Dispenser.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Dispenser.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_ExtFlash.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_ExtFlash.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_GPIO.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_GPIO.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Heater.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Heater.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_MotorEncoder.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_MotorEncoder.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_OptLimitSwitch.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_OptLimitSwitch.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Status.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Status.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_SteperMotor.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_SteperMotor.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Valve.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Valve.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/User_Leds.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Stubs_Handler/User_Leds.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Thread/Thread.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Thread/Thread_BIT.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Thread/Thread_ex.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Thread/Thread_init.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Thread/Thread_maint.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Thread/Thread_print.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Waste/Waste.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Waste/Waste_BIT.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Waste/Waste_ex.h create mode 100644 Software/Embedded_SW/Embedded/Modules/Waste/Waste_init.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Waste/Waste_maint.c create mode 100644 Software/Embedded_SW/Embedded/Modules/Waste/Waste_print.c create mode 100644 Software/Embedded_SW/Embedded/StateMachines/Printing/JobSTM.c create mode 100644 Software/Embedded_SW/Embedded/StateMachines/Printing/PrintingSTM.c create mode 100644 Software/Embedded_SW/Embedded/StateMachines/Printing/PrintingSTM.h create mode 100644 Software/Embedded_SW/Embedded/src/.exclude create mode 100644 Software/Embedded_SW/Embedded/src/makefile.libs create mode 100644 Software/Embedded_SW/Embedded/src/sysbios/makefile create mode 100644 Software/Embedded_SW/Embedded/src/sysbios/sysbios.aem4f create mode 100644 Software/Embedded_SW/Embedded/targetConfigs/Tiva TM4C129XNCZAD.ccxml create mode 100644 Software/Embedded_SW/Embedded/targetConfigs/readme.txt create mode 100644 Software/Embedded_SW/Embedded/tm4c129xnczad.cmd (limited to 'Software/Embedded_SW/Embedded') diff --git a/Software/Embedded_SW/Embedded/.ccsproject b/Software/Embedded_SW/Embedded/.ccsproject new file mode 100644 index 000000000..1e9e32a5f --- /dev/null +++ b/Software/Embedded_SW/Embedded/.ccsproject @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/Software/Embedded_SW/Embedded/.cproject b/Software/Embedded_SW/Embedded/.cproject new file mode 100644 index 000000000..ea86340e2 --- /dev/null +++ b/Software/Embedded_SW/Embedded/.cproject @@ -0,0 +1,283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Embedded_SW/Embedded/.project b/Software/Embedded_SW/Embedded/.project new file mode 100644 index 000000000..1d1a99671 --- /dev/null +++ b/Software/Embedded_SW/Embedded/.project @@ -0,0 +1,34 @@ + + + Embedded + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.rtsc.xdctools.buildDefinitions.XDC.xdcNature + com.ti.ccstudio.core.ccsNature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + TIVAWARE_DRIVERS + file:/C:/ti/TivaWare_C_Series-2.1.4.178 + + + diff --git a/Software/Embedded_SW/Embedded/.settings/org.eclipse.cdt.codan.core.prefs b/Software/Embedded_SW/Embedded/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 000000000..f653028c5 --- /dev/null +++ b/Software/Embedded_SW/Embedded/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +inEditor=false +onBuild=false diff --git a/Software/Embedded_SW/Embedded/.settings/org.eclipse.cdt.debug.core.prefs b/Software/Embedded_SW/Embedded/.settings/org.eclipse.cdt.debug.core.prefs new file mode 100644 index 000000000..2adc7b1dd --- /dev/null +++ b/Software/Embedded_SW/Embedded/.settings/org.eclipse.cdt.debug.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.debug.core.toggleBreakpointModel=com.ti.ccstudio.debug.CCSBreakpointMarker diff --git a/Software/Embedded_SW/Embedded/.xdchelp b/Software/Embedded_SW/Embedded/.xdchelp new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.c b/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.c new file mode 100644 index 000000000..76f9c0398 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.c @@ -0,0 +1,723 @@ + +//***************************************************************************** +// +//! \addtogroup sw_crc_api +//! @{ +// +//***************************************************************************** +#include "Common/Software_CRC/sw_crc.h" + +//***************************************************************************** +// +// The CRC table for the polynomial C(x) = x^8 + x^2 + x + 1 (CRC-8-CCITT). +// +//***************************************************************************** +static const uint8_t g_pui8Crc8CCITT[256] = +{ + 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, + 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, + 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, + 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, + 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, + 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, + 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, + 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, + 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, + 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, + 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, + 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, + 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, + 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, + 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, + 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, + 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, + 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, + 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, + 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, + 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, + 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, + 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, + 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, + 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, + 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, + 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, + 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, + 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, + 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, + 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, + 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 +}; + +//***************************************************************************** +// +// The CRC-16 table for the polynomial C(x) = x^16 + x^15 + x^2 + 1 (standard +// CRC-16, also known as CRC-16-IBM and CRC-16-ANSI). +// +//***************************************************************************** +static const uint16_t g_pui16Crc16[256] = +{ + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + +//***************************************************************************** +// +// The CRC-32 table for the polynomial C(x) = x^32 + x^26 + x^23 + x^22 + +// x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 (standard +// CRC32 as used in Ethernet, MPEG-2, PNG, etc.). +// +//***************************************************************************** +static const uint32_t g_pui32Crc32[] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; + +//***************************************************************************** +// +// This macro executes one iteration of the CRC-8-CCITT. +// +//***************************************************************************** +#define CRC8_ITER(crc, data) g_pui8Crc8CCITT[(uint8_t)((crc) ^ (data))] + +//***************************************************************************** +// +// This macro executes one iteration of the CRC-16. +// +//***************************************************************************** +#define CRC16_ITER(crc, data) (((crc) >> 8) ^ \ + g_pui16Crc16[(uint8_t)((crc) ^ (data))]) + +//***************************************************************************** +// +// This macro executes one iteration of the CRC-32. +// +//***************************************************************************** +#define CRC32_ITER(crc, data) (((crc) >> 8) ^ \ + g_pui32Crc32[(uint8_t)((crc & 0xFF) ^ \ + (data))]) + +//***************************************************************************** +// +//! Calculates the CRC-8-CCITT of an array of bytes. +//! +//! \param ui8Crc is the starting CRC-8-CCITT value. +//! \param pui8Data is a pointer to the data buffer. +//! \param ui32Count is the number of bytes in the data buffer. +//! +//! This function is used to calculate the CRC-8-CCITT of the input buffer. +//! The CRC-8-CCITT is computed in a running fashion, meaning that the entire +//! data block that is to have its CRC-8-CCITT computed does not need to be +//! supplied all at once. If the input buffer contains the entire block of +//! data, then \b ui8Crc should be set to 0. If, however, the entire block of +//! data is not available, then \b ui8Crc should be set to 0 for the first +//! portion of the data, and then the returned value should be passed back in +//! as \b ui8Crc for the next portion of the data. +//! +//! For example, to compute the CRC-8-CCITT of a block that has been split into +//! three pieces, use the following: +//! +//! \verbatim +//! ui8Crc = Crc8CCITT(0, pui8Data1, ui32Len1); +//! ui8Crc = Crc8CCITT(ui8Crc, pui8Data2, ui32Len2); +//! ui8Crc = Crc8CCITT(ui8Crc, pui8Data3, ui32Len3); +//! \endverbatim +//! +//! Computing a CRC-8-CCITT in a running fashion is useful in cases where the +//! data is arriving via a serial link (for example) and is therefore not all +//! available at one time. +//! +//! \return The CRC-8-CCITT of the input data. +// +//***************************************************************************** +uint8_t +Crc8CCITT(uint8_t ui8Crc, const uint8_t *pui8Data, uint32_t ui32Count) +{ + uint32_t ui32Temp; + + // + // If the data buffer is not 16 bit-aligned, then perform a single step of + // the CRC to make it 16 bit-aligned. + // + if((uint32_t)pui8Data & 1) + { + // + // Perform the CRC on this input byte. + // + ui8Crc = CRC8_ITER(ui8Crc, *pui8Data); + + // + // Skip this input byte. + // + pui8Data++; + ui32Count--; + } + + // + // If the data buffer is not word-aligned and there are at least two bytes + // of data left, then perform two steps of the CRC to make it word-aligned. + // + if(((uint32_t)pui8Data & 2) && (ui32Count > 1)) + { + // + // Read the next 16 bits. + // + ui32Temp = *(uint16_t *)pui8Data; + + // + // Perform the CRC on these two bytes. + // + ui8Crc = CRC8_ITER(ui8Crc, ui32Temp); + ui8Crc = CRC8_ITER(ui8Crc, ui32Temp >> 8); + + // + // Skip these input bytes. + // + pui8Data += 2; + ui32Count -= 2; + } + + // + // While there is at least a word remaining in the data buffer, perform + // four steps of the CRC to consume a word. + // + while(ui32Count > 3) + { + // + // Read the next word. + // + ui32Temp = *(uint32_t *)pui8Data; + + // + // Perform the CRC on these four bytes. + // + ui8Crc = CRC8_ITER(ui8Crc, ui32Temp); + ui8Crc = CRC8_ITER(ui8Crc, ui32Temp >> 8); + ui8Crc = CRC8_ITER(ui8Crc, ui32Temp >> 16); + ui8Crc = CRC8_ITER(ui8Crc, ui32Temp >> 24); + + // + // Skip these input bytes. + // + pui8Data += 4; + ui32Count -= 4; + } + + // + // If there are 16 bits left in the input buffer, then perform two steps of + // the CRC. + // + if(ui32Count > 1) + { + // + // Read the 16 bits. + // + ui32Temp = *(uint16_t *)pui8Data; + + // + // Perform the CRC on these two bytes. + // + ui8Crc = CRC8_ITER(ui8Crc, ui32Temp); + ui8Crc = CRC8_ITER(ui8Crc, ui32Temp >> 8); + + // + // Skip these input bytes. + // + pui8Data += 2; + ui32Count -= 2; + } + + // + // If there is a final byte remaining in the input buffer, then perform a + // single step of the CRC. + // + if(ui32Count != 0) + { + ui8Crc = CRC8_ITER(ui8Crc, *pui8Data); + } + + // + // Return the resulting CRC-8-CCITT value. + // + return(ui8Crc); +} + +//***************************************************************************** +// +//! Calculates the CRC-16 of an array of bytes. +//! +//! \param ui16Crc is the starting CRC-16 value. +//! \param pui8Data is a pointer to the data buffer. +//! \param ui32Count is the number of bytes in the data buffer. +//! +//! This function is used to calculate the CRC-16 of the input buffer. The +//! CRC-16 is computed in a running fashion, meaning that the entire data block +//! that is to have its CRC-16 computed does not need to be supplied all at +//! once. If the input buffer contains the entire block of data, then +//! \b ui16Crc should be set to 0. If, however, the entire block of data is +//! not available, then \b ui16Crc should be set to 0 for the first portion of +//! the data, and then the returned value should be passed back in as +//! \b ui16Crc for the next portion of the data. +//! +//! For example, to compute the CRC-16 of a block that has been split into +//! three pieces, use the following: +//! +//! \verbatim +//! ui16Crc = Crc16(0, pui8Data1, ui32Len1); +//! ui16Crc = Crc16(ui16Crc, pui8Data2, ui32Len2); +//! ui16Crc = Crc16(ui16Crc, pui8Data3, ui32Len3); +//! \endverbatim +//! +//! Computing a CRC-16 in a running fashion is useful in cases where the data +//! is arriving via a serial link (for example) and is therefore not all +//! available at one time. +//! +//! \return The CRC-16 of the input data. +// +//***************************************************************************** +uint16_t +Crc16(uint16_t ui16Crc, const uint8_t *pui8Data, uint32_t ui32Count) +{ + uint32_t ui32Temp; + + // + // If the data buffer is not 16 bit-aligned, then perform a single step of + // the CRC to make it 16 bit-aligned. + // + if((uint32_t)pui8Data & 1) + { + // + // Perform the CRC on this input byte. + // + ui16Crc = CRC16_ITER(ui16Crc, *pui8Data); + + // + // Skip this input byte. + // + pui8Data++; + ui32Count--; + } + + // + // If the data buffer is not word-aligned and there are at least two bytes + // of data left, then perform two steps of the CRC to make it word-aligned. + // + if(((uint32_t)pui8Data & 2) && (ui32Count > 1)) + { + // + // Read the next 16 bits. + // + ui32Temp = *(uint16_t *)pui8Data; + + // + // Perform the CRC on these two bytes. + // + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp); + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 8); + + // + // Skip these input bytes. + // + pui8Data += 2; + ui32Count -= 2; + } + + // + // While there is at least a word remaining in the data buffer, perform + // four steps of the CRC to consume a word. + // + while(ui32Count > 3) + { + // + // Read the next word. + // + ui32Temp = *(uint32_t *)pui8Data; + + // + // Perform the CRC on these four bytes. + // + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp); + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 8); + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 16); + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 24); + + // + // Skip these input bytes. + // + pui8Data += 4; + ui32Count -= 4; + } + + // + // If there are two bytes left in the input buffer, then perform two steps + // of the CRC. + // + if(ui32Count > 1) + { + // + // Read the two bytes. + // + ui32Temp = *(uint16_t *)pui8Data; + + // + // Perform the CRC on these two bytes. + // + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp); + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 8); + + // + // Skip these input bytes. + // + pui8Data += 2; + ui32Count -= 2; + } + + // + // If there is a final byte remaining in the input buffer, then perform a + // single step of the CRC. + // + if(ui32Count != 0) + { + ui16Crc = CRC16_ITER(ui16Crc, *pui8Data); + } + + // + // Return the resulting CRC-16 value. + // + return(ui16Crc); +} + +//***************************************************************************** +// +//! Calculates the CRC-16 of an array of words. +//! +//! \param ui32WordLen is the length of the array in words (the number of bytes +//! divided by 4). +//! \param pui32Data is a pointer to the data buffer. +//! +//! This function is a wrapper around the running CRC-16 function, providing +//! the CRC-16 for a single block of data. +//! +//! \return The CRC-16 of the input data. +// +//***************************************************************************** +uint16_t +Crc16Array(uint32_t ui32WordLen, const uint32_t *pui32Data) +{ + // + // Calculate and return the CRC-16 of this array of words. + // + return(Crc16(0, (const uint8_t *)pui32Data, ui32WordLen * 4)); +} + +//***************************************************************************** +// +//! Calculates three CRC-16s of an array of words. +//! +//! \param ui32WordLen is the length of the array in words (the number of bytes +//! divided by 4). +//! \param pui32Data is a pointer to the data buffer. +//! \param pui16Crc3 is a pointer to an array in which to place the three +//! CRC-16 values. +//! +//! This function is used to calculate three CRC-16s of the input buffer; the +//! first uses every byte from the array, the second uses only the even-index +//! bytes from the array (in other words, bytes 0, 2, 4, etc.), and the third +//! uses only the odd-index bytes from the array (in other words, bytes 1, 3, +//! 5, etc.). +//! +//! \return None +// +//***************************************************************************** +void +Crc16Array3(uint32_t ui32WordLen, const uint32_t *pui32Data, + uint16_t *pui16Crc3) +{ + uint16_t ui16Crc, ui16Cri8Odd, ui16Cri8Even; + + // + // Initialize the CRC values to zero. + // + ui16Crc = 0; + ui16Cri8Odd = 0; + ui16Cri8Even = 0; + + // + // Loop while there are more words in the data buffer. + // + while(ui32WordLen--) + { + // + // Read the next word. + // + uint32_t ui32Temp = *pui32Data++; + + // + // Perform the first CRC on all four data bytes. + // + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp); + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 8); + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 16); + ui16Crc = CRC16_ITER(ui16Crc, ui32Temp >> 24); + + // + // Perform the second CRC on only the even-index data bytes. + // + ui16Cri8Even = CRC16_ITER(ui16Cri8Even, ui32Temp); + ui16Cri8Even = CRC16_ITER(ui16Cri8Even, ui32Temp >> 16); + + // + // Perform the third CRC on only the odd-index data bytes. + // + ui16Cri8Odd = CRC16_ITER(ui16Cri8Odd, ui32Temp >> 8); + ui16Cri8Odd = CRC16_ITER(ui16Cri8Odd, ui32Temp >> 24); + } + + // + // Return the resulting CRC-16 values. + // + pui16Crc3[0] = ui16Crc; + pui16Crc3[1] = ui16Cri8Even; + pui16Crc3[2] = ui16Cri8Odd; +} + +//***************************************************************************** +// +//! Calculates the CRC-32 of an array of bytes. +//! +//! \param ui32Crc is the starting CRC-32 value. +//! \param pui8Data is a pointer to the data buffer. +//! \param ui32Count is the number of bytes in the data buffer. +//! +//! This function is used to calculate the CRC-32 of the input buffer. The +//! CRC-32 is computed in a running fashion, meaning that the entire data block +//! that is to have its CRC-32 computed does not need to be supplied all at +//! once. If the input buffer contains the entire block of data, then +//! \b ui32Crc should be set to 0xFFFFFFFF. If, however, the entire block of +//! data is not available, then \b ui32Crc should be set to 0xFFFFFFFF for the +//! first portion of the data, and then the returned value should be passed +//! back in as \b ui32Crc for the next portion of the data. Once all data has +//! been passed to the function, the final CRC-32 can be obtained by inverting +//! the last returned value. +//! +//! For example, to compute the CRC-32 of a block that has been split into +//! three pieces, use the following: +//! +//! \verbatim +//! ui32Crc = Crc32(0xFFFFFFFF, pui8Data1, ui32Len1); +//! ui32Crc = Crc32(ui32Crc, pui8Data2, ui32Len2); +//! ui32Crc = Crc32(ui32Crc, pui8Data3, ui32Len3); +//! ui32Crc ^= 0xFFFFFFFF; +//! \endverbatim +//! +//! Computing a CRC-32 in a running fashion is useful in cases where the data +//! is arriving via a serial link (for example) and is therefore not all +//! available at one time. +//! +//! \return The accumulated CRC-32 of the input data. +// +//***************************************************************************** +uint32_t +Crc32(uint32_t ui32Crc, const uint8_t *pui8Data, uint32_t ui32Count) +{ + uint32_t ui32Temp; + + // + // If the data buffer is not 16 bit-aligned, then perform a single step + // of the CRC to make it 16 bit-aligned. + // + if((uint32_t)pui8Data & 1) + { + // + // Perform the CRC on this input byte. + // + ui32Crc = CRC32_ITER(ui32Crc, *pui8Data); + + // + // Skip this input byte. + // + pui8Data++; + ui32Count--; + } + + // + // If the data buffer is not word-aligned and there are at least two bytes + // of data left, then perform two steps of the CRC to make it word-aligned. + // + if(((uint32_t)pui8Data & 2) && (ui32Count > 1)) + { + // + // Read the next int16_t. + // + ui32Temp = *(uint16_t *)pui8Data; + + // + // Perform the CRC on these two bytes. + // + ui32Crc = CRC32_ITER(ui32Crc, ui32Temp); + ui32Crc = CRC32_ITER(ui32Crc, ui32Temp >> 8); + + // + // Skip these input bytes. + // + pui8Data += 2; + ui32Count -= 2; + } + + // + // While there is at least a word remaining in the data buffer, perform + // four steps of the CRC to consume a word. + // + while(ui32Count > 3) + { + // + // Read the next word. + // + ui32Temp = *(uint32_t *)pui8Data; + + // + // Perform the CRC on these four bytes. + // + ui32Crc = CRC32_ITER(ui32Crc, ui32Temp); + ui32Crc = CRC32_ITER(ui32Crc, ui32Temp >> 8); + ui32Crc = CRC32_ITER(ui32Crc, ui32Temp >> 16); + ui32Crc = CRC32_ITER(ui32Crc, ui32Temp >> 24); + + // + // Skip these input bytes. + // + pui8Data += 4; + ui32Count -= 4; + } + + // + // If there are 16 bits left in the input buffer, then perform two steps of + // the CRC. + // + if(ui32Count > 1) + { + // + // Read the two bytes. + // + ui32Temp = *(uint16_t *)pui8Data; + + // + // Perform the CRC on these two bytes. + // + ui32Crc = CRC32_ITER(ui32Crc, ui32Temp); + ui32Crc = CRC32_ITER(ui32Crc, ui32Temp >> 8); + + // + // Skip these input bytes. + // + pui8Data += 2; + ui32Count -= 2; + } + + // + // If there is a final byte remaining in the input buffer, then perform a + // single step of the CRC. + // + if(ui32Count != 0) + { + ui32Crc = CRC32_ITER(ui32Crc, *pui8Data); + } + + // + // Return the resulting CRC-32 value. + // + return(ui32Crc); +} + diff --git a/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.h b/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.h new file mode 100644 index 000000000..92f4c1ee7 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Software_CRC/sw_crc.h @@ -0,0 +1,40 @@ + +#ifndef COMMON_SW_CRC_H_ +#define COMMON_SW_CRC_H_ +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif +#include + +//***************************************************************************** +// +// Prototypes for the functions. +// +//***************************************************************************** +extern uint8_t Crc8CCITT(uint8_t ui8Crc, const uint8_t *pui8Data, + uint32_t ui32Count); +extern uint16_t Crc16(uint16_t ui16Crc, const uint8_t *pui8Data, + uint32_t ui32Count); +extern uint16_t Crc16Array(uint32_t ui32WordLen, const uint32_t *pui32Data); +extern void Crc16Array3(uint32_t ui32WordLen, const uint32_t *pui32Data, + uint16_t *pui16Crc3); +extern uint32_t Crc32(uint32_t ui32Crc, const uint8_t *pui8Data, + uint32_t ui32Count); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_SW_CRC_H_ */ diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.c b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.c new file mode 100644 index 000000000..2899a6a41 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.c @@ -0,0 +1,996 @@ +//***************************************************************************** +// +// Configure the device pins for different signals +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +// This file was automatically generated on 25.2.2018 at 10:21:42 +// by TI PinMux version 4.0.1510 +// +//***************************************************************************** + +#include +#include +#include "inc/hw_gpio.h" +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "driverlib/gpio.h" +#include "driverlib/pin_map.h" +#include "driverlib/rom.h" +#include "driverlib/rom_map.h" +#include "driverlib/sysctl.h" +#include "pinout.h" + +//***************************************************************************** +// +//! \addtogroup pinout_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +//! Configures the device pins for the customer specific usage. +//! +//! \return None. +// +//***************************************************************************** +void +PinoutSet(void) +{ + // + // Enable Peripheral Clocks + // + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOR); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOS); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOT); + + // + // Configure the GPIO Pin Mux for PD1 + // for AIN14 + // + MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PE3 + // for AIN0 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PK1 + // for AIN17 + // + MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PE6 + // for AIN20 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_6); + + // + // Unlock the Port Pin and Set the Commit Bit + // + HWREG(GPIO_PORTD_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY; + HWREG(GPIO_PORTD_BASE+GPIO_O_CR) |= GPIO_PIN_7; + HWREG(GPIO_PORTD_BASE+GPIO_O_LOCK) = 0x0; + + // + // Configure the GPIO Pin Mux for PD7 + // for AIN4 + // + MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PD5 + // for AIN6 + // + MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PD0 + // for AIN15 + // + MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PD3 + // for AIN12 + // + MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PE1 + // for AIN2 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PB5 + // for AIN11 + // + MAP_GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PK3 + // for AIN19 + // + MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PK0 + // for AIN16 + // + MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PD2 + // for AIN13 + // + MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PE4 + // for AIN9 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_4); + + // + // Unlock the Port Pin and Set the Commit Bit + // + HWREG(GPIO_PORTE_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY; + HWREG(GPIO_PORTE_BASE+GPIO_O_CR) |= GPIO_PIN_7; + HWREG(GPIO_PORTE_BASE+GPIO_O_LOCK) = 0x0; + + // + // Configure the GPIO Pin Mux for PE7 + // for AIN21 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PE5 + // for AIN8 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PE2 + // for AIN1 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PE0 + // for AIN3 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PK2 + // for AIN18 + // + MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PB4 + // for AIN10 + // + MAP_GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PD4 + // for AIN7 + // + MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PD6 + // for AIN5 + // + MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PT2 + // for CAN1RX + // + MAP_GPIOPinConfigure(GPIO_PT2_CAN1RX); + MAP_GPIOPinTypeCAN(GPIO_PORTT_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PT3 + // for CAN1TX + // + MAP_GPIOPinConfigure(GPIO_PT3_CAN1TX); + MAP_GPIOPinTypeCAN(GPIO_PORTT_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PK4 + // for EPI0S32 + // + MAP_GPIOPinConfigure(GPIO_PK4_EPI0S32); + GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PL4 + // for EPI0S26 + // + MAP_GPIOPinConfigure(GPIO_PL4_EPI0S26); + GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PK6 + // for EPI0S25 + // + MAP_GPIOPinConfigure(GPIO_PK6_EPI0S25); + GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PL0 + // for EPI0S16 + // + MAP_GPIOPinConfigure(GPIO_PL0_EPI0S16); + GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PG0 + // for EPI0S11 + // + MAP_GPIOPinConfigure(GPIO_PG0_EPI0S11); + GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PA6 + // for EPI0S8 + // + MAP_GPIOPinConfigure(GPIO_PA6_EPI0S8); + GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PH1 + // for EPI0S1 + // + MAP_GPIOPinConfigure(GPIO_PH1_EPI0S1); + GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PN3 + // for EPI0S30 + // + MAP_GPIOPinConfigure(GPIO_PN3_EPI0S30); + GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PB2 + // for EPI0S27 + // + MAP_GPIOPinConfigure(GPIO_PB2_EPI0S27); + GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PN4 + // for EPI0S34 + // + MAP_GPIOPinConfigure(GPIO_PN4_EPI0S34); + GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PQ1 + // for EPI0S21 + // + MAP_GPIOPinConfigure(GPIO_PQ1_EPI0S21); + GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PL3 + // for EPI0S19 + // + MAP_GPIOPinConfigure(GPIO_PL3_EPI0S19); + GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PM0 + // for EPI0S15 + // + MAP_GPIOPinConfigure(GPIO_PM0_EPI0S15); + GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PM2 + // for EPI0S13 + // + MAP_GPIOPinConfigure(GPIO_PM2_EPI0S13); + GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PB3 + // for EPI0S28 + // + MAP_GPIOPinConfigure(GPIO_PB3_EPI0S28); + GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PQ3 + // for EPI0S23 + // + MAP_GPIOPinConfigure(GPIO_PQ3_EPI0S23); + GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PG1 + // for EPI0S10 + // + MAP_GPIOPinConfigure(GPIO_PG1_EPI0S10); + GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PK5 + // for EPI0S31 + // + MAP_GPIOPinConfigure(GPIO_PK5_EPI0S31); + GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PN2 + // for EPI0S29 + // + MAP_GPIOPinConfigure(GPIO_PN2_EPI0S29); + GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PH3 + // for EPI0S3 + // + MAP_GPIOPinConfigure(GPIO_PH3_EPI0S3); + GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PC5 + // for EPI0S6 + // + MAP_GPIOPinConfigure(GPIO_PC5_EPI0S6); + GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PA7 + // for EPI0S9 + // + MAP_GPIOPinConfigure(GPIO_PA7_EPI0S9); + GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PH0 + // for EPI0S0 + // + MAP_GPIOPinConfigure(GPIO_PH0_EPI0S0); + GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PC4 + // for EPI0S7 + // + MAP_GPIOPinConfigure(GPIO_PC4_EPI0S7); + GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PL1 + // for EPI0S17 + // + MAP_GPIOPinConfigure(GPIO_PL1_EPI0S17); + GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PL5 + // for EPI0S33 + // + MAP_GPIOPinConfigure(GPIO_PL5_EPI0S33); + GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PN5 + // for EPI0S35 + // + MAP_GPIOPinConfigure(GPIO_PN5_EPI0S35); + GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PM1 + // for EPI0S14 + // + MAP_GPIOPinConfigure(GPIO_PM1_EPI0S14); + GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PK7 + // for EPI0S24 + // + MAP_GPIOPinConfigure(GPIO_PK7_EPI0S24); + GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PC7 + // for EPI0S4 + // + MAP_GPIOPinConfigure(GPIO_PC7_EPI0S4); + GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PL2 + // for EPI0S18 + // + MAP_GPIOPinConfigure(GPIO_PL2_EPI0S18); + GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PM3 + // for EPI0S12 + // + MAP_GPIOPinConfigure(GPIO_PM3_EPI0S12); + GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PQ0 + // for EPI0S20 + // + MAP_GPIOPinConfigure(GPIO_PQ0_EPI0S20); + GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PQ2 + // for EPI0S22 + // + MAP_GPIOPinConfigure(GPIO_PQ2_EPI0S22); + GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PC6 + // for EPI0S5 + // + MAP_GPIOPinConfigure(GPIO_PC6_EPI0S5); + GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PH2 + // for EPI0S2 + // + MAP_GPIOPinConfigure(GPIO_PH2_EPI0S2); + GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PB6 + // for GPIO_PB6 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PB7 + // for GPIO_PB7 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PJ3 + // for GPIO_PJ3 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PQ6 + // for GPIO_PQ6 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PS5 + // for GPIO_PS5 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PS7 + // for GPIO_PS7 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PN7 + // for GPIO_PN7 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTN_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PS6 + // for GPIO_PS6 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PT1 + // for GPIO_PT1 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTT_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PT0 + // for GPIO_PT0 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTT_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PS4 + // for GPIO_PS4 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PN6 + // for GPIO_PN6 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PF6 + // for GPIO_PF6 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PM7 + // for GPIO_PM7 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTM_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PM6 + // for GPIO_PM6 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PF7 + // for GPIO_PF7 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PR3 + // for GPIO_PR3 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTR_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PM4 + // for GPIO_PM4 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PJ2 + // for GPIO_PJ2 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PM5 + // for GPIO_PM5 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PH4 + // for GPIO_PH4 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PH7 + // for GPIO_PH7 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PH6 + // for GPIO_PH6 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PH5 + // for GPIO_PH5 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PQ7 + // for GPIO_PQ7 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTQ_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PJ4 + // for GPIO_PJ4 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PJ5 + // for GPIO_PJ5 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PS2 + // for GPIO_PS2 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PS3 + // for GPIO_PS3 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PJ7 + // for GPIO_PJ7 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PS1 + // for GPIO_PS1 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PP5 + // for GPIO_PP5 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PP3 + // for GPIO_PP3 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PS0 + // for GPIO_PS0 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PN1 + // for GPIO_PN1 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PN0 + // for GPIO_PN0 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PJ0 + // for GPIO_PJ0 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PP4 + // for GPIO_PP4 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PJ1 + // for GPIO_PJ1 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PP0 + // for GPIO_PP0 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PP1 + // for GPIO_PP1 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PP2 + // for GPIO_PP2 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PR2 + // for GPIO_PR2 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTR_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PJ6 + // for GPIO_PJ6 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PP6 + // for GPIO_PP6 + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PP7 + // for GPIO_PP7 + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PR6 + // for I2C4SCL + // + MAP_GPIOPinConfigure(GPIO_PR6_I2C4SCL); + MAP_GPIOPinTypeI2CSCL(GPIO_PORTR_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PR7 + // for I2C4SDA + // + MAP_GPIOPinConfigure(GPIO_PR7_I2C4SDA); + MAP_GPIOPinTypeI2C(GPIO_PORTR_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PR4 + // for I2C3SCL + // + MAP_GPIOPinConfigure(GPIO_PR4_I2C3SCL); + MAP_GPIOPinTypeI2CSCL(GPIO_PORTR_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PR5 + // for I2C3SDA + // + MAP_GPIOPinConfigure(GPIO_PR5_I2C3SDA); + MAP_GPIOPinTypeI2C(GPIO_PORTR_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PG2 + // for I2C2SCL + // + MAP_GPIOPinConfigure(GPIO_PG2_I2C2SCL); + MAP_GPIOPinTypeI2CSCL(GPIO_PORTG_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PG3 + // for I2C2SDA + // + MAP_GPIOPinConfigure(GPIO_PG3_I2C2SDA); + MAP_GPIOPinTypeI2C(GPIO_PORTG_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PR0 + // for I2C1SCL + // + MAP_GPIOPinConfigure(GPIO_PR0_I2C1SCL); + MAP_GPIOPinTypeI2CSCL(GPIO_PORTR_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PR1 + // for I2C1SDA + // + MAP_GPIOPinConfigure(GPIO_PR1_I2C1SDA); + MAP_GPIOPinTypeI2C(GPIO_PORTR_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PF1 + // for SSI3XDAT0 + // + MAP_GPIOPinConfigure(GPIO_PF1_SSI3XDAT0); + MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PF5 + // for SSI3XDAT3 + // + MAP_GPIOPinConfigure(GPIO_PF5_SSI3XDAT3); + MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PF0 + // for SSI3XDAT1 + // + MAP_GPIOPinConfigure(GPIO_PF0_SSI3XDAT1); + MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PF2 + // for SSI3FSS + // + MAP_GPIOPinConfigure(GPIO_PF2_SSI3FSS); + MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PF4 + // for SSI3XDAT2 + // + MAP_GPIOPinConfigure(GPIO_PF4_SSI3XDAT2); + MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PF3 + // for SSI3CLK + // + MAP_GPIOPinConfigure(GPIO_PF3_SSI3CLK); + MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PG5 + // for SSI2XDAT0 + // + MAP_GPIOPinConfigure(GPIO_PG5_SSI2XDAT0); + MAP_GPIOPinTypeSSI(GPIO_PORTG_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PG4 + // for SSI2XDAT1 + // + MAP_GPIOPinConfigure(GPIO_PG4_SSI2XDAT1); + MAP_GPIOPinTypeSSI(GPIO_PORTG_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PG6 + // for SSI2FSS + // + MAP_GPIOPinConfigure(GPIO_PG6_SSI2FSS); + MAP_GPIOPinTypeSSI(GPIO_PORTG_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PG7 + // for SSI2CLK + // + MAP_GPIOPinConfigure(GPIO_PG7_SSI2CLK); + MAP_GPIOPinTypeSSI(GPIO_PORTG_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PA0 + // for U0RX + // + MAP_GPIOPinConfigure(GPIO_PA0_U0RX); + MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PA1 + // for U0TX + // + MAP_GPIOPinConfigure(GPIO_PA1_U0TX); + MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_1); + + // + // Configure the GPIO Pin Mux for PQ4 + // for U1RX + // + MAP_GPIOPinConfigure(GPIO_PQ4_U1RX); + MAP_GPIOPinTypeUART(GPIO_PORTQ_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PQ5 + // for U1TX + // + MAP_GPIOPinConfigure(GPIO_PQ5_U1TX); + MAP_GPIOPinTypeUART(GPIO_PORTQ_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PA4 + // for U3RX + // + MAP_GPIOPinConfigure(GPIO_PA4_U3RX); + MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_4); + + // + // Configure the GPIO Pin Mux for PA5 + // for U3TX + // + MAP_GPIOPinConfigure(GPIO_PA5_U3TX); + MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_5); + + // + // Configure the GPIO Pin Mux for PA2 + // for U4RX + // + MAP_GPIOPinConfigure(GPIO_PA2_U4RX); + MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_2); + + // + // Configure the GPIO Pin Mux for PA3 + // for U4TX + // + MAP_GPIOPinConfigure(GPIO_PA3_U4TX); + MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_3); + + // + // Configure the GPIO Pin Mux for PL6 + // for USB0DP + // + MAP_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6); + + // + // Configure the GPIO Pin Mux for PL7 + // for USB0DM + // + MAP_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_7); + + // + // Configure the GPIO Pin Mux for PB0 + // for USB0ID + // + MAP_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0); + + // + // Configure the GPIO Pin Mux for PB1 + // for USB0VBUS + // + MAP_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_1); + +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** + diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.h b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.h new file mode 100644 index 000000000..ebbe0b7d6 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/MCU_MAIN_pinout.h @@ -0,0 +1,74 @@ +//***************************************************************************** +// pinout.h +// +// configure the device pins for different signals +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +// This file was automatically generated on 25.2.2018 at 10:21:42 +// by TI PinMux version 4.0.1510 +// +//***************************************************************************** + +#ifndef __DRIVERS_PINOUT_H__ +#define __DRIVERS_PINOUT_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern void PinoutSet(void); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __DRIVERS_PINOUT_H__ diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.c b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.c new file mode 100644 index 000000000..1cb86ce4f --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.c @@ -0,0 +1,621 @@ +//***************************************************************************** +// Copyright (c) 2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// This file was automatically generated by the Tiva C Series PinMux Utility +// Version: 1.0.4 +// +//***************************************************************************** + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "Common/Sys_PinOut_Config/Pin.h" + +#ifdef ROM_GPIOPinTypeEthernetLED +#define MAP_GPIOPinTypeEthernetLED \ + ROM_GPIOPinTypeEthernetLED +#else +#define MAP_GPIOPinTypeEthernetLED \ + GPIOPinTypeEthernetLED +#endif + +//***************************************************************************** +void +PortFunctionInit(void) +{ + // + // Enable Peripheral Clocks + // + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C4); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART5); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); + + //hardware timers enabled manually because the pinout tool + //initialize automatically gpio per timer , deleting the gpio disables the timer + //manual initialization works well without gpios + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER4); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER6); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER7); + + + + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOR); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOS); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOT); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_WDOG0); + // + // Enable pin PD2 for ADC AIN13 + // + //MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_2); + + // + // Enable pin PE3 for ADC AIN0 + // + //MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); + + // + // Enable pin PK0 for ADC AIN16 + // + MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_0); + + // + // Enable pin PE6 for ADC AIN20 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_6); + + // + // Enable pin PD3 for ADC AIN12 + // + MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_3); + + // + // Enable pin PE1 for ADC AIN2 + // + //MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1); + + // + // Enable pin PK1 for ADC AIN17 + // + MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_1); + + // + // Enable pin PK3 for ADC AIN19 + // + MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_3); + + // + // Enable pin PP6 for ADC AIN23 + // + MAP_GPIOPinTypeADC(GPIO_PORTP_BASE, GPIO_PIN_6); + + // + // Enable pin PE7 for ADC AIN21 + // First open the lock and select the bits we want to modify in the GPIO commit register. + // + HWREG(GPIO_PORTE_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; + HWREG(GPIO_PORTE_BASE + GPIO_O_CR) = 0x80; + + // + // Now modify the configuration of the pins that we unlocked. + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_7); + + // + // Enable pin PB4 for ADC AIN10 + // + MAP_GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_4); + + // + // Enable pin PD6 for ADC AIN5 + // + MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_6); + + // + // Enable pin PE2 for ADC AIN1 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2); + + // + // Enable pin PE0 for ADC AIN3 + // + MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0); + + // + // Enable pin PK2 for ADC AIN18 + // + MAP_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_2); + + // + // Enable pin PP7 for ADC AIN22 + // + MAP_GPIOPinTypeADC(GPIO_PORTP_BASE, GPIO_PIN_7); + + // + // Enable pin PK4 for EPHY0 EN0LED0 + // + MAP_GPIOPinConfigure(GPIO_PK4_EN0LED0); + MAP_GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_4); + + // + // Enable pin PK5 for EPHY0 EN0LED2 + // + MAP_GPIOPinConfigure(GPIO_PK5_EN0LED2); + MAP_GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_5); + + // + // Enable pin PK6 for EPHY0 EN0LED1 + // + MAP_GPIOPinConfigure(GPIO_PK6_EN0LED1); + MAP_GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_6); + + // + // Enable pin PD0 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_0); + + // + // Enable pin PD1 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_1); + + // + // Enable pin PE4 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_4); + + // + // Enable pin PF7 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_7); + + // + // Enable pin PF6 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_6); + + // + // Enable pin PG4 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_4); + + // + // Enable pin PG5 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_5); + + // + // Enable pin PG0 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_0); + + // + // Enable pin PG1 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_1); + + // + // Enable pin PH2 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_2); + + // + // Enable pin PH0 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_0); + + // + // Enable pin PH4 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_4); + + // + // Enable pin PH6 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTH_BASE, GPIO_PIN_6); + + // + // Enable pin PH7 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTH_BASE, GPIO_PIN_7); + + // + // Enable pin PH5 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTH_BASE, GPIO_PIN_5); + + // + // Enable pin PH1 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_1); + + // + // Enable pin PH3 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_3); + + // + // Enable pin PJ7 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_7); + + // + // Enable pin PJ6 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_6); + + // + // Enable pin PJ2 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_2); + + // + // Enable pin PJ3 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_3); + + // + // Enable pin PL3 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_3); + + // + // Enable pin PL0 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_0); + + // + // Enable pin PL1 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_1); + + // + // Enable pin PL4 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_4); + + // + // Enable pin PL2 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_2); + + // + // Enable pin PL5 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTL_BASE, GPIO_PIN_5); + + // + // Enable pin PM1 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_1); + + // + // Enable pin PM0 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_0); + + // + // Enable pin PM3 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_3); + + // + // Enable pin PM5 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTM_BASE, GPIO_PIN_5); + + // + // Enable pin PM2 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_2); + + // + // Enable pin PN7 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTN_BASE, GPIO_PIN_7); + + // + // Enable pin PN1 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1); + + // + // Enable pin PN4 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_4); + + // + // Enable pin PN0 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTN_BASE, GPIO_PIN_0); + + // + // Enable pin PP2 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_2); + + // + // Enable pin PP4 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_4); + + // + // Enable pin PP3 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_3); + + // + // Enable pin PP5 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_5); + + // + // Enable pin PP0 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_0); + + // + // Enable pin PQ5 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTQ_BASE, GPIO_PIN_5); + + // + // Enable pin PQ7 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTQ_BASE, GPIO_PIN_7); + + // + // Enable pin PR3 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTR_BASE, GPIO_PIN_3); + + // + // Enable pin PR1 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTR_BASE, GPIO_PIN_1); + + // + // Enable pin PS4 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_4); + + // + // Enable pin PS0 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_0); + + // + // Enable pin PS2 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_2); + + // + // Enable pin PS5 for GPIOOutput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTS_BASE, GPIO_PIN_5); + + // + // Enable pin PS3 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_3); + + // + // Enable pin PT2 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTT_BASE, GPIO_PIN_2); + + // + // Enable pin PT0 for GPIOInput + // + MAP_GPIOPinTypeGPIOInput(GPIO_PORTT_BASE, GPIO_PIN_0); + + // + // Enable pin PA7 for GPIOInput + // + MAP_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_7); + + // + // Enable pin PB3 for I2C0 I2C0SDA + // + MAP_GPIOPinConfigure(GPIO_PB3_I2C0SDA); + MAP_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3); + + // + // Enable pin PB2 for I2C0 I2C0SCL + // + MAP_GPIOPinConfigure(GPIO_PB2_I2C0SCL); + MAP_GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2); + + // + // Enable pin PG6 for I2C4 I2C4SCL + // + MAP_GPIOPinConfigure(GPIO_PG6_I2C4SCL); + MAP_GPIOPinTypeI2CSCL(GPIO_PORTG_BASE, GPIO_PIN_6); + + // + // Enable pin PG7 for I2C4 I2C4SDA + // + MAP_GPIOPinConfigure(GPIO_PG7_I2C4SDA); + MAP_GPIOPinTypeI2C(GPIO_PORTG_BASE, GPIO_PIN_7); + + // + // Enable pin PR2 for PWM0 M0PWM2 + // + MAP_GPIOPinConfigure(GPIO_PR2_M0PWM2); + MAP_GPIOPinTypePWM(GPIO_PORTR_BASE, GPIO_PIN_2); + + // + // Enable pin PR7 for PWM0 M0PWM7 + // + MAP_GPIOPinConfigure(GPIO_PR7_M0PWM7); + MAP_GPIOPinTypePWM(GPIO_PORTR_BASE, GPIO_PIN_7); + + // + // Enable pin PR5 for PWM0 M0PWM5 + // + MAP_GPIOPinConfigure(GPIO_PR5_M0PWM5); + MAP_GPIOPinTypePWM(GPIO_PORTR_BASE, GPIO_PIN_5); + + // + // Enable pin PR0 for PWM0 M0PWM0 + // + MAP_GPIOPinConfigure(GPIO_PR0_M0PWM0); + MAP_GPIOPinTypePWM(GPIO_PORTR_BASE, GPIO_PIN_0); + + // + // Enable pin PA3 for SSI0 SSI0FSS + // + MAP_GPIOPinConfigure(GPIO_PA3_SSI0FSS); + MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_3); + + // + // Enable pin PA4 for SSI0 SSI0XDAT0 + // + MAP_GPIOPinConfigure(GPIO_PA4_SSI0XDAT0); + MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_4); + + // + // Enable pin PA5 for SSI0 SSI0XDAT1 + // + MAP_GPIOPinConfigure(GPIO_PA5_SSI0XDAT1); + MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5); + + // + // Enable pin PA2 for SSI0 SSI0CLK + // + MAP_GPIOPinConfigure(GPIO_PA2_SSI0CLK); + MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2); + + // + // Enable pin PQ0 for SSI3 SSI3CLK + // + MAP_GPIOPinConfigure(GPIO_PQ0_SSI3CLK); + MAP_GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_0); + + // + // Enable pin PF1 for SSI3 SSI3XDAT0 + // + MAP_GPIOPinConfigure(GPIO_PF1_SSI3XDAT0); + MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_1); + + // + // Enable pin PQ1 for SSI3 SSI3FSS + // + MAP_GPIOPinConfigure(GPIO_PQ1_SSI3FSS); + MAP_GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_1); + + // + // Enable pin PF5 for SSI3 SSI3XDAT3 + // + MAP_GPIOPinConfigure(GPIO_PF5_SSI3XDAT3); + MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_5); + + // + // Enable pin PF0 for SSI3 SSI3XDAT1 + // + MAP_GPIOPinConfigure(GPIO_PF0_SSI3XDAT1); + MAP_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0); + + // + // Enable pin PC7 for UART5 U5TX + // + MAP_GPIOPinConfigure(GPIO_PC7_U5TX); + MAP_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_7); + + // + // Enable pin PC6 for UART5 U5RX + // + MAP_GPIOPinConfigure(GPIO_PC6_U5RX); + MAP_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_6); + + // + // Enable pin PC5 for UART7 U7TX + // + MAP_GPIOPinConfigure(GPIO_PC5_U7TX); + MAP_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_5); + + // + // Enable pin PC4 for UART7 U7RX + // + MAP_GPIOPinConfigure(GPIO_PC4_U7RX); + MAP_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4); + + // + // Enable pin PL6 for USB0 USB0DP + // + MAP_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6); + + // + // Enable pin PL7 for USB0 USB0DM + // + MAP_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_7); + + // + // Enable pin PB1 for USB0 USB0VBUS + // + MAP_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_1); +} diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.h b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.h new file mode 100644 index 000000000..d5e51f6b4 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin.h @@ -0,0 +1,43 @@ +//***************************************************************************** +// Copyright (c) 2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// This file was automatically generated by the Tiva C Series PinMux Utility +// Version: 1.0.4 +// +//***************************************************************************** + +#ifndef __PIN_H__ +#define __PIN_H__ + +extern void PortFunctionInit(void); + +#endif // __PIN_H__ diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.c b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.c new file mode 100644 index 000000000..8e378309a --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.c @@ -0,0 +1,51 @@ +#include +#include + +#include +#include + +void InitPinOutPullUps(void) +{ + GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_INT_PIN_1,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_INT_PIN_2,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_INT_PIN_3,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTE_BASE, GPIO_INT_PIN_1,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTE_BASE, GPIO_INT_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTG_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTG_BASE, GPIO_INT_PIN_1,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTH_BASE, GPIO_INT_PIN_5,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTH_BASE, GPIO_INT_PIN_6,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTH_BASE, GPIO_INT_PIN_7,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_INT_PIN_2,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_INT_PIN_3,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_INT_PIN_7,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTM_BASE, GPIO_INT_PIN_5,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTN_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTN_BASE, GPIO_INT_PIN_7,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTP_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTP_BASE, GPIO_INT_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTP_BASE, GPIO_INT_PIN_5,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTQ_BASE, GPIO_INT_PIN_5,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTQ_BASE, GPIO_INT_PIN_7,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTS_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTS_BASE, GPIO_INT_PIN_3,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + + GPIOPadConfigSet(GPIO_PORTT_BASE, GPIO_INT_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + GPIOPadConfigSet(GPIO_PORTT_BASE, GPIO_INT_PIN_2,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); + +} + + + + diff --git a/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.h b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.h new file mode 100644 index 000000000..c83281cd9 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Sys_PinOut_Config/Pin_config.h @@ -0,0 +1,14 @@ +/**************************************************************************************************** + * init ialization of pull up's over GPIO + * those pins must be configured as inputs in the pinmap file by using MAP_GPIOPinTypeGPIOInput func + * here is added onlu the pull up defenition + *****************************************************************************************************/ + +#ifndef PIN_CONFIG_H_ +#define PIN_CONFIG_H_ + + +void InitPinOutPullUps(void); + + +#endif /* PIN_CONFIG_H_ */ diff --git a/Software/Embedded_SW/Embedded/Common/Utilities/Update.c b/Software/Embedded_SW/Embedded/Common/Utilities/Update.c new file mode 100644 index 000000000..8eeee64cf --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Utilities/Update.c @@ -0,0 +1,98 @@ + +#include "include.h" +//#include + +//#include "Drivers/USB_Communication/USBCDCD.h" + + +extern Semaphore_Handle updateSem; + + +void UpdateUsb(void) +{ + // + // Terminate the USB device and detach from the bus. + // + USBDCDTerm(0); + + // + // Disable all interrupts. + // + ROM_IntMasterDisable(); + + // + // Disable SysTick and its interrupt. + // + ROM_SysTickIntDisable(); + ROM_SysTickDisable(); + + // + // Disable all processor interrupts. Instead of disabling them one at a + // time, a direct write to NVIC is done to disable all peripheral + // interrupts. + // + HWREG(NVIC_DIS0) = 0xffffffff; + HWREG(NVIC_DIS1) = 0xffffffff; + HWREG(NVIC_DIS2) = 0xffffffff; + HWREG(NVIC_DIS3) = 0xffffffff; + HWREG(NVIC_DIS4) = 0xffffffff; + + // + // Enable and reset the USB peripheral. + // + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0); + ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_USB0); + ROM_USBClockEnable(USB0_BASE, 8, USB_CLOCK_INTERNAL); + + // + // Wait for about a second. + // + ROM_SysCtlDelay(SYS_CLK_FREQ / 3); + + // + // Re-enable interrupts at the NVIC level. + // + ROM_IntMasterEnable(); + + // + // Call the USB boot loader. + // + ROM_UpdateUSB(0); + + // + // Should never get here, but just in case. + // + while(1) + { + } +} + +Void updateTask(UArg arg0, UArg arg1) +{ + + // + // Wait until new updTE ARRIVED + // + Semaphore_pend(updateSem, BIOS_WAIT_FOREVER); + UpdateUsb(); +} +extern Semaphore_Handle ReconnectSem; + + +void ReconnectUsb(void) +{ + //USBCDC_close(); +} + +Void ReconnectTask(UArg arg0, UArg arg1) +{ + + // + // Wait until new updTE ARRIVED + // + while (1) + { + Semaphore_pend(ReconnectSem, BIOS_WAIT_FOREVER); + ReconnectUsb(); + } +} diff --git a/Software/Embedded_SW/Embedded/Common/Utilities/Utils.c b/Software/Embedded_SW/Embedded/Common/Utilities/Utils.c new file mode 100644 index 000000000..d792d9b5f --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Utilities/Utils.c @@ -0,0 +1,245 @@ +/************************************************************ + * Utils.h + * general module of system utility functions + **************************************************************/ + +#include +#include +#include +#include +#include "Common/Utilities/Utils.h" +//#include +#include "driverlib/hibernate.h" + +static const float speedCoef = 5.3051647697298445256294587790838f;//(200 micro steping)/2*Pi*Radius - 200 micro steping + +//***************************************************************************** + +bool DanserCheckPosition(uint16_t position , Danser_t danser, bool test) +{ + if (test == false) return true; +#ifdef DEBUG_DANCER + ProfileType_t profileType = GetCurrentProfileType(); + if (position < DANSER_POS_MIN) + { + if(danser == Winder) + { + if(profileType == Manual) + { + JigStopAllWithError("Thread torn in winder danser");//for stoping the system operation + } + else if (profileType == User) + { + //notify the UI about an error and pause the system + SendMessageToHost(ERROR_IN_PROFILE_EXECUTION,"Thread torn in winder danser"); + JigPauseAll(); + } + } + else + { + if(profileType == Manual) + { + JigStopAllWithError("Thread torn in pooler danser");//for stoping the system operation + } + else if (profileType == User) + { + //notify the UI about an error and pause the system + SendMessageToHost(ERROR_IN_PROFILE_EXECUTION,"Thread torn in pooler danser"); + JigPauseAll(); + } + } + return false; + } + + if (position > DANSER_POS_MAX) + { + if(danser == Pooler) + { + if(profileType == Manual) + { + JigStopAllWithError("Thread stocked in pooler danser"); + } + else if (profileType == User) + { + SendMessageToHost(ERROR_IN_PROFILE_EXECUTION,"Thread stuck in pooler danser"); + JigPauseAll(); + } + } + else + { + if(profileType == Manual) + { + JigStopAllWithError("Thread stocked in winder danser"); + } + else if (profileType ==User) + { + SendMessageToHost(ERROR_IN_PROFILE_EXECUTION,"Thread stuck in winder danser"); + JigPauseAll(); + } + } + return false; + } +#endif + return true; +} + +//***************************************************************************** +//convert thread speed recieved in milimeters per second into motor steps of pps +//***************************************************************************** +uint16_t ConvertSpeed2Pps(uint16_t milimeterPerSecond) +{ + float res = speedCoef*(float)milimeterPerSecond; + return (uint16_t)res; +} +//***************************************************************************** + +uint16_t ConvertPpsToSpeed(uint16_t Pps) +{ + float res = (float)Pps/speedCoef; + return (uint16_t)res; + +} + +//***************************************************************************** +// +// Init WD timer +// +//***************************************************************************** +void InitWatchdog(uint32_t clock) +{ + // + // Enable the watchdog interrupt. + // + ROM_IntEnable(INT_WATCHDOG); + + // + // Set the period of the watchdog timer. + // + ROM_WatchdogReloadSet(WATCHDOG0_BASE, clock); + + // + // Enable reset generation from the watchdog timer. + // + ROM_WatchdogResetEnable(WATCHDOG0_BASE); + + // + // Enable the watchdog timer. + // + ROM_WatchdogEnable(WATCHDOG0_BASE); +} +void utilsInit(uint32_t ui32SysClock) +{ + + cb_init(); +// SysTickPeriodSet(120000); +// SysTickEnable(); + // Configure Hibernate module clock. + // + HibernateEnableExpClk(ui32SysClock); + + + // Enable RTC mode. + // + HibernateRTCEnable(); + + // + // Configure the hibernate module counter to 24-hour calendar mode. + // + // HibernateCounterMode(HIBERNATE_COUNTER_24HR); + // Configure the hibernate module counter to RTC counter mode. + HibernateCounterMode(HIBERNATE_COUNTER_RTC); + + +} + + +uint32_t UsersysTickGet (void) { + uint32_t tick = 0; +// tick = SysTickValueGet(); + tick = HibernateRTCSSGet()*10000/0x8000; + return tick; +} + +//***************************************************************************** +// +// The interrupt handler for the watchdog. This feeds the dog (so that the +// processor does not get reset) and winks the LED connected to GPIO B3. +// +//***************************************************************************** +void WatchdogIntHandler(void) +{ + // + // Clear the watchdog interrupt. + // + ROM_WatchdogIntClear(WATCHDOG0_BASE); +} + +bool sendDataToHost = false; +void UtilsSetCommunicationOk(void) +{ + sendDataToHost = true; +} + +typedef struct circular_buffer +{ + void *buffer; // data buffer + void *buffer_end; // end of data buffer + uint16_t capacity; // maximum number of items in the buffer + uint16_t count; // number of items in the buffer + uint16_t sz; // size of each item in the buffer + void *head; // pointer to head + void *tail; // pointer to tail +} circular_buffer; + +uint8_t LogBuffer[8002]; +circular_buffer cb; +void cb_init() +{ + //cb.buffer = malloc(capacity * sz); + //if(cb.buffer == NULL) + // handle error + cb.buffer = LogBuffer; + cb.buffer_end = &LogBuffer[3950]; + cb.capacity = 4000; + cb.count = 0; + cb.sz = 60; + cb.head = cb.buffer; + cb.tail = cb.buffer; +} + +void cb_free(circular_buffer *cb) +{ + //free(cb.buffer); + // clear out other fields too, just to be safe +} + +void cb_push_back(/*circular_buffer *cb,*/ const void *item, int size) +{ + if(cb.count == cb.capacity){ + return; + // handle error + } + if ((int)(cb.head) + size > (int)(cb.buffer_end)){ + size = (int)(cb.buffer_end) - (int)(cb.head); + } + + memcpy(cb.head, item, size); + cb.head = (char*)cb.head + size; + if(cb.head >= cb.buffer_end) + cb.head = cb.buffer; + cb.count++; +// if (sendDataToHost) +// SendMessageToHost(DEBUG_LOG,item); +} + +void cb_pop_front(/*circular_buffer *cb,*/ void *item) +{ + if(cb.count == 0){ + // handle error + } + memcpy(item, cb.tail, cb.sz); + cb.tail = (char*)cb.tail + cb.sz; + if(cb.tail == cb.buffer_end) + cb.tail = cb.buffer; + cb.count--; +} diff --git a/Software/Embedded_SW/Embedded/Common/Utilities/Utils.h b/Software/Embedded_SW/Embedded/Common/Utilities/Utils.h new file mode 100644 index 000000000..363cf6eec --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Utilities/Utils.h @@ -0,0 +1,33 @@ +/************************************************************ + * Utils.h + * general module of system utility functions + **************************************************************/ + +#ifndef COMMON_UTILS_H_ +#define COMMON_UTILS_H_ + +#include +#include + + +//digital read of the potentiometer limits +#define DANSER_POS_MIN 1300 +#define DANSER_POS_MAX 3500 + +typedef enum +{ + Winder = 0, + Pooler +}Danser_t; + + +void cb_init(); +void cb_push_back(/*void *cb,*/ const void *item, int size); +void utilsInit(uint32_t ui32SysClock); +uint32_t UsersysTickGet (void); +bool DanserCheckPosition(uint16_t position , Danser_t danser, bool test); +void InitWatchdog(uint32_t clock); +uint16_t ConvertSpeed2Pps(uint16_t milimeterPerSecond); +uint16_t ConvertPpsToSpeed(uint16_t Pps); +void UtilsSetCommunicationOk(void); +#endif /* COMMON_UTILS_H_ */ diff --git a/Software/Embedded_SW/Embedded/Common/Utilities/ustdlib.c b/Software/Embedded_SW/Embedded/Common/Utilities/ustdlib.c new file mode 100644 index 000000000..efee94611 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/Utilities/ustdlib.c @@ -0,0 +1,1825 @@ +//***************************************************************************** +// +// ustdlib.c - Simple standard library functions. +// +// Copyright (c) 2007-2015 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.2.111 of the Tiva Utility Library. +// +//***************************************************************************** + +#include +#include +#include + +//***************************************************************************** +// +//! \addtogroup ustdlib_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// A mapping from an integer between 0 and 15 to its ASCII character +// equivalent. +// +//***************************************************************************** +static const char * const g_pcHex = "0123456789abcdef"; + +//***************************************************************************** +// +//! Copies a certain number of characters from one string to another. +//! +//! \param s1 is a pointer to the destination buffer into which characters +//! are to be copied. +//! \param s2 is a pointer to the string from which characters are to be +//! copied. +//! \param n is the number of characters to copy to the destination buffer. +//! +//! This function copies at most \e n characters from the string pointed to +//! by \e s2 into the buffer pointed to by \e s1. If the end of \e s2 is found +//! before \e n characters have been copied, remaining characters in \e s1 +//! will be padded with zeroes until \e n characters have been written. Note +//! that the destination string will only be NULL terminated if the number of +//! characters to be copied is greater than the length of \e s2. +//! +//! \return Returns \e s1. +// +//***************************************************************************** +char * +ustrncpy(char * restrict s1, const char * restrict s2, size_t n) +{ + size_t count; + + // + // Check the arguments. + // + ASSERT(s1); + ASSERT(s2); + + // + // Start at the beginning of the source string. + // + count = 0; + + // + // Copy the source string until we run out of source characters or + // destination space. + // + while(n && s2[count]) + { + s1[count] = s2[count]; + count++; + n--; + } + + // + // Pad the destination if we are not yet done. + // + while(n) + { + s1[count++] = (char)0; + n--; + } + + // + // Pass the destination pointer back to the caller. + // + return(s1); +} + +//***************************************************************************** +// +//! A simple vsnprintf function supporting \%c, \%d, \%p, \%s, \%u, \%x, and +//! \%X. +//! +//! \param s points to the buffer where the converted string is stored. +//! \param n is the size of the buffer. +//! \param format is the format string. +//! \param arg is the list of optional arguments, which depend on the +//! contents of the format string. +//! +//! This function is very similar to the C library vsnprintf() +//! function. Only the following formatting characters are supported: +//! +//! - \%c to print a character +//! - \%d or \%i to print a decimal value +//! - \%s to print a string +//! - \%u to print an unsigned decimal value +//! - \%x to print a hexadecimal value using lower case letters +//! - \%X to print a hexadecimal value using lower case letters (not upper case +//! letters as would typically be used) +//! - \%p to print a pointer as a hexadecimal value +//! - \%\% to print out a \% character +//! +//! For \%d, \%i, \%p, \%s, \%u, \%x, and \%X, an optional number may reside +//! between the \% and the format character, which specifies the minimum number +//! of characters to use for that value; if preceded by a 0 then the extra +//! characters will be filled with zeros instead of spaces. For example, +//! ``\%8d'' will use eight characters to print the decimal value with spaces +//! added to reach eight; ``\%08d'' will use eight characters as well but will +//! add zeroes instead of spaces. +//! +//! The type of the arguments after \e format must match the requirements of +//! the format string. For example, if an integer was passed where a string +//! was expected, an error of some kind will most likely occur. +//! +//! The \e n parameter limits the number of characters that will be +//! stored in the buffer pointed to by \e s to prevent the possibility of +//! a buffer overflow. The buffer size should be large enough to hold the +//! expected converted output string, including the null termination character. +//! +//! The function will return the number of characters that would be converted +//! as if there were no limit on the buffer size. Therefore it is possible for +//! the function to return a count that is greater than the specified buffer +//! size. If this happens, it means that the output was truncated. +//! +//! \return Returns the number of characters that were to be stored, not +//! including the NULL termination character, regardless of space in the +//! buffer. +// +//***************************************************************************** +int +uvsnprintf(char * restrict s, size_t n, const char * restrict format, + va_list arg) +{ + unsigned long ulIdx, ulValue, ulCount, ulBase, ulNeg; + char *pcStr, cFill; + int iConvertCount = 0; + + // + // Check the arguments. + // + ASSERT(s); + ASSERT(n); + ASSERT(format); + + // + // Adjust buffer size limit to allow one space for null termination. + // + if(n) + { + n--; + } + + // + // Initialize the count of characters converted. + // + iConvertCount = 0; + + // + // Loop while there are more characters in the format string. + // + while(*format) + { + // + // Find the first non-% character, or the end of the string. + // + for(ulIdx = 0; (format[ulIdx] != '%') && (format[ulIdx] != '\0'); + ulIdx++) + { + } + + // + // Write this portion of the string to the output buffer. If there are + // more characters to write than there is space in the buffer, then + // only write as much as will fit in the buffer. + // + if(ulIdx > n) + { + ustrncpy(s, format, n); + s += n; + n = 0; + } + else + { + ustrncpy(s, format, ulIdx); + s += ulIdx; + n -= ulIdx; + } + + // + // Update the conversion count. This will be the number of characters + // that should have been written, even if there was not room in the + // buffer. + // + iConvertCount += ulIdx; + + // + // Skip the portion of the format string that was written. + // + format += ulIdx; + + // + // See if the next character is a %. + // + if(*format == '%') + { + // + // Skip the %. + // + format++; + + // + // Set the digit count to zero, and the fill character to space + // (that is, to the defaults). + // + ulCount = 0; + cFill = ' '; + + // + // It may be necessary to get back here to process more characters. + // Goto's aren't pretty, but effective. I feel extremely dirty for + // using not one but two of the beasts. + // +again: + + // + // Determine how to handle the next character. + // + switch(*format++) + { + // + // Handle the digit characters. + // + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + // + // If this is a zero, and it is the first digit, then the + // fill character is a zero instead of a space. + // + if((format[-1] == '0') && (ulCount == 0)) + { + cFill = '0'; + } + + // + // Update the digit count. + // + ulCount *= 10; + ulCount += format[-1] - '0'; + + // + // Get the next character. + // + goto again; + } + + // + // Handle the %c command. + // + case 'c': + { + // + // Get the value from the varargs. + // + ulValue = va_arg(arg, unsigned long); + + // + // Copy the character to the output buffer, if there is + // room. Update the buffer size remaining. + // + if(n != 0) + { + *s++ = (char)ulValue; + n--; + } + + // + // Update the conversion count. + // + iConvertCount++; + + // + // This command has been handled. + // + break; + } + + // + // Handle the %d and %i commands. + // + case 'd': + case 'i': + { + // + // Get the value from the varargs. + // + ulValue = va_arg(arg, unsigned long); + + // + // If the value is negative, make it positive and indicate + // that a minus sign is needed. + // + if((long)ulValue < 0) + { + // + // Make the value positive. + // + ulValue = -(long)ulValue; + + // + // Indicate that the value is negative. + // + ulNeg = 1; + } + else + { + // + // Indicate that the value is positive so that a + // negative sign isn't inserted. + // + ulNeg = 0; + } + + // + // Set the base to 10. + // + ulBase = 10; + + // + // Convert the value to ASCII. + // + goto convert; + } + + // + // Handle the %s command. + // + case 's': + { + // + // Get the string pointer from the varargs. + // + pcStr = va_arg(arg, char *); + + // + // Determine the length of the string. + // + for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++) + { + } + + // + // Update the convert count to include any padding that + // should be necessary (regardless of whether we have space + // to write it or not). + // + if(ulCount > ulIdx) + { + iConvertCount += (ulCount - ulIdx); + } + + // + // Copy the string to the output buffer. Only copy as much + // as will fit in the buffer. Update the output buffer + // pointer and the space remaining. + // + if(ulIdx > n) + { + ustrncpy(s, pcStr, n); + s += n; + n = 0; + } + else + { + ustrncpy(s, pcStr, ulIdx); + s += ulIdx; + n -= ulIdx; + + // + // Write any required padding spaces assuming there is + // still space in the buffer. + // + if(ulCount > ulIdx) + { + ulCount -= ulIdx; + if(ulCount > n) + { + ulCount = n; + } + n = -ulCount; + + while(ulCount--) + { + *s++ = ' '; + } + } + } + + // + // Update the conversion count. This will be the number of + // characters that should have been written, even if there + // was not room in the buffer. + // + iConvertCount += ulIdx; + + // + // This command has been handled. + // + break; + } + + // + // Handle the %u command. + // + case 'u': + { + // + // Get the value from the varargs. + // + ulValue = va_arg(arg, unsigned long); + + // + // Set the base to 10. + // + ulBase = 10; + + // + // Indicate that the value is positive so that a minus sign + // isn't inserted. + // + ulNeg = 0; + + // + // Convert the value to ASCII. + // + goto convert; + } + + // + // Handle the %x and %X commands. Note that they are treated + // identically; that is, %X will use lower case letters for a-f + // instead of the upper case letters is should use. We also + // alias %p to %x. + // + case 'x': + case 'X': + case 'p': + { + // + // Get the value from the varargs. + // + ulValue = va_arg(arg, unsigned long); + + // + // Set the base to 16. + // + ulBase = 16; + + // + // Indicate that the value is positive so that a minus sign + // isn't inserted. + // + ulNeg = 0; + + // + // Determine the number of digits in the string version of + // the value. + // +convert: + for(ulIdx = 1; + (((ulIdx * ulBase) <= ulValue) && + (((ulIdx * ulBase) / ulBase) == ulIdx)); + ulIdx *= ulBase, ulCount--) + { + } + + // + // If the value is negative, reduce the count of padding + // characters needed. + // + if(ulNeg) + { + ulCount--; + } + + // + // If the value is negative and the value is padded with + // zeros, then place the minus sign before the padding. + // + if(ulNeg && (n != 0) && (cFill == '0')) + { + // + // Place the minus sign in the output buffer. + // + *s++ = '-'; + n--; + + // + // Update the conversion count. + // + iConvertCount++; + + // + // The minus sign has been placed, so turn off the + // negative flag. + // + ulNeg = 0; + } + + // + // See if there are more characters in the specified field + // width than there are in the conversion of this value. + // + if((ulCount > 1) && (ulCount < 65536)) + { + // + // Loop through the required padding characters. + // + for(ulCount--; ulCount; ulCount--) + { + // + // Copy the character to the output buffer if there + // is room. + // + if(n != 0) + { + *s++ = cFill; + n--; + } + + // + // Update the conversion count. + // + iConvertCount++; + } + } + + // + // If the value is negative, then place the minus sign + // before the number. + // + if(ulNeg && (n != 0)) + { + // + // Place the minus sign in the output buffer. + // + *s++ = '-'; + n--; + + // + // Update the conversion count. + // + iConvertCount++; + } + + // + // Convert the value into a string. + // + for(; ulIdx; ulIdx /= ulBase) + { + // + // Copy the character to the output buffer if there is + // room. + // + if(n != 0) + { + *s++ = g_pcHex[(ulValue / ulIdx) % ulBase]; + n--; + } + + // + // Update the conversion count. + // + iConvertCount++; + } + + // + // This command has been handled. + // + break; + } + + // + // Handle the %% command. + // + case '%': + { + // + // Simply write a single %. + // + if(n != 0) + { + *s++ = format[-1]; + n--; + } + + // + // Update the conversion count. + // + iConvertCount++; + + // + // This command has been handled. + // + break; + } + + // + // Handle all other commands. + // + default: + { + // + // Indicate an error. + // + if(n >= 5) + { + ustrncpy(s, "ERROR", 5); + s += 5; + n -= 5; + } + else + { + ustrncpy(s, "ERROR", n); + s += n; + n = 0; + } + + // + // Update the conversion count. + // + iConvertCount += 5; + + // + // This command has been handled. + // + break; + } + } + } + } + + // + // Null terminate the string in the buffer. + // + *s = 0; + + // + // Return the number of characters in the full converted string. + // + return(iConvertCount); +} + +//***************************************************************************** +// +//! A simple sprintf function supporting \%c, \%d, \%p, \%s, \%u, \%x, and \%X. +//! +//! \param s is the buffer where the converted string is stored. +//! \param format is the format string. +//! \param ... are the optional arguments, which depend on the contents of the +//! format string. +//! +//! This function is very similar to the C library sprintf() function. +//! Only the following formatting characters are supported: +//! +//! - \%c to print a character +//! - \%d or \%i to print a decimal value +//! - \%s to print a string +//! - \%u to print an unsigned decimal value +//! - \%x to print a hexadecimal value using lower case letters +//! - \%X to print a hexadecimal value using lower case letters (not upper case +//! letters as would typically be used) +//! - \%p to print a pointer as a hexadecimal value +//! - \%\% to print out a \% character +//! +//! For \%d, \%i, \%p, \%s, \%u, \%x, and \%X, an optional number may reside +//! between the \% and the format character, which specifies the minimum number +//! of characters to use for that value; if preceded by a 0 then the extra +//! characters will be filled with zeros instead of spaces. For example, +//! ``\%8d'' will use eight characters to print the decimal value with spaces +//! added to reach eight; ``\%08d'' will use eight characters as well but will +//! add zeros instead of spaces. +//! +//! The type of the arguments after \e format must match the requirements of +//! the format string. For example, if an integer was passed where a string +//! was expected, an error of some kind will most likely occur. +//! +//! The caller must ensure that the buffer \e s is large enough to hold the +//! entire converted string, including the null termination character. +//! +//! \return Returns the count of characters that were written to the output +//! buffer, not including the NULL termination character. +// +//***************************************************************************** +int +usprintf(char * restrict s, const char *format, ...) +{ + va_list arg; + int ret; + + // + // Start the varargs processing. + // + va_start(arg, format); + + // + // Call vsnprintf to perform the conversion. Use a large number for the + // buffer size. + // + ret = uvsnprintf(s, 0xffff, format, arg); + + // + // End the varargs processing. + // + va_end(arg); + + // + // Return the conversion count. + // + return(ret); +} + +//***************************************************************************** +// +//! A simple snprintf function supporting \%c, \%d, \%p, \%s, \%u, \%x, and +//! \%X. +//! +//! \param s is the buffer where the converted string is stored. +//! \param n is the size of the buffer. +//! \param format is the format string. +//! \param ... are the optional arguments, which depend on the contents of the +//! format string. +//! +//! This function is very similar to the C library sprintf() function. +//! Only the following formatting characters are supported: +//! +//! - \%c to print a character +//! - \%d or \%i to print a decimal value +//! - \%s to print a string +//! - \%u to print an unsigned decimal value +//! - \%x to print a hexadecimal value using lower case letters +//! - \%X to print a hexadecimal value using lower case letters (not upper case +//! letters as would typically be used) +//! - \%p to print a pointer as a hexadecimal value +//! - \%\% to print out a \% character +//! +//! For \%d, \%i, \%p, \%s, \%u, \%x, and \%X, an optional number may reside +//! between the \% and the format character, which specifies the minimum number +//! of characters to use for that value; if preceded by a 0 then the extra +//! characters will be filled with zeros instead of spaces. For example, +//! ``\%8d'' will use eight characters to print the decimal value with spaces +//! added to reach eight; ``\%08d'' will use eight characters as well but will +//! add zeros instead of spaces. +//! +//! The type of the arguments after \e format must match the requirements of +//! the format string. For example, if an integer was passed where a string +//! was expected, an error of some kind will most likely occur. +//! +//! The function will copy at most \e n - 1 characters into the buffer +//! \e s. One space is reserved in the buffer for the null termination +//! character. +//! +//! The function will return the number of characters that would be converted +//! as if there were no limit on the buffer size. Therefore it is possible for +//! the function to return a count that is greater than the specified buffer +//! size. If this happens, it means that the output was truncated. +//! +//! \return Returns the number of characters that were to be stored, not +//! including the NULL termination character, regardless of space in the +//! buffer. +// +//***************************************************************************** +int +usnprintf(char * restrict s, size_t n, const char * restrict format, ...) +{ + va_list arg; + int ret; + + // + // Start the varargs processing. + // + va_start(arg, format); + + // + // Call vsnprintf to perform the conversion. + // + ret = uvsnprintf(s, n, format, arg); + + // + // End the varargs processing. + // + va_end(arg); + + // + // Return the conversion count. + // + return(ret); +} + +//***************************************************************************** +// +// This array contains the number of days in a year at the beginning of each +// month of the year, in a non-leap year. +// +//***************************************************************************** +static const time_t g_psDaysToMonth[12] = +{ + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 +}; + +//***************************************************************************** +// +//! Converts from seconds to calendar date and time. +//! +//! \param timer is the number of seconds. +//! \param tm is a pointer to the time structure that is filled in with the +//! broken down date and time. +//! +//! This function converts a number of seconds since midnight GMT on January 1, +//! 1970 (traditional Unix epoch) into the equivalent month, day, year, hours, +//! minutes, and seconds representation. +//! +//! \return None. +// +//***************************************************************************** +void +ulocaltime(time_t timer, struct tm *tm) +{ + time_t temp, months; + + // + // Extract the number of seconds, converting time to the number of minutes. + // + temp = timer / 60; + tm->tm_sec = timer - (temp * 60); + timer = temp; + + // + // Extract the number of minutes, converting time to the number of hours. + // + temp = timer / 60; + tm->tm_min = timer - (temp * 60); + timer = temp; + + // + // Extract the number of hours, converting time to the number of days. + // + temp = timer / 24; + tm->tm_hour = timer - (temp * 24); + timer = temp; + + // + // Compute the day of the week. + // + tm->tm_wday = (timer + 4) % 7; + + // + // Compute the number of leap years that have occurred since 1968, the + // first leap year before 1970. For the beginning of a leap year, cut the + // month loop below at March so that the leap day is classified as February + // 29 followed by March 1, instead of March 1 followed by another March 1. + // + timer += 366 + 365; + temp = timer / ((4 * 365) + 1); + if((timer - (temp * ((4 * 365) + 1))) > (31 + 28)) + { + temp++; + months = 12; + } + else + { + months = 2; + } + + // + // Extract the year. + // + tm->tm_year = ((timer - temp) / 365) + 68; + timer -= ((tm->tm_year - 68) * 365) + temp; + + // + // Extract the month. + // + for(temp = 0; temp < months; temp++) + { + if(g_psDaysToMonth[temp] > timer) + { + break; + } + } + tm->tm_mon = temp - 1; + + // + // Extract the day of the month. + // + tm->tm_mday = timer - g_psDaysToMonth[temp - 1] + 1; +} + +//***************************************************************************** +// +//! Compares two time structures and determines if one is greater than, +//! less than, or equal to the other. +//! +//! \param t1 is the first time structure to compare. +//! \param t2 is the second time structure to compare. +//! +//! This function compares two time structures and returns a signed number +//! to indicate the result of the comparison. If the time represented by +//! \e t1 is greater than the time represented by \e t2 then a positive +//! number is returned. Likewise if \e t1 is less than \e t2 then a +//! negative number is returned. If the two times are equal then the function +//! returns 0. +//! +//! \return Returns 0 if the two times are equal, +1 if \e t1 is greater +//! than \e t2, and -1 if \e t1 is less than \e t2. +// +//***************************************************************************** +static int +ucmptime(struct tm *t1, struct tm *t2) +{ + // + // Compare each field in descending signficance to determine if + // greater than, less than, or equal. + // + if(t1->tm_year > t2->tm_year) + { + return(1); + } + else if(t1->tm_year < t2->tm_year) + { + return(-1); + } + else if(t1->tm_mon > t2->tm_mon) + { + return(1); + } + else if(t1->tm_mon < t2->tm_mon) + { + return(-1); + } + else if(t1->tm_mday > t2->tm_mday) + { + return(1); + } + else if(t1->tm_mday < t2->tm_mday) + { + return(-1); + } + else if(t1->tm_hour > t2->tm_hour) + { + return(1); + } + else if(t1->tm_hour < t2->tm_hour) + { + return(-1); + } + else if(t1->tm_min > t2->tm_min) + { + return(1); + } + else if(t1->tm_min < t2->tm_min) + { + return(-1); + } + else if(t1->tm_sec > t2->tm_sec) + { + return(1); + } + else if(t1->tm_sec < t2->tm_sec) + { + return(-1); + } + else + { + // + // Reaching this branch of the conditional means that all of the + // fields are equal, and thus the two times are equal. + // + return(0); + } +} + +//***************************************************************************** +// +//! Converts calendar date and time to seconds. +//! +//! \param timeptr is a pointer to the time structure that is filled in with +//! the broken down date and time. +//! +//! This function converts the date and time represented by the \e timeptr +//! structure pointer to the number of seconds since midnight GMT on January 1, +//! 1970 (traditional Unix epoch). +//! +//! \return Returns the calendar time and date as seconds. If the conversion +//! was not possible then the function returns (uint32_t)(-1). +// +//***************************************************************************** +time_t +umktime(struct tm *timeptr) +{ + struct tm sTimeGuess; + unsigned long ulTimeGuess = 0x80000000; + unsigned long ulAdjust = 0x40000000; + int iSign; + + // + // Seed the binary search with the first guess. + // + ulocaltime(ulTimeGuess, &sTimeGuess); + iSign = ucmptime(timeptr, &sTimeGuess); + + // + // While the time is not yet found, execute a binary search. + // + while(iSign && ulAdjust) + { + // + // Adjust the time guess up or down depending on the result of the + // last compare. + // + ulTimeGuess = ((iSign > 0) ? (ulTimeGuess + ulAdjust) : + (ulTimeGuess - ulAdjust)); + ulAdjust /= 2; + + // + // Compare the new time guess against the time pointed at by the + // function parameters. + // + ulocaltime(ulTimeGuess, &sTimeGuess); + iSign = ucmptime(timeptr, &sTimeGuess); + } + + // + // If the above loop was exited with iSign == 0, that means that the + // time in seconds was found, so return that value to the caller. + // + if(iSign == 0) + { + return(ulTimeGuess); + } + + // + // Otherwise the time could not be converted so return an error. + // + else + { + return((unsigned long)-1); + } +} + +//***************************************************************************** +// +//! Converts a string into its numeric equivalent. +//! +//! \param nptr is a pointer to the string containing the integer. +//! \param endptr is a pointer that will be set to the first character past +//! the integer in the string. +//! \param base is the radix to use for the conversion; can be zero to +//! auto-select the radix or between 2 and 16 to explicitly specify the radix. +//! +//! This function is very similar to the C library strtoul() function. +//! It scans a string for the first token (that is, non-white space) and +//! converts the value at that location in the string into an integer value. +//! +//! \return Returns the result of the conversion. +// +//***************************************************************************** +unsigned long +ustrtoul(const char * restrict nptr, const char ** restrict endptr, int base) +{ + unsigned long ulRet, ulDigit, ulNeg, ulValid; + const char *pcPtr; + + // + // Check the arguments. + // + ASSERT(nptr); + ASSERT((base == 0) || ((base > 1) && (base <= 16))); + + // + // Initially, the result is zero. + // + ulRet = 0; + ulNeg = 0; + ulValid = 0; + + // + // Skip past any leading white space. + // + pcPtr = nptr; + while((*pcPtr == ' ') || (*pcPtr == '\t')) + { + pcPtr++; + } + + // + // Take a leading + or - from the value. + // + if(*pcPtr == '-') + { + ulNeg = 1; + pcPtr++; + } + else if(*pcPtr == '+') + { + pcPtr++; + } + + // + // See if the radix was not specified, or is 16, and the value starts with + // "0x" or "0X" (to indicate a hex value). + // + if(((base == 0) || (base == 16)) && (*pcPtr == '0') && + ((pcPtr[1] == 'x') || (pcPtr[1] == 'X'))) + { + // + // Skip the leading "0x". + // + pcPtr += 2; + + // + // Set the radix to 16. + // + base = 16; + } + + // + // See if the radix was not specified. + // + if(base == 0) + { + // + // See if the value starts with "0". + // + if(*pcPtr == '0') + { + // + // Values that start with "0" are assumed to be radix 8. + // + base = 8; + } + else + { + // + // Otherwise, the values are assumed to be radix 10. + // + base = 10; + } + } + + // + // Loop while there are more valid digits to consume. + // + while(1) + { + // + // See if this character is a number. + // + if((*pcPtr >= '0') && (*pcPtr <= '9')) + { + // + // Convert the character to its integer equivalent. + // + ulDigit = *pcPtr++ - '0'; + } + + // + // Otherwise, see if this character is an upper case letter. + // + else if((*pcPtr >= 'A') && (*pcPtr <= 'Z')) + { + // + // Convert the character to its integer equivalent. + // + ulDigit = *pcPtr++ - 'A' + 10; + } + + // + // Otherwise, see if this character is a lower case letter. + // + else if((*pcPtr >= 'a') && (*pcPtr <= 'z')) + { + // + // Convert the character to its integer equivalent. + // + ulDigit = *pcPtr++ - 'a' + 10; + } + + // + // Otherwise, this is not a valid character. + // + else + { + // + // Stop converting this value. + // + break; + } + + // + // See if this digit is valid for the chosen radix. + // + if(ulDigit >= base) + { + // + // Since this was not a valid digit, move the pointer back to the + // character that therefore should not have been consumed. + // + pcPtr--; + + // + // Stop converting this value. + // + break; + } + + // + // Add this digit to the converted value. + // + ulRet *= base; + ulRet += ulDigit; + + // + // Since a digit has been added, this is now a valid result. + // + ulValid = 1; + } + + // + // Set the return string pointer to the first character not consumed. + // + if(endptr) + { + *endptr = ulValid ? pcPtr : nptr; + } + + // + // Return the converted value. + // + return(ulNeg ? (0 - ulRet) : ulRet); +} + +//***************************************************************************** +// +// An array of the value of ten raised to the power-of-two exponents. This is +// used for converting the decimal exponent into the floating-point value of +// 10^exp. +// +//***************************************************************************** +static const float g_pfExponents[] = +{ + 1.0e+01, + 1.0e+02, + 1.0e+04, + 1.0e+08, + 1.0e+16, + 1.0e+32, +}; + +//***************************************************************************** +// +//! Converts a string into its floating-point equivalent. +//! +//! \param nptr is a pointer to the string containing the floating-point +//! value. +//! \param endptr is a pointer that will be set to the first character past +//! the floating-point value in the string. +//! +//! This function is very similar to the C library strtof() function. +//! It scans a string for the first token (that is, non-white space) and +//! converts the value at that location in the string into a floating-point +//! value. +//! +//! \return Returns the result of the conversion. +// +//***************************************************************************** +float +ustrtof(const char *nptr, const char **endptr) +{ + unsigned long ulNeg, ulValid; + float fRet; + const char *pcPtr; + + // + // Check the arguments. + // + ASSERT(nptr); + + // + // Initially, the result is zero. + // + fRet = 0; + ulNeg = 0; + ulValid = 0; + + // + // Skip past any leading white space. + // + pcPtr = nptr; + while((*pcPtr == ' ') || (*pcPtr == '\t')) + { + pcPtr++; + } + + // + // Take a leading + or - from the value. + // + if(*pcPtr == '-') + { + ulNeg = 1; + pcPtr++; + } + else if(*pcPtr == '+') + { + pcPtr++; + } + + // + // Loop while there are valid digits to consume. + // + while((*pcPtr >= '0') && (*pcPtr <= '9')) + { + // + // Add this digit to the converted value. + // + fRet *= 10; + fRet += *pcPtr++ - '0'; + + // + // Since a digit has been added, this is now a valid result. + // + ulValid = 1; + } + + // + // See if the next character is a period and the character after that is a + // digit, indicating the start of the fractional portion of the value. + // + if((*pcPtr == '.') && (pcPtr[1] >= '0') && (pcPtr[1] <= '9')) + { + // + // Skip the period. + // + pcPtr++; + + // + // Loop while there are valid fractional digits to consume. + // + float fDigit = 0.1; + while((*pcPtr >= '0') && (*pcPtr <= '9')) + { + // + // Add this digit to the converted value. + // + fRet += (*pcPtr++ - '0') * fDigit; + fDigit /= (float)10.0; + + // + // Since a digit has been added, this is now a valid result. + // + ulValid = 1; + } + } + + // + // See if the next character is an "e" and a valid number has been + // converted, indicating the start of the exponent. + // + if(((pcPtr[0] == 'e') || (pcPtr[0] == 'E')) && (ulValid == 1) && + (((pcPtr[1] >= '0') && (pcPtr[1] <= '9')) || + (((pcPtr[1] == '+') || (pcPtr[1] == '-')) && + (pcPtr[2] >= '0') && (pcPtr[2] <= '9')))) + { + // + // Skip the "e". + // + pcPtr++; + + // + // Take a leading + or - from the exponenet. + // + unsigned long ulExpNeg = 0; + if(*pcPtr == '-') + { + ulExpNeg = 1; + pcPtr++; + } + else if(*pcPtr == '+') + { + pcPtr++; + } + + // + // Loop while there are valid digits in the exponent. + // + unsigned long ulExp = 0; + while((*pcPtr >= '0') && (*pcPtr <= '9')) + { + // + // Add this digit to the converted value. + // + ulExp *= 10; + ulExp += *pcPtr++ - '0'; + } + + // + // Raise ten to the power of the exponent. Do this via binary + // decomposition; for each binary bit set in the exponent, multiply the + // floating-point representation by ten raised to that binary value + // (extracted from the table above). + // + float fExp = 1; + unsigned long ulIdx = 0; + for(; ulIdx < 7; ulIdx++) + { + if(ulExp & (1 << ulIdx)) + { + fExp *= g_pfExponents[ulIdx]; + } + } + + // + // If the exponent is negative, then the exponent needs to be inverted. + // + if(ulExpNeg == 1) + { + fExp = 1 / fExp; + } + + // + // Multiply the result by the computed exponent value. + // + fRet *= fExp; + } + + // + // Set the return string pointer to the first character not consumed. + // + if(endptr) + { + *endptr = ulValid ? pcPtr : nptr; + } + + // + // Return the converted value. + // + return(ulNeg ? (0 - fRet) : fRet); +} + +//***************************************************************************** +// +//! Returns the length of a null-terminated string. +//! +//! \param s is a pointer to the string whose length is to be found. +//! +//! This function is very similar to the C library strlen() function. +//! It determines the length of the null-terminated string passed and returns +//! this to the caller. +//! +//! This implementation assumes that single byte character strings are passed +//! and will return incorrect values if passed some UTF-8 strings. +//! +//! \return Returns the length of the string pointed to by \e s. +// +//***************************************************************************** +size_t +ustrlen(const char *s) +{ + size_t len; + + // + // Check the arguments. + // + ASSERT(s); + + // + // Initialize the length. + // + len = 0; + + // + // Step throug the string looking for a zero character (marking its end). + // + while(s[len]) + { + // + // Zero not found so move on to the next character. + // + len++; + } + + return(len); +} + +//***************************************************************************** +// +//! Finds a substring within a string. +//! +//! \param s1 is a pointer to the string that will be searched. +//! \param s2 is a pointer to the substring that is to be found within +//! \e s1. +//! +//! This function is very similar to the C library strstr() function. +//! It scans a string for the first instance of a given substring and returns +//! a pointer to that substring. If the substring cannot be found, a NULL +//! pointer is returned. +//! +//! \return Returns a pointer to the first occurrence of \e s2 within +//! \e s1 or NULL if no match is found. +// +//***************************************************************************** +char * +ustrstr(const char *s1, const char *s2) +{ + size_t n; + + // + // Get the length of the string to be found. + // + n = ustrlen(s2); + + // + // Loop while we have not reached the end of the string. + // + while(*s1) + { + // + // Check to see if the substring appears at this position. + // + if(ustrncmp(s2, s1, n) == 0) + { + // + // It does so return the pointer. + // + return((char *)s1); + } + + // + // Move to the next position in the string being searched. + // + s1++; + } + + // + // We reached the end of the string without finding the substring so + // return NULL. + // + return((char *)0); +} + +//***************************************************************************** +// +//! Compares two strings without regard to case. +//! +//! \param s1 points to the first string to be compared. +//! \param s2 points to the second string to be compared. +//! \param n is the maximum number of characters to compare. +//! +//! This function is very similar to the C library strncasecmp() +//! function. It compares at most \e n characters of two strings without +//! regard to case. The comparison ends if a terminating NULL character is +//! found in either string before \e n characters are compared. In this case, +//! the shorter string is deemed the lesser. +//! +//! \return Returns 0 if the two strings are equal, -1 if \e s1 is less +//! than \e s2 and 1 if \e s1 is greater than \e s2. +// +//***************************************************************************** +int +ustrncasecmp(const char *s1, const char *s2, size_t n) +{ + // + // Loop while there are more characters to compare. + // + while(n) + { + // + // If we reached a NULL in both strings, they must be equal so + // we end the comparison and return 0 + // + if(!*s1 && !*s2) + { + return(0); + } + + // + // Lower case the characters at the current position before we compare. + // + char c1 = (((*s1 >= 'A') && (*s1 <= 'Z')) ? (*s1 + ('a' - 'A')) : *s1); + char c2 = (((*s2 >= 'A') && (*s2 <= 'Z')) ? (*s2 + ('a' - 'A')) : *s2); + + // + // Compare the two characters and, if different, return the relevant + // return code. + // + if(c2 < c1) + { + return(1); + } + if(c1 < c2) + { + return(-1); + } + + // + // Move on to the next character. + // + s1++; + s2++; + n--; + } + + // + // If we fall out, the strings must be equal for at least the first n + // characters so return 0 to indicate this. + // + return(0); +} + +//***************************************************************************** +// +//! Compares two strings without regard to case. +//! +//! \param s1 points to the first string to be compared. +//! \param s2 points to the second string to be compared. +//! +//! This function is very similar to the C library strcasecmp() +//! function. It compares two strings without regard to case. The comparison +//! ends if a terminating NULL character is found in either string. In this +//! case, the int16_ter string is deemed the lesser. +//! +//! \return Returns 0 if the two strings are equal, -1 if \e s1 is less +//! than \e s2 and 1 if \e s1 is greater than \e s2. +// +//***************************************************************************** +int +ustrcasecmp(const char *s1, const char *s2) +{ + // + // Just let ustrncasecmp() handle this. + // + return(ustrncasecmp(s1, s2, (size_t)-1)); +} + +//***************************************************************************** +// +//! Compares two strings. +//! +//! \param s1 points to the first string to be compared. +//! \param s2 points to the second string to be compared. +//! \param n is the maximum number of characters to compare. +//! +//! This function is very similar to the C library strncmp() function. +//! It compares at most \e n characters of two strings taking case into +//! account. The comparison ends if a terminating NULL character is found in +//! either string before \e n characters are compared. In this case, the +//! int16_ter string is deemed the lesser. +//! +//! \return Returns 0 if the two strings are equal, -1 if \e s1 is less +//! than \e s2 and 1 if \e s1 is greater than \e s2. +// +//***************************************************************************** +int +ustrncmp(const char *s1, const char *s2, size_t n) +{ + // + // Loop while there are more characters. + // + while(n) + { + // + // If we reached a NULL in both strings, they must be equal so we end + // the comparison and return 0 + // + if(!*s1 && !*s2) + { + return(0); + } + + // + // Compare the two characters and, if different, return the relevant + // return code. + // + if(*s2 < *s1) + { + return(1); + } + if(*s1 < *s2) + { + return(-1); + } + + // + // Move on to the next character. + // + s1++; + s2++; + n--; + } + + // + // If we fall out, the strings must be equal for at least the first n + // characters so return 0 to indicate this. + // + return(0); +} + +//***************************************************************************** +// +//! Compares two strings. +//! +//! \param s1 points to the first string to be compared. +//! \param s2 points to the second string to be compared. +//! +//! This function is very similar to the C library strcmp() +//! function. It compares two strings, taking case into account. The +//! comparison ends if a terminating NULL character is found in either string. +//! In this case, the int16_ter string is deemed the lesser. +//! +//! \return Returns 0 if the two strings are equal, -1 if \e s1 is less +//! than \e s2 and 1 if \e s1 is greater than \e s2. +// +//***************************************************************************** +int +ustrcmp(const char *s1, const char *s2) +{ + // + // Pass this on to ustrncmp. + // + return(ustrncmp(s1, s2, (size_t)-1)); +} + +//***************************************************************************** +// +// Random Number Generator Seed Value +// +//***************************************************************************** +static unsigned int g_iRandomSeed = 1; + +//***************************************************************************** +// +//! Set the random number generator seed. +//! +//! \param seed is the new seed value to use for the random number +//! generator. +//! +//! This function is very similar to the C library srand() function. +//! It will set the seed value used in the urand() function. +//! +//! \return None +// +//***************************************************************************** +void +usrand(unsigned int seed) +{ + g_iRandomSeed = seed; +} + +//***************************************************************************** +// +//! Generate a new (pseudo) random number +//! +//! This function is very similar to the C library rand() function. +//! It will generate a pseudo-random number sequence based on the seed value. +//! +//! \return A pseudo-random number will be returned. +// +//***************************************************************************** +int +urand(void) +{ + // + // Generate a new pseudo-random number with a linear congruence random + // number generator. This new random number becomes the seed for the next + // random number. + // + g_iRandomSeed = (g_iRandomSeed * 1664525) + 1013904223; + + // + // Return the new random number. + // + return((int)g_iRandomSeed); +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.c b/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.c new file mode 100644 index 000000000..7493ef609 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.c @@ -0,0 +1,227 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: person.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "person-pb-c.h" +void address__init + (Address *message) +{ + static const Address init_value = ADDRESS__INIT; + *message = init_value; +} +size_t address__get_packed_size + (const Address *message) +{ + assert(message->base.descriptor == &address__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t address__pack + (const Address *message, + uint8_t *out) +{ + assert(message->base.descriptor == &address__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t address__pack_to_buffer + (const Address *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &address__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Address * + address__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Address *) + protobuf_c_message_unpack (&address__descriptor, + allocator, len, data); +} +void address__free_unpacked + (Address *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &address__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void person__init + (Person *message) +{ + static const Person init_value = PERSON__INIT; + *message = init_value; +} +size_t person__get_packed_size + (const Person *message) +{ + assert(message->base.descriptor == &person__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t person__pack + (const Person *message, + uint8_t *out) +{ + assert(message->base.descriptor == &person__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t person__pack_to_buffer + (const Person *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &person__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Person * + person__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Person *) + protobuf_c_message_unpack (&person__descriptor, + allocator, len, data); +} +void person__free_unpacked + (Person *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &person__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor address__field_descriptors[2] = +{ + { + "street", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Address, street), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "number", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(Address, has_number), + offsetof(Address, number), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned address__field_indices_by_name[] = { + 1, /* field[1] = number */ + 0, /* field[0] = street */ +}; +static const ProtobufCIntRange address__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor address__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "Address", + "Address", + "Address", + "", + sizeof(Address), + 2, + address__field_descriptors, + address__field_indices_by_name, + 1, address__number_ranges, + (ProtobufCMessageInit) address__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor person__field_descriptors[4] = +{ + { + "name", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Person, name), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "age", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(Person, has_age), + offsetof(Person, age), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "email", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Person, email), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "address", + 4, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Person, n_address), + offsetof(Person, address), + &address__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned person__field_indices_by_name[] = { + 3, /* field[3] = address */ + 1, /* field[1] = age */ + 2, /* field[2] = email */ + 0, /* field[0] = name */ +}; +static const ProtobufCIntRange person__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor person__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "Person", + "Person", + "Person", + "", + sizeof(Person), + 4, + person__field_descriptors, + person__field_indices_by_name, + 1, person__number_ranges, + (ProtobufCMessageInit) person__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.h b/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.h new file mode 100644 index 000000000..87b0007b1 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/protobuf-c/person-pb-c.h @@ -0,0 +1,112 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: person.proto */ + +#ifndef PROTOBUF_C_person_2eproto__INCLUDED +#define PROTOBUF_C_person_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _Address Address; +typedef struct _Person Person; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _Address +{ + ProtobufCMessage base; + char *street; + protobuf_c_boolean has_number; + int32_t number; +}; +#define ADDRESS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&address__descriptor) \ + , NULL, 0, 0 } + + +struct _Person +{ + ProtobufCMessage base; + char *name; + protobuf_c_boolean has_age; + int32_t age; + char *email; + size_t n_address; + Address **address; +}; +#define PERSON__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&person__descriptor) \ + , NULL, 0, 0, NULL, 0,NULL } + + +/* Address methods */ +void address__init + (Address *message); +size_t address__get_packed_size + (const Address *message); +size_t address__pack + (const Address *message, + uint8_t *out); +size_t address__pack_to_buffer + (const Address *message, + ProtobufCBuffer *buffer); +Address * + address__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void address__free_unpacked + (Address *message, + ProtobufCAllocator *allocator); +/* Person methods */ +void person__init + (Person *message); +size_t person__get_packed_size + (const Person *message); +size_t person__pack + (const Person *message, + uint8_t *out); +size_t person__pack_to_buffer + (const Person *message, + ProtobufCBuffer *buffer); +Person * + person__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void person__free_unpacked + (Person *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*Address_Closure) + (const Address *message, + void *closure_data); +typedef void (*Person_Closure) + (const Person *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor address__descriptor; +extern const ProtobufCMessageDescriptor person__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_person_2eproto__INCLUDED */ diff --git a/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.c b/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.c new file mode 100644 index 000000000..5debac820 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.c @@ -0,0 +1,3642 @@ +/* + * Copyright (c) 2008-2015, Dave Benson and the protobuf-c authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*! \file + * Support library for `protoc-c` generated code. + * + * This file implements the public API used by the code generated + * by `protoc-c`. + * + * \authors Dave Benson and the protobuf-c authors + * + * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license. + */ + +/** + * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math + * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64). + * + * \todo Use size_t consistently. + */ + +#include /* for malloc, free */ +#include /* for strcmp, strlen, memcpy, memmove, memset */ + +#include "protobuf-c.h" + +#define TRUE 1 +#define FALSE 0 + +#define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0) + +/* Workaround for Microsoft compilers. */ +#ifdef _MSC_VER +# define inline __inline +#endif + +/** + * \defgroup internal Internal functions and macros + * + * These are not exported by the library but are useful to developers working + * on `libprotobuf-c` itself. + */ + +/** + * \defgroup macros Utility macros for manipulating structures + * + * Macros and constants used to manipulate the base "classes" generated by + * `protobuf-c`. They also define limits and check correctness. + * + * \ingroup internal + * @{ + */ + +/** The maximum length of a 64-bit integer in varint encoding. */ +#define MAX_UINT64_ENCODED_SIZE 10 + +#ifndef PROTOBUF_C_UNPACK_ERROR +# define PROTOBUF_C_UNPACK_ERROR(...) +#endif + +const char protobuf_c_empty_string[] = ""; + +/** + * Internal `ProtobufCMessage` manipulation macro. + * + * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and + * STRUCT_MEMBER_PTR(). + */ +#define STRUCT_MEMBER_P(struct_p, struct_offset) \ + ((void *) ((uint8_t *) (struct_p) + (struct_offset))) + +/** + * Return field in a `ProtobufCMessage` based on offset. + * + * Take a pointer to a `ProtobufCMessage` and find the field at the offset. + * Cast it to the passed type. + */ +#define STRUCT_MEMBER(member_type, struct_p, struct_offset) \ + (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset))) + +/** + * Return field in a `ProtobufCMessage` based on offset. + * + * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast + * it to a pointer to the passed type. + */ +#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \ + ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset))) + +/* Assertions for magic numbers. */ + +#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC) + +#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC) + +#define ASSERT_IS_MESSAGE(message) \ + ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor) + +#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC) + +/**@}*/ + +/* --- version --- */ + +const char * +protobuf_c_version(void) +{ + return PROTOBUF_C_VERSION; +} + +uint32_t +protobuf_c_version_number(void) +{ + return PROTOBUF_C_VERSION_NUMBER; +} + +/* --- allocator --- */ + +static void * +system_alloc(void *allocator_data, size_t size) +{ + return malloc(size); +} + +static void +system_free(void *allocator_data, void *data) +{ + free(data); +} + +static inline void * +do_alloc(ProtobufCAllocator *allocator, size_t size) +{ + return allocator->alloc(allocator->allocator_data, size); +} + +static inline void +do_free(ProtobufCAllocator *allocator, void *data) +{ + if (data != NULL) + allocator->free(allocator->allocator_data, data); +} + +/* + * This allocator uses the system's malloc() and free(). It is the default + * allocator used if NULL is passed as the ProtobufCAllocator to an exported + * function. + */ +static ProtobufCAllocator protobuf_c__allocator = { + .alloc = &system_alloc, + .free = &system_free, + .allocator_data = NULL, +}; + +/* === buffer-simple === */ + +void +protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer, + size_t len, const uint8_t *data) +{ + ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer; + size_t new_len = simp->len + len; + + if (new_len > simp->alloced) { + ProtobufCAllocator *allocator = simp->allocator; + size_t new_alloced = simp->alloced * 2; + uint8_t *new_data; + + if (allocator == NULL) + allocator = &protobuf_c__allocator; + while (new_alloced < new_len) + new_alloced += new_alloced; + new_data = do_alloc(allocator, new_alloced); + if (!new_data) + return; + memcpy(new_data, simp->data, simp->len); + if (simp->must_free_data) + do_free(allocator, simp->data); + else + simp->must_free_data = TRUE; + simp->data = new_data; + simp->alloced = new_alloced; + } + memcpy(simp->data + simp->len, data, len); + simp->len = new_len; +} + +/** + * \defgroup packedsz protobuf_c_message_get_packed_size() implementation + * + * Routines mainly used by protobuf_c_message_get_packed_size(). + * + * \ingroup internal + * @{ + */ + +/** + * Return the number of bytes required to store the tag for the field. Includes + * 3 bits for the wire-type, and a single bit that denotes the end-of-tag. + * + * \param number + * Field tag to encode. + * \return + * Number of bytes required. + */ +static inline size_t +get_tag_size(uint32_t number) +{ + if (number < (1UL << 4)) { + return 1; + } else if (number < (1UL << 11)) { + return 2; + } else if (number < (1UL << 18)) { + return 3; + } else if (number < (1UL << 25)) { + return 4; + } else { + return 5; + } +} + +/** + * Return the number of bytes required to store a variable-length unsigned + * 32-bit integer in base-128 varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +uint32_size(uint32_t v) +{ + if (v < (1UL << 7)) { + return 1; + } else if (v < (1UL << 14)) { + return 2; + } else if (v < (1UL << 21)) { + return 3; + } else if (v < (1UL << 28)) { + return 4; + } else { + return 5; + } +} + +/** + * Return the number of bytes required to store a variable-length signed 32-bit + * integer in base-128 varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +int32_size(int32_t v) +{ + if (v < 0) { + return 10; + } else if (v < (1L << 7)) { + return 1; + } else if (v < (1L << 14)) { + return 2; + } else if (v < (1L << 21)) { + return 3; + } else if (v < (1L << 28)) { + return 4; + } else { + return 5; + } +} + +/** + * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed + * integer. + * + * \param v + * Value to encode. + * \return + * ZigZag encoded integer. + */ +static inline uint32_t +zigzag32(int32_t v) +{ + if (v < 0) + return (-(uint32_t)v) * 2 - 1; + else + return (uint32_t)(v) * 2; +} + +/** + * Return the number of bytes required to store a signed 32-bit integer, + * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128 + * varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +sint32_size(int32_t v) +{ + return uint32_size(zigzag32(v)); +} + +/** + * Return the number of bytes required to store a 64-bit unsigned integer in + * base-128 varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +uint64_size(uint64_t v) +{ + uint32_t upper_v = (uint32_t) (v >> 32); + + if (upper_v == 0) { + return uint32_size((uint32_t) v); + } else if (upper_v < (1UL << 3)) { + return 5; + } else if (upper_v < (1UL << 10)) { + return 6; + } else if (upper_v < (1UL << 17)) { + return 7; + } else if (upper_v < (1UL << 24)) { + return 8; + } else if (upper_v < (1UL << 31)) { + return 9; + } else { + return 10; + } +} + +/** + * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed + * integer. + * + * \param v + * Value to encode. + * \return + * ZigZag encoded integer. + */ +static inline uint64_t +zigzag64(int64_t v) +{ + if (v < 0) + return (-(uint64_t)v) * 2 - 1; + else + return (uint64_t)(v) * 2; +} + +/** + * Return the number of bytes required to store a signed 64-bit integer, + * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128 + * varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +sint64_size(int64_t v) +{ + return uint64_size(zigzag64(v)); +} + +/** + * Calculate the serialized size of a single required message field, including + * the space needed by the preceding tag. + * + * \param field + * Field descriptor for member. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +required_field_get_packed_size(const ProtobufCFieldDescriptor *field, + const void *member) +{ + size_t rv = get_tag_size(field->id); + + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + return rv + sint32_size(*(const int32_t *) member); + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + return rv + int32_size(*(const int32_t *) member); + case PROTOBUF_C_TYPE_UINT32: + return rv + uint32_size(*(const uint32_t *) member); + case PROTOBUF_C_TYPE_SINT64: + return rv + sint64_size(*(const int64_t *) member); + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + return rv + uint64_size(*(const uint64_t *) member); + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + return rv + 4; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + return rv + 8; + case PROTOBUF_C_TYPE_BOOL: + return rv + 1; + case PROTOBUF_C_TYPE_FLOAT: + return rv + 4; + case PROTOBUF_C_TYPE_DOUBLE: + return rv + 8; + case PROTOBUF_C_TYPE_STRING: { + const char *str = *(char * const *) member; + size_t len = str ? strlen(str) : 0; + return rv + uint32_size(len) + len; + } + case PROTOBUF_C_TYPE_BYTES: { + size_t len = ((const ProtobufCBinaryData *) member)->len; + return rv + uint32_size(len) + len; + } + case PROTOBUF_C_TYPE_MESSAGE: { + const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member; + size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0; + return rv + uint32_size(subrv) + subrv; + } + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Calculate the serialized size of a single oneof message field, including + * the space needed by the preceding tag. Returns 0 if the oneof field isn't + * selected or is not set. + * + * \param field + * Field descriptor for member. + * \param oneof_case + * Enum value that selects the field in the oneof. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +oneof_field_get_packed_size(const ProtobufCFieldDescriptor *field, + uint32_t oneof_case, + const void *member) +{ + if (oneof_case != field->id) { + return 0; + } + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } + return required_field_get_packed_size(field, member); +} + +/** + * Calculate the serialized size of a single optional message field, including + * the space needed by the preceding tag. Returns 0 if the optional field isn't + * set. + * + * \param field + * Field descriptor for member. + * \param has + * True if the field exists, false if not. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +optional_field_get_packed_size(const ProtobufCFieldDescriptor *field, + const protobuf_c_boolean has, + const void *member) +{ + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } else { + if (!has) + return 0; + } + return required_field_get_packed_size(field, member); +} + +static protobuf_c_boolean +field_is_zeroish(const ProtobufCFieldDescriptor *field, + const void *member) +{ + protobuf_c_boolean ret = FALSE; + + switch (field->type) { + case PROTOBUF_C_TYPE_BOOL: + ret = (0 == *(const protobuf_c_boolean *) member); + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + ret = (0 == *(const uint32_t *) member); + break; + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + ret = (0 == *(const uint64_t *) member); + break; + case PROTOBUF_C_TYPE_FLOAT: + ret = (0 == *(const float *) member); + break; + case PROTOBUF_C_TYPE_DOUBLE: + ret = (0 == *(const double *) member); + break; + case PROTOBUF_C_TYPE_STRING: + ret = (NULL == *(const char * const *) member) || + ('\0' == **(const char * const *) member); + break; + case PROTOBUF_C_TYPE_BYTES: + case PROTOBUF_C_TYPE_MESSAGE: + ret = (NULL == *(const void * const *) member); + break; + default: + ret = TRUE; + break; + } + + return ret; +} + +/** + * Calculate the serialized size of a single unlabeled message field, including + * the space needed by the preceding tag. Returns 0 if the field isn't set or + * if it is set to a "zeroish" value (null pointer or 0 for numerical values). + * Unlabeled fields are supported only in proto3. + * + * \param field + * Field descriptor for member. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +unlabeled_field_get_packed_size(const ProtobufCFieldDescriptor *field, + const void *member) +{ + if (field_is_zeroish(field, member)) + return 0; + return required_field_get_packed_size(field, member); +} + +/** + * Calculate the serialized size of repeated message fields, which may consist + * of any number of values (including 0). Includes the space needed by the + * preceding tags (as needed). + * + * \param field + * Field descriptor for member. + * \param count + * Number of repeated field members. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field, + size_t count, const void *member) +{ + size_t header_size; + size_t rv = 0; + unsigned i; + void *array = *(void * const *) member; + + if (count == 0) + return 0; + header_size = get_tag_size(field->id); + if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) + header_size *= count; + + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + for (i = 0; i < count; i++) + rv += sint32_size(((int32_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + for (i = 0; i < count; i++) + rv += int32_size(((int32_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_UINT32: + for (i = 0; i < count; i++) + rv += uint32_size(((uint32_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_SINT64: + for (i = 0; i < count; i++) + rv += sint64_size(((int64_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + for (i = 0; i < count; i++) + rv += uint64_size(((uint64_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + rv += 4 * count; + break; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + rv += 8 * count; + break; + case PROTOBUF_C_TYPE_BOOL: + rv += count; + break; + case PROTOBUF_C_TYPE_STRING: + for (i = 0; i < count; i++) { + size_t len = strlen(((char **) array)[i]); + rv += uint32_size(len) + len; + } + break; + case PROTOBUF_C_TYPE_BYTES: + for (i = 0; i < count; i++) { + size_t len = ((ProtobufCBinaryData *) array)[i].len; + rv += uint32_size(len) + len; + } + break; + case PROTOBUF_C_TYPE_MESSAGE: + for (i = 0; i < count; i++) { + size_t len = protobuf_c_message_get_packed_size( + ((ProtobufCMessage **) array)[i]); + rv += uint32_size(len) + len; + } + break; + } + + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) + header_size += uint32_size(rv); + return header_size + rv; +} + +/** + * Calculate the serialized size of an unknown field, i.e. one that is passed + * through mostly uninterpreted. This is required for forward compatibility if + * new fields are added to the message descriptor. + * + * \param field + * Unknown field type. + * \return + * Number of bytes required. + */ +static inline size_t +unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field) +{ + return get_tag_size(field->tag) + field->len; +} + +/**@}*/ + +/* + * Calculate the serialized size of the message. + */ +size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message) +{ + unsigned i; + size_t rv = 0; + + ASSERT_IS_MESSAGE(message); + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *field = + message->descriptor->fields + i; + const void *member = + ((const char *) message) + field->offset; + const void *qmember = + ((const char *) message) + field->quantifier_offset; + + if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + rv += required_field_get_packed_size(field, member); + } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL || + field->label == PROTOBUF_C_LABEL_NONE) && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) { + rv += oneof_field_get_packed_size( + field, + *(const uint32_t *) qmember, + member + ); + } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { + rv += optional_field_get_packed_size( + field, + *(protobuf_c_boolean *) qmember, + member + ); + } else if (field->label == PROTOBUF_C_LABEL_NONE) { + rv += unlabeled_field_get_packed_size( + field, + member + ); + } else { + rv += repeated_field_get_packed_size( + field, + *(const size_t *) qmember, + member + ); + } + } + for (i = 0; i < message->n_unknown_fields; i++) + rv += unknown_field_get_packed_size(&message->unknown_fields[i]); + return rv; +} + +/** + * \defgroup pack protobuf_c_message_pack() implementation + * + * Routines mainly used by protobuf_c_message_pack(). + * + * \ingroup internal + * @{ + */ + +/** + * Pack an unsigned 32-bit integer in base-128 varint encoding and return the + * number of bytes written, which must be 5 or less. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +uint32_pack(uint32_t value, uint8_t *out) +{ + unsigned rv = 0; + + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + } + } + } + } + /* assert: value<128 */ + out[rv++] = value; + return rv; +} + +/** + * Pack a signed 32-bit integer and return the number of bytes written. + * Negative numbers are encoded as two's complement 64-bit integers. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +int32_pack(int32_t value, uint8_t *out) +{ + if (value < 0) { + out[0] = value | 0x80; + out[1] = (value >> 7) | 0x80; + out[2] = (value >> 14) | 0x80; + out[3] = (value >> 21) | 0x80; + out[4] = (value >> 28) | 0x80; + out[5] = out[6] = out[7] = out[8] = 0xff; + out[9] = 0x01; + return 10; + } else { + return uint32_pack(value, out); + } +} + +/** + * Pack a signed 32-bit integer using ZigZag encoding and return the number of + * bytes written. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +sint32_pack(int32_t value, uint8_t *out) +{ + return uint32_pack(zigzag32(value), out); +} + +/** + * Pack a 64-bit unsigned integer using base-128 varint encoding and return the + * number of bytes written. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +uint64_pack(uint64_t value, uint8_t *out) +{ + uint32_t hi = (uint32_t) (value >> 32); + uint32_t lo = (uint32_t) value; + unsigned rv; + + if (hi == 0) + return uint32_pack((uint32_t) lo, out); + out[0] = (lo) | 0x80; + out[1] = (lo >> 7) | 0x80; + out[2] = (lo >> 14) | 0x80; + out[3] = (lo >> 21) | 0x80; + if (hi < 8) { + out[4] = (hi << 4) | (lo >> 28); + return 5; + } else { + out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80; + hi >>= 3; + } + rv = 5; + while (hi >= 128) { + out[rv++] = hi | 0x80; + hi >>= 7; + } + out[rv++] = hi; + return rv; +} + +/** + * Pack a 64-bit signed integer in ZigZag encoding and return the number of + * bytes written. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +sint64_pack(int64_t value, uint8_t *out) +{ + return uint64_pack(zigzag64(value), out); +} + +/** + * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire + * types fixed32, sfixed32, float. Similar to "htole32". + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +fixed32_pack(uint32_t value, void *out) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, &value, 4); +#else + uint8_t *buf = out; + + buf[0] = value; + buf[1] = value >> 8; + buf[2] = value >> 16; + buf[3] = value >> 24; +#endif + return 4; +} + +/** + * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire + * types fixed64, sfixed64, double. Similar to "htole64". + * + * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit + * version would be appreciated, plus a way to decide to use 64-bit math where + * convenient. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +fixed64_pack(uint64_t value, void *out) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, &value, 8); +#else + fixed32_pack(value, out); + fixed32_pack(value >> 32, ((char *) out) + 4); +#endif + return 8; +} + +/** + * Pack a boolean value as an integer and return the number of bytes written. + * + * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c + * that is idiomatic C++ in some STL implementations. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +boolean_pack(protobuf_c_boolean value, uint8_t *out) +{ + *out = value ? TRUE : FALSE; + return 1; +} + +/** + * Pack a NUL-terminated C string and return the number of bytes written. The + * output includes a length delimiter. + * + * The NULL pointer is treated as an empty string. This isn't really necessary, + * but it allows people to leave required strings blank. (See Issue #13 in the + * bug tracker for a little more explanation). + * + * \param str + * String to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +string_pack(const char *str, uint8_t *out) +{ + if (str == NULL) { + out[0] = 0; + return 1; + } else { + size_t len = strlen(str); + size_t rv = uint32_pack(len, out); + memcpy(out + rv, str, len); + return rv + len; + } +} + +/** + * Pack a ProtobufCBinaryData and return the number of bytes written. The output + * includes a length delimiter. + * + * \param bd + * ProtobufCBinaryData to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out) +{ + size_t len = bd->len; + size_t rv = uint32_pack(len, out); + memcpy(out + rv, bd->data, len); + return rv + len; +} + +/** + * Pack a ProtobufCMessage and return the number of bytes written. The output + * includes a length delimiter. + * + * \param message + * ProtobufCMessage object to pack. + * \param[out] out + * Packed message. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out) +{ + if (message == NULL) { + out[0] = 0; + return 1; + } else { + size_t rv = protobuf_c_message_pack(message, out + 1); + uint32_t rv_packed_size = uint32_size(rv); + if (rv_packed_size != 1) + memmove(out + rv_packed_size, out + 1, rv); + return uint32_pack(rv, out) + rv; + } +} + +/** + * Pack a field tag. + * + * Wire-type will be added in required_field_pack(). + * + * \todo Just call uint64_pack on 64-bit platforms. + * + * \param id + * Tag value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +tag_pack(uint32_t id, uint8_t *out) +{ + if (id < (1UL << (32 - 3))) + return uint32_pack(id << 3, out); + else + return uint64_pack(((uint64_t) id) << 3, out); +} + +/** + * Pack a required field and return the number of bytes written. + * + * \param field + * Field descriptor. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +required_field_pack(const ProtobufCFieldDescriptor *field, + const void *member, uint8_t *out) +{ + size_t rv = tag_pack(field->id, out); + + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + sint32_pack(*(const int32_t *) member, out + rv); + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + int32_pack(*(const int32_t *) member, out + rv); + case PROTOBUF_C_TYPE_UINT32: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + uint32_pack(*(const uint32_t *) member, out + rv); + case PROTOBUF_C_TYPE_SINT64: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + sint64_pack(*(const int64_t *) member, out + rv); + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + uint64_pack(*(const uint64_t *) member, out + rv); + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT; + return rv + fixed32_pack(*(const uint32_t *) member, out + rv); + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT; + return rv + fixed64_pack(*(const uint64_t *) member, out + rv); + case PROTOBUF_C_TYPE_BOOL: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv); + case PROTOBUF_C_TYPE_STRING: + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + return rv + string_pack(*(char *const *) member, out + rv); + case PROTOBUF_C_TYPE_BYTES: + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv); + case PROTOBUF_C_TYPE_MESSAGE: + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv); + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Pack a oneof field and return the number of bytes written. Only packs the + * field that is selected by the case enum. + * + * \param field + * Field descriptor. + * \param oneof_case + * Enum value that selects the field in the oneof. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +oneof_field_pack(const ProtobufCFieldDescriptor *field, + uint32_t oneof_case, + const void *member, uint8_t *out) +{ + if (oneof_case != field->id) { + return 0; + } + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } + return required_field_pack(field, member, out); +} + +/** + * Pack an optional field and return the number of bytes written. + * + * \param field + * Field descriptor. + * \param has + * Whether the field is set. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +optional_field_pack(const ProtobufCFieldDescriptor *field, + const protobuf_c_boolean has, + const void *member, uint8_t *out) +{ + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } else { + if (!has) + return 0; + } + return required_field_pack(field, member, out); +} + +/** + * Pack an unlabeled field and return the number of bytes written. + * + * \param field + * Field descriptor. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +unlabeled_field_pack(const ProtobufCFieldDescriptor *field, + const void *member, uint8_t *out) +{ + if (field_is_zeroish(field, member)) + return 0; + return required_field_pack(field, member, out); +} + +/** + * Given a field type, return the in-memory size. + * + * \todo Implement as a table lookup. + * + * \param type + * Field type. + * \return + * Size of the field. + */ +static inline size_t +sizeof_elt_in_repeated_array(ProtobufCType type) +{ + switch (type) { + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + case PROTOBUF_C_TYPE_ENUM: + return 4; + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + return 8; + case PROTOBUF_C_TYPE_BOOL: + return sizeof(protobuf_c_boolean); + case PROTOBUF_C_TYPE_STRING: + case PROTOBUF_C_TYPE_MESSAGE: + return sizeof(void *); + case PROTOBUF_C_TYPE_BYTES: + return sizeof(ProtobufCBinaryData); + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Pack an array of 32-bit quantities. + * + * \param[out] out + * Destination. + * \param[in] in + * Source. + * \param[in] n + * Number of elements in the source array. + */ +static void +copy_to_little_endian_32(void *out, const void *in, const unsigned n) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, in, n * 4); +#else + unsigned i; + const uint32_t *ini = in; + for (i = 0; i < n; i++) + fixed32_pack(ini[i], (uint32_t *) out + i); +#endif +} + +/** + * Pack an array of 64-bit quantities. + * + * \param[out] out + * Destination. + * \param[in] in + * Source. + * \param[in] n + * Number of elements in the source array. + */ +static void +copy_to_little_endian_64(void *out, const void *in, const unsigned n) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, in, n * 8); +#else + unsigned i; + const uint64_t *ini = in; + for (i = 0; i < n; i++) + fixed64_pack(ini[i], (uint64_t *) out + i); +#endif +} + +/** + * Get the minimum number of bytes required to pack a field value of a + * particular type. + * + * \param type + * Field type. + * \return + * Number of bytes. + */ +static unsigned +get_type_min_size(ProtobufCType type) +{ + if (type == PROTOBUF_C_TYPE_SFIXED32 || + type == PROTOBUF_C_TYPE_FIXED32 || + type == PROTOBUF_C_TYPE_FLOAT) + { + return 4; + } + if (type == PROTOBUF_C_TYPE_SFIXED64 || + type == PROTOBUF_C_TYPE_FIXED64 || + type == PROTOBUF_C_TYPE_DOUBLE) + { + return 8; + } + return 1; +} + +/** + * Packs the elements of a repeated field and returns the serialised field and + * its length. + * + * \param field + * Field descriptor. + * \param count + * Number of elements in the repeated field array. + * \param member + * Pointer to the elements for this repeated field. + * \param[out] out + * Serialised representation of the repeated field. + * \return + * Number of bytes serialised to `out`. + */ +static size_t +repeated_field_pack(const ProtobufCFieldDescriptor *field, + size_t count, const void *member, uint8_t *out) +{ + void *array = *(void * const *) member; + unsigned i; + + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) { + unsigned header_len; + unsigned len_start; + unsigned min_length; + unsigned payload_len; + unsigned length_size_min; + unsigned actual_length_size; + uint8_t *payload_at; + + if (count == 0) + return 0; + header_len = tag_pack(field->id, out); + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + len_start = header_len; + min_length = get_type_min_size(field->type) * count; + length_size_min = uint32_size(min_length); + header_len += length_size_min; + payload_at = out + header_len; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + copy_to_little_endian_32(payload_at, array, count); + payload_at += count * 4; + break; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + copy_to_little_endian_64(payload_at, array, count); + payload_at += count * 8; + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + payload_at += int32_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_SINT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + payload_at += sint32_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_SINT64: { + const int64_t *arr = (const int64_t *) array; + for (i = 0; i < count; i++) + payload_at += sint64_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_UINT32: { + const uint32_t *arr = (const uint32_t *) array; + for (i = 0; i < count; i++) + payload_at += uint32_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: { + const uint64_t *arr = (const uint64_t *) array; + for (i = 0; i < count; i++) + payload_at += uint64_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_BOOL: { + const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array; + for (i = 0; i < count; i++) + payload_at += boolean_pack(arr[i], payload_at); + break; + } + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + + payload_len = payload_at - (out + header_len); + actual_length_size = uint32_size(payload_len); + if (length_size_min != actual_length_size) { + assert(actual_length_size == length_size_min + 1); + memmove(out + header_len + 1, out + header_len, + payload_len); + header_len++; + } + uint32_pack(payload_len, out + len_start); + return header_len + payload_len; + } else { + /* not "packed" cased */ + /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */ + size_t rv = 0; + unsigned siz = sizeof_elt_in_repeated_array(field->type); + + for (i = 0; i < count; i++) { + rv += required_field_pack(field, array, out + rv); + array = (char *)array + siz; + } + return rv; + } +} + +static size_t +unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out) +{ + size_t rv = tag_pack(field->tag, out); + out[0] |= field->wire_type; + memcpy(out + rv, field->data, field->len); + return rv + field->len; +} + +/**@}*/ + +size_t +protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out) +{ + unsigned i; + size_t rv = 0; + + ASSERT_IS_MESSAGE(message); + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *field = + message->descriptor->fields + i; + const void *member = ((const char *) message) + field->offset; + + /* + * It doesn't hurt to compute qmember (a pointer to the + * quantifier field of the structure), but the pointer is only + * valid if the field is: + * - a repeated field, or + * - a field that is part of a oneof + * - an optional field that isn't a pointer type + * (Meaning: not a message or a string). + */ + const void *qmember = + ((const char *) message) + field->quantifier_offset; + + if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + rv += required_field_pack(field, member, out + rv); + } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL || + field->label == PROTOBUF_C_LABEL_NONE) && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) { + rv += oneof_field_pack( + field, + *(const uint32_t *) qmember, + member, + out + rv + ); + } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { + rv += optional_field_pack( + field, + *(const protobuf_c_boolean *) qmember, + member, + out + rv + ); + } else if (field->label == PROTOBUF_C_LABEL_NONE) { + rv += unlabeled_field_pack(field, member, out + rv); + } else { + rv += repeated_field_pack(field, *(const size_t *) qmember, + member, out + rv); + } + } + for (i = 0; i < message->n_unknown_fields; i++) + rv += unknown_field_pack(&message->unknown_fields[i], out + rv); + return rv; +} + +/** + * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation + * + * Routines mainly used by protobuf_c_message_pack_to_buffer(). + * + * \ingroup internal + * @{ + */ + +/** + * Pack a required field to a virtual buffer. + * + * \param field + * Field descriptor. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes packed. + */ +static size_t +required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + const void *member, ProtobufCBuffer *buffer) +{ + size_t rv; + uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; + + rv = tag_pack(field->id, scratch); + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += sint32_pack(*(const int32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += int32_pack(*(const int32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_UINT32: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += uint32_pack(*(const uint32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_SINT64: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += sint64_pack(*(const int64_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += uint64_pack(*(const uint64_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT; + rv += fixed32_pack(*(const uint32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT; + rv += fixed64_pack(*(const uint64_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_BOOL: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_STRING: { + const char *str = *(char *const *) member; + size_t sublen = str ? strlen(str) : 0; + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + rv += uint32_pack(sublen, scratch + rv); + buffer->append(buffer, rv, scratch); + buffer->append(buffer, sublen, (const uint8_t *) str); + rv += sublen; + break; + } + case PROTOBUF_C_TYPE_BYTES: { + const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member); + size_t sublen = bd->len; + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + rv += uint32_pack(sublen, scratch + rv); + buffer->append(buffer, rv, scratch); + buffer->append(buffer, sublen, bd->data); + rv += sublen; + break; + } + case PROTOBUF_C_TYPE_MESSAGE: { + uint8_t simple_buffer_scratch[256]; + size_t sublen; + const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member; + ProtobufCBufferSimple simple_buffer = + PROTOBUF_C_BUFFER_SIMPLE_INIT(simple_buffer_scratch); + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + if (msg == NULL) + sublen = 0; + else + sublen = protobuf_c_message_pack_to_buffer(msg, &simple_buffer.base); + rv += uint32_pack(sublen, scratch + rv); + buffer->append(buffer, rv, scratch); + buffer->append(buffer, sublen, simple_buffer.data); + rv += sublen; + PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple_buffer); + break; + } + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + return rv; +} + +/** + * Pack a oneof field to a buffer. Only packs the field that is selected by the case enum. + * + * \param field + * Field descriptor. + * \param oneof_case + * Enum value that selects the field in the oneof. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes serialised to `buffer`. + */ +static size_t +oneof_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + uint32_t oneof_case, + const void *member, ProtobufCBuffer *buffer) +{ + if (oneof_case != field->id) { + return 0; + } + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void *const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } + return required_field_pack_to_buffer(field, member, buffer); +} + +/** + * Pack an optional field to a buffer. + * + * \param field + * Field descriptor. + * \param has + * Whether the field is set. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes serialised to `buffer`. + */ +static size_t +optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + const protobuf_c_boolean has, + const void *member, ProtobufCBuffer *buffer) +{ + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void *const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } else { + if (!has) + return 0; + } + return required_field_pack_to_buffer(field, member, buffer); +} + +/** + * Pack an unlabeled field to a buffer. + * + * \param field + * Field descriptor. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes serialised to `buffer`. + */ +static size_t +unlabeled_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + const void *member, ProtobufCBuffer *buffer) +{ + if (field_is_zeroish(field, member)) + return 0; + return required_field_pack_to_buffer(field, member, buffer); +} + +/** + * Get the packed size of an array of same field type. + * + * \param field + * Field descriptor. + * \param count + * Number of elements of this type. + * \param array + * The elements to get the size of. + * \return + * Number of bytes required. + */ +static size_t +get_packed_payload_length(const ProtobufCFieldDescriptor *field, + unsigned count, const void *array) +{ + unsigned rv = 0; + unsigned i; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + return count * 4; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + return count * 8; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + rv += int32_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_SINT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + rv += sint32_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_UINT32: { + const uint32_t *arr = (const uint32_t *) array; + for (i = 0; i < count; i++) + rv += uint32_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_SINT64: { + const int64_t *arr = (const int64_t *) array; + for (i = 0; i < count; i++) + rv += sint64_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: { + const uint64_t *arr = (const uint64_t *) array; + for (i = 0; i < count; i++) + rv += uint64_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_BOOL: + return count; + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + return rv; +} + +/** + * Pack an array of same field type to a virtual buffer. + * + * \param field + * Field descriptor. + * \param count + * Number of elements of this type. + * \param array + * The elements to get the size of. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes packed. + */ +static size_t +pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field, + unsigned count, const void *array, + ProtobufCBuffer *buffer) +{ + uint8_t scratch[16]; + size_t rv = 0; + unsigned i; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: +#if !defined(WORDS_BIGENDIAN) + rv = count * 4; + goto no_packing_needed; +#else + for (i = 0; i < count; i++) { + unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; +#endif + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: +#if !defined(WORDS_BIGENDIAN) + rv = count * 8; + goto no_packing_needed; +#else + for (i = 0; i < count; i++) { + unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; +#endif + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + for (i = 0; i < count; i++) { + unsigned len = int32_pack(((int32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_SINT32: + for (i = 0; i < count; i++) { + unsigned len = sint32_pack(((int32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_UINT32: + for (i = 0; i < count; i++) { + unsigned len = uint32_pack(((uint32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_SINT64: + for (i = 0; i < count; i++) { + unsigned len = sint64_pack(((int64_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + for (i = 0; i < count; i++) { + unsigned len = uint64_pack(((uint64_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_BOOL: + for (i = 0; i < count; i++) { + unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + return count; + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + return rv; + +#if !defined(WORDS_BIGENDIAN) +no_packing_needed: + buffer->append(buffer, rv, array); + return rv; +#endif +} + +static size_t +repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + unsigned count, const void *member, + ProtobufCBuffer *buffer) +{ + char *array = *(char * const *) member; + + if (count == 0) + return 0; + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) { + uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; + size_t rv = tag_pack(field->id, scratch); + size_t payload_len = get_packed_payload_length(field, count, array); + size_t tmp; + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + rv += uint32_pack(payload_len, scratch + rv); + buffer->append(buffer, rv, scratch); + tmp = pack_buffer_packed_payload(field, count, array, buffer); + assert(tmp == payload_len); + return rv + payload_len; + } else { + size_t siz; + unsigned i; + /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */ + unsigned rv = 0; + + siz = sizeof_elt_in_repeated_array(field->type); + for (i = 0; i < count; i++) { + rv += required_field_pack_to_buffer(field, array, buffer); + array += siz; + } + return rv; + } +} + +static size_t +unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field, + ProtobufCBuffer *buffer) +{ + uint8_t header[MAX_UINT64_ENCODED_SIZE]; + size_t rv = tag_pack(field->tag, header); + + header[0] |= field->wire_type; + buffer->append(buffer, rv, header); + buffer->append(buffer, field->len, field->data); + return rv + field->len; +} + +/**@}*/ + +size_t +protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message, + ProtobufCBuffer *buffer) +{ + unsigned i; + size_t rv = 0; + + ASSERT_IS_MESSAGE(message); + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *field = + message->descriptor->fields + i; + const void *member = + ((const char *) message) + field->offset; + const void *qmember = + ((const char *) message) + field->quantifier_offset; + + if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + rv += required_field_pack_to_buffer(field, member, buffer); + } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL || + field->label == PROTOBUF_C_LABEL_NONE) && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) { + rv += oneof_field_pack_to_buffer( + field, + *(const uint32_t *) qmember, + member, + buffer + ); + } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { + rv += optional_field_pack_to_buffer( + field, + *(const protobuf_c_boolean *) qmember, + member, + buffer + ); + } else if (field->label == PROTOBUF_C_LABEL_NONE) { + rv += unlabeled_field_pack_to_buffer( + field, + member, + buffer + ); + } else { + rv += repeated_field_pack_to_buffer( + field, + *(const size_t *) qmember, + member, + buffer + ); + } + } + for (i = 0; i < message->n_unknown_fields; i++) + rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer); + + return rv; +} + +/** + * \defgroup unpack unpacking implementation + * + * Routines mainly used by the unpacking functions. + * + * \ingroup internal + * @{ + */ + +static inline int +int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value) +{ + unsigned n; + unsigned start; + + if (n_ranges == 0) + return -1; + start = 0; + n = n_ranges; + while (n > 1) { + unsigned mid = start + n / 2; + + if (value < ranges[mid].start_value) { + n = mid - start; + } else if (value >= ranges[mid].start_value + + (int) (ranges[mid + 1].orig_index - + ranges[mid].orig_index)) + { + unsigned new_start = mid + 1; + n = start + n - new_start; + start = new_start; + } else + return (value - ranges[mid].start_value) + + ranges[mid].orig_index; + } + if (n > 0) { + unsigned start_orig_index = ranges[start].orig_index; + unsigned range_size = + ranges[start + 1].orig_index - start_orig_index; + + if (ranges[start].start_value <= value && + value < (int) (ranges[start].start_value + range_size)) + { + return (value - ranges[start].start_value) + + start_orig_index; + } + } + return -1; +} + +static size_t +parse_tag_and_wiretype(size_t len, + const uint8_t *data, + uint32_t *tag_out, + ProtobufCWireType *wiretype_out) +{ + unsigned max_rv = len > 5 ? 5 : len; + uint32_t tag = (data[0] & 0x7f) >> 3; + unsigned shift = 4; + unsigned rv; + + *wiretype_out = data[0] & 7; + if ((data[0] & 0x80) == 0) { + *tag_out = tag; + return 1; + } + for (rv = 1; rv < max_rv; rv++) { + if (data[rv] & 0x80) { + tag |= (data[rv] & 0x7f) << shift; + shift += 7; + } else { + tag |= data[rv] << shift; + *tag_out = tag; + return rv + 1; + } + } + return 0; /* error: bad header */ +} + +/* sizeof(ScannedMember) must be <= (1UL< len) { + PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %u", val); + return 0; + } + return hdr_len + val; +} + +static size_t +max_b128_numbers(size_t len, const uint8_t *data) +{ + size_t rv = 0; + while (len--) + if ((*data++ & 0x80) == 0) + ++rv; + return rv; +} + +/**@}*/ + +/** + * Merge earlier message into a latter message. + * + * For numeric types and strings, if the same value appears multiple + * times, the parser accepts the last value it sees. For embedded + * message fields, the parser merges multiple instances of the same + * field. That is, all singular scalar fields in the latter instance + * replace those in the former, singular embedded messages are merged, + * and repeated fields are concatenated. + * + * The earlier message should be freed after calling this function, as + * some of its fields may have been reused and changed to their default + * values during the merge. + */ +static protobuf_c_boolean +merge_messages(ProtobufCMessage *earlier_msg, + ProtobufCMessage *latter_msg, + ProtobufCAllocator *allocator) +{ + unsigned i; + const ProtobufCFieldDescriptor *fields = + latter_msg->descriptor->fields; + for (i = 0; i < latter_msg->descriptor->n_fields; i++) { + if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) { + size_t *n_earlier = + STRUCT_MEMBER_PTR(size_t, earlier_msg, + fields[i].quantifier_offset); + uint8_t **p_earlier = + STRUCT_MEMBER_PTR(uint8_t *, earlier_msg, + fields[i].offset); + size_t *n_latter = + STRUCT_MEMBER_PTR(size_t, latter_msg, + fields[i].quantifier_offset); + uint8_t **p_latter = + STRUCT_MEMBER_PTR(uint8_t *, latter_msg, + fields[i].offset); + + if (*n_earlier > 0) { + if (*n_latter > 0) { + /* Concatenate the repeated field */ + size_t el_size = + sizeof_elt_in_repeated_array(fields[i].type); + uint8_t *new_field; + + new_field = do_alloc(allocator, + (*n_earlier + *n_latter) * el_size); + if (!new_field) + return FALSE; + + memcpy(new_field, *p_earlier, + *n_earlier * el_size); + memcpy(new_field + + *n_earlier * el_size, + *p_latter, + *n_latter * el_size); + + do_free(allocator, *p_latter); + do_free(allocator, *p_earlier); + *p_latter = new_field; + *n_latter = *n_earlier + *n_latter; + } else { + /* Zero copy the repeated field from the earlier message */ + *n_latter = *n_earlier; + *p_latter = *p_earlier; + } + /* Make sure the field does not get double freed */ + *n_earlier = 0; + *p_earlier = 0; + } + } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL || + fields[i].label == PROTOBUF_C_LABEL_NONE) { + const ProtobufCFieldDescriptor *field; + uint32_t *earlier_case_p = STRUCT_MEMBER_PTR(uint32_t, + earlier_msg, + fields[i]. + quantifier_offset); + uint32_t *latter_case_p = STRUCT_MEMBER_PTR(uint32_t, + latter_msg, + fields[i]. + quantifier_offset); + protobuf_c_boolean need_to_merge = FALSE; + void *earlier_elem; + void *latter_elem; + const void *def_val; + + if (fields[i].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) { + if (*latter_case_p == 0) { + /* lookup correct oneof field */ + int field_index = + int_range_lookup( + latter_msg->descriptor + ->n_field_ranges, + latter_msg->descriptor + ->field_ranges, + *earlier_case_p); + field = latter_msg->descriptor->fields + + field_index; + } else { + /* Oneof is present in the latter message, move on */ + continue; + } + } else { + field = &fields[i]; + } + + earlier_elem = STRUCT_MEMBER_P(earlier_msg, field->offset); + latter_elem = STRUCT_MEMBER_P(latter_msg, field->offset); + def_val = field->default_value; + + switch (field->type) { + case PROTOBUF_C_TYPE_MESSAGE: { + ProtobufCMessage *em = *(ProtobufCMessage **) earlier_elem; + ProtobufCMessage *lm = *(ProtobufCMessage **) latter_elem; + if (em != NULL) { + if (lm != NULL) { + if (!merge_messages(em, lm, allocator)) + return FALSE; + /* Already merged */ + need_to_merge = FALSE; + } else { + /* Zero copy the message */ + need_to_merge = TRUE; + } + } + break; + } + case PROTOBUF_C_TYPE_BYTES: { + uint8_t *e_data = + ((ProtobufCBinaryData *) earlier_elem)->data; + uint8_t *l_data = + ((ProtobufCBinaryData *) latter_elem)->data; + const ProtobufCBinaryData *d_bd = + (ProtobufCBinaryData *) def_val; + + need_to_merge = + (e_data != NULL && + (d_bd == NULL || + e_data != d_bd->data)) && + (l_data == NULL || + (d_bd != NULL && + l_data == d_bd->data)); + break; + } + case PROTOBUF_C_TYPE_STRING: { + char *e_str = *(char **) earlier_elem; + char *l_str = *(char **) latter_elem; + const char *d_str = def_val; + + need_to_merge = e_str != d_str && l_str == d_str; + break; + } + default: { + /* Could be has field or case enum, the logic is + * equivalent, since 0 (FALSE) means not set for + * oneof */ + need_to_merge = (*earlier_case_p != 0) && + (*latter_case_p == 0); + break; + } + } + + if (need_to_merge) { + size_t el_size = + sizeof_elt_in_repeated_array(field->type); + memcpy(latter_elem, earlier_elem, el_size); + /* + * Reset the element from the old message to 0 + * to make sure earlier message deallocation + * doesn't corrupt zero-copied data in the new + * message, earlier message will be freed after + * this function is called anyway + */ + memset(earlier_elem, 0, el_size); + + if (field->quantifier_offset != 0) { + /* Set the has field or the case enum, + * if applicable */ + *latter_case_p = *earlier_case_p; + *earlier_case_p = 0; + } + } + } + } + return TRUE; +} + +/** + * Count packed elements. + * + * Given a raw slab of packed-repeated values, determine the number of + * elements. This function detects certain kinds of errors but not + * others; the remaining error checking is done by + * parse_packed_repeated_member(). + */ +static protobuf_c_boolean +count_packed_elements(ProtobufCType type, + size_t len, const uint8_t *data, size_t *count_out) +{ + switch (type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + if (len % 4 != 0) { + PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types"); + return FALSE; + } + *count_out = len / 4; + return TRUE; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + if (len % 8 != 0) { + PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types"); + return FALSE; + } + *count_out = len / 8; + return TRUE; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_UINT64: + *count_out = max_b128_numbers(len, data); + return TRUE; + case PROTOBUF_C_TYPE_BOOL: + *count_out = len; + return TRUE; + case PROTOBUF_C_TYPE_STRING: + case PROTOBUF_C_TYPE_BYTES: + case PROTOBUF_C_TYPE_MESSAGE: + default: + PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type); + return FALSE; + } +} + +static inline uint32_t +parse_uint32(unsigned len, const uint8_t *data) +{ + uint32_t rv = data[0] & 0x7f; + if (len > 1) { + rv |= ((uint32_t) (data[1] & 0x7f) << 7); + if (len > 2) { + rv |= ((uint32_t) (data[2] & 0x7f) << 14); + if (len > 3) { + rv |= ((uint32_t) (data[3] & 0x7f) << 21); + if (len > 4) + rv |= ((uint32_t) (data[4]) << 28); + } + } + } + return rv; +} + +static inline uint32_t +parse_int32(unsigned len, const uint8_t *data) +{ + return parse_uint32(len, data); +} + +static inline int32_t +unzigzag32(uint32_t v) +{ + if (v & 1) + return -(v >> 1) - 1; + else + return v >> 1; +} + +static inline uint32_t +parse_fixed_uint32(const uint8_t *data) +{ +#if !defined(WORDS_BIGENDIAN) + uint32_t t; + memcpy(&t, data, 4); + return t; +#else + return data[0] | + ((uint32_t) (data[1]) << 8) | + ((uint32_t) (data[2]) << 16) | + ((uint32_t) (data[3]) << 24); +#endif +} + +static uint64_t +parse_uint64(unsigned len, const uint8_t *data) +{ + unsigned shift, i; + uint64_t rv; + + if (len < 5) + return parse_uint32(len, data); + rv = ((uint64_t) (data[0] & 0x7f)) | + ((uint64_t) (data[1] & 0x7f) << 7) | + ((uint64_t) (data[2] & 0x7f) << 14) | + ((uint64_t) (data[3] & 0x7f) << 21); + shift = 28; + for (i = 4; i < len; i++) { + rv |= (((uint64_t) (data[i] & 0x7f)) << shift); + shift += 7; + } + return rv; +} + +static inline int64_t +unzigzag64(uint64_t v) +{ + if (v & 1) + return -(v >> 1) - 1; + else + return v >> 1; +} + +static inline uint64_t +parse_fixed_uint64(const uint8_t *data) +{ +#if !defined(WORDS_BIGENDIAN) + uint64_t t; + memcpy(&t, data, 8); + return t; +#else + return (uint64_t) parse_fixed_uint32(data) | + (((uint64_t) parse_fixed_uint32(data + 4)) << 32); +#endif +} + +static protobuf_c_boolean +parse_boolean(unsigned len, const uint8_t *data) +{ + unsigned i; + for (i = 0; i < len; i++) + if (data[i] & 0x7f) + return TRUE; + return FALSE; +} + +static protobuf_c_boolean +parse_required_member(ScannedMember *scanned_member, + void *member, + ProtobufCAllocator *allocator, + protobuf_c_boolean maybe_clear) +{ + unsigned len = scanned_member->len; + const uint8_t *data = scanned_member->data; + ProtobufCWireType wire_type = scanned_member->wire_type; + + switch (scanned_member->field->type) { + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(int32_t *) member = parse_int32(len, data); + return TRUE; + case PROTOBUF_C_TYPE_UINT32: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(uint32_t *) member = parse_uint32(len, data); + return TRUE; + case PROTOBUF_C_TYPE_SINT32: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(int32_t *) member = unzigzag32(parse_uint32(len, data)); + return TRUE; + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT) + return FALSE; + *(uint32_t *) member = parse_fixed_uint32(data); + return TRUE; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(uint64_t *) member = parse_uint64(len, data); + return TRUE; + case PROTOBUF_C_TYPE_SINT64: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(int64_t *) member = unzigzag64(parse_uint64(len, data)); + return TRUE; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT) + return FALSE; + *(uint64_t *) member = parse_fixed_uint64(data); + return TRUE; + case PROTOBUF_C_TYPE_BOOL: + *(protobuf_c_boolean *) member = parse_boolean(len, data); + return TRUE; + case PROTOBUF_C_TYPE_STRING: { + char **pstr = member; + unsigned pref_len = scanned_member->length_prefix_len; + + if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) + return FALSE; + + if (maybe_clear && *pstr != NULL) { + const char *def = scanned_member->field->default_value; + if (*pstr != NULL && *pstr != def) + do_free(allocator, *pstr); + } + *pstr = do_alloc(allocator, len - pref_len + 1); + if (*pstr == NULL) + return FALSE; + memcpy(*pstr, data + pref_len, len - pref_len); + (*pstr)[len - pref_len] = 0; + return TRUE; + } + case PROTOBUF_C_TYPE_BYTES: { + ProtobufCBinaryData *bd = member; + const ProtobufCBinaryData *def_bd; + unsigned pref_len = scanned_member->length_prefix_len; + + if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) + return FALSE; + + def_bd = scanned_member->field->default_value; + if (maybe_clear && + bd->data != NULL && + (def_bd == NULL || bd->data != def_bd->data)) + { + do_free(allocator, bd->data); + } + if (len - pref_len > 0) { + bd->data = do_alloc(allocator, len - pref_len); + if (bd->data == NULL) + return FALSE; + memcpy(bd->data, data + pref_len, len - pref_len); + } else { + bd->data = NULL; + } + bd->len = len - pref_len; + return TRUE; + } + case PROTOBUF_C_TYPE_MESSAGE: { + ProtobufCMessage **pmessage = member; + ProtobufCMessage *subm; + const ProtobufCMessage *def_mess; + protobuf_c_boolean merge_successful = TRUE; + unsigned pref_len = scanned_member->length_prefix_len; + + if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) + return FALSE; + + def_mess = scanned_member->field->default_value; + subm = protobuf_c_message_unpack(scanned_member->field->descriptor, + allocator, + len - pref_len, + data + pref_len); + + if (maybe_clear && + *pmessage != NULL && + *pmessage != def_mess) + { + if (subm != NULL) + merge_successful = merge_messages(*pmessage, subm, allocator); + /* Delete the previous message */ + protobuf_c_message_free_unpacked(*pmessage, allocator); + } + *pmessage = subm; + if (subm == NULL || !merge_successful) + return FALSE; + return TRUE; + } + } + return FALSE; +} + +static protobuf_c_boolean +parse_oneof_member (ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + uint32_t *oneof_case = STRUCT_MEMBER_PTR(uint32_t, message, + scanned_member->field->quantifier_offset); + + /* If we have already parsed a member of this oneof, free it. */ + if (*oneof_case != 0) { + /* lookup field */ + int field_index = + int_range_lookup(message->descriptor->n_field_ranges, + message->descriptor->field_ranges, + *oneof_case); + const ProtobufCFieldDescriptor *old_field = + message->descriptor->fields + field_index; + size_t el_size = sizeof_elt_in_repeated_array(old_field->type); + + switch (old_field->type) { + case PROTOBUF_C_TYPE_STRING: { + char **pstr = member; + const char *def = old_field->default_value; + if (*pstr != NULL && *pstr != def) + do_free(allocator, *pstr); + break; + } + case PROTOBUF_C_TYPE_BYTES: { + ProtobufCBinaryData *bd = member; + const ProtobufCBinaryData *def_bd = old_field->default_value; + if (bd->data != NULL && + (def_bd == NULL || bd->data != def_bd->data)) + { + do_free(allocator, bd->data); + } + break; + } + case PROTOBUF_C_TYPE_MESSAGE: { + ProtobufCMessage **pmessage = member; + const ProtobufCMessage *def_mess = old_field->default_value; + if (*pmessage != NULL && *pmessage != def_mess) + protobuf_c_message_free_unpacked(*pmessage, allocator); + break; + } + default: + break; + } + + memset (member, 0, el_size); + } + if (!parse_required_member (scanned_member, member, allocator, TRUE)) + return FALSE; + + *oneof_case = scanned_member->tag; + return TRUE; +} + + +static protobuf_c_boolean +parse_optional_member(ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + if (!parse_required_member(scanned_member, member, allocator, TRUE)) + return FALSE; + if (scanned_member->field->quantifier_offset != 0) + STRUCT_MEMBER(protobuf_c_boolean, + message, + scanned_member->field->quantifier_offset) = TRUE; + return TRUE; +} + +static protobuf_c_boolean +parse_repeated_member(ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + const ProtobufCFieldDescriptor *field = scanned_member->field; + size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset); + size_t siz = sizeof_elt_in_repeated_array(field->type); + char *array = *(char **) member; + + if (!parse_required_member(scanned_member, array + siz * (*p_n), + allocator, FALSE)) + { + return FALSE; + } + *p_n += 1; + return TRUE; +} + +static unsigned +scan_varint(unsigned len, const uint8_t *data) +{ + unsigned i; + if (len > 10) + len = 10; + for (i = 0; i < len; i++) + if ((data[i] & 0x80) == 0) + break; + if (i == len) + return 0; + return i + 1; +} + +static protobuf_c_boolean +parse_packed_repeated_member(ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message) +{ + const ProtobufCFieldDescriptor *field = scanned_member->field; + size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset); + size_t siz = sizeof_elt_in_repeated_array(field->type); + void *array = *(char **) member + siz * (*p_n); + const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len; + size_t rem = scanned_member->len - scanned_member->length_prefix_len; + size_t count = 0; + unsigned i; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + count = (scanned_member->len - scanned_member->length_prefix_len) / 4; +#if !defined(WORDS_BIGENDIAN) + goto no_unpacking_needed; +#else + for (i = 0; i < count; i++) { + ((uint32_t *) array)[i] = parse_fixed_uint32(at); + at += 4; + } + break; +#endif + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + count = (scanned_member->len - scanned_member->length_prefix_len) / 8; +#if !defined(WORDS_BIGENDIAN) + goto no_unpacking_needed; +#else + for (i = 0; i < count; i++) { + ((uint64_t *) array)[i] = parse_fixed_uint64(at); + at += 8; + } + break; +#endif + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value"); + return FALSE; + } + ((int32_t *) array)[count++] = parse_int32(s, at); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_SINT32: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value"); + return FALSE; + } + ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at)); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_UINT32: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value"); + return FALSE; + } + ((uint32_t *) array)[count++] = parse_uint32(s, at); + at += s; + rem -= s; + } + break; + + case PROTOBUF_C_TYPE_SINT64: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value"); + return FALSE; + } + ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at)); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value"); + return FALSE; + } + ((int64_t *) array)[count++] = parse_uint64(s, at); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_BOOL: + count = rem; + for (i = 0; i < count; i++) { + if (at[i] > 1) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value"); + return FALSE; + } + ((protobuf_c_boolean *) array)[i] = at[i]; + } + break; + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + *p_n += count; + return TRUE; + +#if !defined(WORDS_BIGENDIAN) +no_unpacking_needed: + memcpy(array, at, count * siz); + *p_n += count; + return TRUE; +#endif +} + +static protobuf_c_boolean +is_packable_type(ProtobufCType type) +{ + return + type != PROTOBUF_C_TYPE_STRING && + type != PROTOBUF_C_TYPE_BYTES && + type != PROTOBUF_C_TYPE_MESSAGE; +} + +static protobuf_c_boolean +parse_member(ScannedMember *scanned_member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + const ProtobufCFieldDescriptor *field = scanned_member->field; + void *member; + + if (field == NULL) { + ProtobufCMessageUnknownField *ufield = + message->unknown_fields + + (message->n_unknown_fields++); + ufield->tag = scanned_member->tag; + ufield->wire_type = scanned_member->wire_type; + ufield->len = scanned_member->len; + ufield->data = do_alloc(allocator, scanned_member->len); + if (ufield->data == NULL) + return FALSE; + memcpy(ufield->data, scanned_member->data, ufield->len); + return TRUE; + } + member = (char *) message + field->offset; + switch (field->label) { + case PROTOBUF_C_LABEL_REQUIRED: + return parse_required_member(scanned_member, member, + allocator, TRUE); + case PROTOBUF_C_LABEL_OPTIONAL: + case PROTOBUF_C_LABEL_NONE: + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) { + return parse_oneof_member(scanned_member, member, + message, allocator); + } else { + return parse_optional_member(scanned_member, member, + message, allocator); + } + case PROTOBUF_C_LABEL_REPEATED: + if (scanned_member->wire_type == + PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) || + is_packable_type(field->type))) + { + return parse_packed_repeated_member(scanned_member, + member, message); + } else { + return parse_repeated_member(scanned_member, + member, message, + allocator); + } + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Initialise messages generated by old code. + * + * This function is used if desc->message_init == NULL (which occurs + * for old code, and which would be useful to support allocating + * descriptors dynamically). + */ +static void +message_init_generic(const ProtobufCMessageDescriptor *desc, + ProtobufCMessage *message) +{ + unsigned i; + + memset(message, 0, desc->sizeof_message); + message->descriptor = desc; + for (i = 0; i < desc->n_fields; i++) { + if (desc->fields[i].default_value != NULL && + desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED) + { + void *field = + STRUCT_MEMBER_P(message, desc->fields[i].offset); + const void *dv = desc->fields[i].default_value; + + switch (desc->fields[i].type) { + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + case PROTOBUF_C_TYPE_ENUM: + memcpy(field, dv, 4); + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_UINT64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + memcpy(field, dv, 8); + break; + case PROTOBUF_C_TYPE_BOOL: + memcpy(field, dv, sizeof(protobuf_c_boolean)); + break; + case PROTOBUF_C_TYPE_BYTES: + memcpy(field, dv, sizeof(ProtobufCBinaryData)); + break; + + case PROTOBUF_C_TYPE_STRING: + case PROTOBUF_C_TYPE_MESSAGE: + /* + * The next line essentially implements a cast + * from const, which is totally unavoidable. + */ + *(const void **) field = dv; + break; + } + } + } +} + +/**@}*/ + +/* + * ScannedMember slabs (an unpacking implementation detail). Before doing real + * unpacking, we first scan through the elements to see how many there are (for + * repeated fields), and which field to use (for non-repeated fields given + * twice). + * + * In order to avoid allocations for small messages, we keep a stack-allocated + * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we + * fill that up, we allocate each slab twice as large as the previous one. + */ +#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4 + +/* + * The number of slabs, including the stack-allocated ones; choose the number so + * that we would overflow if we needed a slab larger than provided. + */ +#define MAX_SCANNED_MEMBER_SLAB \ + (sizeof(unsigned int)*8 - 1 \ + - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \ + - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2) + +#define REQUIRED_FIELD_BITMAP_SET(index) \ + (required_fields_bitmap[(index)/8] |= (1UL<<((index)%8))) + +#define REQUIRED_FIELD_BITMAP_IS_SET(index) \ + (required_fields_bitmap[(index)/8] & (1UL<<((index)%8))) + +ProtobufCMessage * +protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc, + ProtobufCAllocator *allocator, + size_t len, const uint8_t *data) +{ + ProtobufCMessage *rv; + size_t rem = len; + const uint8_t *at = data; + const ProtobufCFieldDescriptor *last_field = desc->fields + 0; + ScannedMember first_member_slab[1UL << + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2]; + + /* + * scanned_member_slabs[i] is an array of arrays of ScannedMember. + * The first slab (scanned_member_slabs[0] is just a pointer to + * first_member_slab), above. All subsequent slabs will be allocated + * using the allocator. + */ + ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1]; + unsigned which_slab = 0; /* the slab we are currently populating */ + unsigned in_slab_index = 0; /* number of members in the slab */ + size_t n_unknown = 0; + unsigned f; + unsigned j; + unsigned i_slab; + unsigned last_field_index = 0; + unsigned required_fields_bitmap_len; + unsigned char required_fields_bitmap_stack[16]; + unsigned char *required_fields_bitmap = required_fields_bitmap_stack; + protobuf_c_boolean required_fields_bitmap_alloced = FALSE; + + ASSERT_IS_MESSAGE_DESCRIPTOR(desc); + + if (allocator == NULL) + allocator = &protobuf_c__allocator; + + rv = do_alloc(allocator, desc->sizeof_message); + if (!rv) + return (NULL); + scanned_member_slabs[0] = first_member_slab; + + required_fields_bitmap_len = (desc->n_fields + 7) / 8; + if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) { + required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len); + if (!required_fields_bitmap) { + do_free(allocator, rv); + return (NULL); + } + required_fields_bitmap_alloced = TRUE; + } + memset(required_fields_bitmap, 0, required_fields_bitmap_len); + + /* + * Generated code always defines "message_init". However, we provide a + * fallback for (1) users of old protobuf-c generated-code that do not + * provide the function, and (2) descriptors constructed from some other + * source (most likely, direct construction from the .proto file). + */ + if (desc->message_init != NULL) + protobuf_c_message_init(desc, rv); + else + message_init_generic(desc, rv); + + while (rem > 0) { + uint32_t tag; + ProtobufCWireType wire_type; + size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type); + const ProtobufCFieldDescriptor *field; + ScannedMember tmp; + + if (used == 0) { + PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + /* + * \todo Consider optimizing for field[1].id == tag, if field[1] + * exists! + */ + if (last_field == NULL || last_field->id != tag) { + /* lookup field */ + int field_index = + int_range_lookup(desc->n_field_ranges, + desc->field_ranges, + tag); + if (field_index < 0) { + field = NULL; + n_unknown++; + } else { + field = desc->fields + field_index; + last_field = field; + last_field_index = field_index; + } + } else { + field = last_field; + } + + if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED) + REQUIRED_FIELD_BITMAP_SET(last_field_index); + + at += used; + rem -= used; + tmp.tag = tag; + tmp.wire_type = wire_type; + tmp.field = field; + tmp.data = at; + tmp.length_prefix_len = 0; + + switch (wire_type) { + case PROTOBUF_C_WIRE_TYPE_VARINT: { + unsigned max_len = rem < 10 ? rem : 10; + unsigned i; + + for (i = 0; i < max_len; i++) + if ((at[i] & 0x80) == 0) + break; + if (i == max_len) { + PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + tmp.len = i + 1; + break; + } + case PROTOBUF_C_WIRE_TYPE_64BIT: + if (rem < 8) { + PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + tmp.len = 8; + break; + case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: { + size_t pref_len; + + tmp.len = scan_length_prefixed_data(rem, at, &pref_len); + if (tmp.len == 0) { + /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */ + goto error_cleanup_during_scan; + } + tmp.length_prefix_len = pref_len; + break; + } + case PROTOBUF_C_WIRE_TYPE_32BIT: + if (rem < 4) { + PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + tmp.len = 4; + break; + default: + PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u", + wire_type, (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + + if (in_slab_index == (1UL << + (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2))) + { + size_t size; + + in_slab_index = 0; + if (which_slab == MAX_SCANNED_MEMBER_SLAB) { + PROTOBUF_C_UNPACK_ERROR("too many fields"); + goto error_cleanup_during_scan; + } + which_slab++; + size = sizeof(ScannedMember) + << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2); + scanned_member_slabs[which_slab] = do_alloc(allocator, size); + if (scanned_member_slabs[which_slab] == NULL) + goto error_cleanup_during_scan; + } + scanned_member_slabs[which_slab][in_slab_index++] = tmp; + + if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) { + size_t *n = STRUCT_MEMBER_PTR(size_t, rv, + field->quantifier_offset); + if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) || + is_packable_type(field->type))) + { + size_t count; + if (!count_packed_elements(field->type, + tmp.len - + tmp.length_prefix_len, + tmp.data + + tmp.length_prefix_len, + &count)) + { + PROTOBUF_C_UNPACK_ERROR("counting packed elements"); + goto error_cleanup_during_scan; + } + *n += count; + } else { + *n += 1; + } + } + + at += tmp.len; + rem -= tmp.len; + } + + /* allocate space for repeated fields, also check that all required fields have been set */ + for (f = 0; f < desc->n_fields; f++) { + const ProtobufCFieldDescriptor *field = desc->fields + f; + if (field->label == PROTOBUF_C_LABEL_REPEATED) { + size_t siz = + sizeof_elt_in_repeated_array(field->type); + size_t *n_ptr = + STRUCT_MEMBER_PTR(size_t, rv, + field->quantifier_offset); + if (*n_ptr != 0) { + unsigned n = *n_ptr; + void *a; + *n_ptr = 0; + assert(rv->descriptor != NULL); +#define CLEAR_REMAINING_N_PTRS() \ + for(f++;f < desc->n_fields; f++) \ + { \ + field = desc->fields + f; \ + if (field->label == PROTOBUF_C_LABEL_REPEATED) \ + STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \ + } + a = do_alloc(allocator, siz * n); + if (!a) { + CLEAR_REMAINING_N_PTRS(); + goto error_cleanup; + } + STRUCT_MEMBER(void *, rv, field->offset) = a; + } + } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + if (field->default_value == NULL && + !REQUIRED_FIELD_BITMAP_IS_SET(f)) + { + CLEAR_REMAINING_N_PTRS(); + PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'", + desc->name, field->name); + goto error_cleanup; + } + } + } +#undef CLEAR_REMAINING_N_PTRS + + /* allocate space for unknown fields */ + if (n_unknown) { + rv->unknown_fields = do_alloc(allocator, + n_unknown * sizeof(ProtobufCMessageUnknownField)); + if (rv->unknown_fields == NULL) + goto error_cleanup; + } + + /* do real parsing */ + for (i_slab = 0; i_slab <= which_slab; i_slab++) { + unsigned max = (i_slab == which_slab) ? + in_slab_index : (1UL << (i_slab + 4)); + ScannedMember *slab = scanned_member_slabs[i_slab]; + + for (j = 0; j < max; j++) { + if (!parse_member(slab + j, rv, allocator)) { + PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s", + slab->field ? slab->field->name : "*unknown-field*", + desc->name); + goto error_cleanup; + } + } + } + + /* cleanup */ + for (j = 1; j <= which_slab; j++) + do_free(allocator, scanned_member_slabs[j]); + if (required_fields_bitmap_alloced) + do_free(allocator, required_fields_bitmap); + return rv; + +error_cleanup: + protobuf_c_message_free_unpacked(rv, allocator); + for (j = 1; j <= which_slab; j++) + do_free(allocator, scanned_member_slabs[j]); + if (required_fields_bitmap_alloced) + do_free(allocator, required_fields_bitmap); + return NULL; + +error_cleanup_during_scan: + do_free(allocator, rv); + for (j = 1; j <= which_slab; j++) + do_free(allocator, scanned_member_slabs[j]); + if (required_fields_bitmap_alloced) + do_free(allocator, required_fields_bitmap); + return NULL; +} + +void +protobuf_c_message_free_unpacked(ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + const ProtobufCMessageDescriptor *desc; + unsigned f; + + if (message == NULL) + return; + + desc = message->descriptor; + + ASSERT_IS_MESSAGE(message); + + if (allocator == NULL) + allocator = &protobuf_c__allocator; + message->descriptor = NULL; + for (f = 0; f < desc->n_fields; f++) { + if (0 != (desc->fields[f].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) && + desc->fields[f].id != + STRUCT_MEMBER(uint32_t, message, desc->fields[f].quantifier_offset)) + { + /* This is not the selected oneof, skip it */ + continue; + } + + if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) { + size_t n = STRUCT_MEMBER(size_t, + message, + desc->fields[f].quantifier_offset); + void *arr = STRUCT_MEMBER(void *, + message, + desc->fields[f].offset); + + if (arr != NULL) { + if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { + unsigned i; + for (i = 0; i < n; i++) + do_free(allocator, ((char **) arr)[i]); + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { + unsigned i; + for (i = 0; i < n; i++) + do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data); + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { + unsigned i; + for (i = 0; i < n; i++) + protobuf_c_message_free_unpacked( + ((ProtobufCMessage **) arr)[i], + allocator + ); + } + do_free(allocator, arr); + } + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { + char *str = STRUCT_MEMBER(char *, message, + desc->fields[f].offset); + + if (str && str != desc->fields[f].default_value) + do_free(allocator, str); + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { + void *data = STRUCT_MEMBER(ProtobufCBinaryData, message, + desc->fields[f].offset).data; + const ProtobufCBinaryData *default_bd; + + default_bd = desc->fields[f].default_value; + if (data != NULL && + (default_bd == NULL || + default_bd->data != data)) + { + do_free(allocator, data); + } + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { + ProtobufCMessage *sm; + + sm = STRUCT_MEMBER(ProtobufCMessage *, message, + desc->fields[f].offset); + if (sm && sm != desc->fields[f].default_value) + protobuf_c_message_free_unpacked(sm, allocator); + } + } + + for (f = 0; f < message->n_unknown_fields; f++) + do_free(allocator, message->unknown_fields[f].data); + if (message->unknown_fields != NULL) + do_free(allocator, message->unknown_fields); + + do_free(allocator, message); +} + +void +protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor, + void *message) +{ + descriptor->message_init((ProtobufCMessage *) (message)); +} + +protobuf_c_boolean +protobuf_c_message_check(const ProtobufCMessage *message) +{ + unsigned i; + + if (!message || + !message->descriptor || + message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC) + { + return FALSE; + } + + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *f = message->descriptor->fields + i; + ProtobufCType type = f->type; + ProtobufCLabel label = f->label; + void *field = STRUCT_MEMBER_P (message, f->offset); + + if (label == PROTOBUF_C_LABEL_REPEATED) { + size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset); + + if (*quantity > 0 && *(void **) field == NULL) { + return FALSE; + } + + if (type == PROTOBUF_C_TYPE_MESSAGE) { + ProtobufCMessage **submessage = *(ProtobufCMessage ***) field; + unsigned j; + for (j = 0; j < *quantity; j++) { + if (!protobuf_c_message_check(submessage[j])) + return FALSE; + } + } else if (type == PROTOBUF_C_TYPE_STRING) { + char **string = *(char ***) field; + unsigned j; + for (j = 0; j < *quantity; j++) { + if (!string[j]) + return FALSE; + } + } else if (type == PROTOBUF_C_TYPE_BYTES) { + ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field; + unsigned j; + for (j = 0; j < *quantity; j++) { + if (bd[j].len > 0 && bd[j].data == NULL) + return FALSE; + } + } + + } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */ + + if (type == PROTOBUF_C_TYPE_MESSAGE) { + ProtobufCMessage *submessage = *(ProtobufCMessage **) field; + if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) { + if (!protobuf_c_message_check(submessage)) + return FALSE; + } + } else if (type == PROTOBUF_C_TYPE_STRING) { + char *string = *(char **) field; + if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL) + return FALSE; + } else if (type == PROTOBUF_C_TYPE_BYTES) { + protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset); + ProtobufCBinaryData *bd = field; + if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) { + if (bd->len > 0 && bd->data == NULL) + return FALSE; + } + } + } + } + + return TRUE; +} + +/* === services === */ + +typedef void (*GenericHandler) (void *service, + const ProtobufCMessage *input, + ProtobufCClosure closure, + void *closure_data); +void +protobuf_c_service_invoke_internal(ProtobufCService *service, + unsigned method_index, + const ProtobufCMessage *input, + ProtobufCClosure closure, + void *closure_data) +{ + GenericHandler *handlers; + GenericHandler handler; + + /* + * Verify that method_index is within range. If this fails, you are + * likely invoking a newly added method on an old service. (Although + * other memory corruption bugs can cause this assertion too.) + */ + assert(method_index < service->descriptor->n_methods); + + /* + * Get the array of virtual methods (which are enumerated by the + * generated code). + */ + handlers = (GenericHandler *) (service + 1); + + /* + * Get our method and invoke it. + * \todo Seems like handler == NULL is a situation that needs handling. + */ + handler = handlers[method_index]; + (*handler)(service, input, closure, closure_data); +} + +void +protobuf_c_service_generated_init(ProtobufCService *service, + const ProtobufCServiceDescriptor *descriptor, + ProtobufCServiceDestroy destroy) +{ + ASSERT_IS_SERVICE_DESCRIPTOR(descriptor); + service->descriptor = descriptor; + service->destroy = destroy; + service->invoke = protobuf_c_service_invoke_internal; + memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler)); +} + +void protobuf_c_service_destroy(ProtobufCService *service) +{ + service->destroy(service); +} + +/* --- querying the descriptors --- */ + +const ProtobufCEnumValue * +protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc, + const char *name) +{ + unsigned start = 0; + unsigned count; + + if (desc == NULL || desc->values_by_name == NULL) + return NULL; + + count = desc->n_value_names; + + while (count > 1) { + unsigned mid = start + count / 2; + int rv = strcmp(desc->values_by_name[mid].name, name); + if (rv == 0) + return desc->values + desc->values_by_name[mid].index; + else if (rv < 0) { + count = start + count - (mid + 1); + start = mid + 1; + } else + count = mid - start; + } + if (count == 0) + return NULL; + if (strcmp(desc->values_by_name[start].name, name) == 0) + return desc->values + desc->values_by_name[start].index; + return NULL; +} + +const ProtobufCEnumValue * +protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc, + int value) +{ + int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value); + if (rv < 0) + return NULL; + return desc->values + rv; +} + +const ProtobufCFieldDescriptor * +protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc, + const char *name) +{ + unsigned start = 0; + unsigned count; + const ProtobufCFieldDescriptor *field; + + if (desc == NULL || desc->fields_sorted_by_name == NULL) + return NULL; + + count = desc->n_fields; + + while (count > 1) { + unsigned mid = start + count / 2; + int rv; + field = desc->fields + desc->fields_sorted_by_name[mid]; + rv = strcmp(field->name, name); + if (rv == 0) + return field; + else if (rv < 0) { + count = start + count - (mid + 1); + start = mid + 1; + } else + count = mid - start; + } + if (count == 0) + return NULL; + field = desc->fields + desc->fields_sorted_by_name[start]; + if (strcmp(field->name, name) == 0) + return field; + return NULL; +} + +const ProtobufCFieldDescriptor * +protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc, + unsigned value) +{ + int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value); + if (rv < 0) + return NULL; + return desc->fields + rv; +} + +const ProtobufCMethodDescriptor * +protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc, + const char *name) +{ + unsigned start = 0; + unsigned count; + + if (desc == NULL || desc->method_indices_by_name == NULL) + return NULL; + + count = desc->n_methods; + + while (count > 1) { + unsigned mid = start + count / 2; + unsigned mid_index = desc->method_indices_by_name[mid]; + const char *mid_name = desc->methods[mid_index].name; + int rv = strcmp(mid_name, name); + + if (rv == 0) + return desc->methods + desc->method_indices_by_name[mid]; + if (rv < 0) { + count = start + count - (mid + 1); + start = mid + 1; + } else { + count = mid - start; + } + } + if (count == 0) + return NULL; + if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0) + return desc->methods + desc->method_indices_by_name[start]; + return NULL; +} diff --git a/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.h b/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.h new file mode 100644 index 000000000..c8fa4fc2a --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/protobuf-c/protobuf-c.h @@ -0,0 +1,1106 @@ +/* + * Copyright (c) 2008-2017, Dave Benson and the protobuf-c authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*! \file + * \mainpage Introduction + * + * This is [protobuf-c], a C implementation of [Protocol Buffers]. + * + * This file defines the public API for the `libprotobuf-c` support library. + * This API includes interfaces that can be used directly by client code as well + * as the interfaces used by the code generated by the `protoc-c` compiler. + * + * The `libprotobuf-c` support library performs the actual serialization and + * deserialization of Protocol Buffers messages. It interacts with structures, + * definitions, and metadata generated by the `protoc-c` compiler from .proto + * files. + * + * \authors Dave Benson and the `protobuf-c` authors. + * + * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license. + * + * [protobuf-c]: https://github.com/protobuf-c/protobuf-c + * [Protocol Buffers]: https://developers.google.com/protocol-buffers/ + * [BSD-2-Clause]: http://opensource.org/licenses/BSD-2-Clause + * + * \page gencode Generated Code + * + * For each enum, we generate a C enum. For each message, we generate a C + * structure which can be cast to a `ProtobufCMessage`. + * + * For each enum and message, we generate a descriptor object that allows us to + * implement a kind of reflection on the structures. + * + * First, some naming conventions: + * + * - The name of the type for enums and messages and services is camel case + * (meaning WordsAreCrammedTogether) except that double underscores are used + * to delimit scopes. For example, the following `.proto` file: + * +~~~{.proto} + package foo.bar; + message BazBah { + optional int32 val = 1; + } +~~~ + * + * would generate a C type `Foo__Bar__BazBah`. + * + * - Identifiers for functions and globals are all lowercase, with camel case + * words separated by single underscores. For example, one of the function + * prototypes generated by `protoc-c` for the above example: + * +~~~{.c} +Foo__Bar__BazBah * + foo__bar__baz_bah__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +~~~ + * + * - Identifiers for enum values contain an uppercase prefix which embeds the + * package name and the enum type name. + * + * - A double underscore is used to separate further components of identifier + * names. + * + * For example, in the name of the unpack function above, the package name + * `foo.bar` has become `foo__bar`, the message name BazBah has become + * `baz_bah`, and the method name is `unpack`. These are all joined with double + * underscores to form the C identifier `foo__bar__baz_bah__unpack`. + * + * We also generate descriptor objects for messages and enums. These are + * declared in the `.pb-c.h` files: + * +~~~{.c} +extern const ProtobufCMessageDescriptor foo__bar__baz_bah__descriptor; +~~~ + * + * The message structures all begin with `ProtobufCMessageDescriptor *` which is + * sufficient to allow them to be cast to `ProtobufCMessage`. + * + * For each message defined in a `.proto` file, we generate a number of + * functions and macros. Each function name contains a prefix based on the + * package name and message name in order to make it a unique C identifier. + * + * - `INIT`. Statically initializes a message object, initializing its + * descriptor and setting its fields to default values. Uninitialized + * messages cannot be processed by the protobuf-c library. + * +~~~{.c} +#define FOO__BAR__BAZ_BAH__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&foo__bar__baz_bah__descriptor), 0 } +~~~ + * - `init()`. Initializes a message object, initializing its descriptor and + * setting its fields to default values. Uninitialized messages cannot be + * processed by the protobuf-c library. + * +~~~{.c} +void foo__bar__baz_bah__init + (Foo__Bar__BazBah *message); +~~~ + * - `unpack()`. Unpacks data for a particular message format. Note that the + * `allocator` parameter is usually `NULL` to indicate that the system's + * `malloc()` and `free()` functions should be used for dynamically allocating + * memory. + * +~~~{.c} +Foo__Bar__BazBah * + foo__bar__baz_bah__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +~~~ + * + * - `free_unpacked()`. Frees a message object obtained with the `unpack()` + * method. Freeing `NULL` is allowed (the same as with `free()`). + * +~~~{.c} +void foo__bar__baz_bah__free_unpacked + (Foo__Bar__BazBah *message, + ProtobufCAllocator *allocator); +~~~ + * + * - `get_packed_size()`. Calculates the length in bytes of the serialized + * representation of the message object. + * +~~~{.c} +size_t foo__bar__baz_bah__get_packed_size + (const Foo__Bar__BazBah *message); +~~~ + * + * - `pack()`. Pack a message object into a preallocated buffer. Assumes that + * the buffer is large enough. (Use `get_packed_size()` first.) + * +~~~{.c} +size_t foo__bar__baz_bah__pack + (const Foo__Bar__BazBah *message, + uint8_t *out); +~~~ + * + * - `pack_to_buffer()`. Packs a message into a "virtual buffer". This is an + * object which defines an "append bytes" callback to consume data as it is + * serialized. + * +~~~{.c} +size_t foo__bar__baz_bah__pack_to_buffer + (const Foo__Bar__BazBah *message, + ProtobufCBuffer *buffer); +~~~ + * + * \page pack Packing and unpacking messages + * + * To pack a message, first compute the packed size of the message with + * protobuf_c_message_get_packed_size(), then allocate a buffer of at least + * that size, then call protobuf_c_message_pack(). + * + * Alternatively, a message can be serialized without calculating the final size + * first. Use the protobuf_c_message_pack_to_buffer() function and provide a + * ProtobufCBuffer object which implements an "append" method that consumes + * data. + * + * To unpack a message, call the protobuf_c_message_unpack() function. The + * result can be cast to an object of the type that matches the descriptor for + * the message. + * + * The result of unpacking a message should be freed with + * protobuf_c_message_free_unpacked(). + */ + +#ifndef PROTOBUF_C_H +#define PROTOBUF_C_H + +#include +#include +#include +#include + +#ifdef __cplusplus +# define PROTOBUF_C__BEGIN_DECLS extern "C" { +# define PROTOBUF_C__END_DECLS } +#else +# define PROTOBUF_C__BEGIN_DECLS +# define PROTOBUF_C__END_DECLS +#endif + +PROTOBUF_C__BEGIN_DECLS + +#if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB) +# ifdef PROTOBUF_C_EXPORT +# define PROTOBUF_C__API __declspec(dllexport) +# else +# define PROTOBUF_C__API __declspec(dllimport) +# endif +#else +# define PROTOBUF_C__API +#endif + +#if !defined(PROTOBUF_C__NO_DEPRECATED) && \ + ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# define PROTOBUF_C__DEPRECATED __attribute__((__deprecated__)) +#else +# define PROTOBUF_C__DEPRECATED +#endif + +#ifndef PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE + #define PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(enum_name) \ + , _##enum_name##_IS_INT_SIZE = INT_MAX +#endif + +#define PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC 0x14159bc3 +#define PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9 +#define PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC 0x114315af + +/* Empty string used for initializers */ +extern const char protobuf_c_empty_string[]; + +/** + * \defgroup api Public API + * + * This is the public API for `libprotobuf-c`. These interfaces are stable and + * subject to Semantic Versioning guarantees. + * + * @{ + */ + +/** + * Values for the `flags` word in `ProtobufCFieldDescriptor`. + */ +typedef enum { + /** Set if the field is repeated and marked with the `packed` option. */ + PROTOBUF_C_FIELD_FLAG_PACKED = (1 << 0), + + /** Set if the field is marked with the `deprecated` option. */ + PROTOBUF_C_FIELD_FLAG_DEPRECATED = (1 << 1), + + /** Set if the field is a member of a oneof (union). */ + PROTOBUF_C_FIELD_FLAG_ONEOF = (1 << 2), +} ProtobufCFieldFlag; + +/** + * Message field rules. + * + * \see [Defining A Message Type] in the Protocol Buffers documentation. + * + * [Defining A Message Type]: + * https://developers.google.com/protocol-buffers/docs/proto#simple + */ +typedef enum { + /** A well-formed message must have exactly one of this field. */ + PROTOBUF_C_LABEL_REQUIRED, + + /** + * A well-formed message can have zero or one of this field (but not + * more than one). + */ + PROTOBUF_C_LABEL_OPTIONAL, + + /** + * This field can be repeated any number of times (including zero) in a + * well-formed message. The order of the repeated values will be + * preserved. + */ + PROTOBUF_C_LABEL_REPEATED, + + /** + * This field has no label. This is valid only in proto3 and is + * equivalent to OPTIONAL but no "has" quantifier will be consulted. + */ + PROTOBUF_C_LABEL_NONE, +} ProtobufCLabel; + +/** + * Field value types. + * + * \see [Scalar Value Types] in the Protocol Buffers documentation. + * + * [Scalar Value Types]: + * https://developers.google.com/protocol-buffers/docs/proto#scalar + */ +typedef enum { + PROTOBUF_C_TYPE_INT32, /**< int32 */ + PROTOBUF_C_TYPE_SINT32, /**< signed int32 */ + PROTOBUF_C_TYPE_SFIXED32, /**< signed int32 (4 bytes) */ + PROTOBUF_C_TYPE_INT64, /**< int64 */ + PROTOBUF_C_TYPE_SINT64, /**< signed int64 */ + PROTOBUF_C_TYPE_SFIXED64, /**< signed int64 (8 bytes) */ + PROTOBUF_C_TYPE_UINT32, /**< unsigned int32 */ + PROTOBUF_C_TYPE_FIXED32, /**< unsigned int32 (4 bytes) */ + PROTOBUF_C_TYPE_UINT64, /**< unsigned int64 */ + PROTOBUF_C_TYPE_FIXED64, /**< unsigned int64 (8 bytes) */ + PROTOBUF_C_TYPE_FLOAT, /**< float */ + PROTOBUF_C_TYPE_DOUBLE, /**< double */ + PROTOBUF_C_TYPE_BOOL, /**< boolean */ + PROTOBUF_C_TYPE_ENUM, /**< enumerated type */ + PROTOBUF_C_TYPE_STRING, /**< UTF-8 or ASCII string */ + PROTOBUF_C_TYPE_BYTES, /**< arbitrary byte sequence */ + PROTOBUF_C_TYPE_MESSAGE, /**< nested message */ +} ProtobufCType; + +/** + * Field wire types. + * + * \see [Message Structure] in the Protocol Buffers documentation. + * + * [Message Structure]: + * https://developers.google.com/protocol-buffers/docs/encoding#structure + */ +typedef enum { + PROTOBUF_C_WIRE_TYPE_VARINT = 0, + PROTOBUF_C_WIRE_TYPE_64BIT = 1, + PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED = 2, + /* "Start group" and "end group" wire types are unsupported. */ + PROTOBUF_C_WIRE_TYPE_32BIT = 5, +} ProtobufCWireType; + +struct ProtobufCAllocator; +struct ProtobufCBinaryData; +struct ProtobufCBuffer; +struct ProtobufCBufferSimple; +struct ProtobufCEnumDescriptor; +struct ProtobufCEnumValue; +struct ProtobufCEnumValueIndex; +struct ProtobufCFieldDescriptor; +struct ProtobufCIntRange; +struct ProtobufCMessage; +struct ProtobufCMessageDescriptor; +struct ProtobufCMessageUnknownField; +struct ProtobufCMethodDescriptor; +struct ProtobufCService; +struct ProtobufCServiceDescriptor; + +typedef struct ProtobufCAllocator ProtobufCAllocator; +typedef struct ProtobufCBinaryData ProtobufCBinaryData; +typedef struct ProtobufCBuffer ProtobufCBuffer; +typedef struct ProtobufCBufferSimple ProtobufCBufferSimple; +typedef struct ProtobufCEnumDescriptor ProtobufCEnumDescriptor; +typedef struct ProtobufCEnumValue ProtobufCEnumValue; +typedef struct ProtobufCEnumValueIndex ProtobufCEnumValueIndex; +typedef struct ProtobufCFieldDescriptor ProtobufCFieldDescriptor; +typedef struct ProtobufCIntRange ProtobufCIntRange; +typedef struct ProtobufCMessage ProtobufCMessage; +typedef struct ProtobufCMessageDescriptor ProtobufCMessageDescriptor; +typedef struct ProtobufCMessageUnknownField ProtobufCMessageUnknownField; +typedef struct ProtobufCMethodDescriptor ProtobufCMethodDescriptor; +typedef struct ProtobufCService ProtobufCService; +typedef struct ProtobufCServiceDescriptor ProtobufCServiceDescriptor; + +/** Boolean type. */ +typedef int protobuf_c_boolean; + +typedef void (*ProtobufCClosure)(const ProtobufCMessage *, void *closure_data); +typedef void (*ProtobufCMessageInit)(ProtobufCMessage *); +typedef void (*ProtobufCServiceDestroy)(ProtobufCService *); + +/** + * Structure for defining a custom memory allocator. + */ +struct ProtobufCAllocator { + /** Function to allocate memory. */ + void *(*alloc)(void *allocator_data, size_t size); + + /** Function to free memory. */ + void (*free)(void *allocator_data, void *pointer); + + /** Opaque pointer passed to `alloc` and `free` functions. */ + void *allocator_data; +}; + +/** + * Structure for the protobuf `bytes` scalar type. + * + * The data contained in a `ProtobufCBinaryData` is an arbitrary sequence of + * bytes. It may contain embedded `NUL` characters and is not required to be + * `NUL`-terminated. + */ +struct ProtobufCBinaryData { + size_t len; /**< Number of bytes in the `data` field. */ + uint8_t *data; /**< Data bytes. */ +}; + +/** + * Structure for defining a virtual append-only buffer. Used by + * protobuf_c_message_pack_to_buffer() to abstract the consumption of serialized + * bytes. + * + * `ProtobufCBuffer` "subclasses" may be defined on the stack. For example, to + * write to a `FILE` object: + * +~~~{.c} +typedef struct { + ProtobufCBuffer base; + FILE *fp; +} BufferAppendToFile; + +static void +my_buffer_file_append(ProtobufCBuffer *buffer, + size_t len, + const uint8_t *data) +{ + BufferAppendToFile *file_buf = (BufferAppendToFile *) buffer; + fwrite(data, len, 1, file_buf->fp); // XXX: No error handling! +} +~~~ + * + * To use this new type of ProtobufCBuffer, it could be called as follows: + * +~~~{.c} +... +BufferAppendToFile tmp = {0}; +tmp.base.append = my_buffer_file_append; +tmp.fp = fp; +protobuf_c_message_pack_to_buffer(&message, &tmp); +... +~~~ + */ +struct ProtobufCBuffer { + /** Append function. Consumes the `len` bytes stored at `data`. */ + void (*append)(ProtobufCBuffer *buffer, + size_t len, + const uint8_t *data); +}; + +/** + * Simple buffer "subclass" of `ProtobufCBuffer`. + * + * A `ProtobufCBufferSimple` object is declared on the stack and uses a + * scratch buffer provided by the user for the initial allocation. It performs + * exponential resizing, using dynamically allocated memory. A + * `ProtobufCBufferSimple` object can be created and used as follows: + * +~~~{.c} +uint8_t pad[128]; +ProtobufCBufferSimple simple = PROTOBUF_C_BUFFER_SIMPLE_INIT(pad); +ProtobufCBuffer *buffer = (ProtobufCBuffer *) &simple; +~~~ + * + * `buffer` can now be used with `protobuf_c_message_pack_to_buffer()`. Once a + * message has been serialized to a `ProtobufCBufferSimple` object, the + * serialized data bytes can be accessed from the `.data` field. + * + * To free the memory allocated by a `ProtobufCBufferSimple` object, if any, + * call PROTOBUF_C_BUFFER_SIMPLE_CLEAR() on the object, for example: + * +~~~{.c} +PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple); +~~~ + * + * \see PROTOBUF_C_BUFFER_SIMPLE_INIT + * \see PROTOBUF_C_BUFFER_SIMPLE_CLEAR + */ +struct ProtobufCBufferSimple { + /** "Base class". */ + ProtobufCBuffer base; + /** Number of bytes allocated in `data`. */ + size_t alloced; + /** Number of bytes currently stored in `data`. */ + size_t len; + /** Data bytes. */ + uint8_t *data; + /** Whether `data` must be freed. */ + protobuf_c_boolean must_free_data; + /** Allocator to use. May be NULL to indicate the system allocator. */ + ProtobufCAllocator *allocator; +}; + +/** + * Describes an enumeration as a whole, with all of its values. + */ +struct ProtobufCEnumDescriptor { + /** Magic value checked to ensure that the API is used correctly. */ + uint32_t magic; + + /** The qualified name (e.g., "namespace.Type"). */ + const char *name; + /** The unqualified name as given in the .proto file (e.g., "Type"). */ + const char *short_name; + /** Identifier used in generated C code. */ + const char *c_name; + /** The dot-separated namespace. */ + const char *package_name; + + /** Number elements in `values`. */ + unsigned n_values; + /** Array of distinct values, sorted by numeric value. */ + const ProtobufCEnumValue *values; + + /** Number of elements in `values_by_name`. */ + unsigned n_value_names; + /** Array of named values, including aliases, sorted by name. */ + const ProtobufCEnumValueIndex *values_by_name; + + /** Number of elements in `value_ranges`. */ + unsigned n_value_ranges; + /** Value ranges, for faster lookups by numeric value. */ + const ProtobufCIntRange *value_ranges; + + /** Reserved for future use. */ + void *reserved1; + /** Reserved for future use. */ + void *reserved2; + /** Reserved for future use. */ + void *reserved3; + /** Reserved for future use. */ + void *reserved4; +}; + +/** + * Represents a single value of an enumeration. + */ +struct ProtobufCEnumValue { + /** The string identifying this value in the .proto file. */ + const char *name; + + /** The string identifying this value in generated C code. */ + const char *c_name; + + /** The numeric value assigned in the .proto file. */ + int value; +}; + +/** + * Used by `ProtobufCEnumDescriptor` to look up enum values. + */ +struct ProtobufCEnumValueIndex { + /** Name of the enum value. */ + const char *name; + /** Index into values[] array. */ + unsigned index; +}; + +/** + * Describes a single field in a message. + */ +struct ProtobufCFieldDescriptor { + /** Name of the field as given in the .proto file. */ + const char *name; + + /** Tag value of the field as given in the .proto file. */ + uint32_t id; + + /** Whether the field is `REQUIRED`, `OPTIONAL`, or `REPEATED`. */ + ProtobufCLabel label; + + /** The type of the field. */ + ProtobufCType type; + + /** + * The offset in bytes of the message's C structure's quantifier field + * (the `has_MEMBER` field for optional members or the `n_MEMBER` field + * for repeated members or the case enum for oneofs). + */ + unsigned quantifier_offset; + + /** + * The offset in bytes into the message's C structure for the member + * itself. + */ + unsigned offset; + + /** + * A type-specific descriptor. + * + * If `type` is `PROTOBUF_C_TYPE_ENUM`, then `descriptor` points to the + * corresponding `ProtobufCEnumDescriptor`. + * + * If `type` is `PROTOBUF_C_TYPE_MESSAGE`, then `descriptor` points to + * the corresponding `ProtobufCMessageDescriptor`. + * + * Otherwise this field is NULL. + */ + const void *descriptor; /* for MESSAGE and ENUM types */ + + /** The default value for this field, if defined. May be NULL. */ + const void *default_value; + + /** + * A flag word. Zero or more of the bits defined in the + * `ProtobufCFieldFlag` enum may be set. + */ + uint32_t flags; + + /** Reserved for future use. */ + unsigned reserved_flags; + /** Reserved for future use. */ + void *reserved2; + /** Reserved for future use. */ + void *reserved3; +}; + +/** + * Helper structure for optimizing int => index lookups in the case + * where the keys are mostly consecutive values, as they presumably are for + * enums and fields. + * + * The data structures requires that the values in the original array are + * sorted. + */ +struct ProtobufCIntRange { + int start_value; + unsigned orig_index; + /* + * NOTE: the number of values in the range can be inferred by looking + * at the next element's orig_index. A dummy element is added to make + * this simple. + */ +}; + +/** + * An instance of a message. + * + * `ProtobufCMessage` is a light-weight "base class" for all messages. + * + * In particular, `ProtobufCMessage` doesn't have any allocation policy + * associated with it. That's because it's common to create `ProtobufCMessage` + * objects on the stack. In fact, that's what we recommend for sending messages. + * If the object is allocated from the stack, you can't really have a memory + * leak. + * + * This means that calls to functions like protobuf_c_message_unpack() which + * return a `ProtobufCMessage` must be paired with a call to a free function, + * like protobuf_c_message_free_unpacked(). + */ +struct ProtobufCMessage { + /** The descriptor for this message type. */ + const ProtobufCMessageDescriptor *descriptor; + /** The number of elements in `unknown_fields`. */ + unsigned n_unknown_fields; + /** The fields that weren't recognized by the parser. */ + ProtobufCMessageUnknownField *unknown_fields; +}; + +/** + * Describes a message. + */ +struct ProtobufCMessageDescriptor { + /** Magic value checked to ensure that the API is used correctly. */ + uint32_t magic; + + /** The qualified name (e.g., "namespace.Type"). */ + const char *name; + /** The unqualified name as given in the .proto file (e.g., "Type"). */ + const char *short_name; + /** Identifier used in generated C code. */ + const char *c_name; + /** The dot-separated namespace. */ + const char *package_name; + + /** + * Size in bytes of the C structure representing an instance of this + * type of message. + */ + size_t sizeof_message; + + /** Number of elements in `fields`. */ + unsigned n_fields; + /** Field descriptors, sorted by tag number. */ + const ProtobufCFieldDescriptor *fields; + /** Used for looking up fields by name. */ + const unsigned *fields_sorted_by_name; + + /** Number of elements in `field_ranges`. */ + unsigned n_field_ranges; + /** Used for looking up fields by id. */ + const ProtobufCIntRange *field_ranges; + + /** Message initialisation function. */ + ProtobufCMessageInit message_init; + + /** Reserved for future use. */ + void *reserved1; + /** Reserved for future use. */ + void *reserved2; + /** Reserved for future use. */ + void *reserved3; +}; + +/** + * An unknown message field. + */ +struct ProtobufCMessageUnknownField { + /** The tag number. */ + uint32_t tag; + /** The wire type of the field. */ + ProtobufCWireType wire_type; + /** Number of bytes in `data`. */ + size_t len; + /** Field data. */ + uint8_t *data; +}; + +/** + * Method descriptor. + */ +struct ProtobufCMethodDescriptor { + /** Method name. */ + const char *name; + /** Input message descriptor. */ + const ProtobufCMessageDescriptor *input; + /** Output message descriptor. */ + const ProtobufCMessageDescriptor *output; +}; + +/** + * Service. + */ +struct ProtobufCService { + /** Service descriptor. */ + const ProtobufCServiceDescriptor *descriptor; + /** Function to invoke the service. */ + void (*invoke)(ProtobufCService *service, + unsigned method_index, + const ProtobufCMessage *input, + ProtobufCClosure closure, + void *closure_data); + /** Function to destroy the service. */ + void (*destroy)(ProtobufCService *service); +}; + +/** + * Service descriptor. + */ +struct ProtobufCServiceDescriptor { + /** Magic value checked to ensure that the API is used correctly. */ + uint32_t magic; + + /** Service name. */ + const char *name; + /** Short version of service name. */ + const char *short_name; + /** C identifier for the service name. */ + const char *c_name; + /** Package name. */ + const char *package; + /** Number of elements in `methods`. */ + unsigned n_methods; + /** Method descriptors, in the order defined in the .proto file. */ + const ProtobufCMethodDescriptor *methods; + /** Sort index of methods. */ + const unsigned *method_indices_by_name; +}; + +/** + * Get the version of the protobuf-c library. Note that this is the version of + * the library linked against, not the version of the headers compiled against. + * + * \return A string containing the version number of protobuf-c. + */ +PROTOBUF_C__API +const char * +protobuf_c_version(void); + +/** + * Get the version of the protobuf-c library. Note that this is the version of + * the library linked against, not the version of the headers compiled against. + * + * \return A 32 bit unsigned integer containing the version number of + * protobuf-c, represented in base-10 as (MAJOR*1E6) + (MINOR*1E3) + PATCH. + */ +PROTOBUF_C__API +uint32_t +protobuf_c_version_number(void); + +/** + * The version of the protobuf-c headers, represented as a string using the same + * format as protobuf_c_version(). + */ +#define PROTOBUF_C_VERSION "1.3.0" + +/** + * The version of the protobuf-c headers, represented as an integer using the + * same format as protobuf_c_version_number(). + */ +#define PROTOBUF_C_VERSION_NUMBER 1003000 + +/** + * The minimum protoc-c version which works with the current version of the + * protobuf-c headers. + */ +#define PROTOBUF_C_MIN_COMPILER_VERSION 1000000 + +/** + * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by name. + * + * \param desc + * The `ProtobufCEnumDescriptor` object. + * \param name + * The `name` field from the corresponding `ProtobufCEnumValue` object to + * match. + * \return + * A `ProtobufCEnumValue` object. + * \retval NULL + * If not found or if the optimize_for = CODE_SIZE option was set. + */ +PROTOBUF_C__API +const ProtobufCEnumValue * +protobuf_c_enum_descriptor_get_value_by_name( + const ProtobufCEnumDescriptor *desc, + const char *name); + +/** + * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by numeric + * value. + * + * \param desc + * The `ProtobufCEnumDescriptor` object. + * \param value + * The `value` field from the corresponding `ProtobufCEnumValue` object to + * match. + * + * \return + * A `ProtobufCEnumValue` object. + * \retval NULL + * If not found. + */ +PROTOBUF_C__API +const ProtobufCEnumValue * +protobuf_c_enum_descriptor_get_value( + const ProtobufCEnumDescriptor *desc, + int value); + +/** + * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by + * the name of the field. + * + * \param desc + * The `ProtobufCMessageDescriptor` object. + * \param name + * The name of the field. + * \return + * A `ProtobufCFieldDescriptor` object. + * \retval NULL + * If not found or if the optimize_for = CODE_SIZE option was set. + */ +PROTOBUF_C__API +const ProtobufCFieldDescriptor * +protobuf_c_message_descriptor_get_field_by_name( + const ProtobufCMessageDescriptor *desc, + const char *name); + +/** + * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by + * the tag value of the field. + * + * \param desc + * The `ProtobufCMessageDescriptor` object. + * \param value + * The tag value of the field. + * \return + * A `ProtobufCFieldDescriptor` object. + * \retval NULL + * If not found. + */ +PROTOBUF_C__API +const ProtobufCFieldDescriptor * +protobuf_c_message_descriptor_get_field( + const ProtobufCMessageDescriptor *desc, + unsigned value); + +/** + * Determine the number of bytes required to store the serialised message. + * + * \param message + * The message object to serialise. + * \return + * Number of bytes. + */ +PROTOBUF_C__API +size_t +protobuf_c_message_get_packed_size(const ProtobufCMessage *message); + +/** + * Serialise a message from its in-memory representation. + * + * This function stores the serialised bytes of the message in a pre-allocated + * buffer. + * + * \param message + * The message object to serialise. + * \param[out] out + * Buffer to store the bytes of the serialised message. This buffer must + * have enough space to store the packed message. Use + * protobuf_c_message_get_packed_size() to determine the number of bytes + * required. + * \return + * Number of bytes stored in `out`. + */ +PROTOBUF_C__API +size_t +protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out); + +/** + * Serialise a message from its in-memory representation to a virtual buffer. + * + * This function calls the `append` method of a `ProtobufCBuffer` object to + * consume the bytes generated by the serialiser. + * + * \param message + * The message object to serialise. + * \param buffer + * The virtual buffer object. + * \return + * Number of bytes passed to the virtual buffer. + */ +PROTOBUF_C__API +size_t +protobuf_c_message_pack_to_buffer( + const ProtobufCMessage *message, + ProtobufCBuffer *buffer); + +/** + * Unpack a serialised message into an in-memory representation. + * + * \param descriptor + * The message descriptor. + * \param allocator + * `ProtobufCAllocator` to use for memory allocation. May be NULL to + * specify the default allocator. + * \param len + * Length in bytes of the serialised message. + * \param data + * Pointer to the serialised message. + * \return + * An unpacked message object. + * \retval NULL + * If an error occurred during unpacking. + */ +PROTOBUF_C__API +ProtobufCMessage * +protobuf_c_message_unpack( + const ProtobufCMessageDescriptor *descriptor, + ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); + +/** + * Free an unpacked message object. + * + * This function should be used to deallocate the memory used by a call to + * protobuf_c_message_unpack(). + * + * \param message + * The message object to free. May be NULL. + * \param allocator + * `ProtobufCAllocator` to use for memory deallocation. May be NULL to + * specify the default allocator. + */ +PROTOBUF_C__API +void +protobuf_c_message_free_unpacked( + ProtobufCMessage *message, + ProtobufCAllocator *allocator); + +/** + * Check the validity of a message object. + * + * Makes sure all required fields (`PROTOBUF_C_LABEL_REQUIRED`) are present. + * Recursively checks nested messages. + * + * \retval TRUE + * Message is valid. + * \retval FALSE + * Message is invalid. + */ +PROTOBUF_C__API +protobuf_c_boolean +protobuf_c_message_check(const ProtobufCMessage *); + +/** Message initialiser. */ +#define PROTOBUF_C_MESSAGE_INIT(descriptor) { descriptor, 0, NULL } + +/** + * Initialise a message object from a message descriptor. + * + * \param descriptor + * Message descriptor. + * \param message + * Allocated block of memory of size `descriptor->sizeof_message`. + */ +PROTOBUF_C__API +void +protobuf_c_message_init( + const ProtobufCMessageDescriptor *descriptor, + void *message); + +/** + * Free a service. + * + * \param service + * The service object to free. + */ +PROTOBUF_C__API +void +protobuf_c_service_destroy(ProtobufCService *service); + +/** + * Look up a `ProtobufCMethodDescriptor` by name. + * + * \param desc + * Service descriptor. + * \param name + * Name of the method. + * + * \return + * A `ProtobufCMethodDescriptor` object. + * \retval NULL + * If not found or if the optimize_for = CODE_SIZE option was set. + */ +PROTOBUF_C__API +const ProtobufCMethodDescriptor * +protobuf_c_service_descriptor_get_method_by_name( + const ProtobufCServiceDescriptor *desc, + const char *name); + +/** + * Initialise a `ProtobufCBufferSimple` object. + */ +#define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \ +{ \ + { protobuf_c_buffer_simple_append }, \ + sizeof(array_of_bytes), \ + 0, \ + (array_of_bytes), \ + 0, \ + NULL \ +} + +/** + * Clear a `ProtobufCBufferSimple` object, freeing any allocated memory. + */ +#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \ +do { \ + if ((simp_buf)->must_free_data) { \ + if ((simp_buf)->allocator != NULL) \ + (simp_buf)->allocator->free( \ + (simp_buf)->allocator, \ + (simp_buf)->data); \ + else \ + free((simp_buf)->data); \ + } \ +} while (0) + +/** + * The `append` method for `ProtobufCBufferSimple`. + * + * \param buffer + * The buffer object to append to. Must actually be a + * `ProtobufCBufferSimple` object. + * \param len + * Number of bytes in `data`. + * \param data + * Data to append. + */ +PROTOBUF_C__API +void +protobuf_c_buffer_simple_append( + ProtobufCBuffer *buffer, + size_t len, + const unsigned char *data); + +PROTOBUF_C__API +void +protobuf_c_service_generated_init( + ProtobufCService *service, + const ProtobufCServiceDescriptor *descriptor, + ProtobufCServiceDestroy destroy); + +PROTOBUF_C__API +void +protobuf_c_service_invoke_internal( + ProtobufCService *service, + unsigned method_index, + const ProtobufCMessage *input, + ProtobufCClosure closure, + void *closure_data); + +/**@}*/ + +PROTOBUF_C__END_DECLS + +#endif /* PROTOBUF_C_H */ diff --git a/Software/Embedded_SW/Embedded/Common/report/distributor.c b/Software/Embedded_SW/Embedded/Common/report/distributor.c new file mode 100644 index 000000000..38b9ccff8 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/report/distributor.c @@ -0,0 +1,851 @@ +/****************************************************************************** + * File name : distributor.c + * Title : REPORT PACKAGE - Message Distributor + * Date created : 01 SEP, 1996 + * Revision : 1.0 + * Author : Zvika Zilberman + * + * Description : Report distributor provides the duplicating of + * messages to the several destinations. + * + ****************************************************************************** + * + * Procedures: + * + * ReportFd - Add or remove file descriptor to/from the + * list of destinations + * ReportFunc - Add or remove funtion to/from the list of + * destnations + * ReportEnableAll - Resume the work of distributor + * + * Functions, internal for Report: + * + * distibutorInit - Initialize message distributor + * reportDistribute - Send message to destibutor + * + * Local functions: + * + * messageDistribute - Forward message to all destinations. + * reportService - Distibutor Task main function + * + ****************************************************************************** + * + * History: + * 01.09.96 Ilia Maller - start of coding + * 21.02.97 Ilia Maller - minor improvements + * 17.09.97 Zvika Zilberman - porting to DCME SWINFRA + * + ******************************************************************************/ + +/*------------- Includes --------------------------------*/ +#include "include.h" + +#include "report.h" +#include "filter.h" +#include "distributor.h" + +/*------------- Local Definitions -----------------------*/ + +#define SEVERITY_MASK(severity) ((severity) & 0x10) +#define REPORT_ROOT_NAME "system" +#define REPORT_TASK_STACK_SIZE 1024 + +typedef struct +{ + FormatType format; + char message[REPORT_MAX_MSG_LEN]; + char FileName[REPORT_MAX_MSG_LEN]; + int LineNumber; + int errorCode; + ErrorSeverity severity; + int parameter1; + int parameter2; +}INPUT_MESSAGE; + +#define INPUT_MESSAGE_LEN sizeof(INPUT_MESSAGE) + +typedef struct +{ + int fd; + ReportFunction function; +}DESTINATION; + +#define DESTINATION_SIZE sizeof(DESTINATION) + +#define NUM_OF_DESTINATIONS 4 +typedef struct +{ + char name[11]; + bool IsActive; /* false - discard its messages. true - send them. */ + bool IsAlive; /* false - if not in action, can not be used or seen */ + DESTINATION dest[NUM_OF_DESTINATIONS]; +} DistributorElement; + + +static void messageDistribute(char *msg, + int DistTableEntry, + char *FileName, + int LineNumber, + int errorCode, + int parameter1, + int parameter2); +/*static STATUS reportFormat(char *buffer, + int *maxlen, + const char *message, + int errorCode, + ErrorSeverity severity, + int parameter1, + int parameter2);*/ +static int FindFreeDestinationElement(int DistTableEntry); + +/*------------- Local Data ------------------------------*/ + +static Mailbox_Handle inputQueue; + +/* Table where output of distributor (destinations) stored + Every element of the table may be or file descriptor + or function address. + The destinations stored unsorted */ +static DistributorElement *Dist_Table; +static int DistCounter; /* number of current elements in the table */ +static int NumOfDistributions; + +/*************************************************************************** + * + * Name : distibutorInit + * + * Function : Initialize message distributor + * + * Notes : Function uses malloc for memory allocation + * + * Parameters: priority - distributor task priority + * maxMsgs - maximum number of messages stored in + * destributor task queue + * maxDstr - maximum number of distributors + * + * Return value: STATUS - OK or ERROR + **************************************************************************/ +STATUS distibutorInit( int priority, int maxMsgs, int maxDstr ) +{ + + static int initialized = false; + int i, j; + + if (initialized) + return OK; + + NumOfDistributions = maxDstr; + /* create mailbox to recive messages */ + inputQueue = Mailbox_create(INPUT_MESSAGE_LEN,maxMsgs, 0,0); + if (inputQueue == NULL) + return ERROR; + + /* create table for destionations. malloc takes care about allignment */ + Dist_Table = (DistributorElement *)malloc(sizeof(DistributorElement)*(maxDstr+1)); + if (Dist_Table == NULL) + return ERROR; + /* initialize table */ + for (i=0; i<=maxDstr; i++) + { + for (j=0; j 0) + { + if (Dist_Table[Distributor].IsAlive == false) + return OK; + if (Dist_Table[Distributor].IsActive == false) + return OK; + } + else if (Dist_Table[0].IsActive == false) + return OK; + /* truncate if message length greater than defined */ + msg.format = format; + strncpy(msg.message, message, REPORT_MAX_MSG_LEN); + msg.errorCode = errorCode; + msg.severity = severity; + msg.parameter1 = parameter1; + msg.parameter2 = parameter2; + + if (inputQueue != NULL) + Mailbox_post(inputQueue , &msg, BIOS_NO_WAIT); + return OK; +} + + +/*************************************************************************** + * + * Name : reportService + * + * Function : Distibutor Task main function + * + * Notes : + * + * Return value: void + **************************************************************************/ +Void reportService(UArg arg0, UArg arg1) +{ + INPUT_MESSAGE msg; + //static char buf[REPORT_MAX_MSG_LEN + REPORT_MSG_FORMAT_LEN]; + int DistTableEntry;//,msgLen, errCode, par1, par2; + + while(1) + { + Mailbox_pend(inputQueue , &msg, BIOS_WAIT_FOREVER); + + DistTableEntry = (SEVERITY_MASK(msg.severity) == RpPrivate) ? (msg.severity >> 5) : 0; +// /* format received string */ +// /*if (msg.format == REPORT_FORMAT) +// { +// msgLen = REPORT_MAX_MSG_LEN + REPORT_MSG_FORMAT_LEN; +// reportFormat(buf, &msgLen, msg.message, msg.errorCode, +// msg.severity, msg.parameter1, msg.parameter2); +// errCode = msg.errorCode; +// par1 = msg.parameter1; +// par2 = msg.parameter2; +// } +// else /* MESSAGE_FORMAT - regular message */ +// { +// msgLen = strlen(msg.message); +// if (msgLen > REPORT_MAX_MSG_LEN-1) +// msgLen = REPORT_MAX_MSG_LEN-1; +// strcpy(buf,msg.message); +// errCode = 0; +// par1 = 0; +// par2 = 0; +// }*/ + /* send message to subscribers */ + messageDistribute( msg.message, DistTableEntry,msg.FileName, msg.LineNumber,msg.errorCode,msg.severity,msg.parameter2); + } +} + +/*----------------------------------------------------------------------------*/ +/*----------------------------- Private Severity -----------------------------*/ +/*----------------------------------------------------------------------------*/ + +/*************************************************************************** + * + * Name : ReportDistributor + * + * Function : Add static distributor + * + * Notes : The name is given in order to note the severity name + * during the report exception. + * + * Parameters: distributorName - The severity's name must be up to 10 + * letters long. + * SwitchAddRemove - REPORT_ADD to add the new static severity, + * REPORT_REMOVE to remove it. + * + * Return value: the new distributor handle, or -1 and thus: + * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name, + * errno = REPORT_ERROR_NAME_ALREADY_DISABLE if the distributor + * was already removed, + * errno = REPORT_ERROR_NAME_NOT_EXISTS if the distributorName + * not exists, + * errno = REPORT_ERROR_TABLE_FULL if there are already too + * many distributors, + * errno = REPORT_ERROR_NAME_EXISTS if the distributorName + * already exists. + **************************************************************************/ +DistributorHandle ReportDistributor(const char *distributorName, uint32_t SwitchAddRemove) +{ + int index; + + if ((DistCounter > NumOfDistributions) && (SwitchAddRemove == REPORT_ADD)) + { + errno = REPORT_ERROR_TABLE_FULL; + return -1; + } + if (strlen(distributorName) > 10) + { + errno = REPORT_ERROR_NAME_TOO_LONG; + return -1; + } + else if ((strcmp(distributorName,"system")==0) || ((strcmp(distributorName,"SYSTEM")==0))) + { + errno = REPORT_ERROR_NAME; + return -1; + } + if (IsNameExistsInFiltersTable(distributorName)) + { + errno = REPORT_ERROR_NAME_EXISTS; + return -1; + } + for (index=1; index DistCounter) || (Distributor < 0)) + return ERROR; + Dist_Table[Distributor].IsActive = (SwitchOnOff == REPORT_ON) ? true : false; + return OK; +} + + +/*************************************************************************** + * + * Name : ReportGetDistributorHandleByName + * + * Function : Get the severity handle given the severity's name + * + * Notes : + * + * Return value: the handle; or -1 if no such name + **************************************************************************/ +DistributorHandle ReportGetDistributorHandleByName(const char *distributorName) +{ + int index; + + for (index = 0; index <= DistCounter; index++) + if (ReportStrCmp(distributorName,Dist_Table[index].name)) + { + if (Dist_Table[index].IsAlive) + return index; + else + return -1; /* disable used */ + } + return -1; +} + + +/*************************************************************************** + * + * Name : GetDistributorParamsByHandle + * + * Function : Get the static severity details according to its handle + * + * Parameters : DistributorHandle - table entry + * name - buffer to contain the static severity's name + * IsActive - a reference to a boolean flag + * + * Notes : The name field must exceeds 10 bytes long + * + * Return value: OK or ERROR and then: + * errno = REPORT_ERROR_ILLEGAL_PARAMETER if no such entry + * errno = REPORT_ERROR_FILTER_NOT_ALIVE if the static + * severity has already removed. + **************************************************************************/ +STATUS GetDistributorParamsByHandle(uint32_t DistributorHandle, char *name, bool *IsActive) +{ + if (DistributorHandle >= DistCounter) + { + errno = REPORT_ERROR_ILLEGAL_PARAMETER; + return ERROR; + } + if ((Dist_Table[DistributorHandle].IsAlive) == false) + { + errno = REPORT_ERROR_FILTER_NOT_ALIVE; + return ERROR; + } + strcpy(name,Dist_Table[DistributorHandle].name); + *IsActive = Dist_Table[DistributorHandle].IsActive; + return OK; +} + + +/*************************************************************************** + * + * Name : ReportFd + * + * Function : Add or remove a file descriptor to/from the output distributor + * + * Notes : + * + * Parameters: fd - file descriptor. Supplied by the user + * SwitchAddRemove - REPORT_ADD to add the fd + * REPORT_REMOVE to remove it. + * Distributor - 0 if not concerned with any static + * severity, or the static severity's handle + * to set with the given fd + * + * Return value: OK or ERROR with: + * errno = REPORT_ERROR_NOT_ENOUGH_MEMORY if destination list + * is full + * errno = REPORT_ERROR_ILLEGAL_PARAMETER if (fd == -1) or + * not found if asked to remove + **************************************************************************/ +STATUS ReportFd(int fd, uint32_t SwitchAddRemove, DistributorHandle Distributor) +{ + int index = 0, i; + + if (SwitchAddRemove == REPORT_ADD) + { + index = FindFreeDestinationElement(Distributor); + /* check for the table overflow */ + if (index == -1) + { + errno = REPORT_ERROR_NOT_ENOUGH_MEMORY; + return ERROR; + } + } + /* consistency check: don't add illegal fd */ + if (fd == -1) + { + errno = REPORT_ERROR_ILLEGAL_PARAMETER; + return ERROR; + } + + /* search for fd */ + for( i = 0; i < NUM_OF_DESTINATIONS; i++ ) + if ( Dist_Table[Distributor].dest[i].fd == fd ) + break; + + if (i == NUM_OF_DESTINATIONS) + { + if (SwitchAddRemove == REPORT_REMOVE) + { + errno = REPORT_ERROR_CODE_NOT_FOUND; + return ERROR; + } + /* Add fd */ + /* add new destination to the end of the table */ + Dist_Table[Distributor].dest[index].fd = fd; + /* set the function to NULL to ensure that destination is nothing but fd */ + Dist_Table[Distributor].dest[index].function = NULL; + } + else if (SwitchAddRemove == REPORT_ADD) + return OK; /* this fd is already exists in the table */ + else /* Remove fd */ + Dist_Table[Distributor].dest[i].fd = -1; + return OK; +} + + +/*************************************************************************** + * + * Name : ReportFunc + * + * Function : Add or remove an output routine to/from the distributor + * + * Notes : + * + * Parameters: func - hook to the routine. Supplied by the user . + * SwitchAddRemove - REPORT_ADD to add the hook + * REPORT_REMOVE to remove it. + * Distributor - Set 0 if not concerned with any static + * severity, or give the static severity's + * handle to set with the given fd. + * + * Return value: OK or ERROR with: + * errno = REPORT_ERROR_NOT_ENOUGH_MEMORY if destination list + * is full + * errno = REPORT_ERROR_ILLEGAL_PARAMETER if (func == NULL) + **************************************************************************/ +STATUS ReportFunc(ReportFunction func, uint32_t SwitchAddRemove, DistributorHandle Distributor) +{ + int index = 0, i; + + if (SwitchAddRemove == REPORT_ADD) + { + index = FindFreeDestinationElement(Distributor); + /* check for the table overflow */ + if (index == -1) + { + errno = REPORT_ERROR_NOT_ENOUGH_MEMORY; + return ERROR; + } + } + /* consistency check: don't add illegal pointer */ + if( func == NULL ) + { + errno = REPORT_ERROR_ILLEGAL_PARAMETER; + return ERROR; + } + + /* search for func - if already exists */ + for( i = 0; i < NUM_OF_DESTINATIONS; i++ ) + if (Dist_Table[Distributor].dest[i].function == func) + break; + + if (i == NUM_OF_DESTINATIONS) + { + if (SwitchAddRemove == REPORT_REMOVE) /* nothing to remove */ + { + errno = REPORT_ERROR_CODE_NOT_FOUND; + return ERROR; + } + /* Add routine */ + /* add new destination to the end of the table */ + Dist_Table[Distributor].dest[index].function = func; + /* set the fd to illegal value to ensure that destination is nothing but function */ + Dist_Table[Distributor].dest[index].fd = -1; + } + else if (SwitchAddRemove == REPORT_ADD) + return OK; /* this routine is already exists in the table */ + else /* Remove routine */ + Dist_Table[Distributor].dest[i].function = NULL; + return OK; +} + + +/*************************************************************************** + * + * Name : ReportMessage2Dist + * + * Function : Report a message to the appropriate distributor + * + * Notes : The distributor handle should be passed using the macro + * SET_PRIVATE_DISTRIBUTOR + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +STATUS ReportMessage2Dist(DistributorHandle distributor, const char *message) +{ + return reportDistribute(MESSAGE_FORMAT, message,NULL, 0, 0, distributor, 0, 0); +} + + +/*************************************************************************** + * + * Name : ReportMonitorFunc + * + * Function : Add/remove an output routine that prints to the monitor + * + * Notes : Hiding Report messages from appearing on the monitor is + * enable when the HALT> prompt is shown (by pressing ). + * The filtering is done using an internal routine. + * This routine can be added/removed using this call. + * It can be added either to the regular distributor or to the + * distributor of each of the static severities. + * + * Parameters: SwitchAddRemove - REPORT_ADD to add the routine + * REPORT_REMOVE to remove it. + * Distributor - Set 0 if not concerned with any static + * severity, or give the static severity's + * handle to set with it . + * + * Return value: void + **************************************************************************/ +/*void ReportMonitorFunc(uint32_t SwitchAddRemove, uint32_t Distributor) +{ + switch (SwitchAddRemove) + { + case REPORT_ADD: + ReportFunc(MonitorFuncRoutine, REPORT_ADD, Distributor); + break; + case REPORT_REMOVE: + ReportFunc(MonitorFuncRoutine, REPORT_REMOVE, Distributor); + break; + } +} +*/ + +/*------------- messageDistribute ------------------------*/ +/* + * Forward message to all destinations. + * + * Parameters: + * void* msg - address of the message + * int len - message length + * + * Returns: + * None + * + */ + +static void messageDistribute(char *msg, + int DistTableEntry, + char *FileName, + int LineNumber, + int errorCode, + int parameter1, + int parameter2) +{ + int index; + + /* pass through the table and send message to destination. + Assume for consistency: when the destination is fd, + it should not be -1 and function must be NULL. + If the destination is function, it's address must not be NULL + and fd should be -1 */ + for (index = 0; index < NUM_OF_DESTINATIONS; index++ ) + { + if (Dist_Table[DistTableEntry].dest[index].function != NULL) + Dist_Table[DistTableEntry].dest[index].function(msg,FileName,LineNumber,errorCode,parameter1,parameter2); + } +} + + +/*------------- reportFormat --------------------------*/ +/* + * The function converts mesage with error type, code, etc. into string + * with length using the following format (example): + * "H/W Error #12,05,01: Bus error (0xffde,0x1234)" + * + * Parameters: + * char* buffer - buffer to store the formatted message + * int* maxlen - length of the buffer. If the estimated length + * of the formatted message exceeds maxlen, + * function returns ERROR, set errno to + * REPORT_ERROR_NOT_ENOUGH_MEMORY and buffer left unchanged. + * char* message - user message + * UNIT16 extErrorType - error type and severity + * ERRORCODE errorCode - error code + * uint32_t32 parameter1 - user parameter 1 + * uint32_t32 parameter2 - user parameter 2 + * + */ + +//STATUS reportFormat(char *buffer, +// int *maxlen, +// const char *message, +// int errorCode, +// ErrorSeverity severity, +// int parameter1, +// int parameter2) +//{ +// int DstrTableEntry; +// char *name; +// static char* severities[8] = {"Message","Warning","","Error","","","","Fatal error"}; +// +// /* Total message length w/o text is REPORT_MSG_FORMAT_LEN bytes */ +// int msgLen = strlen(message) + REPORT_MSG_FORMAT_LEN; +// +// /* check if message fit the supplied buffer */ +// if (*maxlen < msgLen) +// { +// errno = REPORT_ERROR_NOT_ENOUGH_MEMORY; +// return ERROR; +// } +// /* Format message. +// ATTENTION: DON'T forget to change REPORT_MSG_FORMAT_LEN +// when changing the format string */ +// if (SEVERITY_MASK(severity) == RpPrivate) +// { +// DstrTableEntry = (severity >> 5); +// if (Dist_Table[DstrTableEntry].IsAlive == false) +// { +// errno = REPORT_ERROR_ILLEGAL_PARAMETER; +// return ERROR; +// } +// name = Dist_Table[DstrTableEntry].name; +// } +// else +// name = severities[severity-1]; +// +// *maxlen = sprintf(buffer,"%s: #%d: %s (0x%x,0x%x)\r\n",name,errorCode,message,parameter1,parameter2); +// return OK; +//} + + +/*************************************************************************** + * + * Name : FindFreeDestinationElement + * + * Function : Find Free Destination Element. + * + * Notes : + * + * Return value: index if found , ERROR - otherwise + **************************************************************************/ +int FindFreeDestinationElement(int DistTableEntry) +{ + int index; + + for (index=0; index>5) + +/* The mask of currently enabled severity. */ +extern bool filterTest(ErrorSeverity severity); + +extern STATUS distibutorInit( int priority, int maxMsgs, int maxDestinations ); + +extern STATUS reportDistribute(FormatType format, + const char *message, + char *FileName, + int LineNumber, + int errorCode, + ErrorSeverity severity, + int parameter1, + int parameter2); + + +/*************************************************************************** + * + * Name : ReportStrCmp + * + * Function : compare between two string with case-insensitive. + * + * Notes : + * + * Return value: TRUE - strings are identical; FALSE - otherwise + **************************************************************************/ +extern bool ReportStrCmp(const char *str1, const char *str2); + + +/*************************************************************************** + * + * Name : IsNameExistsInDistributorTable + * + * Function : Check if a given name is already found in the table + * of the private severities + * + * Notes : + * + * Return value: TRUE if found; FALSE otherwise + **************************************************************************/ +extern bool IsNameExistsInDistributorTable(const char *name); + +/*************************************************************************** + * + * Name : ReportGetDistributorHandleByName + * + * Function : Get the severity handle given the severity's name + * + * Notes : + * + * Return value: the handle; or -1 if no such name + **************************************************************************/ +extern DistributorHandle ReportGetDistributorHandleByName(const char *distributorName); + + +/*************************************************************************** + * + * Name : GetDistributorParamsByHandle + * + * Function : Get the private severity details according to its handle + * + * Parameters : DistributorHandle - table entry + * name - buffer to contain the private severity's name + * IsActive - FALSE if the private severity + * + * Notes : The name field must exceeds 10 bytes long + * + * Return value: OK or ERROR and then: + * errno = REPORT_ERROR_ILLEGAL_PARAMETER if no such entry + * errno = REPORT_ERROR_FILTER_NOT_ALIVE if the private + * severity has already removed (and thus it is no + * no longer exists until re-added). + **************************************************************************/ +extern STATUS GetDistributorParamsByHandle(uint32_t DistributorHandle, + char *name, + bool *IsActive); +/* Total message length w/o message text in bytes + (for reportMsgFormat function ) */ +#define REPORT_MSG_FORMAT_LEN 61 + +#endif /* __RDISTRIBUTOR_H__ */ + diff --git a/Software/Embedded_SW/Embedded/Common/report/filter.c b/Software/Embedded_SW/Embedded/Common/report/filter.c new file mode 100644 index 000000000..7efc56d36 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/report/filter.c @@ -0,0 +1,526 @@ + /*+************************************************************************* + * File name : FILTER.C + * Title : TERMINAL DRIVER INTERFACE + * Project : NEVADA + * Subsystem : SYSTEM + * Date created: 18 SEP, 1997 + * Revision : Rev 1.0 + * Author : Zvika Zilberman + * History : 18.09.97 Zvika Zilberman - porting to DCME SWINFRA + * + * Description : This file includes the FILTER part of the report package + * + * + * Procedures: + * + * Report - Report message using filters and message multiplexing. + * ReportSeveritySet - Set message severity + * + ******************************************************************************/ + +#include "report.h" +#include +#include +#include +#include +#include "stdint.h" /* RETCODE */ +#include "filter.h" +#include "distributor.h" /* reportDistribute */ + +#define MAX_STRING_LEN 255 + +/*------------- Local Data ------------------------------*/ + +/* the filter's table */ + +packageFilter *packageFilterTable; +uint8_t filterTableSize; +uint8_t filterNumOfCurrentEntries; + +/* The mask of currently enabled severity. */ +static ErrorSeverity SeverityLevel; + +/* flag allows or dennies filter usage */ +static bool filterDontUse; + + +/*************************************************************************** + * + * Name : filterTableInit + * + * Function : Init the filtering mechanism + * + * Notes : + * + * Return value: OK; ERROR if malloc is failed + **************************************************************************/ +STATUS filterTableInit(uint32_t TableSize) +{ + int index; + + filterTableSize = TableSize; + packageFilterTable = (packageFilter*)malloc(sizeof(packageFilter)*TableSize); + if (packageFilterTable == NULL) + return ERROR; + for (index=0; index 10) + { + errno = REPORT_ERROR_NAME_TOO_LONG; + return -1; + } + else if ((IsNameExistsInDistributorTable(filterName)) && (SwitchAddRemove == REPORT_ADD)) + { + errno = REPORT_ERROR_NAME_EXISTS; + return -1; + } + for (index=0; index= filterNumOfCurrentEntries) + return ERROR; + packageFilterTable[ReportPackageHandle].filterDontUse = (SwitchOnOff == REPORT_OFF); + return OK; +} + + +/*************************************************************************** + * + * Name : GetFilterParamsByHandle + * + * Function : Get the filter details according to its handle + * + * Notes : filterNameBuf must exceeds 10 bytes long + * + * Return value: OK; or ERROR if wrong handle + **************************************************************************/ +STATUS GetFilterParamsByHandle(uint32_t filterHandle, + packageFilter *pPackage) +{ + if (filterHandle >= filterNumOfCurrentEntries) + return ERROR; + strcpy(pPackage->filterName,packageFilterTable[filterHandle].filterName); + pPackage->filterDontUse = packageFilterTable[filterHandle].filterDontUse; + pPackage->IsActive = packageFilterTable[filterHandle].IsActive; + return OK; +} + + +/*************************************************************************** + * + * Name : GetFilterHandleByName + * + * Function : Get the filter handle given the filter's name + * + * Notes : + * + * Return value: the handle; or -1 if no such name + **************************************************************************/ +int ReportGetFilterHandleByName(const char *filterName) +{ + int index; + + for (index = 0; index < filterNumOfCurrentEntries; index++) + if (ReportStrCmp(filterName,packageFilterTable[index].filterName) == true) + { + if (packageFilterTable[index].IsActive) + return index; + else + return -1; /* disable used */ + } + return -1; +} + + +/*************************************************************************** + * + * Name : IsNameExistsInFiltersTable + * + * Function : Check if a given name is already found in the filter's + * table. + * + * Notes : + * + * Return value: true if found; false otherwise + **************************************************************************/ +bool IsNameExistsInFiltersTable(const char *name) +{ + int index; + + for (index = 0; index < filterNumOfCurrentEntries; index++) + if (ReportStrCmp(name,packageFilterTable[index].filterName) == true) + return true; + return false; +} + + +/*************************************************************************** + * + * Name : ReportFilterTest + * + * Function : Test the filter's handle to check if to report or not + * + * Notes : + * + * Return value: true - discard the report; false - report. + **************************************************************************/ +bool ReportFilterTest(uint8_t filterHandle) +{ + if (filterHandle >= filterNumOfCurrentEntries) + return false; + return (packageFilterTable[filterHandle].filterDontUse); +} + + +bool filterTest(ErrorSeverity severity) +{ + if (filterDontUse) + return true; /* The filter machnism is disabled - */ + /* all errors are enabled */ + if( SeverityLevel <= severity ) /* check for severity */ + return true; + + return false; +} + + +/*************************************************************************** + * + * Name : ReportSeveritySet + * + * Function : Determine the filter level of the message's severity + * + * Notes : Messages with severity below this level wont be sent to + * their output + * + * Return value: void + **************************************************************************/ +void ReportSeveritySet(ErrorSeverity level) +{ + SeverityLevel = level; +} + + +/*************************************************************************** + * + * Name : Report + * + * Function : PEPORT main routine + * + * Notes : + * + * Parameters: message - user's message + * errorCode - should be the return code of the routine that + * failed and made this report + * severity - the error level + * parameter1 - user params no.1 (for additional information) + * parameter2 - another user params. + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +STATUS Report(const char *message, + char *FileName, + int LineNumber, + int errorCode, + ErrorSeverity severity, + int parameter1, + int parameter2) +{ + + /* if message passes the filter send it to distributor */ + if (filterTest(severity) || (GET_PRIVATE_SEVERITY(severity) > 0)) + return reportDistribute(REPORT_FORMAT, + message, + FileName, + LineNumber, + errorCode, + severity, + parameter1, + parameter2); + return OK; +} + + +/*************************************************************************** + * + * Name : ReportMessage2SysDist + * + * Function : Report a message to the System Distributor + * + * Notes : The severity of this report is always + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +/*STATUS ReportMessage2SysDist(const char *message) +{ + if (filterTest(RpMessage) == false) + return OK; + return reportDistribute(MESSAGE_FORMAT, message,NULL,0, 0, RpMessage, 0, 0); +} + +STATUS ReportMessage(const char *message) +{ + if (filterTest(RpMessage) == false) + return OK; + return reportDistribute(MESSAGE_FORMAT, message, NULL, 0,0, RpMessage, 0, 0); +} + +*/ +/*************************************************************************** + * + * Name : ReportPackageMessage2SysDist + * + * Function : Report a message to the System distributor if the handle + * is not filtered + * + * Notes : The severity of this report is always + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +/*STATUS ReportPackageMessage2SysDist(PackageHandle ReportPackageHandle, const char *message) +{ + if (filterTest(RpMessage) == false) + return OK; + if (ReportFilterTest(ReportPackageHandle)) + return OK; + return ReportMessage2SysDist(message); +} +*/ + +/*************************************************************************** + * + * Name : ReportFormatMessage2SysDist + * + * Function : Report a formatted message (like printf) to the System + * distributor + * + * Notes : The severity of this report is always + * IMPORTANT: the formatting is done in the context of the + * calling application!! + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +/*STATUS ReportFormatMessage2SysDist(const char *format, ...) +{ + static char text[MAX_STRING_LEN]; + va_list ap; + + if (filterTest(RpMessage) == false) + return OK; + + va_start (ap , format ); + vsprintf ( text , format , ap ); + va_end ( ap ); + return reportDistribute(MESSAGE_FORMAT, text, NULL,0,0, RpMessage, 0, 0); +} + +STATUS Reportf(const char *format, ...) +{ + static char text[MAX_STRING_LEN]; + va_list ap; + + if (filterTest(RpMessage) == false) + return OK; + + va_start (ap , format ); + vsprintf ( text , format , ap ); + va_end ( ap ); + return reportDistribute(MESSAGE_FORMAT, text, NULL,0,0, RpMessage, 0, 0); +} + +*/ +/*************************************************************************** + * + * Name : ReportWithFilter + * + * Function : PEPORT with filter - main routine + * + * Notes : It is recommended to use one of the macros below instead + * of using this routine directly. This is because the macros + * support other benefits such: file name, line number etc. + * + * Parameters: handle - filter's handle + * message - user's message + * errorCode - should be the return code of the routine that + * failed and made this report + * severity - the error level + * parameter1 - user params no.1 (for additional information) + * parameter2 - another user param. + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +STATUS ReportWithPackageFilter(PackageHandle ReportPackageHandle, + const char *message, + char *FileName, + int LineNumber, + int errorCode, + ErrorSeverity severity, + int parameter1, + int parameter2) +{ + if (ReportFilterTest(ReportPackageHandle)) + return OK; /* discard message */ + return Report(message,FileName,LineNumber,errorCode,severity,parameter1,parameter2); +} + + +/*************************************************************************** + * + * Name : ReportFormatPackageMessage2SysDist + * + * Function : Report a formatted message (like printf) to the output + * if handle is not filtered + * + * Notes : The severity of this report is always + * IMPORTANT: the formatting is done in the context of the + * calling task!! + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +/*STATUS ReportFormatPackageMessage2SysDist(PackageHandle ReportPackageHandle, + const char *format, ...) +{ + static char text[MAX_STRING_LEN]; + va_list ap; + + if (ReportFilterTest(ReportPackageHandle)) + return OK; + if (filterTest(RpMessage) == false) + return OK; + va_start (ap , format ); + vsprintf ( text , format , ap ); + va_end ( ap ); + return reportDistribute(MESSAGE_FORMAT, text, NULL,0,0, RpMessage, 0, 0); +}*/ + diff --git a/Software/Embedded_SW/Embedded/Common/report/filter.h b/Software/Embedded_SW/Embedded/Common/report/filter.h new file mode 100644 index 000000000..481f6cb66 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/report/filter.h @@ -0,0 +1,74 @@ + +#ifndef __RFILTER_H__ +#define __RFILTER_H__ + +/* the type definition of the filter per package */ +#ifdef __cplusplus +extern "C"{ +#endif + +typedef struct packageFilter { + char filterName[11]; /* up to 10 letter of filter's name */ + bool filterDontUse; /* TRUE - dont use. FALSE - send to report */ + bool IsActive; /* TRUE - can be used. FALSE - disable it */ +} packageFilter; + +/*************************************************************************** + * + * Name : filterTableInit + * + * Function : Init the filtering mechanism + * + * Notes : + * + * Return value: OK; ERROR if malloc is failed + **************************************************************************/ +extern STATUS filterTableInit(uint32_t TableSize); + + +/*************************************************************************** + * + * Name : GetFilterParamsByHandle + * + * Function : Get the filter details according to its handle + * + * Notes : filterNameBuf must exceeds 10 bytes long + * + * Return value: OK; or ERROR if wrong handle + **************************************************************************/ +extern STATUS GetFilterParamsByHandle(uint32_t filterHandle, + packageFilter *pPackage); + + +/*************************************************************************** + * + * Name : IsNameExistsInFiltersTable + * + * Function : Check if a given name is already found in the filter's + * table. + * + * Notes : + * + * Return value: TRUE if found; FALSE otherwise + **************************************************************************/ +extern bool IsNameExistsInFiltersTable(const char *name); + + +/*************************************************************************** + * + * Name : GetFilterHandleByName + * + * Function : Get the filter handle given the filter's name + * + * Notes : + * + * Return value: the handle; or -1 if no such name (or filter was removed). + **************************************************************************/ +extern int ReportGetFilterHandleByName(const char *filterName); + +#ifdef __cplusplus +} +#endif + +#endif /* __RFILTER_H__ */ + diff --git a/Software/Embedded_SW/Embedded/Common/report/report.h b/Software/Embedded_SW/Embedded/Common/report/report.h new file mode 100644 index 000000000..d98844d71 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/report/report.h @@ -0,0 +1,593 @@ +/****************************************************************************** + * File name : REPORT.H + * Title : INFRA REPORT PACKAGE - Application Interface + * Date created : 16 SEP, 1997 + * Revision : 2.0 + * Author : Zvika Zilberman + * + * Description : This package provides services for reporting and + * debug tracing. The package includes: + * - Error coding convention definitions + * - Message report interface + * - Message filtering interface + * - Message distributor interface + * - Compatibility with UT_EXCEPTION package + * + ****************************************************************************** + * + * History: + * 01.05.96 Roie Geron - first cut + * 01.09.96 Ilia Maller - start of coding + * 21.02.97 Ilia Maller - minor improvements + * 16.09.97 Zvika Zilberman - porting to DCME SWINFRA (0200 - 0240) + * 29.07.98 Zvika Zilberman - approach to new generation (0300 - 0320) + * 10.11.98 Zvika Zilberman - update the new generation (0330) + * + ****************************************************************************** + * Dependencies of SWINFRA packages: + * Terminal + * Monitor + ******************************************************************************/ + +#ifndef __REPORT_H__ +#define __REPORT_H__ + + +/*---------------------------- Includes ---------------------------------------*/ + +#include "include.h" +#include /* _ASSET_STR */ +#include "PMR/common/MessageContainer.pb-c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*#define OK 0 +#define ERROR -1 +//#define FALSE false +//#define TRUE true +#define OFF 0 +#define ON 1 +*/ +#define RET_NOTOK -1 +#define RET_OK 0 +typedef int STATUS; +/*--------------------------- Type definitions -------------------------------*/ + +/* This following redefinition is the filter level. Reports with lower severity than */ +/* the filter's one, won't be sent to the output. */ +typedef int ErrorSeverity; + +#define RpMessage 0x1 +#define RpWarning 0x2 +#define RpError 0x4 +#define RpFatalError 0x8 +#define RpPrivate 0x10 +typedef int DistributorHandle; +typedef int PackageHandle; + +#define REPORT_MAX_MSG_LEN 128 + +/* Use the following macro in order to pass the private severity as the */ +/* severity parameter to one of the Report routines */ +#define SET_PRIVATE_DISTRIBUTOR(handle) (ErrorSeverity)(Private | ((handle)<<5)) + +/* The following are some constant for control and manipulation throughout the */ +/* Report's control routines */ +#define REPORT_OFF 0 +#define REPORT_ON 1 +#define REPORT_REMOVE 0 +#define REPORT_ADD 1 + +/* This is a prototype of the output hook. When adding a function to the distributor, */ +/* the routine's prototype should be the same as here */ +typedef int (* ReportFunction)(char *message, /* The formatted message */ + char *FileName, + int LineNumber, + int errorCode, /* error code that caused the report */ + int parameter1, /* user parameter no. 1 */ + int parameter2); /* user parameter no. 2 */ + +/* Initialization struct. Default values are below */ +typedef struct{ + int DistributorTaskPriority; /* The report task's priority */ + int DistributorQueueMaxMsgs; /* Maximum number of messages in the queue */ + int MaxNumberOfPrivateDistributors; /* Maximum number of private distributor */ + int MaxNumOfFilterNames; /* Maximum number of filters to enable the applica */ +}ReportInitParams; +/* these values can be used as default in the above package configuration */ +#define REPORT_TASK_PRIORITY 150 +#define REPORT_MAX_FILTER_PACKAGES 20 +#define REPORT_QUEUE_MAX_MSGS 100 + + +/*----------------------------------------------------------------------------*/ +/*---------------------- Report Tracing and Exceptions -----------------------*/ +/*---------------------------- without filtering -----------------------------*/ +/*----------------------------------------------------------------------------*/ +//void SendStatusResponse (uint32_t Code, char *Token); +/*************************************************************************** + * + * Name : ReportInit + * + * Function : PEPORT library init + * + * Notes : Should be called before any other function from the Report + * package. + * + * Return value: OK or ERROR if malloc has failed or task creation has + * failed + **************************************************************************/ +extern STATUS ReportInit(ReportInitParams InitParams); +extern uint32_t ReportInitMessage(MessageContainer* requestContainer); + +/*************************************************************************** + * + * Name : Report + * + * Function : PEPORT main routine + * + * Notes : It is recommended to use one of the macros below (Debug + * Tracing ) instead of using this routine directly. This + * is because the macros support other benefits such: file + * name, line number etc. + * + * Parameters: message - user's message + * errorCode - should be the return code of the routine that + * failed and made this report + * severity - the error level + * parameter1 - user params no.1 (for additional information) + * parameter2 - another user param. + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +extern STATUS Report(const char *message, + char *FileName, + int LineNumber, + int errorCode, + ErrorSeverity severity, + int parameter1, + int parameter2); + + +/*************************************************************************** + * + * Name : ReportMessage2SysDist + * + * Function : Report a message to the System distributor + * + * Notes : The severity of this report is always + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +extern STATUS ReportMessage2SysDist(const char *message); + + +/*************************************************************************** + * + * Name : ReportFormatMessage2SysDist + * + * Function : Report a formatted message (like printf) to the System + * distributor + * + * Notes : The severity of this report is always + * IMPORTANT: the formatting is done in the context of the + * calling task!! + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +extern STATUS ReportFormatMessage2SysDist(const char *format, ...); + + +/*************************************************************************** + * + * Name : ReportMessage2Dist + * + * Function : Report a message to the appropriate distributor + * + * Notes : The distributor handle should be passed using the macro + * SET_PRIVATE_DISTRIBUTOR + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +extern STATUS ReportMessage2Dist(DistributorHandle distributor, const char *message); + + +/*************************************************************************** + * + * Name : REPORT_ERR + * + * Function : Report an error + * + * Notes : Attention: this is a macro. Will add the file name & the + * line number where the error is reported + * + * Parameters : See above, Report. + * + * Return value: OK; or Report's return code + **************************************************************************/ +#define REPORT_ERR(msg, error, severity, par1, par2) \ + Report(REPORT_LINE(msg), error, severity, par1, par2) + + +/*************************************************************************** + * + * Name : REPORT_IF_ERROR + * + * Function : if is TRUE then report an error + * + * Notes : Attention: this is a macro. Will add the file name & the + * line number where the error is reported + * + * Parameters : See above, Report. + * + * Return value: OK; or Report's return code + **************************************************************************/ +#define REPORT_IF_ERROR(condition, msg, error, severity, par1, par2) \ + ((condition) ? Report(REPORT_LINE(msg), error, severity, par1, par2) : OK) + +/*----------------------------------------------------------------------------*/ +/*---------------------- Report Tracing and Exceptions -----------------------*/ +/*----------------------------- with filtering -------------------------------*/ +/*----------------------------------------------------------------------------*/ + +/*************************************************************************** + * + * Name : ReportWithPackageFilter + * + * Function : PEPORT with package filter - main routine + * + * Notes : It is recommended to use one of the macros below instead + * of using this routine directly. This is because the macros + * support other benefits such: file name, line number etc. + * + * Parameters: ReportPackageHandle - filter's handle + * message - user's message + * errorCode - should be the return code of the routine + * that failed and made this report + * severity - the error level + * parameter1 - user params no.1 (for additional + * information) + * parameter2 - another user param. + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +extern STATUS ReportWithPackageFilter(PackageHandle ReportPackageHandle, + const char *message, + char *FileName, + int LineNumber, + int errorCode, + ErrorSeverity severity, + int parameter1, + int parameter2); + + +/*************************************************************************** + * + * Name : ReportPackageMessage2SysDist + * + * Function : Report a message to the System distributor if the handle + * is not filtered + * + * Notes : The severity of this report is always + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +/*extern STATUS ReportPackageMessage2SysDist(PackageHandle ReportPackageHandle, + const char *message); +*/ + +/*************************************************************************** + * + * Name : ReportFormatPackageMessage2SysDist + * + * Function : Report a formatted message (like printf) to the output + * if handle is not filtered + * + * Notes : The severity of this report is always + * IMPORTANT: the formatting is done in the context of the + * calling task!! + * + * Return value: OK or ERROR if failed to send to distributor + **************************************************************************/ +/*extern STATUS ReportFormatPackageMessage2SysDist(PackageHandle ReportPackageHandle, + const char *format, ...); +*/ + +/*************************************************************************** + * + * Name : REPORT_ERR_FILTER + * + * Function : Report an error if handle is not filtered + * + * Notes : Attention: this is a macro. Will add the file name & the + * line number where the error is reported + * + * Parameters : See above, Report. + * + * Return value: OK; or Report's return code + **************************************************************************/ +#define REPORT_ERR_FILTER(handle, msg, FileName, LineNumber,error, severity, par1, par2) \ + ReportWithPackageFilter(handle, REPORT_LINE(msg), FileName, LineNumber,error, severity, par1, par2) + + +/*************************************************************************** + * + * Name : REPORT_IF_ERROR_FILTER + * + * Function : if is TRUE and handle is not filtered + * then report an error + * + * Notes : Attention: this is a macro. Will add the file name & the + * line number where the error is reported + * + * Parameters : See above, Report. + * + * Return value: OK; or Report's return code + **************************************************************************/ +#define REPORT_IF_ERROR_FILTER(condition, handle, msg, FileName, LineNumber,error, severity, par1, par2) \ + ((condition) ? REPORT_ERR_FILTER(handle,msg,FileName, LineNumber,error,severity,par1,par2) : OK) + + +/*************************************************************************** + * + * Name : ReportAddFilterPackage + * + * Function : Add a package filter to the package filter's data base + * + * Notes : + * + * Parameters : filterName - The filter's name must be up to 10 letters + * long + * + * Return value: The new filter handle; or -1 in case of an ERROR, thus: + * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name, + * errno = REPORT_ERROR_TABLE_FULL if there are already too + * many filters, + * errno = REPORT_ERROR_NAME_EXISTS if the filterName already exists. + **************************************************************************/ +extern PackageHandle ReportAddFilterPackage(const char *filterName); + + +/*************************************************************************** + * + * Name : ReportRemoveFilterPackage + * + * Function : Remove a package filter from the package filter's data base + * + * Notes : + * + * Parameters : filterName - The filter's name must be up to 10 letters + * long + * + * Return value: OK; or ERROR and thus errno is set to one of the following: + * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name, + * errno = REPORT_ERROR_NAME_ALREADY_DISABLE if the filter was + * already removed, + * errno = REPORT_ERROR_NAME_NOT_EXISTS if the filterName not exists. + **************************************************************************/ +extern STATUS ReportRemoveFilterPackage(const char *filterName); + + +/*************************************************************************** + * + * Name : ReportSwitchPackageFilter + * + * Function : Switch the filter of the given handle + * + * Notes : REPORT_ON - filter is active. messages do not discarded. + * REPORT_OFF - filter is not active. Its messages are discarded. + * + * Return value: OK; or ERROR if wrong handle + **************************************************************************/ +extern STATUS ReportSwitchPackageFilter(PackageHandle ReportPackageHandle, uint32_t SwitchOnOff); + +/*----------------------------------------------------------------------------*/ +/*---------------------------- Distributor -----------------------------------*/ +/*----------------------------------------------------------------------------*/ + +/*************************************************************************** + * + * Name : ReportAddDistributor + * + * Function : Add private distributor + * + * Notes : + * + * Parameters: distributorName - The name must be up to 10 letters long + * + * Return value: The new distributor handle, or -1 and thus: + * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name, + * errno = REPORT_ERROR_TABLE_FULL if there are already too + * many distributors, + * errno = REPORT_ERROR_NAME_EXISTS if the distributorName + * already exists. + **************************************************************************/ +extern DistributorHandle ReportAddDistributor(const char *distributorName); + + +/*************************************************************************** + * + * Name : ReportRemoveDistributor + * + * Function : Remove private distributor + * + * Notes : The distributor's messages will be discarded. + * Its name will be no longer seen in the distributor's list + * when the REP_CONTROL is typed in the Monitor. + * + * Parameters: distributorName - The severity's name must be up to 10 + * letters long. + * + * Return value: OK; or ERROR and thus errno is set to one of the following: + * errno = REPORT_ERROR_NAME_TOO_LONG in case of long name, + * errno = REPORT_ERROR_NAME_ALREADY_DISABLE if the distributor + * was already removed, + * errno = REPORT_ERROR_NAME_NOT_EXISTS if the distributorName + * not exists. + **************************************************************************/ +extern DistributorHandle ReportRemoveDistributor(const char *distributorName); + + +/*************************************************************************** + * + * Name : ReportDistributorControl + * + * Function : Disable / enable the flow of reports given its private + * severity + * + * Notes : Disable reports using the constant REPORT_OFF + * Enable the reports using the constant REPORT_ON + * + * Return value: OK or ERROR if illegal Distributor + **************************************************************************/ +extern STATUS ReportDistributorControl(DistributorHandle Distributor, uint32_t SwitchOnOff); + +/*----------------------------------------------------------------------------*/ +/*------------------------ Message Distributor -------------------------------*/ +/*----------------------------------------------------------------------------*/ + +/*************************************************************************** + * + * Name : ReportFd + * + * Function : Add or remove a file descriptor to/from the output distributor + * + * Notes : + * + * Parameters: fd - file descriptor. Supplied by the user + * SwitchAddRemove - REPORT_ADD to add the fd + * REPORT_REMOVE to remove it. + * Distributor - 0 if not concerned with any private + * severity, or the private severity's handle + * to set with the given fd + * + * Return value: OK or ERROR with: + * errno = REPORT_ERROR_NOT_ENOUGH_MEMORY if destination list + * is full + * errno = REPORT_ERROR_ILLEGAL_PARAMETER if (fd == -1) or + * not found if asked to remove + **************************************************************************/ +extern STATUS ReportFd(int fd, uint32_t SwitchAddRemove, DistributorHandle Distributor); + + +/*************************************************************************** + * + * Name : ReportFunc + * + * Function : Add or remove an output routine to/from the distributor + * + * Notes : + * + * Parameters: func - hook to the routine. Supplied by the user . + * SwitchAddRemove - REPORT_ADD to add the hook + * REPORT_REMOVE to remove it. + * Distributor - Set 0 if not concerned with any private + * severity, or give the private severity's + * handle to set with the given fd. + * + * Return value: OK or ERROR with: + * errno = REPORT_ERROR_NOT_ENOUGH_MEMORY if destination list + * is full + * errno = REPORT_ERROR_ILLEGAL_PARAMETER if (func == NULL) + **************************************************************************/ +extern STATUS ReportFunc(ReportFunction func, + uint32_t SwitchAddRemove, + DistributorHandle Distributor); + + +/*************************************************************************** + * + * Name : ReportMonitorFunc + * + * Function : Add/remove an output routine that prints to the monitor + * + * Notes : Hiding Report messages from appearing on the monitor is + * enable when the HALT> prompt is shown (by pressing ). + * The filtering is done using an internal routine. + * This routine can be added/removed using this call. + * It can be added either to the regular distributor or to each + * of the private distributors + * + * Parameters: SwitchAddRemove - REPORT_ADD to add the routine + * REPORT_REMOVE to remove it. + * Distributor - Set 0 if not concerned with any private + * severity, or give the private severity's + * handle to set with it . + * + * Return value: void + **************************************************************************/ +extern void ReportMonitorFunc(uint32_t SwitchAddRemove, uint32_t Distributor); + +/*----------------------------------------------------------------------------*/ +/*------------------------------ Severity ------------------------------------*/ +/*----------------------------------------------------------------------------*/ + +/*************************************************************************** + * + * Name : ReportSeveritySet + * + * Function : Determine the filter level of the message's severity + * + * Notes : Messages with severity below this level wont be sent to + * their output + * It does not affect the private severities + * + * Return value: void + **************************************************************************/ +extern void ReportSeveritySet(ErrorSeverity level); + +/*----------------------------------------------------------------------------*/ + +#define S1(x) #x +#define S2(x) S1(x) +//#define LOCATION __FILE__ " : " S2(__LINE__) +#define REPORT_LINE(message) __FILE__ "." S2(__LINE__) ":t"S2(UsersysTickGet())" : " S2(message) +//#define REPORT_LINE(message) __FILE__ "." _ASSERT_STR(__LINE__) ": " message + +/*----------------------------------------------------------------------------*/ +/*---------------------- Backward Support to UT_Except -----------------------*/ +/*----------------------------------------------------------------------------*/ + +#define ON_ERROR_REPORT_ERROR(msg) if ( rc != 0 ) \ + Report("\n\r*** ERROR :" REPORT_LINE(msg),__FILE__,__LINE__,rc,RpFatalError,0,0) + +#define REPORT_ERROR(rc,msg) \ + Report("\n\r*** ERROR :" REPORT_LINE(msg),__FILE__,__LINE__,rc,RpFatalError,0,0) + +#define ON_ERROR_LOG_ERROR(msg) if ( rc != 0 ) \ + Report("\n\r*** ERROR :" REPORT_LINE(msg),__FILE__,__LINE__,rc,RpError,0,0) + +#define LOG_ERROR(rc,msg) \ + Report("\n\r*** ERROR :" REPORT_LINE(msg),__FILE__,__LINE__,rc,RpError,0,0) + +/*----------------------------------------------------------------------------*/ +/*----------------------- Backward Compatible --------------------------------*/ +/*----------------------------------------------------------------------------*/ +extern STATUS ReportMessage(const char *message); +extern STATUS Reportf(const char *format, ...); +#define ReportFilterMessage ReportPackageMessage2SysDist + +/*----------------------------------------------------------------------------*/ +/*---------------------------- Error Codes -----------------------------------*/ +/*----------------------------------------------------------------------------*/ + +/* Error, returned by errno in Report's routines */ +#define REPORT_ERROR_ILLEGAL_PARAMETER 1 +#define REPORT_ERROR_CODE_NOT_FOUND 2 +#define REPORT_ERROR_FILTER_NOT_ALIVE 3 +#define REPORT_ERROR_NAME 10 +#define REPORT_ERROR_NAME_EXISTS 11 +#define REPORT_ERROR_NAME_NOT_EXISTS 12 +#define REPORT_ERROR_NAME_TOO_LONG 13 +#define REPORT_ERROR_NAME_ALREADY_DISABLE 14 +#define REPORT_ERROR_NOT_ENOUGH_MEMORY 20 +#define REPORT_ERROR_TABLE_FULL 21 + +#ifdef __cplusplus +} +#endif + +#endif /* __REPORT_H__ */ + diff --git a/Software/Embedded_SW/Embedded/Common/report/reportInit.c b/Software/Embedded_SW/Embedded/Common/report/reportInit.c new file mode 100644 index 000000000..c7ea0c194 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Common/report/reportInit.c @@ -0,0 +1,161 @@ +/****************************************************************************** + * File name : reportInit.c + * Title : REPORT PACKAGE - Application Interface + * Date created : 01 SEP, 1996 + * Revision : 1.0 + * Author : Ilia Maller, Zvika Zilberman + * + * Description : + * + ****************************************************************************** + * + * Procedures: + * + * ReportInit - Initialise report package + * + ****************************************************************************** + * + * History: + * 01.09.96 Ilia Maller - start of coding + * 21.02.97 Ilia Maller - minor improvements + * 17.09.97 Zvika Zilberman - porting to DCME SWINFRA + * + ******************************************************************************/ + +/*------------- Includes --------------------------------*/ + +#include /* puts(), etc. */ +#include "report.h" +#include "distributor.h" /* distibutorInit */ +#include "filter.h" +#include "include.h" + +#include +#include "PMR/common/MessageContainer.pb-c.h" +#include "PMR/debugging/DebugLogRequest.pb-c.h" +#include "PMR/debugging/DebugLogResponse.pb-c.h" +#include "drivers/twine_usblib/usb_serial_adapter.h" +//#include "graphics_adapter.h" +#include "Modules/Stubs_Handler/Container.h" + +#include "Modules/thread/thread.h" + +MotorConfigStruc MotorsCfg[MAX_THREAD_MOTORS_NUM]; +InternalWinderConfigStruc InternalWinderCfg; +char protobufToken[36]; +/*void SendStatusResponse (uint32_t Code, char *Token) +{ + MessageContainer responseContainer; + StatusResponse response = STATUS_RESPONSE__INIT; + + + response.has_status = true; + response.status = (ErrorCode)Code; + + responseContainer = createContainer(MESSAGE_TYPE__StatusResponse, Token, true, &response, &status_response__pack, &status_response__get_packed_size); + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + + +}*/ + +int ReportResponseFunc(char *message, /* The formatted message */ + char *FileName, + int LineNumber, + int errorCode, /* error code that caused the report */ + int parameter1, /* user parameter no. 1 */ + int parameter2) /* user parameter no. 2 */ +{ + MessageContainer responseContainer; + + DebugLogResponse response = DEBUG_LOG_RESPONSE__INIT; + response.filename = FileName; + response.has_linenumber = true; + response.linenumber = LineNumber; + /*response.has_errorcode = true; + response.errorcode = (ErrorCode)errorCode; + response.has_severity = true; + response.severity = (Severity)parameter1;*/ + response.has_filter = true; + response.has_category = true; + response.category = (DebugLogCategory)parameter1; + response.filter = parameter2; + strcpy (response.message,message); + responseContainer = createContainer(MESSAGE_TYPE__DebugLogResponse, protobufToken, false, &response, &debug_log_response__pack, &debug_log_response__get_packed_size); + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + + return OK; + +} + + +uint32_t ReportInitMessage(MessageContainer* requestContainer) +{ + uint32_t status = NOT_SUPPORTED; + //MessageContainer responseContainer; + + ReportInitParams InitParams; + + DebugLogRequest* request = debug_log_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + strcpy (protobufToken, requestContainer->token); + InitParams.DistributorQueueMaxMsgs = 20; + InitParams.DistributorTaskPriority = 6; + InitParams.MaxNumOfFilterNames = 1; + InitParams.MaxNumberOfPrivateDistributors = 2; + status |= ReportInit (InitParams); + DistributorHandle ReportHandle = ReportAddDistributor("ProtoBuf"); + if (ReportHandle == NULL) status |= 0x8; + status |= ReportFunc(ReportResponseFunc , REPORT_ADD, ReportHandle); + + return status; +} + +#define REPORT_RESERVED_NUM_OF_FILTER_PACKAGES 30 /* This reserved for swinfra packages */ + +/*************************************************************************** + * + * Name : ReportInit + * + * Function : PEPORT library init + * + * Notes : Should be called before any other function from the Report + * package. + * + * Return value: OK or ERROR if malloc has failed or task creation has + * failed + **************************************************************************/ +STATUS ReportInit(ReportInitParams InitParams) +{ + static int initialized = false; + STATUS status; + int MaxNumOfFilterNames; + + if (initialized) + return OK; + + /* Set the filter to receive all kind */ + ReportSeveritySet(RpMessage); + + /* Configure distributor */ + if( distibutorInit(InitParams.DistributorTaskPriority, + InitParams.DistributorQueueMaxMsgs, + InitParams.MaxNumberOfPrivateDistributors) == -1) + return ERROR; + + /* Add the support of the monitor commands */ + //ReportMonitorInit(); + /* Add the Monitor Output routine, by default */ + //ReportMonitorFunc(REPORT_ADD, 0); + + MaxNumOfFilterNames = InitParams.MaxNumOfFilterNames; + MaxNumOfFilterNames += REPORT_RESERVED_NUM_OF_FILTER_PACKAGES; + status = filterTableInit(MaxNumOfFilterNames); + if (status == OK) + initialized = true; + + return status; +} diff --git a/Software/Embedded_SW/Embedded/Drivers/ADC_Sampling/ADC.c b/Software/Embedded_SW/Embedded/Drivers/ADC_Sampling/ADC.c new file mode 100644 index 000000000..a99ed7134 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/ADC_Sampling/ADC.c @@ -0,0 +1,317 @@ +//***************************************************************************** +// +// This is the data acquisition module. It performs acquisition of data from +// selected channels, starting and stopping data logging, storing acquired +// data, and running the strip chart display. +// +//***************************************************************************** + +#include "ADC.h" +#include "include.h" +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include "Drivers/I2C_Communication/I2C.h" + +//***************************************************************************** +// +// The following defines which ADC channel control should be used for each +// kind of data item. Basically it maps how the ADC channels are connected +// on the board. This is a hardware pinmap configuration. +// Physical ADC connected channels in the TIVA +//***************************************************************************** + +#define CHAN_AIR_PRESSURE_1 ADC_CTL_CH0 +#define CHAN_AIR_PRESSURE_2 ADC_CTL_CH1 +#define CHAN_DISPENSE_PRESSURE_1 ADC_CTL_CH2 +#define CHAN_DISPENSE_PRESSURE_2 ADC_CTL_CH3 +#define CHAN_DISPENSE_PRESSURE_3 ADC_CTL_CH4 +#define CHAN_DISPENSE_PRESSURE_4 ADC_CTL_CH5 +#define CHAN_DISPENSE_PRESSURE_5 ADC_CTL_CH6 +#define CHAN_DISPENSE_PRESSURE_6 ADC_CTL_CH7 +#define CHAN_DISPENSE_PRESSURE_7 ADC_CTL_CH8 +#define CHAN_DISPENSE_PRESSURE_8 ADC_CTL_CH9 +#define CHAN_LEFT_DANCER_1 ADC_CTL_CH13 +#define CHAN_LEFT_DANCER_2 ADC_CTL_CH14 +#define CHAN_RIGHT_DANCER ADC_CTL_CH15 +#define CHAN_DRYER_CURRENT_1 ADC_CTL_CH16 +#define CHAN_DRYER_CURRENT_2 ADC_CTL_CH17 +#define CHAN_DRYER_CURRENT_3 ADC_CTL_CH18 + +//***************************************************************************** +// +// The following maps the order that items are acquired and stored by the +// ADC sequencers. Note that 16 samples are specified, using 2 of the +// 8 sample sequencers. The current is sampled multiple times deliberately +// because that value tends to bounce around. It is sampled multiple +// times and will be averaged. +// +//***************************************************************************** +uint32_t g_pui32ADCSeq[] = +{ + CHAN_AIR_PRESSURE_1,CHAN_AIR_PRESSURE_2, + CHAN_DISPENSE_PRESSURE_1, CHAN_DISPENSE_PRESSURE_2, CHAN_DISPENSE_PRESSURE_3, CHAN_DISPENSE_PRESSURE_4, + CHAN_DISPENSE_PRESSURE_5, CHAN_DISPENSE_PRESSURE_6, CHAN_DISPENSE_PRESSURE_7, CHAN_DISPENSE_PRESSURE_8, + CHAN_LEFT_DANCER_1, CHAN_LEFT_DANCER_2, CHAN_RIGHT_DANCER, + CHAN_DRYER_CURRENT_1, CHAN_DRYER_CURRENT_2, CHAN_DRYER_CURRENT_3 +}; + +#define NUM_ADC_CHANNELS (sizeof(g_pui32ADCSeq) / \ + sizeof(g_pui32ADCSeq[0])) + +//#define SAMPLE_ARRAY_SIZE (NUM_ADC_CHANNELS + I2C_NUM_OF_CHANNELS) +#define SAMPLE_ARRAY_SIZE NUM_ADC_CHANNELS +#define DOUBLE_BUFFER 2 + +static bool isInitialized = false; +static bool adcCollectActive = false; +static int bufferFlipFlop = 0; + +//***************************************************************************** +// +// Global _storage for most recent sampaled Sensor Data +// +//***************************************************************************** +// +// A buffer to hold one set of ADC data that is acquired per sample time. +// +//***************************************************************************** +static uint32_t g_pui32ADCData[DOUBLE_BUFFER][SAMPLE_ARRAY_SIZE]; + +//***************************************************************************** +//configured in the cfg file and thats why should be defined as extern +//***************************************************************************** +extern Semaphore_Handle adcResultSem; + +static ProcessCallback processCallBack; + +//***************************************************************************** +// ADCClockHandle: clock event handler - initiates trigger for the adc sampaling +//***************************************************************************** +// This function starts an ADC Conversion. +//static void ADCClockHandle(UArg arg0) +uint32_t ADC_TriggerCollection(void) +{ + // + // Kick off the next ADC acquisition. When these are done they will + // cause an ADC interrupt. + // + if (adcCollectActive == true) + { + MAP_ADCProcessorTrigger(ADC1_BASE, 0); + MAP_ADCProcessorTrigger(ADC0_BASE, 0); + } + return 0; +} +//***************************************************************************** +// +// ADC Data get for a single data read +// +//***************************************************************************** +uint32_t ADC_GetReading(int DataItemId) +{ + int bufnotinuse; + assert (DataItemId + +//***************************************************************************** +// +// The following are indexes for values returned from the ADC's. These index's +// map directly to g_pui32ADCSeq[], and inside this array there is a directly +// ADC copied data +//***************************************************************************** + +typedef enum +{ + AIR_PRESSURE_1, + AIR_PRESSURE_2, + DISPENSE_PRESSURE_1, + DISPENSE_PRESSURE_2, + DISPENSE_PRESSURE_3, + DISPENSE_PRESSURE_4, + DISPENSE_PRESSURE_5, + DISPENSE_PRESSURE_6, + DISPENSE_PRESSURE_7, + DISPENSE_PRESSURE_8, + LEFT_DANCER_1, + LEFT_DANCER_2, + RIGHT_DANCER, + DRYER_CURRENT_1, + DRYER_CURRENT_2, + DRYER_CURRENT_3, + MAX_ADC_DEVICES +}ADC_DATA_DEVICES; +//max potentiometer read in I2C protocol +#define MAX_DIGITAL_POTENTIOMETER_READ 0x660D + +typedef void (*ProcessCallback)(uint32_t* adcData); + +void ADCAcquireInit(void); + +uint32_t ADC_TriggerCollection(void); + +uint32_t ADC_GetReading(int DataItemId); + +void ADCAcquireStart(ProcessCallback _callback, uint32_t _period); + +void ADCAcquireStop(void); + +#endif /* DRIVERS_ADC_H_ */ diff --git a/Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.c b/Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.c new file mode 100644 index 000000000..5eea54a1c --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.c @@ -0,0 +1,488 @@ +//Avi Last update: 20/12/17 +//Based on TM4C129_SSI3_MacronixFlash.c +//On board Quad SPI 512Mb Flash + +#include +#include +#include +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_gpio.h" +#include "inc/hw_ssi.h" +#include "inc/hw_sysctl.h" +#include "inc/hw_epi.h" +#include "inc/hw_ints.h" +#include "inc/hw_nvic.h" + +#include "driverlib/debug.h" +#include "driverlib/fpu.h" +#include "driverlib/gpio.h" +#include "driverlib/rom.h" +#include "driverlib/rom_map.h" +#include "driverlib/interrupt.h" +#include "driverlib/pin_map.h" +#include "driverlib/sysctl.h" +#include "driverlib/ssi.h" +#include "driverlib/uart.h" +#include "utils/uartstdio.h" + +#include "drivers/twine_graphicslib/graphics_adapter.h" +#include "include.h" + +//#define NUM_SSI_DATA 20 +#define INS_WRITE_ENABLE 0x06 +#define INS_READ_STATUS_REGISTER1 0x05 +#define DUMMY_BYTE 0x00 +#define FLASH_BUSY_BIT 0x01 +#define FLASH_WRITE_EN_LATCH_BIT 0x02 +#define INS_SECTOR_ERASE_4KB 0x20 +#define INS_PAGE_PROGRAM 0x02 +#define INS_READ_DATA 0x03 + + +uint8_t g_ui8InstrReadID[] = {0x90,0x00,0x00,0x00}; +//uint32_t pui32DataTx[NUM_SSI_DATA]; +//uint32_t pui32DataRx[NUM_SSI_DATA]; + +//***************************************************************************** +// +// This function sets up SSI External Flash ID Read +// +//***************************************************************************** +uint32_t SSILibSendReadIDAdvMode(uint32_t ui32Base) +{ + uint32_t ui32Idx, ui32Receive; + uint32_t ui32MfgID; + uint32_t ui32DevID; + uint32_t ui32ReadID[]={0xaa,0xaa}; + uint32_t ui32ReadIDFlash; + + for(ui32Idx = 0; ui32Idx < sizeof(g_ui8InstrReadID) / sizeof(g_ui8InstrReadID[0]); ui32Idx++) + { + SSIDataPut(ui32Base, g_ui8InstrReadID[ui32Idx]); + } + + SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE); + SSIDataPut(ui32Base, 0x00); + SSIDataGet(ui32Base, &ui32Receive); + ui32ReadID[0] = ui32Receive; + SSIAdvDataPutFrameEnd(ui32Base,0x00); + SSIDataGet(ui32Base, &ui32Receive); + ui32ReadID[1] = ui32Receive; + ui32MfgID = ui32ReadID[0]; + ui32DevID = ui32ReadID[1]; + ui32ReadIDFlash = ui32MfgID; + + ui32ReadIDFlash = ui32ReadIDFlash << 8; + ui32ReadIDFlash |= ui32DevID; + + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + + return ui32ReadIDFlash; +} + +uint8_t SSILibSendReadStatusRegister(uint32_t ui32Base, uint8_t ui8FlashCommand) +{ + uint32_t ui32Status = 0; + uint8_t ui8FlashStatus; + + SSIAdvFrameHoldEnable(ui32Base); + SSIDataPut(ui32Base,ui8FlashCommand); + SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE); + SSIAdvDataPutFrameEnd(ui32Base,DUMMY_BYTE); + while(SSIBusy(ui32Base)); + SSIDataGet(ui32Base, &ui32Status); + ui8FlashStatus = (uint8_t)ui32Status; + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + + return ui8FlashStatus; +} + + +void SSILibDeviceBusyCheck(uint32_t ui32Base) +{ + uint8_t ui8TempData=0xFF; + + ui8TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + + while((ui8TempData & FLASH_BUSY_BIT) == FLASH_BUSY_BIT) + { + ui8TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + } +} + +void SSILibSendPageProgram(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand) +{ + uint32_t ui32TempAddr, ui32TempData; + uint8_t ui8AddrByte1, ui8AddrByte2, ui8AddrByte3; + + ui32TempAddr = ui32Address >> 16 ; + ui8AddrByte1 = (uint8_t)ui32TempAddr; + ui32TempAddr = ui32Address >> 8 ; + ui8AddrByte2 = (uint8_t)ui32TempAddr; + ui8AddrByte3 = (uint8_t)ui32Address; + + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(ui32Base); + SSIAdvDataPutFrameEnd(ui32Base,INS_WRITE_ENABLE); + while(SSIBusy(ui32Base)); + + ui32TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + while((ui32TempData & FLASH_WRITE_EN_LATCH_BIT) != FLASH_WRITE_EN_LATCH_BIT) { + ui32TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + } + + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(ui32Base); + SSIDataPut(ui32Base,ui8FlashCommand); + SSIDataPut(ui32Base,ui8AddrByte1); + SSIDataPut(ui32Base,ui8AddrByte2); + SSIDataPut(ui32Base,ui8AddrByte3); +} + +void SSILibSendReadDataAdvBi(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand) +{ + uint32_t ui32TempAddr; + uint8_t ui8AddrByte1, ui8AddrByte2, ui8AddrByte3; + + ui32TempAddr = ui32Address >> 16 ; + ui8AddrByte1 = (uint8_t)ui32TempAddr; + ui32TempAddr = ui32Address >> 8 ; + ui8AddrByte2 = (uint8_t)ui32TempAddr; + ui8AddrByte3 = (uint8_t)ui32Address; + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(ui32Base); + SSIDataPut(ui32Base,ui8FlashCommand); + SSIDataPut(ui32Base,ui8AddrByte1); + SSIDataPut(ui32Base,ui8AddrByte2); + SSIDataPut(ui32Base,ui8AddrByte3); + + SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE); +} + + +//***************************************************************************** +// +// This function sets up SSI External Flash Erase +// +//***************************************************************************** +void SSILibSendEraseCommand (uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand) +{ + uint32_t ui32TempAddr, ui32TempData; + uint8_t ui8AddrByte1, ui8AddrByte2, ui8AddrByte3; + + ui32TempAddr = ui32Address >> 16 ; + + ui8AddrByte1 = (uint8_t)ui32TempAddr; + ui32TempAddr = ui32Address >> 8 ; + ui8AddrByte2 = (uint8_t)ui32TempAddr; + ui8AddrByte3 = (uint8_t)ui32Address; + + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(ui32Base); + SSIAdvDataPutFrameEnd(ui32Base,INS_WRITE_ENABLE); + while(SSIBusy(ui32Base)); + + ui32TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + while((ui32TempData & FLASH_WRITE_EN_LATCH_BIT) != FLASH_WRITE_EN_LATCH_BIT) { + ui32TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + } + + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(ui32Base); + SSIDataPut(ui32Base,ui8FlashCommand); + SSIDataPut(ui32Base,ui8AddrByte1); + SSIDataPut(ui32Base,ui8AddrByte2); + SSIAdvDataPutFrameEnd(ui32Base,ui8AddrByte3); + while(SSIBusy(ui32Base)); + //wait till the erase is completed + SSILibDeviceBusyCheck(ui32Base); + +} + + +int Init_Ext_Flash() +{ + uint32_t pui32Dummy[1]; + uint32_t ui32SysClockFreq; + + // + // Set the clocking to run directly from the external crystal/oscillator. + // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the + // crystal on your board. + // + ui32SysClockFreq = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | + SYSCTL_OSC_MAIN | + SYSCTL_USE_PLL | + SYSCTL_CFG_VCO_480), 120000000); + + // Display the setup on the console. + writeLine("SSI3 To DK-TM4C129 FLASH TRANSFER"); + + // The SSI3 peripheral must be enabled for use. + SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3); + + // + // For this example SSI3 is used with PortA[5:2]. The actual port and pins + // used may be different on your part, consult the data sheet for more + // information. GPIO port A needs to be enabled so these pins can be used. + // TODO: change this to whichever GPIO port you are using. + // + SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); + SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); + SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); + + // + // GPIO Port F0 Pin is Locked. So Unlock and write the CR bit + // + HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY; + HWREG(GPIO_PORTF_BASE+GPIO_O_CR) |= GPIO_PIN_0; + + // + // Configure the pin muxing for SSI3 functions on port Q0, Q1, Q2, F0, + // F4, F5 + // + GPIOPinConfigure(GPIO_PQ0_SSI3CLK); + GPIOPinConfigure(GPIO_PQ1_SSI3FSS); + GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0); + GPIOPinConfigure(GPIO_PF0_SSI3XDAT1); + GPIOPinConfigure(GPIO_PF4_SSI3XDAT2); + GPIOPinConfigure(GPIO_PF5_SSI3XDAT3); + + // + // Configure the GPIO settings for the SSI pins. This function also gives + // control of these pins to the SSI hardware. Consult the data sheet to + // see which functions are allocated per pin. + // The pins are assigned as follows: + // PF5 - SSI3XDAT3 + // PF4 - SSI3XDAT2 + // PF0 - SSI3XDAT1 + // PQ2 - SSI3XDAT0 + // PQ1 - SSI3Fss + // PQ0 - SSI3CLK + // TODO: change this to select the port/pin you are using. + // + GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_2 | GPIO_PIN_1 | + GPIO_PIN_0); + GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_5 | GPIO_PIN_4 | + GPIO_PIN_0); + + // + // Configure and enable the SSI port for SPI master mode. Use SSI3, + // system clock supply, idle clock level low and active low clock in + // freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data. + // For SPI mode, you can set the polarity of the SSI clock when the SSI + // unit is idle. You can also configure what clock edge you want to + // capture data on. Please reference the datasheet for more information on + // the different SPI modes. + // + SSIConfigSetExpClk(SSI3_BASE, ui32SysClockFreq, SSI_FRF_MOTO_MODE_0, + SSI_MODE_MASTER, 1000000, 8); + + // + // Enable the SSI3 module. + // + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(SSI3_BASE); + SSIEnable(SSI3_BASE); + + // + // Read any residual data from the SSI port. This makes sure the receive + // FIFOs are empty, so we don't read any unwanted junk. This is done here + // because the SPI SSI mode is full-duplex, which allows you to send and + // receive at the same time. The SSIDataGetNonBlocking function returns + // "true" when data was returned, and "false" when no data was returned. + // The "non-blocking" function checks if there is any data in the receive + // FIFO and does not "hang" if there isn't. + // + while(SSIDataGetNonBlocking(SSI3_BASE, &pui32Dummy[0])) + { + } + + return 0; +} + +int Init_TxBuf(uint32_t NumOfWords, uint32_t* TxBuf) +{ + uint32_t ui32Index; + + for(ui32Index=0;ui32Index +#include +#include +#include +#include + +#include "inc/hw_memmap.h" + +#include "driverlib/rom.h" +#include "driverlib/gpio.h" +#include "driverlib/sysctl.h" + +#include +#include +#include "PMR/Hardware/HardwarePIDControl.pb-c.h" + +#define MAX_HEATERS_NUM HARDWARE_PID_CONTROL_TYPE__MixerHeater+1 + +typedef struct +{ + uint32_t m_port; + uint32_t m_pin; + bool Active; +} GPIOIntPortMap; + +static GPIOIntPortMap portMap[MAX_HEATERS_NUM] = +{ + {GPIO_PORTQ_BASE, GPIO_INT_PIN_7, false}, // HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w + {GPIO_PORTQ_BASE, GPIO_INT_PIN_4, false}, // HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1 + {GPIO_PORTQ_BASE, GPIO_INT_PIN_4, false}, // HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2 + {GPIO_PORTN_BASE, GPIO_INT_PIN_5, false}, // HARDWARE_PID_CONTROL_TYPE__HeadHeaterZ1 + {GPIO_PORTN_BASE, GPIO_INT_PIN_5, false}, // HARDWARE_PID_CONTROL_TYPE__HeadHeaterZ2 + {GPIO_PORTN_BASE, GPIO_INT_PIN_5, false}, // HARDWARE_PID_CONTROL_TYPE__HeadHeaterZ3 + {GPIO_PORTN_BASE, GPIO_INT_PIN_5, false}, // HARDWARE_PID_CONTROL_TYPE__HeadHeaterZ4 + {GPIO_PORTN_BASE, GPIO_INT_PIN_5, false}, // HARDWARE_PID_CONTROL_TYPE__MixerHeater +}; +uint32_t ActivateHeater (int HeaterId) +{ + assert(HeaterId < MAX_HEATERS_NUM); + ROM_GPIOPinWrite(portMap[HeaterId].m_port, portMap[HeaterId].m_pin, ROM_GPIOPinRead(portMap[HeaterId].m_port, GPIO_BYTE)|portMap[HeaterId].m_pin); //Turn the Heater ON + portMap[HeaterId].Active = true; + return OK; +} +uint32_t DeActivateHeater (int HeaterId) +{ + assert(HeaterId < MAX_HEATERS_NUM); + ROM_GPIOPinWrite(portMap[HeaterId].m_port, portMap[HeaterId].m_pin, ROM_GPIOPinRead(portMap[HeaterId].m_port, GPIO_BYTE)&~portMap[HeaterId].m_pin); //Turn the Heater OFF + portMap[HeaterId].Active = false; + return OK; +} +bool GetHeaterState (int HeaterId) +{ + assert(HeaterId < MAX_HEATERS_NUM); + return portMap[HeaterId].Active; +} + diff --git a/Software/Embedded_SW/Embedded/Drivers/Heater/Heater.h b/Software/Embedded_SW/Embedded/Drivers/Heater/Heater.h new file mode 100644 index 000000000..9292f10b7 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/Heater/Heater.h @@ -0,0 +1,7 @@ +#define HEATER_ON true +#define HEATER_OFF false + + +uint32_t ActivateHeater (int HeaterId); +uint32_t DeActivateHeater (int HeaterId); +bool GetHeaterState (int HeaterId); diff --git a/Software/Embedded_SW/Embedded/Drivers/I2C_Communication/I2C.c b/Software/Embedded_SW/Embedded/Drivers/I2C_Communication/I2C.c new file mode 100644 index 000000000..22a01f6aa --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/I2C_Communication/I2C.c @@ -0,0 +1,127 @@ + +#include "Drivers/I2C_Communication/I2C.h" +#include +#include +#include +#include +#include "include.h" +//#include "Common/Sys_Configuration/Configuration.h" + +#define CONFIG_REGISTER_ADDRESS 0x01 +#define LSB_BITMAP_CONFIGURATION_OF_CONFIG_REG 0x83 + +#define MSB_BITMAP_CONFIG_REG_SAMPELING_CHANEL_A0 0xc4 +#define MSB_BITMAP_CONFIG_REG_SAMPELING_CHANEL_A1 0xd4 +#define MSB_BITMAP_CONFIG_REG_SAMPELING_CHANEL_A2 0xe4 +#define MSB_BITMAP_CONFIG_REG_SAMPELING_CHANEL_A3 0xf4 + +#define START_DATA_DELAY 1500 +#define READ_DATA_DELAY 1000 +#define END_DATA_DELAY 100000 + +#define SLAVE_ADDRESS_1 0x48 +#define SLAVE_ADDRESS_2 0x4a +#define SLAVE_NUM_OF_CHAN 4 +#define I2C_FIRST_CHANNEL_ADDR 0xc3 +#define START_WRITING_TO_CONFIG_REG_IN_SLAVE 0x01 +#define START_READ_FROM_CONVERSION_REG_IN_SLAVE 0x00 //read sampled results + +void InitI2C(void) +{ + // + MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0); + // + // Stop the Clock, Reset and Enable I2C Module + // in Master Function + // + MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C0); + MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0); + MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0); + + // + // Wait for the Peripheral to be ready for programming + // + while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0)); + // + // Initialize the I2C master module. + // + I2CMasterInitExpClk (I2C0_BASE, SYS_CLK_FREQ, true); +} + +//each entry into the function reads result from one sampled channel in the USB +void SampleI2CData(uint32_t* resultData) +{ + uint8_t _resultData[2]; + static uint8_t _currSlaveAddress = SLAVE_ADDRESS_1; + static uint8_t _currChannel = 0; + uint8_t dataIndex = 0; + + // modulo calculation used to take specific channel from ADC each time - channel 0,1,2,3 + _currChannel = (_currChannel+1) & 0x3; + + //if finished reading first ADC channels , reset the channel index to next ADC + if ((_currSlaveAddress == SLAVE_ADDRESS_2) && (_currChannel == 3)) + { + _currChannel = 0; + } + + // reset slave addres to next ADC card + if (_currChannel == 0) + { + _currSlaveAddress = (_currSlaveAddress == SLAVE_ADDRESS_1) ? SLAVE_ADDRESS_2 : SLAVE_ADDRESS_1; + } + + //calculate index of where to write result data in the resultData array + dataIndex = (_currSlaveAddress == SLAVE_ADDRESS_2) ? SLAVE_NUM_OF_CHAN + _currChannel : _currChannel; + // Send slave address and config reg address + I2CMasterSlaveAddrSet (I2C0_BASE, _currSlaveAddress, false); + I2CMasterDataPut(I2C0_BASE, START_WRITING_TO_CONFIG_REG_IN_SLAVE); + I2CMasterControl(I2C0_BASE,I2C_MASTER_CMD_BURST_SEND_START); + SysCtlDelay(1500); +// while (!(I2CMasterBusy(I2C0_BASE))); //Wait till end of transaction +// while (I2CMasterBusy(I2C0_BASE)); //Wait till end of transaction + + //Send MSB of config reg to current slave + uint32_t chanAddr = I2C_FIRST_CHANNEL_ADDR + 0x10*_currChannel; + I2CMasterDataPut(I2C0_BASE, chanAddr); + I2CMasterControl(I2C0_BASE,I2C_MASTER_CMD_BURST_SEND_CONT); + SysCtlDelay(15000); +// while (!(I2CMasterBusy(I2C0_BASE))); //Wait till end of transaction +// while (I2CMasterBusy(I2C0_BASE)); //Wait till end of transaction + + //Send LSB of config reg to current slave + I2CMasterDataPut(I2C0_BASE, 0xe3); + I2CMasterControl(I2C0_BASE,I2C_MASTER_CMD_BURST_SEND_FINISH); + SysCtlDelay(15000); +// while (!(I2CMasterBusy(I2C0_BASE))); //Wait till end of transaction +// while (I2CMasterBusy(I2C0_BASE)); //Wait till end of transaction + + // Send slave address and conversion reg address (reg for reading results) + I2CMasterSlaveAddrSet (I2C0_BASE, _currSlaveAddress, false); + I2CMasterDataPut(I2C0_BASE, START_READ_FROM_CONVERSION_REG_IN_SLAVE); + I2CMasterControl(I2C0_BASE,I2C_MASTER_CMD_SINGLE_SEND); + SysCtlDelay(15000); + // while (!(I2CMasterBusy(I2C0_BASE))); //Wait till end of transaction + //while (I2CMasterBusy(I2C0_BASE)); //Wait till end of transaction + + // Start Read from configured slave + I2CMasterSlaveAddrSet(I2C0_BASE, _currSlaveAddress, true); + I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); + SysCtlDelay(15000); +// while (!(I2CMasterBusy(I2C0_BASE))); //Wait till end of transaction +// while (I2CMasterBusy(I2C0_BASE)); //Wait till end of transaction + //each read result is represented in 16 bit this why we read twise + //each time in 8 bits + //read MSB byte + _resultData[0] = I2CMasterDataGet(I2C0_BASE); + + I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); + SysCtlDelay(15000); +// while (!(I2CMasterBusy(I2C0_BASE))); //Wait till end of transaction +// while (I2CMasterBusy(I2C0_BASE)); //Wait till end of transaction + //read LSB byte + _resultData[1] = I2CMasterDataGet(I2C0_BASE); + + //concutenate 2 reads of 8 bytes into one read of 16 bytes + resultData[dataIndex] = _resultData[0] << 8 | _resultData[1]; +} diff --git a/Software/Embedded_SW/Embedded/Drivers/I2C_Communication/I2C.h b/Software/Embedded_SW/Embedded/Drivers/I2C_Communication/I2C.h new file mode 100644 index 000000000..c072ed156 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/I2C_Communication/I2C.h @@ -0,0 +1,31 @@ + +#ifndef DRIVERS_I2C_H_ +#define DRIVERS_I2C_H_ + + +#include +#include + +#define I2C_NUM_OF_CHANNELS 7 // 6 dispensers and feeder +//front panel date saved in the same array of sampeled ADC data g_pui32ADCSeq[] + +#define I2C_START_INDEX 14 +#define I2C_ADC_DISP_1_POT 20 +#define I2C_ADC_DISP_2_POT 19 +#define I2C_ADC_DISP_3_POT 14 +#define I2C_ADC_DISP_4_POT 17 +#define I2C_ADC_DISP_5_POT 16 +#define I2C_ADC_DISP_6_POT 15 +#define I2C_ADC_FEEDER_POT 18 + + +/********************************************************************************************* + * this function is responsible for recieving a to d data of the potentiometers that connected + * to front panel and arrives in I2C communication protocol. + * input parameters - slave addres of I2C device + * buffer to write the result into + * index inside the beffer from where to atart writing + *********************************************************************************************/ +void SampleI2CData(uint32_t* _resultData); +void InitI2C(void); +#endif /* DRIVERS_I2C_H_ */ diff --git a/Software/Embedded_SW/Embedded/Drivers/On_Chip_Flash/Flashstore.c b/Software/Embedded_SW/Embedded/Drivers/On_Chip_Flash/Flashstore.c new file mode 100644 index 000000000..0849538bf --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/On_Chip_Flash/Flashstore.c @@ -0,0 +1,655 @@ +//***************************************************************************** +// +// Flashstore.c - Data logger module handles storage in flash. +// this module is responsible for all memory interfacess in the system +// each storage type can be defined here and to be accessed from this interface. +// This module manages the storage of data logger of sampeled data and configuration into flash memory. +//***************************************************************************** + +#include +#include +#include +#include +#include +#include +#include "Drivers/On_Chip_Flash/Flashstore.h" + +//***************************************************************************** +// +// This module manages the storage of data logger of sampeled data and configuration into flash memory. +// +//***************************************************************************** + +//***************************************************************************** +// +// Define the beginning and end of the flash storage area. You must make sure +// that this area is well clear of any space occupied by the application +// binary, and that this space is not used for any other purpose. +// The start and end addresses must be 1K aligned. The end address is +// exclusive - it is 1 value greater than the last valid location used for +// storage. +// +//***************************************************************************** +typedef struct +{ + uint32_t m_startAddress; + uint32_t m_endAddress; +} DataSection_t; + +static DataSection_t g_ui32Addresses[NumOfDataTypes] = {{FLASH_STORE_START_ADDR,FLASH_STORE_END_ADDR}, + {FLASH_CONFIG_START_ADDR,FLASH_CONFIG_END_ADDR}}; + +//***************************************************************************** +// This array holds pointer per memory section/type config each pointer represents +// The next address in flash, that will be used for storing a data record. +// +//***************************************************************************** +static uint32_t g_ui32StoreAddr[NumOfDataTypes]; + +//***************************************************************************** +// +// A buffer used to assemble a complete record of data prior to storing it +// in the flash. +// +//***************************************************************************** +static uint32_t g_pui32RecordBuf[32]; + +//***************************************************************************** +// +// Check for non cyclic section owerflow +// +//***************************************************************************** +inline FlashStoreCheckCyclic(FlashDataType_t _dataType,uint32_t _currAddress) +{ + if ((_dataType == ConfigData) && (_currAddress > g_ui32Addresses[_dataType].m_endAddress)) + { + //JigStopAllWithError("Internal: flash address owerflow"); + } +} + +//***************************************************************************** +// +// Initializes the flash storage. This is a stub because there is nothing +// special to do. +// +//***************************************************************************** +void FlashStoreInit(void) +{ +} + +void FlashSendEndReq(FlashDataType_t _dataType) +{ +/* if (_dataType == ADCData) + { + // Write last record + ((tLogRecord *)g_pui32RecordBuf)->m_itemMask = 0; + WriteLogRecord((tLogRecord *)g_pui32RecordBuf); + }*/ +} +//***************************************************************************** +// +// Saves data records that are stored in the flash to an externally connected +// USB memory storage device (USB stick). +// The flash memory is scanned for the presence of store data records. When +// records are found they are written in CSV format to the USB stick. This +// function assumes a non-corrupted storage area, and that any records, once +// found, are contiguous with all stored records. It will find the oldest +// record and start with that when storing. +// +//***************************************************************************** +int32_t FlashStoreSave(FlashDataType_t _dataType) +{ +/* uint32_t ui32Addr, ui32OldestRecord, ui32OldestIndex, ui32Count, ui32PartialCount; + tLogRecord *p_sRecord; + + // + // Initialize locals. + // + ui32OldestRecord = g_ui32Addresses[_dataType].m_startAddress; + ui32OldestIndex = FORMATED_FLASH_SIGNATURE; + + // + // Show a message to the user. + // + //SetStatusText("SAVE\r\n", "SCANNING ", "FLASH\r\n", 0); + + // + // Start at beginning of flash storage area + // + ui32Addr = g_ui32Addresses[_dataType].m_startAddress; + + // + // Search all of flash area checking every stored record. + // + while(ui32Addr < g_ui32Addresses[_dataType].m_endAddress) + { + // + // If a record signature is found, check for oldest record, then + // increment to the next record + // + if((HWREG(ui32Addr) & CRC_SEED_MASK) == MAGIC_NUMBER_OF_FREE_REC_BEG) + { + // + // Get a pointer to the data record (account for flash header word) + // + p_sRecord = (tLogRecord *)(ui32Addr + RECORD_HEADER_SIZE); + + // + // If the seconds in this record are older than any found so far + // then save the seconds value, and the address of this record + // + if(p_sRecord->m_recIndex < ui32OldestIndex) + { + ui32OldestIndex = p_sRecord->m_recIndex; + ui32OldestRecord = ui32Addr; + } + + // + // Advance the address to the next record. + // jump to the begining of the next free page + ui32Addr += HWREG(ui32Addr) & RECORD_LENGTH_MASK; + } + else + { + // + // A record was not found so just advance to the next location in + // flash + // + ui32Addr += RECORD_HEADER_SIZE; + } + } + + // + // If no "oldest" records was found, then there is no valid data stored + // + if(ui32OldestIndex == FORMATED_FLASH_SIGNATURE) + { + FlashSendEndReq(_dataType); + //SetStatusText("SAVE\r\n", "NO RECORDS ", "FOUND\r\n", 0); + return(1); + } + + // + // Open the output file on the USB stick. It will return NULL if there + // was any problem. + // TODO open external flash +// if(!USBStickOpenLogFile(0)) +// { +// SetStatusText("SAVE", 0, "USB ERROR", "PRESS <"); +// return(1); +// } + + // + // Notify user we are saving data to USB + // + //SetStatusText("SAVE\r\n", "SAVING ", "TO USB\r\n", 0); + + // + // Start reading records from flash, start at the address of the oldest + // record, as found above. We scan through records, assuming the flash + // store is not corrupted. Continue scanning until a blank space is + // found which should indicate the end of recorded data, or until we + // have read all the records. + // + ui32Addr = ui32OldestRecord; + while(HWREG(ui32Addr) != FORMATED_FLASH_SIGNATURE) + { + // + // If a record signature is found (which it should be), extract the + // record data and send it to USB stick. + // + if((HWREG(ui32Addr) & CRC_SEED_MASK) == MAGIC_NUMBER_OF_FREE_REC_BEG) + { + // + // Get byte count for this record + // + ui32Count = HWREG(ui32Addr) & RECORD_LENGTH_MASK; + + // + // Adjust the count and the address to remove the flash header + // + ui32Count -= RECORD_HEADER_SIZE; + ui32Addr += RECORD_HEADER_SIZE; + + // + // Adjust for memory wrap + // + if(ui32Addr >= g_ui32Addresses[_dataType].m_endAddress) + { + FlashStoreCheckCyclic(_dataType,ui32Addr); + ui32Addr = g_ui32Addresses[_dataType].m_startAddress; + } + + // + // If the contents of this record go past the end of the memory + // storage area, then perform a partial copy first. + // + ui32PartialCount = 0; + + if((ui32Addr + ui32Count) >= g_ui32Addresses[_dataType].m_endAddress) + { + FlashStoreCheckCyclic(_dataType,ui32Addr + ui32Count); + // + // Find how many bytes are left on this page + // + ui32PartialCount = g_ui32Addresses[_dataType].m_endAddress - ui32Addr; + + // + // Copy the portion until the end of memory store, adjust + // remaining count and address + // + memcpy(g_pui32RecordBuf, (void *)ui32Addr, ui32PartialCount); + ui32Count -= ui32PartialCount; + ui32Addr = g_ui32Addresses[_dataType].m_startAddress; + } + + // + // Copy entire record (or remaining part of record if memory wrap) + // into record buffer + // + memcpy(&g_pui32RecordBuf[ui32PartialCount / 4], (void *)ui32Addr,ui32Count); + + // + // Update address pointer to next record + // + ui32Addr += ui32Count; + + // + // Now we have an entire data logger record copied from flash + // storage into a local (contiguous) memory buffer. Pass it + // to the USB file writing function to write the record to the + // USB stick. + // + switch(_dataType) + { + case ConfigData: + { + //ConfigurationReadData((tLogRecord *)g_pui32RecordBuf); TODO fix + break; + } + case ADCData: + { + //WriteLogRecord((tLogRecord *)g_pui32RecordBuf); TODO fix + break; + } + } + } + else + { + // + // This should not happen, but it means we ended up in a non-blank + // location that is not the start of a record. In this case just + // advance through memory until either a blank location or another + // record is found. + // + // Increment to next word in flash, adjust for memory wrap. + // + ui32Addr += RECORD_HEADER_SIZE; + if(ui32Addr >= g_ui32Addresses[_dataType].m_endAddress) + { + FlashStoreCheckCyclic(_dataType,ui32Addr); + ui32Addr = g_ui32Addresses[_dataType].m_startAddress; + } + } + } + + // + // Close the USB stick file so that any buffers will be flushed. + // + // TODO close extrnal flash USBStickCloseFile(); + + // + // Inform user that save is complete. + // + //SetStatusText("SAVE\r\n", "USB SAVE ", "COMPLETE\r\n", 0); + if (_dataType == ADCData) + { + FlashSendEndReq(_dataType); + } + // + // Return success + // + * + */ + return(0); +} + +//***************************************************************************** +// function used to write into internal flash specific buffer +//***************************************************************************** +int32_t FlashStoreWriteBuffer(FlashDataType_t _dataType,uint32_t* _pui32Record,uint32_t _ui32ItemCount) +{ + // + // Check the arguments + // + if(!_pui32Record) + { + //JigStopAllWithError("Internal: empty flash record"); + return(1); + } + + // + // Check to see if the record is going to cross a page boundary. + // + if(((g_ui32StoreAddr[_dataType] & FLASH_PAGE_BOUNDARY_MASK) + _ui32ItemCount) > FLASH_PAGE_BOUNDARY_MASK) + { + // + // Find number of bytes remaining on this page + // + uint32_t ui32Idx = FLASH_PAGE_SIZE_IN_BYTES - (g_ui32StoreAddr[_dataType] & FLASH_PAGE_BOUNDARY_MASK); + + // + // Program part of the record on the space remaining on the current + // page + // + FlashProgram(_pui32Record, g_ui32StoreAddr[_dataType], ui32Idx); + + // + // Increment the store address by the amount just written, which + // should make the new store address be at the beginning of the next + // flash page. + // + g_ui32StoreAddr[_dataType] += ui32Idx; + + // + // Adjust the remaining bytes to program, and the pointer to the + // remainder of the record data. + // + _ui32ItemCount -= ui32Idx; + _pui32Record = &_pui32Record[ui32Idx / NUMBER_OF_BYTES_IN_INT]; + + // + // Check to see if the new page is past the end of store and adjust + // + if(g_ui32StoreAddr[_dataType] >= g_ui32Addresses[_dataType].m_endAddress) + { + FlashStoreCheckCyclic(_dataType,g_ui32StoreAddr[_dataType]); + g_ui32StoreAddr[_dataType] = g_ui32Addresses[_dataType].m_startAddress; + } + + // + // If new page is not blank, then erase it + // + if(HWREG(g_ui32StoreAddr[_dataType]) != FORMATED_FLASH_SIGNATURE) + { + FlashErase(g_ui32StoreAddr[_dataType]); + } + } + + // + // Now program the remaining part of the record (if we crossed a page + // boundary above) or the full record to the current location in flash + // + FlashProgram(_pui32Record, g_ui32StoreAddr[_dataType], _ui32ItemCount); + + // + // Increment the storage address to the next location. + // + g_ui32StoreAddr[_dataType] += _ui32ItemCount; + + // + // Return success indication to caller. + // + return(0); +} + +//***************************************************************************** +// +// This is called at the start of logging to prepare space in flash for +// storage of logged data. It searches for the first blank area in the +// flash storage to be used for storing records. +// +// If a starting address is specified then the search is skipped and it goes +// directly to the new address. If the starting address is 0, then it performs +// the search. +// +//***************************************************************************** +int32_t FlashStoreOpenLogFile(FlashDataType_t _dataType,uint32_t _ui32StartAddr) +{ + uint32_t ui32Addr; + + // + // If a valid starting address is specified, then just use that and skip + // the search below. + // + if((_ui32StartAddr >= g_ui32Addresses[_dataType].m_startAddress) && + (_ui32StartAddr < g_ui32Addresses[_dataType].m_endAddress)) + { + g_ui32StoreAddr[_dataType] = _ui32StartAddr; + return(0); + } + + // + // Start at beginning of flash storage area + // + ui32Addr = g_ui32Addresses[_dataType].m_startAddress; + + // + // Search until a blank is found or the end of flash storage area + // + while((HWREG(ui32Addr) != FORMATED_FLASH_SIGNATURE) && (ui32Addr < g_ui32Addresses[_dataType].m_endAddress)) + { + // + // If a record signature is found, then increment to the next record + // + if((HWREG(ui32Addr) & CRC_SEED_MASK) == MAGIC_NUMBER_OF_FREE_REC_BEG) + { + ui32Addr += HWREG(ui32Addr) & RECORD_LENGTH_MASK; + } + else + { + // + // Just advance to the next location in flash + // + ui32Addr += RECORD_HEADER_SIZE; + } + } + + // + // If we are at the end of flash that means no blank area was found. + // So reset to the beginning and erase the first page. + // + if(ui32Addr >= g_ui32Addresses[_dataType].m_endAddress) + { + ui32Addr = g_ui32Addresses[_dataType].m_startAddress; + FlashErase(ui32Addr); + } + + // + // When we reach here we either found a blank location, or made a new + // blank location by erasing the first page. + // To keep things simple we are making an assumption that the flash store + // is not corrupted and that the first blank location implies the start + // of a blank area suitable for storing data records. + // + g_ui32StoreAddr[_dataType] = ui32Addr; + + // + // Return success indication to caller + // + return(0); +} + +//***************************************************************************** +// +// This is called each time there is a new data record to log to the flash +// storage area. A simple algorithm is used which rotates programming +// data log records through an area of flash. It is assumed that the current +// page is blank. Records are stored on the current page until a page +// boundary is crossed. If the page boundary is crossed and the new page +// is not blank (testing only the first location), then the new page is +// erased. Finally the entire record is programmed into flash and the +// storage pointers are updated. +// +// While storing and when crossing to a new page, if the flash page is not +// blank it is erased. So this algorithm overwrites old data. +// +// The data is stored in flash as a record, with a flash header prepended, +// and with the record length padded to be a multiple of 4 bytes. The flash +// header is a 3-byte magic number and one byte of record length. +// +//***************************************************************************** + /*int32_t FlashStoreWriteRecord(FlashDataType_t _dataType,tLogRecord *_psRecord) +{ + + uint32_t ui32Idx, _ui32ItemCount, *_pui32Record; + + // + // Check the arguments + // + if(!_psRecord) + { + JigStopAllWithError("Internal: invalid flash record"); + return(1); + } + + // + // Determine how many channels are to be logged + // + ui32Idx = _psRecord->m_itemMask; + _ui32ItemCount = 0; + while(ui32Idx) + { + if(ui32Idx & 1) + { + _ui32ItemCount++; + } + ui32Idx >>= 1; + } + + // + // Add 16-bit count equivalent of record header, time stamp, and + // selected items mask. This is the total number of 16 bit words + // of the record. + // + _ui32ItemCount += 6; + + // + // Convert the count to bytes, be sure to pad to 32-bit alignment. + // + _ui32ItemCount = ((_ui32ItemCount * 2) + 3) & ~3; + + // + // Create the flash record header, which is a 3-byte signature and a + // one byte count of bytes in the record. Save it at the beginning + // of the write buffer. + // + ui32Idx = MAGIC_NUMBER_OF_FREE_REC_BEG | (_ui32ItemCount & RECORD_LENGTH_MASK); + g_pui32RecordBuf[0] = ui32Idx; + + // + // Copy the rest of the record to the buffer, and get a pointer to + // the buffer. + // + memcpy(&g_pui32RecordBuf[1], _psRecord, _ui32ItemCount - NUMBER_OF_BYTES_IN_INT); + _pui32Record = g_pui32RecordBuf; + int32_t result_of_flash_writing = FlashStoreWriteBuffer(_dataType,_pui32Record,_ui32ItemCount); + return result_of_flash_writing; + return 0; + } + */ + +//***************************************************************************** +// +// Erase the data storage area of flash. +// +//***************************************************************************** +void FlashStoreErase(FlashDataType_t _dataType) +{ + uint32_t ui32Addr; + + // + // Inform user we are erasing + // + // SetStatusText("ERASE\r\n", 0, "ERASING\r\n", 0); + + // + // Loop through entire storage area and erase each page. + // + for(ui32Addr = g_ui32Addresses[_dataType].m_startAddress; ui32Addr < g_ui32Addresses[_dataType].m_endAddress; ui32Addr += FLASH_PAGE_SIZE_IN_BYTES) + { + FlashErase(ui32Addr); + } + + // + // Inform user the erase is done. + // + // SetStatusText("SAVE\r\n", "ERASE ", "COMPLETE\r\n", 0); +} + +//***************************************************************************** +// +// Determine if the flash block that contains the address is blank. +// +//***************************************************************************** +static int32_t IsBlockFree(uint32_t _ui32BaseAddr) +{ + uint32_t ui32Addr; + + // + // Make sure we start at the beginning of a 1K block + // + _ui32BaseAddr &= ~FLASH_PAGE_BOUNDARY_MASK; + + // + // Loop through every address in this block and test if it is blank. + // + for(ui32Addr = 0; ui32Addr < FLASH_PAGE_SIZE_IN_BYTES; ui32Addr += RECORD_HEADER_SIZE) + { + if(HWREG(_ui32BaseAddr + ui32Addr) != FORMATED_FLASH_SIGNATURE) + { + // + // Found a non-blank location, so return indication that block + // is not free. + // + return(0); + } + } + + // + // If we made it to here then every location in this block is erased, + // so return indication that the block is free. + // + return(1); +} + +//***************************************************************************** +// +// Report to the user the amount of free space and used space in the data +// storage area. +// +//***************************************************************************** +void FlashStoreReport(FlashDataType_t _dataType) +{ + uint32_t ui32Addr, ui32FreeBlocks, ui32UsedBlocks = 0; + static char p_cBufFree[16], p_cBufUsed[16]; + + // + // Initialize locals. + // + ui32FreeBlocks = 0; + ui32UsedBlocks = 0; + + // + // Loop through each block of the storage area and count how many blocks + // are free and non-free. + // + for(ui32Addr = g_ui32Addresses[_dataType].m_startAddress; ui32Addr < g_ui32Addresses[_dataType].m_endAddress; ui32Addr += FLASH_PAGE_SIZE_IN_BYTES) + { + if(IsBlockFree(ui32Addr)) + { + ui32FreeBlocks++; + } + else + { + ui32UsedBlocks++; + } + } + + // + // Report the result to the user via a status display screen. + // + usnprintf(p_cBufFree, sizeof(p_cBufFree), "FREE: %3uK", ui32FreeBlocks); + usnprintf(p_cBufUsed, sizeof(p_cBufUsed), "USED: %3uK", ui32UsedBlocks); + //SetStatusText("FREE FLASH\r\n", p_cBufFree, p_cBufUsed, "\r\n"); +} diff --git a/Software/Embedded_SW/Embedded/Drivers/On_Chip_Flash/Flashstore.h b/Software/Embedded_SW/Embedded/Drivers/On_Chip_Flash/Flashstore.h new file mode 100644 index 000000000..31018b9cf --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/On_Chip_Flash/Flashstore.h @@ -0,0 +1,136 @@ +//***************************************************************************** +// +// Flashstore.h - Prototypes and definitions for flash storage module. +// this module is responsible for all memory interfacess in the system +// each storage type can be defined here and to be accessed from this interface. +// This module manages the storage of data logger of sampeled data and configuration +// into on chip flash memory. +//***************************************************************************** + +#ifndef DRIVERS_FLASHSTORE_H_ +#define DRIVERS_FLASHSTORE_H_ + + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + + +//memory sections currently defined for storage on internal flash +#define FLASH_STORE_START_ADDR 0x20000 +#define FLASH_STORE_END_ADDR 0x40000 + +#define FLASH_CONFIG_START_ADDR 0x40000 +#define FLASH_CONFIG_END_ADDR 0x50000 + +#define MAGIC_NUMBER_OF_FREE_REC_BEG 0x53554100 +#define CRC_SEED_MASK 0xFFFFFF00 //used as crc seed and masking number for searching in flash records +#define RECORD_LENGTH_MASK 0xFF +#define FLASH_PAGE_BOUNDARY_MASK 0x3FF //beyond this mask begins new paging each page is of 1k - 0x3ff is the last addres +#define FLASH_PAGE_SIZE_IN_BYTES 0x400 +#define NUMBER_OF_BYTES_IN_INT 4 + +#define RECORD_HEADER_SIZE 4 +#define FORMATED_FLASH_SIGNATURE 0xFFFFFFFF + +typedef enum +{ + ADCData = 0, + ConfigData, + NumOfDataTypes +} FlashDataType_t; + +//***************************************************************************** +// +// Module function prototypes. +// +//***************************************************************************** +void FlashStoreInit(void); + +//***************************************************************************** +// +// This is called at the start of logging to prepare space in flash for +// storage of logged data. It searches for the first blank area in the +// flash storage to be used for storing records. +// +// If a starting address is specified then the search is skipped and it goes +// directly to the new address. If the starting address is 0, then it performs +// the search. +// +//***************************************************************************** +int32_t FlashStoreOpenLogFile(FlashDataType_t _dataType,uint32_t _ui32StartAddr); + +//***************************************************************************** +// function used to write into internal flash specific buffer +//***************************************************************************** +int32_t FlashStoreWriteBuffer(FlashDataType_t _dataType,uint32_t* _pui32Record,uint32_t _ui32ItemCount); + +//***************************************************************************** +// +// This is called each time there is a new data record to log to the flash +// storage area. A simple algorithm is used which rotates programming +// data log records through an area of flash. It is assumed that the current +// page is blank. Records are stored on the current page until a page +// boundary is crossed. If the page boundary is crossed and the new page +// is not blank (testing only the first location), then the new page is +// erased. Finally the entire record is programmed into flash and the +// storage pointers are updated. +// +// While storing and when crossing to a new page, if the flash page is not +// blank it is erased. So this algorithm overwrites old data. +// +// The data is stored in flash as a record, with a flash header prepended, +// and with the record length padded to be a multiple of 4 bytes. The flash +// header is a 3-byte magic number and one byte of record length. +// +//***************************************************************************** +//int32_t FlashStoreWriteRecord(FlashDataType_t _dataType,tLogRecord *_psRecord); + +//***************************************************************************** +// +// Saves data records that are stored in the flash to an externally connected +// USB memory storage device (USB stick). +// The flash memory is scanned for the presence of store data records. When +// records are found they are written in CSV format to the USB stick. This +// function assumes a non-corrupted storage area, and that any records, once +// found, are contiguous with all stored records. It will find the oldest +// record and start with that when storing. +// +//***************************************************************************** +int32_t FlashStoreSave(FlashDataType_t _dataType); + +//***************************************************************************** +// +// Erase the data storage area of flash. +// +//***************************************************************************** +void FlashStoreErase(FlashDataType_t _dataType); + + +void FlashStoreReport(FlashDataType_t _dataType); + +void FlashSendEndReq(FlashDataType_t _dataType); +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + + + + + + + + +#endif /* DRIVERS_FLASHSTORE_H_ */ diff --git a/Software/Embedded_SW/Embedded/Drivers/Peripheral_GPIO/GPIO.c b/Software/Embedded_SW/Embedded/Drivers/Peripheral_GPIO/GPIO.c new file mode 100644 index 000000000..158dd2e14 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/Peripheral_GPIO/GPIO.c @@ -0,0 +1,130 @@ + +#include +#include +#include +#include +#include "Drivers/Peripheral_GPIO/GPIO.h" + +//#define MAX_NUM_OF_REGISTRED_CALLBACKS 9 // screw,6 dispensers , 2 sw - start manual/stop manual +#define MAX_NUM_OF_REGISTRED_CALLBACKS 7 // screw,6 dispensers , 2 sw - start manual/stop manual + +typedef struct +{ + uint32_t m_port; + uint32_t m_pin; +} GPIOIntPortMap; + +static GPIOIntPortMap portMap[NUM_OF_GPIO_INT] = +{ + {GPIO_PORTG_BASE, GPIO_INT_PIN_0}, // Dispenser LSW 1 + {GPIO_PORTG_BASE, GPIO_INT_PIN_1}, // Dispenser LSW 2 + {GPIO_PORTP_BASE, GPIO_INT_PIN_4}, // Dispenser LSW 3 + {GPIO_PORTP_BASE, GPIO_INT_PIN_5}, // Dispenser LSW 4 + {GPIO_PORTQ_BASE, GPIO_INT_PIN_7}, // Dispenser LSW 5 + {GPIO_PORTS_BASE, GPIO_INT_PIN_0}, // Dispenser LSW 6 + {GPIO_PORTS_BASE, GPIO_INT_PIN_3}, // Screw LSW + {GPIO_PORTD_BASE, GPIO_INT_PIN_1}, // Start Manual Btn + {GPIO_PORTJ_BASE, GPIO_INT_PIN_3}, // End Manual Btn + {GPIO_PORTE_BASE, GPIO_INT_PIN_4}, // + {GPIO_PORTH_BASE, GPIO_INT_PIN_5}, // + {GPIO_PORTP_BASE, GPIO_INT_PIN_0}, // + {GPIO_PORTQ_BASE, GPIO_INT_PIN_5}, // +}; + +typedef struct +{ + bool m_isEnabled; + GPIOInt_t m_param; + GPIOIntCallback m_callback; +}PortConfig_t; + +static PortConfig_t gpio_configuration[MAX_NUM_OF_REGISTRED_CALLBACKS]; + +bool PollGPIO (uint8_t index) +{ + unsigned long ulStatus = ROM_GPIOPinRead(portMap[index].m_port, portMap[index].m_pin); + if ( ulStatus) + { + return true; + } + return false; +} +//******************************************************************************************************************** +//genneral interrupt handler for all GPIO's +//******************************************************************************************************************** +void IntGPIO(UArg arg0) +{ + uint32_t port = (uint32_t)arg0; + unsigned long ulStatus = ROM_GPIOIntStatus(port, true); + + + uint8_t index; + for (index = 0; index < MAX_NUM_OF_REGISTRED_CALLBACKS; ++index) + { + GPIOInt_t gpioInt = gpio_configuration[index].m_param; + if (gpio_configuration[index].m_isEnabled && (portMap[gpioInt].m_port == port) && (portMap[gpioInt].m_pin & ulStatus)) + { + gpio_configuration[index].m_callback(gpio_configuration[index].m_param); + } + } + // + // Clear all the pin interrupts that are set + // + ROM_GPIOIntClear(port, ulStatus); +} + +//******************************************************************************************************************** +void GPIOInit(void) +{ + uint8_t index; + for (index = 0; index < MAX_NUM_OF_REGISTRED_CALLBACKS; ++index) + { + gpio_configuration[index].m_isEnabled = false; + } +} + +//******************************************************************************************************************** +void GPIOEnableInterrupt(GPIOInt_t gpioInt, GPIOIntCallback callBack, uint32_t type) +{ + uint8_t index; + for (index = 0; index < MAX_NUM_OF_REGISTRED_CALLBACKS; ++index) + { + if (!gpio_configuration[index].m_isEnabled) + { + gpio_configuration[index].m_isEnabled = true; + gpio_configuration[index].m_param = gpioInt; + gpio_configuration[index].m_callback = callBack; + ROM_GPIOIntTypeSet(portMap[gpioInt].m_port,portMap[gpioInt].m_pin, type); + ROM_GPIOIntClear(portMap[gpioInt].m_port,portMap[gpioInt].m_pin); + ROM_GPIOIntEnable(portMap[gpioInt].m_port,portMap[gpioInt].m_pin); + return; + } + else + { + if ((gpio_configuration[index].m_param == gpioInt) && + (gpio_configuration[index].m_callback == callBack)) + { + return; + } + } + } +} + +//******************************************************************************************************************** + +void GPIODisableInterrupt(GPIOInt_t gpioInt,GPIOIntCallback callBack) +{ + uint8_t index; + for (index = 0; index < MAX_NUM_OF_REGISTRED_CALLBACKS; ++index) + { + if (gpio_configuration[index].m_isEnabled && + (gpio_configuration[index].m_param == gpioInt) && + (gpio_configuration[index].m_callback == callBack)) + { + ROM_GPIOIntDisable(portMap[gpioInt].m_port,portMap[gpioInt].m_pin); + ROM_GPIOIntClear(portMap[gpioInt].m_port,portMap[gpioInt].m_pin); + gpio_configuration[index].m_isEnabled = false; + return; + } + } +} diff --git a/Software/Embedded_SW/Embedded/Drivers/Peripheral_GPIO/GPIO.h b/Software/Embedded_SW/Embedded/Drivers/Peripheral_GPIO/GPIO.h new file mode 100644 index 000000000..8a0c54df4 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/Peripheral_GPIO/GPIO.h @@ -0,0 +1,37 @@ + +#ifndef DRIVERS_GPIO_H_ +#define DRIVERS_GPIO_H_ + +#include +#include +#include + +typedef enum +{ + DISPENSER_1_LMS, + DISPENSER_2_LMS, + DISPENSER_3_LMS, + DISPENSER_4_LMS, + DISPENSER_5_LMS, + DISPENSER_6_LMS, + SCREW_LMS, + START_MANUAL_BTN, + END_MANUAL_BTN, + MANUAL_1_BTN, + MANUAL_2_BTN, + MANUAL_3_BTN, + MANUAL_4_BTN, + NUM_OF_GPIO_INT +}GPIOInt_t; + +typedef void (*GPIOIntCallback)(GPIOInt_t arg); + +void GPIOInit(void); + +bool PollGPIO (uint8_t index); + +void GPIOEnableInterrupt(GPIOInt_t gpioInt, GPIOIntCallback callBack, uint32_t type); + +void GPIODisableInterrupt(GPIOInt_t gpioInt,GPIOIntCallback callBack); + +#endif /* DRIVERS_GPIO_H_ */ diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.ccsproject b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.ccsproject new file mode 100644 index 000000000..d132942b2 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.ccsproject @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.cproject b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.cproject new file mode 100644 index 000000000..670f72289 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.cproject @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.project b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.project new file mode 100644 index 000000000..8736c1f5b --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.project @@ -0,0 +1,45 @@ + + + twine_graphicslib + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + com.ti.ccstudio.core.ccsNature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + drivers/frame.c + 1 + SW_ROOT/examples/boards/dk-tm4c129x/drivers/frame.c + + + drivers/kentec320x240x16_ssd2119.c + 1 + SW_ROOT/examples/boards/dk-tm4c129x/drivers/kentec320x240x16_ssd2119.c + + + + + SW_ROOT + $%7BTI_PRODUCTS_DIR%7D/TivaWare_C_Series-2.1.4.178 + + + diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.cdt.codan.core.prefs b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 000000000..f653028c5 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +inEditor=false +onBuild=false diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.cdt.debug.core.prefs b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.cdt.debug.core.prefs new file mode 100644 index 000000000..2adc7b1dd --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.cdt.debug.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.debug.core.toggleBreakpointModel=com.ti.ccstudio.debug.CCSBreakpointMarker diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.core.resources.prefs b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..3774f8b3e --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +encoding//Debug/drivers/subdir_rules.mk=UTF-8 +encoding//Debug/drivers/subdir_vars.mk=UTF-8 +encoding//Debug/makefile=UTF-8 +encoding//Debug/objects.mk=UTF-8 +encoding//Debug/sources.mk=UTF-8 +encoding//Debug/subdir_rules.mk=UTF-8 +encoding//Debug/subdir_vars.mk=UTF-8 diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/graphics_adapter.c b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/graphics_adapter.c new file mode 100644 index 000000000..dde30df95 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/graphics_adapter.c @@ -0,0 +1,109 @@ +/* + * graphics_adapter.c + * + * Created on: Sep 24, 2017 + * Author: Roy + */ + +#include +#include +#include +#include +#include "graphics_adapter.h" +#include "grlib/grlib.h" +//#include "drivers/frame.h" +//#include "drivers/kentec320x240x16_ssd2119.h" + +#define LINE_HEIGHT 12 +#define MAX_POSITION 240 +int current_position = 0; +char current_line[100]; + +void init_graphics(uint32_t ui32SysClock) +{ +#ifdef USE_GRAPHICS + // Initialize the display driver. + Kentec320x240x16_SSD2119Init(ui32SysClock); + + // Initialize the graphics context. + GrContextInit(&g_sContext, &g_sKentec320x240x16_SSD2119); + + clear(); + +#endif +} + +void draw_image(uint8_t* data) +{ +#ifdef USE_GRAPHICS + GrImageDraw(&g_sContext, data, 0, 0); +#endif +} + +void draw_string(char* data, size_t length) +{ +#ifdef USE_GRAPHICS + tRectangle backRect; + backRect.i16XMin = 100; + backRect.i16XMax = 300; + backRect.i16YMin = 100; + backRect.i16YMax = 80; + + GrContextForegroundSet(&g_sContext, ClrBlack); + GrRectFill(&g_sContext, &backRect); + + + GrStringDraw(&g_sContext, data, length, 0, 0, true); +#endif +} + +void writeLine(char* text) +{ +#ifdef USE_GRAPHICS + if (current_position >= MAX_POSITION) + { + clear(); + } + + strcpy(current_line, text); + GrStringDraw(&g_sContext, current_line, strlen(current_line), 0, current_position, true); + current_position += LINE_HEIGHT; +#endif +} + +void writeFloat(float num) +{ +#ifdef USE_GRAPHICS + char num_buf[10]; + ltoa(num, num_buf); + strcat(current_line, num_buf); + GrStringDraw(&g_sContext, current_line, strlen(current_line), 0, current_position - LINE_HEIGHT, true); +#endif +} + +void writeString(char* text) +{ +#ifdef USE_GRAPHICS + strcat(current_line,text); + GrStringDraw(&g_sContext, current_line, strlen(current_line), 0, current_position - LINE_HEIGHT, true); +#endif +} + +void clear() +{ +#ifdef USE_GRAPHICS + tRectangle backRect; + backRect.i16XMin = 0; + backRect.i16XMax = 340; + backRect.i16YMin = 240; + backRect.i16YMax = 0; + + GrContextForegroundSet(&g_sContext, ClrBlack); + GrRectFill(&g_sContext, &backRect); + + GrContextFontSet(&g_sContext, TEXT_FONT); + GrContextForegroundSet(&g_sContext, ClrWhite); + + current_position = 0; +#endif +} diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/graphics_adapter.h b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/graphics_adapter.h new file mode 100644 index 000000000..3242f9068 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_graphicslib/graphics_adapter.h @@ -0,0 +1,32 @@ +/* + * graphics_adapter.h + * + * Created on: Sep 24, 2017 + * Author: Roy + */ + +#include +#include +#include +#include "grlib/grlib.h" +//#include "drivers/frame.h" +//#include "drivers/kentec320x240x16_ssd2119.h" + +//***************************************************************************** +// +// Graphics context used to show text on the color STN display. +// +//***************************************************************************** +static tContext g_sContext; +#define TEXT_FONT g_psFontCmss12 +#define TEXT_HEIGHT (GrFontHeightGet(TEXT_FONT)) +#define BUFFER_METER_HEIGHT TEXT_HEIGHT +#define BUFFER_METER_WIDTH 150 + +void init_graphics(uint32_t ui32SysClock); +void draw_image(uint8_t* data); +void draw_string(char* data, size_t length); +void writeLine(char* text); +void writeFloat(float num); +void writeString(char* text); +void clear(); diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.ccsproject b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.ccsproject new file mode 100644 index 000000000..83cc5ba74 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.ccsproject @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.cproject b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.cproject new file mode 100644 index 000000000..5c4201208 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.cproject @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.project b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.project new file mode 100644 index 000000000..3d83dab3e --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.project @@ -0,0 +1,40 @@ + + + twine_usblib + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + com.ti.ccstudio.core.ccsNature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + utils/ustdlib.c + 1 + SW_ROOT/utils/ustdlib.c + + + + + SW_ROOT + $%7BTI_PRODUCTS_DIR%7D/TivaWare_C_Series-2.1.4.178 + + + diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.cdt.codan.core.prefs b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 000000000..f653028c5 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +inEditor=false +onBuild=false diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.cdt.debug.core.prefs b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.cdt.debug.core.prefs new file mode 100644 index 000000000..2adc7b1dd --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.cdt.debug.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.debug.core.toggleBreakpointModel=com.ti.ccstudio.debug.CCSBreakpointMarker diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.core.resources.prefs b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..67f3dce24 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +encoding//Debug/makefile=UTF-8 +encoding//Debug/objects.mk=UTF-8 +encoding//Debug/sources.mk=UTF-8 +encoding//Debug/subdir_rules.mk=UTF-8 +encoding//Debug/subdir_vars.mk=UTF-8 +encoding//Debug/utils/subdir_rules.mk=UTF-8 +encoding//Debug/utils/subdir_vars.mk=UTF-8 diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_adapter.c b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_adapter.c new file mode 100644 index 000000000..7869cf947 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_adapter.c @@ -0,0 +1,542 @@ +//Twine USB Serial Communication Library + +//! Assuming you installed TivaWare in the default directory, a +//! driver information (INF) file for use with Windows XP, Windows Vista and +//! Windows7 can be found in C:/ti/TivaWare-for-C-Series/windows_drivers. +//! For Windows 2000, the required INF file is in +//! C:/ti/TivaWare-for-C-Series/windows_drivers/win2K. + +#include "include.h" +#include +#include +#include + +#include +#include +#include + + +#include "inc/hw_ints.h" +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_uart.h" +#include "driverlib/debug.h" +#include "driverlib/gpio.h" +#include "driverlib/interrupt.h" +#include "driverlib/sysctl.h" + +#include "driverlib/systick.h" +#include "driverlib/timer.h" +#include "driverlib/uart.h" +#include "driverlib/usb.h" +#include "driverlib/rom.h" +#include "driverlib/rom_map.h" +#include "usblib/usblib.h" +#include "usblib/usbcdc.h" +#include "usblib/usb-ids.h" +#include "usblib/device/usbdevice.h" +#include "usblib/device/usbdcdc.h" +#include +#include "utils/ustdlib.h" +#include "usb_serial_structs.h" +#include "usb_serial_buffer.h" +#include "usb_serial_adapter.h" + +static SerialBuffer inBuffer; +static int expected_message_size; +static int current_message_size; + +//***************************************************************************** +// +// This function is called whenever serial data is received from the UART. +// It is passed the accumulated error flags from each character received in +// this interrupt and determines from them whether or not an interrupt +// notification to the host is required. +// +// If a notification is required and the control interrupt endpoint is idle, +// we send the notification immediately. If the endpoint is not idle, we +// accumulate the errors in a global variable which will be checked on +// completion of the previous notification and used to send a second one +// if necessary. +// +//***************************************************************************** +void CheckForSerialStateChange(const tUSBDCDCDevice *psDevice, uint32_t ui32Errors) +{ + uint16_t ui16SerialState; + + // + // Clear our USB serial state. Since we are faking the handshakes, always + // set the TXCARRIER (DSR) and RXCARRIER (DCD) bits. + // + ui16SerialState = USB_CDC_SERIAL_STATE_TXCARRIER | + USB_CDC_SERIAL_STATE_RXCARRIER; + + // + // Are any error bits set? + // + if(ui32Errors) + { + // + // At least one error is being notified so translate from our hardware + // error bits into the correct state markers for the USB notification. + // + if(ui32Errors & UART_DR_OE) + { + ui16SerialState |= USB_CDC_SERIAL_STATE_OVERRUN; + } + + if(ui32Errors & UART_DR_PE) + { + ui16SerialState |= USB_CDC_SERIAL_STATE_PARITY; + } + + if(ui32Errors & UART_DR_FE) + { + ui16SerialState |= USB_CDC_SERIAL_STATE_FRAMING; + } + + if(ui32Errors & UART_DR_BE) + { + ui16SerialState |= USB_CDC_SERIAL_STATE_BREAK; + } + + // + // Call the CDC driver to notify the state change. + // + USBDCDCSerialStateChange((void *)psDevice, ui16SerialState); + } +} + +//***************************************************************************** +// +// Set the state of the RS232 RTS and DTR signals. +// +//***************************************************************************** +void SetControlLineState(uint16_t ui16State) +{ + // + // TODO: If configured with GPIOs controlling the handshake lines, + // set them appropriately depending upon the flags passed in the wValue + // field of the request structure passed. + // +} + +//***************************************************************************** +// +// Get the communication parameters in use on the UART. +// +//***************************************************************************** +void GetLineCoding(tLineCoding *psLineCoding) +{ + psLineCoding->ui32Rate = 9600; + psLineCoding->ui8Databits = 8; + psLineCoding->ui8Parity = USB_CDC_PARITY_NONE; + psLineCoding->ui8Stop = USB_CDC_STOP_BITS_1; +} + +//***************************************************************************** +// +// Handles CDC driver notifications related to control and setup of the device. +// +// \param pvCBData is the client-supplied callback pointer for this channel. +// \param ulEvent identifies the event we are being notified about. +// \param ulMsgValue is an event-specific value. +// \param pvMsgData is an event-specific pointer. +// +// This function is called by the CDC driver to perform control-related +// operations on behalf of the USB host. These functions include setting +// and querying the serial communication parameters, setting handshake line +// states and sending break conditions. +// +// \return The return value is event-specific. +// +//***************************************************************************** +uint32_t ControlHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData) +{ + // + // Which event are we being asked to process? + // + switch(ui32Event) + { + // + // We are connected to a host and communication is now possible. + // + case USB_EVENT_CONNECTED: + { + // + // Now connected and ready for normal operation. + // + HWREGBITW(&g_ui32Flags, FLAG_USB_CONFIGURED) = 1; + + // + // Flush our buffers. + // + USBBufferFlush(&g_sTxBuffer); + USBBufferFlush(&g_sRxBuffer); + + //TODO: Notify connection! + + // + // Set the command status update flag. + // + HWREGBITW(&g_ui32Flags, FLAG_STATUS_UPDATE) = 1; + + break; + } + + // + // The host has disconnected. + // + case USB_EVENT_DISCONNECTED: + { + // + // No longer connected. + // + HWREGBITW(&g_ui32Flags, FLAG_USB_CONFIGURED) = 0; + + //TODO: Notify disconnection! + + // + // Set the command status update flag. + // + HWREGBITW(&g_ui32Flags, FLAG_STATUS_UPDATE) = 1; + + break; + } + + // + // Return the current serial communication parameters. + // + case USBD_CDC_EVENT_GET_LINE_CODING: + { + GetLineCoding(pvMsgData); + break; + } + + // + // Set the current serial communication parameters. + // + case USBD_CDC_EVENT_SET_LINE_CODING: + { + GetLineCoding(pvMsgData); + break; + } + + // + // Set the current serial communication parameters. + // + case USBD_CDC_EVENT_SET_CONTROL_LINE_STATE: + { + SetControlLineState((uint16_t)ui32MsgValue); + break; + } + + // + // Send a break condition on the serial line. + // + case USBD_CDC_EVENT_SEND_BREAK: + { + break; + } + + // + // Clear the break condition on the serial line. + // + case USBD_CDC_EVENT_CLEAR_BREAK: + { + break; + } + + // + // Ignore SUSPEND and RESUME for now. + // + case USB_EVENT_SUSPEND: + case USB_EVENT_RESUME: + { + break; + } + + // + // We don't expect to receive any other events. Ignore any that show + // up in a release build or hang in a debug build. + // + default: + { +#ifdef DEBUG + while(1); +#else + break; +#endif + } + + } + + return(0); +} + +//***************************************************************************** +// +// Handles CDC driver notifications related to the transmit channel (data to +// the USB host). +// +// \param pvCBData is the client-supplied callback pointer for this channel. +// \param ui32Event identifies the event we are being notified about. +// \param ui32MsgValue is an event-specific value. +// \param pvMsgData is an event-specific pointer. +// +// This function is called by the CDC driver to notify us of any events +// related to operation of the transmit data channel (the IN channel carrying +// data to the USB host). +// +// \return The return value is event-specific. +// +//***************************************************************************** +uint32_t TxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData) +{ + // + // Which event have we been sent? + // + switch(ui32Event) + { + case USB_EVENT_TX_COMPLETE: + { + // + // Since we are using the USBBuffer, we don't need to do anything + // here. + // + break; + } + + // + // We don't expect to receive any other events. Ignore any that show + // up in a release build or hang in a debug build. + // + default: + { +#ifdef DEBUG + while(1); +#else + break; +#endif + } + } + return(0); +} + +//***************************************************************************** +// +// Handles CDC driver notifications related to the receive channel (data from +// the USB host). +// +// \param pvCBData is the client-supplied callback data value for this channel. +// \param ui32Event identifies the event we are being notified about. +// \param ui32MsgValue is an event-specific value. +// \param pvMsgData is an event-specific pointer. +// +// This function is called by the CDC driver to notify us of any events +// related to operation of the receive data channel (the OUT channel carrying +// data from the USB host). +// +// \return The return value is event-specific. +// +//***************************************************************************** +uint32_t RxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,void *pvMsgData) +{ + // + // Which event are we being sent? + // + switch(ui32Event) + { + // + // A new packet has been received. + // + case USB_EVENT_RX_AVAILABLE: + { + // + // Feed some characters into the UART TX FIFO and enable the + // interrupt so we are told when there is more space. + // + handleRx(); + break; + } + + // + // We are being asked how much unprocessed data we have still to + // process. We return 0 if the UART is currently idle or 1 if it is + // in the process of transmitting something. The actual number of + // bytes in the UART FIFO is not important here, merely whether or + // not everything previously sent to us has been transmitted. + // + case USB_EVENT_DATA_REMAINING: + { + // + // Get the number of bytes in the buffer and add 1 if some data + // still has to clear the transmitter. + return(0); + } + + // + // We are being asked to provide a buffer into which the next packet + // can be read. We do not support this mode of receiving data so let + // the driver know by returning 0. The CDC driver should not be sending + // this message but this is included just for illustration and + // completeness. + // + case USB_EVENT_REQUEST_BUFFER: + { + return(0); + } + + // + // We don't expect to receive any other events. Ignore any that show + // up in a release build or hang in a debug build. + // + default: +#ifdef DEBUG + while(1); +#else + break; +#endif + } + + return(0); +} + +void handleRx(void) +{ + uint32_t ui32Read; + uint8_t ui8Char; + uint8_t size[4]; + int size_bar = 0; + + if (expected_message_size == 0) + { + do + { + ui32Read = USBBufferRead((tUSBBuffer *)&g_sRxBuffer, &ui8Char, 1); + + if(ui32Read) + { + size[size_bar++] = ui8Char; + } + + } while(size_bar < 4); + + expected_message_size = *(int *)size; + } + + do + { + ui32Read = USBBufferRead((tUSBBuffer *)&g_sRxBuffer, &ui8Char, 1); + + // Did we get a character? + if(ui32Read) + { + insertArray(&inBuffer, ui8Char); + current_message_size++; + } + + if (current_message_size == expected_message_size) + { + g_RxCount += current_message_size; + expected_message_size = 0; + current_message_size = 0; + break; + } + + } while(ui32Read); +} +/******************************************************************** + * ======== USBCDCD_hwiHandler ======== + * This function calls the USB library's device interrupt handler. + ********************************************************************/ +static Void USBCDCD_hwiHandler(UArg arg0) +{ + USB0DeviceIntHandler(); +} + +//Execute this function on UART0 Interrupt; +void InitUSB(void) +{ + CheckForSerialStateChange(&g_sCDCDevice, 0); +} + +//Initialize USB. +void StartUSB(uint32_t ui32SysClock) +{ + uint32_t ui32PLLRate, ui32RxCount; + Hwi_Handle hwi; + Error_Block eb; + + Error_init(&eb); + + /* Install interrupt handler */ + hwi = Hwi_create(INT_USB0, USBCDCD_hwiHandler, NULL, &eb); + if (hwi == NULL) + { + LOG_ERROR(hwi,"Can't create USB Hwi"); + } + + + ui32RxCount = 0; + g_RxCount = 0; + + initArray(&inBuffer, 1); + + // Save the PLL rate used by this application. + SysCtlVCOGet(SYSCTL_XTAL_25MHZ, &ui32PLLRate); + + // Not configured initially. + g_ui32Flags = 0; + + // Initialize the transmit and receive buffers. + USBBufferInit(&g_sTxBuffer); + USBBufferInit(&g_sRxBuffer); + + // Set the USB stack mode to Device mode with VBUS monitoring. + USBStackModeSet(0, eUSBModeDevice, 0); + + // Tell the USB library the CPU clock and the PLL frequency. This is a + // new requirement for TM4C129 devices. + USBDCDFeatureSet(0, USBLIB_FEATURE_CPUCLK, &ui32SysClock); + USBDCDFeatureSet(0, USBLIB_FEATURE_USBPLL, &ui32PLLRate); + + // Pass our device information to the USB library and place the device + // on the bus. + USBDCDCInit(0, (tUSBDCDCDevice *)&g_sCDCDevice); + + while (1) + { + if(ui32RxCount != g_RxCount) + { + ui32RxCount = g_RxCount; + + if (callback != NULL) + { + callback(inBuffer.buffer,inBuffer.used); + } + + freeArray(&inBuffer); + initArray(&inBuffer, 1); + } + } +} + +//Send a sequence of chars to PC. +uint32_t SendChars(char* buffer,size_t length) +{ + uint8_t size[4]; + size[3] = (length>>24) & 0xFF; + size[2] = (length>>16) & 0xFF; + size[1] = (length>>8) & 0xFF; + size[0] = length & 0xFF; + + USBBufferWrite((tUSBBuffer *)&g_sTxBuffer, size, 4); + return USBBufferWrite((tUSBBuffer *)&g_sTxBuffer, (uint8_t*)buffer, length); +} + +//Register for serial data receive callback. +void RegisterReceiveCallback(void (*callback_ptr)(char* buffer, size_t length)) +{ + callback = callback_ptr; +} diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_adapter.h b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_adapter.h new file mode 100644 index 000000000..64db33052 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_adapter.h @@ -0,0 +1,73 @@ +#include +#include +#include + +#include "inc/hw_ints.h" +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_uart.h" + +#include "driverlib/debug.h" +#include "driverlib/gpio.h" +#include "driverlib/interrupt.h" +#include "driverlib/sysctl.h" +#include "driverlib/systick.h" +#include "driverlib/timer.h" +#include "driverlib/uart.h" +#include "driverlib/usb.h" +#include "driverlib/rom.h" +#include "driverlib/rom_map.h" + +#include "usblib/usblib.h" +#include "usblib/usbcdc.h" +#include "usblib/usb-ids.h" +#include "usblib/device/usbdevice.h" +#include "usblib/device/usbdcdc.h" +//#include +#include "utils/ustdlib.h" +#include "usb_serial_structs.h" + +//***************************************************************************** +// +// The system tick rate expressed both as ticks per second and a millisecond +// period. +// +//***************************************************************************** +#define TICKS_PER_SECOND 1000 + +//***************************************************************************** +// +// Variables tracking transmit and receive counts. +// +//***************************************************************************** +static volatile uint32_t g_RxCount; + +#ifdef DEBUG +uint32_t g_ui32UARTRxErrors; +#endif + +//***************************************************************************** +// +// Flags used to pass commands from interrupt context to the main loop. +// +//***************************************************************************** +#define FLAG_STATUS_UPDATE 0 +#define FLAG_USB_CONFIGURED 1 +#define FLAG_SENDING_BREAK 2 +static volatile uint32_t g_ui32Flags; + +static void (*callback)(char* buffer, size_t length); + +//***************************************************************************** +// +// Internal function prototypes. +// +//***************************************************************************** +static void CheckForSerialStateChange(const tUSBDCDCDevice *psDevice, uint32_t ui32Errors); +static void SetControlLineState(uint16_t ui16State); +static void GetLineCoding(tLineCoding *psLineCoding); +static void handleRx(void); +void StartUSB(uint32_t ui32SysClock); +void InitUSB(void); +uint32_t SendChars(char* buffer,size_t length); +void RegisterReceiveCallback(void (*callback_ptr)(char* buffer, size_t length)); diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_buffer.c b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_buffer.c new file mode 100644 index 000000000..5025bb772 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_buffer.c @@ -0,0 +1,32 @@ +/* + * usb_serial_buffer.c + * + * Created on: Sep 24, 2017 + * Author: Roy + */ + +#include +#include "usb_serial_buffer.h" + +void initArray(SerialBuffer *a, size_t initialSize) { + a->buffer = (char *)malloc(initialSize); + a->used = 0; + a->size = initialSize; +} + +void insertArray(SerialBuffer *a, char element) { + // a->used is the number of used entries, because a->array[a->used++] updates a->used only *after* the array has been accessed. + // Therefore a->used can go up to a->size + if (a->used == a->size) { + a->size += 1; + a->buffer = (char *)realloc(a->buffer, a->size * sizeof(char)); + } + a->buffer[a->used++] = element; +} + +void freeArray(SerialBuffer *a) { + free(a->buffer); + a->buffer = NULL; + a->used = a->size = 0; +} + diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_buffer.h b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_buffer.h new file mode 100644 index 000000000..561f84b29 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_buffer.h @@ -0,0 +1,20 @@ +/* + * usb_serial_buffer.h + * + * Created on: Sep 24, 2017 + * Author: Roy + */ +#include + +struct serialBuffer { + char *buffer; + size_t used; + size_t size; +} typedef SerialBuffer; + +void initArray(SerialBuffer *a, size_t initialSize); + +void insertArray(SerialBuffer *a, char element); + +void freeArray(SerialBuffer *a); + diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_structs.c b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_structs.c new file mode 100644 index 000000000..eaf5eebf4 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_structs.c @@ -0,0 +1,211 @@ +//***************************************************************************** +// +// usb_serial_structs.c - Data structures defining this CDC USB device. +// +// Copyright (c) 2013-2017 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.4.178 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#include +#include +#include "inc/hw_types.h" +#include "driverlib/usb.h" +#include "usblib/usblib.h" +#include "usblib/usbcdc.h" +#include "usblib/usb-ids.h" +#include "usblib/device/usbdevice.h" +#include "usblib/device/usbdcdc.h" +#include "usb_serial_structs.h" + +#define USB_BUFFER_SIZE 1024 + +//***************************************************************************** +// +// The languages supported by this device. +// +//***************************************************************************** +const uint8_t g_pui8LangDescriptor[] = +{ + 4, + USB_DTYPE_STRING, + USBShort(USB_LANG_EN_US) +}; + +//***************************************************************************** +// +// The manufacturer string. +// +//***************************************************************************** +const uint8_t g_pui8ManufacturerString[] = +{ + (17 + 1) * 2, + USB_DTYPE_STRING, + 'T', 0, 'e', 0, 'x', 0, 'a', 0, 's', 0, ' ', 0, 'I', 0, 'n', 0, 's', 0, + 't', 0, 'r', 0, 'u', 0, 'm', 0, 'e', 0, 'n', 0, 't', 0, 's', 0, +}; + +//***************************************************************************** +// +// The product string. +// +//***************************************************************************** +const uint8_t g_pui8ProductString[] = +{ + 2 + (16 * 2), + USB_DTYPE_STRING, + 'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0, 'a', 0, 'l', 0, ' ', 0, + 'C', 0, 'O', 0, 'M', 0, ' ', 0, 'P', 0, 'o', 0, 'r', 0, 't', 0 +}; + +//***************************************************************************** +// +// The serial number string. +// +//***************************************************************************** +const uint8_t g_pui8SerialNumberString[] = +{ + 2 + (8 * 2), + USB_DTYPE_STRING, + '1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0 +}; + +//***************************************************************************** +// +// The control interface description string. +// +//***************************************************************************** +const uint8_t g_pui8ControlInterfaceString[] = +{ + 2 + (21 * 2), + USB_DTYPE_STRING, + 'A', 0, 'C', 0, 'M', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0, 't', 0, + 'r', 0, 'o', 0, 'l', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, + 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0 +}; + +//***************************************************************************** +// +// The configuration description string. +// +//***************************************************************************** +const uint8_t g_pui8ConfigString[] = +{ + 2 + (26 * 2), + USB_DTYPE_STRING, + 'S', 0, 'e', 0, 'l', 0, 'f', 0, ' ', 0, 'P', 0, 'o', 0, 'w', 0, + 'e', 0, 'r', 0, 'e', 0, 'd', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0, + 'f', 0, 'i', 0, 'g', 0, 'u', 0, 'r', 0, 'a', 0, 't', 0, 'i', 0, + 'o', 0, 'n', 0 +}; + +//***************************************************************************** +// +// The descriptor string table. +// +//***************************************************************************** +const uint8_t * const g_pui8StringDescriptors[] = +{ + g_pui8LangDescriptor, + g_pui8ManufacturerString, + g_pui8ProductString, + g_pui8SerialNumberString, + g_pui8ControlInterfaceString, + g_pui8ConfigString +}; + +#define NUM_STRING_DESCRIPTORS (sizeof(g_pui8StringDescriptors) / \ + sizeof(uint8_t *)) + +//***************************************************************************** +// +// CDC device callback function prototypes. +// +//***************************************************************************** +uint32_t RxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, + void *pvMsgData); +uint32_t TxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, + void *pvMsgData); +uint32_t ControlHandler(void *pvCBData, uint32_t ui32Event, + uint32_t ui32MsgValue, void *pvMsgData); + +//***************************************************************************** +// +// The CDC device initialization and customization structures. In this case, +// we are using USBBuffers between the CDC device class driver and the +// application code. The function pointers and callback data values are set +// to insert a buffer in each of the data channels, transmit and receive. +// +// With the buffer in place, the CDC channel callback is set to the relevant +// channel function and the callback data is set to point to the channel +// instance data. The buffer, in turn, has its callback set to the application +// function and the callback data set to our CDC instance structure. +// +//***************************************************************************** +tCDCSerInstance g_sCDCInstance; +tUSBDCDCDevice g_sCDCDevice = +{ + USB_VID_TI_1CBE, + USB_PID_SERIAL, + 0, + USB_CONF_ATTR_SELF_PWR, + ControlHandler, + (void *)&g_sCDCDevice, + USBBufferEventCallback, + (void *)&g_sRxBuffer, + USBBufferEventCallback, + (void *)&g_sTxBuffer, + g_pui8StringDescriptors, + NUM_STRING_DESCRIPTORS, +}; + +//***************************************************************************** +// +// Receive buffer (from the USB perspective). +// +//***************************************************************************** +uint8_t g_pui8USBRxBuffer[USB_BUFFER_SIZE]; +tUSBBuffer g_sRxBuffer = +{ + false, // This is a receive buffer. + RxHandler, // pfnCallback + (void *)&g_sCDCDevice, // Callback data is our device pointer. + USBDCDCPacketRead, // pfnTransfer + USBDCDCRxPacketAvailable, // pfnAvailable + (void *)&g_sCDCDevice, // pvHandle + g_pui8USBRxBuffer, // pui8Buffer + USB_BUFFER_SIZE, // ui32BufferSize +}; + +//***************************************************************************** +// +// Transmit buffer (from the USB perspective). +// +//***************************************************************************** +uint8_t g_pui8USBTxBuffer[USB_BUFFER_SIZE]; +tUSBBuffer g_sTxBuffer = +{ + true, // This is a transmit buffer. + TxHandler, // pfnCallback + (void *)&g_sCDCDevice, // Callback data is our device pointer. + USBDCDCPacketWrite, // pfnTransfer + USBDCDCTxPacketAvailable, // pfnAvailable + (void *)&g_sCDCDevice, // pvHandle + g_pui8USBTxBuffer, // pcBuffer + USB_BUFFER_SIZE, // ulBufferSize +}; diff --git a/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_structs.h b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_structs.h new file mode 100644 index 000000000..a02ac1c75 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/twine_usblib/usb_serial_structs.h @@ -0,0 +1,49 @@ +//***************************************************************************** +// +// usb_serial_structs.h - Data structures defining this USB CDC device. +// +// Copyright (c) 2013-2017 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.4.178 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#ifndef _USB_SERIAL_STRUCTS_H_ +#define _USB_SERIAL_STRUCTS_H_ + +//***************************************************************************** +// +// The size of the transmit and receive buffers used for the redirected UART. +// This number should be a power of 2 for best performance. 256 is chosen +// pretty much at random though the buffer should be at least twice the size of +// a maximum-sized USB packet. +// +//***************************************************************************** +#define UART_BUFFER_SIZE 256 + +extern uint32_t RxHandler(void *pvCBData, uint32_t ui32Event, + uint32_t ui32MsgValue, void *pvMsgData); +extern uint32_t TxHandler(void *pvlCBData, uint32_t ui32Event, + uint32_t ui32MsgValue, void *pvMsgData); + +extern tUSBBuffer g_sTxBuffer; +extern tUSBBuffer g_sRxBuffer; +extern tUSBDCDCDevice g_sCDCDevice; +extern uint8_t g_pui8USBTxBuffer[]; +extern uint8_t g_pui8USBRxBuffer[]; + +#endif diff --git a/Software/Embedded_SW/Embedded/Embedded.cfg b/Software/Embedded_SW/Embedded/Embedded.cfg new file mode 100644 index 000000000..c3e496533 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Embedded.cfg @@ -0,0 +1,205 @@ +var Hwi = xdc.useModule('ti.sysbios.family.arm.m3.Hwi'); +var Clock = xdc.useModule('ti.sysbios.knl.Clock'); +var BIOS = xdc.useModule('ti.sysbios.BIOS'); +var SysMin = xdc.useModule('xdc.runtime.SysMin'); +var System = xdc.useModule('xdc.runtime.System'); +var Error = xdc.useModule('xdc.runtime.Error'); +var ti_sysbios_hal_Hwi = xdc.useModule('ti.sysbios.hal.Hwi'); +var Memory = xdc.useModule('xdc.runtime.Memory'); +var Timestamp = xdc.useModule('xdc.runtime.Timestamp'); +var TimestampProvider = xdc.useModule('ti.sysbios.family.arm.lm4.TimestampProvider'); +var SyncGeneric = xdc.useModule('xdc.runtime.knl.SyncGeneric'); +var Mailbox = xdc.useModule('ti.sysbios.knl.Mailbox'); +var HeapStd = xdc.useModule('xdc.runtime.HeapStd'); +var GIO = xdc.useModule('ti.sysbios.io.GIO'); +var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore'); +var Task = xdc.useModule('ti.sysbios.knl.Task'); +BIOS.heapSize = 10240; +Program.stack = 2048; + +Clock.timerId = 7; + +var hwi0Params = new Hwi.Params(); +hwi0Params.instance.name = "adcHwi"; +Program.global.adcHwi = Hwi.create(30, "&ADC0SS0Handler", hwi0Params); + +var hwi13Params = new Hwi.Params(); +hwi13Params.instance.name = "timer0"; +Program.global.timer0 = Hwi.create(35, "&OneMilliSecondControlInterrupt", hwi13Params); +/*var hwi14Params = new Hwi.Params(); +hwi14Params.instance.name = "timer1"; +hwi14Params.arg = 1; +Program.global.timer1 = Hwi.create(37, "&OneMilliSecondControlInterrupt", hwi14Params);*/ +var hwi20Params = new Hwi.Params(); +hwi20Params.instance.name = "watchdog"; +Program.global.watchdog = Hwi.create(34, "&WatchdogIntHandler", hwi20Params); +var hwi15Params = new Hwi.Params(); +hwi15Params.instance.name = "timer2"; +hwi15Params.arg = 2; +Program.global.timer2 = Hwi.create(38, "&EightMilliSecondHeatersInterrupt", hwi15Params); +/*var hwi20Params0 = new Hwi.Params(); +hwi20Params0.instance.name = "uart7"; +Program.global.uart7 = Hwi.create(76, "&UARTIntHandler", hwi20Params0);*/ + +/* +var semaphore1Params = new Semaphore.Params(); +semaphore1Params.instance.name = "messageSem"; +semaphore1Params.mode = Semaphore.Mode_BINARY; +Program.global.messageSem = Semaphore.create(null, semaphore1Params); + +var semaphore2Params = new Semaphore.Params(); +semaphore2Params.instance.name = "selfCheckSem"; +semaphore2Params.mode = Semaphore.Mode_BINARY; +Program.global.selfCheckSem = Semaphore.create(null, semaphore2Params); + + +var semaphore4Params = new Semaphore.Params(); +semaphore4Params.instance.name = "initConnectionSem"; +semaphore4Params.mode = Semaphore.Mode_BINARY; +Program.global.initConnectionSem = Semaphore.create(null, semaphore4Params); + +var semaphore5Params = new Semaphore.Params(); +semaphore5Params.instance.name = "uart7Sem"; +semaphore5Params.mode = Semaphore.Mode_BINARY; +Program.global.uart7Sem = Semaphore.create(null, semaphore5Params); + +var semaphore6Params = new Semaphore.Params(); +semaphore6Params.instance.name = "ethernetSem"; +semaphore6Params.mode = Semaphore.Mode_BINARY; +Program.global.ethernetSem = Semaphore.create(null, semaphore6Params); +*/ +var semaphore0Params = new Semaphore.Params(); +semaphore0Params.instance.name = "adcResultSem"; +semaphore0Params.mode = Semaphore.Mode_BINARY; +Program.global.adcResultSem = Semaphore.create(null, semaphore0Params); + +var semaphore3Params = new Semaphore.Params(); +semaphore3Params.instance.name = "updateSem"; +semaphore3Params.mode = Semaphore.Mode_BINARY; +Program.global.updateSem = Semaphore.create(null, semaphore3Params); + +var semaphore7Params = new Semaphore.Params(); +semaphore7Params.instance.name = "ReconnectSem"; +semaphore7Params.mode = Semaphore.Mode_BINARY; +Program.global.ReconnectSem = Semaphore.create(null, semaphore7Params); + +var task0Params = new Task.Params(); +task0Params.instance.name = "adcProcess"; +task0Params.priority = 5; +Program.global.adcProcess = Task.create("&ADCProcessTask", task0Params); +/*var task1Params = new Task.Params(); +task1Params.instance.name = "message"; +task1Params.priority = 3; +Program.global.message = Task.create("&messageTsk", task1Params); +var task2Params = new Task.Params(); +task2Params.instance.name = "communication"; +task2Params.priority = 2; +Program.global.communication = Task.create("&communicationTask", task2Params);*/ +var task3Params = new Task.Params(); +task3Params.instance.name = "update"; +task3Params.priority = 4; +Program.global.update = Task.create("&updateTask", task3Params); +var task4Params = new Task.Params(); +task4Params.instance.name = "Reconnect"; +task4Params.priority = 4; +Program.global.Reconnect = Task.create("&ReconnectTask", task4Params); +var task5Params = new Task.Params(); +task5Params.instance.name = "process"; +task5Params.priority = 9; +Program.global.process = Task.create("&jobTask", task5Params); +var task6Params = new Task.Params(); +task6Params.instance.name = "report"; +task6Params.priority = 2; +Program.global.report = Task.create("&reportService", task6Params); +var task7Params = new Task.Params(); +task7Params.instance.name = "control"; +task7Params.priority = 2; +Program.global.report = Task.create("&controlTask", task7Params); + + +/* ================ NDK configuration ================ */ +/*var Ndk = xdc.loadPackage('ti.ndk.config'); +var Global = xdc.useModule('ti.ndk.config.Global'); +var Ip = xdc.useModule('ti.ndk.config.Ip'); +var Udp = xdc.useModule('ti.ndk.config.Udp'); +var Tcp = xdc.useModule('ti.ndk.config.Tcp'); + +Global.IPv6 = false; +Global.stackLibType = Global.MIN; +Global.networkOpenHook = "&netOpenHook"; + +/* automatically call fdOpen/CloseSession for our sockets Task */ +/*Global.autoOpenCloseFD = true; + +Global.pktNumFrameBufs = 10; +Global.memRawPageCount = 6; +Global.ndkThreadStackSize = 2048; +Global.lowTaskStackSize = 1024; +Global.normTaskStackSize = 1024; +Global.highTaskStackSize = 1024; +Tcp.transmitBufSize = 1024; +Tcp.receiveBufSize = 1024; +/* ================ Text configuration ================ */ +var Text = xdc.useModule('xdc.runtime.Text'); +/* + * These strings are placed in the .const section. Setting this parameter to + * false will save space in the .const section. Error, Assert and Log messages + * will print raw ids and args instead of a formatted message. + * + * Pick one: + * - true (default) + * This option loads test string into the .const for easier debugging. + * - false + * This option reduces the .const footprint. + */ +Text.isLoaded = true; +//Text.isLoaded = false; + + + +/* ================ Types configuration ================ */ +var Types = xdc.useModule('xdc.runtime.Types'); +/* + * This module defines basic constants and types used throughout the + * xdc.runtime package. + */ + +/* ================ TI-RTOS middleware configuration ================ */ +var mwConfig = xdc.useModule('ti.mw.Config'); +/* + * Include TI-RTOS middleware libraries + */ + + + +/* ================ TI-RTOS drivers' configuration ================ */ +var driversConfig = xdc.useModule('ti.drivers.Config'); +/* + * Include TI-RTOS drivers + * + * Pick one: + * - driversConfig.LibType_NonInstrumented (default) + * Use TI-RTOS drivers library optimized for footprint and performance + * without asserts or logs. + * - driversConfig.LibType_Instrumented + * Use TI-RTOS drivers library for debugging with asserts and logs enabled. + */ +driversConfig.libType = driversConfig.LibType_NonInstrumented; +//driversConfig.libType = driversConfig.LibType_Instrumented; + + + +/* ================ Application Specific Instances ================ */ +var FatFS = xdc.useModule('ti.mw.fatfs.FatFS'); +System.maxAtexitHandlers = 2; +TimestampProvider.timerId = 3; +TimestampProvider.useClockTimer = true; +var task4Params = new Task.Params(); +/*task4Params.instance.name = "SDCardWriterHandle"; +task4Params.priority = 5; +Program.global.SDCardWriterHandle = Task.create("&SDCardWriterTask", task4Params);*/ +var semaphore7Params = new Semaphore.Params(); +semaphore7Params.instance.name = "sdCardSem"; +semaphore7Params.mode = Semaphore.Mode_BINARY; +Program.global.sdCardSem = Semaphore.create(null, semaphore7Params); +Program.gen.debuggerFiles = false; diff --git a/Software/Embedded_SW/Embedded/Include.h b/Software/Embedded_SW/Embedded/Include.h new file mode 100644 index 000000000..c898789f4 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Include.h @@ -0,0 +1,53 @@ +//standard lib includes +#include +#include +#include +#include + +#include /*malloc*/ +#include /* tolower */ +#include +#include "./Modules/Stubs_Handler/DataDef.h" +#include "./common/protobuf-c/protobuf-c.h" + +//operation system includes +#include +#include +#include +#include +#include +#include +//xdc +#include +#include + + +//driver includes +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include "inc/hw_uart.h" + +#include "Modules/General/GeneralHardware.h" +#include "drivers/twine_usblib/usb_serial_adapter.h" + +#include + +#include + +#include "Common/Utilities/Utils.h" +#include "Common/report/report.h" + +#define SYS_CLK_FREQ 120000000 + + diff --git a/Software/Embedded_SW/Embedded/Main.c b/Software/Embedded_SW/Embedded/Main.c new file mode 100644 index 000000000..4d828b0ea --- /dev/null +++ b/Software/Embedded_SW/Embedded/Main.c @@ -0,0 +1,92 @@ +#include "include.h" +/*#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +*/ +#include +#include +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "PMR/common/MessageContainer.pb-c.h" +#include "Common/Sys_PinOut_Config/Pin.h" +#include "Common/Sys_PinOut_Config/Pin_config.h" +#include "Drivers/ADC_Sampling/ADC.h" +#include "Drivers/Peripheral_GPIO/GPIO.h" +#include "Modules/Stubs_Handler/Container.h" + +#include "drivers/twine_graphicslib/graphics_adapter.h" + +/* +#include "Drivers/SPI_SDCARD/SDSPI.h" +#include "Drivers/SPI_SDCARD/SDCardSPI.h" +#include "Drivers/Ethernet_Config/EMACCommon.h" +#include "Drivers/USBStick_FileSys/USBstick.h" +#include "Drivers/USBStick_FileSys/USBMSCHFatFs.h" +*/ +#include "Modules/Control/control.h" +#include "StateMachines/Printing/PrintingSTM.h" +extern Semaphore_Handle sdCardSem; +//#define WATCHDOG + +int main(void) +{ + //Set the clock 120MHz + uint32_t ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), SYS_CLK_FREQ); + // Set the system clock to run at 120MHz from the PLL. + + // Save the PLL rate used by this application. + //SysCtlVCOGet(SYSCTL_XTAL_25MHZ, &ui32PLLRate); + + // Enable the system tick. + ROM_SysTickPeriodSet(ui32SysClock / TICKS_PER_SECOND); + ROM_SysTickIntEnable(); + ROM_SysTickEnable(); + + PortFunctionInit(); + + InitPinOutPullUps(); + + // Enable interrupts to the processor. + // + MAP_IntMasterEnable(); + + // + // Enable lazy stacking for interrupt handlers. This allows floating-point + // instructions to be used within interrupt handlers, but at the expense of + // extra stack usage. + // + MAP_FPULazyStackingEnable(); + + SysCtlUSBPLLEnable(); + +#ifdef WATCHDOG + InitWatchdog(ui32SysClock); +#endif + + utilsInit(ui32SysClock); + init_graphics(ui32SysClock); + clear(); + + RegisterReceiveCallback(&receive_callback); + StartUSB(ui32SysClock); + //messageHostInit(); + //InitUSBMSCHFatFs(); + + //EMAC_initEMAC(); + ControlInit(); + JobInit(); + PrintingsInit(); + //LoadManual(); + //Semaphore_post(sdCardSem); + + + BIOS_start(); + + return (0); +} diff --git a/Software/Embedded_SW/Embedded/Modules/Control/PIDAlgo.c b/Software/Embedded_SW/Embedded/Modules/Control/PIDAlgo.c new file mode 100644 index 000000000..fbea57f7d --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Control/PIDAlgo.c @@ -0,0 +1,39 @@ + +#include "PIDAlgo.h" + +float PIDAlgorithmCalculation(uint32_t _setPoint,uint32_t _mesuredParam , PID_Config_Params *params, float *_pre_error, float *_integral) +{ + float error; + float derivative; + float output; + + //Calculate P,I,D + error = _setPoint - _mesuredParam; + + //In case of error too small then stop integration + if(abs(error) > params->epsilon) + { + *_integral = *_integral + error*params->dt; + } + + derivative = (error - *_pre_error)/params->dt; + + output = params->Kp*error + params->Ki**_integral + params->Kd*derivative; + + //Saturation Filter + if(output > params->MAX) + { + output = params->MAX; + } + else if(output < params->MIN) + { + output = params->MIN; + } + + //Update error + *_pre_error = error; + + return output; +} + + diff --git a/Software/Embedded_SW/Embedded/Modules/Control/PIDAlgo.h b/Software/Embedded_SW/Embedded/Modules/Control/PIDAlgo.h new file mode 100644 index 000000000..5f8f4dfe6 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Control/PIDAlgo.h @@ -0,0 +1,18 @@ + +#ifndef MODULES_PIDALGO_H_ +#define MODULES_PIDALGO_H_ +#include + +typedef struct +{ + float epsilon; + float dt; + float MAX; + float MIN; + float Kp; + float Kd; + float Ki; +}PID_Config_Params; +float PIDAlgorithmCalculation(uint32_t _setPoint,uint32_t _mesuredParam , PID_Config_Params *params, float *_pre_error, float *_integral); + +#endif /* MODULES_PIDALGO_H_ */ diff --git a/Software/Embedded_SW/Embedded/Modules/Control/control.c b/Software/Embedded_SW/Embedded/Modules/Control/control.c new file mode 100644 index 000000000..8f389855e --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Control/control.c @@ -0,0 +1,333 @@ +/************************************************************************************************************************ + * control.c + * Control module + * + * The control module is hardware agnostic, not related to a specific hardware module, to enable it to deal with hardware and system changes easily. + * The control module contains a high priority task that connects the hardware drivers + * below to the control algorithms of the high level system modules above. + * + * The control task is invoked by a message from a 1 millisecond timer interrupt. + * The module is based on system components registered in the control module, supplying callback hooks for information gathering and distribution. + * All control clients (drivers and modules) will not perform long procedures that will block the control task. + * + * Control interfaces: + * System Devices list: + * + * All control system input devices will be listed in a system-shared enumareted list, to create a common language between the modules and the drivers. + * (The list will include all hardware devices, but for this module only control input devices are valid) + * Drivers: + * Device registration: a driver that initializes a control input device will call the ControlDeviceRegister function with the deviceId, + * and a control callback hook. This callback is called with a deviceId as the parameter, and returns an unsigned 32bit integer + * as a read value and a call status. The callback will be a non-blocking call, and will indicate in the status value if the data is valid. + * + * It is the responsibility of the device driver to update the control information according to the module hardware requirements. + * If the polling of the information is immediate, it can be collected at the callback call (e.g. local GPI). + * + * Module registration – control: a module is registering to receive the value of the input from a specific device. + * The module indicates what will be the desired frequency of the device polling (in milliseconds). + * It supplies a callback routine that will receive the deviceId, the control value status and the control value. + * The callback will be a non-blocking call. + * The polling frequency is one of a specific list of frequencies: 1/10/100/1000 Hz. (others - TBD) + * + * + * Registering a request for control information from a device that is not registered will be rejected. + * The device registration process must be performed before module registration process. + * + * Unregistering: when control information is not needed, the module will unregister the device polling request from the control module. + * There is a separate call for control hooks and for report hooks. + * The unregistering command contains the callback function pointer, to enable distribution of control + * information of the same device to more than one destination. + * + **************************************************************************************************************************/ + +////////////////////////////////State machine operation//////////////////////////////////// +//the state machine operation is used to operate in runtime correct profile flow execution +//by recieved esign flow of the user from the UI +/////////////////////////////////////////////////////////////////////////////////////////// +#include "include.h" +#include "Modules/General/GeneralHardware.h" + +#include +#include + +#include "drivers/adc_sampling/adc.h" +#include "control.h" +/******************** Definitions ********************************************/ +#define INVALID_MSG_ID 0xFFFF +#define MAX_TANGO_CONTROL_DEVICES 200 +/******************** STRUCTURES AND ENUMs ********************************************/ +typedef struct +{ + uint32_t PartId; // the identity of the inspected/controlled part in the Devices enum. + DeviceDataFunction Callback; + uint32_t lastStatus; +}DriverDeviceStruc; +DriverDeviceStruc DevicesArray[MAX_PORT_ENUM]; + + +typedef struct +{ + uint32_t PartId; // the identity of the inspected/controlled part in the Devices enum. + bool ControlActive; + uint32_t Parameter; + DataReadCBFunction ControlDataReadPtr; + ControlCBFunction ControlCallbackPtr; + CTRL_TIMING_ENUM ControlTiming; +}ControlDeviceStruc; + +typedef enum +{ + OneMillisec, +}controlMessages; + +typedef struct ControlMessage{ + uint16_t messageId; + uint16_t msglen; + uint32_t tick; + uint8_t messageData[20]; +}ControlMessageStruc; +/******************** GLOBAL PARAMETERS ********************************************/ +Mailbox_Handle ControlMsgQ = NULL; +bool ControlRestart; +static GateMutex_Handle gateControlDB; + +ControlDeviceStruc ControlArray[MAX_TANGO_CONTROL_DEVICES]; +uint32_t ControlDatalog[MAX_TANGO_CONTROL_DEVICES]; +uint32_t Control_timerBase = TIMER0_BASE; //Timer handle +/******************** Functions ********************************************/ +void OneMilliSecondFunction(UArg arg0); + +//********************************************************************** +/******************** CODE ********************************************/ +//********************************************************************** + +void ControlInit(void) +{ + int Device_i; + Error_Block eb; + + ControlMsgQ = Mailbox_create(sizeof(ControlMessageStruc), 20, NULL,NULL); + + ControlRestart = false; + + memset(ControlDatalog,0,sizeof(uint32_t)*MAX_TANGO_CONTROL_DEVICES); + + for (Device_i = 0; Device_i < MAX_TANGO_CONTROL_DEVICES; Device_i++) + { + DevicesArray[Device_i].Callback = NULL; + DevicesArray[Device_i].lastStatus = ERROR; + } + + for (Device_i = 0; Device_i < MAX_TANGO_CONTROL_DEVICES; Device_i++) + { + ControlArray[Device_i].ControlActive = false; + ControlArray[Device_i].ControlCallbackPtr = NULL; + ControlArray[Device_i].ControlDataReadPtr = NULL; + ControlArray[Device_i].ControlTiming = eNoControl; + } + gateControlDB = GateMutex_create(NULL, &eb); + if (gateControlDB == NULL) + { + System_abort("Could not create USB Wait gate"); + } + + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); + ROM_TimerConfigure(Control_timerBase, TIMER_CFG_PERIODIC); // 32 bits Timer + //TimerIntRegister(Control_timerBase, TIMER_A, Timer0Isr); // Registering isr + ROM_TimerEnable(Control_timerBase, TIMER_A); + ROM_IntEnable(INT_TIMER0A); + ROM_TimerIntEnable(Control_timerBase, TIMER_TIMA_TIMEOUT); + + ADCAcquireInit(); + + return; +} +void ControlStop(void) +{ + ControlRestart = false; + ADCAcquireStop(); +} + +void ControlStart(void) +{ + ControlRestart = true; + ROM_TimerLoadSet(Control_timerBase, TIMER_BOTH,120000/*one millisecond*/); + ADCAcquireStart(0,1); +} + +/************************************************************************************************************************************************ + * the control task reads the data from the devices every millisecond. + * (the data might be old data, if it is polled in a slower rate) + * for every polled device, there is a need to add a Data read callback, with a device id. the read value is always 32bits unsigned integer + * if there is a need to run a control function based on the read data, then the hardware module will add a control function, specifying the control calling rate + * both these callbacks can be removed. if a new call is arriving, it invalidates the previous one (no dual control or data) + * + ***************************************************************************************************************************************************/ +int AddControlCallback(uint32_t deviceId, ControlCBFunction Callback, CTRL_TIMING_ENUM CtrlFrequency ) +{ + assert(deviceId < MAX_TANGO_CONTROL_DEVICES); + assert(Callback); + unsigned int key; + + if(ControlArray[deviceId].ControlDataReadPtr == NULL) + { + LOG_ERROR (deviceId, "No dataread function for device"); + return ERROR; + } + + key = GateMutex_enter(gateControlDB); + ControlArray[deviceId].ControlTiming = CtrlFrequency; + ControlArray[deviceId].ControlCallbackPtr = Callback; + ControlArray[deviceId].ControlActive = true; + GateMutex_leave(gateControlDB, key); + + return OK; + +} +int RemoveControlCallback(uint32_t deviceId , ControlCBFunction Callback) +{ + assert(deviceId < MAX_TANGO_CONTROL_DEVICES); + unsigned int key; + + if (Callback == ControlArray[deviceId].ControlCallbackPtr) + { + key = GateMutex_enter(gateControlDB); + ControlArray[deviceId].ControlTiming = eNoControl; + ControlArray[deviceId].ControlCallbackPtr = NULL; + ControlArray[deviceId].ControlActive = false; + GateMutex_leave(gateControlDB, key); + return OK; + } + else + return ERROR; + +} + +int RegisterDevice(uint32_t deviceId, DataReadCBFunction Callback, uint32_t Parameter) +{ + assert(deviceId < MAX_TANGO_CONTROL_DEVICES); + assert(Callback); + unsigned int key; + key = GateMutex_enter(gateControlDB); + ControlArray[deviceId].Parameter = Parameter; + ControlArray[deviceId].ControlDataReadPtr = Callback; + GateMutex_leave(gateControlDB, key); + return OK; + +} +int UnRegisterDevice(uint32_t deviceId, DataReadCBFunction Callback ) +{ + assert(deviceId < MAX_TANGO_CONTROL_DEVICES); + unsigned int key; + if (Callback == ControlArray[deviceId].ControlDataReadPtr) + { + key = GateMutex_enter(gateControlDB); + ControlArray[deviceId].Parameter = 0; + ControlArray[deviceId].ControlDataReadPtr = NULL; + ControlDatalog[deviceId] = 0; + GateMutex_leave(gateControlDB, key); + return OK; + } + else + return ERROR; + +} + +void OneMilliSecondControlInterrupt(UArg arg0) +{ + ControlMessageStruc Message; + bool retcode = false; + ROM_IntMasterDisable(); + + //trigger the ADC collection - check and set priorities to make sure handling timing is correct. + //we might want to call it from the task, afetr execution of other taks!!! + ADC_TriggerCollection(); + //send message to the control task + Message.messageId = OneMillisec; + Message.tick = UsersysTickGet(); + Message.msglen = sizeof(ControlMessageStruc); + if (ControlMsgQ != NULL) + retcode = Mailbox_post(ControlMsgQ , &Message, BIOS_NO_WAIT); + if (ControlRestart == true) + { + ROM_TimerLoadSet(Control_timerBase, TIMER_BOTH,120000/*one millisecond*/); + } + + ROM_TimerIntClear(Control_timerBase, TIMER_TIMA_TIMEOUT); // Clear the timer interrupt + // + // Enable all interrupts. + // + ROM_IntMasterEnable(); + return ; +} + +uint32_t ControlLoop(uint32_t tick) +{ + //call all modules control functions + //test dancers and speed encoders + //check all callback units (state machine waiting for completion of a change) + uint32_t Device_i; + bool Ten_msTick, Hundred_msTick, Onesecond_Tick; + Ten_msTick = (tick%eTenMilliSecond == 0) ?true:false; + Hundred_msTick = (tick%eHunderdMillisecond == 0) ?true:false; + Onesecond_Tick = (tick%eOneSecond == 0) ?true:false; + + for (Device_i = 0; Device_i < MAX_TANGO_CONTROL_DEVICES;Device_i++) + { + if (ControlArray[Device_i].ControlDataReadPtr) + ControlDatalog[Device_i] = ControlArray[Device_i].ControlDataReadPtr(Device_i, ControlArray[Device_i].Parameter); + if (ControlArray[Device_i].ControlActive) + { + switch (ControlArray[Device_i].ControlTiming) + { + case eOneMillisecond: + ControlArray[Device_i].ControlCallbackPtr(Device_i, ControlDatalog[Device_i]); + break; + case eTenMilliSecond: + if (Ten_msTick) + ControlArray[Device_i].ControlCallbackPtr(Device_i, ControlDatalog[Device_i]); + break; + case eHunderdMillisecond: + if (Hundred_msTick) + ControlArray[Device_i].ControlCallbackPtr(Device_i, ControlDatalog[Device_i]); + break; + case eOneSecond: + if (Onesecond_Tick) + ControlArray[Device_i].ControlCallbackPtr(Device_i, ControlDatalog[Device_i]); + break; + default: + LOG_ERROR (ControlArray[Device_i].ControlTiming, "Invalid control timing value"); + break; + } + } + } + + return OK; +} +/****************************************************************************** + * ======== messageTsk ======== + * Task for this function is created statically. See the project's .cfg file. + * this message task is created statically in system initialization, + ******************************************************************************/ +void controlTask(UArg arg0, UArg arg1) +{ + ControlMessageStruc Message; + //char str[60]; + //uint16_t length; + //Clock_setTimeout(HostKAClock, 1000); + //Clock_start(HostKAClock); + + + while(1) + { + Mailbox_pend(ControlMsgQ , &Message, BIOS_WAIT_FOREVER); + switch (Message.messageId) + { + case OneMillisec: + ControlLoop(Message.tick); + break; + default: + break; + } + } +} diff --git a/Software/Embedded_SW/Embedded/Modules/Control/control.h b/Software/Embedded_SW/Embedded/Modules/Control/control.h new file mode 100644 index 000000000..ab259993a --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Control/control.h @@ -0,0 +1,30 @@ +/************************************************************************************************************************ + * control.c + **************************************************************************************************************************/ + +////////////////////////////////State machine operation//////////////////////////////////// +//the state machine operation is used to operate in runtime correct profile flow execution +//by recieved esign flow of the user from the UI +/////////////////////////////////////////////////////////////////////////////////////////// +#include "include.h" + +typedef uint32_t (* DeviceDataFunction)(uint32_t deviceID, uint32_t *Value); +typedef uint32_t (* ControlCBFunction)(uint32_t deviceID, uint32_t ReadValue); +typedef uint32_t (* DataReadCBFunction)(uint32_t deviceID, uint32_t Parameter); +typedef enum { + eNoControl = 0, + eOneMillisecond = 1, + eTenMilliSecond = 10, + eHunderdMillisecond = 100, + eOneSecond = 1000 +}CTRL_TIMING_ENUM; + + +void ControlInit(void); +void ControlStop(void); +void ControlStart(void); +int AddControlCallback(uint32_t deviceID, ControlCBFunction Callback, CTRL_TIMING_ENUM CtrlFrequency ); +int RemoveControlCallback(uint32_t deviceID, ControlCBFunction Callback ); +int RegisterDevice(uint32_t deviceID, DataReadCBFunction Callback, uint32_t Parameter); +int UnRegisterDevice(uint32_t deviceID, DataReadCBFunction Callback ); + diff --git a/Software/Embedded_SW/Embedded/Modules/General/GeneralHardware.c b/Software/Embedded_SW/Embedded/Modules/General/GeneralHardware.c new file mode 100644 index 000000000..1f5e3aa84 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/General/GeneralHardware.c @@ -0,0 +1,348 @@ +/************************************************************************************************************************ + * control.c + * Control module + * +************************************************************************************************************************/ +#include "include.h" +#include "GeneralHardware.h" +#include "thread/thread.h" +#include "ids/ids.h" +#include "control/control.h" +#include "heaters/heaters_ex.h" +#include +#include "PMR/common/MessageContainer.pb-c.h" +#include "Modules/Stubs_Handler/Container.h" +#include "PMR/Hardware/UploadHardWareConfigurationRequest.pb-c.h" +#include "PMR/Hardware/UploadHardWareConfigurationResponse.pb-c.h" + +PortInfoStruct PortInfoTable[MAX_PORT_ENUM] = { + {ANALOG_MIXCHIP_TEMP,"ANALOG_MIXCHIP_TEMP"}, + {AN_DYEINGH_CURSEN_1,"AN_DYEINGH_CURSEN_1"}, + {AN_DYEINGH_CURSEN_2,"AN_DYEINGH_CURSEN_2"}, + {AN_DYEINGH_CURSEN_3,"AN_DYEINGH_CURSEN_3"}, + {AN_DYEINGH_CURSEN_4,"AN_DYEINGH_CURSEN_4"}, + {AN_DYEINGH_CURSEN_5,"AN_DYEINGH_CURSEN_5"}, + {ANALOG_DYEINGH_TEMP1,"ANALOG_DYEINGH_TEMP1"}, + {ANALOG_DYEINGH_TEMP2,"ANALOG_DYEINGH_TEMP2"}, + {ANALOG_DYEINGH_TEMP3,"ANALOG_DYEINGH_TEMP3"}, + {ANALOG_DYEINGH_TEMP4,"ANALOG_DYEINGH_TEMP4"}, + {ANALOG_DYEINGH_TEMP5,"ANALOG_DYEINGH_TEMP5"}, + {AN_DRYER_CURSEN1,"AN_DRYER_CURSEN1"}, + {AN_DRYER_CURSEN2,"AN_DRYER_CURSEN2"}, + {AN_DRYER_CURSEN3,"AN_DRYER_CURSEN3"}, + {ANALOG_DRYER_TEMP1,"ANALOG_DRYER_TEMP1"}, + {ANALOG_DRYER_TEMP2,"ANALOG_DRYER_TEMP2"}, + {ANALOG_DRYER_TEMP3,"ANALOG_DRYER_TEMP3"}, + {AN_ENCLOSURETEMP1,"AN_ENCLOSURETEMP1"}, + {AN_ENCLOSURETEMP2,"AN_ENCLOSURETEMP2"}, + {AN_ENCLOSURETEMP3,"AN_ENCLOSURETEMP3"}, + {AN_IDS_PRESSENS_1,"AN_IDS_PRESSENS_1"}, + {AN_IDS_PRESSENS_2,"AN_IDS_PRESSENS_2"}, + {AN_IDS_PRESSENS_3,"AN_IDS_PRESSENS_3"}, + {AN_IDS_PRESSENS_4,"AN_IDS_PRESSENS_4"}, + {AN_IDS_PRESSENS_5,"AN_IDS_PRESSENS_5"}, + {AN_IDS_PRESSENS_6,"AN_IDS_PRESSENS_6"}, + {AN_IDS_PRESSENS_7,"AN_IDS_PRESSENS_7"}, + {AN_IDS_PRESSENS_8,"AN_IDS_PRESSENS_8"}, + {AN_MIDTANK_PRESSENS1,"AN_MIDTANK_PRESSENS1"}, + {AN_MIDTANK_PRESSENS2,"AN_MIDTANK_PRESSENS2"}, + {AN_MIDTANK_PRESSENS3,"AN_MIDTANK_PRESSENS3"}, + {AN_MIDTANK_PRESSENS4,"AN_MIDTANK_PRESSENS4"}, + {AN_MIDTANK_PRESSENS5,"AN_MIDTANK_PRESSENS5"}, + {AN_MIDTANK_PRESSENS6,"AN_MIDTANK_PRESSENS6"}, + {AN_MIDTANK_PRESSENS7,"AN_MIDTANK_PRESSENS7"}, + {AN_MIXCHIP_CURSENn,"AN_MIXCHIP_CURSENn"}, + {AN5V_LDANCER1,"AN5V_LDANCER1"}, + {AN5V_LDANCER2,"AN5V_LDANCER2"}, + {AN5V_RDANCER,"AN5V_RDANCER"}, + {AN10V_SPARE1,"AN10V_SPARE1"}, + {AN10V_SPARE2,"AN10V_SPARE2"}, + {AN_AIRPRESS_1,"AN_AIRPRESS_1"}, + {AN_AIRPRESS_2,"AN_AIRPRESS_2"}, + {AN_VOCSENS,"AN_VOCSENS"}, + {AN_BLOWERCTRL,"AN_BLOWERCTRL"}, + {LS_DH_LID_CLEANING,"LS_DH_LID_CLEANING"}, + {LS_DH_LID_CLOSED,"LS_DH_LID_CLOSED"}, + {LS_DH_CLEAN_UP,"LS_DH_CLEAN_UP"}, + {LS_DH_CLEAN_RIGHT,"LS_DH_CLEAN_RIGHT"}, + {LS_DH_SPARE1,"LS_DH_SPARE1"}, + {LS_DH_LID_OPEN,"LS_DH_LID_OPEN"}, + {LS_DH_CLEAN_DOWN,"LS_DH_CLEAN_DOWN"}, + {LS_DH_CLEAN_LEFT,"LS_DH_CLEAN_LEFT"}, + {LS_DRYER_LID_OPEN,"LS_DRYER_LID_OPEN"}, + {LS_DRYER_SPARE3,"LS_DRYER_SPARE3"}, + {LS_DRYER_LID_CLOSED,"LS_DRYER_LID_CLOSED"}, + {LS_DRYER_SPARE4,"LS_DRYER_SPARE4"}, + {LS_DRYER_SPARE1,"LS_DRYER_SPARE1"}, + {LS_LOADARM_RIGHT,"LS_LOADARM_RIGHT"}, + {LS_DRYER_SPARE2,"LS_DRYER_SPARE2"}, + {LS_LOADARM_LEFT,"LS_LOADARM_LEFT"}, + {GPI_PS1_DC_OK,"GPI_PS1_DC_OK"}, + {GPI_PANSW2,"GPI_PANSW2"}, + {GPI_PANSW4,"GPI_PANSW4"}, + {GPI_PANSW1,"GPI_PANSW1"}, + {GPI_PANSW3,"GPI_PANSW3"}, + {GPI_PANSW5,"GPI_PANSW5"}, + {GPI_PANSW6,"GPI_PANSW6"}, + {GPI_TACTSW1,"GPI_TACTSW1"}, + {GPI_TACTSW3,"GPI_TACTSW3"}, + {GPI_PWRBUTTON,"GPI_PWRBUTTON"}, + {GPI_TACTSW2,"GPI_TACTSW2"}, + {GPI_TACTSW4,"GPI_TACTSW4"}, + {GPI_EXTWINDER_1,"GPI_EXTWINDER_1"}, + {GPI_EXTWINDER_2,"GPI_EXTWINDER_2"}, + {GPI_EXTWINDER_3,"GPI_EXTWINDER_3"}, + {GPI_EXTWINDER_1_rtn,"GPI_EXTWINDER_1_rtn"}, + {GPI_EXTWINDER_2_rtn,"GPI_EXTWINDER_2_rtn"}, + {GPI_EXTWINDER_3_rtn,"GPI_EXTWINDER_3_rtn"}, + {LS_DISPENSER_UP_1,"LS_DISPENSER_UP_1"}, + {LS_DISPENSER_25_1,"LS_DISPENSER_25_1"}, + {LS_DISPENSER_75_1,"LS_DISPENSER_75_1"}, + {LS_DISPENSER_UP_3,"LS_DISPENSER_UP_3"}, + {LS_DISPENSER_25_3,"LS_DISPENSER_25_3"}, + {LS_DISPENSER_75_3,"LS_DISPENSER_75_3"}, + {LS_DISPENSER_UP_5,"LS_DISPENSER_UP_5"}, + {LS_DISPENSER_25_5,"LS_DISPENSER_25_5"}, + {LS_DISPENSER_75_5,"LS_DISPENSER_75_5"}, + {LS_DISPENSER_UP_7,"LS_DISPENSER_UP_7"}, + {LS_DISPENSER_25_7,"LS_DISPENSER_25_7"}, + {LS_DISPENSER_75_7,"LS_DISPENSER_75_7"}, + {LS_DISPENSER_DOWN_1,"LS_DISPENSER_DOWN_1"}, + {LS_DISPENSER_50_1,"LS_DISPENSER_50_1"}, + {LS_DISPENSER_SPARE_1,"LS_DISPENSER_SPARE_1"}, + {LS_DISPENSER_DOWN_3,"LS_DISPENSER_DOWN_3"}, + {LS_DISPENSER_50_3,"LS_DISPENSER_50_3"}, + {LS_DISPENSER_SPARE_3,"LS_DISPENSER_SPARE_3"}, + {LS_DISPENSER_DOWN_5,"LS_DISPENSER_DOWN_5"}, + {LS_DISPENSER_50_5,"LS_DISPENSER_50_5"}, + {LS_DISPENSER_SPARE_5,"LS_DISPENSER_SPARE_5"}, + {LS_DISPENSER_DOWN_7,"LS_DISPENSER_DOWN_7"}, + {LS_DISPENSER_50_7,"LS_DISPENSER_50_7"}, + {LS_DISPENSER_SPARE_7,"LS_DISPENSER_SPARE_7"}, + {LS_DISPENSER_UP_2,"LS_DISPENSER_UP_2"}, + {LS_DISPENSER_25_2,"LS_DISPENSER_25_2"}, + {LS_DISPENSER_75_2,"LS_DISPENSER_75_2"}, + {LS_DISPENSER_UP_4,"LS_DISPENSER_UP_4"}, + {LS_DISPENSER_25_4,"LS_DISPENSER_25_4"}, + {LS_DISPENSER_75_4,"LS_DISPENSER_75_4"}, + {LS_DISPENSER_UP_6,"LS_DISPENSER_UP_6"}, + {LS_DISPENSER_25_6,"LS_DISPENSER_25_6"}, + {LS_DISPENSER_75_6,"LS_DISPENSER_75_6"}, + {LS_DISPENSER_UP_8,"LS_DISPENSER_UP_8"}, + {LS_DISPENSER_25_8,"LS_DISPENSER_25_8"}, + {LS_DISPENSER_75_8,"LS_DISPENSER_75_8"}, + {LS_RLOADMOTOR_UP,"LS_RLOADMOTOR_UP"}, + {LS_DISPENSER_DOWN_2,"LS_DISPENSER_DOWN_2"}, + {LS_DISPENSER_50_2,"LS_DISPENSER_50_2"}, + {LS_DISPENSER_SPARE_2,"LS_DISPENSER_SPARE_2"}, + {LS_DISPENSER_DOWN_4,"LS_DISPENSER_DOWN_4"}, + {LS_DISPENSER_50_4,"LS_DISPENSER_50_4"}, + {LS_DISPENSER_SPARE_4,"LS_DISPENSER_SPARE_4"}, + {LS_DISPENSER_DOWN_6,"LS_DISPENSER_DOWN_6"}, + {LS_DISPENSER_50_6,"LS_DISPENSER_50_6"}, + {LS_DISPENSER_SPARE_6,"LS_DISPENSER_SPARE_6"}, + {LS_DISPENSER_DOWN_8,"LS_DISPENSER_DOWN_8"}, + {LS_DISPENSER_50_8,"LS_DISPENSER_50_8"}, + {LS_DISPENSER_SPARE_8,"LS_DISPENSER_SPARE_8"}, + {LS_SCREW_LEFT,"LS_SCREW_LEFT"}, + {SW_SPOOL_EXISTS,"SW_SPOOL_EXISTS"}, + {LS_SCREW_RIGHT,"LS_SCREW_RIGHT"}, + {SW_SPARE,"SW_SPARE"}, + {LS_LDANCER1_DOWN,"LS_LDANCER1_DOWN"}, + {LS_LDANCER2_DOWN,"LS_LDANCER2_DOWN"}, + {LS_LPIVOT_DOWN,"LS_LPIVOT_DOWN"}, + {LS_PIVOT_SPARE1,"LS_PIVOT_SPARE1"}, + {LS_LDANCER1_UP,"LS_LDANCER1_UP"}, + {LS_LDANCER2_UP,"LS_LDANCER2_UP"}, + {LS_LPIVOT_UP,"LS_LPIVOT_UP"}, + {LS_PIVOT_SPARE2,"LS_PIVOT_SPARE2"}, + {LS_LLOADMOTOR_DOWN,"LS_LLOADMOTOR_DOWN"}, + {LS_LSPARE1,"LS_LSPARE1"}, + {LS_LLOADMOTOR_UP,"LS_LLOADMOTOR_UP"}, + {LS_LSPARE2,"LS_LSPARE2"}, + {LS_RDANCER_DOWN,"LS_RDANCER_DOWN"}, + {LS_RLOADRAM_DOWN,"LS_RLOADRAM_DOWN"}, + {LS_RDANCER_UP,"LS_RDANCER_UP"}, + {LS_RLOADRAM_UP,"LS_RLOADRAM_UP"}, + {LS_RLOADMOTOR_DOWN,"LS_RLOADMOTOR_DOWN"}, + {GPI_TFEED_BREAK_1,"GPI_TFEED_BREAK_1"}, + {GPI_TFEED_BREAK_2,"GPI_TFEED_BREAK_2"}, + {LS_RSPARE1,"LS_RSPARE1"}, + {LS_SPARE2_1,"LS_SPARE2_1"}, + {LS_SPARE2_3,"LS_SPARE2_3"}, + {LS_SPARE1_1,"LS_SPARE1_1"}, + {LS_SPARE1_3,"LS_SPARE1_3"}, + {LS_RSPARE2,"LS_RSPARE2"}, + {LS_SPARE2_2,"LS_SPARE2_2"}, + {LS_SPARE2_4,"LS_SPARE2_4"}, + {LS_SPARE1_2,"LS_SPARE1_2"}, + {LS_SPARE1_4,"LS_SPARE1_4"}, + {GPI_WCONTAINER_WARN,"GPI_WCONTAINER_WARN"}, + {GPI_SW_WCONTAINER_PRES,"GPI_SW_WCONTAINER_PRES"}, + {GPI_CHILLER_FAULT,"GPI_CHILLER_FAULT"}, + {GPI_CHILLER_STAT1,"GPI_CHILLER_STAT1"}, + {GPI_BLOWER_TACH,"GPI_BLOWER_TACH"}, + {GPI_WCONTAINER_FULL,"GPI_WCONTAINER_FULL"}, + {GPI_AIRFLOW_FLAP,"GPI_AIRFLOW_FLAP"}, + {GPO_MIXCHIP_SSR4_CTRL,"GPO_MIXCHIP_SSR4_CTRL"}, + {GPO_DYEINGH_SSR7_CTRL,"GPO_DYEINGH_SSR7_CTRL"}, + {GPO_DYEINGH_SSR8_CTRL,"GPO_DYEINGH_SSR8_CTRL"}, + {GPO_DYEINGH_SSR5_CTRL,"GPO_DYEINGH_SSR5_CTRL"}, + {GPO_DYEINGH_SSR6_CTRL,"GPO_DYEINGH_SSR6_CTRL"}, + {GPO_DRYER_SSR3_CTRL,"GPO_DRYER_SSR3_CTRL"}, + {GPO_DRYER_SSR1_CTRL,"GPO_DRYER_SSR1_CTRL"}, + {GPO_DRYER_SSR2_CTRL,"GPO_DRYER_SSR2_CTRL"}, + {GPO_SPARE_SSR12_CTRL,"GPO_SPARE_SSR12_CTRL"}, + {GPO_SPARE_SSR13_CTRL,"GPO_SPARE_SSR13_CTRL"}, + {GPO_PDOWN_RL1_CTRL,"GPO_PDOWN_RL1_CTRL"}, + {GPO_LED1,"GPO_LED1"}, + {GPO_LED3,"GPO_LED3"}, + {GPO_LED2,"GPO_LED2"}, + {GPO_LED4,"GPO_LED4"}, + {GPO_BUZZER,"GPO_BUZZER"}, + {GPO_EXTWINDER_SSR11_CTRL,"GPO_EXTWINDER_SSR11_CTRL"}, + {GPO_EXTWINDER_1,"GPO_EXTWINDER_1"}, + {GPO_EXTWINDER_2,"GPO_EXTWINDER_2"}, + {GPO_EXTWINDER_3,"GPO_EXTWINDER_3"}, + {GPO_DILUTORPUMP_SSR10_CTRL,"GPO_DILUTORPUMP_SSR10_CTRL"}, + {GPO_WASTECH_PUMP1,"GPO_WASTECH_PUMP1"}, + {GPO_WASTECH_PUMP2,"GPO_WASTECH_PUMP2"}, + {GPO_TFEED_BREAK_1,"GPO_TFEED_BREAK_1"}, + {GPO_TFEED_BREAK_2,"GPO_TFEED_BREAK_2"}, + {GPO_SPARE1_1,"GPO_SPARE1_1"}, + {GPO_SPARE2_1,"GPO_SPARE2_1"}, + {GPO_SPARE1_2,"GPO_SPARE1_2"}, + {GPO_SPARE2_2,"GPO_SPARE2_2"}, + {GPO_BLOWER_PWM,"GPO_BLOWER_PWM"}, + {GPO_WHS_WTANKPUMP2,"GPO_WHS_WTANKPUMP2"}, + {GPO_CHILLER_SSR9_CTRL,"GPO_CHILLER_SSR9_CTRL"}, + {DH2,"DH2"}, + {DH1,"DH1"}, + {DRYER2,"DRYER2"}, + {DRYER1,"DRYER1"}, + {ELECTRICALENC,"ELECTRICALENC"}, + {USERPANEL,"USERPANEL"}, + {EXTWINDINGUNIT,"EXTWINDINGUNIT"}, + {DISPENSER_1,"DISPENSER_1"}, + {DISPENSER_3,"DISPENSER_3"}, + {DISPENSER_5,"DISPENSER_5"}, + {DISPENSER_7,"DISPENSER_7"}, + {MIDTANK3_1,"MIDTANK3_1"}, + {DISPENSER_2,"DISPENSER_2"}, + {DISPENSER_4,"DISPENSER_4"}, + {DISPENSER_6,"DISPENSER_6"}, + {DISPENSER_8,"DISPENSER_8"}, + {CART3,"CART3"}, + {CART1,"CART1"}, + {CART2,"CART2"}, + {CART4,"CART4"}, + {CART7,"CART7"}, + {CART5,"CART5"}, + {CART6,"CART6"}, + {CART8,"CART8"}, + {INTWINDINGUNIT,"INTWINDINGUNIT"}, + {LTFEEDUNIT2,"LTFEEDUNIT2"}, + {LTFEEDUNIT1,"LTFEEDUNIT1"}, + {RTFEEDUNIT2,"RTFEEDUNIT2"}, + {RTFEEDUNIT1,"RTFEEDUNIT1"}, + {SPARE2,"SPARE2"}, + {SPARE1,"SPARE1"}, + {WHS,"WHS"}, + {MIDTANK3_2,"MIDTANK3_2"}, + {MOTO_DH_CLEANHEAD,"MOTO_DH_CLEANHEAD"}, + {MOTO_DH_CLEANMECH,"MOTO_DH_CLEANMECH"}, + {MOTO_DH_LID,"MOTO_DH_LID"}, + {MOTO_DRYER_DRIVING,"MOTO_DRYER_DRIVING"}, + {MOTO_DRYER_LID,"MOTO_DRYER_LID"}, + {MOTO_DRYER_LOADARM,"MOTO_DRYER_LOADARM"}, + {MOTO_DISPENSER_1,"MOTO_DISPENSER_1"}, + {MOTO_DISPENSER_2,"MOTO_DISPENSER_2"}, + {MOTO_DISPENSER_3,"MOTO_DISPENSER_3"}, + {MOTO_DISPENSER_4,"MOTO_DISPENSER_4"}, + {MOTO_DISPENSER_5,"MOTO_DISPENSER_5"}, + {MOTO_DISPENSER_6,"MOTO_DISPENSER_6"}, + {MOTO_DISPENSER_7,"MOTO_DISPENSER_7"}, + {MOTO_DISPENSER_8,"MOTO_DISPENSER_8"}, + {MOTO_SCREW,"MOTO_SCREW"}, + {MOTO_WINDER,"MOTO_WINDER"}, + {MOTO_LDANCER1,"MOTO_LDANCER1"}, + {MOTO_LDANCER2,"MOTO_LDANCER2"}, + {MOTO_LDRIVING,"MOTO_LDRIVING"}, + {MOTO_LLOADING,"MOTO_LLOADING"}, + {MOTO_LPIVOT1,"MOTO_LPIVOT1"}, + {MOTO_RDANCER,"MOTO_RDANCER"}, + {MOTO_RDRIVING,"MOTO_RDRIVING"}, + {MOTO_RLOADARM,"MOTO_RLOADARM"}, + {MOTO_RLOADING,"MOTO_RLOADING"}, + {MOTO_SPARE1_1,"MOTO_SPARE1_1"}, + {MOTO_SPARE1_2,"MOTO_SPARE1_2"}, + {MOTO_SPARE2_1,"MOTO_SPARE2_1"}, + {MOTO_SPARE2_2,"MOTO_SPARE2_2"}, + {DRYER_LOADARM_ROTENC,"DRYER_LOADARM_ROTENC"}, + {DISPENSER_ROTENC1,"DISPENSER_ROTENC1"}, + {DISPENSER_ROTENC2,"DISPENSER_ROTENC2"}, + {DISPENSER_ROTENC3,"DISPENSER_ROTENC3"}, + {DISPENSER_ROTENC4,"DISPENSER_ROTENC4"}, + {DISPENSER_ROTENC5,"DISPENSER_ROTENC5"}, + {DISPENSER_ROTENC6,"DISPENSER_ROTENC6"}, + {DISPENSER_ROTENC7,"DISPENSER_ROTENC7"}, + {DISPENSER_ROTENC8,"DISPENSER_ROTENC8"}, + {SCREW_ROTENC,"SCREW_ROTENC"}, + {LDANCER1_ROTENC2,"LDANCER1_ROTENC2"}, + {LDANCER2_ROTENC2,"LDANCER2_ROTENC2"}, + {LSPARE_ROTENC,"LSPARE_ROTENC"}, + {LSPARE_ROTENCn,"LSPARE_ROTENCn"}, + {LSPARE1_ROTENC,"LSPARE1_ROTENC"}, + {LSPARE2_ROTENC,"LSPARE2_ROTENC"}, + {RDANCER_ROTENC2,"RDANCER_ROTENC2"}, + {RSPARE_ROTENC,"RSPARE_ROTENC"}, + {RSPEEDSENS_ROTENC,"RSPEEDSENS_ROTENC"}, + {SPARE1_ROTENC,"SPARE1_ROTENC"}, + {SPARE2_ROTENC,"SPARE2_ROTENC"}, + {FAN_TACHO1,"FAN_TACHO1"}, + {FAN_TACHO3,"FAN_TACHO3"}, + {FAN_TACHO2,"FAN_TACHO2"}, + {FAN1_TACH,"FAN1_TACH"}, + {FAN2_TACH,"FAN2_TACH"}, + {FAN5_TACH,"FAN5_TACH"}, + {FAN3_TACH,"FAN3_TACH"}, + {FAN4_TACH,"FAN4_TACH"}, +}; + + + +uint32_t HWConfigurationFunc(MessageContainer* requestContainer) +{ + uint32_t status = 0; + int Motor_i, Dancer_i, Dispenser_i,PID_i; + MessageContainer responseContainer; + UploadHardwareConfigurationResponse response = UPLOAD_HARDWARE_CONFIGURATION_RESPONSE__INIT; + + UploadHardwareConfigurationRequest* UploadRequest = upload_hardware_configuration_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + HardwareConfiguration *request = UploadRequest->hardwareconfiguration; + status += InternalWinderConfigMessage(request->winders); + for (Motor_i = 0; Motor_i < request->n_motors ; Motor_i++) + status += MotorsConfigMessage(request->motors[Motor_i]); + for (Dancer_i = 0; Dancer_i < request->n_dancers ; Dancer_i++) + status += DancerConfigMessage(request->dancers[Dancer_i]); + for (PID_i = 0; PID_i < request->n_pidcontrols ; PID_i++) + status += HeaterConfigRequestMessage(request->pidcontrols[PID_i]); + for (Dispenser_i = 0; Dispenser_i < request->n_dispensers ; Dispenser_i++) + status += DispenserConfigMessage(request->dispensers[Dispenser_i]); + //status += HeaterConfigSetSharedHeatersParams (request->outputproportionalcycletime, request->outputproportionalsinglestep); + + + + + responseContainer = createContainer(MESSAGE_TYPE__UploadHardwareConfigurationResponse, requestContainer->token, true, &response, &upload_hardware_configuration_response__pack, &upload_hardware_configuration_response__get_packed_size); + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); + + return OK; + + + +} diff --git a/Software/Embedded_SW/Embedded/Modules/General/GeneralHardware.h b/Software/Embedded_SW/Embedded/Modules/General/GeneralHardware.h new file mode 100644 index 000000000..ab55c3e57 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/General/GeneralHardware.h @@ -0,0 +1,313 @@ +#ifndef GENERALHARDWARE_H +#define GENERALHARDWARE_H + +#include "include.h" +#include +#include "PMR/common/MessageContainer.pb-c.h" +#include "Modules/Stubs_Handler/Container.h" + +typedef enum +{ + ANALOG_MIXCHIP_TEMP, + AN_DYEINGH_CURSEN_1, + AN_DYEINGH_CURSEN_2, + AN_DYEINGH_CURSEN_3, + AN_DYEINGH_CURSEN_4, + AN_DYEINGH_CURSEN_5, + ANALOG_DYEINGH_TEMP1, + ANALOG_DYEINGH_TEMP2, + ANALOG_DYEINGH_TEMP3, + ANALOG_DYEINGH_TEMP4, + ANALOG_DYEINGH_TEMP5, + AN_DRYER_CURSEN1, + AN_DRYER_CURSEN2, + AN_DRYER_CURSEN3, + ANALOG_DRYER_TEMP1, + ANALOG_DRYER_TEMP2, + ANALOG_DRYER_TEMP3, + AN_ENCLOSURETEMP1, + AN_ENCLOSURETEMP2, + AN_ENCLOSURETEMP3, + AN_IDS_PRESSENS_1, + AN_IDS_PRESSENS_2, + AN_IDS_PRESSENS_3, + AN_IDS_PRESSENS_4, + AN_IDS_PRESSENS_5, + AN_IDS_PRESSENS_6, + AN_IDS_PRESSENS_7, + AN_IDS_PRESSENS_8, + AN_MIDTANK_PRESSENS1, + AN_MIDTANK_PRESSENS2, + AN_MIDTANK_PRESSENS3, + AN_MIDTANK_PRESSENS4, + AN_MIDTANK_PRESSENS5, + AN_MIDTANK_PRESSENS6, + AN_MIDTANK_PRESSENS7, + AN_MIXCHIP_CURSENn, + AN5V_LDANCER1, + AN5V_LDANCER2, + AN5V_RDANCER, + AN10V_SPARE1, + AN10V_SPARE2, + AN_AIRPRESS_1, + AN_AIRPRESS_2, + AN_VOCSENS, + AN_BLOWERCTRL, + LS_DH_LID_CLEANING, + LS_DH_LID_CLOSED, + LS_DH_CLEAN_UP, + LS_DH_CLEAN_RIGHT, + LS_DH_SPARE1, + LS_DH_LID_OPEN, + LS_DH_CLEAN_DOWN, + LS_DH_CLEAN_LEFT, + LS_DRYER_LID_OPEN, + LS_DRYER_SPARE3, + LS_DRYER_LID_CLOSED, + LS_DRYER_SPARE4, + LS_DRYER_SPARE1, + LS_LOADARM_RIGHT, + LS_DRYER_SPARE2, + LS_LOADARM_LEFT, + GPI_PS1_DC_OK, + GPI_PANSW2, + GPI_PANSW4, + GPI_PANSW1, + GPI_PANSW3, + GPI_PANSW5, + GPI_PANSW6, + GPI_TACTSW1, + GPI_TACTSW3, + GPI_PWRBUTTON, + GPI_TACTSW2, + GPI_TACTSW4, + GPI_EXTWINDER_1, + GPI_EXTWINDER_2, + GPI_EXTWINDER_3, + GPI_EXTWINDER_1_rtn, + GPI_EXTWINDER_2_rtn, + GPI_EXTWINDER_3_rtn, + LS_DISPENSER_UP_1, + LS_DISPENSER_25_1, + LS_DISPENSER_75_1, + LS_DISPENSER_UP_3, + LS_DISPENSER_25_3, + LS_DISPENSER_75_3, + LS_DISPENSER_UP_5, + LS_DISPENSER_25_5, + LS_DISPENSER_75_5, + LS_DISPENSER_UP_7, + LS_DISPENSER_25_7, + LS_DISPENSER_75_7, + LS_DISPENSER_DOWN_1, + LS_DISPENSER_50_1, + LS_DISPENSER_SPARE_1, + LS_DISPENSER_DOWN_3, + LS_DISPENSER_50_3, + LS_DISPENSER_SPARE_3, + LS_DISPENSER_DOWN_5, + LS_DISPENSER_50_5, + LS_DISPENSER_SPARE_5, + LS_DISPENSER_DOWN_7, + LS_DISPENSER_50_7, + LS_DISPENSER_SPARE_7, + LS_DISPENSER_UP_2, + LS_DISPENSER_25_2, + LS_DISPENSER_75_2, + LS_DISPENSER_UP_4, + LS_DISPENSER_25_4, + LS_DISPENSER_75_4, + LS_DISPENSER_UP_6, + LS_DISPENSER_25_6, + LS_DISPENSER_75_6, + LS_DISPENSER_UP_8, + LS_DISPENSER_25_8, + LS_DISPENSER_75_8, + LS_RLOADMOTOR_UP, + LS_DISPENSER_DOWN_2, + LS_DISPENSER_50_2, + LS_DISPENSER_SPARE_2, + LS_DISPENSER_DOWN_4, + LS_DISPENSER_50_4, + LS_DISPENSER_SPARE_4, + LS_DISPENSER_DOWN_6, + LS_DISPENSER_50_6, + LS_DISPENSER_SPARE_6, + LS_DISPENSER_DOWN_8, + LS_DISPENSER_50_8, + LS_DISPENSER_SPARE_8, + LS_SCREW_LEFT, + SW_SPOOL_EXISTS, + LS_SCREW_RIGHT, + SW_SPARE, + LS_LDANCER1_DOWN, + LS_LDANCER2_DOWN, + LS_LPIVOT_DOWN, + LS_PIVOT_SPARE1, + LS_LDANCER1_UP, + LS_LDANCER2_UP, + LS_LPIVOT_UP, + LS_PIVOT_SPARE2, + LS_LLOADMOTOR_DOWN, + LS_LSPARE1, + LS_LLOADMOTOR_UP, + LS_LSPARE2, + LS_RDANCER_DOWN, + LS_RLOADRAM_DOWN, + LS_RDANCER_UP, + LS_RLOADRAM_UP, + LS_RLOADMOTOR_DOWN, + GPI_TFEED_BREAK_1, + GPI_TFEED_BREAK_2, + LS_RSPARE1, + LS_SPARE2_1, + LS_SPARE2_3, + LS_SPARE1_1, + LS_SPARE1_3, + LS_RSPARE2, + LS_SPARE2_2, + LS_SPARE2_4, + LS_SPARE1_2, + LS_SPARE1_4, + GPI_WCONTAINER_WARN, + GPI_SW_WCONTAINER_PRES, + GPI_CHILLER_FAULT, + GPI_CHILLER_STAT1, + GPI_BLOWER_TACH, + GPI_WCONTAINER_FULL, + GPI_AIRFLOW_FLAP, + GPO_MIXCHIP_SSR4_CTRL, + GPO_DYEINGH_SSR7_CTRL, + GPO_DYEINGH_SSR8_CTRL, + GPO_DYEINGH_SSR5_CTRL, + GPO_DYEINGH_SSR6_CTRL, + GPO_DRYER_SSR3_CTRL, + GPO_DRYER_SSR1_CTRL, + GPO_DRYER_SSR2_CTRL, + GPO_SPARE_SSR12_CTRL, + GPO_SPARE_SSR13_CTRL, + GPO_PDOWN_RL1_CTRL, + GPO_LED1, + GPO_LED3, + GPO_LED2, + GPO_LED4, + GPO_BUZZER, + GPO_EXTWINDER_SSR11_CTRL, + GPO_EXTWINDER_1, + GPO_EXTWINDER_2, + GPO_EXTWINDER_3, + GPO_DILUTORPUMP_SSR10_CTRL, + GPO_WASTECH_PUMP1, + GPO_WASTECH_PUMP2, + GPO_TFEED_BREAK_1, + GPO_TFEED_BREAK_2, + GPO_SPARE1_1, + GPO_SPARE2_1, + GPO_SPARE1_2, + GPO_SPARE2_2, + GPO_BLOWER_PWM, + GPO_WHS_WTANKPUMP2, + GPO_CHILLER_SSR9_CTRL, + DH2, + DH1, + DRYER2, + DRYER1, + ELECTRICALENC, + USERPANEL, + EXTWINDINGUNIT, + DISPENSER_1, + DISPENSER_3, + DISPENSER_5, + DISPENSER_7, + MIDTANK3_1, + DISPENSER_2, + DISPENSER_4, + DISPENSER_6, + DISPENSER_8, + CART3, + CART1, + CART2, + CART4, + CART7, + CART5, + CART6, + CART8, + INTWINDINGUNIT, + LTFEEDUNIT2, + LTFEEDUNIT1, + RTFEEDUNIT2, + RTFEEDUNIT1, + SPARE2, + SPARE1, + WHS, + MIDTANK3_2, + MOTO_DH_CLEANHEAD, + MOTO_DH_CLEANMECH, + MOTO_DH_LID, + MOTO_DRYER_DRIVING, + MOTO_DRYER_LID, + MOTO_DRYER_LOADARM, + MOTO_DISPENSER_1, + MOTO_DISPENSER_2, + MOTO_DISPENSER_3, + MOTO_DISPENSER_4, + MOTO_DISPENSER_5, + MOTO_DISPENSER_6, + MOTO_DISPENSER_7, + MOTO_DISPENSER_8, + MOTO_SCREW, + MOTO_WINDER, + MOTO_LDANCER1, + MOTO_LDANCER2, + MOTO_LDRIVING, + MOTO_LLOADING, + MOTO_LPIVOT1, + MOTO_RDANCER, + MOTO_RDRIVING, + MOTO_RLOADARM, + MOTO_RLOADING, + MOTO_SPARE1_1, + MOTO_SPARE1_2, + MOTO_SPARE2_1, + MOTO_SPARE2_2, + DRYER_LOADARM_ROTENC, + DISPENSER_ROTENC1, + DISPENSER_ROTENC2, + DISPENSER_ROTENC3, + DISPENSER_ROTENC4, + DISPENSER_ROTENC5, + DISPENSER_ROTENC6, + DISPENSER_ROTENC7, + DISPENSER_ROTENC8, + SCREW_ROTENC, + LDANCER1_ROTENC2, + LDANCER2_ROTENC2, + LSPARE_ROTENC, + LSPARE_ROTENCn, + LSPARE1_ROTENC, + LSPARE2_ROTENC, + RDANCER_ROTENC2, + RSPARE_ROTENC, + RSPEEDSENS_ROTENC, + SPARE1_ROTENC, + SPARE2_ROTENC, + FAN_TACHO1, + FAN_TACHO3, + FAN_TACHO2, + FAN1_TACH, + FAN2_TACH, + FAN5_TACH, + FAN3_TACH, + FAN4_TACH, + MAX_PORT_ENUM +}SYSTEM_PORTS_ENUM; +typedef struct +{ + SYSTEM_PORTS_ENUM PortId; + char PortName[30]; +}PortInfoStruct; + +extern PortInfoStruct PortInfoTable[MAX_PORT_ENUM]; +extern uint32_t HWConfigurationFunc(MessageContainer* requestContainer); + +#endif diff --git a/Software/Embedded_SW/Embedded/Modules/General/process.c b/Software/Embedded_SW/Embedded/Modules/General/process.c new file mode 100644 index 000000000..f15c65f22 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/General/process.c @@ -0,0 +1,121 @@ +/* + * process.c + * + * Created on: 4 áîøõ 2018 + * Author: shlomo + */ +//******************************************************************************************************************** +#include "include.h" +#include "process.h" + +#include +#include "heaters/heaters_ex.h" +#include "PMR/Printing/UploadProcessParametersRequest.pb-c.h" +#include "PMR/Printing/UploadProcessParametersResponse.pb-c.h" +#include "PMR/Hardware/HardwarePidControlType.pb-c.h" +#include "PMR/common/MessageContainer.pb-c.h" + +void ProcessRequestFunc(MessageContainer* requestContainer) +{ + MessageContainer responseContainer; + uint8_t* container_buffer; + uint32_t status = 0; + + UploadProcessParametersRequest* request = upload_process_parameters_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + ProcessParameters* ProcessParams = request->processparameters; + + + UploadProcessParametersResponse response = UPLOAD_PROCESS_PARAMETERS_RESPONSE__INIT; + + responseContainer = createContainer(MESSAGE_TYPE__UploadProcessParametersResponse, requestContainer->token, true, &response, &upload_process_parameters_request__pack, &upload_process_parameters_request__get_packed_size); + container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + + + /* + * + * uint32_t HeaterCommandRequestMessage(int HeaterId, bool OnOff, int Temperature) + * + struct _ProcessParameters +{ + protobuf_c_boolean has_dyeingspeed; + double dyeingspeed; + protobuf_c_boolean has_dryerbufferlength; + double dryerbufferlength; + protobuf_c_boolean has_mininkuptake; + double mininkuptake; + protobuf_c_boolean has_feedertension; + double feedertension; + protobuf_c_boolean has_pullertension; + double pullertension; + protobuf_c_boolean has_windertension; + double windertension; + protobuf_c_boolean has_headairflow; + double headairflow; + protobuf_c_boolean has_dryerairflow; + double dryerairflow; + protobuf_c_boolean has_tableindex; + int32_t tableindex; +}; + + + */ + if (ProcessParams->has_mixertemp) + { + if(ProcessParams->mixertemp) + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__MixerHeater, true, ProcessParams->mixertemp); + else + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__MixerHeater, false, ProcessParams->mixertemp); + } + if (ProcessParams->has_headzone1temp) + { + if(ProcessParams->headzone1temp) + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__HeadHeaterZ1, true, ProcessParams->headzone1temp); + else + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__HeadHeaterZ1, false, ProcessParams->headzone1temp); + } + if (ProcessParams->has_headzone2temp) + { + if(ProcessParams->headzone2temp) + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__HeadHeaterZ2, true, ProcessParams->headzone2temp); + else + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__HeadHeaterZ2, false, ProcessParams->headzone2temp); + } + if (ProcessParams->has_headzone3temp) + { + if(ProcessParams->headzone3temp) + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__HeadHeaterZ3, true, ProcessParams->headzone3temp); + else + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__HeadHeaterZ3, false, ProcessParams->headzone3temp); + } + if (ProcessParams->has_dryerzone1temp) + { + if(ProcessParams->dryerzone1temp) + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w, true, ProcessParams->dryerzone1temp); + else + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w, false, ProcessParams->dryerzone1temp); + } + if (ProcessParams->has_dryerzone2temp) + { + if(ProcessParams->dryerzone2temp) + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1, true, ProcessParams->dryerzone2temp); + else + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1, false, ProcessParams->dryerzone2temp); + } + if (ProcessParams->has_dryerzone3temp) + { + if(ProcessParams->dryerzone3temp) + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2, true, ProcessParams->dryerzone3temp); + else + status |= HeaterCommandRequestMessage(HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2, false, ProcessParams->dryerzone3temp); + } + + if (status) + { + responseContainer.has_error = true; + responseContainer.error = (ErrorCode)status; + } + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} diff --git a/Software/Embedded_SW/Embedded/Modules/General/process.h b/Software/Embedded_SW/Embedded/Modules/General/process.h new file mode 100644 index 000000000..aa7b157a2 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/General/process.h @@ -0,0 +1,16 @@ +/* + * process.h + * + * Created on: 4 áîøõ 2018 + * Author: shlomo + */ + +#ifndef MODULES_GENERAL_PROCESS_H_ +#define MODULES_GENERAL_PROCESS_H_ + + +void ProcessRequestFunc(MessageContainer* requestContainer); + + + +#endif /* MODULES_GENERAL_PROCESS_H_ */ diff --git a/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters.h b/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters.h new file mode 100644 index 000000000..beaf32b2a --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters.h @@ -0,0 +1,62 @@ +#include "PMR/Hardware/HardwarePidControl.pb-c.h" +#include "PMR/Hardware/HardwarePidControlType.pb-c.h" +/******************** DEFINITIONS ********************************************/ +#define MAX_AC_HEATERS HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2+1 +#define MAX_TIMESLICES 200 +#define MAX_HEATERS_NUM HARDWARE_PID_CONTROL_TYPE__MixerHeater+1 +#define MAX_HEATERS_TEMPERATURE 300 + +extern uint32_t OutputProportionalSingleStep; //A/C Heaters step size from one decision point to another - in cpu clocks. 120000 = 1 millisecod +extern uint32_t OutputProportionalCycleTime; //A/C Heaters Cycle time in milliseconds - one for all heaters +//extern uint32_t Heater_timerBase; //Timer handle +extern char TimeSliceAllocation[MAX_TIMESLICES]; +extern int NumberOFSlicesInUse; + + +typedef struct HeaterPIDControlConfigstruc +{ + int id; //HardwarePidControlType + char name[20]; + int32_t outputproportionalpowerlimit; + int32_t outputproportionalband; + int32_t integraltime; + int32_t derivativetime; + int32_t sensorcorrectionadjustment; + int32_t sensortypeandsetpointlimits; + int32_t setpointramprateorsoftstartramp; + int32_t setpointcontroloutputrate; + int32_t controloutputtype; + int32_t ssrcontroloutputtype; + int32_t outputonoffhysteresisvalues; + int32_t processvariablesamplingrate; + int32_t pvinputfilterfactormode; + double kp; + double ki; + double kd; +}HeaterPIDControlConfig; + +typedef struct HeaterCommandstruc +{ + int heaterid; //HardwarePidControlType + bool command; + uint32_t targettemperatue; +}HeaterCommand; + +typedef struct +{ + bool m_isEnabled; + uint32_t m_SetParam; + uint32_t m_mesuredParam; + float m_preError; + float m_integral; + float m_calculatedError; + bool m_isReady; + PID_Config_Params m_params; +}HeaterControlConfig_t; + +extern HeaterPIDControlConfig HeaterControl[MAX_HEATERS_NUM]; +extern HeaterControlConfig_t HeaterPIDConfig[MAX_HEATERS_NUM]; +extern HeaterCommand HeaterCmd[MAX_HEATERS_NUM]; +extern uint32_t DeviceId2Heater[MAX_HEATERS_NUM]; + + diff --git a/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_bit.c b/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_bit.c new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_ex.h b/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_ex.h new file mode 100644 index 000000000..b5249d302 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_ex.h @@ -0,0 +1,9 @@ +#include "PMR/common/MessageContainer.pb-c.h" +#include "PMR/Hardware/HardwarePidControl.pb-c.h" + +//uint32_t HeaterCommandRequestMessage(MessageContainer* requestContainer); +uint32_t HeaterConfigRequestMessage(HardwarePidControl* request); +uint32_t HeaterConfigSetSharedHeatersParams (uint32_t outputproportionalcycletime, uint32_t outputproportionalsinglestep); + +uint32_t HeaterCommandRequestMessage(int HeaterId, bool OnOff, int Temperature); + diff --git a/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_init.c b/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_init.c new file mode 100644 index 000000000..55da2ecfa --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_init.c @@ -0,0 +1,154 @@ +/************************************************************************************************************************ + * Heaters_init.c + **************************************************************************************************************************/ + +////////////////////////////////State machine operation//////////////////////////////////// +//the state machine operation is used to operate in runtime correct profile flow execution +//by recieved esign flow of the user from the UI +/////////////////////////////////////////////////////////////////////////////////////////// +#include "include.h" + +#include +//#include "PMR/Hardware/PIDControlConfig.pb-c.h" +//#include "PMR/Hardware/PIDCluster.pb-c.h" +//#include "PMR/Hardware/HeaterControl.pb-c.h" +//#include "PMR/Hardware/HeaterCommandRequest.pb-c.h" +//#include "PMR/Hardware/HeaterCommandRequest.pb-c.h" +#include "PMR/Hardware/HardwarePidControl.pb-c.h" +#include "PMR/Hardware/HardwarePidControlType.pb-c.h" +#include "PMR/common/MessageContainer.pb-c.h" + +#include "../control/control.h" +#include "../control/pidalgo.h" +#include "include.h" +#include + +#include "heaters.h" +#include "Drivers/Heater/Heater.h" + + + +/******************** STRUCTURES AND ENUMs ********************************************/ +typedef enum { + HeatersInitialState, + HeatersInit, + HeatersControlledOp, + HeatersShutdown, + HeatersTest, + MaxHeatersStates +}HEATERS_STATES_ENUM; +typedef enum { + HeatersCold, + HeatersAtPIDStrip, + HeatersOverHeat, + HeatersOnTest +}HEATERS_EVENTS_ENUM; + +/******************** GLOBAL PARAMETERS ********************************************/ +HeaterPIDControlConfig HeaterControl[MAX_HEATERS_NUM] = {0}; +HeaterControlConfig_t HeaterPIDConfig[MAX_HEATERS_NUM] = {0}; +uint32_t DeviceId2Heater[MAX_HEATERS_NUM] = {0}; +bool AcHeaterConfigured[MAX_AC_HEATERS] = {0}; + +/******************** CODE ********************************************/ +/* + * HeatersInit + * called by: General Hardware Init + * initialized all global data + */ +uint32_t Heaters_Init(void) +{ + return OK; +} + + +uint32_t HeaterConfigRequestMessage(HardwarePidControl* request) +{ + //uint32_t status = OK; + HardwarePidControlType HeaterId; + + HeaterId = request->hardwarepidcontroltype; + int ValidationError = 0; + + if ((HeaterId)&&(HeaterId< MAX_HEATERS_NUM)) + { + HeaterControl[HeaterId].id = HeaterId; + //strncpy (HeaterControl[HeaterId].name, request->name, 20); + HeaterControl[HeaterId].outputproportionalpowerlimit = request->outputproportionalpowerlimit; + HeaterControl[HeaterId].outputproportionalband = request->outputproportionalband; + HeaterControl[HeaterId].integraltime = request->integraltime; + HeaterControl[HeaterId].derivativetime = request->derivativetime; + HeaterControl[HeaterId].sensorcorrectionadjustment = request->sensorcorrectionadjustment; + //HeaterControl[HeaterId].sensortypeandsetpointlimits = request->sensortypeandsetpointlimits; + HeaterControl[HeaterId].setpointramprateorsoftstartramp = request->setpointramprateorsoftstartramp; + HeaterControl[HeaterId].setpointcontroloutputrate = request->setpointcontroloutputrate; + HeaterControl[HeaterId].controloutputtype = request->controloutputtype; + HeaterControl[HeaterId].ssrcontroloutputtype = request->ssrcontroloutputtype; + HeaterControl[HeaterId].outputonoffhysteresisvalues = request->outputonoffhysteresisvalue; + HeaterControl[HeaterId].processvariablesamplingrate = request->processvariablesamplingrate; + HeaterControl[HeaterId].pvinputfilterfactormode = request->pvinputfilterfactormode; + + if (HeaterId < MAX_AC_HEATERS) + AcHeaterConfigured[HeaterId] = true; + + //check if all A/C heaters are defined. if they are - validate the configuration + if (HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w].id + &&HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1].id + &&HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2].id) + { + if (HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w].outputproportionalpowerlimit + + HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1].outputproportionalpowerlimit + + HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2].outputproportionalpowerlimit> 100) + ValidationError += 2; + if (ValidationError) + { + LOG_ERROR (ValidationError, "Validation Error in Heaters Control"); + return ERROR; + } + } + return OK; + } + return ERROR; + +} + +/* + * HeaterConfigSetSharedHeatersParams - prepare the time slices for A/C heaters co-ordinated operation + * called by the general hardware HWConfigurationFunc + * parameters - the cycle time for the coordinated operation, the size (in MCU cycles) of a single step. + */ +uint32_t HeaterConfigSetSharedHeatersParams(uint32_t outputproportionalcycletime, uint32_t outputproportionalsinglestep) +{ + int Slice_i; + int Heater1000Slices,Heater200aSlices /*,Heater200bSlices Currently both 200W heaters will work together*/; + + //A/C Heaters Cycle time in milliseconds - one for all heaters + OutputProportionalCycleTime = outputproportionalcycletime; + + //A/C Heaters step size from one decision point to another - in cpu clocks. 120000 = 1 millisecod + OutputProportionalSingleStep = outputproportionalsinglestep; + + // calculate how many milliseconds is in each operating cycle (should be an integer number) + uint32_t MillisecondsPerChange = OutputProportionalSingleStep/120000; + + // calculate how many time slices are used. the total cycle time / the length of one operating cycle. (one added to put a time gap??? TBD) + NumberOFSlicesInUse = (OutputProportionalCycleTime/MillisecondsPerChange); + + if (NumberOFSlicesInUse > MAX_TIMESLICES ) + { + LOG_ERROR (NumberOFSlicesInUse, "NumberOFSlicesInUse too high"); + return ERROR;//NumberOFSlicesInUse = MAX_TIMESLICES; + } + + // all numbers are rounded down. better to have carefully calculated numbers + Heater1000Slices = HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w].outputproportionalpowerlimit * NumberOFSlicesInUse / 100; + Heater200aSlices = HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1].outputproportionalpowerlimit * NumberOFSlicesInUse / 100; + + //mark the time slices for heaters operation as empty / Heater1000 / Heater 200 + memset (TimeSliceAllocation,0xFF,sizeof(TimeSliceAllocation)); + for (Slice_i = 0; Slice_i < Heater1000Slices;Slice_i++ ) TimeSliceAllocation[Slice_i] = HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w; + for (Slice_i = Heater1000Slices; Slice_i < Heater1000Slices+Heater200aSlices;Slice_i++ ) TimeSliceAllocation[Slice_i] = HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1; + + return OK; + +} diff --git a/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_maint.c b/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_maint.c new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_print.c b/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_print.c new file mode 100644 index 000000000..3eeff9ec3 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Heaters/Heaters_print.c @@ -0,0 +1,247 @@ +/************************************************************************************************************************ + * Heaters_print.c + **************************************************************************************************************************/ + +////////////////////////////////State machine operation//////////////////////////////////// +//the state machine operation is used to operate in runtime correct profile flow execution +//by recieved esign flow of the user from the UI +/////////////////////////////////////////////////////////////////////////////////////////// +#include "include.h" + +#include +//#include "PMR/Hardware/PIDCluster.pb-c.h" +#include "PMR/Hardware/HardwarePidControlType.pb-c.h" +#include "PMR/Hardware/HardwarePidControl.pb-c.h" +#include "PMR/common/MessageContainer.pb-c.h" + +#include "../control/control.h" +#include "../control/pidalgo.h" +#include "include.h" +#include + +#include "heaters.h" +#include "Drivers/Heater/Heater.h" + + +/******************** GLOBAL PARAMETERS ********************************************/ +HeaterCommand HeaterCmd[MAX_HEATERS_NUM] = {}; +int NumberOFSlicesInUse = 0; +bool HeatersRestart = false; + +uint32_t OutputProportionalSingleStep = 0; //A/C Heaters step size from one decision point to another - in cpu clocks. 120000 = 1 millisecod +uint32_t Heater_timerBase = TIMER2_BASE; //Timer handle +uint32_t OutputProportionalCycleTime = 0; //A/C Heaters Cycle time in milliseconds - one for all heaters +char TimeSliceAllocation[MAX_TIMESLICES] = {0}; + +bool InitialHeatingState = false; +/******************** FUNCTIONS ********************************************/ +uint32_t HeaterControlCBFunction(uint32_t deviceID, uint32_t ReadValue); +uint32_t PrepareHeater(int HeaterId, uint32_t SetTemperatue); + +/* + * HeaterCommandRequestMessage + * called by: Communication from host + * initialized all global data + */ +uint32_t HeaterCommandRequestMessage(int HeaterId, bool OnOff, int Temperature) +{ + //uint32_t status = NOT_SUPPORTED; + //MessageContainer responseContainer; + if ((HeaterId)&&(HeaterId< MAX_HEATERS_NUM)) + { + if (HeaterControl[HeaterId].id != HeaterId) // heater configuration missing + { + LOG_ERROR (HeaterId, "Heater is not yet configured"); + return ERROR; + } + HeaterCmd[HeaterId].heaterid = HeaterId; + HeaterCmd[HeaterId].command = OnOff; + HeaterCmd[HeaterId].targettemperatue = Temperature; + } + bool HeaterState = GetHeaterState(HeaterId); + + if ((HeaterState == HEATER_OFF)&& (OnOff == HEATER_ON)) //start heating + { + //set the heater control parameters + //set the target operation temperature + //start the control + PrepareHeater(HeaterId,Temperature); //prepare the heaters control info + //set the power balance handler (if not set yet) + ROM_TimerConfigure(Heater_timerBase, TIMER_CFG_PERIODIC); // 32 bits Timer + ROM_IntEnable(INT_TIMER2B); + ROM_TimerIntEnable(Heater_timerBase, TIMER_TIMA_TIMEOUT); + // if the heater is off (?) start it. + ActivateHeater(HeaterId); + //set the heater operation mode to fast heating - depended on the current temperature + // timers are prepared but not started yet!!! only when the system is hot. + + } + else if ((HeaterState == HEATER_ON)&& (OnOff == HEATER_ON)) //set temperature + { + HeaterPIDConfig[HeaterId].m_SetParam = Temperature; + // if the heater is not on return (?). + //set the target operation temperature + //set the heater operation mode to fast heating - depended on the current temperature + } + else if ((HeaterState == HEATER_ON)&& (OnOff == HEATER_OFF)) //stop heating + { + //turn off the heater + //stop the control + HeaterPIDConfig[HeaterId].m_SetParam = HeaterId; + } + else + { + LOG_ERROR (OnOff, "unsupported command id"); + return ERROR; + } + + return OK; +} +/* + * PrepareHeater + * called by: Communication from host + * initialized all global data + */ +uint32_t PrepareHeater(int HeaterId, uint32_t SetTemperatue) +{ + assert(HeaterId < MAX_HEATERS_NUM); + assert(SetTemperatue < MAX_HEATERS_TEMPERATURE); + + //start thread control for all motors + HeaterPIDConfig[HeaterId].m_params.MAX = HeaterControl[HeaterId].outputproportionalpowerlimit; + HeaterPIDConfig[HeaterId].m_params.MIN = .0; + HeaterPIDConfig[HeaterId].m_params.Kd = HeaterControl[HeaterId].kd; + HeaterPIDConfig[HeaterId].m_params.Kp = HeaterControl[HeaterId].kp; + HeaterPIDConfig[HeaterId].m_params.Ki = HeaterControl[HeaterId].ki; + HeaterPIDConfig[HeaterId].m_params.dt = eHunderdMillisecond; + HeaterPIDConfig[HeaterId].m_calculatedError = 0; + HeaterPIDConfig[HeaterId].m_integral = 0; + HeaterPIDConfig[HeaterId].m_isEnabled = true; + HeaterPIDConfig[HeaterId].m_isReady = true; + HeaterPIDConfig[HeaterId].m_mesuredParam = 0; + HeaterPIDConfig[HeaterId].m_preError = 0; + HeaterPIDConfig[HeaterId].m_SetParam = SetTemperatue;//need to update SetParams on presegment stage + AddControlCallback(DeviceId2Heater[HeaterId], HeaterControlCBFunction, eHunderdMillisecond); + + return OK; +} + +/* + * HeaterControlCBFunction + * called by: Communication from host + * initialized all global data + */ + +uint32_t HeaterControlCBFunction(uint32_t deviceID, uint32_t ReadValue) +{ + int i,index=MAX_HEATERS_NUM; + char str[100]; + uint8_t len = 0; + + for (i=0;i (HeaterCmd[index].targettemperatue * (1+HeaterControl[index].outputproportionalband))) + { + //Heaters OFF until coming into the proportional band + len = usnprintf(str, 100, "\r\n HeaterControlCBFunction devId %d temp %d over proportional band %d of set temp %d " + ,index, ReadValue,HeaterControl[index].outputproportionalband,HeaterCmd[index].targettemperatue); + Report(str, __FILE__,__LINE__,0, RpMessage, index, deviceID); + return OK; + } + if (ReadValue < (HeaterCmd[index].targettemperatue * (1-HeaterControl[index].outputproportionalband))) + { + len = usnprintf(str, 100, "\r\n HeaterControlCBFunction devId %d temp %d below proportional band %d of set temp %d " + ,index, ReadValue,HeaterControl[index].outputproportionalband,HeaterCmd[index].targettemperatue); + Report(str, __FILE__,__LINE__,0, RpMessage, index, deviceID); + //Heaters ON until coming into the proportional band + return OK; + } + + if(HeaterPIDConfig[index].m_isEnabled && (HeaterPIDConfig[index].m_SetParam != 0)) + { + HeaterPIDConfig[index].m_mesuredParam = ReadValue; + HeaterPIDConfig[index].m_calculatedError = PIDAlgorithmCalculation(HeaterPIDConfig[index].m_SetParam , HeaterPIDConfig[index].m_mesuredParam, + &HeaterPIDConfig[index].m_params, &HeaterPIDConfig[index].m_preError, &HeaterPIDConfig[index].m_integral); + if (HeaterPIDConfig[index].m_calculatedError >= HeaterPIDConfig[index].m_params.MAX) + { + HeaterPIDConfig[index].m_calculatedError = HeaterPIDConfig[index].m_params.MAX; + } + if (HeaterPIDConfig[index].m_calculatedError < HeaterPIDConfig[index].m_params.MIN) + { + HeaterPIDConfig[index].m_calculatedError = HeaterPIDConfig[index].m_params.MIN; + } + + //SetMotorFreq (index, HeaterControl[index].m_calculatedError); + } + + return OK; +} + +/* + * EightMilliSecondHeatersInterrupt - a timer based interrupt, that will handle the time sharing between the A/C heaters + * There is a need to prevent the system from activating all A/C heaters at the same time, due to electrical current problems + */ +int SliceCounter = 0; +void EightMilliSecondHeatersInterrupt(UArg arg0) +{ + char str[100]; + uint8_t len = 0; + + len = usnprintf(str, 100, "\r\n EightMilliSecondHeatersInterrupt SliceCounter %d Owner %d H1000 %d H2000 %d" + ,SliceCounter,TimeSliceAllocation[SliceCounter],HeatersRestart,NumberOFSlicesInUse); + Report(str, __FILE__,__LINE__,0, RpMessage, SliceCounter, TimeSliceAllocation[SliceCounter]); + ROM_IntMasterDisable(); + + if (TimeSliceAllocation[SliceCounter] == HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w) + { + //If HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w should be active + //Activate HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w + ActivateHeater (HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w); + //DeActivate HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1 + DeActivateHeater (HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1); + DeActivateHeater (HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2); + } + else if (TimeSliceAllocation[SliceCounter] == HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1) + { + //DeActivate HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w + DeActivateHeater (HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w); + //If HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1 should be active + //Activate HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1 + ActivateHeater (HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1); + ActivateHeater (HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2); + } + else + { + //DeActivate HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w + DeActivateHeater (HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w); + //DeActivate HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1 + DeActivateHeater (HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1); + DeActivateHeater (HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2); + } + //handle the time sharing module + SliceCounter++; + if (SliceCounter >= NumberOFSlicesInUse) + SliceCounter = 0; + + if (HeatersRestart == true) + { + ROM_TimerLoadSet(Heater_timerBase, TIMER_BOTH,OutputProportionalSingleStep/*twelve millisecond???*/); + } + + ROM_TimerIntClear(Heater_timerBase, TIMER_TIMA_TIMEOUT); // Clear the timer interrupt + // + // Enable all interrupts. + // + ROM_IntMasterEnable(); + return ; +} diff --git a/Software/Embedded_SW/Embedded/Modules/IDS/IDS.h b/Software/Embedded_SW/Embedded/Modules/IDS/IDS.h new file mode 100644 index 000000000..1c9fee547 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/IDS/IDS.h @@ -0,0 +1,25 @@ +#include "PMR/common/MessageContainer.pb-c.h" +#include "PMR/Hardware/HardwareDispenser.pb-c.h" + +#define MAX_SYSTEM_DISPENSERS 8 +typedef struct +{ + int32_t dispensercapacity; //milliliters + int32_t midtankcapacity;//milliliters + double nlperpulse; //nanoliter per step , uStep = 1 + uint32_t minfrequency; + uint32_t maxfrequency; + uint32_t minmicrostep; + uint32_t maxmicrostep; + double correctiongain; + double ratiotodryerspeed; + double kp; + double ki; + double kd; + double changeslope; + double highlengthmicrosecond; + int32_t controltiming; //10-100-1000 milliseconds + int32_t id; +}DispenserConfigStruc; + +uint32_t DispenserConfigMessage(HardwareDispenser * request); diff --git a/Software/Embedded_SW/Embedded/Modules/IDS/IDS_BIT.c b/Software/Embedded_SW/Embedded/Modules/IDS/IDS_BIT.c new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/IDS/IDS_ex.h b/Software/Embedded_SW/Embedded/Modules/IDS/IDS_ex.h new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/IDS/IDS_init.c b/Software/Embedded_SW/Embedded/Modules/IDS/IDS_init.c new file mode 100644 index 000000000..0294615b6 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/IDS/IDS_init.c @@ -0,0 +1,46 @@ +/************************************************************************************************************************ + **************************************************************************************************************************/ + +#include "include.h" + +#include + +#include "ids.h" +#include "PMR/common/MessageContainer.pb-c.h" +#include "PMR/Hardware/HardwareDispenser.pb-c.h" + + +DispenserConfigStruc DispensersCfg[ MAX_SYSTEM_DISPENSERS]; + + + +uint32_t DispenserConfigMessage(HardwareDispenser * request) +{ + uint32_t status = PASSED; + int Dispenser_i; + + Dispenser_i = request->hardwaredispensertype; + if ((Dispenser_i)&&(Dispenser_i< MAX_SYSTEM_DISPENSERS)) + { + + DispensersCfg[Dispenser_i].id = request->hardwaredispensertype; + DispensersCfg[Dispenser_i].minfrequency = request->minfrequency; + DispensersCfg[Dispenser_i].maxfrequency = request->maxfrequency; + DispensersCfg[Dispenser_i].minmicrostep = request->minmicrostep; + DispensersCfg[Dispenser_i].maxmicrostep = request->maxmicrostep; + DispensersCfg[Dispenser_i].correctiongain = request->correctiongain; + DispensersCfg[Dispenser_i].ratiotodryerspeed = request->ratiotodryerspeed; + DispensersCfg[Dispenser_i].kp = request->kp; + DispensersCfg[Dispenser_i].ki = request->ki; + DispensersCfg[Dispenser_i].kd = request->kd; + DispensersCfg[Dispenser_i].changeslope = request->changeslope; + DispensersCfg[Dispenser_i].highlengthmicrosecond = request->highlengthmicrosecond; + DispensersCfg[Dispenser_i].dispensercapacity= request->capacity; +// DispensersCfg[Dispenser_i].midtankcapacity = request->midtankcapacity; + DispensersCfg[Dispenser_i].nlperpulse = request->nlperpulse; + DispensersCfg[Dispenser_i].controltiming = request->controltiming; + return status; + } + else return Dispenser_i; + +} diff --git a/Software/Embedded_SW/Embedded/Modules/IDS/IDS_maint.c b/Software/Embedded_SW/Embedded/Modules/IDS/IDS_maint.c new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/IDS/IDS_print.c b/Software/Embedded_SW/Embedded/Modules/IDS/IDS_print.c new file mode 100644 index 000000000..32b147569 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/IDS/IDS_print.c @@ -0,0 +1,43 @@ +/************************************************************************************************************************ + * Ids_print.c + * Printing module is responsible for : + * operating diffrent winding algorithms with predefined parameters from the UI + * operating the dispensers according to predefined dispensing rate from the UI + **************************************************************************************************************************/ +#include "include.h" +#include "ids.h" +#include "../control/control.h" +#include "../control/pidalgo.h" +#include "PMR/Hardware/Hardwaremotor.pb-c.h" +#include "PMR/Hardware/HardwareDispenser.pb-c.h" +#include "StateMachines/Printing/printingSTM.h" + + + +/******************** STRUCTURES AND ENUMs ********************************************/ +/******************** GLOBAL PARAMETERS ********************************************/ + + +/* + * IDS Printing support + * Prepare: build pressure in all participating dispensers + * Print - dispense ink to the printing head + * stop - stop dispensing + * + * control processes: + * on prepare stage - each 10msec against the pressure sensors + * on print stage - every 10/100 msec against the speed sensor + * + * */ +//Dispenser Pressure control +//callback - calls printing stm with the result + +// registration - 10 msec, dispenser pressure sensor +// AddControlCallback(DeviceId2Heater[HeaterId], HeaterControlCBFunction, eHunderdMillisecond); +// start the dispenser pressure building - move up in a TBD speed, valve closed +//Dispenser Speed control +//callback - handles speed +// registration - 10msec, dispenser speed senseo +// start the dispensing - move up according to the segment defined speed and microstepping, valve opened +// + diff --git a/Software/Embedded_SW/Embedded/Modules/IDS/MixerHandler.c b/Software/Embedded_SW/Embedded/Modules/IDS/MixerHandler.c new file mode 100644 index 000000000..ce423ab72 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/IDS/MixerHandler.c @@ -0,0 +1,37 @@ +/* + * MixerHandle.c + * + * Created on: 26 áôáø× 2018 + * Author: shlomo + */ + +#ifndef MODULES_IDS_MIXERHANDLER_C_ +#define MODULES_IDS_MIXERHANDLER_C_ +#include "include.h" +#include "MixerHandler.h" +typedef enum +{ + MixerStateNone, + MixerStateHead, + MixerStateWaste +}MIXER_STATE_ENUM; + +MIXER_STATE_ENUM MixerState = MixerStateNone; + +uint32_t MixerHandlerSwitchToWaste(void) +{ + return OK; + +} +uint32_t MixerHandlerSwitchToHead(void) +{ + return OK; +} +uint32_t MixerHandlerGetState(void) +{ + return MixerState; +} + + + +#endif /* MODULES_IDS_MIXERHANDLER_C_ */ diff --git a/Software/Embedded_SW/Embedded/Modules/IDS/MixerHandler.h b/Software/Embedded_SW/Embedded/Modules/IDS/MixerHandler.h new file mode 100644 index 000000000..51093e1b7 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/IDS/MixerHandler.h @@ -0,0 +1,17 @@ +/* + * MixerHandle.h + * + * Created on: 26 áôáø× 2018 + * Author: shlomo + */ + +#ifndef MODULES_IDS_MIXERHANDLER_H_ +#define MODULES_IDS_MIXERHANDLER_H_ + +extern uint32_t MixerHandlerSwitchToWaste(void); +extern uint32_t MixerHandlerSwitchToHead(void); +extern uint32_t MixerHandlerGetState(void); + + + +#endif /* MODULES_IDS_MIXERHANDLER_H_ */ diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Calculate.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Calculate.c new file mode 100644 index 000000000..f12b92adc --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Calculate.c @@ -0,0 +1,39 @@ + +#include +#include +#include +#include "include.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "drivers/twine_graphicslib/graphics_adapter.h" +#include "Container.h" + +void Stub_CalculateRequest(MessageContainer* requestContainer) +{ + MessageContainer responseContainer; + + CalculateRequest* request = calculate_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + writeLine("Calculate Request: "); + writeFloat(request->a); + writeString(" + "); + writeFloat(request->b); + + CalculateResponse response = CALCULATE_RESPONSE__INIT; + response.sum = request->a + request->b; + response.has_sum = true; + + responseContainer = createContainer(MESSAGE_TYPE__CalculateResponse, requestContainer->token, true, &response, &calculate_response__pack, &calculate_response__get_packed_size); + + writeLine("Sending Response: "); + writeFloat(response.sum); + + free(request); + + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Calculate.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Calculate.h new file mode 100644 index 000000000..0623435f0 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Calculate.h @@ -0,0 +1,8 @@ +#ifndef STUB_CALCULATE_H +#define STUB_CALCULATE_H + +#include "PMR/Common/MessageContainer.pb-c.h" +void Stub_CalculateRequest(MessageContainer* requestContainer); + +#endif //STUB_CALCULATE_H + diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Container.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Container.c new file mode 100644 index 000000000..b9c3ffbd0 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Container.c @@ -0,0 +1,125 @@ +#include +#include "include.h" +#include "driverlib/gpio.h" + +//#include "usb_serial_adapter.h" +//#include "graphics_adapter.h" +#include "Calculate.h" +#include "Progress.h" +#include "Stub_Cartridge.h" +#include "Stub_Dispenser.h" +#include "Stub_GPIO.h" +#include "Stub_Heater.h" +#include "Stub_MotorEncoder.h" +#include "Stub_OptLimitSwitch.h" +#include "Stub_SteperMotor.h" +#include "Stub_Valve.h" +#include "Stub_ExtFlash.h" +#include "General/GeneralHardware.h" +#include "heaters/heaters_ex.h" +#include "StateMachines/Printing/PrintingSTM.h" +#include "Modules/General/process.h" +#include "Common/report/report.h" + + +MessageContainer createContainer(MessageType type, char* token, protobuf_c_boolean completed, void* response, size_t (*packPtr)(void*, uint8_t*), size_t (*sizePtr)(void*)) +{ + MessageContainer container = MESSAGE_CONTAINER__INIT; + container.completed = completed; + container.token = token; + container.has_completed = true; + container.has_data = true; + container.has_type = true; + container.type = type; + + + + uint8_t* response_buffer = malloc((*sizePtr)(response)); + size_t response_size = (*packPtr)(response, response_buffer); + container.data.data = response_buffer; + container.data.len = response_size; + + free(response); + return container; +} + +void receive_callback(char* buffer, size_t length) +{ + //SendChars(buffer,length); + //draw_string(buffer, length); + //draw_image((uint8_t *)buffer); + + //writeLine("Received "); + //writeFloat(length); + //writeString(" bytes"); + //writeLine("Parsing message..."); + + MessageContainer* requestContainer = message_container__unpack(NULL, length, (uint8_t*)buffer); + + switch(requestContainer->type) + { + case MESSAGE_TYPE__CalculateRequest: + Stub_CalculateRequest(requestContainer); + break; + case MESSAGE_TYPE__ProgressRequest: + Stub_ProgressRequest(requestContainer); + break; + case MESSAGE_TYPE__StubCartridgeReadRequest: + Stub_CartridgeReadRequest(requestContainer); + break; + case MESSAGE_TYPE__StubCartridgeWriteRequest: + Stub_CartridgeWriteRequest(requestContainer); + break; + case MESSAGE_TYPE__StubDispenserRequest: + Stub_DispenserRequest(requestContainer); + break; + case MESSAGE_TYPE__StubGPIOInputSetupRequest: + Stub_GPIOInputSetupRequest(requestContainer); + break; + case MESSAGE_TYPE__StubGPIOReadBitRequest: + Stub_GPIOReadBitRequest(requestContainer); + break; + case MESSAGE_TYPE__StubGPIOReadByteRequest: + Stub_GPIOReadByteRequest(requestContainer); + break; + case MESSAGE_TYPE__StubGPIOWriteBitRequest: + Stub_GPIOWriteBitRequest(requestContainer); + break; + case MESSAGE_TYPE__StubGPIOWriteByteRequest: + Stub_GPIOWriteByteRequest(requestContainer); + break; + case MESSAGE_TYPE__StubHeaterRequest: + Stub_HeaterRequest(requestContainer); + break; + case MESSAGE_TYPE__StubMotorEncoderRequest: + Stub_MotorEncoderRequest(requestContainer); + break; + case MESSAGE_TYPE__StubOptLimitSwitchRequest: + Stub_OptLimitSwitchRequest(requestContainer); + break; + case MESSAGE_TYPE__StubSteperMotorRequest: + Stub_SteperMotorRequest(requestContainer); + break; + case MESSAGE_TYPE__StubValveRequest: + Stub_ValveRequest(requestContainer); + break; + case MESSAGE_TYPE__StubExtFlashReadRequest: + Stub_ExtFlashReadRequest(requestContainer); + break; + case MESSAGE_TYPE__StubExtFlashWriteRequest: + Stub_ExtFlashWriteRequest(requestContainer); + break; + case MESSAGE_TYPE__DebugLogRequest: + ReportInitMessage(requestContainer); + break; + case MESSAGE_TYPE__JobRequest: + JobRequestFunc(requestContainer); + break; + case MESSAGE_TYPE__UploadProcessParametersRequest: + ProcessRequestFunc(requestContainer); + break; + default: + //unsupported message type !! + break; + } +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Container.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Container.h new file mode 100644 index 000000000..2c5d9fa60 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Container.h @@ -0,0 +1,7 @@ +#ifndef CONTAINER_H +#define CONTAINER_H + +MessageContainer createContainer(MessageType type, char* token, protobuf_c_boolean completed, void* response, size_t (*packPtr)(void*, uint8_t*), size_t (*sizePtr)(void*)); +void receive_callback(char* buffer, size_t length); + +#endif //CONTAINER_H diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/DataDef.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/DataDef.h new file mode 100644 index 000000000..08da87c09 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/DataDef.h @@ -0,0 +1,71 @@ +#ifndef DATADEF_H +#define DATADEF_H + +#define EVALUATION_BOARD // to use the LCD only when using the evaluation board +#define USE_HIGH_SPEED_GPIO // to use AHB GPIO (A..J) ports A-J APB or AHB, ports K-Q on AHB only + +#define ON 1 +#define OFF 0 + +enum +{ + PASSED = 0, + FAILED = 1, + NOT_SUPPORTED = 254, + VERIFIED = 255 +}; + + +#define OK 0 +#define ERROR 1 + +#define ENABLE 0 +#define DISABLE 1 + +#define NEW 0 +#define USED 1 + +#define START 1 +#define STOP 0 + +// motor direction +#define CW 1 // clockwise +#define CCW 0 // counter clockwise + +#define TRUE 1 +#define FALSE 0 + +#define INPUT 1 +#define OUTPUT 0 + +#define PULLDOWN 0 +#define PULLUP 1 + +#define TX 0 +#define RX 1 +#define TXRX 2 + +//--------------------------------------------------------------------- +#pragma diag_suppress 169 /* Avoid warnings on VOID * conversions (protobuf issue) +The warning: +#169-D argument of type "size_t (*)(const CalculateResponse *, uint8_t *)" is incompatible with parameter of type "size_t (*)(void *, uint8_t *)" Calculate.c /twine_usblib_demo/PMR/Stubs line 53 C/C++ Problem + + +//#pragma diag_suppress 190 // Avoid the warning - #190-D enumerated type mixed with another type protobuf-c.c + * +or in the environment add command line: + +Project -> properties -> + +Add the warning number in +Supports diagnostic (--diag_suppress, - pds) +169 +190 +*/ + +//Project Properties->Build->Compiler->Include Options +//There may be paths there relative to a build variable, rather than hard-coded paths, that may be triggering the error. + + + +#endif /* DATADEF_H */ diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Progress.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Progress.c new file mode 100644 index 000000000..c44df4ef7 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Progress.c @@ -0,0 +1,48 @@ + +#include +#include +#include +#include "include.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +//#include "graphics_adapter.h" +#include "Container.h" + +void Stub_ProgressRequest(MessageContainer* requestContainer) +{ + MessageContainer responseContainer; + + ProgressRequest* request = progress_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + //writeLine("Progress Request..."); + + ProgressResponse response = PROGRESS_RESPONSE__INIT; + response.has_progress = true; + + int i = 0; + for (i = 0; i < request->amount; i++) + { + response.progress = i; + responseContainer = createContainer(MESSAGE_TYPE__ProgressResponse, requestContainer->token, false, &response, &progress_response__pack, &progress_response__get_packed_size); + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + //writeLine("Sending Progress: "); + //writeFloat(response.progress); + SendChars((char*)container_buffer, container_size); + + int co = 0; + for (co = 0; co < request->delay; co++) + { + __delay_cycles(1000000); + } + } + + responseContainer = createContainer(MESSAGE_TYPE__ProgressResponse, requestContainer->token, true, &response, &progress_response__pack, &progress_response__get_packed_size); + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + //writeLine("Progress Completed!"); + SendChars((char*)container_buffer, container_size); + return; + +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Progress.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Progress.h new file mode 100644 index 000000000..a0595e4b9 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Progress.h @@ -0,0 +1,7 @@ +#ifndef PROGRESS_H +#define PROGRESS_H + +#include "PMR/Common/MessageContainer.pb-c.h" +void Stub_ProgressRequest(MessageContainer* requestContainer); + +#endif //PROGRESS_H diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Cartridge.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Cartridge.c new file mode 100644 index 000000000..166cf9e7a --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Cartridge.c @@ -0,0 +1,128 @@ + + +#include +#include +#include +#include +#include +#include "include.h" +#include "inc/hw_uart.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "drivers/twine_graphicslib/graphics_adapter.h" + +#include "Container.h" +#include "Stub_Status.h" + +void Stub_CartridgeReadRequest(MessageContainer* requestContainer) +{ + uint32_t status = NOT_SUPPORTED; + MessageContainer responseContainer; + + StubCartridgeReadRequest* request = stub_cartridge_read_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + //request->cartridgeid + + writeLine("cartridge Request: "); + + writeFloat(request->cartridgeid); + + StubCartridgeReadResponse response = STUB_CARTRIDGE_READ_RESPONSE__INIT; + + response.cartridgeid = request->cartridgeid; + response.has_cartridgeid = true; + + //response.cartridgecolor + response.has_cartridgecolor = false; + + //response.cartridgeversion + response.has_cartridgeversion = false; + + //response.cartridgedata + response.has_cartridgedata = false; + + //response.cartridgeused + response.has_cartridgeused = false; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeFloat(response.cartridgeid); + writeString(", "); + writeFloat(response.cartridgecolor); + writeString(", "); + writeFloat(response.cartridgeversion); + writeString(", "); + writeFloat(response.cartridgedata); + writeString(", "); + writeFloat(response.cartridgeused); + writeString(", "); + + Write_status_response(status); + + responseContainer = createContainer(MESSAGE_TYPE__StubCartridgeReadResponse, requestContainer->token, true, &response, &stub_cartridge_read_response__pack, &stub_cartridge_read_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} + +void Stub_CartridgeWriteRequest(MessageContainer* requestContainer) +{ + uint32_t status = NOT_SUPPORTED; + MessageContainer responseContainer; + + StubCartridgeWriteRequest* request = stub_cartridge_write_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + //request->cartridgeid + //request->cartridgecolor + //request->cartridgeversion + //request->cartridgedata + //request->cartridgeused + + writeLine("Cartridge Request: "); + + writeFloat(request->cartridgeid); + writeString(", "); + writeFloat(request->cartridgecolor); + writeString(", "); + writeFloat(request->cartridgeversion); + writeString(", "); + writeFloat(request->cartridgedata); + writeString(", "); + writeFloat(request->cartridgeused); + + StubCartridgeWriteResponse response = STUB_CARTRIDGE_WRITE_RESPONSE__INIT; + + response.cartridgeid = request->cartridgeid; + response.has_cartridgeid = true; + +// char temp[7] = "PASSED"; +// response.status = temp; +// response.statusword = OK; +// response.has_statusword = true; + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeFloat(response.cartridgeid); + writeString(", "); +// writeFloat(response.statusword); +// WRITELINESTATUS; + Write_status_response(status); + + responseContainer = createContainer(MESSAGE_TYPE__StubCartridgeWriteResponse, requestContainer->token, true, &response, &stub_cartridge_write_response__pack, &stub_cartridge_write_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} + diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Cartridge.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Cartridge.h new file mode 100644 index 000000000..38c71c233 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Cartridge.h @@ -0,0 +1,9 @@ +#ifndef STUB_CARTRIDGE_H +#define STUB_CARTRIDGE_H + +#include "PMR/Common/MessageContainer.pb-c.h" + +void Stub_CartridgeReadRequest(MessageContainer* requestContainer); +void Stub_CartridgeWriteRequest(MessageContainer* requestContainer); + +#endif //STUB_CARTRIDGE_H diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Dispenser.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Dispenser.c new file mode 100644 index 000000000..384133e7e --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Dispenser.c @@ -0,0 +1,72 @@ + + +#include +#include +#include +#include "include.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "drivers/twine_graphicslib/graphics_adapter.h" + +#include "Container.h" +#include "Stub_Status.h" + +void Stub_DispenserRequest(MessageContainer* requestContainer) +{ + uint32_t status = NOT_SUPPORTED; + MessageContainer responseContainer; + + StubDispenserRequest* request = stub_dispenser_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + //request->dispenserid + //request->start + //request->setdirection + //request->setmicrostepdivision + //request->setspeed + + writeLine("Dispenser Request: "); + + writeFloat(request->dispenserid); + writeString(", "); + writeFloat(request->start); + writeString(", "); + writeFloat(request->setdirection); + writeString(", "); + writeFloat(request->setmicrostepdivision); + writeString(", "); + writeFloat(request->setspeed); + + StubDispenserResponse response = STUB_DISPENSER_RESPONSE__INIT; + + response.dispenserid = request->dispenserid; + response.has_dispenserid = true; + + //response.dispenserposition + response.has_dispenserposition = false; + + //response.inkworninglevel + response.has_inkworninglevel = false; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeFloat(response.dispenserid); + writeString(", "); + writeFloat(response.dispenserposition); + writeString(", "); + writeFloat(response.inkworninglevel); + writeString(", "); + + Write_status_response(status); + + responseContainer = createContainer(MESSAGE_TYPE__StubDispenserResponse, requestContainer->token, true, &response, &stub_dispenser_response__pack, &stub_dispenser_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Dispenser.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Dispenser.h new file mode 100644 index 000000000..f2f163e99 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Dispenser.h @@ -0,0 +1,9 @@ + +#ifndef STUB_DISPENSER_H +#define STUB_DISPENSER_H + +#include "PMR/Common/MessageContainer.pb-c.h" + +void Stub_DispenserRequest(MessageContainer* requestContainer); + +#endif //STUB_DISPENSER_H diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_ExtFlash.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_ExtFlash.c new file mode 100644 index 000000000..5b7577dfe --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_ExtFlash.c @@ -0,0 +1,160 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_uart.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "drivers/twine_graphicslib/graphics_adapter.h" + +#include "Container.h" +#include "Stub_Status.h" + + +#define Max_words 5 + + +void Stub_ExtFlashWriteRequest(MessageContainer* requestContainer) +{ + + uint32_t WriteBuf[5]; + uint32_t status = PASSED; + + MessageContainer responseContainer; + + StubExtFlashWriteRequest* request = stub_ext_flash_write_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + + WriteBuf[0] = request->wordtowrite1; + WriteBuf[1] = request->wordtowrite2; + WriteBuf[2] = request->wordtowrite3; + WriteBuf[3] = request->wordtowrite4; + WriteBuf[4] = request->wordtowrite5; + + writeLine("ExtFlash Request: "); + writeFloat(request->wordtowrite1); + writeString(", "); + writeFloat(request->wordtowrite2); + writeString(", "); + writeFloat(request->wordtowrite3); + writeString(", "); + writeFloat(request->wordtowrite4); + writeString(", "); + writeFloat(request->wordtowrite5); + + Ext_Flash_Operation(TX, Max_words, WriteBuf, NULL ); + + StubExtFlashWriteResponse response = STUB_EXT_FLASH_WRITE_RESPONSE__INIT; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + responseContainer = createContainer(MESSAGE_TYPE__StubExtFlashWriteResponse, requestContainer->token, true, &response, &stub_ext_flash_write_response__pack, &stub_ext_flash_write_response__get_packed_size); + + writeLine("Sending Response: "); + + Write_status_response(status); + + free(request); + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); + +} + +void Stub_ExtFlashReadRequest(MessageContainer* requestContainer) +{ + uint32_t status = PASSED; + MessageContainer responseContainer; + + StubExtFlashReadRequest* request = stub_ext_flash_read_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + uint32_t No_Words; + uint32_t ReadBuf[Max_words]; + + if(request->number_of_words>Max_words) + { + No_Words = Max_words; + } + else + { + No_Words = request->number_of_words; + } + + Ext_Flash_Operation(RX, No_Words, NULL, ReadBuf ); + + writeLine("ExtFlash Request: "); + writeFloat(request->number_of_words); + + + StubExtFlashReadResponse response = STUB_EXT_FLASH_READ_RESPONSE__INIT; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + response.has_readword_5 = false; + response.has_readword_4 = false; + response.has_readword_3 = false; + response.has_readword_2 = false; + response.has_readword_1 = false; + + switch(No_Words) + { + case 5: + response.readword_5 = ReadBuf[4]; + response.has_readword_5 = true; + case 4: + response.readword_4 = ReadBuf[3]; + response.has_readword_4 = true; + case 3: + response.readword_3 = ReadBuf[2]; + response.has_readword_3 = true; + case 2: + response.readword_2 = ReadBuf[1]; + response.has_readword_2 = true; + case 1: + response.readword_1 = ReadBuf[0]; + response.has_readword_1 = true; + break; + default: + break; + } + + responseContainer = createContainer(MESSAGE_TYPE__StubExtFlashReadResponse, requestContainer->token, true, &response, &stub_ext_flash_read_response__pack, &stub_ext_flash_read_response__get_packed_size); + //clear(); + writeLine("Sending Response: "); + + Write_status_response(status); + writeString(", "); + writeFloat(response.readword_1); + writeString(", "); + writeFloat(response.readword_2); + writeString(", "); + writeFloat(response.readword_3); + writeString(", "); + writeFloat(response.readword_4); + writeString(", "); + writeFloat(response.readword_5); + + free(request); + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} + diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_ExtFlash.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_ExtFlash.h new file mode 100644 index 000000000..35fc78f85 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_ExtFlash.h @@ -0,0 +1,8 @@ +#ifndef STUB_EXTFLASH_H +#define STUB_EXTFLASH_H + +void Stub_ExtFlashWriteRequest(MessageContainer* requestContainer); +void Stub_ExtFlashReadRequest(MessageContainer* requestContainer); + +#endif //STUB_EXTFLASH_H + diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_GPIO.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_GPIO.c new file mode 100644 index 000000000..07ef4a360 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_GPIO.c @@ -0,0 +1,947 @@ +#include "include.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_uart.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "drivers/twine_graphicslib/graphics_adapter.h" + +#include "Container.h" +#include + +#include "Stub_Status.h" + +void Stub_GPIOWriteBitRequest(MessageContainer* requestContainer) +{ + uint32_t status = FAILED; + MessageContainer responseContainer; + + StubGPIOWriteBitRequest* request = stub_gpiowrite_bit_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + writeLine("GPIO Request: "); + + writeString(request->portid); + writeString(", "); + writeFloat(request->pinid); + writeString(", "); + writeFloat(request->bittowrite); + + + uint8_t PinId = 0; + uint32_t PortId = 0; + + switch(request->pinid) + { + case 0: + PinId = GPIO_PIN_0; + break; + case 1: + PinId = GPIO_PIN_1; + break; + case 2: + PinId = GPIO_PIN_2; + break; + case 3: + PinId = GPIO_PIN_3; + break; + case 4: + PinId = GPIO_PIN_4; + break; + case 5: + PinId = GPIO_PIN_5; + break; + case 6: + PinId = GPIO_PIN_6; + break; + case 7: + PinId = GPIO_PIN_7; + break; + default: + break; + } + + char Port = request->portid[0]; + switch(Port) + { + #ifdef USE_HIGH_SPEED_GPIO + case 'A': + PortId = GPIO_PORTA_AHB_BASE; + break; + case 'B': + PortId = GPIO_PORTB_AHB_BASE; + break; + case 'C': + PortId = GPIO_PORTC_AHB_BASE; + break; + case 'D': + PortId = GPIO_PORTD_AHB_BASE; + break; + case 'E': + PortId = GPIO_PORTE_AHB_BASE; + break; + case 'F': + PortId = GPIO_PORTF_AHB_BASE; + break; + case 'G': + PortId = GPIO_PORTG_AHB_BASE; + break; + case 'H': + PortId = GPIO_PORTH_AHB_BASE; + break; + case 'J': + PortId = GPIO_PORTJ_AHB_BASE; + break; + #else + case 'A': + PortId = GPIO_PORTA_BASE; + break; + case 'B': + PortId = GPIO_PORTB_BASE; + break; + case 'C': + PortId = GPIO_PORTC_BASE; + break; + case 'D': + PortId = GPIO_PORTD_BASE; + break; + case 'E': + PortId = GPIO_PORTE_BASE; + break; + case 'F': + PortId = GPIO_PORTF_BASE; + break; + case 'G': + PortId = GPIO_PORTG_BASE; + break; + case 'H': + PortId = GPIO_PORTH_BASE; + break; + case 'J': + PortId = GPIO_PORTJ_BASE; + break; + #endif + case 'K': + PortId = GPIO_PORTK_BASE; + break; + case 'L': + PortId = GPIO_PORTL_BASE; + break; + case 'M': + PortId = GPIO_PORTM_BASE; + break; + case 'N': + PortId = GPIO_PORTN_BASE; + break; + case 'P': + PortId = GPIO_PORTP_BASE; + break; + case 'Q': + PortId = GPIO_PORTQ_BASE; + break; + case 'R': + PortId = GPIO_PORTR_BASE; + break; + case 'S': + PortId = GPIO_PORTS_BASE; + break; + case 'T': + PortId = GPIO_PORTT_BASE; + break; + + default: + writeLine("Unsupported Port ID: "); + writeString(request->portid); + break; + } + + ROM_GPIOPinTypeGPIOOutput(PortId, PinId); // set the requested GPIO to output + SysCtlDelay(10000); + + if(request->bittowrite) + ROM_GPIOPinWrite(PortId, PinId, ROM_GPIOPinRead(PortId, GPIO_BYTE) | PinId); //Turn ON the requested GPIO + else + ROM_GPIOPinWrite(PortId, PinId, ROM_GPIOPinRead(PortId, GPIO_BYTE) & ~PinId); //Turn OFF the requested GPIO + + //GPIOPinWrite(PortId, PinId, PinId*request->bittowrite);// + + StubGPIOWriteBitResponse response = STUB_GPIOWRITE_BIT_RESPONSE__INIT; + + response.portid = request->portid; + + response.pinid = request->pinid; + response.has_pinid = true; + + //Verify Writing + if(request->bittowrite) + { + if(ROM_GPIOPinRead(PortId, PinId) == PinId) + status = VERIFIED; + } + else + { + if(ROM_GPIOPinRead(PortId, PinId) == 0) + status = VERIFIED; + } + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeString(response.portid); + writeString(", "); + writeFloat(response.pinid); + writeString(", "); + + Write_status_response(status); + + + responseContainer = createContainer(MESSAGE_TYPE__StubGPIOWriteBitResponse, requestContainer->token, true, &response, &stub_gpiowrite_bit_response__pack, &stub_gpiowrite_bit_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} + +// +void Stub_GPIOReadByteRequest(MessageContainer* requestContainer) +{ + uint32_t status = PASSED; + MessageContainer responseContainer; + + StubGPIOReadByteRequest* request = stub_gpioread_byte_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + writeLine("GPIO Request: "); + + writeString(request->portid); + + char Port = request->portid[0]; + uint32_t PortId = 0; + + switch(Port) + { + #ifdef USE_HIGH_SPEED_GPIO + case 'A': + PortId = GPIO_PORTA_AHB_BASE; + break; + case 'B': + PortId = GPIO_PORTB_AHB_BASE; + break; + case 'C': + PortId = GPIO_PORTC_AHB_BASE; + break; + case 'D': + PortId = GPIO_PORTD_AHB_BASE; + break; + case 'E': + PortId = GPIO_PORTE_AHB_BASE; + break; + case 'F': + PortId = GPIO_PORTF_AHB_BASE; + break; + case 'G': + PortId = GPIO_PORTG_AHB_BASE; + break; + case 'H': + PortId = GPIO_PORTH_AHB_BASE; + break; + case 'J': + PortId = GPIO_PORTJ_AHB_BASE; + break; + #else + case 'A': + PortId = GPIO_PORTA_BASE; + break; + case 'B': + PortId = GPIO_PORTB_BASE; + break; + case 'C': + PortId = GPIO_PORTC_BASE; + break; + case 'D': + PortId = GPIO_PORTD_BASE; + break; + case 'E': + PortId = GPIO_PORTE_BASE; + break; + case 'F': + PortId = GPIO_PORTF_BASE; + break; + case 'G': + PortId = GPIO_PORTG_BASE; + break; + case 'H': + PortId = GPIO_PORTH_BASE; + break; + case 'J': + PortId = GPIO_PORTJ_BASE; + break; + #endif + case 'K': + PortId = GPIO_PORTK_BASE; + break; + case 'L': + PortId = GPIO_PORTL_BASE; + break; + case 'M': + PortId = GPIO_PORTM_BASE; + break; + case 'N': + PortId = GPIO_PORTN_BASE; + break; + case 'P': + PortId = GPIO_PORTP_BASE; + break; + case 'Q': + PortId = GPIO_PORTQ_BASE; + break; + case 'R': + PortId = GPIO_PORTR_BASE; + break; + case 'S': + PortId = GPIO_PORTS_BASE; + break; + case 'T': + PortId = GPIO_PORTT_BASE; + break; + + default: + writeLine("Unsupported Port ID: "); + writeString(request->portid); + break; + } + + StubGPIOReadByteResponse response = STUB_GPIOREAD_BYTE_RESPONSE__INIT; + + response.portid = request->portid; + + char temp = ROM_GPIOPinRead(PortId, GPIO_BYTE); + response.bytevalue = temp; + response.has_bytevalue = true; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeString(response.portid); + writeString(", "); + writeFloat(response.bytevalue); + writeString(", "); + + Write_status_response(status); + + responseContainer = createContainer(MESSAGE_TYPE__StubGPIOReadByteResponse, requestContainer->token, true, &response, &stub_gpioread_byte_response__pack, &stub_gpioread_byte_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} + + +void Stub_GPIOReadBitRequest(MessageContainer* requestContainer) +{ + uint32_t status = PASSED; + MessageContainer responseContainer; + + StubGPIOReadBitRequest* request = stub_gpioread_bit_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + writeLine("GPIO Request: "); + + writeString(request->portid); + writeString(", "); + writeFloat(request->pinid); + + uint8_t PinId = 0; + uint32_t PortId = 0; + + switch(request->pinid) + { + case 0: + PinId = GPIO_PIN_0; + break; + case 1: + PinId = GPIO_PIN_1; + break; + case 2: + PinId = GPIO_PIN_2; + break; + case 3: + PinId = GPIO_PIN_3; + break; + case 4: + PinId = GPIO_PIN_4; + break; + case 5: + PinId = GPIO_PIN_5; + break; + case 6: + PinId = GPIO_PIN_6; + break; + case 7: + PinId = GPIO_PIN_7; + break; + default: + break; + } + + char Port = request->portid[0]; + switch(Port) + { + #ifdef USE_HIGH_SPEED_GPIO + case 'A': + PortId = GPIO_PORTA_AHB_BASE; + break; + case 'B': + PortId = GPIO_PORTB_AHB_BASE; + break; + case 'C': + PortId = GPIO_PORTC_AHB_BASE; + break; + case 'D': + PortId = GPIO_PORTD_AHB_BASE; + break; + case 'E': + PortId = GPIO_PORTE_AHB_BASE; + break; + case 'F': + PortId = GPIO_PORTF_AHB_BASE; + break; + case 'G': + PortId = GPIO_PORTG_AHB_BASE; + break; + case 'H': + PortId = GPIO_PORTH_AHB_BASE; + break; + case 'J': + PortId = GPIO_PORTJ_AHB_BASE; + break; + #else + case 'A': + PortId = GPIO_PORTA_BASE; + break; + case 'B': + PortId = GPIO_PORTB_BASE; + break; + case 'C': + PortId = GPIO_PORTC_BASE; + break; + case 'D': + PortId = GPIO_PORTD_BASE; + break; + case 'E': + PortId = GPIO_PORTE_BASE; + break; + case 'F': + PortId = GPIO_PORTF_BASE; + break; + case 'G': + PortId = GPIO_PORTG_BASE; + break; + case 'H': + PortId = GPIO_PORTH_BASE; + break; + case 'J': + PortId = GPIO_PORTJ_BASE; + break; + #endif + case 'K': + PortId = GPIO_PORTK_BASE; + break; + case 'L': + PortId = GPIO_PORTL_BASE; + break; + case 'M': + PortId = GPIO_PORTM_BASE; + break; + case 'N': + PortId = GPIO_PORTN_BASE; + break; + case 'P': + PortId = GPIO_PORTP_BASE; + break; + case 'Q': + PortId = GPIO_PORTQ_BASE; + break; + case 'R': + PortId = GPIO_PORTR_BASE; + break; + case 'S': + PortId = GPIO_PORTS_BASE; + break; + case 'T': + PortId = GPIO_PORTT_BASE; + break; + + default: + writeLine("Unsupported Port ID: "); + writeString(request->portid); + break; + } + +///////////////////////////////////////////----------------------------------------------------------------------------- + char temp; + uint8_t expvalue; + uint32_t timeout = 10000; + + if(request->pollexpvalue) + expvalue = PinId; + + //Polling + if(request->polling) + { + do + { + timeout--; + SysCtlDelay(10000); + temp = ROM_GPIOPinRead(PortId, PinId); + } while(( temp != expvalue) && (timeout)); + + } + else + { + temp = ROM_GPIOPinRead(PortId, PinId); + } + + StubGPIOReadBitResponse response = STUB_GPIOREAD_BIT_RESPONSE__INIT; + + response.portid = request->portid; + + response.pinid = request->pinid; + response.has_pinid = true; + + response.bitvalue = temp; + response.has_bitvalue = true; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeString(response.portid); + writeString(", "); + writeFloat(response.pinid); + writeString(", "); + writeFloat(response.bitvalue); + writeString(", "); + + Write_status_response(status); + + responseContainer = createContainer(MESSAGE_TYPE__StubGPIOReadBitResponse, requestContainer->token, true, &response, &stub_gpioread_bit_response__pack, &stub_gpioread_bit_response__get_packed_size); + +///////////////////////////////////////////----------------------------------------------------------------------------- +/* +// if( (PortId == GPIO_PORTS_BASE) && (PinId == GPIO_PIN_3)) +// { +// MAP_GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_3); // Enable pin PS3 for GPIOInput +// GPIOPadConfigSet(GPIO_PORTS_BASE,GPIO_PIN_3,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);//Configure GPIO pull up resistors. NOTE: does not work if ROM_GPIOPinTypeGPIOInput() isnt called before. +// //GPIOPadConfigSet(GPIO_PORTS_BASE,GPIO_PIN_3,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPD );//Configure GPIO pull down resistors. NOTE: does not work if ROM_GPIOPinTypeGPIOInput() isnt called before. +// } + + //ROM_GPIOPinTypeGPIOInput(PortId, PinId); // set the requested GPIO to Input + //SysCtlDelay(10000); + + StubGPIOReadBitResponse response = STUB_GPIOREAD_BIT_RESPONSE__INIT; + + response.portid = request->portid; + + response.pinid = request->pinid; + response.has_pinid = true; + + char temp = ROM_GPIOPinRead(PortId, PinId); + + //char temp2 = ROM_GPIOPinRead(GPIO_PORTQ_BASE, GPIO_BYTE); + + //GPIOPinTypeGPIOInput(GPIO_PORTS_BASE, GPIO_PIN_3); // set the requested GPIO to Input + //SysCtlDelay(10000); + //char temp3 = GPIOPinRead(GPIO_PORTS_BASE, GPIO_PIN_3); + //char temp4 = GPIOPinRead(GPIO_PORTS_BASE, GPIO_BYTE); + + response.bitvalue = temp; + response.has_bitvalue = true; + + response.status = OK; + response.has_status = true; + + writeLine("Sending Response: "); + + writeString(response.portid); + writeString(", "); + writeFloat(response.pinid); + writeString(", "); + writeFloat(response.bitvalue); + writeString(", "); + writeFloat(response.status); + WRITELINESTATUS; + + responseContainer = createContainer(MESSAGE_TYPE__StubGPIOReadBitResponse, requestContainer->token, true, &response, &stub_gpioread_bit_response__pack, &stub_gpioread_bit_response__get_packed_size); +*/ + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} + + + +void Stub_GPIOWriteByteRequest(MessageContainer* requestContainer) +{ + uint32_t status = FAILED; + MessageContainer responseContainer; + + StubGPIOWriteByteRequest* request = stub_gpiowrite_byte_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + writeLine("GPIO Request: "); + + writeString(request->portid); + writeString(", "); + writeFloat(request->datatowrite); + + uint32_t PortId = 0; + + char Port = request->portid[0]; + switch(Port) + { + #ifdef USE_HIGH_SPEED_GPIO + case 'A': + PortId = GPIO_PORTA_AHB_BASE; + break; + case 'B': + PortId = GPIO_PORTB_AHB_BASE; + break; + case 'C': + PortId = GPIO_PORTC_AHB_BASE; + break; + case 'D': + PortId = GPIO_PORTD_AHB_BASE; + break; + case 'E': + PortId = GPIO_PORTE_AHB_BASE; + break; + case 'F': + PortId = GPIO_PORTF_AHB_BASE; + break; + case 'G': + PortId = GPIO_PORTG_AHB_BASE; + break; + case 'H': + PortId = GPIO_PORTH_AHB_BASE; + break; + case 'J': + PortId = GPIO_PORTJ_AHB_BASE; + break; + #else + case 'A': + PortId = GPIO_PORTA_BASE; + break; + case 'B': + PortId = GPIO_PORTB_BASE; + break; + case 'C': + PortId = GPIO_PORTC_BASE; + break; + case 'D': + PortId = GPIO_PORTD_BASE; + break; + case 'E': + PortId = GPIO_PORTE_BASE; + break; + case 'F': + PortId = GPIO_PORTF_BASE; + break; + case 'G': + PortId = GPIO_PORTG_BASE; + break; + case 'H': + PortId = GPIO_PORTH_BASE; + break; + case 'J': + PortId = GPIO_PORTJ_BASE; + break; + #endif + case 'K': + PortId = GPIO_PORTK_BASE; + break; + case 'L': + PortId = GPIO_PORTL_BASE; + break; + case 'M': + PortId = GPIO_PORTM_BASE; + break; + case 'N': + PortId = GPIO_PORTN_BASE; + break; + case 'P': + PortId = GPIO_PORTP_BASE; + break; + case 'Q': + PortId = GPIO_PORTQ_BASE; + break; + case 'R': + PortId = GPIO_PORTR_BASE; + break; + case 'S': + PortId = GPIO_PORTS_BASE; + break; + case 'T': + PortId = GPIO_PORTS_BASE; + break; + + default: + writeLine("Unsupported Port ID: "); + writeString(request->portid); + break; + } + + ROM_GPIOPinTypeGPIOOutput(PortId, GPIO_BYTE); // set the requested GPIO to output + SysCtlDelay(10000); + + ROM_GPIOPinWrite(PortId, GPIO_BYTE, request->datatowrite); //Turn ON the requested GPIOs BYTE + + StubGPIOWriteByteResponse response = STUB_GPIOWRITE_BYTE_RESPONSE__INIT; + + response.portid = request->portid; + + //Verify writing + if(ROM_GPIOPinRead(PortId, GPIO_BYTE) == request->datatowrite) + { + status = VERIFIED; + } + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeString(response.portid); + writeString(", "); + + Write_status_response(status); + + responseContainer = createContainer(MESSAGE_TYPE__StubGPIOWriteByteResponse, requestContainer->token, true, &response, &stub_gpiowrite_byte_response__pack, &stub_gpiowrite_byte_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} + + + +void Stub_GPIOInputSetupRequest(MessageContainer* requestContainer) +{ + uint32_t status = PASSED; + MessageContainer responseContainer; + + StubGPIOInputSetupRequest* request = stub_gpioinput_setup_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + writeLine("GPIO Request: "); + + writeString(request->portid); + writeString(", "); + writeFloat(request->pinid); + writeString(", "); + writeFloat(request->setinput); + writeString(", "); + writeFloat(request->setpullup); + + + uint8_t PinId = 0; + uint32_t PortId = 0; + + switch(request->pinid) + { + case 0: + PinId = GPIO_PIN_0; + break; + case 1: + PinId = GPIO_PIN_1; + break; + case 2: + PinId = GPIO_PIN_2; + break; + case 3: + PinId = GPIO_PIN_3; + break; + case 4: + PinId = GPIO_PIN_4; + break; + case 5: + PinId = GPIO_PIN_5; + break; + case 6: + PinId = GPIO_PIN_6; + break; + case 7: + PinId = GPIO_PIN_7; + break; + default: + break; + } + + char Port = request->portid[0]; + switch(Port) + { + #ifdef USE_HIGH_SPEED_GPIO + case 'A': + PortId = GPIO_PORTA_AHB_BASE; + break; + case 'B': + PortId = GPIO_PORTB_AHB_BASE; + break; + case 'C': + PortId = GPIO_PORTC_AHB_BASE; + break; + case 'D': + PortId = GPIO_PORTD_AHB_BASE; + break; + case 'E': + PortId = GPIO_PORTE_AHB_BASE; + break; + case 'F': + PortId = GPIO_PORTF_AHB_BASE; + break; + case 'G': + PortId = GPIO_PORTG_AHB_BASE; + break; + case 'H': + PortId = GPIO_PORTH_AHB_BASE; + break; + case 'J': + PortId = GPIO_PORTJ_AHB_BASE; + break; + #else + case 'A': + PortId = GPIO_PORTA_BASE; + break; + case 'B': + PortId = GPIO_PORTB_BASE; + break; + case 'C': + PortId = GPIO_PORTC_BASE; + break; + case 'D': + PortId = GPIO_PORTD_BASE; + break; + case 'E': + PortId = GPIO_PORTE_BASE; + break; + case 'F': + PortId = GPIO_PORTF_BASE; + break; + case 'G': + PortId = GPIO_PORTG_BASE; + break; + case 'H': + PortId = GPIO_PORTH_BASE; + break; + case 'J': + PortId = GPIO_PORTJ_BASE; + break; + #endif + case 'K': + PortId = GPIO_PORTK_BASE; + break; + case 'L': + PortId = GPIO_PORTL_BASE; + break; + case 'M': + PortId = GPIO_PORTM_BASE; + break; + case 'N': + PortId = GPIO_PORTN_BASE; + break; + case 'P': + PortId = GPIO_PORTP_BASE; + break; + case 'Q': + PortId = GPIO_PORTQ_BASE; + break; + case 'R': + PortId = GPIO_PORTR_BASE; + break; + case 'S': + PortId = GPIO_PORTS_BASE; + break; + case 'T': + PortId = GPIO_PORTT_BASE; + break; + + default: + writeLine("Unsupported Port ID: "); + writeString(request->portid); + break; + } + + if(request->setinput == INPUT) + { + MAP_GPIOPinTypeGPIOInput(PortId, PinId); // Enable pin for GPIOInput + + if(request->setpullup == PULLUP) + { + GPIOPadConfigSet(PortId,PinId,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);//Configure GPIO pull up resistors. NOTE: does not work if ROM_GPIOPinTypeGPIOInput() isnt called before. + } + else //set pulldown: + { + GPIOPadConfigSet(GPIO_PORTS_BASE,GPIO_PIN_3,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPD );//Configure GPIO pull down resistors. NOTE: does not work if ROM_GPIOPinTypeGPIOInput() isnt called before. + } + } + else + { + ROM_GPIOPinTypeGPIOOutput(PortId, PinId); // set the requested GPIO to output + } + + SysCtlDelay(10000); + + StubGPIOInputSetupResponse response = STUB_GPIOINPUT_SETUP_RESPONSE__INIT; + + response.portid = request->portid; + + response.pinid = request->pinid; + response.has_pinid = true; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeString(response.portid); + writeString(", "); + writeFloat(response.pinid); + writeString(", "); + + Write_status_response(status); + + responseContainer = createContainer(MESSAGE_TYPE__StubGPIOInputSetupResponse, requestContainer->token, true, &response, &stub_gpioinput_setup_response__pack, &stub_gpioinput_setup_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_GPIO.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_GPIO.h new file mode 100644 index 000000000..3830ba54f --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_GPIO.h @@ -0,0 +1,12 @@ +#ifndef STUB_GPIO_H +#define STUB_GPIO_H + +#include "PMR/Common/MessageContainer.pb-c.h" + +void Stub_GPIOWriteBitRequest(MessageContainer* requestContainer); +void Stub_GPIOReadByteRequest(MessageContainer* requestContainer); +void Stub_GPIOReadBitRequest(MessageContainer* requestContainer); +void Stub_GPIOWriteByteRequest(MessageContainer* requestContainer); +void Stub_GPIOInputSetupRequest(MessageContainer* requestContainer); + +#endif //STUB_GPIO_H diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Heater.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Heater.c new file mode 100644 index 000000000..ff2f2ce1c --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Heater.c @@ -0,0 +1,74 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_uart.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "drivers/twine_graphicslib/graphics_adapter.h" + +#include "Container.h" +#include "Stub_Status.h" +#include "Drivers/Heater/Heater.h" + +void Stub_HeaterRequest(MessageContainer* requestContainer) +{ + uint32_t status = NOT_SUPPORTED; + MessageContainer responseContainer; + + StubHeaterRequest* request = stub_heater_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + /* + request->heaterid + request->heatergroupon + */ + + writeLine("Heater Request: "); + + writeFloat(request->heatergroupid); + writeString(", "); + writeFloat(request->heatergroupon); + + if (request->heatergroupon ) + status = ActivateHeater(request->heatergroupid); + else + status = DeActivateHeater(request->heatergroupid); + StubHeaterResponse response = STUB_HEATER_RESPONSE__INIT; + + response.heatergroupid = request->heatergroupid; + response.has_heatergroupid = true; + + //response.heatertemperaturesensor + response.has_heatertemperaturesensor = false; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeFloat(response.heatergroupid); + writeString(", "); + writeFloat(response.heatertemperaturesensor); + writeString(", "); + + Write_status_response(status); + + responseContainer = createContainer(MESSAGE_TYPE__StubHeaterResponse, requestContainer->token, true, &response, &stub_heater_response__pack, &stub_heater_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Heater.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Heater.h new file mode 100644 index 000000000..14c2dad3c --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Heater.h @@ -0,0 +1,6 @@ +#ifndef STUB_HEATER_H +#define STUB_HEATER_H + +void Stub_HeaterRequest(MessageContainer* requestContainer); + +#endif //STUB_HEATER_H diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_MotorEncoder.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_MotorEncoder.c new file mode 100644 index 000000000..346b595e2 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_MotorEncoder.c @@ -0,0 +1,84 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_uart.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "drivers/twine_graphicslib/graphics_adapter.h" + +#include "Container.h" +#include "Stub_Status.h" + +void Stub_MotorEncoderRequest(MessageContainer* requestContainer) +{ + uint32_t status = NOT_SUPPORTED; + MessageContainer responseContainer; + + StubMotorEncoderRequest* request = stub_motor_encoder_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + /* + request->motorid + request->readencspeed + request->readdirection + request->motion_control + */ + + writeLine("Encoder Request: "); + + writeFloat(request->motorid); + writeString(", "); + writeFloat(request->readencspeed); + writeString(", "); + writeFloat(request->readdirection); + writeString(", "); + writeFloat(request->motion_control); + + StubMotorEncoderResponse response = STUB_MOTOR_ENCODER_RESPONSE__INIT; + + response.encoderid = request->motorid; + response.has_encoderid = true; + + response.encoderversion = 456; + response.has_encoderversion = true; + + //response.motorspeed + response.has_motorspeed = false; + + response.motordirection = CW; + response.has_motordirection = true; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeFloat(response.encoderid); + writeString(", "); + writeFloat(response.encoderversion); + writeString(", "); + writeFloat(response.motorspeed); + writeString(", "); + writeFloat(response.motordirection); + writeString(", "); + + Write_status_response(status); + + responseContainer = createContainer(MESSAGE_TYPE__StubMotorEncoderResponse, requestContainer->token, true, &response, &stub_motor_encoder_response__pack, &stub_motor_encoder_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_MotorEncoder.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_MotorEncoder.h new file mode 100644 index 000000000..0e0a1c41e --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_MotorEncoder.h @@ -0,0 +1,6 @@ +#ifndef STUB_MOTORENCODER_H +#define STUB_MOTORENCODER_H + +void Stub_MotorEncoderRequest(MessageContainer* requestContainer); + +#endif //STUB_STUB_MOTORENCODER_H diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_OptLimitSwitch.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_OptLimitSwitch.c new file mode 100644 index 000000000..5da89ab10 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_OptLimitSwitch.c @@ -0,0 +1,70 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_uart.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "drivers/twine_graphicslib/graphics_adapter.h" + +#include "Container.h" +#include "Stub_Status.h" + +void Stub_OptLimitSwitchRequest(MessageContainer* requestContainer) +{ + uint32_t status = NOT_SUPPORTED; + + MessageContainer responseContainer; + + StubOptLimitSwitchRequest* request = stub_opt_limit_switch_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + /* + request->limitswitchrid + request->limitswitchrdisable + */ + + writeLine("OptLimit Switch Request: "); + + writeFloat(request->limitswitchrid); + writeString(", "); + writeFloat(request->limitswitchrdisable); + + StubOptLimitSwitchResponse response = STUB_OPT_LIMIT_SWITCH_RESPONSE__INIT; + + response.limitswitchrid = request->limitswitchrid; + response.has_limitswitchrid = true; + + //response.limitswitchditection = 2; + response.has_limitswitchditection = false; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeFloat(response.limitswitchrid); + writeString(", "); + writeFloat(response.limitswitchditection); + writeString(", "); + + Write_status_response(status); + + responseContainer = createContainer(MESSAGE_TYPE__StubOptLimitSwitchResponse, requestContainer->token, true, &response, &stub_opt_limit_switch_response__pack, &stub_opt_limit_switch_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_OptLimitSwitch.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_OptLimitSwitch.h new file mode 100644 index 000000000..dbd064a1d --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_OptLimitSwitch.h @@ -0,0 +1,6 @@ +#ifndef STUB_OPTLIMITSWITCH_H +#define STUB_OPTLIMITSWITCH_H + +void Stub_OptLimitSwitchRequest(MessageContainer* requestContainer); + +#endif //STUB_OPTLIMITSWITCH_H diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Status.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Status.c new file mode 100644 index 000000000..00299c74c --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Status.c @@ -0,0 +1,58 @@ + +#include "include.h" +/*#include +#include +#include +#include "Stub_Status.h" +#include */ +#include "drivers/twine_graphicslib/graphics_adapter.h" + +int status_response(uint32_t Rstatus,char *status[20],uint32_t *statusword ,protobuf_c_boolean *has_statusword) +{ + if(Rstatus==PASSED) + { + *status = "PASSED"; + *has_statusword = false; + } + else if(Rstatus==VERIFIED) + { + *status = "PASSED (VERIFIED)"; + *has_statusword = false; + } + else if(Rstatus==NOT_SUPPORTED) + { + *status = "NOT_SUPPORTED"; + *statusword = Rstatus; + *has_statusword = false; + } + else + { + *status = "FAILED"; + *statusword = Rstatus; + *has_statusword = true; + } + return 0; +} + +int Write_status_response(uint32_t Rstatus) +{ + writeFloat(Rstatus); + + if(Rstatus==PASSED) + { + writeLine("PASSED"); + } + else if(Rstatus==VERIFIED) + { + writeLine("PASSED (VERIFIED)"); + } + else if(Rstatus==NOT_SUPPORTED) + { + writeLine("NOT_SUPPORTED"); + } + else + { + writeLine("FAILED"); + } + return 0; +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Status.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Status.h new file mode 100644 index 000000000..c2ff1b7e5 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Status.h @@ -0,0 +1,3 @@ + +int status_response(uint32_t Rstatus,char *status[8],uint32_t *statusword ,protobuf_c_boolean *has_statusword); +int Write_status_response(uint32_t Rstatus); diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_SteperMotor.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_SteperMotor.c new file mode 100644 index 000000000..03807934b --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_SteperMotor.c @@ -0,0 +1,79 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_uart.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "drivers/twine_graphicslib/graphics_adapter.h" + +#include "Container.h" +#include "Stub_Status.h" + +void Stub_SteperMotorRequest(MessageContainer* requestContainer) +{ + uint32_t status = NOT_SUPPORTED; + MessageContainer responseContainer; + + StubSteperMotorRequest* request = stub_steper_motor_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + + writeLine("Steper Motor Request: "); + + writeFloat(request->motorid); + writeString(", "); + writeFloat(request->start); + writeString(", "); + writeFloat(request->setdirection); + writeString(", "); + writeFloat(request->setmicrostepdivision); + writeString(", "); + writeFloat(request->setspeed); + /* + request->motorid + request->start + request->setdirection + request->setmicrostepdivision + request->setspeed + */ + + StubSteperMotorResponse response = STUB_STEPER_MOTOR_RESPONSE__INIT; + + response.motorid = request->motorid; + response.has_motorid = true; + + response.motorversion = 123; + response.has_motorversion = true; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + writeLine("Sending Response: "); + + writeFloat(response.motorid); + writeString(", "); + writeFloat(response.motorversion); + writeString(", "); + + Write_status_response(status); + + + responseContainer = createContainer(MESSAGE_TYPE__StubSteperMotorResponse, requestContainer->token, true, &response, &stub_steper_motor_response__pack, &stub_steper_motor_response__get_packed_size); + + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_SteperMotor.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_SteperMotor.h new file mode 100644 index 000000000..b19aa0cc0 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_SteperMotor.h @@ -0,0 +1,7 @@ + +#ifndef STUB_STEPERMOTOR_H +#define STUB_STEPERMOTOR_H + +void Stub_SteperMotorRequest(MessageContainer* requestContainer); + +#endif //STUB_STEPERMOTOR_H diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Valve.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Valve.c new file mode 100644 index 000000000..ef38bb496 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Valve.c @@ -0,0 +1,60 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_uart.h" +#include "driverlib/gpio.h" + +#include "drivers/twine_usblib/usb_serial_adapter.h" +#include "drivers/twine_graphicslib/graphics_adapter.h" + +#include "Container.h" + +#include "Stub_Status.h" + +void Stub_ValveRequest(MessageContainer* requestContainer) +{ + MessageContainer responseContainer; + uint32_t status = NOT_SUPPORTED; + + StubValveRequest* request = stub_valve_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + /* + request->valveid + request->inkflow + request->valveon + */ + writeLine("Valve Request: "); + writeFloat(request->valveid); + writeString(", "); + writeFloat(request->inkflow); + writeString(", "); + writeFloat(request->valveon); + + StubValveResponse response = STUB_VALVE_RESPONSE__INIT; + + status_response(status,&response.status, &response.statusword ,&response.has_statusword); + + responseContainer = createContainer(MESSAGE_TYPE__StubValveResponse, requestContainer->token, true, &response, &stub_valve_response__pack, &stub_valve_response__get_packed_size); + + writeLine("Sending Response: "); + + Write_status_response(status); + + free(request); + //------------------------------------------------------------------------------------------- + uint8_t* container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Valve.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Valve.h new file mode 100644 index 000000000..1948fa37b --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/Stub_Valve.h @@ -0,0 +1,6 @@ +#ifndef STUB_VALVE_H +#define STUB_VALVE_H +void Stub_ValveRequest(MessageContainer* requestContainer); + +#endif //STUB_VALVE_H + diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/User_Leds.c b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/User_Leds.c new file mode 100644 index 000000000..d06b3aeef --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/User_Leds.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + +#include "inc/hw_memmap.h" + +#include "driverlib/rom.h" +#include "driverlib/gpio.h" +#include "driverlib/sysctl.h" + +#include +#include + +void Turn_Green_Led_On() +{ + INIT_GPIO_GREEN_LED + GREEN_LED_ON + LED_SET_DELAY +} + +void Turn_Green_Led_Off() +{ + GREEN_LED_OFF +} + +void Turn_Blue_Led_On() +{ + INIT_GPIO_BLUE_LED + BLUE_LED_ON + LED_SET_DELAY +} + +void Turn_Blue_Led_Off() +{ + BLUE_LED_OFF +} + +void Turn_Red_Led_On() +{ + INIT_GPIO_RED_LED + RED_LED_ON + LED_SET_DELAY +} + +void Turn_Red_Led_Off() +{ + RED_LED_OFF +} + + +void Test_3_Color_Led() +{ + char i; + + for (i=0;i<5000;i++) + { + Turn_Green_Led_On(); + Turn_Green_Led_Off(); + + Turn_Blue_Led_On(); + Turn_Blue_Led_Off(); + + Turn_Red_Led_On(); + Turn_Red_Led_Off(); + } +} diff --git a/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/User_Leds.h b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/User_Leds.h new file mode 100644 index 000000000..5f0016bda --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Stubs_Handler/User_Leds.h @@ -0,0 +1,23 @@ +#ifndef USER_LEDS_H +#define USER_LEDS_H + +#define GPIO_BYTE (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7) + +#define INIT_GPIO_GREEN_LED ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_7); // set PQ7 to output (Green LED) +#define INIT_GPIO_BLUE_LED ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_4); // set PQ4 to output (Blue LED) +#define INIT_GPIO_RED_LED ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_5); // set PN5 to output (RED LED) + +#define GREEN_LED_ON ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_7, ROM_GPIOPinRead(GPIO_PORTQ_BASE, GPIO_BYTE) | GPIO_PIN_7); //Turn the GREEN led on +#define GREEN_LED_OFF ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_7, ROM_GPIOPinRead(GPIO_PORTQ_BASE, GPIO_BYTE) & ~ GPIO_PIN_7); //Turn the GREEN led off + +#define BLUE_LED_ON ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_4, ROM_GPIOPinRead(GPIO_PORTQ_BASE, GPIO_BYTE) | GPIO_PIN_4); //Turn the BLUE led on +#define BLUE_LED_OFF ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_4, ROM_GPIOPinRead(GPIO_PORTQ_BASE, GPIO_BYTE) & ~ GPIO_PIN_4); //Turn the BLUE led off + +#define RED_LED_ON ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_5, ROM_GPIOPinRead(GPIO_PORTN_BASE, GPIO_BYTE) | GPIO_PIN_5); //Turn the RED led on +#define RED_LED_OFF ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_5, ROM_GPIOPinRead(GPIO_PORTN_BASE, GPIO_BYTE) & ~ GPIO_PIN_5); //Turn the RED led off + +#define LED_SET_DELAY SysCtlDelay(10000000); // need #include "driverlib/sysctl.h" + +void Test_3_Color_Led(); + +#endif //USER_LEDS_H diff --git a/Software/Embedded_SW/Embedded/Modules/Thread/Thread.h b/Software/Embedded_SW/Embedded/Modules/Thread/Thread.h new file mode 100644 index 000000000..475f63795 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Thread/Thread.h @@ -0,0 +1,55 @@ +#include "PMR/common/MessageContainer.pb-c.h" +#include "PMR/Hardware/HardwareMotor.pb-c.h" +#include "PMR/Hardware/HardwareMotorType.pb-c.h" +#include "PMR/Hardware/HardwareDancer.pb-c.h" +#include "PMR/Hardware/HardwareDancerType.pb-c.h" +#include "PMR/Hardware/HardwareWinder.pb-c.h" +#include "PMR/Printing/JobSpool.pb-c.h" +#include "PMR/Printing/JobSpoolType.pb-c.h" + + +typedef struct +{ + HardwareMotorType id; + uint32_t minfreq; + uint32_t maxfreq; + uint32_t minmicrostep; + uint32_t maxmicrostep; + double linearratio; + uint32_t medianposition; + double correctiongain; + double ratio2dryerspeed; + double kp; + double ki; + double kd; + double changeslope; + double hightimeoutusec; +}MotorConfigStruc; +typedef struct +{ + uint32_t startoffsetpulses; + uint32_t spoolbackingrate; + uint32_t segmentoffsetpulses; + uint32_t milimetersperrotation; +}InternalWinderConfigStruc; + +typedef struct +{ + bool fixorgradual; + double k; + double x; + int32_t pulsepermmspring; + int id; //HardwareDancerType +}DancerConfigStruc; +#define MAX_THREAD_MOTORS_NUM HARDWARE_MOTOR_TYPE__WinderMotor +1 + + +extern MotorConfigStruc MotorsCfg[MAX_THREAD_MOTORS_NUM]; +extern InternalWinderConfigStruc InternalWinderCfg; + + +uint32_t InternalWinderConfigMessage(HardwareWinder* request); +uint32_t MotorsConfigMessage(HardwareMotor * request); +uint32_t InternalWindingConfigMessage(JobSpool* request); + +uint32_t DancerConfigMessage(HardwareDancer * request); diff --git a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_BIT.c b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_BIT.c new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_ex.h b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_ex.h new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_init.c b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_init.c new file mode 100644 index 000000000..f32026ca8 --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_init.c @@ -0,0 +1,94 @@ +/************************************************************************************************************************ + **************************************************************************************************************************/ + +#include "include.h" + +#include +#include "PMR/Hardware/HardwareMotor.pb-c.h" +#include "PMR/Hardware/HardwareDancer.pb-c.h" +#include "PMR/Hardware/HardwareWinder.pb-c.h" +#include "PMR/Printing/JobSpool.pb-c.h" +#include "PMR/common/MessageContainer.pb-c.h" + +#include "thread.h" +#define MAX_SYSTEM_DANCERS HARDWARE_DANCER_TYPE__RightDancer+1 +MotorConfigStruc MotorsCfg[MAX_THREAD_MOTORS_NUM]; +InternalWinderConfigStruc InternalWinderCfg; +DancerConfigStruc DancersCfg[MAX_SYSTEM_DANCERS]; + + + +uint32_t InternalWinderConfigMessage(HardwareWinder* request) +{ + uint32_t status = PASSED; + + InternalWinderCfg.milimetersperrotation = request->millimeterperrotation; + + return status; +} +uint32_t InternalWindingConfigMessage(JobSpool* request) +{ + uint32_t status = PASSED; + + InternalWinderCfg.segmentoffsetpulses = request->segmentoffsetpulses; + InternalWinderCfg.spoolbackingrate = request->backingrate; + InternalWinderCfg.startoffsetpulses = request->startoffsetpulses; + + return status; +} + +//******************************************************************************************************************** +uint32_t MotorsConfigMessage(HardwareMotor * request) +{ + uint32_t status = PASSED; + int Motor_i; + + Motor_i = request->hardwaremotortype; + if ((Motor_i)&&(Motor_i< MAX_THREAD_MOTORS_NUM)) + { + MotorsCfg[Motor_i].id = request->hardwaremotortype; + MotorsCfg[Motor_i].minfreq = request->minfrequency; + MotorsCfg[Motor_i].maxfreq = request->maxfrequency; + MotorsCfg[Motor_i].minmicrostep = request->minmicrostep; + MotorsCfg[Motor_i].maxmicrostep = request->maxmicrostep; + MotorsCfg[Motor_i].linearratio = request->linearratio; + MotorsCfg[Motor_i].medianposition = request->medianposition; + MotorsCfg[Motor_i].correctiongain = request->correctiongain; + MotorsCfg[Motor_i].ratio2dryerspeed = request->ratiotodryerspeed; + MotorsCfg[Motor_i].kp = request->kp; + MotorsCfg[Motor_i].ki = request->ki; + MotorsCfg[Motor_i].kd = request->kd; + MotorsCfg[Motor_i].changeslope = request->changeslope; + MotorsCfg[Motor_i].hightimeoutusec = request->highlengthmicrosecond; + return status; + } + else return Motor_i; + +} +uint32_t DancerConfigMessage(HardwareDancer * request) +{ + uint32_t status = PASSED; + int Dancer_i; + + Dancer_i = request->hardwaredancertype; + if ((Dancer_i)&&(Dancer_igradual; + DancersCfg[Dancer_i].k = request->k; + DancersCfg[Dancer_i].x = request->x; + DancersCfg[Dancer_i].pulsepermmspring = request->pulsepermmspring; + return status; + } + else + return Dancer_i; + +} + +uint32_t thread_init(void) +{ + memset (MotorsCfg,0,sizeof(MotorsCfg)); + memset (&InternalWinderCfg,0,sizeof(InternalWinderConfigStruc)); + + return OK; +} diff --git a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_maint.c b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_maint.c new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_print.c b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_print.c new file mode 100644 index 000000000..10baaed8e --- /dev/null +++ b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_print.c @@ -0,0 +1,326 @@ +/************************************************************************************************************************ + * Thread_print.c + * Printing module is responsible for : + * operating diffrent winding algorithms with predefined parameters from the UI + * operating the dispensers according to predefined dispensing rate from the UI + **************************************************************************************************************************/ +#include "include.h" +#include "thread.h" +#include "../control/control.h" +#include "../control/pidalgo.h" +#include "PMR/Hardware/HardwareMotor.pb-c.h" +#include "PMR/Hardware/HardwareMotorType.pb-c.h" +////////////////////////////////State machine operation//////////////////////////////////// +//the state machine operation is used to operate in runtime correct profile flow execution +//by recieved esign flow of the user from the UI +/////////////////////////////////////////////////////////////////////////////////////////// +typedef enum +{ + NextState = 0, + Repeat, + Inter, + Home, + Stop +} ReturnCode; + +/******************************************************************************************** +* functions describes motor operation flow and movement state during profile execution +* used to operate in runtime correct profileflow execution +*********************************************************************************************/ +static ReturnCode EntryState(void *JobDetails); +static ReturnCode PrepareState(void *JobDetails); +static ReturnCode PreSegmentState(void *JobDetails); +static ReturnCode SegmentState(void *JobDetails); +static ReturnCode EndState(void *JobDetails); +static ReturnCode ExitState(void *JobDetails); +; + +/********************************************************************** +* the array and enum of PrintingState_t below must be in sync order +***********************************************************************/ +static ReturnCode (* state[])(void *JobDetails) = { EntryState, PrepareState, PreSegmentState, SegmentState, EndState, ExitState}; + +typedef enum +{ + Entry= 0, + Prepare, + PreSegment, + Segment, + End, + Exit +} PrintingState_t; + +typedef struct +{ + PrintingState_t m_sourceState; + ReturnCode m_returnCode; + PrintingState_t m_destinationState; +} Transition_t; + +//************************************************************* +/* transitions from end state aren't needed */ +//************************************************************* +#define NUM_OF_TRANSITION 17 +#define EXIT_STATE Exit +#define ENTRY_STATE Entry +/************************************************************* + * table which describes fast motors transitions states + * during p_profile / segments execution + *************************************************************/ +static Transition_t stateTransitionTable[NUM_OF_TRANSITION] = +{}; +/* {Entry, NextState, HomingStart}, + {Entry, Repeat, Entry}, //for homing of dispensers + {HomingStart, NextState, Start}, + {HomingStart, Repeat, HomingStart}, + {Start, NextState, Segment}, + {Start, Repeat, Start}, + {Segment, Inter, Intersegment}, + {Segment, Repeat, Segment}, + {Segment, Home, HomingEnd}, + {Intersegment, NextState, Segment}, + {Intersegment, Repeat, Intersegment}, + {Intersegment, Home, HomingEnd}, + {HomingEnd, NextState, End}, + {HomingEnd, Repeat, HomingEnd}, + {End, NextState, Entry}, + {End, Repeat, Entry}, + {Exit, Stop, Exit} //for stoping the machine iteration in case of error +};*/ +typedef struct +{ + bool m_isEnabled; + uint32_t m_SetParam; + uint32_t m_mesuredParam; + float m_preError; + float m_integral; + float m_calculatedError; + bool m_isReady; + PID_Config_Params m_params; +}MotorControlConfig_t; +/*typedef struct +{ + float epsilon; + float dt; + float MAX; + float MIN; + float Kp; + float Kd; + float Ki; +}PID_Config_Params; +#define epsilon 0.01 +#define dt 0.01 //100ms loop time +#define MAX 4 //For Current Saturation +#define MIN -4 +#define Kp 0.1 +#define Kd 0.01 +#define Ki 0.005 +*/ +MotorControlConfig_t MotorControlConfig[MAX_THREAD_MOTORS_NUM]; +uint32_t DeviceId2Motor[MAX_THREAD_MOTORS_NUM]; +////////////////////////Slow Motor State//////////////////////////////////// +static PrintingState_t gPrintingState; +//////////////////////////////////////////////////////////////////////////// + +uint32_t ThreadControlCBFunction(uint32_t deviceID, uint32_t ReadValue) +{ + int i,index=MAX_THREAD_MOTORS_NUM; + for (i=0;i= MotorControlConfig[index].m_params.MAX) + { + MotorControlConfig[index].m_calculatedError = MotorControlConfig[index].m_params.MAX; + } + if (MotorControlConfig[index].m_calculatedError < MotorControlConfig[index].m_params.MIN) + { + MotorControlConfig[index].m_calculatedError = MotorControlConfig[index].m_params.MIN; + } + + //SetMotorFreq (index, MotorControlConfig[index].m_calculatedError); + } + + return OK; +} + +//******************************************************************************************************************** +/******************************************************************************************************************** +*function describes entry point of motor in profile execution - accelerate from stop position +*function described above used to operate motor operation flow and movement state during profile execution +*********************************************************************************************************************/ +static ReturnCode EntryState(void *JobDetails) +{ + return NextState; +} + +//******************************************************************************************************************** +static ReturnCode PrepareState(void *JobDetails) +{ + int Motor_i; + //start thread control for all motors + for (Motor_i = 0;Motor_i < MAX_THREAD_MOTORS_NUM;Motor_i++) + { + MotorControlConfig[Motor_i].m_params.MAX = MotorsCfg[Motor_i].maxfreq; + MotorControlConfig[Motor_i].m_params.MIN = MotorsCfg[Motor_i].minfreq; + MotorControlConfig[Motor_i].m_params.Kd = MotorsCfg[Motor_i].kd; + MotorControlConfig[Motor_i].m_params.Kp = MotorsCfg[Motor_i].kp; + MotorControlConfig[Motor_i].m_params.Ki = MotorsCfg[Motor_i].ki; + MotorControlConfig[Motor_i].m_params.dt = eOneMillisecond; + MotorControlConfig[Motor_i].m_calculatedError = 0; + MotorControlConfig[Motor_i].m_integral = 0; + MotorControlConfig[Motor_i].m_isEnabled = true; + MotorControlConfig[Motor_i].m_isReady = true; + MotorControlConfig[Motor_i].m_mesuredParam = 0; + MotorControlConfig[Motor_i].m_preError = 0; + MotorControlConfig[Motor_i].m_SetParam = 0;//need to update SetParams on presegment stage + AddControlCallback(DeviceId2Motor[Motor_i], ThreadControlCBFunction, eOneMillisecond); + } + //set 3 dancers to the profile positions + return NextState; +} + +//******************************************************************************************************************** +static ReturnCode PreSegmentState(void *JobDetails) +{ + + int Motor_i; + for (Motor_i = 0;Motor_i < MAX_THREAD_MOTORS_NUM;Motor_i++) + { + MotorControlConfig[Motor_i].m_SetParam = getMotorFreq(Motor_i);//need to update SetParams on presegment stage + } + // set the new speed in the dryer motor to the speed of the new segment + // activate control fr all motors + //set speed for both rocker motors + //wait for all motors to get to the required speed (set the target speed for the control to check) + //call the job state machine when the thread system is ready + return NextState; +} + +//******************************************************************************************************************** +static ReturnCode SegmentState(void *JobDetails) +{ + return Repeat; +} + +//******************************************************************************************************************** +static ReturnCode EndState(void *JobDetails) +{ + return NextState; +} +//******************************************************************************************************************** +static ReturnCode ExitState(void *JobDetails) +{ + return Stop; +} + + +//*********************************************************************************************************************** +//this function is responsible for operating and transitioning between the diffrent motor state executions of the profile +//the lower managment level +//*********************************************************************************************************************** +static PrintingState_t LookupTransitions(PrintingState_t state,ReturnCode returnCode) +{ + char str[80]; + uint8_t len = 0; + uint8_t indexInTransitionTable; + for (indexInTransitionTable = 0; indexInTransitionTable < NUM_OF_TRANSITION; ++indexInTransitionTable) + { + if ((stateTransitionTable[indexInTransitionTable].m_sourceState == state) && (stateTransitionTable[indexInTransitionTable].m_returnCode == returnCode)) + { + //len = usnprintf(str, 60, "\r\n tick %d state %d return code %d",tick,state, returnCode ); + //cb_push_back (str, len); + + //in normal execution flow function should not arrive here + //in case it did the meaning is that the entery point was wrong and a bug should be corrected + return stateTransitionTable[indexInTransitionTable].m_destinationState; + } + } + //int tick = UsersysTickGet(); + //len = usnprintf(str, 60, "\r\n tick %d state %d return code %d",tick,state, returnCode ); + //cb_push_back (str, len); + + //in normal execution flow function should not arrive here + //in case it did the meaning is that the entery point was wrong and a bug should be corrected + len = usnprintf(str, 80, "Internal: invalid slow motor transition state %d return code %d",state, returnCode ); + + return EXIT_STATE; +} +//******************************************************************************** +//this function is used to manage and operate the motor managmant state mashine +//the highest managment level +//******************************************************************************** +bool ThreadPrintingIterate(void *JobDetails) +{ + uint32_t tick = 0; + char str[60]; + uint8_t len = 0; + PrintingState_t keepstate = gPrintingState; + // + // Disable all interrupts. + // + ROM_IntMasterDisable(); + + ReturnCode (* state_fun)(void *JobDetails) = state[gPrintingState]; + //if (_motorId == SCREW_MOTOR) + // screw_movement[gPrintingState[_motorId]]++; + ReturnCode returnCode = state_fun(JobDetails); + + /*if ((_motorId == SCREW_MOTOR)&&(pause_active)) + { + tick = UsersysTickGet(); + len = usnprintf(str, 60, "\r\n PrintingIterate tick %d state %d retcode %d ",tick, gPrintingState[_motorId],returnCode); + cb_push_back (str, len); + //SendInterruptMessageToHost(10+gPrintingState[_motorId],returnCode); + }*/ + gPrintingState = LookupTransitions(gPrintingState, returnCode); + if (keepstate != gPrintingState){ + tick = UsersysTickGet(); + len = usnprintf(str, 60, "\r\n changed state tick %d state %d retcode %d ", tick, gPrintingState,returnCode); + cb_push_back (str, len); + + } + + // + // Enable all interrupts. + // + ROM_IntMasterEnable(); + return (gPrintingState != EXIT_STATE); +} + + +//******************************************************************************************************************** + +void ThreadPrintingsInit(void) +{ +// gPrintingState = Start; +} + +//******************************************************************************************************************** + +void ThreadStartPrinting(void) +{ + gPrintingState = ENTRY_STATE; + //PrintingIterate(); +} + +//******************************************************************************************************************** +//******************************************************************************************************************** + +void ThreadStopPrinting(void) +{ + gPrintingState = EXIT_STATE; + //PrintingIterate(); +} diff --git a/Software/Embedded_SW/Embedded/Modules/Waste/Waste.h b/Software/Embedded_SW/Embedded/Modules/Waste/Waste.h new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/Waste/Waste_BIT.c b/Software/Embedded_SW/Embedded/Modules/Waste/Waste_BIT.c new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/Waste/Waste_ex.h b/Software/Embedded_SW/Embedded/Modules/Waste/Waste_ex.h new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/Waste/Waste_init.c b/Software/Embedded_SW/Embedded/Modules/Waste/Waste_init.c new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/Waste/Waste_maint.c b/Software/Embedded_SW/Embedded/Modules/Waste/Waste_maint.c new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/Modules/Waste/Waste_print.c b/Software/Embedded_SW/Embedded/Modules/Waste/Waste_print.c new file mode 100644 index 000000000..e69de29bb diff --git a/Software/Embedded_SW/Embedded/StateMachines/Printing/JobSTM.c b/Software/Embedded_SW/Embedded/StateMachines/Printing/JobSTM.c new file mode 100644 index 000000000..b62f538e8 --- /dev/null +++ b/Software/Embedded_SW/Embedded/StateMachines/Printing/JobSTM.c @@ -0,0 +1,341 @@ +/************************************************************************************************************************ + * Printing.c + * High managment logical unit of slow motors in the system ( 6 dispensers and the screw motor) + * profile run up begins from screw homing to begin position and only then from fast motors activation. + * when every slow motor tuches the limit switch (no matter whether its screw or dispenser) + * an interrupt occures in the system and as long as its pushing the limit switch all the system is prevented from operation. + * because of that the work flow with interrupts must be : + * design a function handle (what to do in the moment the interrupt arrives) + * configure the wanted interrupt in the cfg file (according to the defined port and pin and its interrupt number and the handler) + * enable interupt for predefined gpio in the application + * when the interrupt arrives the handle will be automatically called + * in case of the limit switches since the operation is continuess the interrupt must be disabled in order to continue the application running. + * then the operation is not continues (like butten pushing) there is no need in disabling the interrupts + + * Printing module is responsible for : + * operating diffrent winding algorithms with predefined parameters from the UI + * operating the dispensers according to predefined dispensing rate from the UI + **************************************************************************************************************************/ + +////////////////////////////////State machine operation//////////////////////////////////// +//the state machine operation is used to operate in runtime correct profile flow execution +//by recieved esign flow of the user from the UI +/////////////////////////////////////////////////////////////////////////////////////////// +#include "include.h" +#include +#include +#include + +#include +#include "PMR/Printing/JobSegment.pb-c.h" +#include "PMR/Printing/JobRequest.pb-c.h" +#include "PMR/Hardware/Hardwaremotor.pb-c.h" +#include "PMR/Hardware/HardwareWinder.pb-c.h" +#include "PMR/common/MessageContainer.pb-c.h" +#include "Modules/Stubs_Handler/Container.h" + +#include "./printingSTM.h" + + +#define INVALID_MSG_ID 0xFFFF + +Mailbox_Handle JobmsgQ = NULL; + +static Clock_Handle JobClock; +static Clock_Params jobclkParams; + +char JobDetails[MAX_MSG_LEN]; + +#define MAX_TICKET_SIZE 10000 +SegmentGradientStruc SegmentGradient; +char CurrentJobBuffer[MAX_TICKET_SIZE]; +JobTicket *CurrentJob = (JobTicket *)CurrentJobBuffer; +char PreviousJobBuffer[MAX_TICKET_SIZE]; +JobTicket *PreviousJob = (JobTicket *)PreviousJobBuffer; + + + +typedef enum +{ + JobSuccess = 0, + JobFail, + JobStop +} ReturnCode; + +/******************************************************************************************** +* functions describes motor operation flow and movement state during profile execution +* used to operate in runtime correct profileflow execution +*********************************************************************************************/ +static ReturnCode IdleState(void *JobDetails); +static ReturnCode ValidateState(void *JobDetails); +static ReturnCode PrepareState(void *JobDetails); +static ReturnCode PrintState(void *JobDetails); +static ReturnCode CleanState(void *JobDetails); +static ReturnCode ExitState(void *JobDetails); +/********************************************************************** +* the array and enum of JobState_t below must be in sync order +***********************************************************************/ +static ReturnCode (* state[])(void *JobDetails) = { IdleState, ValidateState, PrepareState, PrintState, CleanState}; + + +typedef enum +{ + Idle= 0, + Validate, + PrepareJob, + Print, + Clean, + ExitJob +} JobState_t; + +typedef struct +{ + JobState_t m_sourceState; + ReturnCode m_returnCode; + JobState_t m_destinationState; +} Transition_t; + + +//************************************************************* +/* transitions from end state aren't needed */ +//************************************************************* +#define NUM_OF_TRANSITION 11 +#define ENTRY_STATE Idle +/************************************************************* + * table which describes fast motors transitions states + * during p_profile / segments execution + *************************************************************/ +static Transition_t stateTransitionTable[NUM_OF_TRANSITION] = +{ + {Idle, JobSuccess, Validate}, + {Validate, JobSuccess, PrepareJob}, + {PrepareJob,JobSuccess, Print}, + {Print, JobSuccess, Clean}, + {Clean, JobSuccess, Idle}, + {Idle, JobFail, Idle}, + {Validate, JobFail, Idle}, + {PrepareJob,JobFail, Idle}, + {Print, JobFail, Clean}, + {Clean, JobFail, Idle}, + {ExitJob, JobStop, ExitJob} //for stoping the machine iteration in case of error +}; + +////////////////////////Slow Motor State//////////////////////////////////// +static JobState_t gJobState_t; +char JobToken[36]; + +//////////////////////////////////////////////////////////////////////////// +void StartJob(void *JobDetails); + + +//******************************************************************************************************************** +/******************************************************************************************************************** +*function describes entry point of motor in profile execution - accelerate from stop position +*function described above used to operate motor operation flow and movement state during profile execution +*********************************************************************************************************************/ +static ReturnCode IdleState(void *JobDetails) +{ + ReturnCode retcode; + retcode = JobSuccess; + + return retcode; +} +//******************************************************************************************************************** +static ReturnCode ValidateState(void *JobDetails) +{ + ReturnCode retcode; + retcode = JobSuccess; + + return retcode; +} + +//******************************************************************************************************************** +static ReturnCode PrepareState(void *JobDetails) +{ + ReturnCode retcode; + retcode = JobSuccess; + + return retcode; +} + +//******************************************************************************************************************** +static ReturnCode PrintState(void *JobDetails) +{ + ReturnCode retcode; + retcode = JobSuccess; + + return retcode; +} + +//******************************************************************************************************************** +static ReturnCode CleanState(void *JobDetails) +{ + ReturnCode retcode; + retcode = JobSuccess; + + return retcode; +} +//******************************************************************************************************************** +static ReturnCode ExitState(void *JobDetails) +{ + ReturnCode retcode; + retcode = JobStop; + + return retcode; +} + +static void JobClockHandle(UArg arg0) +{ + //Clock_setTimeout(JobClock, 1000); + //Clock_start(JobClock); + +} + +//******************************************************************************************************************** + +void JobInit(void) +{ + gJobState_t = Idle; + JobmsgQ = Mailbox_create(MAX_MSG_LEN, 20, NULL,NULL); + Clock_Params_init(&jobclkParams); + jobclkParams.period = 0; + jobclkParams.startFlag = FALSE; + JobClock = Clock_create(JobClockHandle, 0, &jobclkParams, NULL); + return ; +} +//******************************************************************************************************************** +//******************************************************************************************************************** +void JobRequestFunc(MessageContainer* requestContainer) +{ + uint32_t status = NOT_SUPPORTED; + MessageContainer responseContainer; + uint8_t* container_buffer; + + + JobRequest* request = job_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); + + strcpy (JobToken, requestContainer->token); + JobTicket *Ticket = request->jobticket; + int TicketSize = job_ticket__get_packed_size(Ticket); + if (TicketSize >= MAX_TICKET_SIZE) + { + LOG_ERROR (TicketSize, "job ticket message too long"); + status = FAILED; + } + else + { + memcpy(CurrentJob, Ticket,TicketSize); + status = PASSED; + StartJob(&CurrentJob); + } + + JobResponse response = JOB_RESPONSE__INIT; + if (status == PASSED) + { + + responseContainer = createContainer(MESSAGE_TYPE__JobResponse, JobToken, false, &response, &job_response__pack, &job_response__get_packed_size); + container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + + strcpy (response.status->message,"Job Accepted"); + response.status->has_progress = true; + response.status->progress = 0.0; + response.status->has_currentsegmentindex = false; + } + else + { + + responseContainer = createContainer(MESSAGE_TYPE__JobResponse, JobToken, true, &response, &job_response__pack, &job_response__get_packed_size); + container_buffer = malloc(message_container__get_packed_size(&responseContainer)); + responseContainer.has_error = true; + responseContainer.error = ERROR_CODE__BAD_CRC; + + strcpy (response.status->message,"Job message too large"); + response.status->has_progress = true; + response.status->progress = 0.0; + response.status->has_currentsegmentindex = false; + } + + size_t container_size = message_container__pack(&responseContainer, container_buffer); + SendChars((char*)container_buffer, container_size); + free(container_buffer); + free(requestContainer); +} + +void StartJob(void *JobDetails) +{ + JobMessageStruc Message; + bool retcode = false; + + Message.messageId = JobRequestMsg; + memcpy(Message.messageData,JobDetails,MAX_MSG_LEN); + Message.msglen = MAX_MSG_LEN; + if (JobmsgQ != NULL) + retcode = Mailbox_post(JobmsgQ , &Message, BIOS_NO_WAIT); +} + +/****************************************************************************** + * ======== messageTsk ======== + * Task for this function is created statically. See the project's .cfg file. + * this message task is created statically in system initialization, + ******************************************************************************/ +Void jobTask(UArg arg0, UArg arg1) +{ + JobMessageStruc Message; + //char str[60]; + //uint16_t length; + //Clock_setTimeout(HostKAClock, 1000); + //Clock_start(HostKAClock); + + + while(1) + { + Mailbox_pend(JobmsgQ , &Message, BIOS_WAIT_FOREVER); + switch (Message.messageId) + { + case JobRequestMsg: + memcpy(JobDetails,Message.messageData, Message.msglen); + ValidateState (&JobDetails); + break; + case ValidationResultsOk: + PrepareState (&JobDetails); + break; + case ValidationResultsFail: + //send message data as a validation error message to host + ExitState(Message.messageData); + break; + case PreparationResultsOk: + PrintState(&JobDetails); + break; + case PreparationResultsFail: + //send message data as a validation error message to host + ExitState(Message.messageData); + break; + case PrintMessage: + //send message data as a validation error message to host + PrintSTMMsgHandler(&Message); + break; + case PrintingResultsOk: + CleanState(&JobDetails); + break; + case PrintingResultsFail: + //send message data as a validation error message to host + ExitState(Message.messageData); + break; + case CleaningResultsOk: + //send message data as a validation error message to host + ExitState(Message.messageData); + break; + case CleaningResultsFail: + //send message data as a validation error message to host + ExitState(Message.messageData); + break; + case SystemFailure: + //send message data as a validation error message to host + ExitState(Message.messageData); + break; + default: + break; + } + } +} + diff --git a/Software/Embedded_SW/Embedded/StateMachines/Printing/PrintingSTM.c b/Software/Embedded_SW/Embedded/StateMachines/Printing/PrintingSTM.c new file mode 100644 index 000000000..76b7b2a69 --- /dev/null +++ b/Software/Embedded_SW/Embedded/StateMachines/Printing/PrintingSTM.c @@ -0,0 +1,274 @@ +/************************************************************************************************************************ + * Printing.c + * High managment logical unit of slow motors in the system ( 6 dispensers and the screw motor) + * profile run up begins from screw homing to begin position and only then from fast motors activation. + * when every slow motor tuches the limit switch (no matter whether its screw or dispenser) + * an interrupt occures in the system and as long as its pushing the limit switch all the system is prevented from operation. + * because of that the work flow with interrupts must be : + * design a function handle (what to do in the moment the interrupt arrives) + * configure the wanted interrupt in the cfg file (according to the defined port and pin and its interrupt number and the handler) + * enable interupt for predefined gpio in the application + * when the interrupt arrives the handle will be automatically called + * in case of the limit switches since the operation is continuess the interrupt must be disabled in order to continue the application running. + * then the operation is not continues (like butten pushing) there is no need in disabling the interrupts + + * Printing module is responsible for : + * operating diffrent winding algorithms with predefined parameters from the UI + * operating the dispensers according to predefined dispensing rate from the UI + **************************************************************************************************************************/ +#include "include.h" +#include "./printingSTM.h" + +////////////////////////////////State machine operation//////////////////////////////////// +//the state machine operation is used to operate in runtime correct profile flow execution +//by recieved esign flow of the user from the UI +/////////////////////////////////////////////////////////////////////////////////////////// +typedef enum +{ + NextState = 0, + Repeat, + Inter, + Home, + Stop +} ReturnCode; + +/******************************************************************************************** +* functions describes motor operation flow and movement state during profile execution +* used to operate in runtime correct profileflow execution +*********************************************************************************************/ +static ReturnCode EntryState(void *JobDetails); +static ReturnCode PrepareState(void *JobDetails); +static ReturnCode PreSegmentState(void *JobDetails); +static ReturnCode SegmentState(void *JobDetails); +static ReturnCode EndState(void *JobDetails); +static ReturnCode ExitState(void *JobDetails); + +/********************************************************************** +* the array and enum of PrintingState_t below must be in sync order +***********************************************************************/ +static ReturnCode (* state[])(void *JobDetails) = { EntryState, PrepareState, PreSegmentState, SegmentState, EndState, ExitState}; + + +typedef enum +{ + PrintRequest, + PreSegmentResultsOk, + PreSegmentResultsFail, + SegmentResultsOk, + SegmentResultsFail, + FinishResultsOk, + FinishResultsFail, + PrintSystemFailure +}PrintSTMEventsEnum; + +typedef struct +{ + PrintingState_t m_sourceState; + ReturnCode m_returnCode; + PrintingState_t m_destinationState; +} Transition_t; + +//************************************************************* +/* transitions from end state aren't needed */ +//************************************************************* +#define NUM_OF_TRANSITION 17 +#define ENTRY_STATE Entry +/************************************************************* + * table which describes fast motors transitions states + * during p_profile / segments execution + *************************************************************/ +static Transition_t stateTransitionTable[NUM_OF_TRANSITION] = {}; +/*{ + {Entry, NextState, HomingStart}, + {Entry, Repeat, Entry}, //for homing of dispensers + {HomingStart, NextState, Start}, + {HomingStart, Repeat, HomingStart}, + {Start, NextState, Segment}, + {Start, Repeat, Start}, + {Segment, Inter, Intersegment}, + {Segment, Repeat, Segment}, + {Segment, Home, HomingEnd}, + {Intersegment, NextState, Segment}, + {Intersegment, Repeat, Intersegment}, + {Intersegment, Home, HomingEnd}, + {HomingEnd, NextState, End}, + {HomingEnd, Repeat, HomingEnd}, + {End, NextState, Entry}, + {End, Repeat, Entry}, + {Exit, Stop, Exit} //for stoping the machine iteration in case of error +};*/ + +////////////////////////Slow Motor State//////////////////////////////////// +static PrintingState_t gPrintingState; +//////////////////////////////////////////////////////////////////////////// + + +//******************************************************************************************************************** +/******************************************************************************************************************** +*function describes entry point of motor in profile execution - accelerate from stop position +*function described above used to operate motor operation flow and movement state during profile execution +*********************************************************************************************************************/ +static ReturnCode EntryState(void *JobDetails) +{ + return NextState; +} + +//******************************************************************************************************************** +static ReturnCode PrepareState(void *JobDetails) +{ + return NextState; +} + +//******************************************************************************************************************** +static ReturnCode PreSegmentState(void *JobDetails) +{ + + return NextState; +} + +//******************************************************************************************************************** +static ReturnCode SegmentState(void *JobDetails) +{ + return Repeat; +} + +//******************************************************************************************************************** +static ReturnCode EndState(void *JobDetails) +{ + return NextState; +} +//******************************************************************************************************************** +static ReturnCode ExitState(void *JobDetails) +{ + return Stop; +} + +//*********************************************************************************************************************** +//this function is responsible for operating and transitioning between the diffrent motor state executions of the profile +//the lower managment level +//*********************************************************************************************************************** +static PrintingState_t LookupTransitions(PrintingState_t state,ReturnCode returnCode) +{ + char str[80]; + uint8_t len = 0; + uint8_t indexInTransitionTable; + for (indexInTransitionTable = 0; indexInTransitionTable < NUM_OF_TRANSITION; ++indexInTransitionTable) + { + if ((stateTransitionTable[indexInTransitionTable].m_sourceState == state) && (stateTransitionTable[indexInTransitionTable].m_returnCode == returnCode)) + { + //len = usnprintf(str, 60, "\r\n tick %d state %d return code %d",tick,state, returnCode ); + //cb_push_back (str, len); + + //in normal execution flow function should not arrive here + //in case it did the meaning is that the entery point was wrong and a bug should be corrected + return stateTransitionTable[indexInTransitionTable].m_destinationState; + } + } + //int tick = UsersysTickGet(); + //len = usnprintf(str, 60, "\r\n tick %d state %d return code %d",tick,state, returnCode ); + //cb_push_back (str, len); + + //in normal execution flow function should not arrive here + //in case it did the meaning is that the entery point was wrong and a bug should be corrected + len = usnprintf(str, 80, "Internal: invalid slow motor transition state %d return code %d",state, returnCode ); + + return EXIT_STATE; +} +//******************************************************************************** +//this function is used to manage and operate the motor managmant state mashine +//the highest managment level +//******************************************************************************** +bool PrintingIterate(void *JobDetails) +{ + uint32_t tick = 0; + char str[60]; + uint8_t len = 0; + PrintingState_t keepstate = gPrintingState; + // + // Disable all interrupts. + // + ROM_IntMasterDisable(); + + ReturnCode (* state_fun)(void *JobDetails) = state[gPrintingState]; + //if (_motorId == SCREW_MOTOR) + // screw_movement[gPrintingState]++; + ReturnCode returnCode = state_fun(JobDetails); + + /*if ((_motorId == SCREW_MOTOR)&&(pause_active)) + { + tick = UsersysTickGet(); + len = usnprintf(str, 60, "\r\n PrintingIterate tick %d state %d retcode %d ",tick, gPrintingState,returnCode); + cb_push_back (str, len); + //SendInterruptMessageToHost(10+gPrintingState,returnCode); + }*/ + gPrintingState = LookupTransitions(gPrintingState, returnCode); + if (keepstate != gPrintingState){ + tick = UsersysTickGet(); + len = usnprintf(str, 60, "\r\n changed state tick %d state %d retcode %d ", tick, gPrintingState,returnCode); + cb_push_back (str, len); + + } + + // + // Enable all interrupts. + // + ROM_IntMasterEnable(); + return (gPrintingState != EXIT_STATE); +} + + +//******************************************************************************************************************** + +void PrintingsInit(void) +{ +} + +//******************************************************************************************************************** + +void StartPrinting(void) +{ +} + +//******************************************************************************************************************** +//******************************************************************************************************************** + +void StopPrinting(void) +{ +} +void PrintSTMMsgHandler(void * msg) +{ + JobMessageStruc *Message = msg; + PrintMessageStruc *PrtMessage = (PrintMessageStruc *)Message->messageData; + + Report(REPORT_LINE("PrintSTMMsgHandler"),__FILE__,__LINE__, RpMessage,0x1000,Message->messageId,PrtMessage->messageId); + + if (Message->messageId != PrintMessage) + { + //REPORT_ERR ... + return; + } + switch(PrtMessage->messageId) + { + case PrintRequest: + break; + case PreSegmentResultsOk: + break; + case PreSegmentResultsFail: + break; + case SegmentResultsOk: + break; + case SegmentResultsFail: + break; + case FinishResultsOk: + break; + case FinishResultsFail: + break; + case PrintSystemFailure: + break; + default: + break; + } + + + +} diff --git a/Software/Embedded_SW/Embedded/StateMachines/Printing/PrintingSTM.h b/Software/Embedded_SW/Embedded/StateMachines/Printing/PrintingSTM.h new file mode 100644 index 000000000..e9aa4cffd --- /dev/null +++ b/Software/Embedded_SW/Embedded/StateMachines/Printing/PrintingSTM.h @@ -0,0 +1,97 @@ +/************************************************************************************************************************ + * PrintSTM.c + * High managment logical unit of slow motors in the system ( 6 dispensers and the screw) + * profile run up begins from screw homing to begin position and only then from fast motors activation. + * SlowMotor module is responsible for : + * operating diffrent winding algorithms with predefined parameters from the UI + * operating the dispensers according to predefined dispensing rate from the UI + **************************************************************************************************************************/ + +#ifndef STATEMACHINES_PRINTSTM_H_ +#define STATEMACHINES_PRINTSTM_H_ + +//#include "include.h" +#include "PMR/common/MessageContainer.pb-c.h" +#include "PMR/Hardware/HardwareDispenser.pb-c.h" +#include "PMR/Printing/JobSegment.pb-c.h" +#include "PMR/Printing/JobRequest.pb-c.h" +#include "PMR/Printing/JobTicket.pb-c.h" +#include "PMR/Printing/JobResponse.pb-c.h" + +#define MAX_MSG_LEN 100 +typedef enum +{ + Entry= 0, + Prepare, + PreSegment, + PrintSegment, + End, + ExitPrint +} PrintingState_t; +#define EXIT_STATE ExitPrint + +typedef enum +{ + JobRequestMsg, + ValidationResultsOk, + ValidationResultsFail, + PreparationResultsOk, + PreparationResultsFail, + PrintMessage, + PrintingResultsOk, + PrintingResultsFail, + CleaningResultsOk, + CleaningResultsFail, + SystemFailure +}JobSTMEventsEnum; +#define MAX_JOB_NAME_LEN 40 +#define MAX_SEGMENT_NUM 30 +#define MAX_GRADIENT_STAGES_PER_SEGMENT_NUM 50 +#define MAX_DISPENSER_NUM 8 + +typedef struct +{ + int32_t prevstepmiliseconds; + double nlflow; +}GradientFlowStruc; +typedef struct +{ + size_t n_gradients; + GradientFlowStruc gradient[MAX_GRADIENT_STAGES_PER_SEGMENT_NUM]; +}SegmentGradientStruc; + +typedef struct +{ + int32_t id; + double startflow; +}DispenserStruc; + +typedef struct +{ + char Segmentname[MAX_JOB_NAME_LEN]; + int32_t length; + //RGB *color; + size_t n_dispensers; + DispenserStruc dispenser[MAX_DISPENSER_NUM]; +}SegmentStruc; + + + +typedef struct JobMessage{ + uint16_t messageId; + uint16_t msglen; + uint8_t messageData[MAX_MSG_LEN]; +}JobMessageStruc; +typedef struct PrintMessage{ + uint16_t messageId; + uint16_t msglen; + uint8_t messageData[MAX_MSG_LEN]; +}PrintMessageStruc; + +void PrintSTMMsgHandler(void * msg); +void JobInit(void); +void PrintingsInit(void); + +void JobRequestFunc(MessageContainer* requestContainer); + +#endif /* STATEMACHINES_PRINTSTM_H_ */ diff --git a/Software/Embedded_SW/Embedded/src/.exclude b/Software/Embedded_SW/Embedded/src/.exclude new file mode 100644 index 000000000..8c863310d --- /dev/null +++ b/Software/Embedded_SW/Embedded/src/.exclude @@ -0,0 +1 @@ +This file exists to prevent Eclipse/CDT from adding the C sources contained in this directory (or below) to any enclosing project. diff --git a/Software/Embedded_SW/Embedded/src/makefile.libs b/Software/Embedded_SW/Embedded/src/makefile.libs new file mode 100644 index 000000000..ae6999352 --- /dev/null +++ b/Software/Embedded_SW/Embedded/src/makefile.libs @@ -0,0 +1,62 @@ +# +# This file was generated based on the configuration script: +# C:\tango\Software\Embedded_SW\Embedded\Embedded.cfg +# +# This makefile may be included in other makefiles that need to build +# the libraries containing the compiled source files generated as +# part of the configuration step. + +# +# ======== GEN_SRC_DIR ========= +# The path to the sources generated during configuration +# +# This path must be either absolute or relative to the build directory. +# +# The absolute path to the generated source directory (at the time the +# sources were generated) is: +# C:\tango\Software\Embedded_SW\Embedded\src +# +GEN_SRC_DIR ?= ../src + +ifeq (,$(wildcard $(GEN_SRC_DIR))) +$(error "ERROR: GEN_SRC_DIR must be set to the directory containing the generated sources") +endif + +# +# ======== .force ======== +# The .force goal is used to force the build of any goal that names it as +# a prerequisite +# +.PHONY: .force + +# +# ======== library macros ======== +# +sysbios_SRC = $(GEN_SRC_DIR)/sysbios +sysbios_LIB = $(GEN_SRC_DIR)/sysbios/sysbios.aem4f + +# +# ======== dependencies ======== +# +all: $(sysbios_LIB) +clean: .sysbios_clean + + +# ======== convenient build goals ======== +.PHONY: sysbios +sysbios: $(GEN_SRC_DIR)/sysbios/sysbios.aem4f + +# CDT managed make executables depend on $(OBJS) +OBJS += $(sysbios_LIB) + +# +# ======== rules ======== +# +$(sysbios_LIB): .force + @echo making $@ ... + @$(MAKE) -C $(sysbios_SRC) + +.sysbios_clean: + @echo cleaning $(sysbios_SRC) ... + -@$(MAKE) --no-print-directory -C $(sysbios_SRC) clean + diff --git a/Software/Embedded_SW/Embedded/src/sysbios/makefile b/Software/Embedded_SW/Embedded/src/sysbios/makefile new file mode 100644 index 000000000..b8d0ab697 --- /dev/null +++ b/Software/Embedded_SW/Embedded/src/sysbios/makefile @@ -0,0 +1,96 @@ + +XOPTS = -I"C:/ti/xdctools_3_32_00_06_core/packages/" -Dxdc_target_types__=C:/ti/tirtos_tivac_2_16_01_14/products/bios_6_45_02_31/packages/ti/targets/arm/elf/std.h -Dxdc_target_name__=M4F + +vpath % C:/ti/tirtos_tivac_2_16_01_14/products/bios_6_45_02_31/packages/ti/sysbios/ +vpath %.c C:/ti/xdctools_3_32_00_06_core/packages/ + +CCOPTS = --endian=little -mv7M4 --abi=eabi --float_support=fpv4spd16 -q -ms --opt_for_speed=2 --program_level_compile -o3 -g --optimize_with_debug -Dti_sysbios_knl_Task_minimizeLatency__D=FALSE -Dti_sysbios_knl_Clock_stopCheckNext__D=FALSE -Dti_sysbios_family_arm_m3_Hwi_enableException__D=TRUE -Dti_sysbios_family_arm_m3_Hwi_disablePriority__D=32U -Dti_sysbios_family_arm_m3_Hwi_numSparseInterrupts__D=0U + +XDC_ROOT = C:/ti/xdctools_3_32_00_06_core/packages/ + +BIOS_ROOT = C:/ti/tirtos_tivac_2_16_01_14/products/bios_6_45_02_31/packages/ti/sysbios/ + +BIOS_DEFS = -Dti_sysbios_BIOS_swiEnabled__D=TRUE -Dti_sysbios_BIOS_taskEnabled__D=TRUE -Dti_sysbios_BIOS_clockEnabled__D=TRUE -Dti_sysbios_BIOS_runtimeCreatesEnabled__D=TRUE -Dti_sysbios_hal_Hwi_DISABLE_ALL_HOOKS -Dti_sysbios_knl_Swi_DISABLE_ALL_HOOKS -Dti_sysbios_BIOS_smpEnabled__D=FALSE -Dti_sysbios_Build_useHwiMacros -Dti_sysbios_knl_Swi_numPriorities__D=16 -Dti_sysbios_knl_Task_deleteTerminatedTasks__D=FALSE -Dti_sysbios_knl_Task_numPriorities__D=16 -Dti_sysbios_knl_Task_checkStackFlag__D=TRUE -Dti_sysbios_knl_Task_initStackFlag__D=TRUE -Dti_sysbios_knl_Task_DISABLE_ALL_HOOKS -Dti_sysbios_knl_Clock_TICK_SOURCE=ti_sysbios_knl_Clock_TickSource_TIMER -Dti_sysbios_knl_Clock_TICK_MODE=ti_sysbios_knl_Clock_TickMode_PERIODIC -Dti_sysbios_hal_Core_delegate_getId=ti_sysbios_hal_CoreNull_getId__E -Dti_sysbios_hal_Core_delegate_interruptCore=ti_sysbios_hal_CoreNull_interruptCore__E -Dti_sysbios_hal_Core_delegate_lock=ti_sysbios_hal_CoreNull_lock__E -Dti_sysbios_hal_Core_delegate_unlock=ti_sysbios_hal_CoreNull_unlock__E -Dti_sysbios_hal_Core_numCores__D=1 -Dti_sysbios_hal_CoreNull_numCores__D=1 -Dti_sysbios_utils_Load_taskEnabled__D=TRUE -Dti_sysbios_utils_Load_swiEnabled__D=FALSE -Dti_sysbios_utils_Load_hwiEnabled__D=FALSE -Dti_sysbios_family_arm_m3_Hwi_dispatcherSwiSupport__D=TRUE -Dti_sysbios_family_arm_m3_Hwi_dispatcherTaskSupport__D=TRUE -Dti_sysbios_family_arm_m3_Hwi_dispatcherAutoNestingSupport__D=TRUE -Dti_sysbios_family_arm_m3_Hwi_dispatcherIrpTrackingSupport__D=TRUE -Dti_sysbios_knl_Semaphore_supportsEvents__D=FALSE -Dti_sysbios_knl_Semaphore_supportsPriority__D=TRUE + +BIOS_INC = -I"C:/ti/tirtos_tivac_2_16_01_14/products/bios_6_45_02_31/packages/" + +TARGET_INC = -I"C:/ti/tirtos_tivac_2_16_01_14/products/bios_6_45_02_31/packages/" + +INCS = $(BIOS_INC) $(TARGET_INC) + +CC = C:/ti/ccsv7/tools/compiler/ti-cgt-arm_16.9.2.LTS/bin/armcl -c $(CCOPTS) -I C:/ti/ccsv7/tools/compiler/ti-cgt-arm_16.9.2.LTS/include +ASM = C:/ti/ccsv7/tools/compiler/ti-cgt-arm_16.9.2.LTS/bin/armcl -c $(CCOPTS) -I C:/ti/ccsv7/tools/compiler/ti-cgt-arm_16.9.2.LTS/include +AR = C:/ti/ccsv7/tools/compiler/ti-cgt-arm_16.9.2.LTS/bin/armar rq + +DEL = C:/ti/xdctools_3_32_00_06_core/packages/../bin/rm -f +CP = C:/ti/xdctools_3_32_00_06_core/packages/../bin/cp -f + +define RM + $(if $(wildcard $1),$(DEL) $1,:) +endef + +define ASSEMBLE + @echo asmem4f $< ... + @$(ASM) $(BIOS_DEFS) $(XOPTS) $(INCS) $< +endef + +all: sysbios.aem4f + +m3_Hwi_asm.obj: family/arm/m3/Hwi_asm.sv7M makefile + @-$(call RM, $@) + $(ASSEMBLE) --output_file=m3_Hwi_asm.obj + +m3_Hwi_asm_switch.obj: family/arm/m3/Hwi_asm_switch.sv7M makefile + @-$(call RM, $@) + $(ASSEMBLE) --output_file=m3_Hwi_asm_switch.obj + +m3_IntrinsicsSupport_asm.obj: family/arm/m3/IntrinsicsSupport_asm.sv7M makefile + @-$(call RM, $@) + $(ASSEMBLE) --output_file=m3_IntrinsicsSupport_asm.obj + +m3_TaskSupport_asm.obj: family/arm/m3/TaskSupport_asm.sv7M makefile + @-$(call RM, $@) + $(ASSEMBLE) --output_file=m3_TaskSupport_asm.obj + + +BIOS.obj: BIOS.c family/arm/m3/Hwi.c family/arm/m3/TaskSupport.c knl/Clock.c knl/Idle.c knl/Intrinsics.c knl/Event.c knl/Mailbox.c knl/Queue.c knl/Semaphore.c knl/Swi.c knl/Swi_andn.c knl/Task.c hal/Hwi.c hal/Hwi_stack.c hal/Hwi_startup.c hal/Seconds.c family/arm/lm4/Seconds.c family/arm/lm4/TimestampProvider.c family/arm/lm4/Timer.c io/DEV.c io/GIO.c io/IOM_stub.c gates/GateHwi.c gates/GateMutex.c xdcruntime/SemThreadSupport.c heaps/HeapMem.c makefile + @-$(call RM, $@) + @echo clem4f $< ... + @$(CC) $(BIOS_DEFS) $(XOPTS) $(INCS) \ + $(BIOS_ROOT)BIOS.c \ + $(BIOS_ROOT)family/arm/m3/Hwi.c \ + $(BIOS_ROOT)family/arm/m3/TaskSupport.c \ + $(BIOS_ROOT)knl/Clock.c \ + $(BIOS_ROOT)knl/Idle.c \ + $(BIOS_ROOT)knl/Intrinsics.c \ + $(BIOS_ROOT)knl/Event.c \ + $(BIOS_ROOT)knl/Mailbox.c \ + $(BIOS_ROOT)knl/Queue.c \ + $(BIOS_ROOT)knl/Semaphore.c \ + $(BIOS_ROOT)knl/Swi.c \ + $(BIOS_ROOT)knl/Swi_andn.c \ + $(BIOS_ROOT)knl/Task.c \ + $(BIOS_ROOT)hal/Hwi.c \ + $(BIOS_ROOT)hal/Hwi_stack.c \ + $(BIOS_ROOT)hal/Hwi_startup.c \ + $(BIOS_ROOT)hal/Seconds.c \ + $(BIOS_ROOT)family/arm/lm4/Seconds.c \ + $(BIOS_ROOT)family/arm/lm4/TimestampProvider.c \ + $(BIOS_ROOT)family/arm/lm4/Timer.c \ + $(BIOS_ROOT)io/DEV.c \ + $(BIOS_ROOT)io/GIO.c \ + $(BIOS_ROOT)io/IOM_stub.c \ + $(BIOS_ROOT)gates/GateHwi.c \ + $(BIOS_ROOT)gates/GateMutex.c \ + $(BIOS_ROOT)xdcruntime/SemThreadSupport.c \ + $(BIOS_ROOT)heaps/HeapMem.c \ + +sysbios.aem4f: BIOS.obj m3_Hwi_asm.obj m3_Hwi_asm_switch.obj m3_IntrinsicsSupport_asm.obj m3_TaskSupport_asm.obj + @-$(call RM, $@) + @echo arem4f $^ ... + @$(AR) $@ $^ + + +clean: + @$(DEL) ..\makefile.libs + @-$(call RM, *) diff --git a/Software/Embedded_SW/Embedded/src/sysbios/sysbios.aem4f b/Software/Embedded_SW/Embedded/src/sysbios/sysbios.aem4f new file mode 100644 index 000000000..aa3e01c82 Binary files /dev/null and b/Software/Embedded_SW/Embedded/src/sysbios/sysbios.aem4f differ diff --git a/Software/Embedded_SW/Embedded/targetConfigs/Tiva TM4C129XNCZAD.ccxml b/Software/Embedded_SW/Embedded/targetConfigs/Tiva TM4C129XNCZAD.ccxml new file mode 100644 index 000000000..534ac1ba0 --- /dev/null +++ b/Software/Embedded_SW/Embedded/targetConfigs/Tiva TM4C129XNCZAD.ccxml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Software/Embedded_SW/Embedded/targetConfigs/readme.txt b/Software/Embedded_SW/Embedded/targetConfigs/readme.txt new file mode 100644 index 000000000..d783fef4d --- /dev/null +++ b/Software/Embedded_SW/Embedded/targetConfigs/readme.txt @@ -0,0 +1,9 @@ +The 'targetConfigs' folder contains target-configuration (.ccxml) files, automatically generated based +on the device and connection settings specified in your project on the Properties > General page. + +Please note that in automatic target-configuration management, changes to the project's device and/or +connection settings will either modify an existing or generate a new target-configuration file. Thus, +if you manually edit these auto-generated files, you may need to re-apply your changes. Alternatively, +you may create your own target-configuration file for this project and manage it manually. You can +always switch back to automatic target-configuration management by checking the "Manage the project's +target-configuration automatically" checkbox on the project's Properties > General page. \ No newline at end of file diff --git a/Software/Embedded_SW/Embedded/tm4c129xnczad.cmd b/Software/Embedded_SW/Embedded/tm4c129xnczad.cmd new file mode 100644 index 000000000..6530052f6 --- /dev/null +++ b/Software/Embedded_SW/Embedded/tm4c129xnczad.cmd @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Default Linker Command file for the Texas Instruments TM4C129XNCZAD + * + * This is derived from revision 15071 of the TivaWare Library. + * + *****************************************************************************/ + +--retain=g_pfnVectors + +MEMORY +{ + FLASH (RX) : origin = 0x00000000, length = 0x00100000 + SRAM (RWX) : origin = 0x20000000, length = 0x00040000 +} + +/* The following command line options are set as part of the CCS project. */ +/* If you are building using the command line, or for some reason want to */ +/* define them here, you can uncomment and modify these lines as needed. */ +/* If you are using CCS for building, it is probably better to make any such */ +/* modifications in your CCS project and leave this file alone. */ +/* */ +/* --heap_size=0 */ +/* --stack_size=256 */ +/* --library=rtsv7M4_T_le_eabi.lib */ + +/* Section allocation in memory */ + +SECTIONS +{ + .intvecs: > 0x00000000 + .text : > FLASH + .const : > FLASH + .cinit : > FLASH + .pinit : > FLASH + .init_array : > FLASH + + .vtable : > 0x20000000 + .data : > SRAM + .bss : > SRAM + .sysmem : > SRAM + .stack : > SRAM +} + +__STACK_TOP = __stack + 512; -- cgit v1.3.1