Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incomplete samd51 implementation #21

Open
Silvanosky opened this issue Feb 7, 2019 · 28 comments · May be fixed by #34
Open

Incomplete samd51 implementation #21

Silvanosky opened this issue Feb 7, 2019 · 28 comments · May be fixed by #34
Labels
topic: code Related to content of the project itself type: enhancement Proposed improvement

Comments

@Silvanosky
Copy link

Hi,

The implementation for the samd servo library doesn't work on samd51.

The syncbusy bit and clock management are different on this new chip so the code here need to be adapted for samd51.

For example when I try to compile the sweep example for the Feather M4 I get this :

Build options changed, rebuilding all
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp: In function 'void Servo_Handler(timer16_Sequence_t, Tc*, uint8_t, uint8_t)':
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:64:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
         WAIT_TC16_REGS_SYNC(tc)
         ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:81:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
         WAIT_TC16_REGS_SYNC(tc)
         ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:84:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
         WAIT_TC16_REGS_SYNC(tc)
         ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:91:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
         WAIT_TC16_REGS_SYNC(tc)
         ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:99:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
         WAIT_TC16_REGS_SYNC(tc)
         ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp: In function 'void resetTC(Tc*)':
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:112:5: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
     WAIT_TC16_REGS_SYNC(TCx)
     ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:116:5: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
     WAIT_TC16_REGS_SYNC(TCx)
     ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp: In function 'void _initISR(Tc*, uint8_t, uint32_t, IRQn_Type, uint8_t, uint8_t)':
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:123:11: error: 'struct Gclk' has no member named 'CLKCTRL'
     GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer));
           ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:123:37: error: 'GCLK_CLKCTRL_CLKEN' was not declared in this scope
     GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer));
                                     ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:123:58: error: 'GCLK_CLKCTRL_GEN_GCLK0' was not declared in this scope
     GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer));
                                                          ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:123:110: error: 'GCLK_CLKCTRL_ID' was not declared in this scope
     GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer));
                                                                                                              ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:124:18: error: 'struct Gclk' has no member named 'STATUS'
     while (GCLK->STATUS.bit.SYNCBUSY);
                  ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:134:30: error: 'TC_CTRLA_WAVEGEN_NPWM' was not declared in this scope
     tc->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_NPWM;
                              ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:141:5: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
     WAIT_TC16_REGS_SYNC(tc)
     ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:145:5: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
     WAIT_TC16_REGS_SYNC(tc)
     ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:159:5: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
     WAIT_TC16_REGS_SYNC(tc)
     ^
exit status 1
Error compiling for board Adafruit Feather M4 Express (SAMD51).
@ladyada
Copy link

ladyada commented Jun 10, 2019

@facchinm heya would y'all take a PR to fix this?

@facchinm
Copy link
Contributor

Hi @ladyada , we are going to merge the PR, no problem 😉

@PaintYourDragon
Copy link

I’m on it. It’s a little more involved than just the sync registers, but I should have something this afternoon.

@PaintYourDragon
Copy link

A pull request has been made to arduino-libraries:master. If you need it sooner than the next merge, can be downloaded here: https://github.com/PaintYourDragon/Servo

@josephkapp
Copy link

Thank you for the fix, this has been driving me crazy for weeks! Was about to attempt to write my own PWM class. It is compiling for me now.

@knoxvillesjoker
Copy link

Please note, in your existing sketch, copy the servo.h from this updated library which you will download and place in your Arduino libraries folder under servo-master, into whatever sketch you are using.

@richard-pepe
Copy link

richard-pepe commented Jul 24, 2019

I tried this, but I still get a number of compiler errors when compiling for the Adafruit ItsyBitsy M4 (SAMD51).

In file included from /home/rlpepe/Arduino/libraries/Servo-master/src/Servo.h:67:0,
                 from /home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:22:
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp: In function 'void TC4_Handler()':
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/ServoTimers.h:41:35: error: 'TC4' was not declared in this scope
 #define TC_FOR_TIMER1             TC4
                                   ^

I get the same for a number of other macro definitions. The list is much shorter than before updating the library, but I still can't compile successfully. Any thoughts?

@knoxvillesjoker
Copy link

knoxvillesjoker commented Jul 24, 2019

Tc4 needs to be a declared variable?

