uint32_t analogRead(uint32_t pin)
{

    uint32_t val = 0;

    /* allow for channel or pin numbers */
    if (pin < 6) pin += A0;

    PinDescription *p = &g_APinDescription[pin];

    /* Disable pull-up and set pin mux for ADC output */
    SET_PIN_MODE(p->ulSocPin, ADC_MUX_MODE);
    SET_PIN_PULLUP(p->ulSocPin,0);

    /* Reset sequence pointer */
    SET_ARC_MASK(ADC_CTRL, ADC_SEQ_PTR_RST);
    /* Update sequence table */
    WRITE_ARC_REG(p->ulAdcChan, ADC_SEQ);
    /* Reset sequence pointer & start sequencer */
    SET_ARC_MASK(ADC_CTRL, ADC_SEQ_PTR_RST | ADC_SEQ_START | ADC_ENABLE);
    /* Poll for ADC data ready status (DATA_A) */
    while((READ_ARC_REG(ADC_INTSTAT) & ADC_INT_DATA_A) == 0);
    /* Pop the data sample from FIFO to sample register */
    SET_ARC_MASK(ADC_SET, ADC_POP_SAMPLE);
    /* Read sample from sample register */
    val = READ_ARC_REG( ADC_SAMPLE);
    /* Clear the DATA_A status bit */
    SET_ARC_MASK( ADC_CTRL, ADC_CLR_DATA_A);

    return mapResolution(val, ADC_RESOLUTION, _readResolution);

}
Beispiel #2
0
static void update_PWM_value(uint32_t ulPin, uint32_t ulValue, uint32_t PWM_channel)
{
  PWM_Channels_Value[PWM_channel] = (2^PWM_RESOLUTION - 1) - mapResolution(ulValue, _writeResolution, PWM_RESOLUTION);
  if ((NRF_GPIOTE->CONFIG[PWM_channel] & GPIOTE_CONFIG_MODE_Msk) == (GPIOTE_CONFIG_MODE_Disabled << GPIOTE_CONFIG_MODE_Pos))
  {
    PWM_Channels_Start[PWM_channel] = 1;
  }
}
uint32_t analogRead(uint32_t pin)
{
  uint32_t valueRead = 0;

  if (pin < A0) {
    pin += A0;
  }

  pinPeripheral(pin, PIO_ANALOG);

  // Disable DAC, if analogWrite() was used previously to enable the DAC
  if ((g_APinDescription[pin].ulADCChannelNumber == ADC_Channel0) || (g_APinDescription[pin].ulADCChannelNumber == DAC_Channel0)) {
    syncDAC();
    DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC
    //DAC->CTRLB.bit.EOEN = 0x00; // The DAC output is turned off.
    syncDAC();
  }

  syncADC();
  ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[pin].ulADCChannelNumber; // Selection for the positive ADC input

  // Control A
  /*
   * Bit 1 ENABLE: Enable
   *   0: The ADC is disabled.
   *   1: The ADC is enabled.
   * Due to synchronization, there is a delay from writing CTRLA.ENABLE until the peripheral is enabled/disabled. The
   * value written to CTRL.ENABLE will read back immediately and the Synchronization Busy bit in the Status register
   * (STATUS.SYNCBUSY) will be set. STATUS.SYNCBUSY will be cleared when the operation is complete.
   *
   * Before enabling the ADC, the asynchronous clock source must be selected and enabled, and the ADC reference must be
   * configured. The first conversion after the reference is changed must not be used.
   */
  syncADC();
  ADC->CTRLA.bit.ENABLE = 0x01;             // Enable ADC

  // Start conversion
  syncADC();
  ADC->SWTRIG.bit.START = 1;

  // Clear the Data Ready flag
  ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY;

  // Start conversion again, since The first conversion after the reference is changed must not be used.
  syncADC();
  ADC->SWTRIG.bit.START = 1;

  // Store the value
  while (ADC->INTFLAG.bit.RESRDY == 0);   // Waiting for conversion to complete
  valueRead = ADC->RESULT.reg;

  syncADC();
  ADC->CTRLA.bit.ENABLE = 0x00;             // Disable ADC
  syncADC();

  return mapResolution(valueRead, _ADCResolution, _readResolution);
}
uint32_t analogRead(uint32_t ulPin)
{
  uint32_t ulValue = 0;
  uint32_t ulChannel;

  if (ulPin < A0)
    ulPin += A0;

  ulChannel = g_APinDescription[ulPin].ulADCChannelNumber ;

	if (ulPin >= PINS_COUNT || ulChannel == NONE )
	{
		return -1;
	}

  pinMode(ulPin,AN_INPUT);

#if defined (STM32F10X_HD) || (STM32F10X_MD)
	ADC_RegularChannelConfig(ADC1, g_APinDescription[ulPin].ulADCChannelNumber, 1, ADC_SampleTime_55Cycles5);
#elif defined (STM32F40_41xxx)
	ADC_RegularChannelConfig(ADC1, g_APinDescription[ulPin].ulADCChannelNumber, 1, ADC_SampleTime_15Cycles);
#endif
	//Start ADC1 Software Conversion
#if defined (STM32F10X_HD) || (STM32F10X_MD)
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
#elif defined (STM32F40_41xxx)	
	ADC_SoftwareStartConv(ADC1);
#endif

	// Wait until conversion completion
	// while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));

  // Read the value
  ulValue = ADC_GetConversionValue(ADC1);
  ulValue = mapResolution(ulValue, ADC_RESOLUTION, _readResolution);

	return ulValue;
}
Beispiel #5
0
uint32_t analogRead(uint32_t ulPin)
{
	uint32_t ulValue = 0;
	uint8_t pselValue = 0;
	if ((ulPin > 0) && (ulPin < PINS_COUNT))	// Only pins 1-6 is avaliable for using as ADC inputs
	{
		pselValue = (1 << (ulPin + 1));	// Calculate PSEL value
    if (analog_reference == ADC_CONFIG_REFSEL_External)
		    NRF_ADC->CONFIG = 	(ADC_CONFIG_RES_10bit 	<< ADC_CONFIG_RES_Pos)|			// 10bit ADC resolution
							(adc_input_selection 	<< ADC_CONFIG_INPSEL_Pos)|		// DEFAULT: Analog input specified by PSEL with 1/3 prescaling used as input for the conversion
							(ADC_CONFIG_REFSEL_External  << ADC_CONFIG_REFSEL_Pos)|
							(pselValue 				<< ADC_CONFIG_PSEL_Pos)|		// Select ADC input
							(external_reference 	<< ADC_CONFIG_EXTREFSEL_Pos);	// DEFAULT: Use analog reference 0 as reference if selected external reference
    else
        NRF_ADC->CONFIG =   (ADC_CONFIG_RES_10bit   << ADC_CONFIG_RES_Pos)|     // 10bit ADC resolution
              (adc_input_selection  << ADC_CONFIG_INPSEL_Pos)|    // DEFAULT: Analog input specified by PSEL with 1/3 prescaling used as input for the conversion
              (analog_reference     << ADC_CONFIG_REFSEL_Pos)|    // DEFAULT: Use supply voltage with 1/3 prescaling as reference for conversion. Only usable when supply voltage is between 2.5V and 3.6V
              (pselValue        << ADC_CONFIG_PSEL_Pos)|    // Select ADC input
              (ADC_CONFIG_EXTREFSEL_None  << ADC_CONFIG_EXTREFSEL_Pos);
		NRF_ADC->INTENCLR = 0xFFFFFFFF;
		NRF_ADC->ENABLE = 	(ADC_ENABLE_ENABLE_Enabled 		<< ADC_ENABLE_ENABLE_Pos);		// Enable ADC
		NRF_ADC->TASKS_START = 	1;															// Start A-D conversion
    NRF_ADC->EVENTS_END = 0;
    while (! NRF_ADC->EVENTS_END)  // Wait for end of conversion
      ;
		ulValue = NRF_ADC->RESULT;															// Read the value
		ulValue = mapResolution(ulValue, ADC_RESOLUTION, _readResolution);
		NRF_ADC->ENABLE =	(ADC_ENABLE_ENABLE_Disabled 	<< ADC_ENABLE_ENABLE_Pos);		// Disable ADC
    NRF_ADC->TASKS_STOP = 1;
		// GPIOs release regarding PAN028
		NRF_ADC->CONFIG = 	(ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos) |
							(ADC_CONFIG_INPSEL_SupplyTwoThirdsPrescaling << ADC_CONFIG_INPSEL_Pos) |
							(ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
							(ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) |
							(ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
	}
	return ulValue;
}
Beispiel #6
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( uint32_t ulPin, uint32_t ulValue )
{
#if 0 // pwm test
#if 1 // port configuration
    *(volatile unsigned int *)0x44000010 |= 1 << 8;   //GPIOx->OUTENSET

    //PAD_AFConfig(PAD_PC, GPIO_Pin_8, 0x01/*PAD_AF1*/); ///< PAD Config - LED used 2nd Function	// (0x01 <<  8)
    *(volatile unsigned int *)(0x41002080 + 0x20) &= ~0x03/*PAD_AF1*/;	// (0x01 <<  8)
//    *(volatile unsigned int *)(0x41002080 + 0x20) |= 0x01/*PAD_AF1*/;	// (0x01 <<  8)

    *(volatile unsigned int *)0x44000010 |= 1 << 9;   //GPIOx->OUTENSET

    *(volatile unsigned int *)(0x41002080 + 0x24) &= ~0x03/*PAD_AF1*/;	// (0x01 <<  8)
//    *(volatile unsigned int *)(0x41002080 + 0x24) |= 0x01/*PAD_AF1*/;	// (0x01 <<  8)
#endif // port configuration
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
    /* Select Timer/Counter mode as Timer mode */ 
    //PWM_CHn->TCMR = PWM_CHn_TCMR_TimerMode;                      
//    *(volatile unsigned int *)0x40005324 = (0x0ul);  // ch3
    *(volatile unsigned int *)0x40005024 = (0x0);
    /* Set Prescale register value */
    //PWM_CHn->PR = PWM_TimerModeInitStruct->PWM_CHn_PR;        
//    *(volatile unsigned int *)0x40005314 = (20000000 / 1000000) / 10 - 1; //PrescalerValue - 1;    
    *(volatile unsigned int *)0x40005014 = (20000000 / 1000000) / 10 - 1; //PrescalerValue - 1;    
    /* Set Match register value */
    //PWM_CHn->MR = PWM_TimerModeInitStruct->PWM_CHn_MR;        
//    *(volatile unsigned int *)0x40005318 = 80000;
    *(volatile unsigned int *)0x40005018 = 80000;
    /* Set Limit register value */
    //PWM_CHn->LR = PWM_TimerModeInitStruct->PWM_CHn_LR;         
//    *(volatile unsigned int *)0x4000531C = 100000; // 80% duty cycle
    *(volatile unsigned int *)0x4000501C = 100000; // 80% duty cycle
    /* Select Up-down mode */
    //PWM_CHn->UDMR = PWM_TimerModeInitStruct->PWM_CHn_UDMR;     
//    *(volatile unsigned int *)0x40005320 = (0x0ul);        //PWM_CHn_UDMR_UpCount
    *(volatile unsigned int *)0x40005020 = (0x0);        //PWM_CHn_UDMR_UpCount
    /* Select Periodic mode */ 
    //PWM_CHn->PDMR = PWM_TimerModeInitStruct->PWM_CHn_PDMR;     
//    *(volatile unsigned int *)0x40005334 = (0x1ul);        //PWM_CHn_PDMR_Periodic
    *(volatile unsigned int *)0x40005034 = (0x1);        //PWM_CHn_PDMR_Periodic

//------------------------------------------------------------------------------------------
    /* Select Timer/Counter mode as Timer mode */ 
    //PWM_CHn->TCMR = PWM_CHn_TCMR_TimerMode;                      
//    *(volatile unsigned int *)0x40005324 = (0x0ul);  // ch3
    *(volatile unsigned int *)0x40005124 = (0x0ul);
    /* Set Prescale register value */
    //PWM_CHn->PR = PWM_TimerModeInitStruct->PWM_CHn_PR;        
//    *(volatile unsigned int *)0x40005314 = (20000000 / 1000000) / 10 - 1; //PrescalerValue - 1;    
    *(volatile unsigned int *)0x40005114 = (20000000 / 1000000) / 10 - 1; //PrescalerValue - 1;    
    /* Set Match register value */
    //PWM_CHn->MR = PWM_TimerModeInitStruct->PWM_CHn_MR;        
//    *(volatile unsigned int *)0x40005318 = 80000;
    *(volatile unsigned int *)0x40005118 = 80000;
    /* Set Limit register value */
    //PWM_CHn->LR = PWM_TimerModeInitStruct->PWM_CHn_LR;         
//    *(volatile unsigned int *)0x4000531C = 100000; // 80% duty cycle
    *(volatile unsigned int *)0x4000511C = 100000; // 80% duty cycle
    /* Select Up-down mode */
    //PWM_CHn->UDMR = PWM_TimerModeInitStruct->PWM_CHn_UDMR;     
//    *(volatile unsigned int *)0x40005320 = (0x0ul);        //PWM_CHn_UDMR_UpCount
    *(volatile unsigned int *)0x40005120 = (0x0ul);        //PWM_CHn_UDMR_UpCount
    /* Select Periodic mode */ 
    //PWM_CHn->PDMR = PWM_TimerModeInitStruct->PWM_CHn_PDMR;     
//    *(volatile unsigned int *)0x40005334 = (0x1ul);        //PWM_CHn_PDMR_Periodic
    *(volatile unsigned int *)0x40005134 = (0x1ul);        //PWM_CHn_PDMR_Periodic

//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
        //PWM->SSR &= PWM_SSR_SS3_Stop;
//        *(volatile unsigned int *)0x40005804 &= ~(0x1ul << 3);
        *(volatile unsigned int *)0x40005804 &= ~(0x1ul << 0);
        //PWM_CHn->PEEER = outputEnDisable; 
//        *(volatile unsigned int *)0x40005328 = (0x2ul);
        *(volatile unsigned int *)0x40005028 = (0x2ul);

//------------------------------------------------------------------------------------------
        //PWM->SSR &= PWM_SSR_SS3_Stop;
//        *(volatile unsigned int *)0x40005804 &= ~(0x1ul << 3);
        *(volatile unsigned int *)0x40005804 &= ~(0x1ul << 1);
        //PWM_CHn->PEEER = outputEnDisable; 
//        *(volatile unsigned int *)0x40005328 = (0x2ul);
        *(volatile unsigned int *)0x40005128 = (0x2ul);

//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------

        //PWM->SSR |= PWM_SSR_SS3_Start;
//        *(volatile unsigned int *)0x40005804 |= (0x1ul << 3);
        *(volatile unsigned int *)0x40005804 |= (0x1ul << 0);

//------------------------------------------------------------------------------------------
        //PWM->SSR |= PWM_SSR_SS3_Start;
//        *(volatile unsigned int *)0x40005804 |= (0x1ul << 3);
        *(volatile unsigned int *)0x40005804 |= (0x1ul << 1);




    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'P';
    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'W';
    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'M';
while(1);
#endif

#if 1
//------------------------------------------------------------------------------------------
    *(volatile unsigned int *)(0x42000010 + pwm_pin_tbl[ulPin].port_num) |= 1 << pwm_pin_tbl[ulPin].pin_num;   //GPIOx->OUTENSET
    //PAD_AFConfig(PAD_PC, GPIO_Pin_8, 0x01/*PAD_AF1*/); ///< PAD Config - LED used 2nd Function	// (0x01 <<  8)
    *(volatile unsigned int *)(0x41002000 + pwm_pin_tbl[ulPin].af_base + pwm_pin_tbl[ulPin].pin_num * 4) &= ~0x03/*PAD_AF1*/;	// (0x01 <<  8)
    *(volatile unsigned int *)(0x41002000 + pwm_pin_tbl[ulPin].af_base + pwm_pin_tbl[ulPin].pin_num * 4) |= pwm_pin_tbl[ulPin].af_num/*PAD_AF1*/;	// (0x01 <<  8)
//------------------------------------------------------------------------------------------
//PWM-n
    /* Select Timer/Counter mode as Timer mode */ 
    *(volatile unsigned int *)(0x40005024 + pwm_pin_tbl[ulPin].pwm_num) = (0x0);
    /* Set Prescale register value */
    *(volatile unsigned int *)(0x40005014 + pwm_pin_tbl[ulPin].pwm_num) = (20000000 / 1000000) / 10 - 1; //PrescalerValue - 1;    
    /* Set Match register value */
    *(volatile unsigned int *)(0x40005018 + pwm_pin_tbl[ulPin].pwm_num) = 400 * ulValue;     //MR
    /* Set Limit register value */
    *(volatile unsigned int *)(0x4000501C + pwm_pin_tbl[ulPin].pwm_num) = 102400; // 80% duty cycle
    /* Select Up-down mode */
    *(volatile unsigned int *)(0x40005020 + pwm_pin_tbl[ulPin].pwm_num) = (0x0);        //PWM_CHn_UDMR_UpCount
    /* Select Periodic mode */ 
    *(volatile unsigned int *)(0x40005034 + pwm_pin_tbl[ulPin].pwm_num) = (0x1);        //PWM_CHn_PDMR_Periodic

//------------------------------------------------------------------------------------------
        //PWM->SSR &= PWM_SSR_SS3_Stop;
        *(volatile unsigned int *)0x40005804 &= ~(0x1 << pwm_pin_tbl[ulPin].pwm_pin);
        //PWM_CHn->PEEER = outputEnDisable; 
        *(volatile unsigned int *)(0x40005028 + pwm_pin_tbl[ulPin].pwm_num) = 0x2;

//------------------------------------------------------------------------------------------
        //PWM->SSR |= PWM_SSR_SS3_Start;
        *(volatile unsigned int *)0x40005804 |= (0x1ul << pwm_pin_tbl[ulPin].pwm_pin);

#if 0  // pwm serial character out
    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'P';
    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'W';
    while( !((*(volatile unsigned long *) 0x4000D018) & (0x01 << 7)) ) ;
    *(volatile unsigned long *) 0x4000D000 = 'M';
#endif  // pwm serial character out

#endif













#if 0
  uint32_t attr = g_APinDescription[ulPin].ulPinAttribute ;
//   uint32_t pwm_name = g_APinDescription[ulPin].ulTCChannel ;
  uint8_t isTC = 0 ;
  uint8_t Channelx ;
  Tc* TCx ;
  Tcc* TCCx ;

  if ( (attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG )
  {
    if ( ulPin == 24 )  // Only 1 DAC on A0 (PA02)
    {
      	ulValue = mapResolution(ulValue, _writeResolution, DAC_RESOLUTION);
    	DAC->DATA.reg = ulValue & 0x3FF;  // Dac on 10 bits.
		DAC->CTRLA.bit.ENABLE = 1; // DAC Enabled
/////////////////////////////////////		syncDAC();
      	return;
    }
	

  }

  if ( (attr & PIN_ATTR_PWM) == PIN_ATTR_PWM )
  {
    if ( (g_APinDescription[ulPin].ulPinType == PIO_TIMER) || g_APinDescription[ulPin].ulPinType == PIO_TIMER_ALT )
    {
      pinPeripheral( ulPin, g_APinDescription[ulPin].ulPinType ) ;
    }

    switch ( g_APinDescription[ulPin].ulPWMChannel )
    {
      case PWM3_CH0 :
                TCx = TC3 ;
                Channelx = 0 ;
                isTC = 1 ;
            break;

      case  PWM3_CH1:
                TCx = TC3 ;
                Channelx = 1;
                isTC = 1;
            break;

      case  PWM0_CH0 :
                TCCx = TCC0;
                Channelx = 0;
            break;

      case  PWM0_CH1 :
                TCCx = TCC0;
                Channelx = 1;
            break;

      case  PWM0_CH4 :
                TCCx = TCC0;
                Channelx = 0;
            break;

      case  PWM0_CH5 :
                TCCx = TCC0;
                Channelx = 1;
            break;

      case  PWM0_CH6 :
                TCCx = TCC0;
                Channelx = 2;
            break;

      case  PWM0_CH7 :
                TCCx = TCC0;
                Channelx = 3;
            break;

      case  PWM1_CH0 :
                TCCx = TCC1;
                Channelx = 0;
            break;

      case  PWM1_CH1 :
                TCCx = TCC1;
                Channelx = 1;
            break;

      case  PWM2_CH0 :
                TCCx = TCC2;
                Channelx = 0;
            break;

      case  PWM2_CH1 :
                TCCx = TCC2;
                Channelx = 1;
            break;
    }


    // Enable clocks according to TCCx instance to use
    switch ( GetTCNumber( g_APinDescription[ulPin].ulPWMChannel ) )
    {
      case 0: // TCC0
                //Enable GCLK for TCC0 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
            break;

      case 1: // TCC1
                //Enable GCLK for TCC1 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
            break;

      case 2: // TCC2
                //Enable GCLK for TCC2 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 )) ;
            break;

      case 3: // TC3
                //Enable GCLK for TC3 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 ));
            break;

      case 4: // TC4
                //Enable GCLK for TC4 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 ));
            break;

      case 5: // TC5
                //Enable GCLK for TC5 (timer counter input clock)
                GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 )) ;
            break;
    }

    // Set PORT
    if ( isTC )
    {
      // -- Configure TC
      //DISABLE TCx
      TCx->COUNT8.CTRLA.reg &=~(TC_CTRLA_ENABLE);
      //Set Timer counter Mode to 8 bits
      TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8;
      //Set TCx as normal PWM
      TCx->COUNT8.CTRLA.reg |= TC_CTRLA_WAVEGEN_NPWM;
      //Set TCx in waveform mode Normal PWM
      TCx->COUNT8.CC[Channelx].reg = (uint8_t) ulValue;
      //Set PER to maximum counter value (resolution : 0xFF)
      TCx->COUNT8.PER.reg = 0xFF;
      // Enable TCx
      TCx->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE;
    }
    else
    {
      // -- Configure TCC

      //DISABLE TCCx
      TCCx->CTRLA.reg &=~(TCC_CTRLA_ENABLE);
      //Set TCx as normal PWM
      TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
      //Set TCx in waveform mode Normal PWM
      TCCx->CC[Channelx].reg = (uint32_t)ulValue;
      //Set PER to maximum counter value (resolution : 0xFF)
      TCCx->PER.reg = 0xFF;
      //ENABLE TCCx
      TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
    }

    return ;
  }

  // -- Defaults to digital write
  pinMode( ulPin, OUTPUT ) ;

  if ( ulValue < 128 )
  {
    digitalWrite( ulPin, LOW ) ;
  }
  else
  {
    digitalWrite( ulPin, HIGH ) ;
  }
#endif

}
// 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 analogFastWrite(uint32_t pin, uint32_t value)
{
  PinDescription pinDesc = g_APinDescription[pin];
  uint32_t attr = pinDesc.ulPinAttribute;

  if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG)
  {
    // DAC handling code

    if (pin != PIN_A0) { // Only 1 DAC on A0 (PA02)
      return;
    }

    value = mapResolution(value, _writeResolution, 10);

    syncDAC();
    DAC->DATA.reg = value & 0x3FF;  // DAC on 10 bits.
    syncDAC();
    DAC->CTRLA.bit.ENABLE = 0x01;     // Enable DAC
    syncDAC();
    return;
  }

  if ((attr & PIN_ATTR_PWM) == PIN_ATTR_PWM)
  {
    value = mapResolution(value, _writeResolution, 8);  // change to 10 for 10 bit... must also change  TCx->COUNT8.PER.reg = 0x3FF
    uint32_t tcNum = GetTCNumber(pinDesc.ulPWMChannel);
    uint8_t tcChannel = GetTCChannelNumber(pinDesc.ulPWMChannel);
    static bool tcEnabled[TCC_INST_NUM+TC_INST_NUM];

    if (!tcEnabled[tcNum]) {
      tcEnabled[tcNum] = true;

      if (attr & PIN_ATTR_TIMER) {
        #if !(ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10603)
        // Compatibility for cores based on SAMD core <=1.6.2
        if (pinDesc.ulPinType == PIO_TIMER_ALT) {
          pinPeripheral(pin, PIO_TIMER_ALT);
        } else
        #endif
        {
          pinPeripheral(pin, PIO_TIMER);
        }
      } else {
        // We suppose that attr has PIN_ATTR_TIMER_ALT bit set...
        pinPeripheral(pin, PIO_TIMER_ALT);
      }

      uint16_t GCLK_CLKCTRL_IDs[] = {
        GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC0
        GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC1
        GCLK_CLKCTRL_ID(GCM_TCC2_TC3),  // TCC2
        GCLK_CLKCTRL_ID(GCM_TCC2_TC3),  // TC3
        GCLK_CLKCTRL_ID(GCM_TC4_TC5),   // TC4
        GCLK_CLKCTRL_ID(GCM_TC4_TC5),   // TC5
        GCLK_CLKCTRL_ID(GCM_TC6_TC7),   // TC6
        GCLK_CLKCTRL_ID(GCM_TC6_TC7),   // TC7
      };
      GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_IDs[tcNum]);
      while (GCLK->STATUS.bit.SYNCBUSY == 1);

      // Set PORT
      if (tcNum >= TCC_INST_NUM) {
        // -- Configure TC
        Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
        // Disable TCx
        TCx->COUNT8.CTRLA.bit.ENABLE = 0;
        syncTC_8(TCx);
        // Set Timer counter Mode to 8 bits, normal PWM
        TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8 | TC_CTRLA_WAVEGEN_NPWM;
        syncTC_8(TCx);
        // Set the initial value
        TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
        syncTC_8(TCx);
        // Set PER to maximum counter value (resolution : 0xFF)
        TCx->COUNT8.PER.reg = 0xFF;
        syncTC_8(TCx);
        // Enable TCx
        TCx->COUNT8.CTRLA.bit.ENABLE = 1;
        syncTC_8(TCx);
      } else {
        // -- Configure TCC
        Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
        // Disable TCCx
        TCCx->CTRLA.bit.ENABLE = 0;
        syncTCC(TCCx);

        // Set TCx as normal PWM
        TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
        syncTCC(TCCx);
        // Set the initial value
        TCCx->CC[tcChannel].reg = (uint32_t) value;
        syncTCC(TCCx);
        // Set PER to maximum counter value (resolution : 0xFF)
        TCCx->PER.reg = 0xFF; //change to 0x43FF for 10 bit... must also change mapping above
        syncTCC(TCCx);
        // Enable TCCx
        TCCx->CTRLA.bit.ENABLE = 1;
        syncTCC(TCCx);
      }
    } else {
      if (tcNum >= TCC_INST_NUM) {
        Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
        TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
        syncTC_8(TCx);
    } else {
        Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
        TCCx->CTRLBSET.bit.LUPD = 1;
        syncTCC(TCCx);
        TCCx->CCB[tcChannel].reg = (uint32_t) value;
        syncTCC(TCCx);
        TCCx->CTRLBCLR.bit.LUPD = 1;
        syncTCC(TCCx);
      }
    }
    return;
  }

  // -- Defaults to digital write
  pinMode(pin, OUTPUT);
  value = mapResolution(value, _writeResolution, 8);
  if (value < 128) {
    digitalWrite(pin, LOW);
  } else {
    digitalWrite(pin, HIGH);
  }
}
Beispiel #8
0
void analogWrite(uint32_t ulPin, uint32_t ulValue) {

  if (ulValue == 0)
  {
    digitalWrite(ulPin, LOW);
    return;
  }

  if (ulValue == 255)
  {
    digitalWrite(ulPin, HIGH);
    return;
  }

	if (Timer1_Compare_Unit_Occupied_by_Pin[0] == ulPin)
	{
		update_PWM_value(ulPin, ulValue, 0);
	}
	else if (Timer1_Compare_Unit_Occupied_by_Pin[1] == ulPin)
	{
		update_PWM_value(ulPin, ulValue, 1);
	}
	else if (Timer1_Compare_Unit_Occupied_by_Pin[2] == ulPin)
	{
		update_PWM_value(ulPin, ulValue, 2);
	}
	else if (Timer2_Compare_Unit_Occupied_by_Pin[0] == ulPin)
	{
		update_PWM_value(ulPin, ulValue, 3);
	}
	else
	{
		if ((Timer1_Compare_Unit_Occupied_by_Pin[0] == 255) && (Timer1_Compare_Unit_Occupied_by_Pin[1] == 255) && (Timer1_Compare_Unit_Occupied_by_Pin[2] == 255))
		{
			// Timer1 is not used: need to initialize it

			// Configure ulPin as output
      digitalWrite(ulPin, LOW);
			pinMode(ulPin, OUTPUT);

			if (ulValue > 0)
			{
				// Configure GPIOTE channel "gpiote_channel" to toggle the PWM pin state
				// Note that we can only connect one GPIOTE task to an output pin
				nrf_gpiote_task_config(0, ulPin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
			}
			GPIOTE_Channels_Occupied[ulPin] = 0;

			NRF_TIMER1->TASKS_STOP = 1;
			NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
			//NRF_TIMER1->PRESCALER = 6; // Source clock frequency is divided by 2^6 = 64
			NRF_TIMER1->PRESCALER = 0; // Source clock frequency is divided by 2^6 = 64 /////////////////////////////////////////
			//NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_08Bit;
			NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_16Bit;	////////////////////////////
			// Clears the timer, sets it to 0
			NRF_TIMER1->TASKS_CLEAR = 1;
			NRF_TIMER1->CC[0] = (2^PWM_RESOLUTION - 1);
			NRF_TIMER1->CC[1] = (2^PWM_RESOLUTION - 1);
			NRF_TIMER1->CC[2] = (2^PWM_RESOLUTION - 1);
			NRF_TIMER1->CC[3] = 0;
			NRF_TIMER1->EVENTS_COMPARE[0] = 0;
			NRF_TIMER1->EVENTS_COMPARE[1] = 0;
			NRF_TIMER1->EVENTS_COMPARE[2] = 0;
			NRF_TIMER1->EVENTS_COMPARE[3] = 0;
			// Interrupt setup
			NRF_TIMER1->INTENSET = (TIMER_INTENSET_COMPARE3_Enabled << TIMER_INTENSET_COMPARE3_Pos);
      attachInterrupt(TIMER1_IRQn, TIMER1_Interrupt);

			// Start clock
			NRF_TIMER1->TASKS_START = 1;

			turn_On_PPI_to_GPIO_for_PWM(ulPin, 0, NRF_TIMER1, 0);

			PWM_Channels_Value[0] = (2^PWM_RESOLUTION - 1) - mapResolution(ulValue, _writeResolution, PWM_RESOLUTION);
			Timer1_Compare_Unit_Occupied_by_Pin[0] = ulPin;
			Pin_Occupied_for_PWM[ulPin] = 1;
		}
		else
		{
			if (Timer1_Compare_Unit_Occupied_by_Pin[0] == 255)
			{
				// Configure ulPin as output
        digitalWrite(ulPin, LOW);
				pinMode(ulPin, OUTPUT);
				if (ulValue > 0)
				{
					// Configure GPIOTE channel "gpiote_channel" to toggle the PWM pin state
					// Note that we can only connect one GPIOTE task to an output pin
					nrf_gpiote_task_config(0, ulPin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
				}
				GPIOTE_Channels_Occupied[ulPin] = 0;
				turn_On_PPI_to_GPIO_for_PWM(ulPin, 0, NRF_TIMER1, 0);
				PWM_Channels_Value[0] = (2^PWM_RESOLUTION - 1) - mapResolution(ulValue, _writeResolution, PWM_RESOLUTION);
				Timer1_Compare_Unit_Occupied_by_Pin[0] = ulPin;
				Pin_Occupied_for_PWM[ulPin] = 1;
				NRF_TIMER1->EVENTS_COMPARE[0] = 0;
			}
			else if (Timer1_Compare_Unit_Occupied_by_Pin[1] == 255)
			{
				// Configure ulPin as output
        digitalWrite(ulPin, LOW);
				pinMode(ulPin, OUTPUT);
				if (ulValue > 0)
				{
					// Configure GPIOTE channel "gpiote_channel" to toggle the PWM pin state
					// Note that we can only connect one GPIOTE task to an output pin
					nrf_gpiote_task_config(1, ulPin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
				}
				GPIOTE_Channels_Occupied[ulPin] = 1;
				turn_On_PPI_to_GPIO_for_PWM(ulPin, 1, NRF_TIMER1, 1);
				PWM_Channels_Value[1] = (2^PWM_RESOLUTION - 1) - mapResolution(ulValue, _writeResolution, PWM_RESOLUTION);
				Timer1_Compare_Unit_Occupied_by_Pin[1] = ulPin;
				Pin_Occupied_for_PWM[ulPin] = 1;
				NRF_TIMER1->EVENTS_COMPARE[1] = 0;
			}
			else if (Timer1_Compare_Unit_Occupied_by_Pin[2] == 255)
			{
				// Configure ulPin as output
        digitalWrite(ulPin, LOW);
				pinMode(ulPin, OUTPUT);
				if (ulValue > 0)
				{
					// Configure GPIOTE channel "gpiote_channel" to toggle the PWM pin state
					// Note that we can only connect one GPIOTE task to an output pin
					nrf_gpiote_task_config(2, ulPin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
				}
				GPIOTE_Channels_Occupied[ulPin] = 2;
				turn_On_PPI_to_GPIO_for_PWM(ulPin, 2, NRF_TIMER1, 2);
				PWM_Channels_Value[2] = (2^PWM_RESOLUTION - 1) - mapResolution(ulValue, _writeResolution, PWM_RESOLUTION);
				Timer1_Compare_Unit_Occupied_by_Pin[2] = ulPin;
				Pin_Occupied_for_PWM[ulPin] = 1;
				NRF_TIMER1->EVENTS_COMPARE[2] = 0;
			}
			else
			{
				// All channels of Timer1 is occupied, need to use Timer2
				if (!RFduinoGZLL_used && Timer2_Compare_Unit_Occupied_by_Pin[0] == 255)
				{
					// Timer2 is not used: need to initialize it

					// Configure ulPin as output
          digitalWrite(ulPin, LOW);
					pinMode(ulPin, OUTPUT);

					if (ulValue > 0)
					{
						// Configure GPIOTE channel "gpiote_channel" to toggle the PWM pin state
						// Note that we can only connect one GPIOTE task to an output pin
						nrf_gpiote_task_config(3, ulPin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
					}
					GPIOTE_Channels_Occupied[ulPin] = 3;

					NRF_TIMER2->TASKS_STOP = 1;
					NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;
					//NRF_TIMER2->PRESCALER = 6; // Source clock frequency is divided by 2^6 = 64
					NRF_TIMER2->PRESCALER = 0; // Source clock frequency is divided by 2^6 = 64 /////////////////////////////////////////
					//NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_08Bit;
					NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;	////////////////////////////
					// Clears the timer, sets it to 0
					NRF_TIMER2->TASKS_CLEAR = 1;
					NRF_TIMER2->CC[0] = (2^PWM_RESOLUTION - 1);
					NRF_TIMER2->CC[3] = 0;
					NRF_TIMER2->EVENTS_COMPARE[0] = 0;
					NRF_TIMER2->EVENTS_COMPARE[3] = 0;

					// Interrupt setup
					NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE3_Enabled << TIMER_INTENSET_COMPARE3_Pos);
          attachInterrupt(TIMER2_IRQn, TIMER2_Interrupt);

					// Start clock
					NRF_TIMER2->TASKS_START = 1;

					turn_On_PPI_to_GPIO_for_PWM(ulPin, 3, NRF_TIMER2, 0);

					PWM_Channels_Value[3] = (2^PWM_RESOLUTION - 1) - mapResolution(ulValue, _writeResolution, PWM_RESOLUTION);
					Timer2_Compare_Unit_Occupied_by_Pin[0] = ulPin;
					Pin_Occupied_for_PWM[ulPin] = 1;
				}
				else
				{
					// Using all 4 TASK channels of GPIOTE, it is not possible to add another PWM channel.
				}
			}
		}
	}

/*
	// Defaults to digital write
	pinMode(ulPin, OUTPUT);
	ulValue = mapResolution(ulValue, _writeResolution, 8);
	if (ulValue < 128)
		digitalWrite(ulPin, LOW);
	else
		digitalWrite(ulPin, HIGH);
*/
}
Beispiel #9
0
extern void pinMode( uint32_t ulPin, uint32_t ulMode )
{
	
	if ( ulPin > PINS_COUNT )
    {
        return ;
    }

  GPIO_TypeDef *gpio_port = g_APinDescription[ulPin].pPort;
  uint16_t gpio_pin = g_APinDescription[ulPin].ulPin;

  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(g_APinDescription[ulPin].ulPeripheral,ENABLE);

  GPIO_InitStructure.GPIO_Pin = gpio_pin;

	switch ( ulMode )
    {
        case INPUT:
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        break ;

        case INPUT_PULLUP:
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        break ;

        case INPUT_PULLDOWN:
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
        break;
	

        case OUTPUT:
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        break ;

        case AF_OUTPUT_PUSHPULL:	//Used internally for Alternate Function Output PushPull(TIM, UART, SPI etc)
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        break;

        case AF_OUTPUT_DRAIN:		//Used internally for Alternate Function Output Drain(I2C etc)
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        break;

        case AN_INPUT:				//Used internally for ADC Input
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        break;
	 case OUTPUT_OD	:			//Used internally for ADC Input
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        break;
	#if 0	
     case TIMER_PWM:
	 {
		  uint32_t ulValue = 0;
 		  uint32_t ulChannel;
	 	
		if ( g_APinDescription[ulPin].ulTimerPeripheral == NULL)
			{
			// Defaults to digital write
			pinMode(ulPin, OUTPUT);
			ulValue = mapResolution(ulValue, _writeResolution, 8);
			if (ulValue < 128)
			  digitalWrite(ulPin, LOW);
			else
			  digitalWrite(ulPin, HIGH);
		
			return;
		  }
		
			TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
			TIM_OCInitTypeDef  TIM_OCInitStructure;
		    uint16_t TIM_CCR = 0;
		    ulValue = mapResolution(ulValue, _writeResolution, PWM_RESOLUTION);		//对于PWM 模块来说 该函数直接返回ulValue.
		
			//PWM Frequency : 1000 Hz,Timer counter clk:1MHz
			uint16_t TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1;
			uint16_t TIM_ARR = (uint16_t)(1000000 / PWM_FREQUENCY) - 1;
		
		
		   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		   GPIO_Init(gpio_port, &GPIO_InitStructure);  
		   
		  if (!pinEnabled[ulPin]) {
			// Setup PWM for this pin
		
			// AFIO clock enable
			RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
		
			// TIM clock enable
			if(g_APinDescription[ulPin].ulTimerPeripheral == TIM1)
			  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);
			else if(g_APinDescription[ulPin].ulTimerPeripheral == TIM2)
			{
			  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
			}
			else if(g_APinDescription[ulPin].ulTimerPeripheral == TIM3)
			{
			  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
			}
			else if(g_APinDescription[ulPin].ulTimerPeripheral == TIM4)
			{
			  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
			}
			else if(g_APinDescription[ulPin].ulTimerPeripheral == TIM5)
			{
			  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
			}
			else if(g_APinDescription[ulPin].ulTimerPeripheral == TIM8)
			  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8 , ENABLE);
		
			// Time base configuration
			TIM_TimeBaseStructure.TIM_Period = TIM_ARR;
			TIM_TimeBaseStructure.TIM_Prescaler = TIM_Prescaler;
			TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//0
			TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
		
			//for TIM1 and TIM8
			TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
		
			TIM_TimeBaseInit(g_APinDescription[ulPin].ulTimerPeripheral, &TIM_TimeBaseStructure);
			pinEnabled[ulPin] = 1;
		  }
		
			// PWM1 Mode configuration
			TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
			TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
			
			TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
			TIM_OCInitStructure.TIM_Pulse = TIM_CCR;
		
		  //for TIM1 and TIM8
		  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
		  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
		  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
		  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
		
			if(g_APinDescription[ulPin].ulTimerChannel == TIM_Channel_1)
			{
				// PWM1 Mode configuration: Channel1
				TIM_OC1Init(g_APinDescription[ulPin].ulTimerPeripheral, &TIM_OCInitStructure);
				TIM_OC1PreloadConfig(g_APinDescription[ulPin].ulTimerPeripheral, TIM_OCPreload_Enable);
			}
			else if(g_APinDescription[ulPin].ulTimerChannel == TIM_Channel_2)
			{
				// PWM1 Mode configuration: Channel2
				TIM_OC2Init(g_APinDescription[ulPin].ulTimerPeripheral, &TIM_OCInitStructure);
				TIM_OC2PreloadConfig(g_APinDescription[ulPin].ulTimerPeripheral, TIM_OCPreload_Enable);
			}
			else if(g_APinDescription[ulPin].ulTimerChannel == TIM_Channel_3)
			{
				// PWM1 Mode configuration: Channel3
				TIM_OC3Init(g_APinDescription[ulPin].ulTimerPeripheral, &TIM_OCInitStructure);
				TIM_OC3PreloadConfig(g_APinDescription[ulPin].ulTimerPeripheral, TIM_OCPreload_Enable);
			}
			else if(g_APinDescription[ulPin].ulTimerChannel == TIM_Channel_4)
			{
				// PWM1 Mode configuration: Channel4
				TIM_OC4Init(g_APinDescription[ulPin].ulTimerPeripheral, &TIM_OCInitStructure);
				TIM_OC4PreloadConfig(g_APinDescription[ulPin].ulTimerPeripheral, TIM_OCPreload_Enable);
			}
		
			TIM_ARRPreloadConfig(g_APinDescription[ulPin].ulTimerPeripheral, ENABLE);
		
			// TIM enable counter
			TIM_Cmd(g_APinDescription[ulPin].ulTimerPeripheral, ENABLE);
		
		  //for TIM1 and TIM8
		  TIM_CtrlPWMOutputs(g_APinDescription[ulPin].ulTimerPeripheral, ENABLE);
	 }
		  return;
#endif

		
        default:
        break ;
    }


  GPIO_Init(gpio_port, &GPIO_InitStructure);  
}
// 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(uint32_t ulPin, uint32_t ulValue) {

	if (ulPin >= PINS_COUNT )
	{
		return;
	}

	if ( g_APinDescription[ulPin].ulTimerPeripheral == NULL)
	{
    // Defaults to digital write
    pinMode(ulPin, OUTPUT);
    ulValue = mapResolution(ulValue, _writeResolution, 8);
    if (ulValue < 128)
      digitalWrite(ulPin, LOW);
    else
      digitalWrite(ulPin, HIGH);

    return;
  }

	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

  ulValue = mapResolution(ulValue, _writeResolution, PWM_RESOLUTION);

	//PWM Frequency : 1000 Hz,Timer counter clk:1MHz
	uint16_t TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1;
	uint16_t TIM_ARR = (uint16_t)(1000000 / PWM_FREQUENCY) - 1;

	uint16_t Duty_Cycle = (uint16_t)((ulValue * 100) / 255);
	// TIM Channel Duty Cycle(%) = (TIM_CCR / TIM_ARR + 1) * 100
	uint16_t TIM_CCR = (uint16_t)((Duty_Cycle * (TIM_ARR + 1)) / 100);

#if defined (STM32F40_41xxx)
  uint8_t GPIO_AF_TIM;
#endif

  pinMode(ulPin, AF_OUTPUT_PUSHPULL);

  if (!pinEnabled[ulPin]) {
    // Setup PWM for this pin

    // AFIO clock enable
#if defined(STM32F10X_HD) || defined (STM32F10X_MD)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
#elif defined (STM32F40_41xxx)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
#endif


    // TIM clock enable
    if(g_APinDescription[ulPin].ulTimerPeripheral == TIM1)
    {
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);
#if defined (STM32F40_41xxx)
      GPIO_AF_TIM = GPIO_AF_TIM1;
#endif
    }
    else if(g_APinDescription[ulPin].ulTimerPeripheral == TIM2)
    {
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
#if defined (STM32F40_41xxx)
      GPIO_AF_TIM = GPIO_AF_TIM2;
#endif
    }
    else if(g_APinDescription[ulPin].ulTimerPeripheral == TIM3)
    {
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
#if defined (STM32F40_41xxx)
      GPIO_AF_TIM = GPIO_AF_TIM3;
#endif
    }
    else if(g_APinDescription[ulPin].ulTimerPeripheral == TIM4)
    {
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
#if defined (STM32F40_41xxx)
      GPIO_AF_TIM = GPIO_AF_TIM4;
#endif
    }
    else if(g_APinDescription[ulPin].ulTimerPeripheral == TIM5)
    {
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
#if defined (STM32F40_41xxx)
      GPIO_AF_TIM = GPIO_AF_TIM5;
#endif
    }
    else if(g_APinDescription[ulPin].ulTimerPeripheral == TIM8)
    {
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8 , ENABLE);
#if defined (STM32F40_41xxx)
      GPIO_AF_TIM = GPIO_AF_TIM8;
#endif
    }

  #if defined (STM32F40_41xxx)
    uint8_t pin_source=0;
    uint16_t pin_temp = ulPin;
    while(pin_temp != 0x0001)
    {
      pin_temp = pin_temp>>1;
      pin_source +=1;
    }
  
    GPIO_PinAFConfig(g_APinDescription[ulPin].pPort, pin_source, GPIO_AF_TIM);
  #endif

    // Time base configuration
    TIM_TimeBaseStructure.TIM_Period = TIM_ARR;
    TIM_TimeBaseStructure.TIM_Prescaler = TIM_Prescaler;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//0
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    //for TIM1 and TIM8
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(g_APinDescription[ulPin].ulTimerPeripheral, &TIM_TimeBaseStructure);
    pinEnabled[ulPin] = 1;
  }