Example #1
0
//takes a 16 bit value instead of an 8 bit value for maximum resolution
void pwmWriteHR(uint8_t pin, uint16_t val)
{
	pinMode(pin, OUTPUT);
	
	uint32_t tmp = val;	
	
	if (val == 0)
	digitalWrite(pin, LOW);
	else if (val == 65535)
	digitalWrite(pin, HIGH);
	else
	{
		TimerData td = timer_to_pwm_data[digitalPinToTimer(pin)];
		if(td.ChannelRegLoc) //null checking
		{
			if(td.Is16Bit)
			{
				sbi(_SFR_MEM8(td.PinConnectRegLoc), td.PinConnectBits);
				_SFR_MEM16(td.ChannelRegLoc) = (tmp * _SFR_MEM16(td.TimerTopRegLoc)) / 65535;
			}
			else
			{
				sbi(_SFR_MEM8(td.PinConnectRegLoc), td.PinConnectBits);
				_SFR_MEM8(td.ChannelRegLoc) = (tmp * _SFR_MEM8(td.TimerTopRegLoc)) / 65535;
			}
		}
	}
}
Example #2
0
static int pwm_set_duty_1_3(struct pwm *pwm, uint32_t val)
{
	if (val > 0)
		val--;
	_SFR_MEM16(pwm->duty_reg_l) = val;
	return 0;
}
Example #3
0
void pwmWrite(uint8_t pin, uint8_t val)
{
	pinMode(pin, OUTPUT);
	
	//casting "val" to be larger so that the final value (which is the partially
	//the result of multiplying two potentially high value int16s) will not truncate
	uint32_t tmp = val;
	
	if (val == 0)
		digitalWrite(pin, LOW);
	else if (val == 255)
		digitalWrite(pin, HIGH);
	else
	{
		uint16_t regLoc16 = 0;
		uint16_t regLoc8 = 0;
		
		uint16_t top;
		
		switch(digitalPinToTimer(pin))
		{
			case TIMER0B:
			sbi(TCCR0A, COM0B1);
			regLoc8 = OCR0B_MEM;
			top = Timer0_GetTop();
			break;
			case TIMER1A:
			sbi(TCCR1A, COM1A1);
			regLoc16 = OCR1A_MEM;
			top = Timer1_GetTop();
			break;
			case TIMER1B:
			sbi(TCCR1A, COM1B1);
			regLoc16 = OCR1B_MEM;
			top = Timer1_GetTop();
			break;
			case TIMER2B:
			sbi(TCCR2A, COM2B1);
			regLoc8 = OCR2B_MEM;
			top = Timer2_GetTop();
			break;
			case NOT_ON_TIMER:
			default:
			if (val < 128)
			digitalWrite(pin, LOW);
			else
			digitalWrite(pin, HIGH);
			return;
		}
		
		if(regLoc16)
			_SFR_MEM16(regLoc16) = (tmp*top)/255;
		else
			_SFR_MEM8(regLoc8) = (tmp*top)/255;
		
	}		
}
Example #4
0
File: pwm.c Project: bechu/hexapod
// Set up PWM on the given pin
boolean pwmInitDeciHertz(const IOPin* pin, uint32_t deciHertz, PERCENTAGE duty, uint32_t* actualDeciHertz){
	boolean rtn = FALSE;
	const TimerCompare* channel = compareFromIOPin(pin);

	if(channel==null){
		setError(PWM_PIN_NOT_AVAILABLE);
	}else{
		// The pin is valid
		// The pin is valid and available
		TIMER_MODE mode;
		uint16_t icr;
		uint16_t prescaler;
		uint32_t actual;

		const Timer* timer = compareGetTimer(channel);

		// Find the best PWM setting
		boolean valid = timerCalcPwm(timer, deciHertz, 100, &mode, &icr, &prescaler, &actual);

		if(!valid){
			// There is no PWM setting that is valid
			setError( (timerIsInUse(timer)) ? PWM_TIMER_IN_USE : TIMER_HAS_NO_PWM );
		}else{
			// Lets set up the PWM
			timerSetMode(timer,mode);
			if(modeIsICR(mode)){
				// Set the ICR
				PORT icrPort = pgm_read_word(&timer->pgm_icr);
				_SFR_MEM16(icrPort)=icr;
			}

			// Mark the channel as in use
//			compareAttach(channel,&nullTimerCompareCallback,0,null);

			// Turn the pin into an output, low
			pin_make_output(pin, FALSE);

			// Turn on the PWM pin output
			compareSetOutputMode(channel, CHANNEL_MODE_NON_INVERTING);

			// Turn on the timer
			timerSetPrescaler(timer,prescaler);

			// Set the initial duty cycle
			pwmSetDutyCycle(pin,duty);

			// Set the return value
			if(actualDeciHertz){
				*actualDeciHertz = actual;
			}

			rtn = TRUE;
		}
	}
	return rtn;
}
Example #5
0
//takes a 16 bit value instead of an 8 bit value for maximum resolution
void pwmWriteHR(uint8_t pin, uint16_t val)
{
	pinMode(pin, OUTPUT);
	
	uint32_t tmp = val;
	
	if (val == 0)
	digitalWrite(pin, LOW);
	else if (val == 65535)
	digitalWrite(pin, HIGH);
	else
	{
		uint16_t regLoc16 = 0;
		uint16_t regLoc8 = 0;
		
		uint16_t top;
		switch(digitalPinToTimer(pin))
		{
			case TIMER0B:
			sbi(TCCR0A, COM0B1);
			regLoc8 = OCR0B_MEM;
			top = Timer0_GetTop();
			break;
			case TIMER1A:
			sbi(TCCR1A, COM1A1);
			regLoc16 = OCR1A_MEM;
			top = Timer1_GetTop();
			break;
			case TIMER1B:
			sbi(TCCR1A, COM1B1);
			regLoc16 = OCR1B_MEM;
			top = Timer1_GetTop();
			break;
			case TIMER2B:
			sbi(TCCR2A, COM2B1);
			regLoc8 = OCR2B_MEM;
			top = Timer2_GetTop();
			break;
			case NOT_ON_TIMER:
			default:
			if (val < 128)
			digitalWrite(pin, LOW);
			else
			digitalWrite(pin, HIGH);
			return;
		}			
		
		if(regLoc16)
			_SFR_MEM16(regLoc16) = (tmp*top)/65535;
		else
			_SFR_MEM8(regLoc8) = (tmp*top)/65535;
	}
}
Example #6
0
/**
 * We have just hit top and are starting to count down again.
 * The new PWM duty cycle has been clocked in for the next servo
 */