At top add :

const int TC4;
TC4 = 4;

@GMagician
Copy link

Hi, since I'm working on Marlin and I integrated Grand Central M4 into it, this servo library will be very helpful if integrated into libraries (Marlin uses platformIO but I think this is not a problem).
There are some news about the status of this?

@richard-pepe
Copy link

richard-pepe commented Jul 31, 2019

There seem to be a number of issues yet to resolve to support the SAMD51 (compiles fine for the SAMD21 though). Here's the complete list of compiler messages when compiling for the Adafruit ItsyBitsy M4:

/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp: In function 'void TC4_Handler()':
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:63:86: error: invalid conversion from 'int' to 'Tc*' [-fpermissive]
     Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, INTFLAG_BIT_FOR_TIMER_1);
                                                                                      ^
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:60:6: error:   initializing argument 2 of 'void Servo_Handler(timer16_Sequence_t, Tc*, uint8_t, uint8_t)' [-fpermissive]
 void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel, uint8_t intFlag);
      ^
In file included from /home/rlpepe/Arduino/libraries/Servo-master/src/Servo.h:67:0,
                 from /home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:22:
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp: In function 'void initISR(timer16_Sequence_t)':
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/ServoTimers.h:48:35: error: 'ID_TC4' was not declared in this scope
 #define ID_TC_FOR_TIMER1          ID_TC4
                                   ^
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:251:53: note: in expansion of macro 'ID_TC_FOR_TIMER1'
         _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1, GCM_FOR_TIMER_1, INTENSET_BIT_FOR_TIMER_1);
                                                     ^
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/ServoTimers.h:49:35: error: 'TC4_IRQn' was not declared in this scope
 #define IRQn_FOR_TIMER1           TC4_IRQn
                                   ^
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:251:71: note: in expansion of macro 'IRQn_FOR_TIMER1'
         _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1, GCM_FOR_TIMER_1, INTENSET_BIT_FOR_TIMER_1);
                                                                       ^
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp: In function 'void finISR(timer16_Sequence_t)':
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:263:18: error: base operand of '->' is not a pointer
     TC_FOR_TIMER1->COUNT16.INTENCLR.reg = INTENCLR_BIT_FOR_TIMER_1;
                  ^

@GMagician
Copy link

@richard-pepe that sound weird, I temporary added #28 in Marlin and it compile fine for samd51 (don't know if it works because I don't have proper H/W to test)

@richard-pepe
Copy link

richard-pepe commented Sep 7, 2019

I gave it a shot, but still doesn't compile.

In file included from /home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/Servo.h:67:0,
                 from /home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/Servo.cpp:19:
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/Servo.cpp: In function 'void TC4_Handler()':
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/ServoTimers.h:41:35: error: 'TC4' was not declared in this scope
 #define TC_FOR_TIMER1             TC4
                                   ^
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/Servo.cpp:60:28: note: in expansion of macro 'TC_FOR_TIMER1'
     Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, INTFLAG_BIT_FOR_TIMER_1);
                            ^
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/Servo.cpp: In function 'void initISR(timer16_Sequence_t)':
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/ServoTimers.h:41:35: error: 'TC4' was not declared in this scope
 #define TC_FOR_TIMER1             TC4
                                   ^
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/Servo.cpp:248:18: note: in expansion of macro 'TC_FOR_TIMER1'
         _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1, GCM_FOR_TIMER_1, INTENSET_BIT_FOR_TIMER_1);
                  ^
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/ServoTimers.h:46:35: error: 'ID_TC4' was not declared in this scope
 #define ID_TC_FOR_TIMER1          ID_TC4
                                   ^
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/Servo.cpp:248:53: note: in expansion of macro 'ID_TC_FOR_TIMER1'
         _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1, GCM_FOR_TIMER_1, INTENSET_BIT_FOR_TIMER_1);
                                                     ^
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/ServoTimers.h:47:35: error: 'TC4_IRQn' was not declared in this scope
 #define IRQn_FOR_TIMER1           TC4_IRQn
                                   ^
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/Servo.cpp:248:71: note: in expansion of macro 'IRQn_FOR_TIMER1'
         _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1, GCM_FOR_TIMER_1, INTENSET_BIT_FOR_TIMER_1);
                                                                       ^
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/Servo.cpp: In function 'void finISR(timer16_Sequence_t)':
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/ServoTimers.h:41:35: error: 'TC4' was not declared in this scope
 #define TC_FOR_TIMER1             TC4
                                   ^
