int __digitalRead(uint8_t pin)
{
	uint8_t timer = digitalPinToTimer(pin);
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);

	if (port == NOT_A_PIN) return LOW;

	// If the pin that support PWM output, we need to turn it off
	// before getting a digital reading.
	//if (timer != NOT_ON_TIMER) turnOffPWM(timer);

	if (*portInputRegister(port) & bit) return HIGH;
	return LOW;
}
// Right now, PWM output only works on the pins with
// hardware support.  These are defined in the appropriate
// pins_*.c file.  For the rest of the pins, we default
// to digital output.
void analogWrite(uint8_t pin, int val)
{
	// We need to make sure the PWM output is enabled for those pins
	// that support it, as we turn it off when digitally reading or
	// writing with them.  Also, make sure the pin is in output mode
	// for consistenty with Wiring, which doesn't require a pinMode
	// call for the analog output pins.
	pinMode(pin, OUTPUT);
	
	if (digitalPinToTimer(pin) == TIMER1A) {
		// connect pwm to pin on timer 1, channel A
		sbi(TCCR1A, COM1A1);
		// set pwm duty
		OCR1A = val;
	} else if (digitalPinToTimer(pin) == TIMER1B) {
		// connect pwm to pin on timer 1, channel B
		sbi(TCCR1A, COM1B1);
		// set pwm duty
		OCR1B = val;
	} else if (digitalPinToTimer(pin) == TIMER1C) {
		// connect pwm to pin on timer 1, channel B
		sbi(TCCR1A, COM1C1);
		// set pwm duty
		OCR1C = val;
	} else if (digitalPinToTimer(pin) == TIMER2A) {
		// connect pwm to pin on timer 2, channel A
		sbi(TCCR2A, COM2A1);
		// set pwm duty
		OCR2A = val;	
	} else if (digitalPinToTimer(pin) == TIMER3A) {
		// connect pwm to pin on timer 3, channel A
		sbi(TCCR3A, COM3A1);
		// set pwm duty
		OCR3A = val;
	} else if (digitalPinToTimer(pin) == TIMER3B) {
		// connect pwm to pin on timer 3, channel B
		sbi(TCCR3A, COM3B1);
		// set pwm duty
		OCR3B = val;
	} else if (digitalPinToTimer(pin) == TIMER3C) {
		// connect pwm to pin on timer 3, channel C
		sbi(TCCR3A, COM3C1);
		// set pwm duty
		OCR3C = val;
	} else if (val < 128)
		digitalWrite(pin, LOW);
	else
		digitalWrite(pin, HIGH);
}
Beispiel #3
0
bool SetPinFrequencySafe(int8_t pin, uint32_t frequency)
{
	uint8_t timer = digitalPinToTimer(pin);
	
	if(timer == TIMER1A || timer == TIMER1B)
	return Timer1_SetFrequency(frequency);
	else if(timer == TIMER2B)
	return Timer2_SetFrequency(frequency);
	else if(timer == TIMER3A || timer == TIMER3B || timer == TIMER3C)
	return Timer3_SetFrequency(frequency);
	else if(timer == TIMER4A || timer == TIMER4B || timer == TIMER4C)
	return Timer4_SetFrequency(frequency);
	else if(timer == TIMER5A || timer == TIMER5B || timer == TIMER5C)
	return Timer5_SetFrequency(frequency);
	else
	return false;
}
Beispiel #4
0
void digitalWrite(uint8_t pin, uint8_t val)
{
	uint8_t timer = digitalPinToTimer(pin);
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	volatile uint8_t *out;

	if (port == NOT_A_PIN) return;

	// If the pin that support PWM output, we need to turn it off
	// before doing a digital write.
	if (timer != NOT_ON_TIMER) turnOffPWM(timer);

	out = portOutputRegister(port);

	if (val == LOW) *out &= ~bit;
	else *out |= bit;
}
void DirectAnalogOutput::setPin(uint8_t pin) 
{
	uint8_t port = digitalPinToPort(pin);

	if (port == NOT_A_PIN) return;

	volatile uint8_t *modeRegister = portModeRegister(port);

	_outputRegister = portOutputRegister(port);
	_bitMask = digitalPinToBitMask(pin);

	uint8_t oldSREG = SREG;
	cli();
	*modeRegister |= _bitMask;
	SREG = oldSREG;

	_timer = digitalPinToTimer(pin);
}
Beispiel #6
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;
	}
}
Beispiel #7
0
void   digitalWrite(uint8_t pin, uint8_t value)
{
	uint8_t timer = digitalPinToTimer(pin);
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	t_SetPortCfg cfg;

	if (timer != NOT_ON_TIMER) turnOffPWM(timer);
	
	if(port == NOT_A_PORT)
	{
		return;
	}
	
	cfg.pID = (uint16_t)portModeRegister(port);
	
	setPinValue(value,cfg.pID,bit);
}
Beispiel #8
0
int digitalRead(uint8_t pin)
{
	if( (pin >= 0) && (pin <= 7) ) //port A outputs!
		return -1; //do nothing!
		
	uint8_t timer = digitalPinToTimer(pin);
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);

	if (port == NOT_A_PIN) return LOW;

	// If the pin that support PWM output, we need to turn it off
	// before getting a digital reading.
	if (timer != NOT_ON_TIMER) turnOffPWM(timer);

	if (*portInputRegister(port) & bit) return HIGH;
	return LOW;
}
Beispiel #9
0
/*
 * 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 DirectOutputPin::setPin(uint8_t pin) 
{
	uint8_t port = digitalPinToPort(pin);

	if (port == NOT_A_PIN) return;

	volatile uint8_t *modeRegister = portModeRegister(port);

	_outputRegister = portOutputRegister(port);
	_bitMask = digitalPinToBitMask(pin);

	uint8_t oldSREG = SREG;
	cli();
	*modeRegister |= _bitMask;
	SREG = oldSREG;

	uint8_t timer = digitalPinToTimer(pin);
	if (timer != NOT_ON_TIMER) turnOffPWM(timer);
}
Beispiel #11
0
uint8_t  digitalRead(uint8_t pin)
{
	uint8_t timer = digitalPinToTimer(pin);
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	t_SetPortCfg cfg;
	
	if (timer != NOT_ON_TIMER) turnOffPWM(timer);

	if(port == NOT_A_PIN)
	{
		return 0;
	}
	
	cfg.pID = (uint16_t)portModeRegister(port);
	
	return getPinValue(cfg.pID,bit);
	
}
Beispiel #12
0
void analogWrite(uint8_t pin, int val) {
	/* duty cycle(%) = val / 255;
	 * Frequency of 490Hz specified by Arduino API */
	uint8_t timer = digitalPinToTimer(pin);

	if(timer == NOT_ON_TIMER)
		return;

	if (val == 0) {
		pinMode(pin, OUTPUT);
		digitalWrite(pin, LOW);
		return;
	}

	if (val >= 255) {
		pinMode(pin, OUTPUT);
		digitalWrite(pin, HIGH);
		return;
	}

	PWMWrite(pin, 255, val, 490);
}
Beispiel #13
0
float GetPinResolution(uint8_t pin)
{
	uint8_t timer = digitalPinToTimer(pin);	
	uint16_t top;
	
	switch(timer)
	{
		case TIMER0B:
			top = Timer0_GetTop();
			break;
		case TIMER1A:
			top = Timer1_GetTop();
			break;
		case TIMER1B:
			top = Timer1_GetTop();
			break;
		case TIMER2B:
			top = Timer2_GetTop();
		default:
			return 0;
	}
	
	return toBaseTwo(top);
}
Beispiel #14
0
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);
    }
}
Beispiel #15
0
void analogWrite(uint8_t pin, int16_t val)
{
	uint8_t timer = 0xff;
	setPinMode(pin, OUTPUT);
	
	if ((val == 0) || (val <0))
	{
		digitalWrite(pin, LOW);

	}
	else if ((val > 255) || (val == 255))
	{
		digitalWrite(pin, HIGH);

	}
	else
	{
		timer = digitalPinToTimer(pin);
		initPwm(timer);
		setPwmDutyCycle((uint8_t)val, timer);

	}
	
}
Beispiel #16
0
// Right now, PWM output only works on the pins with
// hardware support.  These are defined in the appropriate
// pins_*.c file.  For the rest of the pins, we default
// to digital output.
void analogWrite(uint8_t pin, int val)
{
  // We need to make sure the PWM output is enabled for those pins
  // that support it, as we turn it off when digitally reading or
  // writing with them.  Also, make sure the pin is in output mode
  // for consistenty with Wiring, which doesn't require a pinMode
  // call for the analog output pins.
  pinMode(pin, OUTPUT);

  if (val <= 0)
  {
    digitalWrite(pin, LOW);
  }
  else if (val >= 255)
  {
    digitalWrite(pin, HIGH);
  }
  else
  {
    uint8_t timer = digitalPinToTimer(pin);
	#if defined(TCCR0A) && defined(COM0A1)
	if( timer == TIMER0A){
		// connect pwm to pin on timer 0, channel A
		sbi(TCCR0A, COM0A1);
		cbi(TCCR0A, COM0A0);
		OCR0A = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR0A) && defined(COM0B1)
	if( timer == TIMER0B){
		// connect pwm to pin on timer 0, channel B
		sbi(TCCR0A, COM0B1);
		cbi(TCCR0A, COM0B0);
		OCR0B = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR1A) && defined(COM1A1) && !defined(TCCR1E)
	if( timer == TIMER1A){
		// connect pwm to pin on timer 1, channel A
		sbi(TCCR1A, COM1A1);
		cbi(TCCR1A, COM1A0);
	#ifdef OC1AX 
		cbi(TCCR1D, OC1AV);
		cbi(TCCR1D, OC1AU);
		cbi(TCCR1D, OC1AW);
		sbi(TCCR1D, OC1AX);
	#endif
		OCR1A = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR1E)
	if( timer == TIMER1A){
		// connect pwm to pin on timer 1, channel A
		cbi(TCCR1C,COM1A1S);
		sbi(TCCR1C,COM1A0S);
		OCR1A = val; // set pwm duty
	} else if (timer == TIMER1B){
		// connect pwm to pin on timer 1, channel A
		cbi(TCCR1C,COM1B1S);
		sbi(TCCR1C,COM1B0S);
		OCR1B = val; // set pwm duty
	} else if (timer == TIMER1D){
		// connect pwm to pin on timer 1, channel A
		cbi(TCCR1C,COM1D1);
		sbi(TCCR1C,COM1D0);
		OCR1D = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR1) && defined(COM1A1)
	if(timer == TIMER1A){
		// connect pwm to pin on timer 1, channel A
		sbi(TCCR1, COM1A1);
		cbi(TCCR1, COM1A0);
		OCR1A = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR1A) && defined(COM1B1) && !defined(TCCR1E)
	if( timer == TIMER1B){
		// connect pwm to pin on timer 1, channel B
		sbi(TCCR1A, COM1B1);
		cbi(TCCR1A, COM1B0);
	#ifdef OC1BV
		sbi(TCCR1D, OC1BV);
		cbi(TCCR1D, OC1BU);
		cbi(TCCR1D, OC1BW);
		cbi(TCCR1D, OC1BX);
	#endif
		OCR1B = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR1) && defined(COM1B1)
	if( timer == TIMER1B){
		// connect pwm to pin on timer 1, channel B
		sbi(GTCCR, COM1B1);
		cbi(GTCCR, COM1B0);
		OCR1B = val; // set pwm duty
	} else
	#endif
	
    {
      if (val < 128)
      {
        digitalWrite(pin, LOW);
      }
      else
      {
        digitalWrite(pin, HIGH);
      }
    }

  }
}
Beispiel #17
0
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);
        uint32_t periodPWM;

        if (port == NOT_A_PORT) return; 	// pin on timer?

        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);

    }
