/*
 Copyright (c) 2011 Arduino.  All right reserved.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 See the GNU Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "Arduino.h"

#ifdef __cplusplus
extern "C" {
#endif

eAnalogReference analog_reference = AR_DEFAULT;

void analogReference(eAnalogReference ulMode)
{
	analog_reference = ulMode;
}

uint32_t analogRead(uint32_t ulPin)
{
  uint32_t ulValue = 0;
  uint32_t ulChannel;

  if (ulPin < A0)
    ulPin += A0;

  ulChannel = g_APinDescription[ulPin].ulADCChannelNumber ;

#if defined __SAM3U4E__
	switch ( g_APinDescription[ulPin].ulAnalogChannel )
	{
		// Handling ADC 10 bits channels
		case ADC0 :
		case ADC1 :
		case ADC2 :
		case ADC3 :
		case ADC4 :
		case ADC5 :
		case ADC6 :
		case ADC7 :
      // Enable the corresponding channel
      adc_enable_channel( ADC, ulChannel );

      // Start the ADC
      adc_start( ADC );

			// Wait for end of conversion
			while ((adc_get_status(ADC) & ADC_SR_DRDY) != ADC_SR_DRDY)
				;

			// Read the value
			ulValue = adc_get_latest_value(ADC);

      // Disable the corresponding channel
      adc_disable_channel( ADC, ulChannel );

      // Stop the ADC
      //      adc_stop( ADC ) ; // never do adc_stop() else we have to reconfigure the ADC each time
		break;

		// Handling ADC 12 bits channels
		case ADC8 :
		case ADC9 :
		case ADC10 :
		case ADC11 :
		case ADC12 :
		case ADC13 :
		case ADC14 :
		case ADC15 :
      // Enable the corresponding channel
      adc12b_enable_channel( ADC12B, ulChannel );

      // Start the ADC12B
      adc12b_start( ADC12B );

			// Wait for end of conversion
			while ((adc12b_get_status(ADC12B) & ADC12B_SR_DRDY) != ADC12B_SR_DRDY)
				;

			// Read the value
			ulValue = adc12b_get_latest_value(ADC12B);

      // Stop the ADC12B
      //      adc12_stop( ADC12B ) ; // never do adc12_stop() else we have to reconfigure the ADC12B each time

      // Disable the corresponding channel
      adc12b_disable_channel( ADC12B, ulChannel );
		break;

		// Compiler could yell because we don't handle DAC pins
		default :
      ulValue=0;
		break;
	}
#endif

#if defined __SAM3X8E__ || defined __SAM3X8H__
	switch ( g_APinDescription[ulPin].ulAnalogChannel )
	{
		// Handling ADC 10 bits channels
		case ADC0 :
		case ADC1 :
		case ADC2 :
		case ADC3 :
		case ADC4 :
		case ADC5 :
		case ADC6 :
		case ADC7 :
		case ADC8 :
		case ADC9 :
		case ADC10 :
		case ADC11 :

			// Enable the corresponding channel
			adc_enable_channel( ADC, ulChannel );

			// Start the ADC
			adc_start( ADC );

			// Wait for end of conversion
			while ((adc_get_status(ADC) & ADC_ISR_DRDY) != ADC_ISR_DRDY)
				;

			// Read the value
			ulValue = adc_get_latest_value(ADC);

			// Disable the corresponding channel
			adc_disable_channel(ADC, ulChannel);
			break;

		// Compiler could yell because we don't handle DAC pins
		default :
			ulValue=0;
			break;
	}
#endif

	return ulValue;
}

static void TC_SetRA(Tc *tc, uint32_t chan, uint32_t v )
{
    tc->TC_CHANNEL[chan].TC_RA = v;
}

static void TC_SetRB(Tc *tc, uint32_t chan, uint32_t v )
{
    tc->TC_CHANNEL[chan].TC_RB = v;
}

static void TC_SetRC(Tc *tc, uint32_t chan, uint32_t v )
{
    tc->TC_CHANNEL[chan].TC_RC = v;
}

static uint8_t PWMEnabled = 0;
static uint8_t pinEnabled[PINS_COUNT];
static uint8_t TCChanEnabled[] = {0, 0, 0};

void analogOutputInit(void) {
	uint8_t i;
	for (i=0; i<PINS_COUNT; i++)
		pinEnabled[i] = 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) {
	uint32_t attr = g_APinDescription[ulPin].ulPinAttribute;

	if ((attr & PIN_ATTR_PWM) == PIN_ATTR_PWM) {
		if (!PWMEnabled) {
			// PWM Startup code
		    pmc_enable_periph_clk(PWM_INTERFACE_ID);
		    PWMC_ConfigureClocks(PWM_FREQUENCY * PWM_MAX_DUTY_CYCLE, 0, VARIANT_MCK);
			PWMEnabled = 1;
		}

		uint32_t chan = g_APinDescription[ulPin].ulPWMChannel;
		if (!pinEnabled[ulPin]) {
			// Setup PWM for this pin
			PIO_Configure(g_APinDescription[ulPin].pPort,
					g_APinDescription[ulPin].ulPinType,
					g_APinDescription[ulPin].ulPin,
					g_APinDescription[ulPin].ulPinConfiguration);
			PWMC_ConfigureChannel(PWM_INTERFACE, chan, PWM_CMR_CPRE_CLKA, 0, 0);
			PWMC_SetPeriod(PWM_INTERFACE, chan, PWM_MAX_DUTY_CYCLE);
			PWMC_SetDutyCycle(PWM_INTERFACE, chan, ulValue);
			PWMC_EnableChannel(PWM_INTERFACE, chan);
			pinEnabled[ulPin] = 1;
		}

		PWMC_SetDutyCycle(PWM_INTERFACE, chan, ulValue);
		return;
	}

	if ((attr & PIN_ATTR_TIMER) == PIN_ATTR_TIMER) {
		// We use MCLK/2 => 96Mhz/2 => 48Mhz as clock.
		// To get 1KHz we should use 48000 as TC
		// 48Mhz/48000 = 1KHz
		const uint32_t TC = VARIANT_MCK / 2 / TC_FREQUENCY;

		// Map value to Timer ranges 0..255=>0..48000
		ulValue = ulValue * TC;
		ulValue = ulValue / TC_MAX_DUTY_CYCLE;

		// Setup Timer for this pin
		ETCChannel channel = g_APinDescription[ulPin].ulTCChannel;
		static const uint32_t channelToChNo[] = { 0, 0, 1, 1, 2, 2 };
		static const uint32_t channelToAB[] = { 1, 0, 1, 0, 1, 0 };
		uint32_t chNo = channelToChNo[channel];
		uint32_t chA = channelToAB[channel];

		if (!TCChanEnabled[chNo]) {
			pmc_enable_periph_clk(TC_INTERFACE_ID + chNo);
			TC_Configure(TC_INTERFACE, chNo,
					TC_CMR_TCCLKS_TIMER_CLOCK1 |
					TC_CMR_WAVE |
					TC_CMR_WAVSEL_UP_RC |
					TC_CMR_ACPA_CLEAR |   // RA Compare Effect on OA: clear
					TC_CMR_ACPC_SET |     // RC Compare Effect on OA: set
					TC_CMR_BCPB_CLEAR |   // RB Compare Effect on OB: clear
					TC_CMR_BCPC_SET);     // RC Compare Effect on OB: set
			TC_SetRC(TC_INTERFACE, chNo, TC);
		}
		if (chA)
			TC_SetRA(TC_INTERFACE, chNo, ulValue);
		else
			TC_SetRB(TC_INTERFACE, chNo, ulValue);
		if (!pinEnabled[ulPin]) {
			PIO_Configure(g_APinDescription[ulPin].pPort,
					g_APinDescription[ulPin].ulPinType,
					g_APinDescription[ulPin].ulPin,
					g_APinDescription[ulPin].ulPinConfiguration);
			pinEnabled[ulPin] = 1;
		}
		if (!TCChanEnabled[chNo]) {
			TC_Start(TC_INTERFACE, chNo);
			TCChanEnabled[chNo] = 1;
		}
		return;
	}

	// Default to digital write
	pinMode(ulPin, OUTPUT);
	if (ulValue < 128)
		digitalWrite(ulPin, LOW);
	else
		digitalWrite(ulPin, HIGH);
}

#ifdef __cplusplus
}
#endif
