diff options
-rw-r--r-- | .cproject | 12 | ||||
-rw-r--r-- | src/Alligator/Pins_Alligator.h | 28 | ||||
-rw-r--r-- | src/Duet/Pins_Duet.h | 8 | ||||
-rw-r--r-- | src/DuetM/Pins_DuetM.h | 22 | ||||
-rw-r--r-- | src/DuetNG/Pins_DuetNG.h | 8 | ||||
-rw-r--r-- | src/Fans/Fan.cpp (renamed from src/Fan.cpp) | 0 | ||||
-rw-r--r-- | src/Fans/Fan.h (renamed from src/Fan.h) | 0 | ||||
-rw-r--r-- | src/Fans/Tacho.cpp | 53 | ||||
-rw-r--r-- | src/Fans/Tacho.h | 32 | ||||
-rw-r--r-- | src/GCodes/GCodes.cpp | 38 | ||||
-rw-r--r-- | src/GCodes/GCodes.h | 14 | ||||
-rw-r--r-- | src/GCodes/GCodes2.cpp | 37 | ||||
-rw-r--r-- | src/Heating/Sensors/TemperatureSensor.cpp | 4 | ||||
-rw-r--r-- | src/Pccb/Pins_Pccb.h | 21 | ||||
-rw-r--r-- | src/Platform.cpp | 109 | ||||
-rw-r--r-- | src/Platform.h | 32 | ||||
-rw-r--r-- | src/RADDS/Pins_RADDS.h | 29 | ||||
-rw-r--r-- | src/RepRap.cpp | 46 | ||||
-rw-r--r-- | src/SAME70_TEST/Pins_SAME70_TEST.h | 14 | ||||
-rw-r--r-- | src/StepperDrivers/TMC22xx/TMC22xx.cpp | 186 | ||||
-rw-r--r-- | src/StepperDrivers/TMC2660/TMC2660.cpp | 2 | ||||
-rw-r--r-- | src/StepperDrivers/TMC2660/TMC2660.h | 2 | ||||
-rw-r--r-- | src/Version.h | 2 |
23 files changed, 480 insertions, 219 deletions
@@ -20,7 +20,7 @@ </extensions> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850" name="Duet085" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${ProjName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${ProjName}.bin"> + <configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850" name="Duet085" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin"> <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850." name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.947353540" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> <option id="cdt.managedbuild.option.gnu.cross.path.1742191832" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/> @@ -135,7 +135,7 @@ </extensions> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="${ProjName}-RADDS" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1027429289" name="RADDS" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${ProjName}-RADDS.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${ProjName}-RADDS.bin"> + <configuration artifactExtension="elf" artifactName="${ProjName}-RADDS" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1027429289" name="RADDS" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin"> <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1027429289." name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.1973208555" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> <option id="cdt.managedbuild.option.gnu.cross.path.2092504710" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/> @@ -245,7 +245,7 @@ </extensions> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="${ProjName}-Alligator" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887" name="Alligator" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${ProjName}-Alligator.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${ProjName}-Alligator.bin"> + <configuration artifactExtension="elf" artifactName="${ProjName}-Alligator" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887" name="Alligator" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin"> <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887." name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.623324432" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> <option id="cdt.managedbuild.option.gnu.cross.path.645044151" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/> @@ -366,7 +366,7 @@ </extensions> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="Duet2CombinedFirmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622" name="Duet2_RTOS" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/Duet2CombinedFirmware.elf ${workspace_loc:/${ProjName}/${ConfigName}}/Duet2CombinedFirmware.bin"> + <configuration artifactExtension="elf" artifactName="Duet2CombinedFirmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622" name="Duet2_RTOS" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin"> <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622." name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.435431950" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> <option id="cdt.managedbuild.option.gnu.cross.path.1881231799" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/> @@ -486,7 +486,7 @@ </extensions> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="DuetMaestroFirmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786" name="DuetM_RTOS" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/DuetMaestroFirmware.elf ${workspace_loc:/${ProjName}/${ConfigName}}/DuetMaestroFirmware.bin"> + <configuration artifactExtension="elf" artifactName="DuetMaestroFirmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786" name="DuetM_RTOS" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin"> <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786." name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.1494327638" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> <option id="cdt.managedbuild.option.gnu.cross.path.1101985181" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/> @@ -606,7 +606,7 @@ </extensions> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="SAME70Firmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203" name="SAME70_RTOS" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/SAME70Firmware.elf ${workspace_loc:/${ProjName}/${ConfigName}}/SAME70Firmware.bin"> + <configuration artifactExtension="elf" artifactName="SAME70Firmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203" name="SAME70_RTOS" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin"> <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203." name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.5959303" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> <option id="cdt.managedbuild.option.gnu.cross.path.163568524" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/> diff --git a/src/Alligator/Pins_Alligator.h b/src/Alligator/Pins_Alligator.h index 1f965e98..fe3bcff8 100644 --- a/src/Alligator/Pins_Alligator.h +++ b/src/Alligator/Pins_Alligator.h @@ -35,16 +35,16 @@ const size_t MaxDriversPerAxis = 4; // The maximum number of stepper drivers #define AXES_(a,b,c,d,e,f,g,h,i) { a,b,c,d,e,f } // Alligator + Piggy module max 5 heaters -const int8_t Heaters = 5; // The number of heaters in the machine; 0 is the heated bed even if there isn't one -#define HEATERS_(a,b,c,d,e,f,g,h) { a,b,c,d,e } +constexpr size_t Heaters = 5; // The number of heaters in the machine; 0 is the heated bed even if there isn't one -const size_t NumExtraHeaterProtections = 4; // The number of extra heater protection instances +constexpr size_t NumExtraHeaterProtections = 4; // The number of extra heater protection instances +constexpr size_t NumThermistorInputs = 5; -const size_t MaxAxes = 7; // The maximum number of movement axes in the machine, usually just X, Y and Z, <= DRIVES -const size_t MinAxes = 3; // The minimum and default number of axes -const size_t MaxExtruders = DRIVES - MinAxes; // The maximum number of extruders +constexpr size_t MaxAxes = 7; // The maximum number of movement axes in the machine, usually just X, Y and Z, <= DRIVES +constexpr size_t MinAxes = 3; // The minimum and default number of axes +constexpr size_t MaxExtruders = DRIVES - MinAxes; // The maximum number of extruders -const size_t NUM_SERIAL_CHANNELS = 3; // The number of serial IO channels (USB and two auxiliary UARTs) +constexpr size_t NUM_SERIAL_CHANNELS = 3; // The number of serial IO channels (USB and two auxiliary UARTs) #define SERIAL_MAIN_DEVICE SerialUSB #define SERIAL_AUX_DEVICE Serial #define SERIAL_AUX2_DEVICE Serial1 @@ -67,19 +67,18 @@ const Pin MotorFaultDetectPin = 22; // Alligator End-stop pinout mapping for RepRapFirmware: // 5V SIGN SIGN GND , 5V SIGN SIGN GND, 5V SIGN SIGN GND // X E0 Y E1 Z E2-Zprobe -const Pin END_STOP_PINS[DRIVES] = { 33, 35, 38, 34, 37, 39 ,NoPin }; +const Pin END_STOP_PINS[DRIVES] = { 33, 35, 38, 34, 37, 39, NoPin }; // SPI DAC Motor for Current Vref const size_t MaxSpiDac = 2; const Pin SPI_DAC_CS[MaxSpiDac] = { 53, 6 }; // HEATERS -const Pin TEMP_SENSE_PINS[Heaters] = HEATERS_(1, 0, 2, 3, 4, f, g, h); // Analogue pin numbers +const Pin TEMP_SENSE_PINS[NumThermistorInputs] = { 1, 0, 2, 3, 4 }; // Analogue pin numbers // h1,h2,h3,h4: X2,8,9,X8 is hardware PWM // b: X3 is not hardware PWM -const Pin HEAT_ON_PINS[Heaters] = HEATERS_(X3, X2, 8, 9, X8, f, g, h); // b,h1,h2,h3,h4 - +const Pin HEAT_ON_PINS[Heaters] = { X3, X2, 8, 9, X8 }; // Default thermistor parameters // Bed thermistor: http://uk.farnell.com/epcos/b57863s103f040/sensor-miniature-ntc-10k/dp/1299930?Ntt=129-9930 @@ -110,11 +109,11 @@ const Pin ATX_POWER_PIN = NoPin; // Arduino Due pin number that control const Pin Z_PROBE_PIN = 39; // Z min pin ,Last signal of the end-stop connectors // Digital pin number to turn the IR LED on (high) or off (low) -const Pin Z_PROBE_MOD_PIN = NoPin; // Digital pin number to turn the IR LED on (high) or off (low) on Duet v0.6 and v1.0 (PB21) +const Pin Z_PROBE_MOD_PIN = NoPin; // Digital pin number to turn the IR LED on (high) or off (low) on Duet v0.6 and v1.0 (PB21) const Pin DiagPin = NoPin; // Pin number that the DAC that controls the second extruder motor current on the Duet 0.8.5 is connected to -const int Dac0DigitalPin = NoPin; // Arduino Due pin number corresponding to DAC0 output pin +const int Dac0DigitalPin = NoPin; // Arduino Due pin number corresponding to DAC0 output pin // COOLING FANS const size_t NUM_FANS = 4; @@ -122,7 +121,8 @@ const size_t NUM_FANS = 4; // Fan2: 31 is not hardware PWM // J5 pin1 black connector ha hardware PWM, attached to FANS const Pin COOLING_FAN_PINS[NUM_FANS] = { X0, 31, X17}; -const Pin COOLING_FAN_RPM_PIN = NoPin; // Pin PA15 +constexpr size_t NumTachos = 0; +constexpr Pin TachoPins[NumTachos] = { }; // SD cards const size_t NumSdCards = 1; diff --git a/src/Duet/Pins_Duet.h b/src/Duet/Pins_Duet.h index 766fd81f..ceefd4bc 100644 --- a/src/Duet/Pins_Duet.h +++ b/src/Duet/Pins_Duet.h @@ -30,9 +30,8 @@ constexpr size_t DRIVES = 9; // The number of drives in the machine, includ #define DRIVES_(a,b,c,d,e,f,g,h,i,j,k,l) { a,b,c,d,e,f,g,h,i } constexpr size_t Heaters = 7; // The number of heaters in the machine; 0 is the heated bed even if there isn't one -#define HEATERS_(a,b,c,d,e,f,g,h) { a,b,c,d,e,f,g } - constexpr size_t NumExtraHeaterProtections = 4; // The number of extra heater protection instances +constexpr size_t NumThermistorInputs = 7; constexpr size_t MinAxes = 3; // The minimum and default number of axes constexpr size_t MaxAxes = 6; // The maximum number of movement axes in the machine, usually just X, Y and Z, <= DRIVES @@ -71,7 +70,7 @@ constexpr float STEPPER_DAC_VOLTAGE_RANGE = 2.02; // Stepper motor current constexpr float STEPPER_DAC_VOLTAGE_OFFSET = -0.025; // Stepper motor current offset voltage for E1 if using a DAC // HEATERS -constexpr Pin TEMP_SENSE_PINS[Heaters] = { 5, 4, 0, 7, 8, 9, 11 }; // Analogue pin numbers +constexpr Pin TEMP_SENSE_PINS[NumThermistorInputs] = { 5, 4, 0, 7, 8, 9, 11 }; // Analogue pin numbers constexpr Pin HEAT_ON_PINS[Heaters] = { 6, X5, X7, 7, 8, 9, X17 }; // Heater Channel 7 (pin X17) is shared with Fan1 // Default thermistor parameters @@ -125,7 +124,8 @@ constexpr int Dac0DigitalPin = 66; // Arduino Due pin number correspon // COOLING FANS constexpr size_t NUM_FANS = 2; constexpr Pin COOLING_FAN_PINS[NUM_FANS] = { X6, X17 }; // Pin D34 is PWM capable but not an Arduino PWM pin - use X6 instead -constexpr Pin COOLING_FAN_RPM_PIN = 23; // Pin PA15 +constexpr size_t NumTachos = 1; +constexpr Pin TachoPins[NumTachos] = { 23 }; // Pin PA15 // SD cards constexpr size_t NumSdCards = 2; diff --git a/src/DuetM/Pins_DuetM.h b/src/DuetM/Pins_DuetM.h index 62da1bfb..8f11b2fd 100644 --- a/src/DuetM/Pins_DuetM.h +++ b/src/DuetM/Pins_DuetM.h @@ -41,10 +41,9 @@ constexpr size_t DRIVES = 7; // The maximum number of drives supported by t constexpr size_t MaxSmartDrivers = 7; // The maximum number of smart drivers #define DRIVES_(a,b,c,d,e,f,g,h,i,j,k,l) { a,b,c,d,e,f,g } -constexpr size_t Heaters = 4; // The number of heaters/thermistors in the machine. Duet M has 3 heaters but 4 thermistors. -#define HEATERS_(a,b,c,d,e,f,g,h) { a,b,c } - +constexpr size_t Heaters = 3; // The number of heaters/thermistors in the machine. Duet M has 3 heaters but 4 thermistors. constexpr size_t NumExtraHeaterProtections = 4; // The number of extra heater protection instances +constexpr size_t NumThermistorInputs = 4; constexpr size_t MinAxes = 3; // The minimum and default number of axes constexpr size_t MaxAxes = 6; // The maximum number of movement axes in the machine, usually just X, Y and Z, <= DRIVES @@ -70,12 +69,12 @@ constexpr Pin STEP_PINS[DRIVES] = { 56, 38, 64, 40, 41, 67, 57 }; constexpr Pin DIRECTION_PINS[DRIVES] = { 54, 8, 30, 33, 42, 18, 60 }; // UART interface to stepper drivers -#define UART_TMC_DRV UART0 -#define SERIAL_TMC_DRV_IRQn UART0_IRQn -#define ID_UART_TMC_DRV ID_UART0 -#define UART_TMC_DRV_Handler UART0_Handler +Uart * const UART_TMC_DRV = UART0; +const IRQn UART_TMC_DRV_IRQn = UART0_IRQn; +const uint32_t ID_UART_TMC_DRV = ID_UART0; +const uint8_t UART_TMC_DRV_PINS = APINS_UART0; -static const uint8_t UART_TMC_DRV_PINS = APINS_UART0; +#define UART_TMC_DRV_Handler UART0_Handler constexpr Pin DriverMuxPins[3] = { 50, 52, 53 }; // Pins that control the UART multiplexer, LSB first @@ -85,8 +84,8 @@ constexpr Pin DriverMuxPins[3] = { 50, 52, 53 }; // Pins that control the UART m constexpr Pin END_STOP_PINS[DRIVES] = { 24, 32, 46, 25, 43, NoPin, NoPin }; // Heaters and thermistors -constexpr Pin HEAT_ON_PINS[Heaters] = { 36, 37, 16, NoPin }; // Heater pin numbers -constexpr Pin TEMP_SENSE_PINS[Heaters] = { 20, 26, 66, 27 }; // Thermistor pin numbers +constexpr Pin HEAT_ON_PINS[Heaters] = { 36, 37, 16 }; // Heater pin numbers +constexpr Pin TEMP_SENSE_PINS[NumThermistorInputs] = { 20, 26, 66, 27 }; // Thermistor pin numbers constexpr Pin VssaSensePin = 19; constexpr Pin VrefSensePin = 17; @@ -125,7 +124,8 @@ constexpr Pin DiagPin = Z_PROBE_MOD_PIN; // Cooling fans constexpr size_t NUM_FANS = 3; constexpr Pin COOLING_FAN_PINS[NUM_FANS] = { 59, 58, 65 }; -constexpr Pin COOLING_FAN_RPM_PIN = 21; +constexpr size_t NumTachos = 1; +constexpr Pin TachoPins[NumTachos] = { 21 }; // SD cards constexpr size_t NumSdCards = 2; diff --git a/src/DuetNG/Pins_DuetNG.h b/src/DuetNG/Pins_DuetNG.h index c7709380..6f1063fa 100644 --- a/src/DuetNG/Pins_DuetNG.h +++ b/src/DuetNG/Pins_DuetNG.h @@ -37,9 +37,8 @@ constexpr size_t MaxSmartDrivers = 10; // The maximum number of smart drivers #define DRIVES_(a,b,c,d,e,f,g,h,i,j,k,l) { a,b,c,d,e,f,g,h,i,j,k,l } constexpr size_t Heaters = 8; // The number of heaters in the machine; 0 is the heated bed even if there isn't one -#define HEATERS_(a,b,c,d,e,f,g,h) { a,b,c,d,e,f,g,h } - constexpr size_t NumExtraHeaterProtections = 8; // The number of extra heater protection instances +constexpr size_t NumThermistorInputs = 8; constexpr size_t MinAxes = 3; // The minimum and default number of axes constexpr size_t MaxAxes = 9; // The maximum number of movement axes in the machine, usually just X, Y and Z, <= DRIVES @@ -77,7 +76,7 @@ constexpr Pin END_STOP_PINS[DRIVES] = { 46, 02, 93, 74, 48, 96, 97, 98, 99, 17, constexpr Pin DUEX_END_STOP_PINS[5] = { 200, 203, 202, 201, 213 }; // these replace endstops 5-9 if a DueX is present // HEATERS -constexpr Pin TEMP_SENSE_PINS[Heaters] = { 45, 47, 44, 61, 62, 63, 59, 18 }; // Thermistor pin numbers +constexpr Pin TEMP_SENSE_PINS[NumThermistorInputs] = { 45, 47, 44, 61, 62, 63, 59, 18 }; // Thermistor pin numbers constexpr Pin HEAT_ON_PINS[Heaters] = { 19, 20, 16, 35, 37, 40, 43, 15 }; // Heater pin numbers (heater 7 pin TBC) // Default thermistor parameters @@ -129,7 +128,8 @@ constexpr Pin DiagPin = Z_PROBE_MOD_PIN; // Cooling fans constexpr size_t NUM_FANS = 9; constexpr Pin COOLING_FAN_PINS[NUM_FANS] = { 55, 58, 00, 212, 207, 206, 205, 204, 215 }; -constexpr Pin COOLING_FAN_RPM_PIN = 102; // PB6 on expansion connector +constexpr size_t NumTachos = 1; +constexpr Pin TachoPins[NumTachos] = { 102 }; // PB6 on expansion connector // SD cards constexpr size_t NumSdCards = 2; diff --git a/src/Fan.cpp b/src/Fans/Fan.cpp index 0351abce..0351abce 100644 --- a/src/Fan.cpp +++ b/src/Fans/Fan.cpp diff --git a/src/Fan.h b/src/Fans/Fan.h index f0e5598f..f0e5598f 100644 --- a/src/Fan.h +++ b/src/Fans/Fan.h diff --git a/src/Fans/Tacho.cpp b/src/Fans/Tacho.cpp new file mode 100644 index 00000000..00f697ad --- /dev/null +++ b/src/Fans/Tacho.cpp @@ -0,0 +1,53 @@ +/* + * Tacho.cpp + * + * Created on: 16 Jul 2018 + * Author: David + */ + +#include "Tacho.h" +#include "Platform.h" + +void FanInterrupt(CallbackParameter cb) +{ + static_cast<Tacho *>(cb.vp)->Interrupt(); +} + +Tacho::Tacho() : fanInterruptCount(0), fanLastResetTime(0), fanInterval(0), pin(NoPin) +{ +} + +void Tacho::Init(Pin p_pin) +{ + pin = p_pin; + if (pin != NoPin) + { + pinModeDuet(pin, INPUT_PULLUP, 1500); // enable pullup and 1500Hz debounce filter (500Hz only worked up to 7000RPM) + attachInterrupt(pin, FanInterrupt, INTERRUPT_MODE_FALLING, this); + } +} + +uint32_t Tacho::GetRPM() const +{ + // The ISR sets fanInterval to the number of step interrupt clocks it took to get fanMaxInterruptCount interrupts. + // We get 2 tacho pulses per revolution, hence 2 interrupts per revolution. + // However, if the fan stops then we get no interrupts and fanInterval stops getting updated. + // We must recognise this and return zero. + return (fanInterval != 0 && Platform::GetInterruptClocks() - fanLastResetTime < 3 * StepClockRate) // if we have a reading and it is less than 3 second old + ? (StepClockRate * fanMaxInterruptCount)/(2 * fanInterval) // then calculate RPM assuming 2 interrupts per rev + : 0; // else assume fan is off or tacho not connected +} + +void Tacho::Interrupt() +{ + ++fanInterruptCount; + if (fanInterruptCount == fanMaxInterruptCount) + { + const uint32_t now = Platform::GetInterruptClocks(); + fanInterval = now - fanLastResetTime; + fanLastResetTime = now; + fanInterruptCount = 0; + } +} + +// End diff --git a/src/Fans/Tacho.h b/src/Fans/Tacho.h new file mode 100644 index 00000000..279f0d91 --- /dev/null +++ b/src/Fans/Tacho.h @@ -0,0 +1,32 @@ +/* + * Tacho.h + * + * Created on: 16 Jul 2018 + * Author: David + */ + +#ifndef SRC_FANS_TACHO_H_ +#define SRC_FANS_TACHO_H_ + +#include "RepRapFirmware.h" + +class Tacho +{ +public: + Tacho(); + void Init(Pin p_pin); + uint32_t GetRPM() const; + + void Interrupt(); + +private: + static constexpr uint32_t fanMaxInterruptCount = 32; // number of fan interrupts that we average over + + uint32_t fanInterruptCount; // accessed only in ISR, so no need to declare it volatile + volatile uint32_t fanLastResetTime; // time (microseconds) at which we last reset the interrupt count, accessed inside and outside ISR + volatile uint32_t fanInterval; // written by ISR, read outside the ISR + + Pin pin; +}; + +#endif /* SRC_FANS_TACHO_H_ */ diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 8724e9e7..28783186 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -66,16 +66,23 @@ GCodes::GCodes(Platform& p) : telnetInput = new NetworkGCodeInput; fileInput = new FileGCodeInput(); serialInput = new StreamGCodeInput(SERIAL_MAIN_DEVICE); +#ifdef SERIAL_AUX_DEVICE auxInput = new StreamGCodeInput(SERIAL_AUX_DEVICE); - +#endif httpGCode = new GCodeBuffer("http", HttpMessage, false); telnetGCode = new GCodeBuffer("telnet", TelnetMessage, true); fileGCode = new GCodeBuffer("file", GenericMessage, true); serialGCode = new GCodeBuffer("serial", UsbMessage, true); +#ifdef SERIAL_AUX_DEVICE auxGCode = new GCodeBuffer("aux", LcdMessage, false); +#else + auxGCode = nullptr; +#endif daemonGCode = new GCodeBuffer("daemon", GenericMessage, false); #if SUPPORT_12864_LCD lcdGCode = new GCodeBuffer("lcd", GenericMessage, false); +#else + lcdGCode = nullptr; #endif queuedGCode = new GCodeBuffer("queue", GenericMessage, false); autoPauseGCode = new GCodeBuffer("autopause", GenericMessage, false); @@ -240,7 +247,7 @@ bool GCodes::DoingFileMacro() const { for (const GCodeBuffer *gb : gcodeSources) { - if (gb->IsDoingFileMacro()) + if (gb != nullptr && gb->IsDoingFileMacro()) { return true; } @@ -296,9 +303,12 @@ bool GCodes::IsDaemonBusy() const // Copy the feed rate etc. from the daemon to the input channels void GCodes::CopyConfigFinalValues(GCodeBuffer& gb) { - for (size_t i = 0; i < ARRAY_SIZE(gcodeSources); ++i) + for (GCodeBuffer *gb2 : gcodeSources) { - gcodeSources[i]->MachineState().CopyStateFrom(gb.MachineState()); + if (gb2 != nullptr) + { + gb2->MachineState().CopyStateFrom(gb.MachineState()); + } } } @@ -325,12 +335,15 @@ void GCodes::Spin() GCodeBuffer *gbp = autoPauseGCode; if (gbp->IsCompletelyIdle() && !(gbp->MachineState().fileState.IsLive())) { - gbp = gcodeSources[nextGcodeSource]; - ++nextGcodeSource; // move on to the next gcode source ready for next time - if (nextGcodeSource == ARRAY_SIZE(gcodeSources) - 1) // the last one is autoPauseGCode, so don't do it again + do { - nextGcodeSource = 0; - } + gbp = gcodeSources[nextGcodeSource]; + ++nextGcodeSource; // move on to the next gcode source ready for next time + if (nextGcodeSource == ARRAY_SIZE(gcodeSources) - 1) // the last one is autoPauseGCode, so don't do it again + { + nextGcodeSource = 0; + } + } while (gbp == nullptr); // we must have at least one GCode source, so this can't loop indefinitely } GCodeBuffer& gb = *gbp; @@ -1416,6 +1429,7 @@ void GCodes::StartNextGCode(GCodeBuffer& gb, const StringRef& reply) // USB interface. This line may be shared with a 3D scanner serialInput->FillBuffer(serialGCode); } +#ifdef SERIAL_AUX_DEVICE else if (&gb == auxGCode) { // Aux serial port (typically PanelDue) @@ -1425,6 +1439,7 @@ void GCodes::StartNextGCode(GCodeBuffer& gb, const StringRef& reply) platform.SetAuxDetected(); } } +#endif } void GCodes::DoFilePrint(GCodeBuffer& gb, const StringRef& reply) @@ -2061,7 +2076,10 @@ void GCodes::Diagnostics(MessageType mtype) for (size_t i = 0; i < ARRAY_SIZE(gcodeSources); ++i) { - gcodeSources[i]->Diagnostics(mtype); + if (gcodeSources[i] != nullptr) + { + gcodeSources[i]->Diagnostics(mtype); + } } codeQueue->Diagnostics(mtype); diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h index 74f86ba9..086deb94 100644 --- a/src/GCodes/GCodes.h +++ b/src/GCodes/GCodes.h @@ -379,27 +379,21 @@ private: NetworkGCodeInput* telnetInput; // ... FileGCodeInput* fileInput; // ... StreamGCodeInput* serialInput; // ... +#ifdef SERIAL_AUX_DEVICE StreamGCodeInput* auxInput; // ...for the GCodeBuffers below +#endif -#if SUPPORT_12864_LCD GCodeBuffer* gcodeSources[9]; // The various sources of gcodes -#else - GCodeBuffer* gcodeSources[8]; // The various sources of gcodes -#endif GCodeBuffer*& httpGCode = gcodeSources[0]; GCodeBuffer*& telnetGCode = gcodeSources[1]; GCodeBuffer*& fileGCode = gcodeSources[2]; GCodeBuffer*& serialGCode = gcodeSources[3]; - GCodeBuffer*& auxGCode = gcodeSources[4]; // This one is for the LCD display on the async serial interface + GCodeBuffer*& auxGCode = gcodeSources[4]; // This one is for the PanelDue on the async serial interface GCodeBuffer*& daemonGCode = gcodeSources[5]; // Used for executing config.g and trigger macro files GCodeBuffer*& queuedGCode = gcodeSources[6]; -#if SUPPORT_12864_LCD - GCodeBuffer*& lcdGCode = gcodeSources[7]; // This one for the internally-supported LCD + GCodeBuffer*& lcdGCode = gcodeSources[7]; // This one for the 12864 LCD GCodeBuffer*& autoPauseGCode = gcodeSources[8]; // ***THIS ONE MUST BE LAST*** GCode state machine used to run macros on power fail, heater faults and filament out -#else - GCodeBuffer*& autoPauseGCode = gcodeSources[7]; // ***THIS ONE MUST BE LAST*** GCode state machine used to run macros on power fail, heater faults and filament out -#endif size_t nextGcodeSource; // The one to check next diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index f996eb02..46d846eb 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -2021,13 +2021,16 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) { // Update the feed rate for ALL input sources, and all feed rates on the stack const float speedFactorRatio = newSpeedFactor / speedFactor; - for (size_t i = 0; i < ARRAY_SIZE(gcodeSources); ++i) + for (GCodeBuffer *gb : gcodeSources) { - GCodeMachineState *ms = &gcodeSources[i]->MachineState(); - while (ms != nullptr) + if (gb != nullptr) { - ms->feedRate *= speedFactorRatio; - ms = ms->previous; + GCodeMachineState *ms = &gb->MachineState(); + while (ms != nullptr) + { + ms->feedRate *= speedFactorRatio; + ms = ms->previous; + } } } // If the last move hasn't gone yet, update its feed rate too if it is not a firmware retraction @@ -2262,13 +2265,13 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) case 303: // Run PID tuning if (gb.Seen('H')) { - const int heater = gb.GetIValue(); + const unsigned int heater = gb.GetUIValue(); const float temperature = (gb.Seen('S')) ? gb.GetFValue() : reprap.GetHeat().IsBedHeater(heater) ? 75.0 : reprap.GetHeat().IsChamberHeater(heater) ? 50.0 : 200.0; const float maxPwm = (gb.Seen('P')) ? gb.GetFValue() : reprap.GetHeat().GetHeaterModel(heater).GetMaxPwm(); - if (heater < 0 || heater >= (int)Heaters) + if (heater >= Heaters) { reply.copy("Bad heater number in M303 command"); } @@ -2302,8 +2305,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) case 307: // Set heater process model parameters if (gb.Seen('H')) { - const int heater = gb.GetIValue(); - if (heater >= 0 && heater < (int)Heaters) + const unsigned int heater = gb.GetUIValue(); + if (heater < Heaters) { const FopDt& model = reprap.GetHeat().GetHeaterModel(heater); bool seen = false; @@ -2992,8 +2995,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) case 562: // Reset temperature fault - use with great caution if (gb.Seen('P')) { - const int heater = gb.GetIValue(); - if (heater >= 0 && heater < (int)Heaters) + const unsigned int heater = gb.GetUIValue(); + if (heater < Heaters) { reprap.ClearTemperatureFault(heater); } @@ -3006,7 +3009,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) else { // Clear all heater faults - for (int heater = 0; heater < (int)Heaters; ++heater) + for (unsigned int heater = 0; heater < Heaters; ++heater) { reprap.ClearTemperatureFault(heater); } @@ -3207,8 +3210,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) } if (gb.Seen('H')) { - const int heater = gb.GetIValue(); - if (heater >= 0 && heater < (int)Heaters) + const unsigned heater = gb.GetUIValue(); + if (heater < Heaters) { bool seenValue = false; float maxTempExcursion, maxFaultTime; @@ -3305,10 +3308,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) case 573: // Report heater average PWM if (gb.Seen('P')) { - const int heater = gb.GetIValue(); - if (heater >= 0 && heater < (int)Heaters) + const unsigned int heater = gb.GetUIValue(); + if (heater < Heaters) { - reply.printf("Average heater %d PWM: %.3f", heater, (double)reprap.GetHeat().GetAveragePWM(heater)); + reply.printf("Average heater %u PWM: %.3f", heater, (double)reprap.GetHeat().GetAveragePWM(heater)); } } break; diff --git a/src/Heating/Sensors/TemperatureSensor.cpp b/src/Heating/Sensors/TemperatureSensor.cpp index 2f97a41a..12b45866 100644 --- a/src/Heating/Sensors/TemperatureSensor.cpp +++ b/src/Heating/Sensors/TemperatureSensor.cpp @@ -86,11 +86,11 @@ void TemperatureSensor::TryConfigureHeaterName(GCodeBuffer& gb, bool& seen) TemperatureSensor *TemperatureSensor::Create(unsigned int channel) { TemperatureSensor *ts = nullptr; - if (channel < Heaters) + if (channel < NumThermistorInputs) { ts = new Thermistor(channel, false); } - else if (FirstPT1000Channel <= channel && channel < FirstPT1000Channel + Heaters) + else if (FirstPT1000Channel <= channel && channel < FirstPT1000Channel + NumThermistorInputs) { ts = new Thermistor(channel, true); } diff --git a/src/Pccb/Pins_Pccb.h b/src/Pccb/Pins_Pccb.h index 32d988c8..3a70f215 100644 --- a/src/Pccb/Pins_Pccb.h +++ b/src/Pccb/Pins_Pccb.h @@ -41,10 +41,9 @@ constexpr size_t DRIVES = 8; // The maximum number of drives supported by t constexpr size_t MaxSmartDrivers = 2; // The maximum number of smart drivers #define DRIVES_(a,b,c,d,e,f,g,h,i,j,k,l) { a,b,c,d,e,f,g,h } -constexpr size_t Heaters = 2; // The number of heaters/thermistors in the machine. PCCB has no heaters but 2 thermistors. -#define HEATERS_(a,b,c,d,e,f,g,h) { a,b } - +constexpr size_t Heaters = 1; // The number of heaters in the machine. PCCB has no heaters, but the code doesn't like that so we say 1 constexpr size_t NumExtraHeaterProtections = 4; // The number of extra heater protection instances +constexpr size_t NumThermistorInputs = 2; constexpr size_t MinAxes = 3; // The minimum and default number of axes constexpr size_t MaxAxes = 6; // The maximum number of movement axes in the machine, usually just X, Y and Z, <= DRIVES @@ -70,9 +69,13 @@ constexpr Pin DIRECTION_PINS[DRIVES] = { 8, 11, 17, 57, 54, 34, 1, 53 }; #define TMC22xx_NO_MUX 1 // each driver has its own UART -const Uart *DriverUarts[MaxSmartDrivers] = { UART0, UART1 }; +Uart * const DriverUarts[MaxSmartDrivers] = { UART0, UART1 }; constexpr uint32_t DriverUartIds[MaxSmartDrivers] = { ID_UART0, ID_UART1 }; constexpr IRQn DriverUartIRQns[MaxSmartDrivers] = { UART0_IRQn, UART1_IRQn }; +constexpr Pin DriverUartPins[MaxSmartDrivers] = { APINS_UART0, APINS_UART1 }; + +#define UART_TMC_DRV0_Handler UART0_Handler +#define UART_TMC_DRV1_Handler UART1_Handler // Endstops // RepRapFirmware only has a single endstop per axis. @@ -80,8 +83,8 @@ constexpr IRQn DriverUartIRQns[MaxSmartDrivers] = { UART0_IRQn, UART1_IRQn }; constexpr Pin END_STOP_PINS[DRIVES] = { 24, 25, 67, 63, NoPin, NoPin, NoPin, NoPin }; // Heaters and thermistors -constexpr Pin HEAT_ON_PINS[Heaters] = { NoPin, NoPin }; // Heater pin numbers -constexpr Pin TEMP_SENSE_PINS[Heaters] = { 20, 49 }; // Thermistor pin numbers +constexpr Pin HEAT_ON_PINS[Heaters] = { NoPin }; // Heater pin numbers +constexpr Pin TEMP_SENSE_PINS[NumThermistorInputs] = { 20, 49 }; // Thermistor pin numbers constexpr Pin VssaSensePin = 19; constexpr Pin VrefSensePin = 27; @@ -116,16 +119,16 @@ constexpr Pin DiagPin = NoPin; // Cooling fans constexpr size_t NUM_FANS = 4; -constexpr size_t NUM_TACHOS = 2; +constexpr size_t NumTachos = 2; constexpr Pin COOLING_FAN_PINS[NUM_FANS] = { 16, 39, 15, 37 }; // PWML2, PWML3, TIOA1, PWML1 -constexpr Pin TACHO_PINS[NUM_TACHOS] = { 26, 66 }; +constexpr Pin TachoPins[NumTachos] = { 26, 66 }; // Main LED control constexpr size_t NUM_LEDS = 2; // number of main LEDs constexpr Pin LedOnPins[NUM_LEDS] = { 36, 59 }; // LED control pins // DotStar LED control -const Usart *DotStarUsart = USART1; +Usart * const DotStarUsart = USART1; constexpr uint32_t DotStarUsartId = ID_USART1; constexpr IRQn DotStarUsartIRQn = USART1_IRQn; diff --git a/src/Platform.cpp b/src/Platform.cpp index bf5a6053..8550bb6f 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -107,11 +107,6 @@ constexpr uint16_t driverNormalVoltageAdcReading = PowerVoltageToAdcReading(27.5 #endif -static uint32_t fanInterruptCount = 0; // accessed only in ISR, so no need to declare it volatile -const uint32_t fanMaxInterruptCount = 32; // number of fan interrupts that we average over -static volatile uint32_t fanLastResetTime = 0; // time (microseconds) at which we last reset the interrupt count, accessed inside and outside ISR -static volatile uint32_t fanInterval = 0; // written by ISR, read outside the ISR - const float MinStepPulseTiming = 0.2; // we assume that we always generate step high and low times at least this wide without special action const LogicalPin Heater0LogicalPin = 0; @@ -208,23 +203,31 @@ void Platform::Init() // Comms baudRates[0] = MAIN_BAUD_RATE; +#ifdef SERIAL_AUX_DEVICE baudRates[1] = AUX_BAUD_RATE; +#endif #ifdef SERIAL_AUX2_DEVICE baudRates[2] = AUX2_BAUD_RATE; #endif commsParams[0] = 0; +#ifdef SERIAL_AUX_DEVICE commsParams[1] = 1; // by default we require a checksum on data from the aux port, to guard against overrun errors +#endif #ifdef SERIAL_AUX2_DEVICE commsParams[2] = 0; #endif usbMutex.Create("USB"); +#ifdef SERIAL_AUX_DEVICE auxMutex.Create("Aux"); auxDetected = false; auxSeq = 0; +#endif SERIAL_MAIN_DEVICE.begin(baudRates[0]); +#ifdef SERIAL_AUX_DEVICE SERIAL_AUX_DEVICE.begin(baudRates[1]); // this can't be done in the constructor because the Arduino port initialisation isn't complete at that point +#endif #ifdef SERIAL_AUX2_DEVICE SERIAL_AUX2_DEVICE.begin(baudRates[2]); aux2Mutex.Create("Aux2"); @@ -493,18 +496,20 @@ void Platform::Init() for (size_t heater = 0; heater < Heaters; heater++) { - if (heatOnPins[heater] != NoPin) - { - pinMode(heatOnPins[heater], + // pinMode is safe to call when the pin is NoPin, so we don't need to check it here + pinMode(heatOnPins[heater], #if ACTIVE_LOW_HEAT_ON OUTPUT_LOW #else OUTPUT_HIGH #endif ); - } - pinMode(tempSensePins[heater], AIN); - filteredAdcChannels[heater] = PinToAdcChannel(tempSensePins[heater]); // translate the pin number to the SAM ADC channel number; + } + + for (size_t thermistor = 0; thermistor < NumThermistorInputs; thermistor++) + { + pinMode(tempSensePins[thermistor], AIN); + filteredAdcChannels[thermistor] = PinToAdcChannel(tempSensePins[thermistor]); // translate the pin number to the SAM ADC channel number; } #if HAS_VREF_MONITOR @@ -528,6 +533,10 @@ void Platform::Init() // Fans InitFans(); + for (size_t i = 0; i < NumTachos; ++i) + { + tachos[i].Init(TachoPins[i]); + } // Hotend configuration nozzleDiameter = NOZZLE_DIAMETER; @@ -1120,6 +1129,7 @@ void Platform::Beep(int freq, int ms) // Send a short message to the aux channel. There is no flow control on this port, so it can't block for long. void Platform::SendAuxMessage(const char* msg) { +#ifdef SERIAL_AUX_DEVICE OutputBuffer *buf; if (OutputBuffer::Allocate(buf)) { @@ -1129,6 +1139,7 @@ void Platform::SendAuxMessage(const char* msg) auxOutput.Push(buf); FlushAuxMessages(); } +#endif } void Platform::Exit() @@ -1147,7 +1158,9 @@ void Platform::Exit() // Close down USB and serial ports SERIAL_MAIN_DEVICE.end(); +#ifdef SERIAL_AUX_DEVICE SERIAL_AUX_DEVICE.end(); +#endif #ifdef SERIAL_AUX2_DEVICE SERIAL_AUX2_DEVICE.end(); #endif @@ -1202,6 +1215,7 @@ void Platform::SetNetMask(uint8_t nm[]) // Flush messages to aux, returning true if there is more to send bool Platform::FlushAuxMessages() { +#ifdef SERIAL_AUX_DEVICE // Write non-blocking data to the AUX line MutexLocker lock(auxMutex); OutputBuffer *auxOutputBuffer = auxOutput.GetFirstItem(); @@ -1220,6 +1234,9 @@ bool Platform::FlushAuxMessages() } } return auxOutput.GetFirstItem() != nullptr; +#else + return false; +#endif } // Flush messages to USB and aux, returning true if there is more to send @@ -1743,14 +1760,17 @@ void Platform::SoftwareReset(uint16_t reason, const uint32_t *stk) reason |= (uint16_t)SoftwareResetReason::inLwipSpin; } #endif + +#ifdef SERIAL_AUX_DEVICE if (SERIAL_AUX_DEVICE.canWrite() == 0 -#ifdef SERIAL_AUX2_DEVICE +# ifdef SERIAL_AUX2_DEVICE || SERIAL_AUX2_DEVICE.canWrite() == 0 -#endif +# endif ) { reason |= (uint16_t)SoftwareResetReason::inAuxOutput; // if we are resetting because we are stuck in a Spin function, record whether we are trying to send to aux } +#endif } reason |= (uint8_t)reprap.GetSpinningModule(); reason |= (softwareResetDebugInfo & 0x07) << 5; @@ -1839,18 +1859,6 @@ void NETWORK_TC_HANDLER() #endif -static void FanInterrupt(CallbackParameter) -{ - ++fanInterruptCount; - if (fanInterruptCount == fanMaxInterruptCount) - { - const uint32_t now = Platform::GetInterruptClocks(); - fanInterval = now - fanLastResetTime; - fanLastResetTime = now; - fanInterruptCount = 0; - } -} - void Platform::InitialiseInterrupts() { #if SAM4E || SAM7E @@ -1864,17 +1872,23 @@ void Platform::InitialiseInterrupts() NVIC_SetPriority(SysTick_IRQn, NvicPrioritySystick); // set priority for tick interrupts #endif -#if SAM4E || SAME70 + // Set UART interrupt priorities +#ifdef PCCB + NVIC_SetPriority(DriverUartIRQns[0], NvicPriorityDriversSerialTMC); + NVIC_SetPriority(DriverUartIRQns[1], NvicPriorityDriversSerialTMC); +#else +# if SAM4E || SAME70 NVIC_SetPriority(UART0_IRQn, NvicPriorityPanelDueUart); // set priority for UART interrupt NVIC_SetPriority(UART1_IRQn, NvicPriorityWiFiUart); // set priority for WiFi UART interrupt -#elif SAM4S +# elif SAM4S NVIC_SetPriority(UART1_IRQn, NvicPriorityPanelDueUart); // set priority for UART interrupt -#else +# else NVIC_SetPriority(UART_IRQn, NvicPriorityPanelDueUart); // set priority for UART interrupt -#endif +# endif -#if HAS_SMART_DRIVERS - NVIC_SetPriority(SERIAL_TMC_DRV_IRQn, NvicPriorityDriversSerialTMC); +# if HAS_SMART_DRIVERS + NVIC_SetPriority(UART_TMC_DRV_IRQn, NvicPriorityDriversSerialTMC); +# endif #endif // Timer interrupt for stepper motors @@ -1946,12 +1960,6 @@ void Platform::InitialiseInterrupts() NVIC_SetPriority(I2C_IRQn, NvicPriorityTwi); #endif - // Interrupt for 4-pin PWM fan sense line - if (coolingFanRpmPin != NoPin) - { - attachInterrupt(coolingFanRpmPin, FanInterrupt, INTERRUPT_MODE_FALLING, nullptr); - } - // Tick interrupt for ADC conversions tickState = 0; currentFilterNumber = 0; @@ -3230,15 +3238,9 @@ const char *Platform::GetFanName(size_t fan) const } // Get current fan RPM -float Platform::GetFanRPM() const +uint32_t Platform::GetFanRPM(size_t tachoIndex) const { - // The ISR sets fanInterval to the number of microseconds it took to get fanMaxInterruptCount interrupts. - // We get 2 tacho pulses per revolution, hence 2 interrupts per revolution. - // However, if the fan stops then we get no interrupts and fanInterval stops getting updated. - // We must recognise this and return zero. - return (fanInterval != 0 && Platform::GetInterruptClocks() - fanLastResetTime < 3 * StepClockRate) // if we have a reading and it is less than 3 second old - ? (float)(3 * StepClockRate * fanMaxInterruptCount)/fanInterval // then calculate RPM assuming 2 interrupts per rev - : 0.0; // else assume fan is off or tacho not connected + return (tachoIndex < NumTachos) ? tachos[tachoIndex].GetRPM() : 0; } bool Platform::FansHardwareInverted(size_t fanNumber) const @@ -3285,12 +3287,6 @@ void Platform::InitFans() fans[1].SetPwm(1.0); // set it full on #endif } - - coolingFanRpmPin = COOLING_FAN_RPM_PIN; - if (coolingFanRpmPin != NoPin) - { - pinModeDuet(coolingFanRpmPin, INPUT_PULLUP, 1500); // enable pullup and 1500Hz debounce filter (500Hz only worked up to 7000RPM) - } } void Platform::SetEndStopConfiguration(size_t axis, EndStopPosition esPos, EndStopInputType inputType) @@ -3309,6 +3305,7 @@ void Platform::GetEndStopConfiguration(size_t axis, EndStopPosition& esType, End void Platform::AppendAuxReply(const char *msg, bool rawMessage) { +#ifdef SERIAL_AUX_DEVICE // Discard this response if either no aux device is attached or if the response is empty if (msg[0] != 0 && HaveAux()) { @@ -3333,10 +3330,12 @@ void Platform::AppendAuxReply(const char *msg, bool rawMessage) } } } +#endif } void Platform::AppendAuxReply(OutputBuffer *reply, bool rawMessage) { +#ifdef SERIAL_AUX_DEVICE // Discard this response if either no aux device is attached or if the response is empty if (reply == nullptr || reply->Length() == 0 || !HaveAux()) { @@ -3365,6 +3364,9 @@ void Platform::AppendAuxReply(OutputBuffer *reply, bool rawMessage) } } } +#else + OutputBuffer::ReleaseAll(reply); +#endif } // Send the specified message to the specified destinations. The Error and Warning flags have already been handled. @@ -3770,16 +3772,21 @@ void Platform::ResetChannel(size_t chan) SERIAL_MAIN_DEVICE.end(); SERIAL_MAIN_DEVICE.begin(baudRates[0]); break; + +#ifdef SERIAL_AUX_DEVICE case 1: SERIAL_AUX_DEVICE.end(); SERIAL_AUX_DEVICE.begin(baudRates[1]); break; +#endif + #ifdef SERIAL_AUX2_DEVICE case 2: SERIAL_AUX2_DEVICE.end(); SERIAL_AUX2_DEVICE.begin(baudRates[2]); break; #endif + default: break; } diff --git a/src/Platform.h b/src/Platform.h index 6afdb6b7..57d83de2 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -31,7 +31,8 @@ Licence: GPL #include "RepRapFirmware.h" #include "IoPorts.h" #include "DueFlashStorage.h" -#include "Fan.h" +#include "Fans/Fan.h" +#include "Fans/Tacho.h" #include "Heating/TemperatureError.h" #include "OutputMemory.h" #include "Storage/FileStore.h" @@ -57,19 +58,19 @@ constexpr bool BACKWARDS = !FORWARDS; // Define the number of ADC filters and the indices of the extra ones #if HAS_VREF_MONITOR -constexpr size_t VrefFilterIndex = Heaters; -constexpr size_t VssaFilterIndex = Heaters + 1; +constexpr size_t VrefFilterIndex = NumThermistorInputs; +constexpr size_t VssaFilterIndex = NumThermistorInputs + 1; # if HAS_CPU_TEMP_SENSOR -constexpr size_t CpuTempFilterIndex = Heaters + 2; -constexpr size_t NumAdcFilters = Heaters + 3; +constexpr size_t CpuTempFilterIndex = NumThermistorInputs + 2; +constexpr size_t NumAdcFilters = NumThermistorInputs + 3; # else -constexpr size_t NumAdcFilters = Heaters + 2; +constexpr size_t NumAdcFilters = NumThermistorInputs + 2; # endif #elif HAS_CPU_TEMP_SENSOR -constexpr size_t CpuTempFilterIndex = Heaters; -constexpr size_t NumAdcFilters = Heaters + 1; +constexpr size_t CpuTempFilterIndex = NumThermistorInputs; +constexpr size_t NumAdcFilters = NumThermistorInputs + 1; #else -constexpr size_t NumAdcFilters = Heaters; +constexpr size_t NumAdcFilters = NumThermistorInputs; #endif /**************************************************************************************************/ @@ -525,7 +526,7 @@ public: const char *GetFanName(size_t fan) const; bool WriteFanSettings(FileStore *f) const; // Save some resume information - float GetFanRPM() const; + uint32_t GetFanRPM(size_t tachoIndex) const; // Flash operations void UpdateFirmware(); @@ -813,7 +814,7 @@ private: static bool WriteAxisLimits(FileStore *f, AxesBitmap axesProbed, const float limits[MaxAxes], int sParam); // Heaters - bed is assumed to be the first - Pin tempSensePins[Heaters]; + Pin tempSensePins[NumThermistorInputs]; Pin heatOnPins[Heaters]; Pin spiTempSenseCsPins[MaxSpiTempSensors]; uint32_t configuredHeaters; // bitmask of all real heaters in use @@ -821,20 +822,25 @@ private: // Fans Fan fans[NUM_FANS]; - Pin coolingFanRpmPin; // we currently support only one fan RPM input uint32_t lastFanCheckTime; void InitFans(); bool FansHardwareInverted(size_t fanNumber) const; + // Fan tachos + Tacho tachos[NumTachos]; + // Serial/USB uint32_t baudRates[NUM_SERIAL_CHANNELS]; uint8_t commsParams[NUM_SERIAL_CHANNELS]; +#ifdef SERIAL_AUX_DEVICE volatile OutputStack auxOutput; Mutex auxMutex; +#endif + OutputBuffer *auxGCodeReply; // G-Code reply for AUX devices (special one because it is actually encapsulated before sending) uint32_t auxSeq; // Sequence number for AUX devices - bool auxDetected; // Have we processed at least one G-Code from an AUX device? + bool auxDetected; // Have we processed at least one G-Code from an AUX device? #ifdef SERIAL_AUX2_DEVICE volatile OutputStack aux2Output; diff --git a/src/RADDS/Pins_RADDS.h b/src/RADDS/Pins_RADDS.h index 01eac0ed..902c8e84 100644 --- a/src/RADDS/Pins_RADDS.h +++ b/src/RADDS/Pins_RADDS.h @@ -37,24 +37,20 @@ const size_t DRIVES = 9; // The number of heaters in the machine // 0 is the heated bed even if there isn't one. -const size_t Heaters = 4; +constexpr size_t Heaters = 4; +constexpr size_t NumExtraHeaterProtections = 4; // The number of extra heater protection instances +constexpr size_t NumThermistorInputs = 4; -const size_t NumExtraHeaterProtections = 4; // The number of extra heater protection instances - -// Initialization macro used in statements needing to initialize values in arrays of size HEATERS. E.g., -// defaultPidKis[HEATERS] = {HEATERS_(5.0, 0.1, 0.1, 0.1, 0.1, 0.1)}; -#define HEATERS_(a,b,c,d,e,f,g,h) { a,b,c,d } - -const size_t MinAxes = 3; // The minimum and default number of axes -const size_t MaxAxes = 6; // The maximum number of movement axes in the machine, usually just X, Y and Z, <= DRIVES +constexpr size_t MinAxes = 3; // The minimum and default number of axes +constexpr size_t MaxAxes = 6; // The maximum number of movement axes in the machine, usually just X, Y and Z, <= DRIVES // Initialization macro used in statements needing to initialize values in arrays of size MAX_AXES #define AXES_(a,b,c,d,e,f,g,h,i) { a,b,c,d,e,f } -const size_t MIN_AXES = 3; // The minimum and default number of axes -const size_t MaxExtruders = DRIVES - MIN_AXES; // The maximum number of extruders -const size_t MaxDriversPerAxis = 4; // The maximum number of stepper drivers assigned to one axis +constexpr size_t MIN_AXES = 3; // The minimum and default number of axes +constexpr size_t MaxExtruders = DRIVES - MIN_AXES; // The maximum number of extruders +constexpr size_t MaxDriversPerAxis = 4; // The maximum number of stepper drivers assigned to one axis -const size_t NUM_SERIAL_CHANNELS = 2; +constexpr size_t NUM_SERIAL_CHANNELS = 2; // Use TX0/RX0 for the auxiliary serial line #define SERIAL_MAIN_DEVICE SerialUSB #define SERIAL_AUX_DEVICE Serial1 @@ -85,14 +81,14 @@ const Pin END_STOP_PINS[DRIVES] = { 28, 30, 32, 39, NoPin, NoPin, NoPin, NoPin } // HEATERS - The bed is assumed to be the at index 0 // Analogue pin numbers -const Pin TEMP_SENSE_PINS[Heaters] = HEATERS_(4, 0, 1, 2, e, f, g, h); +const Pin TEMP_SENSE_PINS[NumThermistorInputs] = { 4, 0, 1, 2 }; // Heater outputs // Bed PMW: D7 has hardware PWM so bed has PWM // h0, h1 PMW: D13 & D12 are on TIOB0 & B8 which are both TC B channels, so they get PWM // h2 bang-bang: D11 is on TIOA8 which is a TC A channel shared with h1, it gets bang-bang control -const Pin HEAT_ON_PINS[Heaters] = HEATERS_(7, 13, 12, 11, e, f, g, h); // bed, h0, h1, h2 +const Pin HEAT_ON_PINS[Heaters] = { 7, 13, 12, 11 }; // bed, h0, h1, h2 // Default thermistor betas const float BED_R25 = 10000.0; @@ -131,7 +127,8 @@ const Pin COOLING_FAN_PINS[NUM_FANS] = { 9, 8 }; // Fan 0, Fan 1 // see FanInterrupt() in Platform.cpp // // D25 -- Unused GPIO on AUX1 -const Pin COOLING_FAN_RPM_PIN = 25; +constexpr size_t NumTachos = 1; +constexpr Pin TachoPins[NumTachos] = { 25 }; // SD cards const size_t NumSdCards = 2; diff --git a/src/RepRap.cpp b/src/RepRap.cpp index 1f8c15cd..e9ec6605 100644 --- a/src/RepRap.cpp +++ b/src/RepRap.cpp @@ -931,8 +931,27 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source) break; } - // Fan RPM - response->catf(",\"fanRPM\":%d}", static_cast<unsigned int>(platform->GetFanRPM())); + // Send fan RPM value(s) + if (NumTachos != 0) + { + response->cat(",\"fanRPM\":"); + // For compatibility with older versions of DWC, if there is only one tacho value then we send it as a simple variable + if (NumTachos > 1) + { + char ch = '['; + for (size_t i = 0; i < NumTachos; ++i) + { + response->catf("%c%" PRIu32, ch, platform->GetFanRPM(i)); + ch = ','; + } + response->cat(']'); + } + else + { + response->catf("%" PRIu32, platform->GetFanRPM(0)); + } + } + response->cat('}'); // end sensors } /* Temperatures */ @@ -1628,8 +1647,27 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq) ch = ','; } - // Send fan RPM value (we only support one) - response->catf("],\"fanRPM\":%u", static_cast<unsigned int>(platform->GetFanRPM())); + // Send fan RPM value(s) + response->cat(']'); + if (NumTachos != 0) + { + response->cat(",\"fanRPM\":"); + // For compatibility with older versions of DWC, if there is only one tacho value then we send it as a simple variable + if (NumTachos > 1) + { + char ch = '['; + for (size_t i = 0; i < NumTachos; ++i) + { + response->catf("%c%" PRIu32, ch, platform->GetFanRPM(i)); + ch = ','; + } + response->cat(']'); + } + else + { + response->catf("%" PRIu32, platform->GetFanRPM(0)); + } + } // Send the home state. To keep the messages short, we send 1 for homed and 0 for not homed, instead of true and false. response->cat(",\"homed\":"); diff --git a/src/SAME70_TEST/Pins_SAME70_TEST.h b/src/SAME70_TEST/Pins_SAME70_TEST.h index 0c028c60..3dce6245 100644 --- a/src/SAME70_TEST/Pins_SAME70_TEST.h +++ b/src/SAME70_TEST/Pins_SAME70_TEST.h @@ -34,9 +34,8 @@ const size_t MaxSmartDrivers = 10; // The maximum number of smart drivers #define DRIVES_(a,b,c,d,e,f,g,h,i,j,k,l) { a,b,c,d,e,f,g,h,i,j,k,l } constexpr size_t Heaters = 8; // The number of heaters in the machine; 0 is the heated bed even if there isn't one -#define HEATERS_(a,b,c,d,e,f,g,h) { a,b,c,d,e,f,g,h } - constexpr size_t NumExtraHeaterProtections = 8; // The number of extra heater protection instances +constexpr size_t NumThermistorInputs = 8; constexpr size_t MinAxes = 3; // The minimum and default number of axes constexpr size_t MaxAxes = 9; // The maximum number of movement axes in the machine, usually just X, Y and Z, <= DRIVES @@ -59,12 +58,12 @@ constexpr Pin AdditionalIoExpansionStart = 220; // Pin numbers 220-235 are on t // The numbers of entries in each array must correspond with the values of DRIVES, AXES, or HEATERS. Set values to NoPin to flag unavailability. // DRIVES -constexpr Pin GlobalTmcEnablePin = NoPin; // The pin that drives ENN of all TMC2660 drivers on production boards (on pre-production boards they are grounded) +constexpr Pin GlobalTmcEnablePin = NoPin; // The pin that drives ENN of all TMC2660 drivers on production boards (on pre-production boards they are grounded) constexpr Pin ENABLE_PINS[DRIVES] = { NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin }; constexpr Pin STEP_PINS[DRIVES] = { NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin }; constexpr Pin DIRECTION_PINS[DRIVES] = { NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin }; -constexpr Pin DueX_SG = NoPin; // DueX stallguard detect pin (TBD) +constexpr Pin DueX_SG = NoPin; // DueX stallguard detect pin (TBD) constexpr Pin DueX_INT = NoPin; // DueX interrupt pin (TBD) // Endstops @@ -72,8 +71,8 @@ constexpr Pin DueX_INT = NoPin; // DueX interrupt pin (TBD) // Gcode defines if it is a max ("high end") or min ("low end") endstop and sets if it is active HIGH or LOW. constexpr Pin END_STOP_PINS[DRIVES] = { NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin }; -// HEATERS -constexpr Pin TEMP_SENSE_PINS[Heaters] = { NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin }; // Thermistor pin numbers +// Heater and thermistors +constexpr Pin TEMP_SENSE_PINS[NumThermistorInputs] = { NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin }; // Thermistor pin numbers constexpr Pin HEAT_ON_PINS[Heaters] = { NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin }; // Heater pin numbers (TBD) // Default thermistor parameters @@ -116,7 +115,8 @@ constexpr Pin DiagPin = NoPin; // TBD // Cooling fans constexpr size_t NUM_FANS = 1; constexpr Pin COOLING_FAN_PINS[NUM_FANS] = { NoPin }; -constexpr Pin COOLING_FAN_RPM_PIN = NoPin; // TBD +constexpr size_t NumTachos = 1; +constexpr Pin TachoPins[NumTachos] = { NoPin }; // TBD // SD cards constexpr size_t NumSdCards = 2; diff --git a/src/StepperDrivers/TMC22xx/TMC22xx.cpp b/src/StepperDrivers/TMC22xx/TMC22xx.cpp index 3a52f2e8..55ee62a6 100644 --- a/src/StepperDrivers/TMC22xx/TMC22xx.cpp +++ b/src/StepperDrivers/TMC22xx/TMC22xx.cpp @@ -280,11 +280,22 @@ public: void TransferDone() __attribute__ ((hot)); // called by the ISR when the SPI transfer has completed void StartTransfer() __attribute__ ((hot)); // called to start a transfer void TransferTimedOut() { ++numTimeouts; } - static void AbortTransfer(); + void AbortTransfer(); uint32_t ReadLiveStatus() const; uint32_t ReadAccumulatedStatus(uint32_t bitsToKeep); + // Variables used by the ISR +#if TMC22xx_HAS_MUX + static TmcDriverState * volatile currentDriver; // volatile because the ISR changes it + static uint32_t transferStartedTime; +#else + uint32_t transferStartedTime; + + void CheckTransfer(); // start a transfer or check for timeout + void UartTmcHandler(); // core of the ISR for this driver +#endif + private: void UpdateRegister(size_t regIndex, uint32_t regVal); void UpdateChopConfRegister(); // calculate the chopper control register and flag it for sending @@ -326,6 +337,12 @@ private: uint32_t microstepShiftFactor; // how much we need to shift 1 left by to get the current microstepping uint32_t motorCurrent; // the configured motor current +#if TMC22xx_HAS_MUX + static Uart * const uart; +#else + Uart *uart; // the UART that controls this driver +#endif + uint16_t readErrors; // how many read errors we had uint16_t writeErrors; // how many write errors we had uint16_t numReads; // how many successful reads we had @@ -341,6 +358,10 @@ private: bool enabled; // true if driver is enabled }; +#if TMC22xx_HAS_MUX +Uart * const TmcDriverState::uart = UART_TMC_DRV; +#endif + const uint8_t TmcDriverState::WriteRegNumbers[NumWriteRegisters] = { REGNUM_GCONF, @@ -365,15 +386,6 @@ const uint8_t TmcDriverState::ReadRegCRCs[NumReadRegisters] = // State structures for all drivers static TmcDriverState driverStates[MaxSmartDrivers]; -#if TMC22xx_HAS_MUX -// PDC address for the single UART that communicates with all drivers -static Pdc * const uartPdc = uart_get_pdc_base(UART_TMC_DRV); -#endif - -// Variables used by the ISR -static TmcDriverState * volatile currentDriver = nullptr; // volatile because the ISR changes it -static uint32_t transferStartedTime; - // Set up the PDC to send a register /*static*/ inline void TmcDriverState::SetupDMASend(Pdc *pdc, uint8_t regNum, uint32_t regVal, uint8_t crc) { @@ -444,10 +456,16 @@ pre(!driversPowered) driverNumber = p_driverNumber; axisNumber = p_driverNumber; // assume straight-through axis mapping initially enablePin = p_pin; // this is NoPin for the built-in drivers + +#if !TMC22xx_HAS_MUX + uart = DriverUarts[p_driverNumber]; +#endif + if (p_pin != NoPin) { pinMode(p_pin, OUTPUT_HIGH); } + enabled = false; registersToUpdate = 0; motorCurrent = 0; @@ -677,14 +695,16 @@ inline void TmcDriverState::TransferDone() // This is called to abandon the current transfer, if any void TmcDriverState::AbortTransfer() { - UART_TMC_DRV->UART_IDR = UART_IDR_ENDRX; // disable end-of-receive interrupt - uartPdc->PERIPH_PTCR = (PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); // disable the PDC - UART_TMC_DRV->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA; - currentDriver = nullptr; + uart->UART_IDR = UART_IDR_ENDRX; // disable end-of-receive interrupt + uart_get_pdc_base(uart)->PERIPH_PTCR = (PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); // disable the PDC + uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA; } #if TMC22xx_HAS_MUX +TmcDriverState * volatile TmcDriverState::currentDriver = nullptr; // volatile because the ISR changes it +uint32_t TmcDriverState::transferStartedTime; + // Set up the UART multiplexer to address the selected driver inline void TmcDriverState::SetUartMux() { @@ -714,14 +734,31 @@ inline void TmcDriverState::SetUartMux() } } +#else + +// If no transfer is in progress, start one +// If a transfer is in progress, check for timeout +void TmcDriverState::CheckTransfer() +{ + if ((uart->UART_IMR & UART_IMR_ENDRX) == 0) // if no transfer is in progress + { + StartTransfer(); + } + else if (millis() - TmcDriverState::transferStartedTime > TransferTimeout) + { + // A UART transfer was started but has timed out + TransferTimedOut(); + AbortTransfer(); + } +} + #endif // This is called from the ISR or elsewhere to start a new SPI transfer. Inlined for ISR speed. inline void TmcDriverState::StartTransfer() { - currentDriver = this; - #if TMC22xx_HAS_MUX + currentDriver = this; SetUartMux(); #endif @@ -732,10 +769,10 @@ inline void TmcDriverState::StartTransfer() // Read a register const irqflags_t flags = cpu_irq_save(); // avoid race condition - UART_TMC_DRV->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX; // reset transmitter and receiver - SetupDMAReceive(uartPdc, ReadRegNumbers[registerToRead], ReadRegCRCs[registerToRead]); // set up the PDC - UART_TMC_DRV->UART_IER = UART_IER_ENDRX; // enable end-of-receive interrupt - UART_TMC_DRV->UART_CR = UART_CR_RXEN | UART_CR_TXEN; // enable transmitter and receiver + uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX; // reset transmitter and receiver + SetupDMAReceive(uart_get_pdc_base(uart), ReadRegNumbers[registerToRead], ReadRegCRCs[registerToRead]); // set up the PDC + uart->UART_IER = UART_IER_ENDRX; // enable end-of-receive interrupt + uart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; // enable transmitter and receiver transferStartedTime = millis(); cpu_irq_restore(flags); } @@ -757,21 +794,25 @@ inline void TmcDriverState::StartTransfer() // Kick off a transfer for that register const irqflags_t flags = cpu_irq_save(); // avoid race condition registerBeingUpdated = mask; - UART_TMC_DRV->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX; // reset transmitter and receiver - SetupDMASend(uartPdc, WriteRegNumbers[regNum], writeRegisters[regNum], writeRegCRCs[regNum]); // set up the PDC - UART_TMC_DRV->UART_IER = UART_IER_ENDRX; // enable end-of-transfer interrupt - UART_TMC_DRV->UART_CR = UART_CR_RXEN | UART_CR_TXEN; // enable transmitter and receiver + uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX; // reset transmitter and receiver + SetupDMASend(uart_get_pdc_base(uart), WriteRegNumbers[regNum], writeRegisters[regNum], writeRegCRCs[regNum]); // set up the PDC + uart->UART_IER = UART_IER_ENDRX; // enable end-of-transfer interrupt + uart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; // enable transmitter and receiver transferStartedTime = millis(); cpu_irq_restore(flags); } } -// ISR for the UART -extern "C" void UART_TMC_DRV_Handler(void) __attribute__ ((hot)); +// ISR(s) for the UART(s) -void UART_TMC_DRV_Handler(void) +#if TMC22xx_HAS_MUX + +// ISR for the single UART +extern "C" void UART_TMC_DRV_Handler() __attribute__ ((hot)); + +void UART_TMC_DRV_Handler() { - TmcDriverState *driver = currentDriver; // capture volatile variable + TmcDriverState *driver = TmcDriverState::currentDriver; // capture volatile variable if (driver != nullptr) { driver->TransferDone(); // tidy up after the transfer we just completed @@ -790,9 +831,40 @@ void UART_TMC_DRV_Handler(void) // Driver power is down or there is no current driver, so stop polling UART_TMC_DRV->UART_IDR = UART_IDR_ENDRX; - currentDriver = nullptr; // signal that we are not waiting for an interrupt + TmcDriverState::currentDriver = nullptr; // signal that we are not waiting for an interrupt +} + +#else + +inline void TmcDriverState::UartTmcHandler() +{ + TransferDone(); // tidy up after the transfer we just completed + if (driversState != DriversState::noPower) + { + // Power is still good, so send/receive again + StartTransfer(); + } + else + { + // Driver power is down so disable interrupt to stop polling + uart->UART_IDR = UART_IDR_ENDRX; + } +} + +extern "C" void UART_TMC_DRV0_Handler() __attribute__ ((hot)); +void UART_TMC_DRV0_Handler() +{ + driverStates[0].UartTmcHandler(); +} + +extern "C" void UART_TMC_DRV1_Handler() __attribute__ ((hot)); +void UART_TMC_DRV1_Handler() +{ + driverStates[1].UartTmcHandler(); } +#endif + //--------------------------- Public interface --------------------------------- namespace SmartDrivers @@ -807,8 +879,8 @@ namespace SmartDrivers pinMode(GlobalTmcEnablePin, OUTPUT_HIGH); #if TMC22xx_HAS_MUX - // The pins are already set up for UART use in the pins table - ConfigurePin(GetPinDescription(UART_TMC_DRV_PINS)); + // Set up- the single UART that communicates with all TMC22xx drivers + ConfigurePin(GetPinDescription(UART_TMC_DRV_PINS)); // the pins are already set up for UART use in the pins table // Enable the clock to the UART pmc_enable_periph_clk(ID_UART_TMC_DRV); @@ -819,6 +891,7 @@ namespace SmartDrivers UART_TMC_DRV->UART_MR = UART_MR_CHMODE_NORMAL | UART_MR_PAR_NO; UART_TMC_DRV->UART_BRGR = VARIANT_MCK/(16 * DriversBaudRate); // set baud rate UART_TMC_DRV->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA; + NVIC_EnableIRQ(UART_TMC_DRV_IRQn); // Set up the multiplexer control pins as outputs pinMode(DriverMuxPins[0], OUTPUT_LOW); @@ -829,6 +902,23 @@ namespace SmartDrivers driversState = DriversState::noPower; for (size_t drive = 0; drive < numTmc22xxDrivers; ++drive) { +#if !TMC22xx_HAS_MUX + // Initialise the UART that controls this driver + // The pins are already set up for UART use in the pins table + ConfigurePin(GetPinDescription(DriverUartPins[drive])); + + // Enable the clock to the UART + pmc_enable_periph_clk(DriverUartIds[drive]); + + // Set the UART baud rate, 8 bits, 2 stop bits, no parity + Uart * const uart = DriverUarts[drive]; + uart->UART_IDR = ~0u; + uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS; + uart->UART_MR = UART_MR_CHMODE_NORMAL | UART_MR_PAR_NO; + uart->UART_BRGR = VARIANT_MCK/(16 * DriversBaudRate); // set baud rate + uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA; + NVIC_EnableIRQ(DriverUartIRQns[drive]); +#endif driverStates[drive].Init(drive, driverSelectPins[drive]); // axes are mapped straight through to drivers initially } } @@ -933,28 +1023,37 @@ namespace SmartDrivers } else if (powered) { - if (currentDriver == nullptr) + // If no transfer is in progress, kick one off. + // If a transfer has timed out, abort it. +#if TMC22xx_HAS_MUX + if (TmcDriverState::currentDriver == nullptr) { // No transfer in progress, so start one if (numTmc22xxDrivers != 0) { // Kick off the first transfer - NVIC_EnableIRQ(SERIAL_TMC_DRV_IRQn); driverStates[0].StartTransfer(); } } - else if (millis() - transferStartedTime > TransferTimeout) + else if (millis() - TmcDriverState::transferStartedTime > TransferTimeout) { // A UART transfer was started but has timed out - currentDriver->TransferTimedOut(); - uint8_t driverNum = currentDriver->GetDriverNumber(); - TmcDriverState::AbortTransfer(); // this clears currentDriver + TmcDriverState::currentDriver->TransferTimedOut(); + TmcDriverState::currentDriver->AbortTransfer(); + TmcDriverState::currentDriver = nullptr; + uint8_t driverNum = TmcDriverState::currentDriver->GetDriverNumber(); ++driverNum; if (driverNum >= numTmc22xxDrivers) { driverNum = 0; } } +#else + for (size_t drive = 0; drive < numTmc22xxDrivers; ++drive) + { + driverStates[drive].CheckTransfer(); + } +#endif if (driversState == DriversState::initialising) { @@ -980,7 +1079,18 @@ namespace SmartDrivers { // We had power but we lost it digitalWrite(GlobalTmcEnablePin, HIGH); // disable the drivers - TmcDriverState::AbortTransfer(); +#if TMC22xx_HAS_MUX + if (TmcDriverState::currentDriver == nullptr) + { + TmcDriverState::currentDriver->AbortTransfer(); + TmcDriverState::currentDriver = nullptr; + } +#else + for (size_t drive = 0; drive < numTmc22xxDrivers; ++drive) + { + driverStates[drive].AbortTransfer(); + } +#endif driversState = DriversState::noPower; } } diff --git a/src/StepperDrivers/TMC2660/TMC2660.cpp b/src/StepperDrivers/TMC2660/TMC2660.cpp index 51fbc84c..f99961ea 100644 --- a/src/StepperDrivers/TMC2660/TMC2660.cpp +++ b/src/StepperDrivers/TMC2660/TMC2660.cpp @@ -750,7 +750,7 @@ namespace SmartDrivers if (currentDriver == nullptr && numTmc2660Drivers != 0) { // Kick off the first transfer - NVIC_EnableIRQ(SERIAL_TMC_DRV_IRQn); + NVIC_EnableIRQ(UART_TMC_DRV_IRQn); driverStates[0].StartTransfer(); } } diff --git a/src/StepperDrivers/TMC2660/TMC2660.h b/src/StepperDrivers/TMC2660/TMC2660.h index fa18c27c..ceed9734 100644 --- a/src/StepperDrivers/TMC2660/TMC2660.h +++ b/src/StepperDrivers/TMC2660/TMC2660.h @@ -18,7 +18,7 @@ // The Platform class needs to know which USART we are using when assigning interrupt priorities #define USART_TMC_DRV USART1 -#define SERIAL_TMC_DRV_IRQn USART1_IRQn +#define UART_TMC_DRV_IRQn USART1_IRQn #define ID_USART_TMC_DRV ID_USART1 #define USART_TMC_DRV_Handler USART1_Handler diff --git a/src/Version.h b/src/Version.h index 5d4587ba..2c5b9195 100644 --- a/src/Version.h +++ b/src/Version.h @@ -22,7 +22,7 @@ #endif #ifndef DATE -# define DATE "2018-07-15b1" +# define DATE "2018-07-16b2" #endif #define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman" |