Parcourir la source

SAMD51 Servo class (#14781)

Giuliano Zaro il y a 4 ans
Parent
révision
21993b75f4

+ 2
- 2
Marlin/src/HAL/HAL_AVR/ServoTimers.h Voir le fichier

@@ -53,8 +53,8 @@
53 53
  * --------------------
54 54
  */
55 55
 
56
-#define TRIM_DURATION       2   // compensation ticks to trim adjust for digitalWrite delays
57
-#define PRESCALER           8   // timer prescaler
56
+#define TRIM_DURATION           2   // compensation ticks to trim adjust for digitalWrite delays
57
+#define SERVO_TIMER_PRESCALER   8   // timer prescaler
58 58
 
59 59
 // Say which 16 bit timers can be used and in what order
60 60
 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

+ 2
- 2
Marlin/src/HAL/HAL_DUE/ServoTimers.h Voir le fichier

@@ -36,8 +36,8 @@
36 36
 //!#define _useTimer4
37 37
 #define _useTimer5
38 38
 
39
-#define TRIM_DURATION       2    // compensation ticks to trim adjust for digitalWrite delays
40
-#define PRESCALER           32   // timer prescaler
39
+#define TRIM_DURATION             2   // compensation ticks to trim adjust for digitalWrite delays
40
+#define SERVO_TIMER_PRESCALER     32  // timer prescaler
41 41
 
42 42
 /*
43 43
   TC0, chan 0 => TC0_Handler

+ 29
- 29
Marlin/src/HAL/HAL_SAMD51/HAL.cpp Voir le fichier

@@ -193,8 +193,8 @@ uint16_t HAL_adc_result;
193 193
   uint16_t HAL_adc_results[COUNT(adc_pins)];
194 194
 
195 195
   #if ADC0_IS_REQUIRED
196
-    Adafruit_ZeroDMA adc0ProgramDMA,
197
-                     adc0ReadDMA;
196
+    Adafruit_ZeroDMA adc0DMAProgram,
197
+                     adc0DMARead;
198 198
 
199 199
     const HAL_DMA_DAC_Registers adc0_dma_regs_list[] = {
200 200
       #if GET_TEMP_0_ADC() == 0
@@ -233,8 +233,8 @@ uint16_t HAL_adc_result;
233 233
   #endif // ADC0_IS_REQUIRED
234 234
 
235 235
   #if ADC1_IS_REQUIRED
236
-    Adafruit_ZeroDMA adc1ProgramDMA,
237
-                     adc1ReadDMA;
236
+    Adafruit_ZeroDMA adc1DMAProgram,
237
+                     adc1DMARead;
238 238
 
239 239
     const HAL_DMA_DAC_Registers adc1_dma_regs_list[] = {
240 240
       #if GET_TEMP_0_ADC() == 1
@@ -284,11 +284,11 @@ uint16_t HAL_adc_result;
284 284
     DmacDescriptor *descriptor;
285 285
 
286 286
     #if ADC0_IS_REQUIRED
287
-      adc0ProgramDMA.setTrigger(ADC0_DMAC_ID_SEQ);
288
-      adc0ProgramDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
289
-      adc0ProgramDMA.loop(true);
290
-      if (adc0ProgramDMA.allocate() == DMA_STATUS_OK) {
291
-        descriptor = adc0ProgramDMA.addDescriptor(
287
+      adc0DMAProgram.setTrigger(ADC0_DMAC_ID_SEQ);
288
+      adc0DMAProgram.setAction(DMA_TRIGGER_ACTON_BEAT);
289
+      adc0DMAProgram.loop(true);
290
+      if (adc0DMAProgram.allocate() == DMA_STATUS_OK) {
291
+        descriptor = adc0DMAProgram.addDescriptor(
292 292
           (void *)adc0_dma_regs_list,         // SRC
293 293
           (void *)&ADC0->DSEQDATA.reg,        // DEST
294 294
           sizeof(adc0_dma_regs_list) / 4,     // CNT
@@ -300,14 +300,14 @@ uint16_t HAL_adc_result;
300 300
         );
301 301
         if (descriptor != nullptr)
302 302
           descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
303
-        adc0ProgramDMA.startJob();
303
+        adc0DMAProgram.startJob();
304 304
       }
305 305
 
306
-      adc0ReadDMA.setTrigger(ADC0_DMAC_ID_RESRDY);
307
-      adc0ReadDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
308
-      adc0ReadDMA.loop(true);
309
-      if (adc0ReadDMA.allocate() == DMA_STATUS_OK) {
310
-        adc0ReadDMA.addDescriptor(
306
+      adc0DMARead.setTrigger(ADC0_DMAC_ID_RESRDY);
307
+      adc0DMARead.setAction(DMA_TRIGGER_ACTON_BEAT);
308
+      adc0DMARead.loop(true);
309
+      if (adc0DMARead.allocate() == DMA_STATUS_OK) {
310
+        adc0DMARead.addDescriptor(
311 311
           (void *)&ADC0->RESULT.reg,          // SRC
312 312
           &HAL_adc_results,                   // DEST
313 313
           ADC0_AINCOUNT,                      // CNT
@@ -317,15 +317,15 @@ uint16_t HAL_adc_result;
317 317
           DMA_ADDRESS_INCREMENT_STEP_SIZE_1,  // STEPSIZE
318 318
           DMA_STEPSEL_DST                     // STEPSEL
319 319
         );
320
-        adc0ReadDMA.startJob();
320
+        adc0DMARead.startJob();
321 321
       }
322 322
     #endif
323 323
     #if ADC1_IS_REQUIRED
324
-      adc1ProgramDMA.setTrigger(ADC1_DMAC_ID_SEQ);
325
-      adc1ProgramDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
326
-      adc1ProgramDMA.loop(true);
327
-      if (adc1ProgramDMA.allocate() == DMA_STATUS_OK) {
328
-        descriptor = adc1ProgramDMA.addDescriptor(
324
+      adc1DMAProgram.setTrigger(ADC1_DMAC_ID_SEQ);
325
+      adc1DMAProgram.setAction(DMA_TRIGGER_ACTON_BEAT);
326
+      adc1DMAProgram.loop(true);
327
+      if (adc1DMAProgram.allocate() == DMA_STATUS_OK) {
328
+        descriptor = adc1DMAProgram.addDescriptor(
329 329
           (void *)adc1_dma_regs_list,         // SRC
330 330
           (void *)&ADC1->DSEQDATA.reg,        // DEST
331 331
           sizeof(adc1_dma_regs_list) / 4,     // CNT
@@ -337,14 +337,14 @@ uint16_t HAL_adc_result;
337 337
         );
338 338
         if (descriptor != nullptr)
339 339
           descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
340
-        adc1ProgramDMA.startJob();
340
+        adc1DMAProgram.startJob();
341 341
       }
342 342
 
343
-      adc1ReadDMA.setTrigger(ADC1_DMAC_ID_RESRDY);
344
-      adc1ReadDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
345
-      adc1ReadDMA.loop(true);
346
-      if (adc1ReadDMA.allocate() == DMA_STATUS_OK) {
347
-        adc1ReadDMA.addDescriptor(
343
+      adc1DMARead.setTrigger(ADC1_DMAC_ID_RESRDY);
344
+      adc1DMARead.setAction(DMA_TRIGGER_ACTON_BEAT);
345
+      adc1DMARead.loop(true);
346
+      if (adc1DMARead.allocate() == DMA_STATUS_OK) {
347
+        adc1DMARead.addDescriptor(
348 348
           (void *)&ADC1->RESULT.reg,          // SRC
349 349
           &HAL_adc_results[ADC0_AINCOUNT],    // DEST
350 350
           ADC1_AINCOUNT,                      // CNT
@@ -354,11 +354,11 @@ uint16_t HAL_adc_result;
354 354
           DMA_ADDRESS_INCREMENT_STEP_SIZE_1,  // STEPSIZE
355 355
           DMA_STEPSEL_DST                     // STEPSEL
356 356
         );
357
-        adc1ReadDMA.startJob();
357
+        adc1DMARead.startJob();
358 358
       }
359 359
     #endif
360 360
 
361
-    DMAC->PRICTRL0.bit.RRLVLEN0 = true;                         // Activate round robin for DMA channels used by ADCs
361
+    DMAC->PRICTRL0.bit.RRLVLEN0 = true;                         // Activate round robin for DMA channels required by ADCs
362 362
   }
363 363
 
364 364
 #endif // DMA_IS_REQUIRED

+ 2
- 1
Marlin/src/HAL/HAL_SAMD51/HAL.h Voir le fichier

@@ -76,7 +76,8 @@
76 76
 
77 77
 typedef int8_t pin_t;
78 78
 
79
-//#define HAL_SERVO_LIB Servo
79
+#define SHARED_SERVOS HAS_SERVOS
80
+#define HAL_SERVO_LIB Servo
80 81
 
81 82
 //
82 83
 // Interrupts

+ 2
- 2
Marlin/src/HAL/HAL_SAMD51/HAL_timers_SAMD51.cpp Voir le fichier

@@ -40,8 +40,8 @@
40 40
 const tTimerConfig TimerConfig[NUM_HARDWARE_TIMERS] = {
41 41
   { TC0, TC0_IRQn, TC_PRIORITY(0) },
42 42
   { TC1, TC1_IRQn, TC_PRIORITY(1) },
43
-  { TC2, TC2_IRQn, TC_PRIORITY(2) },
44
-  { TC3, TC3_IRQn, TC_PRIORITY(3) },
43
+  { TC2, TC2_IRQn, TC_PRIORITY(2) },  // Reserved by framework tone function
44
+  { TC3, TC3_IRQn, TC_PRIORITY(3) },  // Reserved by servo library
45 45
   { TC4, TC4_IRQn, TC_PRIORITY(4) },
46 46
   { TC5, TC5_IRQn, TC_PRIORITY(5) },
47 47
   { TC6, TC6_IRQn, TC_PRIORITY(6) },

+ 4
- 5
Marlin/src/HAL/HAL_SAMD51/HAL_timers_SAMD51.h Voir le fichier

@@ -33,7 +33,6 @@ typedef uint32_t hal_timer_t;
33 33
 
34 34
 #define STEP_TIMER_NUM      0  // index of timer to use for stepper (also +1 for 32bits counter)
35 35
 #define PULSE_TIMER_NUM     STEP_TIMER_NUM
36
-#define TONE_TIMER_NUM      2  // index of timer to use for beeper tones (also +1 for 32bits counter)
37 36
 #define TEMP_TIMER_NUM      4  // index of timer to use for temperature (also +1 for 32bits counter)
38 37
 
39 38
 #define TEMP_TIMER_FREQUENCY   1000 // temperature interrupt frequency
@@ -53,9 +52,10 @@ typedef uint32_t hal_timer_t;
53 52
 #define ENABLE_TEMPERATURE_INTERRUPT()  HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
54 53
 #define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
55 54
 
56
-#define TC_PRIORITY(t)        (t == STEP_TIMER_NUM || t == PULSE_TIMER_NUM) ? 2     \
57
-                               : (t == TEMP_TIMER_NUM) ? 6                          \
58
-                               : (t == TONE_TIMER_NUM) ? 5 : 7
55
+#define TC_PRIORITY(t)        (t == STEP_TIMER_NUM || t == PULSE_TIMER_NUM) ? 2   \
56
+                               : (t == TEMP_TIMER_NUM) ? 6                        \
57
+                               : 7
58
+
59 59
 #define _TC_HANDLER(t)        void TC##t##_Handler()
60 60
 #define TC_HANDLER(t)         _TC_HANDLER(t)
61 61
 #define HAL_STEP_TIMER_ISR()  TC_HANDLER(STEP_TIMER_NUM)
@@ -63,7 +63,6 @@ typedef uint32_t hal_timer_t;
63 63
   #define HAL_PULSE_TIMER_ISR()  TC_HANDLER(PULSE_TIMER_NUM)
64 64
 #endif
65 65
 #define HAL_TEMP_TIMER_ISR()  TC_HANDLER(TEMP_TIMER_NUM)
66
-#define HAL_TONE_TIMER_ISR()  TC_HANDLER(TONE_TIMER_NUM)
67 66
 
68 67
 // --------------------------------------------------------------------------
69 68
 // Types

+ 2
- 2
Marlin/src/HAL/HAL_SAMD51/SAMD51.h Voir le fichier

@@ -20,8 +20,8 @@
20 20
  */
21 21
 #pragma once
22 22
 
23
-#define SYNC(sc)    while (sc) {   \
24
-                      asm("");     \
23
+#define SYNC(sc)    while (sc) {  \
24
+                      asm("");    \
25 25
                     }
