Esempio n. 1
0
static void pwm_bcm2836_config(struct pwm_t * pwm, int duty, int period, int polarity)
{
	struct pwm_bcm2836_pdata_t * pdat = (struct pwm_bcm2836_pdata_t *)pwm->priv;
	unsigned long scaler = (unsigned long)(1000000000ULL / clk_get_rate(pdat->clk));
	u32_t ctrl;

	if(pwm->__duty != duty)
	{
		write32(pdat->virt + PWM_DUTY(pdat->channel), duty / scaler);
	}

	if(pwm->__period != period)
	{
		write32(pdat->virt + PWM_PERIOD(pdat->channel), period /scaler);
	}

	if(pwm->__polarity != polarity)
	{
		ctrl = read32(pdat->virt + PWM_CTRL);
		if(polarity)
			ctrl |= (0x10 << PWM_CTRL_SHIFT(pdat->channel));
		else
			ctrl &= ~(0x10 << PWM_CTRL_SHIFT(pdat->channel));
		write32(pdat->virt + PWM_CTRL, ctrl);
	}
}
static int lpc32xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
			      int duty_ns, int period_ns)
{
	struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip);
	unsigned long long c;
	int period_cycles, duty_cycles;
	u32 val;

	c = clk_get_rate(lpc32xx->clk) / 256;
	c = c * period_ns;
	do_div(c, NSEC_PER_SEC);

	/* Handle high and low extremes */
	if (c == 0)
		c = 1;
	if (c > 255)
		c = 0; /* 0 set division by 256 */
	period_cycles = c;

	/* The duty-cycle value is as follows:
	 *
	 *  DUTY-CYCLE     HIGH LEVEL
	 *      1            99.9%
	 *      25           90.0%
	 *      128          50.0%
	 *      220          10.0%
	 *      255           0.1%
	 *      0             0.0%
	 *
	 * In other words, the register value is duty-cycle % 256 with
	 * duty-cycle in the range 1-256.
	 */
	c = 256 * duty_ns;
	do_div(c, period_ns);
	if (c > 255)
		c = 255;
	duty_cycles = 256 - c;

	val = readl(lpc32xx->base + (pwm->hwpwm << 2));
	val &= ~0xFFFF;
	val |= PWM_RELOADV(period_cycles) | PWM_DUTY(duty_cycles);
	writel(val, lpc32xx->base + (pwm->hwpwm << 2));

	return 0;
}
Esempio n. 3
0
void analogWrite(uint8_t pin, int val)
{
        pinMode(pin, OUTPUT); // pin as output

 	if (val == 0)
	{
		digitalWrite(pin, LOW); // set pin to LOW when duty cycle is 0
                                        // digitalWrite will take care of invalid pins
	}
	else if (val == 255)
	{
		digitalWrite(pin, HIGH); // set pin HIGH when duty cycle is 255
                                         // digitalWrite will take care of invalid pins
	}
	else
	{

	        uint8_t bit = digitalPinToBitMask(pin); // get pin bit
	        uint8_t port = digitalPinToPort(pin);   // get pin port
	        volatile uint16_t *sel;
	        volatile uint16_t *sel2;
                
                if (port == NOT_A_PORT) return; // pin on timer?
               
	        sel = portSelRegister(port); // get the port function select register address
		*sel |= bit;                 // set bit in pin function select register  
                
                //TODO: Firgure out a better way to determine if SEL2 needs to be set
	        if(bit == BV(4) && port == P1) {
                        sel2 = portSel2Register(port); // get the port function select register address
                        *sel2 |= bit;
                }
                switch(digitalPinToTimer(pin)) {                // which timer and CCR?
 			//case: T0A0                            // CCR0 used as period register
			case T0A1:                              // Timer0 / CCR1
                                TA0CCR0 = PWM_PERIOD;           // PWM Period
                                TA0CCTL1 = OUTMOD_7;            // reset/set
                                TA0CCR1 = PWM_DUTY(val);       // PWM duty cycle
                                TA0CTL = TASSEL_2 + MC_1 + analog_div;       // SMCLK, up mode
                                break;
#if defined(__MSP430_HAS_TA3__) 
 			case T0A2:                              // Timer0 / CCR1
                                TA0CCR0 = PWM_PERIOD;           // PWM Period
                                TA0CCTL2 = OUTMOD_7;            // reset/set
                                TA0CCR2 = PWM_DUTY(val);       // PWM duty cycle
                                TA0CTL = TASSEL_2 + MC_1+ analog_div;       // SMCLK, up mode
                                break;
#endif
#if defined(__MSP430_HAS_T1A3__) 
 			//case: T1A0                            // CCR0 used as period register
			case T1A1:                              // Timer0 / CCR1
                                TA1CCR0 = PWM_PERIOD;           // PWM Period
                                TA1CCTL1 = OUTMOD_7;            // reset/set
                                TA1CCR1 = PWM_DUTY(val);       // PWM duty cycle
                                TA1CTL = TASSEL_2 + MC_1+ analog_div;       // SMCLK, up mode
                                break;
 			case T1A2:                              // Timer0 / CCR1
                                TA1CCR0 = PWM_PERIOD;           // PWM Period
                                TA1CCTL2 = OUTMOD_7;            // reset/set
                                TA1CCR2 = PWM_DUTY(val);       // PWM duty cycle
                                TA1CTL = TASSEL_2 + MC_1+ analog_div;       // SMCLK, up mode
                                break;
#endif
#if defined(__MSP430_HAS_T2A3__)  
 			//case: T2A0                            // CCR0 used as period register
			case T2A1:                              // Timer0 / CCR1
                                TA2CCR0 = PWM_PERIOD;           // PWM Period
                                TA2CCTL1 = OUTMOD_7;            // reset/set
                                TA2CCR1 = PWM_DUTY(val);       // PWM duty cycle
                                TA2CTL = TASSEL_2 + MC_1+ analog_div;       // SMCLK, up mode
                                break;
 			case T2A2:                              // Timer0 / CCR1
                                TA2CCR0 = PWM_PERIOD;           // PWM Period
                                TA2CCTL2 = OUTMOD_7;            // reset/set
                                TA2CCR2 = PWM_DUTY(val);       // PWM duty cycle
                                TA2CTL = TASSEL_2 + MC_1+ analog_div;       // SMCLK, up mode
                                break;
#endif
                        case NOT_ON_TIMER:                      // not on a timer output pin
			default:                                // or TxA0 pin
				if (val < 128) {
					digitalWrite(pin, LOW); // 
				} else {
					digitalWrite(pin, HIGH);
				}
                }
        }
}
Esempio n. 4
0
/**
 * analogWrite
 *
 * set PWM output level
 *
 * @param pin pin number
 * @param val duty cycle
 */