static void service(const Timer *timer, void* data){
	SERVO_DRIVER* driver = data;
	uint8_t i;

	// Move to the next servo
	uint8_t index = (driver->specific.softwareMUX.currentServo + 1)& 7;
	driver->specific.softwareMUX.currentServo = index;

	// Set the multiplex pins so the pulse goes to the correct servo
	// This needs to be done quickly to stop the start of the pulse
	// going to the wrong sevo
	uint8_t bits = index;
	for (i = 0; i < NUM_MUX_PINS; i++){
		const IOPin* pin = driver->specific.softwareMUX.muxPins[i];
		if(bits & 1){
			pin_high(pin);
		}else{
			pin_low(pin);
		}
		bits >>= 1;
	}

	// Keep track of the lowest value of the timer counter
	// Setting a delay between this value and TOP will mean the mux bits dont get changed in time
	uint16_t thisDelay = timerGetCounter(timer);
	if(thisDelay < maxDelay){
		maxDelay = thisDelay;
	}

	// Time critical part is over
	// Now calculate the pulse width for next servo
	uint16_t newPos=0;
	index = (index + 1) & 7;
	if(index < driver->num_servos){
		SERVO* servo = (SERVO *)pgm_read_word(&driver->servos[index]);
		if(servo->actuator.connected){
			newPos = servo->delay;

			// Limit to the maximum value
			uint16_t limit = maxDelay;
			if(newPos > limit){
				newPos = limit;
			}

		}
	}

	// Set the threshold inline - to save more registers push/pops
	//compareSetThreshold(channel,newPos);
	PORT port = driver->specific.softwareMUX.pwmPort;
	_SFR_MEM16(port) = newPos; 					// set 16 bit word
}
Example #7
0
static boolean initPWM(const IOPin* pin, uint32_t deciHertz){
	const TimerCompare* channel = compareFromIOPin(pin);

	if(channel==null){
		setError(PWM_PIN_NOT_AVAILABLE);
		return FALSE;
	}
	if(compareIsInUse(channel)){
		setError(PWM_PIN_IN_USE);
		return FALSE;
	}

	TIMER_MODE mode;
	uint16_t icr;
	uint16_t prescaler;

	const Timer* timer = compareGetTimer(channel);

	// Find the best PWM setting for 10kHz, with 128 steps
	boolean valid = timerCalcPwm(timer, deciHertz, 128, &mode, &icr, &prescaler);

	if(!valid){
		// There is no PWM setting that is valid
		setError( (timerIsInUse(timer)) ? PWM_TIMER_IN_USE : TIMER_HAS_NO_PWM );
	}else{
		// Lets set up the PWM
		if(!timerIsInUse(timer)){
			timerSetMode(timer,mode);
			if(modeIsICR(mode)){
				// Set the ICR
				PORT icrPort = pgm_read_word(&timer->pgm_icr);
				_SFR_MEM16(icrPort)=icr;
			}
		}

		// Make it an output pin and set high for brake
		pin_make_output(pin,TRUE);

		// Use inverting PWM
		compareSetOutputMode(channel,CHANNEL_MODE_INVERTING);

		// Mark the channels as in use
		compareAttach(channel,&nullTimerCompareCallback,0,null);

		// Do this last as it then turns on the timer
		timerSetPrescaler(timer,prescaler);
	}
	return valid;
}
Example #8
0
float GetPinResolution(uint8_t pin)
{
	TimerData td = timer_to_pwm_data[digitalPinToTimer(pin)];
	double baseTenRes = 0;
	
	if(td.ChannelRegLoc)
	{
		//getting a base 10 resolution
		td.Is16Bit? (baseTenRes = _SFR_MEM16(td.TimerTopRegLoc)) : (baseTenRes = _SFR_MEM8(td.TimerTopRegLoc));
		 
		//change the base and return	
		return toBaseTwo(baseTenRes);
	}
	else
	{
		return 0;
	}
}
Example #9
0
static uint32_t pwm_get_duty_1_3(struct pwm *pwm)
{
	uint32_t ret = _SFR_MEM16(pwm->duty_reg_l);
	return ret + 1;
}