26 26
 
27 27
 // Get SAMD port/pin from specified arduino pin

+ 39
- 0
Marlin/src/HAL/HAL_SAMD51/ServoTimers.h Voir le fichier

@@ -0,0 +1,39 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ *
4
+ * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
5
+ * SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
+ *
20
+ */
21
+#pragma once
22
+
23
+#define _useTimer1
24
+#define _useTimer2
25
+
26
+#define TRIM_DURATION           5   // compensation ticks to trim adjust for digitalWrite delays
27
+#define SERVO_TIMER_PRESCALER   64  // timer prescaler factor to 64 (avoid overflowing 16-bit clock counter, at 120MHz this is 1831 ticks per millisecond
28
+
29
+#define SERVO_TC                3
30
+
31
+typedef enum {
32
+  #ifdef _useTimer1
33
+    _timer1,
34
+  #endif
35
+  #ifdef _useTimer2
36
+    _timer2,
37
+  #endif
38
+  _Nbr_16timers
39
+} timer16_Sequence_t;

+ 226
- 0
Marlin/src/HAL/HAL_SAMD51/Servo_SAMD51.cpp Voir le fichier

@@ -0,0 +1,226 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ *
4
+ * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
5
+ * SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
+ *
20
+ */
21
+
22
+/**
23
+ * This comes from Arduino library which at the moment is buggy and uncompilable
24
+ */
25
+
26
+#ifdef __SAMD51__
27
+
28
+#include "../../inc/MarlinConfig.h"
29
+
30
+#if HAS_SERVOS
31
+
32
+#include "../shared/Marduino.h"
33
+#include "../shared/servo.h"
34
+#include "../shared/servo_private.h"
35
+#include "SAMD51.h"
36
+#include "HAL_timers_SAMD51.h"
37
+
38
+#define __TC_GCLK_ID(t)         TC##t##_GCLK_ID
39
+#define _TC_GCLK_ID(t)          __TC_GCLK_ID(t)
40
+#define TC_GCLK_ID              _TC_GCLK_ID(SERVO_TC)
41
+
42
+#define _TC_PRESCALER(d)        TC_CTRLA_PRESCALER_DIV##d##_Val
43
+#define TC_PRESCALER(d)         _TC_PRESCALER(d)
44
+
45
+#define __SERVO_IRQn(t)         TC##t##_IRQn
46
+#define _SERVO_IRQn(t)          __SERVO_IRQn(t)
47
+#define SERVO_IRQn              _SERVO_IRQn(SERVO_TC)
48
+
49
+#define HAL_SERVO_TIMER_ISR()   TC_HANDLER(SERVO_TC)
50
+
51
+#define TIMER_TCCHANNEL(t)      ((t) & 1)
52
+#define TC_COUNTER_START_VAL    0xFFFF
53
+
54
+
55
+static volatile int8_t currentServoIndex[_Nbr_16timers];    // index for the servo being pulsed for each timer (or -1 if refresh interval)
56
+
57
+FORCE_INLINE static uint16_t getTimerCount() {
58
+  Tc * const tc = TimerConfig[SERVO_TC].pTimer;
59
+
60
+  tc->COUNT16.CTRLBSET.reg = TC_CTRLBCLR_CMD_READSYNC;
61
+  SYNC(tc->COUNT16.SYNCBUSY.bit.CTRLB || tc->COUNT16.SYNCBUSY.bit.COUNT);
62
+
63
+  return tc->COUNT16.COUNT.reg;
64
+}
65
+
66
+// ----------------------------
67
+// Interrupt handler for the TC
68
+// ----------------------------
69
+HAL_SERVO_TIMER_ISR() {
70
+  Tc * const tc = TimerConfig[SERVO_TC].pTimer;
71
+  const timer16_Sequence_t timer =
72
+    #ifndef _useTimer1
73
+      _timer2
74
+    #elif !defined(_useTimer2)
75
+      _timer1
76
+    #else
77
+      (tc->COUNT16.INTFLAG.reg & tc->COUNT16.INTENSET.reg & TC_INTFLAG_MC0) ? _timer1 : _timer2
78
+    #endif
79
+  ;
80
+  const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
81
+
82
+  if (currentServoIndex[timer] < 0) {
83
+    #if defined(_useTimer1) && defined(_useTimer2)
84
+      if (currentServoIndex[timer ^ 1] >= 0) {
85
+        // Wait for both channels
86
+        // Clear the interrupt
87
+        tc->COUNT16.INTFLAG.reg = (tcChannel == 0) ? TC_INTFLAG_MC0 : TC_INTFLAG_MC1;
88
+        return;
89
+      }
90
+    #endif
91
+    tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL;
92
+    SYNC(tc->COUNT16.SYNCBUSY.bit.COUNT);
93
+  }
94
+  else if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive)
95
+    digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW);      // pulse this channel low if activated
96
+
97
+  // Select the next servo controlled by this timer
98
+  currentServoIndex[timer]++;
99
+
100
+  if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) {
101
+    if (SERVO(timer, currentServoIndex[timer]).Pin.isActive)                // check if activated
102
+      digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH);   // it's an active channel so pulse it high
103
+
104
+    tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, currentServoIndex[timer]).ticks;
105
+  }
106
+  else {
107
+    // finished all channels so wait for the refresh period to expire before starting over
108
+    currentServoIndex[timer] = -1;   // this will get incremented at the end of the refresh period to start again at the first channel
109
+
110
+    const uint16_t tcCounterValue = getTimerCount();
111
+
112
+    if ((TC_COUNTER_START_VAL - tcCounterValue) + 4UL < usToTicks(REFRESH_INTERVAL))  // allow a few ticks to ensure the next OCR1A not missed
113
+      tc->COUNT16.CC[tcChannel].reg = TC_COUNTER_START_VAL - (uint16_t)usToTicks(REFRESH_INTERVAL);
114
+    else
115
+      tc->COUNT16.CC[tcChannel].reg = (uint16_t)(tcCounterValue - 4UL);               // at least REFRESH_INTERVAL has elapsed
116
+  }
117
+  if (tcChannel == 0) {
118
+    SYNC(tc->COUNT16.SYNCBUSY.bit.CC0); 
119
+    // Clear the interrupt
120
+    tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
121
+  }
122
+  else {
123
+    SYNC(tc->COUNT16.SYNCBUSY.bit.CC1); 
124
+    // Clear the interrupt
125
+    tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1;
126
+  }
127
+}
128
+
129
+void initISR(timer16_Sequence_t timer) {
130
+  Tc * const tc = TimerConfig[SERVO_TC].pTimer;
131
+  const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
132
+
133
+  static bool initialized = false;  // Servo TC has been initialized
134
+  if (!initialized) {
135
+    NVIC_DisableIRQ(SERVO_IRQn);
136
+
137
+    // Disable the timer
138
+    tc->COUNT16.CTRLA.bit.ENABLE = false;
139
+    SYNC(tc->COUNT16.SYNCBUSY.bit.ENABLE);
140
+
141
+    // Select GCLK0 as timer/counter input clock source
142
+    GCLK->PCHCTRL[TC_GCLK_ID].bit.CHEN = false;
143
+    SYNC(GCLK->PCHCTRL[TC_GCLK_ID].bit.CHEN);
144
+    GCLK->PCHCTRL[TC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;   // 120MHz startup code programmed
145
+    SYNC(!GCLK->PCHCTRL[TC_GCLK_ID].bit.CHEN);
146
+
147
+    // Reset the timer
148
+    tc->COUNT16.CTRLA.bit.SWRST = true;
149
+    SYNC(tc->COUNT16.SYNCBUSY.bit.SWRST);
150
+    SYNC(tc->COUNT16.CTRLA.bit.SWRST);
151
+
152
+    // Set timer counter mode to 16 bits
153
+    tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16;
154
+
155
+    // Set timer counter mode as normal PWM
156
+    tc->COUNT16.WAVE.bit.WAVEGEN = TCC_WAVE_WAVEGEN_NPWM_Val;
157
+
158
+    // Set the prescaler factor
159
+    tc->COUNT16.CTRLA.bit.PRESCALER = TC_PRESCALER(SERVO_TIMER_PRESCALER);
160
+
161
+    // Count down
162
+    tc->COUNT16.CTRLBSET.reg = TC_CTRLBCLR_DIR;
163
+    SYNC(tc->COUNT16.SYNCBUSY.bit.CTRLB);
164
+
165
+    // Reset all servo indexes
166
+    memset(currentServoIndex, 0xFF, sizeof(currentServoIndex));
167
+
168
+    // Configure interrupt request
169
+    NVIC_ClearPendingIRQ(SERVO_IRQn);
170
+    NVIC_SetPriority(SERVO_IRQn, 5);
171
+    NVIC_EnableIRQ(SERVO_IRQn);
172
+
173
+    initialized = true;
174
+  }
175
+
176
+  if (!tc->COUNT16.CTRLA.bit.ENABLE) {
177
+    // Reset the timer counter
178
+    tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL;
179
+    SYNC(tc->COUNT16.SYNCBUSY.bit.COUNT);
180
+
181
+    // Enable the timer and start it
182
+    tc->COUNT16.CTRLA.bit.ENABLE = true;
183
+    SYNC(tc->COUNT16.SYNCBUSY.bit.ENABLE);
184
+  }
185
+  // First interrupt request after 1 ms
186
+  tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)usToTicks(1000UL);
187
+
188
+  if (tcChannel == 0 ) {
189
+    SYNC(tc->COUNT16.SYNCBUSY.bit.CC0);
190
+
191
+    // Clear pending match interrupt
192
+    tc->COUNT16.INTFLAG.reg = TC_INTENSET_MC0;
193
+    // Enable the match channel interrupt request
194
+    tc->COUNT16.INTENSET.reg = TC_INTENSET_MC0;
195
+  }
196
+  else {
197
+    SYNC(tc->COUNT16.SYNCBUSY.bit.CC1);
198
+
199
+    // Clear pending match interrupt
200
+    tc->COUNT16.INTFLAG.reg = TC_INTENSET_MC1;
201
+    // Enable the match channel interrupt request
202
+    tc->COUNT16.INTENSET.reg = TC_INTENSET_MC1;
203
+  }
204
+}
205
+
206
+void finISR(timer16_Sequence_t timer) {
207
+  Tc * const tc = TimerConfig[SERVO_TC].pTimer;
208
+  const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
209
+
210
+  // Disable the match channel interrupt request
211
+  tc->COUNT16.INTENCLR.reg = (tcChannel == 0) ? TC_INTENCLR_MC0 : TC_INTENCLR_MC1;
212
+
213
+  if (true
214
+    #if defined(_useTimer1) && defined(_useTimer2)
215
+      && (tc->COUNT16.INTENCLR.reg & (TC_INTENCLR_MC0|TC_INTENCLR_MC1)) == 0
216
+    #endif
217
+  ) {
218
+    // Disable the timer if not used
219
+    tc->COUNT16.CTRLA.bit.ENABLE = false;
220
+    SYNC(tc->COUNT16.SYNCBUSY.bit.ENABLE);
221
+  }
222
+}
223
+
224
+#endif // HAS_SERVOS
225
+
226
+#endif // __SAMD51__

