adafruit / seesaw

I2C friend to expand capabilities of other chips.
Other
76 stars 34 forks source link

using TCC1 on SeeSaw #17

Open wallarug opened 5 years ago

wallarug commented 5 years ago

Good Evening,

I am unable to get TCC1 to respond using SeeSaw. I have tried using different pins and it just will not work.

The behavior I am getting is the following:

>>> from adafruit_crickit import crickit
>>> crickit.servo_5.angle = 0
>>> crickit.servo_5.angle = 90

There is no movement of the servo IRL. :sob: TCC0 and TCC2 configured pins work fine.

Is there something that TCC1 is used for other than PWM that would prevent it being used?

board_config.h

#define CONFIG_TIMER_PWM_OUT4 1
#define CONFIG_TIMER_PWM_OUT4_IS_TCC
#define CONFIG_TIMER_PWM_OUT4_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT4_TCC TCC1
#define CONFIG_TIMER_PWM_OUT4_WO 0
#define CONFIG_TIMER_PWM_OUT4_PIN 10       //PA10 - SERVO_05

#define CONFIG_TIMER_PWM_OUT5 1
#define CONFIG_TIMER_PWM_OUT5_IS_TCC
#define CONFIG_TIMER_PWM_OUT5_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT5_TCC TCC1
#define CONFIG_TIMER_PWM_OUT5_WO 1
#define CONFIG_TIMER_PWM_OUT5_PIN 11       //PA11 - SERVO_06

All the pins match up in relevant Python libraries.

Thanks

wallarug commented 5 years ago

Alright. I worked this one out :sweat_smile:

In seesaw/source/AOTimer.cpp someone has set it up so that TCC1 is not able to be used. It incorrectly configures the timer to use function 5 instead of function 4.

This is how each PWM OUT is set up in those files (only showing one for brevity):

Original - seesaw/source/AOTimer.cpp

#if CONFIG_TIMER_PWM_OUT4
#ifdef USE_TCC_TIMERS
#ifdef CONFIG_TIMER_PWM_OUT4_IS_TCC
            if(CONFIG_TIMER_PWM_OUT4_TCC == TCC2)
                pinPeripheral(CONFIG_TIMER_PWM_OUT4_PIN, 4);
            else
                pinPeripheral(CONFIG_TIMER_PWM_OUT4_PIN, 5);

            initTimerPWM( CONFIG_TIMER_PWM_OUT4_TCC );
#else 
            pinPeripheral(CONFIG_TIMER_PWM_OUT4_PIN, 4);
            initTimerPWM( CONFIG_TIMER_PWM_OUT4_TC );
#endif //NOT_ON_TC
#else 
            pinPeripheral(CONFIG_TIMER_PWM_OUT4_PIN, 4);
            initTimerPWM( CONFIG_TIMER_PWM_OUT4_TC );
#endif //USE_TCC_TIMERS
#endif //CONFIG_TIMER_PWM_OUTX

... the problem being on line 4 of the above extract.

I am not sure if this has been done deliberately for SeeSaw to use TCC1 for some other purpose, but I was able to use TCC1 for Servo control without any issue after modifying the above to the below code.

Modified - seesaw/source/AOTimer.cpp

#if CONFIG_TIMER_PWM_OUT4
#ifdef USE_TCC_TIMERS
#ifdef CONFIG_TIMER_PWM_OUT4_IS_TCC
            if(CONFIG_TIMER_PWM_OUT4_TCC == TCC2 || 
                CONFIG_TIMER_PWM_OUT4_TCC == TCC1)
                pinPeripheral(CONFIG_TIMER_PWM_OUT4_PIN, 4);
            else
                pinPeripheral(CONFIG_TIMER_PWM_OUT4_PIN, 5);

            initTimerPWM( CONFIG_TIMER_PWM_OUT4_TCC );
#else 
            pinPeripheral(CONFIG_TIMER_PWM_OUT4_PIN, 4);
            initTimerPWM( CONFIG_TIMER_PWM_OUT4_TC );
#endif //NOT_ON_TC
#else 
            pinPeripheral(CONFIG_TIMER_PWM_OUT4_PIN, 4);
            initTimerPWM( CONFIG_TIMER_PWM_OUT4_TC );
#endif //USE_TCC_TIMERS
#endif //CONFIG_TIMER_PWM_OUTX

:100:

If someone could enlighten me on why this was done in the first place and if there is a good reason for it - that would be great.

Otherwise, I am happy to do a pull-request and fix this so others are able to utilize TCC1 (two extra PWM pins).

Please advise :smile:

ladyada commented 5 years ago

hiya you can submit a PR - there's no maintainer at this time so you're on your own :)

wallarug commented 5 years ago

Notes

SeeSaw currently supports 3 different MCUs:

Need to maintain backwards compatibility with all current boards. Since SAMD21 is the only one that has TCC2, it might be wise to try and change the block that has == TCC2. However this will not fix the problem for some SAMD10 boards which have TCC0 on function E.

Code Sample

#if CONFIG_TIMER_PWM_OUT1
#ifdef USE_TCC_TIMERS
#ifdef CONFIG_TIMER_PWM_OUT1_IS_TCC
            if(CONFIG_TIMER_PWM_OUT1_TCC == TCC2)
                pinPeripheral(CONFIG_TIMER_PWM_OUT1_PIN, 4);
            else
                pinPeripheral(CONFIG_TIMER_PWM_OUT1_PIN, 5);

            initTimerPWM( CONFIG_TIMER_PWM_OUT1_TCC );
#else 
            pinPeripheral(CONFIG_TIMER_PWM_OUT1_PIN, 4);
            initTimerPWM( CONFIG_TIMER_PWM_OUT1_TC );
#endif //NOT_ON_TC
#else 
            pinPeripheral(CONFIG_TIMER_PWM_OUT1_PIN, 4);
            initTimerPWM( CONFIG_TIMER_PWM_OUT1_TC );
#endif //USE_TCC_TIMERS
#endif //CONFIG_TIMER_PWM_OUTX

SAMD10 Problem Pins

SAMD21 Problem Pins

Suggested Fix

I was going to try adding in an extra define variable for selecting which function you are using. This would be the easiest, then you could replace CONFIG_TIMER_PWM_OUT_TCC with which function, instead of only being allowed TCC2 on function F.

Option 1: Direct Replacement

#define CONFIG_TIMER_PWM_OUT0 1
#define CONFIG_TIMER_PWM_OUT0_IS_TCC
#define CONFIG_TIMER_PWM_OUT0_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT0_TCC F
#define CONFIG_TIMER_PWM_OUT0_WO 0
#define CONFIG_TIMER_PWM_OUT0_PIN 8    //PA08 - SERVO_08

Option 2: New Variable

#define CONFIG_TIMER_PWM_OUT0 1
#define CONFIG_TIMER_PWM_OUT0_IS_TCC
#define CONFIG_TIMER_PWM_OUT0_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT0_FUNC E // could be E or F
#define CONFIG_TIMER_PWM_OUT0_WO 0
#define CONFIG_TIMER_PWM_OUT0_PIN 8    //PA08 - SERVO_08

I must note that CONFIG_TIMER_PWM_OUT0_TCC is mentioned and used in bsp/bsp_timer.cpp as well. So I will be testing this out.

wallarug commented 5 years ago

Added a new variable to all the impacted files. It is not the most elegant solution but it restores the functionality. I will PR this now but please do not merge in until I confirm it is working for all boards (most likely this weekend).