Beispiel #18
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);
				}
                }
        }
}
Beispiel #19
0
uint8_t WatchPin::pinPWM(uint8_t _pin){				//if  pin is pwm return its value, if not return 0
  switch(digitalPinToTimer(_pin))
  {
    #if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__)
	  case TIMER0A:
      return OCR0;
      break;
    #endif

    #if defined(TCCR0A) && defined(COM0A1)
      case TIMER0A:
      return OCR0A;
      break;
    #endif

    #if defined(TCCR0A) && defined(COM0B1)
      case TIMER0B:
      return OCR0B;
      break;
    #endif

    #if defined(TCCR1A) && defined(COM1A1)
      case TIMER1A:
      return OCR1A;
      break;
    #endif

    #if defined(TCCR1A) && defined(COM1B1)
      case TIMER1B:
      return OCR1B;
      break;
    #endif

    #if defined(TCCR2) && defined(COM21)
      case TIMER2:
      return OCR2;
      break;
    #endif

    #if defined(TCCR2A) && defined(COM2A1)
      case TIMER2A:
      return OCR2A;
      break;
    #endif

    #if defined(TCCR2A) && defined(COM2B1)
      case TIMER2B:
      return OCR2B;
      break;
    #endif

    #if defined(TCCR3A) && defined(COM3A1)
      case TIMER3A:
      return OCR3A;
      break;
    #endif

    #if defined(TCCR3A) && defined(COM3B1)
      case TIMER3B:
      return OCR3B;
      break;
    #endif

    #if defined(TCCR3A) && defined(COM3C1)
      case TIMER3C:
      return OCR3C;
      break;
    #endif
    
    #if defined(TCCR4A)
      case TIMER4A:
      return OCR4A;
      break;
    #endif

    #if defined(TCCR4A) && defined(COM4B1)
      case TIMER4B:
      return OCR4B;
      break;
    #endif

    #if defined(TCCR4A) && defined(COM4C1)
      case TIMER4C:
      return OCR4C;
      break;
    #endif

    #if defined(TCCR4C) && defined(COM4D1)
      case TIMER4D:				
      return OCR4D;
      break;
    #endif

    #if defined(TCCR5A) && defined(COM5A1)
      case TIMER5A:
      return OCR5A;
      break;
    #endif

    #if defined(TCCR5A) && defined(COM5B1)
      case TIMER5B:
      return OCR5B;
      break;
    #endif
    
    #if defined(TCCR5A) && defined(COM5C1)
      case TIMER5C:
      return OCR5C;
      break;
    #endif

    case NOT_ON_TIMER:
    default:
    return NOT_ON_TIMER;
    break;
  }
}
Beispiel #20
0
boolean WatchPin::pinIsPWM(uint8_t _pin){
  return (digitalPinToTimer(_pin)==0) ? false:true;		//return TRUE if pin requested is PWM, FALSE if not
}
// Right now, PWM output only works on the pins with
// hardware support.  These are defined in the appropriate
// pins_*.c file.  For the rest of the pins, we default
// to digital output.
void analogWrite(uint8_t pin, int val)
{
	// We need to make sure the PWM output is enabled for those pins
	// that support it, as we turn it off when digitally reading or
	// writing with them.  Also, make sure the pin is in output mode
	// for consistenty with Wiring, which doesn't require a pinMode
	// call for the analog output pins.
	pinMode(pin, OUTPUT);
	
	if (digitalPinToTimer(pin) == TIMER1A) {
		// connect pwm to pin on timer 1, channel A
		sbi(TCCR1A, COM1A1);
		// set pwm duty
		OCR1A = val;
	} else if (digitalPinToTimer(pin) == TIMER1B) {
		// connect pwm to pin on timer 1, channel B
		sbi(TCCR1A, COM1B1);
		// set pwm duty
		OCR1B = val;
/* ATMega48/32/324P/644 mod provided by AndreS at robotcraft.ca - START */
#if defined(__AVR_ATmega48__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644__)
	} else if (digitalPinToTimer(pin) == TIMER0A) {
		// connect pwm to pin on timer 0, channel A
		sbi(TCCR0A, COM0A1);
		// set pwm duty
		OCR0A = val;	
	} else if (digitalPinToTimer(pin) == TIMER0B) {
		// connect pwm to pin on timer 0, channel B
		sbi(TCCR0A, COM0B1);
		// set pwm duty
		OCR0B = val;
	} else if (digitalPinToTimer(pin) == TIMER2A) {
		// connect pwm to pin on timer 2, channel A
		sbi(TCCR2A, COM2A1);
		// set pwm duty
		OCR2A = val;	
	} else if (digitalPinToTimer(pin) == TIMER2B) {
		// connect pwm to pin on timer 2, channel B
		sbi(TCCR2A, COM2B1);
		// set pwm duty
		OCR2B = val;
#elif defined(__AVR_ATmega32__)
	} else if (digitalPinToTimer(pin) == TIMER0) {
		// connect pwm to pin on timer 0
		sbi(TCCR0, COM01);
		// set pwm duty
		OCR0 = val;
	} else if (digitalPinToTimer(pin) == TIMER2) {
		// connect pwm to pin on timer 2
		sbi(TCCR2, COM21);
		// set pwm duty
		OCR2 = val;
/* ATMega48/32/324P/644 mod provided by AndreS at robotcraft.ca - END */
#else
	} else if (digitalPinToTimer(pin) == TIMER2) {
		// connect pwm to pin on timer 2, channel B
		sbi(TCCR2, COM21);
		// set pwm duty
		OCR2 = val;
#endif
	} else if (val < 128)
		digitalWrite(pin, LOW);
	else
		digitalWrite(pin, HIGH);
}
Beispiel #22
0
void AdaEncoder::addEncoder(char _id, uint8_t _pinA, uint8_t _pinB)
{
	AdaEncoder *tmpencoder;

	id=_id;
	pinA=_pinA;
	pinB=_pinB;
#ifdef DEBUG
	printBuffer.putString(getPSTR("addEncoder: "));
	printBuffer.put(id);
	printBuffer.put('\n');
	printBuffer.putHex(pinA); printBuffer.put(' ');
	printBuffer.putHex(pinB); printBuffer.put(' ');
	printBuffer.putString(getPSTR(" *\n"));
#endif

	// error checking
	if (pinA == pinB) return;  // No! silly
	if (pinA < 8 && pinB > 7) return; // No! different ports
	if ((pinA > 7 && pinA < 14) && (pinB < 8 || pinB > 13)) return; // No! different ports
	if (pinA > 13 && pinB < 14) return; // No! different ports
	if (pinA > 19 || pinB > 19) return; // No! out of band

	turning=0;
	clicks=0;

	/* ADD TO THE LIST HERE */
	if (firstEncoder==NULL) { firstEncoder=this; }
	else {
		tmpencoder=firstEncoder;
		while (tmpencoder->next != NULL) tmpencoder=tmpencoder->next;
		tmpencoder->next=this;
	}
	this->next=NULL;


	port=portInputRegister(digitalPinToPort(pinA));
	if (port == NOT_A_PIN) { return; }

	// ** A **
    bitA=digitalPinToBitMask(pinA);
	uint8_t timerA=digitalPinToTimer(pinA);
    if (timerA != NOT_ON_TIMER) turnOffPWM(timerA);
#ifdef DEBUG
	//char buffer[16];
	//Serial.print("encoder addr: ");
	//sprintf(buffer, "%p", this);
	//Serial.println(buffer);
	printBuffer.putString("bitA: ");
	printBuffer.putHex(bitA);
#endif

	// ** B **
    bitB=digitalPinToBitMask(pinB);
	uint8_t timerB=digitalPinToTimer(pinB);
    if (timerB != NOT_ON_TIMER) turnOffPWM(timerB);
#ifdef DEBUG
	printBuffer.putString("bitB: ");
	printBuffer.putHex(bitB);
#endif

	// ** INTERRUPT **
#ifndef SWINTR_DEBUG
	// This section should be on normally.  OFF if performing software interrupts!
       	// GreyGnome DEBUG:  Turn these two lines off by defining
	// SWINTR_DEBUG.  In the sketch, turn the pins into Outputs and set them high.
	// Then set them as you wish, to create software interrupts.
	pinMode(pinA, INPUT); pinMode(pinB, INPUT);
	digitalWrite(pinA, HIGH); digitalWrite(pinB, HIGH);
#endif
	attachInterrupt(pinA, pinB);

#ifdef DEBUGTIME
	ada_output_port=portOutputRegister(digitalPinToPort(13)); // GreyGnome DEBUG.
	ada_output_mask=digitalPinToBitMask(13);    // defines the actual pin on that port
	ada_not_output_mask=ada_output_mask^0xFF;
#endif
}
Beispiel #23
0
void _analogWrite(uint8_t pin, uint8_t val)
{
  // We need to make sure the PWM output is enabled for those pins
  // that support it, as we turn it off when digitally reading or
  // writing with them.  Also, make sure the pin is in output mode
  // for consistenty with Wiring, which doesn't require a pinMode
  // call for the analog output pins.
  // This is now done from static inline void analogWrite() 
  // which is defined in Arduino.h, this allows us to use the
  // optimized pinMode() for constant pins.
  // pinMode(pin, OUTPUT);

#if ! (defined(ANALOG_WRITE_FLIPPED) && ANALOG_WRITE_FLIPPED)
  if (val <= 0)
  {
    digitalWrite(pin, LOW);
  }
  else if (val >= 255)
  {
    digitalWrite(pin, HIGH);
  }
  else
#else
  // If we flip (invert) the PWM, so that 255 is Off and 0 is On,
  // then we can do away with the special cases of val == 0
  // and val == 255 which in the normal directionality have to 
  // turn off the PWM and use digitalWrite.
  // 
  // We don't get fully "on" (max is about 99.5%), but that's less 
  // of a problem than not getting fully "off" especially when using
  // an LED which is probably the most common use case here.
  //
  // This saves us a bunch of space for something like the usual
  // led fader since digitalWrite() can be totally optimized out.
  //
  // Of course, we don't want the user to know to do this, so 
  // we take 0 = Off and 255 = On and flip that before passing
  // it to the AVR which is expecting the flipped value.
    
  val = 255-val;
#endif
  {
    
#ifdef turnOnPWM
    // Some variants (see tiny13) define a turnOnPWM macro which reduces code size
    turnOnPWM( digitalPinToTimer(pin), val );
#else   

    // All this defined() logic is silly trying to overly generalise wiring_analog.h
    // to cater for different variants; instead see variants/tiny13/pins_arduino.c for a 
    // better way of doing this for variants in future - in other words, you should ask
    // the variant to turn on pwm for itself, not try and figure out how to turn on pwm
    // for any given variant by looking at what is and isn't defined.  Crazyness.
    // 
    // In short, you should #define turnOnPWM(t, v) ( _turnOnPWM(t,v) )
    // in pins_arduino.h, and create pins_arduino.c to define the _turnOnPWM() function
    // (where t is the timer (eg TIMER0A) and v is the value 0-255)
		//
    // Do similar for turnOffPWM(t) by the way!

    uint8_t timer = digitalPinToTimer(pin);
	#if defined(TCCR0A) && defined(COM0A1)
	if( timer == TIMER0A){
		// connect pwm to pin on timer 0, channel A
		sbi(TCCR0A, COM0A1);
		cbi(TCCR0A, COM0A0);
		OCR0A = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR0A) && defined(COM0B1)
	if( timer == TIMER0B){
		// connect pwm to pin on timer 0, channel B
		sbi(TCCR0A, COM0B1);
		cbi(TCCR0A, COM0B0);
		OCR0B = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR1A) && defined(COM1A1) && !defined(TCCR1E)
	if( timer == TIMER1A){
		// connect pwm to pin on timer 1, channel A
		sbi(TCCR1A, COM1A1);
		cbi(TCCR1A, COM1A0);
	#ifdef OC1AX 
		cbi(TCCR1D, OC1AV);
		cbi(TCCR1D, OC1AU);
		cbi(TCCR1D, OC1AW);
		sbi(TCCR1D, OC1AX);
	#endif
		OCR1A = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR1E)
	if( timer == TIMER1A){
		// connect pwm to pin on timer 1, channel A
		cbi(TCCR1C,COM1A1S);
		sbi(TCCR1C,COM1A0S);
		OCR1A = val; // set pwm duty
	} else if (timer == TIMER1B){
		// connect pwm to pin on timer 1, channel A
		cbi(TCCR1C,COM1B1S);
		sbi(TCCR1C,COM1B0S);
		OCR1B = val; // set pwm duty
	} else if (timer == TIMER1D){
		// connect pwm to pin on timer 1, channel A
		cbi(TCCR1C,COM1D1);
		sbi(TCCR1C,COM1D0);
		OCR1D = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR1) && defined(COM1A1)
	if(timer == TIMER1A){
		// connect pwm to pin on timer 1, channel A
		sbi(TCCR1, COM1A1);
		cbi(TCCR1, COM1A0);
		OCR1A = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR1A) && defined(COM1B1) && !defined(TCCR1E)
	if( timer == TIMER1B){
		// connect pwm to pin on timer 1, channel B
		sbi(TCCR1A, COM1B1);
		cbi(TCCR1A, COM1B0);
	#ifdef OC1BV
		sbi(TCCR1D, OC1BV);
		cbi(TCCR1D, OC1BU);
		cbi(TCCR1D, OC1BW);
		cbi(TCCR1D, OC1BX);
	#endif
		OCR1B = val; // set pwm duty
	} else
	#endif

	#if defined(TCCR1) && defined(COM1B1)
	if( timer == TIMER1B){
		// connect pwm to pin on timer 1, channel B
		sbi(GTCCR, COM1B1);
		cbi(GTCCR, COM1B0);
		OCR1B = val; // set pwm duty
	} else
	#endif
	
    {
      if (val < 128)
      {
        digitalWrite(pin, LOW);
      }
      else
      {
        digitalWrite(pin, HIGH);
      }
    }
#endif
  }
}
Beispiel #24
0
void AdaEncoder::addEncoder(char id, uint8_t pinA, uint8_t pinB)
{
#ifdef DEBUG
	Serial.print("DEBUG addEncoder: ");
	Serial.print(pinA, HEX); Serial.print(' ');
	Serial.print(pinB, HEX); Serial.print(' ');
	Serial.println(" *");
#endif

	// error checking
	if (pinA == pinB) return;  // No! silly
	if (pinA < 8 && pinB > 7) return; // No! different ports
	if ((pinA > 7 && pinA < 14) && (pinB < 8 || pinB > 13)) return; // No! different ports
	if (pinA > 13 && pinB < 14) return; // No! different ports
	if (pinA > 19 || pinB > 19) return; // No! out of band

	encoder *newencoder=(encoder*) malloc(sizeof(struct encoder));
	newencoder->turning=0;
	newencoder->clicks=0;
	newencoder->id=id;

	newencoder->next=NULL;

	newencoder->port=portInputRegister(digitalPinToPort(pinA));
	if (newencoder->port == NOT_A_PIN) { free(newencoder); return; }

	// ** A **
    newencoder->bitA=digitalPinToBitMask(pinA);
	uint8_t timerA=digitalPinToTimer(pinA);
    if (timerA != NOT_ON_TIMER) turnOffPWM(timerA);
#ifdef DEBUG
	char buffer[16];
	Serial.print("encoder addr: ");
	sprintf(buffer, "%p", newencoder);
	Serial.println(buffer);
	Serial.print("bitA: ");
	Serial.print(newencoder->bitA, BIN);
#endif

	// ** B **
    newencoder->bitB=digitalPinToBitMask(pinB);
	uint8_t timerB=digitalPinToTimer(pinB);
    if (timerB != NOT_ON_TIMER) turnOffPWM(timerB);
#ifdef DEBUG
	Serial.print("bitB: ");
	Serial.println(newencoder->bitB, BIN);
#endif

	// ** INTERRUPT **
#ifndef SWINTR_DEBUG
	// This section should be on normally.  OFF if performing software interrupts!
       	// GreyGnome DEBUG:  Turn these two lines off by defining
	// SWINTR_DEBUG.  In the sketch, turn the pins into Outputs and set them high.
	// Then set them as you wish, to create software interrupts.
	pinMode(pinA, INPUT); pinMode(pinB, INPUT);
	digitalWrite(pinA, HIGH); digitalWrite(pinB, HIGH);
#endif
	AdaEncoders[pinA]=newencoder;
	AdaEncoders[pinB]=newencoder;
	AdaEncoder::attachInterrupt(pinA, pinB);

	// encoder linked list: add to it.  Use this in loop() to search for the encoder that triggered the interrupt.
	if (firstEncoder==NULL) { firstEncoder=newencoder; }
	else {
		tmpencoder=firstEncoder;
		while (tmpencoder->next != NULL) {
			tmpencoder=tmpencoder->next;
		}
		tmpencoder->next=newencoder;
	}

#ifdef DEBUGTIME
	ada_output_port=portOutputRegister(digitalPinToPort(13)); // GreyGnome DEBUG.
	ada_output_mask=digitalPinToBitMask(13);    // defines the actual pin on that port
	ada_not_output_mask=ada_output_mask^0xFF;
#endif
}
Beispiel #25
0
//http://www.arduino.cc/en/Reference/AnalogWrite
int isValidPWM(int pin){
  //return true if is on a timer
  return (digitalPinToTimer(pin) != NOT_ON_TIMER);
}
// Right now, PWM output only works on the pins with
// hardware support.  These are defined in the appropriate
// pins_*.c file.  For the rest of the pins, we default
// to digital output.
void analogWrite(uint8_t pin, int val)
{
	// We need to make sure the PWM output is enabled for those pins
	// that support it, as we turn it off when digitally reading or
	// writing with them.  Also, make sure the pin is in output mode
	// for consistenty with Wiring, which doesn't require a pinMode
	// call for the analog output pins.
	pinMode(pin, OUTPUT);
	if (val == 0)
	{
		digitalWrite(pin, LOW);
	}
	else if (val == 255)
	{
		digitalWrite(pin, HIGH);
	}
	else
	{
		switch(digitalPinToTimer(pin))
		{
			// XXX fix needed for atmega8
			#if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__)
			case TIMER0A:
				// connect pwm to pin on timer 0
				sbi(TCCR0, COM00);
				OCR0 = val; // set pwm duty
				break;
			#endif

			#if defined(TCCR0A) && defined(COM0A1)
			case TIMER0A:
				// connect pwm to pin on timer 0, channel A
				sbi(TCCR0A, COM0A1);
				OCR0A = val; // set pwm duty
				break;
			#endif

			#if defined(TCCR0A) && defined(COM0B1)
			case TIMER0B:
				// connect pwm to pin on timer 0, channel B
				sbi(TCCR0A, COM0B1);
				OCR0B = val; // set pwm duty
				break;
			#endif

            /*
			case TIMER1B:
				// connect pwm to pin on timer 1, channel B
				sbi(GTCCR, COM1B1);
				sbi(GTCCR, PWM1B);
				OCR1B = val; // set pwm duty
				break;
            */
            #if defined(TCCR1A) && defined(COM1A1)
            case TIMER1A:
                // connect pwm to pin on timer 1, channel A
                sbi(TCCR1A, COM1A1);
                OCR1A = val; // set pwm duty
                break;
            #endif

            #if defined(TCCR1A) && defined(COM1B1)
            case TIMER1B:
                // connect pwm to pin on timer 1, channel B
                sbi(TCCR1A, COM1B1);
                OCR1B = val; // set pwm duty
                break;
            #endif

			case NOT_ON_TIMER:
			default:
				if (val < 128) {
					digitalWrite(pin, LOW);
				} else {
					digitalWrite(pin, HIGH);
				}
		}
	}
}
/**
 * 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
    }
  }
}
Beispiel #28
0
//*********************************************************************
//*	PWM output only works on the pins with hardware support. 
//*	These are defined in the appropriate pins_*.c file.
//*	For the rest of the pins, we default to digital output.
//*********************************************************************
void analogWrite(uint8_t pin, int val)
{

	// We need to make sure the PWM output is enabled for those pins
	// that support it, as we turn it off when digitally reading or
	// writing with them.  Also, make sure the pin is in output mode
	// for consistenty with Wiring, which doesn't require a pinMode
	// call for the analog output pins.
	pinMode(pin, OUTPUT);
	if (val == 0)
	{
		digitalWrite(pin, LOW);
	}
	else if (val == 255)
	{
		digitalWrite(pin, HIGH);
	}
	else
	{
		switch(digitalPinToTimer(pin))
		{
		#ifdef _OCMP1
			case TIMER_OC1:
				//* Open Timer2 with Period register value
				OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
				OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, (PWM_TIMER_PERIOD*val)/256, (PWM_TIMER_PERIOD*val)/256  );
				//Set duty cycle on fly
				SetDCOC1PWM((PWM_TIMER_PERIOD*val)/256);
				break;
		#endif

		#ifdef _OCMP2
			case TIMER_OC2:
				//* Open Timer2 with Period register value
				OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
				OpenOC2( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, (PWM_TIMER_PERIOD*val)/256, (PWM_TIMER_PERIOD*val)/256  );
				//Set duty cycle on fly
				SetDCOC2PWM((PWM_TIMER_PERIOD*val)/256);
				break;
		#endif

		#ifdef _OCMP3
			case TIMER_OC3:
				//* Open Timer2 with Period register value
				OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
				OpenOC3( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, (PWM_TIMER_PERIOD*val)/256, (PWM_TIMER_PERIOD*val)/256  );
				//Set duty cycle on fly
				SetDCOC3PWM((PWM_TIMER_PERIOD*val)/256);
				break;
		#endif

		#ifdef _OCMP4
			case TIMER_OC4:
				//* Open Timer2 with Period register value
				OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
				OpenOC4( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, (PWM_TIMER_PERIOD*val)/256, (PWM_TIMER_PERIOD*val)/256  );
				//Set duty cycle on fly
				SetDCOC4PWM((PWM_TIMER_PERIOD*val)/256);
				break;
		#endif

		#ifdef _OCMP5
			case TIMER_OC5:
				//* Open Timer2 with Period register value
				OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
				OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, (PWM_TIMER_PERIOD*val)/256, (PWM_TIMER_PERIOD*val)/256  );
				//Set duty cycle on fly
				SetDCOC5PWM((PWM_TIMER_PERIOD*val)/256);
				break;
		#endif

#if 0
//*	this is the original code, I want to keep it around for refernce for a bit longer
		#ifdef _OCMP1
			case TIMER_OC1:
				//* Open Timer2 with Period register value
				OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
				OpenOC1( OC_ON | OC_TIMER_MODE32 | OC_TIMER2_SRC | OC_CONTINUE_PULSE | OC_LOW_HIGH, 256, (256 - val) );

//			    SetDCOC1PWM((PWM_TIMER_PERIOD * val) / 256);
				break;
		#endif

		#ifdef _OCMP2
			case TIMER_OC2:
				//* Open Timer2 with Period register value
				OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
				OpenOC2( OC_ON | OC_TIMER_MODE32 | OC_TIMER2_SRC | OC_CONTINUE_PULSE | OC_LOW_HIGH, 256, (256 - val) );

//			    SetDCOC2PWM((PWM_TIMER_PERIOD * val) / 256);
				break;
		#endif

		#ifdef _OCMP3
			case TIMER_OC3:
				//* Open Timer2 with Period register value
				OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
				OpenOC3( OC_ON | OC_TIMER_MODE32 | OC_TIMER2_SRC | OC_CONTINUE_PULSE | OC_LOW_HIGH, 256, (256 - val) );

//			    SetDCOC3PWM((PWM_TIMER_PERIOD * val) / 256);
				break;
		#endif

		#ifdef _OCMP4
			case TIMER_OC4:
				//* Open Timer2 with Period register value
				OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
				OpenOC4( OC_ON | OC_TIMER_MODE32 | OC_TIMER2_SRC | OC_CONTINUE_PULSE | OC_LOW_HIGH, 256, (256 - val) );

//			    SetDCOC4PWM((PWM_TIMER_PERIOD * val) / 256);
				break;
		#endif

		#ifdef _OCMP5
			case TIMER_OC5:
				//* Open Timer2 with Period register value
				OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
				OpenOC5( OC_ON | OC_TIMER_MODE32 | OC_TIMER2_SRC | OC_CONTINUE_PULSE | OC_LOW_HIGH, 256, (256 - val) );

//			    SetDCOC5PWM((PWM_TIMER_PERIOD * val) / 256);
				break;
		#endif
#endif

			case NOT_ON_TIMER:
			default:
				if (val < 128)
				{
					digitalWrite(pin, LOW);
				}
				else
				{
					digitalWrite(pin, HIGH);
				}
		}
	}
}
Beispiel #29
0
void PWMWrite(uint8_t pin, uint32_t analog_res, uint32_t duty, uint32_t freq)
{
	analog_res = analog_res * 1000;
	freq;

	uint32_t load = (F_CPU / freq) * 1000;
	uint32_t match = load / (analog_res / duty);

	match = match;
	load = load / 1000;

	uint16_t prescaler = load >> 16;
	uint16_t prescaler_match = match >> 16;

	uint8_t timer = digitalPinToTimer(pin);

	if(timer == NOT_ON_TIMER)
		return;

	MAP_PRCMPeripheralClkEnable(PRCM_TIMERA0 + (timer/2), PRCM_RUN_MODE_CLK);

	uint16_t pnum = digitalPinToPinNum(pin);

	switch(timer) {
	/* PWM0/1 */
	case TIMERA0A:
	case TIMERA0B:
		MAP_PinTypeTimer(pnum, PIN_MODE_5);
		break;
	/* PWM2/3 */
	case TIMERA1A:
	case TIMERA1B:
		MAP_PinTypeTimer(pnum, PIN_MODE_9);
		break;
	/* PWM4/5 */
	case TIMERA2A:
	case TIMERA2B:
		MAP_PinTypeTimer(pnum, PIN_MODE_3);
		break;
	/* PWM6/7 */
	case TIMERA3A:
	case TIMERA3B:
		MAP_PinTypeTimer(pnum, PIN_MODE_3);
		break;
	}

	uint32_t base = TIMERA0_BASE + ((timer/2) << 12);

	/* FIXME: If B is already opperational and configure A, B get's messed up. */
	MAP_TimerConfigure(base, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PWM);

	uint16_t timerab = timer % 2 ? TIMER_B : TIMER_A;
	MAP_TimerPrescaleSet(base, timerab, prescaler);
	MAP_TimerPrescaleMatchSet(base, timerab, prescaler_match);

	MAP_TimerControlLevel(base, timerab, 1);

	MAP_TimerLoadSet(base, timerab, load);

	MAP_TimerMatchSet(base, timerab, match);

	MAP_TimerEnable(base, timerab);
}
Beispiel #30
0
void tone( uint8_t _pin, unsigned int frequency, unsigned long duration )
{
  if ( tone_pin == 255 )
  {
    /* Set the timer to power-up conditions so we start from a known state */
    // Ensure the timer is in the same state as power-up
    #if (TIMER_TO_USE_FOR_TONE == 0)
    TCCR0B = (0<<FOC0A) | (0<<FOC0B) | (0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00);
    TCCR0A = (0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
    // Reset the count to zero
    TCNT0 = 0;
    // Set the output compare registers to zero
    OCR0A = 0;
    OCR0B = 0;
    #if defined(TIMSK)
    // Disable all Timer0 interrupts
    TIMSK &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
    // Clear the Timer0 interrupt flags
    TIFR |= ((1<<OCF0B) | (1<<OCF0A) | (1<<TOV0));
    #elif defined(TIMSK1)
    // Disable all Timer0 interrupts
    TIMSK0 &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
    // Clear the Timer0 interrupt flags
    TIFR0 |= ((1<<OCF0B) | (1<<OCF0A) | (1<<TOV0));
    #endif
      
      
    #elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1)
    // Turn off Clear on Compare Match, turn off PWM A, disconnect the timer from the output pin, stop the clock
    TCCR1 = (0<<CTC1) | (0<<PWM1A) | (0<<COM1A1) | (0<<COM1A0) | (0<<CS13) | (0<<CS12) | (0<<CS11) | (0<<CS10);
    // Turn off PWM A, disconnect the timer from the output pin, no Force Output Compare Match, no Prescaler Reset
    GTCCR &= ~((1<<PWM1B) | (1<<COM1B1) | (1<<COM1B0) | (1<<FOC1B) | (1<<FOC1A) | (1<<PSR1));
    // Reset the count to zero
    TCNT1 = 0;
    // Set the output compare registers to zero
    OCR1A = 0;
    OCR1B = 0;
    OCR1C = 0;
    // Disable all Timer1 interrupts
    TIMSK &= ~((1<<OCIE1A) | (1<<OCIE1B) | (1<<TOIE1));
    // Clear the Timer1 interrupt flags
    TIFR |= ((1<<OCF1A) | (1<<OCF1B) | (1<<TOV1));
      
      
    #elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
    TCCR1A = 0;
    TCCR1B = 0;
    TCCR1C = 0;
    TCCR1D = 0;
    TCCR1E = 0;
    // Reset the count to zero
    TCNT1 = 0;
    // Set the output compare registers to zero
    OCR1A = 0;
    OCR1B = 0;
    // Disable all Timer1 interrupts
    TIMSK &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<OCIE1D));
    // Clear the Timer1 interrupt flags
    TIFR |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<OCF1D));
  
  
    #elif (TIMER_TO_USE_FOR_TONE == 1)
    // Turn off Input Capture Noise Canceler, Input Capture Edge Select on Falling, stop the clock
    TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
    // Disconnect the timer from the output pins, Set Waveform Generation Mode to Normal
    TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
    // Reset the count to zero
    TCNT1 = 0;
    // Set the output compare registers to zero
    OCR1A = 0;
    OCR1B = 0;
    // Disable all Timer1 interrupts
    #if defined(TIMSK)
    TIMSK &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<ICIE1));
    // Clear the Timer1 interrupt flags
    TIFR |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<ICF1));
    #elif defined(TIMSK1)
    // Disable all Timer1 interrupts
    TIMSK1 &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<ICIE1));
    // Clear the Timer1 interrupt flags
    TIFR1 |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<ICF1));
    #endif
      
    #endif

    /* 
      Compare Output Mode = Normal port operation, OCxA/OCxB disconnected.
      Waveform Generation Mode = 4; 0100; CTC; (Clear Timer on Compare); OCR1A; Immediate; MAX
      Clock Select = No clock source (Timer/Counter stopped).
      Note: Turn off the clock first to avoid ticks and scratches.
    */	
    #if TIMER_TO_USE_FOR_TONE == 1
	#if defined(TCCR1)
	sbi(TCCR1,CTC1);
    cbi(TCCR1,PWM1A);
    cbi(GTCCR,PWM1B);
	#elif !defined(TCCR1E)
	cbi(TCCR1A,WGM10);
	cbi(TCCR1A,WGM11);
	sbi(TCCR1B,WGM12);
	cbi(TCCR1B,WGM13);
	#endif
    #elif TIMER_TO_USE_FOR_TONE == 0
	cbi(TCCR0A,WGM00);
	sbi(TCCR0A,WGM01);
	cbi(TCCR0B,WGM02);
    #endif

    /* If the tone pin can be driven directly from the timer */

    #if (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
    if ( (digitalPinToTimer(_pin) == TIMER1A) || (digitalPinToTimer(_pin) == TIMER1B)  || (digitalPinToTimer(_pin) == TIMER1D) )
    {
    #elif (TIMER_TO_USE_FOR_TONE == 1)
    if ( (digitalPinToTimer(_pin) == TIMER1A) || (digitalPinToTimer(_pin) == TIMER1B) )
    {
    #elif (TIMER_TO_USE_FOR_TONE == 0)
    if ( (digitalPinToTimer(_pin) == TIMER0A) || (digitalPinToTimer(_pin) == TIMER0B) )
    {
    #else
	if (0)
	{ //unsupported, so only use software.
	#endif
      /* Pin toggling is handled by the hardware */
      tone_timer_pin_register = NULL;
      tone_timer_pin_mask = 0;
      uint8_t timer = digitalPinToTimer(_pin);
	  #if defined(COM0A1)
	  //Just in case there are now pwm pins on timer0 (ATTiny861)
      if (timer == TIMER0A)
      {
        /* Compare Output Mode = Toggle OC0A on Compare Match. */
		cbi(TCCR0A,COM0A1);
		sbi(TCCR0A,COM0A0);
      }
      else
	  #endif
	  if (timer == TIMER1A)
      {
        /* Compare Output Mode = Toggle OC1A on Compare Match. */
		#if defined(TCCR1)
		cbi(TCCR1,COM1A1);
		sbi(TCCR1,COM1A0);
		#elif defined(TCCR1E)
		cbi(TCCR1C,COM1A1S);
		sbi(TCCR1C,COM1A0S);
		#else
		cbi(TCCR1A,COM1A1);
		sbi(TCCR1A,COM1A0);
		#endif
      }
	  #if defined(COM0B1)
	  //Just in case there are <2 pwm pins on timer0 (ATTiny861)
      else if (timer == TIMER0B)
      {
        /* Compare Output Mode = Toggle OC0B on Compare Match. */
		cbi(TCCR0A,COM0B1);
		sbi(TCCR0A,COM0B0);
      }
	  #endif
	  #if defined(COM1D1)
	  //in case there is a OCRD. (ATtiny861)
	  else if (timer == TIMER1D){
        /* Compare Output Mode = Toggle OC1D on Compare Match. */
		#if defined(TCCR1)
		cbi(TCCR1,COM1D1);
		sbi(TCCR1,COM1D0);
		#elif defined(TCCR1E)
		cbi(TCCR1C,COM1D1);
		sbi(TCCR1C,COM1D0);
		#else
		cbi(TCCR1A,COM1D1);
		sbi(TCCR1A,COM1D0);
		#endif
	  }
	  #endif
      else
      {
        /* Compare Output Mode = Toggle OC1B on Compare Match. */
		#if defined(TCCR1)
		cbi(GTCCR,COM1B1);
		sbi(GTCCR,COM1B0);
		#elif defined(TCCR1E)
		cbi(TCCR1C,COM1B1S);
		sbi(TCCR1C,COM1B0S);
		#else
		cbi(TCCR1A,COM1B1);
		sbi(TCCR1A,COM1B0);
		#endif
      }
    }
    else
    {
      /* Save information needed by the interrupt service routine */
      tone_timer_pin_register = portOutputRegister( digitalPinToPort( _pin ) );
      tone_timer_pin_mask = digitalPinToBitMask( _pin );

      /* Compare Output Mode = Normal port operation, OCxA disconnected. */
    #if (TIMER_TO_USE_FOR_TONE == 0)
      TCCR0A &= ~((1<<COM0A1)|(1<<COM0A0)|(1<<COM0B1)|(1<<COM0B0));
    #elif (TIMER_TO_USE_FOR_TONE == 1) & defined(TCCR1)
      TCCR1 &= ~((1<<COM1A1)|(1<<COM1A0));
      GTCCR &= ~((1<<COM1B1)|(1<<COM1B0));
    #elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
      TCCR1C &= ~((1<<COM1A1S)|(1<<COM1A0S)|(1<<COM1B1S)|(1<<COM1B0S)|(1<<COM1D1)|(1<<COM1D0));
	#elif (TIMER_TO_USE_FOR_TONE == 1)
      TCCR1A &= ~((1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0));
	#endif
    }

    /* Ensure the pin is configured for output */
    pinMode( _pin, OUTPUT );

    tone_pin = _pin;
  }

  if ( tone_pin == _pin )
  {
    /* Stop the clock while we make changes, then set the counter to zero to reduce ticks and scratches. */

    // Millis timer is always processor clock divided by MillisTimer_Prescale_Value (64)
    #if (TIMER_TO_USE_FOR_TONE == 0)
    TCCR0B &= ~((1<<CS02)|(1<<CS01)|(1<<CS00));
    TCNT0 = 0;
    #elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1)
    TCCR1 &= ~((1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10));
    TCNT1 = 0;
    #elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
    TCCR1B &= ~((1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10));
    TCNT1 = 0;
    #elif (TIMER_TO_USE_FOR_TONE == 1)
    TCCR1B &= ~((1<<CS12)|(1<<CS11)|(1<<CS10));
    TCNT1 = 0;
    #endif

    if ( frequency > 0 )
    {
      /* Determine which prescaler to use */
      /* Set the Output Compare Register (rounding up) */
      
      #if TIMER_TO_USE_FOR_TONE == 1
	  uint16_t ocr = F_CPU / frequency / 2;
	  #if defined(TCCR1E)
      uint8_t prescalarbits = 0b0001;
      if (ocr > 256)
      {
        ocr >>= 3; //divide by 8
        prescalarbits = 0b0100;  // ck/8
        if (ocr > 256)
        {
          ocr >>= 3; //divide by a further 8
          prescalarbits = 0b0111; //ck/64
          if (ocr > 256)
          {
            ocr >>= 2; //divide by a further 4
            prescalarbits = 0b1001; //ck/256
            if (ocr > 256)
            {
              // can't do any better than /1024
              ocr >>= 2; //divide by a further 4
              prescalarbits = 0b1011; //ck/1024
            }
          }
        }