+ 0
- 59
Marlin/src/HAL/HAL_SAMD51/Tone.cpp Voir le fichier

@@ -1,59 +0,0 @@
1
-/**
2
- * Marlin 3D Printer Firmware
3
- *
4
- * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
5
- * SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
6
- *
7
- * This program is free software: you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation, either version 3 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
- *
20
- */
21
-
22
-/**
23
- * Description: Tone function for Arduino Due and compatible (SAM3X8E)
24
- * Derived from http://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012
25
- */
26
-
27
-#ifdef __SAMD51__
28
-
29
-#include "../../inc/MarlinConfig.h"
30
-#include "HAL_timers_SAMD51.h"
31
-
32
-static pin_t tone_pin;
33
-volatile static int32_t toggles;
34
-
35
-void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) {
36
-  tone_pin = _pin;
37
-  toggles = 2 * frequency * duration / 1000;
38
-  HAL_timer_start(TONE_TIMER_NUM, 2 * frequency);
39
-}
40
-
41
-void noTone(const pin_t _pin) {
42
-  HAL_timer_disable_interrupt(TONE_TIMER_NUM);
43
-  extDigitalWrite(_pin, LOW);
44
-}
45
-
46
-HAL_TONE_TIMER_ISR() {
47
-  static bool pin_state = false;
48
-  HAL_timer_isr_prologue(TONE_TIMER_NUM);
49
-
50
-  if (toggles) {
51
-    toggles--;
52
-    extDigitalWrite(tone_pin, (pin_state = !pin_state));
53
-  }
54
-  else noTone(tone_pin);                         // turn off interrupt
55
-
56
-  HAL_timer_isr_epilogue(TONE_TIMER_NUM);
57
-}
58
-
59
-#endif // __SAMD51__

