void PWMWrite(uint8_t pin, uint32_t analog_res, uint32_t duty, unsigned int freq) { if (duty == 0) { pinMode(pin, OUTPUT); digitalWrite(pin, LOW); } else if (duty >= analog_res) { pinMode(pin, OUTPUT); digitalWrite(pin, HIGH); } else { uint8_t bit = digitalPinToBitMask(pin); // get pin bit uint8_t port = digitalPinToPort(pin); // get pin port uint8_t timer = digitalPinToTimer(pin); uint32_t portBase = (uint32_t) portBASERegister(port); uint32_t offset = timerToOffset(timer); uint32_t timerBase = getTimerBase(offset); uint32_t timerAB = TIMER_A << timerToAB(timer); if (port == NOT_A_PORT) return; // pin on timer? uint32_t periodPWM = ROM_SysCtlClockGet()/freq; enableTimerPeriph(offset); ROM_GPIOPinConfigure(timerToPinConfig(timer)); ROM_GPIOPinTypeTimer((long unsigned int) portBase, bit); // // Configure for half-width mode, allowing timers A and B to // operate independently // HWREG(timerBase + TIMER_O_CFG) = 0x04; if(timerAB == TIMER_A) { HWREG(timerBase + TIMER_O_CTL) &= ~TIMER_CTL_TAEN; HWREG(timerBase + TIMER_O_TAMR) = PWM_MODE; } else { HWREG(timerBase + TIMER_O_CTL) &= ~TIMER_CTL_TBEN; HWREG(timerBase + TIMER_O_TBMR) = PWM_MODE; } ROM_TimerLoadSet(timerBase, timerAB, periodPWM); ROM_TimerMatchSet(timerBase, timerAB, (analog_res-duty)*periodPWM/analog_res); // // If using a 16-bit timer, with a periodPWM > 0xFFFF, // need to use a prescaler // if((offset < WTIMER0) && (periodPWM > 0xFFFF)) { ROM_TimerPrescaleSet(timerBase, timerAB, (periodPWM & 0xFFFF0000) >> 16); ROM_TimerPrescaleMatchSet(timerBase, timerAB, (((analog_res-duty)*periodPWM/analog_res) & 0xFFFF0000) >> 16); } ROM_TimerEnable(timerBase, timerAB); }
/* * noTone() - Stop outputting the tone on a pin */ void noTone(uint8_t _pin) { uint8_t timer = digitalPinToTimer(_pin); if(timer == tone_timer) { uint32_t timerBase = getTimerBase(timerToOffset(timer)); uint32_t timerAB = TIMER_A << timerToAB(timer); ROM_TimerIntDisable(timerBase, TIMER_TIMA_TIMEOUT << timerToAB(tone_timer)); ROM_TimerIntClear(timerBase, TIMER_TIMA_TIMEOUT << timerToAB(tone_timer)); ROM_TimerDisable(timerBase, timerAB); tone_state = 0; g_duration = 0; pinMode(_pin, OUTPUT); digitalWrite(_pin, LOW); } }
void OneMsTaskTimer::start(uint32_t timer_index) { uint32_t load = (F_CPU / 1000); //// !!!! count = 0; overflowing = 0; // Base address for first timer g_ulBase = getTimerBase(timerToOffset(timer_index)); timerAB = TIMER_A << timerToAB(timer_index); //Setup interrupts for duration, interrupting at 1kHz ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0+ timer_index); ROM_IntMasterEnable(); ROM_TimerConfigure(g_ulBase, TIMER_CFG_PERIODIC); ROM_TimerLoadSet(g_ulBase, TIMER_A, F_CPU/1000); // Setup the interrupts for the timer timeouts. TimerIntRegister(g_ulBase, TIMER_A, OneMsTaskTimer_int); ROM_IntEnable(INT_TIMER0A+timer_index); ROM_TimerIntEnable(g_ulBase, TIMER_TIMA_TIMEOUT); ROM_TimerEnable(g_ulBase, TIMER_A); }
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) { uint8_t port = digitalPinToPort(_pin); if (port == NOT_A_PORT) return; if (tone_state == 0 || _pin == current_pin) { //Setup PWM current_pin = _pin; tone_timer = digitalPinToTimer(_pin); uint32_t timerBase = getTimerBase(timerToOffset(tone_timer)); tone_state = 1; g_duration = duration; PWMWrite(_pin, 256, 128, frequency); //Setup interrupts for duration, interrupting at 1kHz ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER4); ROM_IntMasterEnable(); ROM_TimerConfigure(TIMER4_BASE, TIMER_CFG_PERIODIC); ROM_TimerLoadSet(TIMER4_BASE, TIMER_A, ROM_SysCtlClockGet()/1000); ROM_IntEnable(INT_TIMER4A); ROM_TimerIntEnable(TIMER4_BASE, TIMER_TIMA_TIMEOUT); ROM_TimerEnable(TIMER4_BASE, TIMER_A); } }
/* * Motor constructor - frequency, PWM pin and Dir pin. * Sets which wires should control the motor. */ Motor::Motor(int pwm_frequency, int motor_pwm_pin, int motor_dir_pin) { this->frequency = pwm_frequency; // the PWM frequency this->direction = 0; // motor direction this->duty = 1; // pwm duty mimimun is 1. Strop the motor this->analog_res = 256; // One byte resolution : 0 - 255 // Tiva Launchpad pins for the motor control connection: this->motor_pwm_pin = motor_pwm_pin; this->motor_dir_pin = motor_dir_pin; //-------------- setup the pins on the microcontroller: ------------ pinMode(this->motor_dir_pin, OUTPUT); uint8_t bit = digitalPinToBitMask(this->motor_dir_pin); // get pin bit uint8_t port = digitalPinToPort(this->motor_dir_pin); // get pin port this->motor_dir_port = (uint32_t) portBASERegister(port); this->motor_dir_pin = bit; //---------------------------------------------------------- bit = digitalPinToBitMask(this->motor_pwm_pin); // get pin bit port = digitalPinToPort(this->motor_pwm_pin); // get pin port uint8_t timer = digitalPinToTimer(this->motor_pwm_pin); uint32_t portBase = (uint32_t) portBASERegister(port); uint32_t offset = timerToOffset(timer); this->timerBase = getTimerBase(offset); this->timerAB = TIMER_A << timerToAB(timer); if (port == NOT_A_PORT) return; // pin on timer? #ifdef __TM4C1294NCPDT__ this->periodPWM = F_CPU/this->frequency; #else this->periodPWM = SysCtlClockGet() / this->frequency; #endif if (offset > TIMER3) { ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER0 + offset - 4); } else { ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0 + offset); } ROM_GPIOPinConfigure(timerToPinConfig(timer)); ROM_GPIOPinTypeTimer((long unsigned int) portBase, bit); // // Configure for half-width mode, allowing timers A and B to // operate independently // HWREG(this->timerBase + TIMER_O_CFG) = 0x04; if (this->timerAB == TIMER_A) { HWREG(this->timerBase + TIMER_O_CTL) &= ~TIMER_CTL_TAEN; HWREG(this->timerBase + TIMER_O_TAMR) = PWM_MODE; } else { HWREG(this->timerBase + TIMER_O_CTL) &= ~TIMER_CTL_TBEN; HWREG(this->timerBase + TIMER_O_TBMR) = PWM_MODE; } ROM_TimerLoadSet(this->timerBase, this->timerAB, this->periodPWM); ROM_TimerMatchSet(this->timerBase, this->timerAB,(this->analog_res - this->duty) * this->periodPWM / this->analog_res); ROM_TimerEnable(this->timerBase, this->timerAB); this->initialized = true; }