/home/rlpepe/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/libraries/Servo/src/samd/Servo.cpp:260:5: note: in expansion of macro 'TC_FOR_TIMER1'
     TC_FOR_TIMER1->COUNT16.INTENCLR.reg = INTENCLR_BIT_FOR_TIMER_1;
     ^

@knoxvillesjoker
Copy link

knoxvillesjoker commented Sep 7, 2019 via email

@GMagician
Copy link

In marlin I have done some job on it and now it should works. Maybe some hints may be got from there

@richard-pepe
Copy link

richard-pepe commented Sep 8, 2019

Not working for me. A number of things aren't defined (TC4, ID_TC4, TC4_IRQn) along with other issues:

/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp: In function 'void TC4_Handler()':
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:60:86: error: invalid conversion from 'int' to 'Tc*' [-fpermissive]
     Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, INTFLAG_BIT_FOR_TIMER_1);
                                                                                      ^
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:57:6: error:   initializing argument 2 of 'void Servo_Handler(timer16_Sequence_t, Tc*, uint8_t, uint8_t)' [-fpermissive]
 void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel, uint8_t intFlag);
      ^
In file included from /home/rlpepe/Arduino/libraries/Servo-master/src/Servo.h:67:0,
                 from /home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:19:
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp: In function 'void initISR(timer16_Sequence_t)':
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/ServoTimers.h:48:35: error: 'ID_TC4' was not declared in this scope
 #define ID_TC_FOR_TIMER1          ID_TC4
                                   ^
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:248:53: note: in expansion of macro 'ID_TC_FOR_TIMER1'
         _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1, GCM_FOR_TIMER_1, INTENSET_BIT_FOR_TIMER_1);
                                                     ^
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/ServoTimers.h:49:35: error: 'TC4_IRQn' was not declared in this scope
 #define IRQn_FOR_TIMER1           TC4_IRQn
                                   ^
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:248:71: note: in expansion of macro 'IRQn_FOR_TIMER1'
         _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1, GCM_FOR_TIMER_1, INTENSET_BIT_FOR_TIMER_1);
                                                                       ^
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp: In function 'void finISR(timer16_Sequence_t)':
/home/rlpepe/Arduino/libraries/Servo-master/src/samd/Servo.cpp:260:18: error: base operand of '->' is not a pointer
     TC_FOR_TIMER1->COUNT16.INTENCLR.reg = INTENCLR_BIT_FOR_TIMER_1;

@knoxvillesjoker
Copy link

knoxvillesjoker commented Sep 9, 2019 via email

@jgarbers
Copy link

I grabbed the fork that @PaintYourDragon posted, and that compiled fine for me. However, it only seems to work with the first servo object defined. If, for example, I have code like this:

Servo s1;
s1.attach(3);
s1.write(100);

Servo s2;
s2.attach(4);
s2.write(100);

the servo attached to pin 3 responds appropriately and my scope shows what looks like a reasonable PWM signal, but the servo on pin 4 doesn't move and the signal on the scope is not at all the same. If I change the order, so s2 is defined before s1, then s2 works and s1 doesn't. The issue seems to be related only to the order in which the objects are instantiated, and doesn't have anything to do with what pins are in use. It also doesn't seem to matter whether I call the attach method on the first servo or not; the second servo still doesn't get the right signal.

At a suggestion from adafruit_support_bill, I've copied this comment from a post I made over on the Adafruit forum, where there's a screenshot from my scope showing the signals being generated. Happy to help troubleshoot from here if I can.

@ladyada
Copy link

ladyada commented Oct 4, 2019

hiya please try
#34
which should compie & work with samd51g19 and j19

@ladyada
Copy link

ladyada commented Oct 4, 2019

multiple-servos also fixed

@GMagician
Copy link