+ 0
- 2
Marlin/src/HAL/HAL_STM32/HAL_timers_STM32.cpp Voir le fichier

@@ -32,8 +32,6 @@
32 32
 
33 33
 #define NUM_HARDWARE_TIMERS 2
34 34
 
35
-//#define PRESCALER 1
36
-
37 35
 // ------------------------
38 36
 // Private Variables
39 37
 // ------------------------

+ 0
- 2
Marlin/src/HAL/HAL_STM32_F4_F7/STM32F4/HAL_timers_STM32F4.cpp Voir le fichier

@@ -33,8 +33,6 @@
33 33
 #define STEP_TIMER_IRQ_ID TIM5_IRQn
34 34
 #define TEMP_TIMER_IRQ_ID TIM7_IRQn
35 35
 
36
-//#define PRESCALER 1
37
-
38 36
 // ------------------------
39 37
 // Private Variables
40 38
 // ------------------------

+ 2
- 3
Marlin/src/HAL/shared/servo.cpp Voir le fichier

@@ -116,9 +116,8 @@ void Servo::detach() {
116 116
 }
117 117
 
118 118
 void Servo::write(int value) {
119
-  if (value < MIN_PULSE_WIDTH) { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
119
+  if (value < MIN_PULSE_WIDTH)    // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
120 120
     value = map(constrain(value, 0, 180), 0, 180, SERVO_MIN(), SERVO_MAX());
121
-  }
122 121
   this->writeMicroseconds(value);
123 122
 }