void analogWrite(uint8_t pin, uint16_t val)
{     
  if (val == 0)
  {
    pinMode(pin, OUTPUT);
    digitalWrite(pin, LOW);
  }
  else
  {
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);

    volatile uint8_t *dir = portDirRegister(port);
    volatile uint8_t *sel = portSelRegister(port);
    volatile uint8_t *map = digitalPinToPortMap(pin);
     
    *dir |= bit;                               // Config pin as an output
    *sel |= bit;                               // Select alternate function
    
    // Set PWM period
    TA0CCR0 = analogPeriod;
    TA1CCR0 = analogPeriod;
    
    uint8_t timer = digitalPinToTimer(pin);

    PMAPPWD = 0x02D52;                         // Get write-access to port mapping regs 
    PMAPCTL |= PMAPRECFG;                      // Leave Pin mapping open
        
    switch(timer)
    {
      case T0A1:
        *map = PM_TA0CCR1A;
        TA0CCTL1 = OUTMOD_7;                    // CCR1 reset/set
        TA0CCR1 = PWM_DUTY(val);                // CCR1 PWM duty cycle
        break;
      case T0A2:
        *map = PM_TA0CCR2A;
        TA0CCTL2 = OUTMOD_7;                    // CCR1 reset/set
        TA0CCR2 = PWM_DUTY(val);                // CCR1 PWM duty cycle
        break;
      case T0A3:
        *map = PM_TA0CCR3A;
        TA0CCTL3 = OUTMOD_7;                    // CCR1 reset/set
        TA0CCR3 = PWM_DUTY(val);                // CCR1 PWM duty cycle
        break;
      case T0A4:
        *map = PM_TA0CCR4A;
        TA0CCTL4 = OUTMOD_7;                    // CCR1 reset/set
        TA0CCR4 = PWM_DUTY(val);                // CCR1 PWM duty cycle
        break;
      case T1A1:
        *map = PM_TA1CCR1A;
        TA1CCTL1 = OUTMOD_7;                    // CCR1 reset/set
        TA1CCR1 = PWM_DUTY(val);                // CCR1 PWM duty cycle
        break;
      case T1A2:
        *map = PM_TA1CCR2A;
        TA1CCTL2 = OUTMOD_7;                    // CCR1 reset/set
        TA1CCR2 = PWM_DUTY(val);                // CCR1 PWM duty cycle
        break;
      default:
        break;
    }

    PMAPPWD = 0;                               // Lock port mapping registers 
  
    if (timer < T1A1)
    {
      if (val == TA0CCR0)                     // duty cycle = period?
      {
        pinMode(pin, OUTPUT);
        digitalWrite(pin, HIGH);
      }
      else
        TA0CTL = TASSEL_2 + MC_1 + TACLR;     // SMCLK, up mode, clear TAR
    }
    else
    {
      if (val == TA1CCR0)                     // duty cycle = period?
      {
        pinMode(pin, OUTPUT);
        digitalWrite(pin, HIGH);
      }
      else
        TA1CTL = TASSEL_2 + MC_1 + TACLR;     // SMCLK, up mode, clear TAR
    }
  }
}