/**********************************************************************
name :
function : 
**********************************************************************/
void analogWrite(uint32_t ulPin, uint32_t ulValue)
{	
	uint32_t nrf_pin, max_value, err_code = NRF_SUCCESS , crystal_is_running=0;
	uint8_t gpiote_channel;

	nrf_pin = Pin_nRF51822_to_Arduino(ulPin);
	if( nrf_pin < 31)
	{	//if vaule 0 or >255, set LOW or HIGH
		if(ulValue <= 0)
		{  
			PPI_Off_FROM_GPIO(nrf_pin);
			NRF_GPIO->OUTCLR = (1 << nrf_pin);
			return;
		}
		max_value = (uint32_t)( pow(2, analogWriteResolution_bit) - 1 );
		if(ulValue >= max_value )
		{	
			ulValue = max_value - 1;
		}
		//if exist,  update the value
		if (Timer1_Occupied_Pin[0] == nrf_pin)
		{	
			update_PWM_value(nrf_pin, ulValue, 0);
		}
		else if (Timer1_Occupied_Pin[1] == nrf_pin)
		{
			update_PWM_value(nrf_pin, ulValue, 1);
		}
		else if (Timer1_Occupied_Pin[2] == nrf_pin)
		{
			update_PWM_value(nrf_pin, ulValue, 2);
		}
		else
		{  
			if ((Timer1_Occupied_Pin[0] == 255) && (Timer1_Occupied_Pin[1] == 255) && (Timer1_Occupied_Pin[2] == 255))
			{	
				// Configure ulPin as output
				NRF_GPIO->PIN_CNF[nrf_pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
						| (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos)
						| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
						| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
						| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
				NRF_GPIO->OUTCLR = (1 << nrf_pin);	
				
				//fine a free gpiote channel
				gpiote_channel = GPIOTE_Channel_Find();
				if( gpiote_channel == 255 )
				{
					return;
				}
				//configure TIMER1
				NRF_TIMER1->TASKS_STOP = 1;
				NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
				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);
				LinkInterrupt( TIMER1_IRQn, TIMER1_handler );
				//can't set low priority, else the GPIO polarity will change 
				//NVIC_SetPriority(TIMER1_IRQn, 3);  
				//NVIC_ClearPendingIRQ(TIMER1_IRQn);
				NVIC_EnableIRQ(TIMER1_IRQn); 
				NRF_TIMER1->TASKS_START = 1;				
				// PPI for TIMER1 and IO TASK
				nrf_gpiote_task_config(gpiote_channel, nrf_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
				GPIOTE_Channel_Set(gpiote_channel);
				PPI_ON_TIMER_GPIO(gpiote_channel, NRF_TIMER1, 0);
				//Save pin , channel and value
				GPIOTE_Channel_for_Analog[0] = gpiote_channel;
				PWM_Channels_Value[0] = ((2^PWM_RESOLUTION) - 1) - conversion_Resolution(ulValue, analogWriteResolution_bit, PWM_RESOLUTION);
				Timer1_Occupied_Pin[0] = nrf_pin;
			}
			else
			{
				if (Timer1_Occupied_Pin[0] == 255)
				{
					NRF_GPIO->PIN_CNF[nrf_pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
												| (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos)
												| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
												| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
												| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
					NRF_GPIO->OUTCLR = (1 << nrf_pin);
					//fine a free gpiote channel and configure the channel
					gpiote_channel = GPIOTE_Channel_Find();
					if( gpiote_channel == 255 )
					{
						return;
					}
					nrf_gpiote_task_config(gpiote_channel, nrf_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
					GPIOTE_Channel_Set(gpiote_channel);
					PPI_ON_TIMER_GPIO(gpiote_channel, NRF_TIMER1, 0);
					//save the pin and value
					GPIOTE_Channel_for_Analog[0] = gpiote_channel;
					PWM_Channels_Value[0] = ((2^PWM_RESOLUTION) - 1) - conversion_Resolution(ulValue, analogWriteResolution_bit, PWM_RESOLUTION);
					Timer1_Occupied_Pin[0] = nrf_pin;
					NRF_TIMER1->EVENTS_COMPARE[0] = 0;
				}
				else if (Timer1_Occupied_Pin[1] == 255)
				{
					NRF_GPIO->PIN_CNF[nrf_pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
												| (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos)
												| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
												| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
												| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
					NRF_GPIO->OUTCLR = (1 << nrf_pin);
					//find a free gpiote channel
					gpiote_channel = GPIOTE_Channel_Find();
					if( gpiote_channel == 255 )
					{
						return;
					}
					
					nrf_gpiote_task_config(gpiote_channel, nrf_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
					GPIOTE_Channel_Set(gpiote_channel);
					PPI_ON_TIMER_GPIO(gpiote_channel, NRF_TIMER1, 1);
					//save the pin and value
					GPIOTE_Channel_for_Analog[1] = gpiote_channel;
					PWM_Channels_Value[1] = ((2^PWM_RESOLUTION) - 1) - conversion_Resolution(ulValue, analogWriteResolution_bit, PWM_RESOLUTION);
					Timer1_Occupied_Pin[1] = nrf_pin;
					NRF_TIMER1->EVENTS_COMPARE[1] = 0;
				}
				else if (Timer1_Occupied_Pin[2] == 255)
				{
					NRF_GPIO->PIN_CNF[nrf_pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
												| (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos)
												| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
												| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
												| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
					NRF_GPIO->OUTCLR = (1 << nrf_pin);
					//find a free gpiote channel
					gpiote_channel = GPIOTE_Channel_Find();
					if( gpiote_channel == 255 )
					{
						return;
					}
					
					nrf_gpiote_task_config(gpiote_channel, nrf_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
					GPIOTE_Channel_Set(gpiote_channel);
					PPI_ON_TIMER_GPIO(gpiote_channel, NRF_TIMER1, 2);
					//save the pin and value
					GPIOTE_Channel_for_Analog[2] = gpiote_channel;
					PWM_Channels_Value[2] = ((2^PWM_RESOLUTION) - 1) - conversion_Resolution(ulValue, analogWriteResolution_bit, PWM_RESOLUTION);
					Timer1_Occupied_Pin[2] = nrf_pin;
					NRF_TIMER1->EVENTS_COMPARE[2] = 0;
				}
				else
				{   
					//no more
				}
			}
		}	
	}
}
Exemple #2
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);
*/
}