124 123
 
@@ -140,7 +139,7 @@ void Servo::writeMicroseconds(int value) {
140 139
 int Servo::read() { return map(this->readMicroseconds() + 1, SERVO_MIN(), SERVO_MAX(), 0, 180); }
141 140
 
142 141
 int Servo::readMicroseconds() {
143
-  return (this->servoIndex == INVALID_SERVO) ? 0 : ticksToUs(servo_info[this->servoIndex].ticks) + TRIM_DURATION;
142
+  return (this->servoIndex == INVALID_SERVO) ? 0 : ticksToUs(servo_info[this->servoIndex].ticks) + (TRIM_DURATION);
144 143
 }
145 144
 
146 145
 bool Servo::attached() { return servo_info[this->servoIndex].Pin.isActive; }

+ 2
- 2
Marlin/src/HAL/shared/servo.h Voir le fichier

@@ -84,10 +84,10 @@
84 84
 #else
85 85
   #include <stdint.h>
86 86
 
87
-  #if defined(__AVR__) || defined(ARDUINO_ARCH_SAM)
87
+  #if defined(__AVR__) || defined(ARDUINO_ARCH_SAM) || defined (__SAMD51__)
88 88
     // we're good to go
89 89
   #else
90
-    #error "This library only supports boards with an AVR or SAM3X processor."
90
+    #error "This library only supports boards with an AVR, SAM3X or SAMD51 processor."
91 91
   #endif
92 92
 
93 93
   #define Servo_VERSION           2     // software version of this library

+ 6
- 6
Marlin/src/HAL/shared/servo_private.h Voir le fichier

@@ -47,8 +47,10 @@
47 47
   #include "../HAL_AVR/ServoTimers.h"
48 48
 #elif defined(ARDUINO_ARCH_SAM)
49 49
   #include "../HAL_DUE/ServoTimers.h"
50
+#elif defined(__SAMD51__)
51
+  #include "../HAL_SAMD51/ServoTimers.h"
50 52
 #else
51
-  #error "This library only supports boards with an AVR or SAM3X processor."
53
+  #error "This library only supports boards with an AVR, SAM3X or SAMD51 processor."
52 54
 #endif
53 55
 
54 56
 // Macros
@@ -64,10 +66,8 @@
64 66
 #define INVALID_SERVO         255     // flag indicating an invalid servo index
65 67
 
66 68
 // Convert microseconds to ticks and back (PRESCALER depends on architecture)
67
-#define usToTicks(_us)    (clockCyclesPerMicrosecond() * (_us) / (PRESCALER))
68
-#define ticksToUs(_ticks) (unsigned(_ticks) * (PRESCALER) / clockCyclesPerMicrosecond())
69
-
70
-//#define NBR_TIMERS        ((MAX_SERVOS) / (SERVOS_PER_TIMER))
69
+#define usToTicks(_us)    (clockCyclesPerMicrosecond() * (_us) / (SERVO_TIMER_PRESCALER))
70
+#define ticksToUs(_ticks) (unsigned(_ticks) * (SERVO_TIMER_PRESCALER) / clockCyclesPerMicrosecond())
71 71
 
72 72
 // convenience macros
73 73
 #define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / (SERVOS_PER_TIMER))) // returns the timer controlling this servo
@@ -78,7 +78,7 @@
78 78
 // Types
79 79
 
80 80
 typedef struct {
81
-  uint8_t nbr        : 6 ;            // a pin number from 0 to 63
81
+  uint8_t nbr        : 7 ;            // a pin number from 0 to 127
82 82
   uint8_t isActive   : 1 ;            // true if this channel is enabled, pin not pulsed if false
83 83
 } ServoPin_t;
84 84
 

Chargement…
Annuler
Enregistrer