|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623 |
- /*
- * Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
- * Original code by Jesse Tane for http://labs.ideo.com August 2008
- * Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
- * Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
- * Modified April 2012 by Paul Stoffregen - portable to other AVR chips, use inline functions
- * Modified again, June 2014 by Paul Stoffregen - support Teensy 3.x & even more AVR chips
- * Modified July 2017 by Stoyko Dimitrov - added support for ATTiny85 except for the PWM functionality
- *
- *
- * This is free software. You can redistribute it and/or modify it under
- * the terms of Creative Commons Attribution 3.0 United States License.
- * To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
- * or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
- *
- */
-
- #ifndef TimerOne_h_
- #define TimerOne_h_
-
- #if defined(ARDUINO) && ARDUINO >= 100
- #include "Arduino.h"
- #else
- #include "WProgram.h"
- #endif
-
- #include "config/known_16bit_timers.h"
- #if defined (__AVR_ATtiny85__)
- #define TIMER1_RESOLUTION 256UL // Timer1 is 8 bit
- #elif defined(__AVR__)
- #define TIMER1_RESOLUTION 65536UL // Timer1 is 16 bit
- #else
- #define TIMER1_RESOLUTION 65536UL // assume 16 bits for non-AVR chips
- #endif
-
- // Placing nearly all the code in this .h file allows the functions to be
- // inlined by the compiler. In the very common case with constant values
- // the compiler will perform all calculations and simply write constants
- // to the hardware registers (for example, setPeriod).
-
-
- class TimerOne
- {
-
- #if defined (__AVR_ATtiny85__)
- public:
- //****************************
- // Configuration
- //****************************
- void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
- TCCR1 = _BV(CTC1); //clear timer1 when it matches the value in OCR1C
- TIMSK |= _BV(OCIE1A); //enable interrupt when OCR1A matches the timer value
- setPeriod(microseconds);
- }
- void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
- const unsigned long cycles = microseconds * ratio;
- if (cycles < TIMER1_RESOLUTION) {
- clockSelectBits = _BV(CS10);
- pwmPeriod = cycles;
- } else
- if (cycles < TIMER1_RESOLUTION * 2UL) {
- clockSelectBits = _BV(CS11);
- pwmPeriod = cycles / 2;
- } else
- if (cycles < TIMER1_RESOLUTION * 4UL) {
- clockSelectBits = _BV(CS11) | _BV(CS10);
- pwmPeriod = cycles / 4;
- } else
- if (cycles < TIMER1_RESOLUTION * 8UL) {
- clockSelectBits = _BV(CS12);
- pwmPeriod = cycles / 8;
- } else
- if (cycles < TIMER1_RESOLUTION * 16UL) {
- clockSelectBits = _BV(CS12) | _BV(CS10);
- pwmPeriod = cycles / 16;
- } else
- if (cycles < TIMER1_RESOLUTION * 32UL) {
- clockSelectBits = _BV(CS12) | _BV(CS11);
- pwmPeriod = cycles / 32;
- } else
- if (cycles < TIMER1_RESOLUTION * 64UL) {
- clockSelectBits = _BV(CS12) | _BV(CS11) | _BV(CS10);
- pwmPeriod = cycles / 64UL;
- } else
- if (cycles < TIMER1_RESOLUTION * 128UL) {
- clockSelectBits = _BV(CS13);
- pwmPeriod = cycles / 128;
- } else
- if (cycles < TIMER1_RESOLUTION * 256UL) {
- clockSelectBits = _BV(CS13) | _BV(CS10);
- pwmPeriod = cycles / 256;
- } else
- if (cycles < TIMER1_RESOLUTION * 512UL) {
- clockSelectBits = _BV(CS13) | _BV(CS11);
- pwmPeriod = cycles / 512;
- } else
- if (cycles < TIMER1_RESOLUTION * 1024UL) {
- clockSelectBits = _BV(CS13) | _BV(CS11) | _BV(CS10);
- pwmPeriod = cycles / 1024;
- } else
- if (cycles < TIMER1_RESOLUTION * 2048UL) {
- clockSelectBits = _BV(CS13) | _BV(CS12);
- pwmPeriod = cycles / 2048;
- } else
- if (cycles < TIMER1_RESOLUTION * 4096UL) {
- clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS10);
- pwmPeriod = cycles / 4096;
- } else
- if (cycles < TIMER1_RESOLUTION * 8192UL) {
- clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11);
- pwmPeriod = cycles / 8192;
- } else
- if (cycles < TIMER1_RESOLUTION * 16384UL) {
- clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10);
- pwmPeriod = cycles / 16384;
- } else {
- clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10);
- pwmPeriod = TIMER1_RESOLUTION - 1;
- }
- OCR1A = pwmPeriod;
- OCR1C = pwmPeriod;
- TCCR1 = _BV(CTC1) | clockSelectBits;
- }
-
- //****************************
- // Run Control
- //****************************
- void start() __attribute__((always_inline)) {
- TCCR1 = 0;
- TCNT1 = 0;
- resume();
- }
- void stop() __attribute__((always_inline)) {
- TCCR1 = _BV(CTC1);
- }
- void restart() __attribute__((always_inline)) {
- start();
- }
- void resume() __attribute__((always_inline)) {
- TCCR1 = _BV(CTC1) | clockSelectBits;
- }
-
- //****************************
- // PWM outputs
- //****************************
- //Not implemented yet for ATTiny85
- //TO DO
-
- //****************************
- // Interrupt Function
- //****************************
- void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
- isrCallback = isr;
- TIMSK |= _BV(OCIE1A);
- }
- void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
- if(microseconds > 0) setPeriod(microseconds);
- attachInterrupt(isr);
- }
- void detachInterrupt() __attribute__((always_inline)) {
- //TIMSK = 0; // Timer 0 and Timer 1 both use TIMSK register so setting it to 0 will override settings for Timer1 as well
- TIMSK &= ~_BV(OCIE1A);
- }
- static void (*isrCallback)();
- static void isrDefaultUnused();
-
- private:
- static unsigned short pwmPeriod;
- static unsigned char clockSelectBits;
- static const byte ratio = (F_CPU)/ ( 1000000 );
-
- #elif defined(__AVR__)
-
- #if defined (__AVR_ATmega8__)
- //in some io definitions for older microcontrollers TIMSK is used instead of TIMSK1
- #define TIMSK1 TIMSK
- #endif
-
- public:
- //****************************
- // Configuration
- //****************************
- void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
- TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer
- TCCR1A = 0; // clear control register A
- setPeriod(microseconds);
- }
- void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
- const unsigned long cycles = ((F_CPU/100000 * microseconds) / 20);
- if (cycles < TIMER1_RESOLUTION) {
- clockSelectBits = _BV(CS10);
- pwmPeriod = cycles;
- } else
- if (cycles < TIMER1_RESOLUTION * 8) {
- clockSelectBits = _BV(CS11);
- pwmPeriod = cycles / 8;
- } else
- if (cycles < TIMER1_RESOLUTION * 64) {
- clockSelectBits = _BV(CS11) | _BV(CS10);
- pwmPeriod = cycles / 64;
- } else
- if (cycles < TIMER1_RESOLUTION * 256) {
- clockSelectBits = _BV(CS12);
- pwmPeriod = cycles / 256;
- } else
- if (cycles < TIMER1_RESOLUTION * 1024) {
- clockSelectBits = _BV(CS12) | _BV(CS10);
- pwmPeriod = cycles / 1024;
- } else {
- clockSelectBits = _BV(CS12) | _BV(CS10);
- pwmPeriod = TIMER1_RESOLUTION - 1;
- }
- ICR1 = pwmPeriod;
- TCCR1B = _BV(WGM13) | clockSelectBits;
- }
-
- //****************************
- // Run Control
- //****************************
- void start() __attribute__((always_inline)) {
- TCCR1B = 0;
- TCNT1 = 0; // TODO: does this cause an undesired interrupt?
- resume();
- }
- void stop() __attribute__((always_inline)) {
- TCCR1B = _BV(WGM13);
- }
- void restart() __attribute__((always_inline)) {
- start();
- }
- void resume() __attribute__((always_inline)) {
- TCCR1B = _BV(WGM13) | clockSelectBits;
- }
-
- //****************************
- // PWM outputs
- //****************************
- void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) {
- unsigned long dutyCycle = pwmPeriod;
- dutyCycle *= duty;
- dutyCycle >>= 10;
- if (pin == TIMER1_A_PIN) OCR1A = dutyCycle;
- #ifdef TIMER1_B_PIN
- else if (pin == TIMER1_B_PIN) OCR1B = dutyCycle;
- #endif
- #ifdef TIMER1_C_PIN
- else if (pin == TIMER1_C_PIN) OCR1C = dutyCycle;
- #endif
- }
- void pwm(char pin, unsigned int duty) __attribute__((always_inline)) {
- if (pin == TIMER1_A_PIN) { pinMode(TIMER1_A_PIN, OUTPUT); TCCR1A |= _BV(COM1A1); }
- #ifdef TIMER1_B_PIN
- else if (pin == TIMER1_B_PIN) { pinMode(TIMER1_B_PIN, OUTPUT); TCCR1A |= _BV(COM1B1); }
- #endif
- #ifdef TIMER1_C_PIN
- else if (pin == TIMER1_C_PIN) { pinMode(TIMER1_C_PIN, OUTPUT); TCCR1A |= _BV(COM1C1); }
- #endif
- setPwmDuty(pin, duty);
- TCCR1B = _BV(WGM13) | clockSelectBits;
- }
- void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) {
- if (microseconds > 0) setPeriod(microseconds);
- pwm(pin, duty);
- }
- void disablePwm(char pin) __attribute__((always_inline)) {
- if (pin == TIMER1_A_PIN) TCCR1A &= ~_BV(COM1A1);
- #ifdef TIMER1_B_PIN
- else if (pin == TIMER1_B_PIN) TCCR1A &= ~_BV(COM1B1);
- #endif
- #ifdef TIMER1_C_PIN
- else if (pin == TIMER1_C_PIN) TCCR1A &= ~_BV(COM1C1);
- #endif
- }
-
- //****************************
- // Interrupt Function
- //****************************
-
- void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
- isrCallback = isr;
- TIMSK1 = _BV(TOIE1);
- }
- void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
- if(microseconds > 0) setPeriod(microseconds);
- attachInterrupt(isr);
- }
- void detachInterrupt() __attribute__((always_inline)) {
- TIMSK1 = 0;
- }
- static void (*isrCallback)();
- static void isrDefaultUnused();
-
- private:
- // properties
- static unsigned short pwmPeriod;
- static unsigned char clockSelectBits;
-
-
-
-
-
-
- #elif defined(__arm__) && defined(TEENSYDUINO) && (defined(KINETISK) || defined(KINETISL))
-
- #if defined(KINETISK)
- #define F_TIMER F_BUS
- #elif defined(KINETISL)
- #define F_TIMER (F_PLL/2)
- #endif
-
- // Use only 15 bit resolution. From K66 reference manual, 45.5.7 page 1200:
- // The CPWM pulse width (duty cycle) is determined by 2 x (CnV - CNTIN) and the
- // period is determined by 2 x (MOD - CNTIN). See the following figure. MOD must be
- // kept in the range of 0x0001 to 0x7FFF because values outside this range can produce
- // ambiguous results.
- #undef TIMER1_RESOLUTION
- #define TIMER1_RESOLUTION 32768
-
- public:
- //****************************
- // Configuration
- //****************************
- void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
- setPeriod(microseconds);
- }
- void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
- const unsigned long cycles = (F_TIMER / 2000000) * microseconds;
- // A much faster if-else
- // This is like a binary serch tree and no more than 3 conditions are evaluated.
- // I haven't checked if this becomes significantly longer ASM than the simple ladder.
- // It looks very similar to the ladder tho: same # of if's and else's
-
- /*
- // This code does not work properly in all cases :(
- // https://github.com/PaulStoffregen/TimerOne/issues/17
- if (cycles < TIMER1_RESOLUTION * 16) {
- if (cycles < TIMER1_RESOLUTION * 4) {
- if (cycles < TIMER1_RESOLUTION) {
- clockSelectBits = 0;
- pwmPeriod = cycles;
- }else{
- clockSelectBits = 1;
- pwmPeriod = cycles >> 1;
- }
- }else{
- if (cycles < TIMER1_RESOLUTION * 8) {
- clockSelectBits = 3;
- pwmPeriod = cycles >> 3;
- }else{
- clockSelectBits = 4;
- pwmPeriod = cycles >> 4;
- }
- }
- }else{
- if (cycles > TIMER1_RESOLUTION * 64) {
- if (cycles > TIMER1_RESOLUTION * 128) {
- clockSelectBits = 7;
- pwmPeriod = TIMER1_RESOLUTION - 1;
- }else{
- clockSelectBits = 7;
- pwmPeriod = cycles >> 7;
- }
- }
- else{
- if (cycles > TIMER1_RESOLUTION * 32) {
- clockSelectBits = 6;
- pwmPeriod = cycles >> 6;
- }else{
- clockSelectBits = 5;
- pwmPeriod = cycles >> 5;
- }
- }
- }
- */
- if (cycles < TIMER1_RESOLUTION) {
- clockSelectBits = 0;
- pwmPeriod = cycles;
- } else
- if (cycles < TIMER1_RESOLUTION * 2) {
- clockSelectBits = 1;
- pwmPeriod = cycles >> 1;
- } else
- if (cycles < TIMER1_RESOLUTION * 4) {
- clockSelectBits = 2;
- pwmPeriod = cycles >> 2;
- } else
- if (cycles < TIMER1_RESOLUTION * 8) {
- clockSelectBits = 3;
- pwmPeriod = cycles >> 3;
- } else
- if (cycles < TIMER1_RESOLUTION * 16) {
- clockSelectBits = 4;
- pwmPeriod = cycles >> 4;
- } else
- if (cycles < TIMER1_RESOLUTION * 32) {
- clockSelectBits = 5;
- pwmPeriod = cycles >> 5;
- } else
- if (cycles < TIMER1_RESOLUTION * 64) {
- clockSelectBits = 6;
- pwmPeriod = cycles >> 6;
- } else
- if (cycles < TIMER1_RESOLUTION * 128) {
- clockSelectBits = 7;
- pwmPeriod = cycles >> 7;
- } else {
- clockSelectBits = 7;
- pwmPeriod = TIMER1_RESOLUTION - 1;
- }
-
- uint32_t sc = FTM1_SC;
- FTM1_SC = 0;
- FTM1_MOD = pwmPeriod;
- FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE);
- }
-
- //****************************
- // Run Control
- //****************************
- void start() __attribute__((always_inline)) {
- stop();
- FTM1_CNT = 0;
- resume();
- }
- void stop() __attribute__((always_inline)) {
- FTM1_SC = FTM1_SC & (FTM_SC_TOIE | FTM_SC_CPWMS | FTM_SC_PS(7));
- }
- void restart() __attribute__((always_inline)) {
- start();
- }
- void resume() __attribute__((always_inline)) {
- FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
- }
-
- //****************************
- // PWM outputs
- //****************************
- void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) {
- unsigned long dutyCycle = pwmPeriod;
- dutyCycle *= duty;
- dutyCycle >>= 10;
- if (pin == TIMER1_A_PIN) {
- FTM1_C0V = dutyCycle;
- } else if (pin == TIMER1_B_PIN) {
- FTM1_C1V = dutyCycle;
- }
- }
- void pwm(char pin, unsigned int duty) __attribute__((always_inline)) {
- setPwmDuty(pin, duty);
- if (pin == TIMER1_A_PIN) {
- *portConfigRegister(TIMER1_A_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
- } else if (pin == TIMER1_B_PIN) {
- *portConfigRegister(TIMER1_B_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
- }
- }
- void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) {
- if (microseconds > 0) setPeriod(microseconds);
- pwm(pin, duty);
- }
- void disablePwm(char pin) __attribute__((always_inline)) {
- if (pin == TIMER1_A_PIN) {
- *portConfigRegister(TIMER1_A_PIN) = 0;
- } else if (pin == TIMER1_B_PIN) {
- *portConfigRegister(TIMER1_B_PIN) = 0;
- }
- }
-
- //****************************
- // Interrupt Function
- //****************************
- void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
- isrCallback = isr;
- FTM1_SC |= FTM_SC_TOIE;
- NVIC_ENABLE_IRQ(IRQ_FTM1);
- }
- void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
- if(microseconds > 0) setPeriod(microseconds);
- attachInterrupt(isr);
- }
- void detachInterrupt() __attribute__((always_inline)) {
- FTM1_SC &= ~FTM_SC_TOIE;
- NVIC_DISABLE_IRQ(IRQ_FTM1);
- }
- static void (*isrCallback)();
- static void isrDefaultUnused();
-
- private:
- // properties
- static unsigned short pwmPeriod;
- static unsigned char clockSelectBits;
-
- #undef F_TIMER
-
- #elif defined(__arm__) && defined(TEENSYDUINO) && defined(__IMXRT1062__)
-
- public:
- //****************************
- // Configuration
- //****************************
- void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
- setPeriod(microseconds);
- }
- void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
- uint32_t period = (float)F_BUS_ACTUAL * (float)microseconds * 0.0000005f;
- uint32_t prescale = 0;
- while (period > 32767) {
- period = period >> 1;
- if (++prescale > 7) {
- prescale = 7; // when F_BUS is 150 MHz, longest
- period = 32767; // period is 55922 us (~17.9 Hz)
- break;
- }
- }
- //Serial.printf("setPeriod, period=%u, prescale=%u\n", period, prescale);
- FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(8); // logic high = fault
- FLEXPWM1_FSTS0 = 0x0008; // clear fault status
- FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
- FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP;
- FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale);
- FLEXPWM1_SM3INIT = -period;
- FLEXPWM1_SM3VAL0 = 0;
- FLEXPWM1_SM3VAL1 = period;
- FLEXPWM1_SM3VAL2 = 0;
- FLEXPWM1_SM3VAL3 = 0;
- FLEXPWM1_SM3VAL4 = 0;
- FLEXPWM1_SM3VAL5 = 0;
- FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8) | FLEXPWM_MCTRL_RUN(8);
- pwmPeriod = period;
- }
- //****************************
- // Run Control
- //****************************
- void start() __attribute__((always_inline)) {
- stop();
- // TODO: how to force counter back to zero?
- resume();
- }
- void stop() __attribute__((always_inline)) {
- FLEXPWM1_MCTRL &= ~FLEXPWM_MCTRL_RUN(8);
- }
- void restart() __attribute__((always_inline)) {
- start();
- }
- void resume() __attribute__((always_inline)) {
- FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_RUN(8);
- }
-
- //****************************
- // PWM outputs
- //****************************
- void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) {
- if (duty > 1023) duty = 1023;
- int dutyCycle = (pwmPeriod * duty) >> 10;
- //Serial.printf("setPwmDuty, period=%u\n", dutyCycle);
- if (pin == TIMER1_A_PIN) {
- FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
- FLEXPWM1_SM3VAL5 = dutyCycle;
- FLEXPWM1_SM3VAL4 = -dutyCycle;
- FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8);
- } else if (pin == TIMER1_B_PIN) {
- FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
- FLEXPWM1_SM3VAL3 = dutyCycle;
- FLEXPWM1_SM3VAL2 = -dutyCycle;
- FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8);
- }
- }
- void pwm(char pin, unsigned int duty) __attribute__((always_inline)) {
- setPwmDuty(pin, duty);
- if (pin == TIMER1_A_PIN) {
- FLEXPWM1_OUTEN |= FLEXPWM_OUTEN_PWMB_EN(8);
- IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01 = 6; // pin 7 FLEXPWM1_PWM3_B
- } else if (pin == TIMER1_B_PIN) {
- FLEXPWM1_OUTEN |= FLEXPWM_OUTEN_PWMA_EN(8);
- IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 6; // pin 8 FLEXPWM1_PWM3_A
- }
- }
- void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) {
- if (microseconds > 0) setPeriod(microseconds);
- pwm(pin, duty);
- }
- void disablePwm(char pin) __attribute__((always_inline)) {
- if (pin == TIMER1_A_PIN) {
- IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01 = 5; // pin 7 FLEXPWM1_PWM3_B
- FLEXPWM1_OUTEN &= ~FLEXPWM_OUTEN_PWMB_EN(8);
- } else if (pin == TIMER1_B_PIN) {
- IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 5; // pin 8 FLEXPWM1_PWM3_A
- FLEXPWM1_OUTEN &= ~FLEXPWM_OUTEN_PWMA_EN(8);
- }
- }
- //****************************
- // Interrupt Function
- //****************************
- void attachInterrupt(void (*f)()) __attribute__((always_inline)) {
- isrCallback = f;
- attachInterruptVector(IRQ_FLEXPWM1_3, &isr);
- FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF;
- FLEXPWM1_SM3INTEN = FLEXPWM_SMINTEN_RIE;
- NVIC_ENABLE_IRQ(IRQ_FLEXPWM1_3);
- }
- void attachInterrupt(void (*f)(), unsigned long microseconds) __attribute__((always_inline)) {
- if(microseconds > 0) setPeriod(microseconds);
- attachInterrupt(f);
- }
- void detachInterrupt() __attribute__((always_inline)) {
- NVIC_DISABLE_IRQ(IRQ_FLEXPWM1_3);
- FLEXPWM1_SM3INTEN = 0;
- }
- static void isr(void);
- static void (*isrCallback)();
- static void isrDefaultUnused();
-
- private:
- // properties
- static unsigned short pwmPeriod;
- static unsigned char clockSelectBits;
-
- #endif
- };
-
- extern TimerOne Timer1;
-
- #endif
-
|