Not sure if it works (I don't have a valid shield to test) and/or may be usefull. This is what I did in Marlin to support both timers:

HAL_SERVO_TIMER_ISR() {
  Tc * const tc = TimerConfig[SERVO_TC].pTimer;
  const timer16_Sequence_t timer =
    #ifndef _useTimer1
      _timer2
    #elif !defined(_useTimer2)
      _timer1
    #else
      (tc->COUNT16.INTFLAG.reg & tc->COUNT16.INTENSET.reg & TC_INTFLAG_MC0) ? _timer1 : _timer2
    #endif
  ;
  const uint8_t tcChannel = TIMER_TCCHANNEL(timer);

  if (currentServoIndex[timer] < 0) {
    #if defined(_useTimer1) && defined(_useTimer2)
      if (currentServoIndex[timer ^ 1] >= 0) {
        // Wait for both channels
        // Clear the interrupt
        tc->COUNT16.INTFLAG.reg = (tcChannel == 0) ? TC_INTFLAG_MC0 : TC_INTFLAG_MC1;
        return;
      }
    #endif
    tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL;
    SYNC(tc->COUNT16.SYNCBUSY.bit.COUNT);
  }
  else if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive)
    digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW);      // pulse this channel low if activated

  // Select the next servo controlled by this timer
  currentServoIndex[timer]++;

  if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) {
    if (SERVO(timer, currentServoIndex[timer]).Pin.isActive)                // check if activated
      digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH);   // it's an active channel so pulse it high

    tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, currentServoIndex[timer]).ticks;
  }
  else {
    // finished all channels so wait for the refresh period to expire before starting over
    currentServoIndex[timer] = -1;   // this will get incremented at the end of the refresh period to start again at the first channel

    const uint16_t tcCounterValue = getTimerCount();

    if ((TC_COUNTER_START_VAL - tcCounterValue) + 4UL < usToTicks(REFRESH_INTERVAL))  // allow a few ticks to ensure the next OCR1A not missed
      tc->COUNT16.CC[tcChannel].reg = TC_COUNTER_START_VAL - (uint16_t)usToTicks(REFRESH_INTERVAL);
    else
      tc->COUNT16.CC[tcChannel].reg = (uint16_t)(tcCounterValue - 4UL);               // at least REFRESH_INTERVAL has elapsed
  }
  if (tcChannel == 0) {
    SYNC(tc->COUNT16.SYNCBUSY.bit.CC0);
    // Clear the interrupt
    tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
  }
  else {
    SYNC(tc->COUNT16.SYNCBUSY.bit.CC1);
    // Clear the interrupt
    tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1;
  }

SYNC(a) is a define that just do while(a)
#define TIMER_TCCHANNEL(t) ((t) & 1)
because I tied timerN with channel

@ladyada
Copy link

ladyada commented Oct 4, 2019

we're doing something similar here, we wanted to be as close to the samd21 implementation as possible

@GMagician
Copy link

yes but SAMD51 CC0 and CC1 share the same timer count, so something different must be done

@ladyada
Copy link

ladyada commented Oct 4, 2019

hiya please explain in more detail. we're using all of TC0, for now just CC0 but it doesnt matter because CC1 wont be usable by anything else anyways. please reference the PR - we want to make this as similar as possible to the SAMD21 code so that means not refactoring the ISR

@GMagician
Copy link

I'll try to explain, but it's not easy due to the fact English is not my natural language.
Code should support 2 timers (timer1 and timer2), both share TC0 and use both TC0 channels (0 and 1) these compare COUNT to CC0 and CC1. Once CC0 terminates its job COUNT is reset but since also CC1 is using the same COUNT value you will change its timing.
AFAIK samd21 has separate counts for channels

@ladyada
Copy link

ladyada commented Oct 4, 2019

OK i know what you're saying - it seems SAMD21 has only one COUNT per timer as well?

Table 30-5. Register Summary – 16-bit Mode

image
image

@GMagician
Copy link

oh yes it seems..but how can it works on samd21?

@ladyada
Copy link

ladyada commented Oct 5, 2019

@GMagician
Copy link

oh how stupid I am...I read it but I was thinking only at samd51...but 21 is also samd...

@per1234 per1234 linked a pull request Jul 19, 2022 that will close this issue
@per1234 per1234 added type: enhancement Proposed improvement topic: code Related to content of the project itself labels Jul 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: code Related to content of the project itself type: enhancement Proposed improvement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants