My settings and use of the Arduino ADC are detailed here. Most of the information in these notes is abstracted from the latest SAM3X8E datasheet.

Many of the connections to the SAM3X8E are mulitplexed, and this is the case for the ADC inputs. However it is not necessary to program the PIO controller directly as enabling an ADC channel automatically connects the corresponding input pin to the ADC. On reset the ADC input pins are allocated as digital inputs with their pull-up resistors enabled, any circuit connected to these pins must allow for this so that no damage is incurred before the ADC channels are initialised. The pins can source up to 6mA and sink up to 3mA. The mapping of the Arduino pins to those of the SAM3X8E is given here; so, for example, Arduino pin A0 is connected to PA16, the SAM3X8E I/O pin for AD7.

The ADC has a number of registers that are used to control its operation. Some are read-only (RO), some are write-only (WO) and others are read-write (RW). I now detail how I setup these registers.

Control Register (WO, see section 43.7.1). This has just two one bit fields: SWRST which when set to one causes a software reset of the ADC and START which when set to one triggers a conversion. I will be using a timer to trigger the ADC at regular intervals and so the only relevant field will be SWRST which I can use to reset the ADC and put it in a known state. The status of the registers after a software reset is:

$\displaystyle \begin{array}{llr} \mbox{Mode Register} & \rm{ADC\_MR} & 0\\ \mbox{Channel Sequence Register 1} & \rm{ADC\_SEQR1} & 0\\ \mbox{Channel Sequence Register 2} & \rm{ADC\_SEQR2} & 0\\ \mbox{Channel Status Register} & \rm{ADC\_CHSR} & 0\\ \mbox{Last Converted Data Register} & \rm{ADC\_LCDR} & 0 \\ \mbox{Interrupt Mask Register} & \rm{ADC\_IMR} & 0\\ \mbox{Interrupt Status Register} & \rm{ADC\_ISR} & \rm{0x18000000}\\ \mbox{Overrun Status Register} & \rm{ADC\_OVER} & 0\\ \mbox{Extended Mode Register} & \rm{ADC\_EMR} & 0\\ \mbox{Compare Window Register} & \rm{ADC\_CWR} & 0\\ \mbox{Channel Gain Register } & \rm{ADC\_CGR} & 0\\ \mbox{Channel Offset Register} & \rm{ADC\_COR} & 0\\ \mbox{Channel Data Register 6} & \rm{ADC\_CDR[6]}\mbox{ (Arduino A1)} & 0 \\ \mbox{Channel Data Register 7} & \rm{ADC\_CDR[7]}\mbox{ (Arduino A0)} & 0 \\ \mbox{Analog Control Register} & \rm{ADC\_ACR} & \rm{0x101} \\ \mbox{Write Protect Mode Register} & \rm{ADC\_WPMR} & 0\\ \mbox{Write Protect Status Register} & \rm{ADC\_WPSR} & 0\\ \end{array}$

Notes:

1. The values shown here are obtained using a software reset directly after a system reset.
2. Testing the software reset after using analogRead() to read A0 or A1 (or both) shows that a software reset does not change the last converted data register, the interrupt status register or the channel data registers.
3. The value shown for the Interrupt Status Register is not the same as given in the data sheet, the bits that are set refer to DMA settings and are not relevant here.
4. The datasheet says that the Analog Control Register should have a value of 0x100, however the first bit is un-used, so the discrepancy seems irrelevant.

Mode Register (RW, see section 43.7.2). I plan to use one, or two, single ended inputs with the same gain and offset values and to use the 12-bit resolution setting. Also for the SDR experiments I will run continuously, although not in free-run mode, and so the sleep mode will be turned off. This determines the following fields of the Mode Register:

$\displaystyle \begin{array}{rcl} \rm{LOWRES} & = & 0 \mbox{\hspace{12pt}12-bit resolution} \\ \rm{SLEEP} & = & 0 \mbox{\hspace{12pt}Sleep mode off} \\ \rm{FWUP} & = & 0 \mbox{\hspace{12pt}Fast wake up - not relevant} \\ \rm{FREERUN} & = & 0 \mbox{\hspace{12pt}Triggered mode} \\ \rm{SETTLING} & = & 0 \mbox{\hspace{12pt}Settling time - not relevant} \\ \rm{ANACH} & = & 0 \mbox{\hspace{12pt}All channels use the same gain and offset} \\ \rm{TRACKTIM} & = & 0 \mbox{\hspace{12pt}Tracking time (see below)} \\ \rm{TRANSFER} & = & 1 \mbox{\hspace{12pt}Transfer time (see below)} \\ \rm{USEQ} & = & 0 \mbox{\hspace{12pt}Convert channels in numerical order} \end{array}$

The TRACKTIM and TRANSFER fields are set to the values given in the electrical characteristics section (45.7.2). The actual tracking time will be 15 ADC clock cycles and the frequency of the ADC clock will need to be adjusted to allow for the source impedance. The frequency of this clock is set by the PRESCAL field, with

$\displaystyle f_{ADC}=\frac{\rm{MCK}}{2(\rm{PRESCAL}+1)}$

where MCK is the master clock frequency (84MHz in this case). In the electrical characteristics section the limits for the ADC clock frequency are minimum 1MHz and maximum 22MHz and so the PRESCAL field must have values between 1 and 41.

As the sleep mode is not used, the startup delay only occurs at the beginning. The startup field, needs to be set to ensure that the tracking time for the first conversion is long enough. The startup times for the different field values are given in the datasheet. In fact, for my configuration this turns out to be largely irrelevant as, in this case, to allow for an error in the system, the datasheet says that the first 16 conversions after startup should be discarded (see section 49.1.4).

The TRGEN field is a one bit field which determines how the ADC is triggered. When set to zero the ADC can only be triggered by software (by setting the START bit in the control register). When set to one the ADC is triggered by hardware and the remaining field (TRGSEL) determines which hardware trigger is used. In this case the TRGEN bit can be used to start and stop the ADC without affecting the other settings.

In my experiments I will be using the TIOA output of timer channel 0 and this is represented by the ${\rm{ADC\_TRIG1}}$ value for the TRGSEL field.

Channel Sequence 1 Register and Channel Sequence 2 Register. These are used to enable the user to define the order in which channels are converted. I am not using this facility.

Channel Enable Register (WO, section 43.7.5). The first 16 bits of this register are used to select which channels are to be converted. Setting the corresponding bit to one enables the channel for conversion.

Channel Disable Register (WO, section 43.7.6). The first 16 bits of this register are used to disable channel conversions. Setting the corresponding bit to one disables the channel for conversion.

Channel Status Register (RO, section 43.7.7). The first 16 bits of this register are used to return the status of each of the channels. A zero in the corresponding bit position means that the channel is disabled, while a one means that the corresponding channel is enabled. The status of a channel depends on the latest update of the Channel Disable Register or the Channel Enable Register. Setting a channel bit position in one of these registers overrides what went before.

Last Converted Data Register (RO, section 43.7.8). This contains the last converted data value and its channel number (if the TAG option is set). I am not using this register.

Interrupt Enable Register (WO, section 43.7.9). The first 16 bits of this register are used to enable end of conversion interrupts on the corresponding channels. Setting the corresponding bit to one enables the interrupt. Other bits of this register are used for other interrupts, but I am not using these (at the moment).

Interrupt Disable Register (WO, section 43.7.10). Similarly the first 16 bits of this register are used to disable end of conversion interrupt from the corresponding channel. Setting the corresponding bit to one disables the interrupt. Other bits of this register are used for other interrupts, but I am not using these.

Interrupt Mask Register (RO, section 43.7.11). The bits of this register are used to return the status of each of the interrupts. A zero in the corresponding bit position means that the interrupt is disabled, while a one means that the corresponding interrupt is enabled. Whether an interrupt is enabled, or disabled, depends on the latest update of the Interrupt Enable or Interrupt Disable Register. Setting an interrupt bit position in one of these registers overrides what went before.

Interrupt Status Register (RO, section 43.7.12). The bits in this register indicate whether the corresponding interrupt is active. For end of conversion interrupts a zero indicates that the channel is disabled, or that a conversion on this channel is incomplete. A one indicates that a conversion on this channel is complete, reading the corresponding Channel Data Register clears this interrupt.

Overrun Status Register (RO, section 43.7.13). The first 16 bits in this register indicate whether there has been an overrun on the corresponding channel since the status register was last read.

Extended Mode Register and Compare Window Register. These are used when testing the converted values against given lower and upper thresholds. I am not using this facility.

Channel Gain Register (RW, section 43.7.16). This allows the gain for each channel to be adjusted. I am using the default value (0) which for single ended inputs gives a gain of 1.

Channel Offset Register (RW, section 43.7.17). This allows channel offsets to be set. For the moment I am using the default 0 values, no offset.

Channel Data Register[${\textrm{x}=0\ldots 15}$] When the conversion of a channel is completed the value is put into the corresponding CDR. It remains there until the next conversion of that channel.

Analog Control Register (RW, section 43.7.19). There are 2 fields in this register. One, TSON turns the temperature sensor on when it is set. The other, 2-bit field, IBCTL is the bias current control. In the electrical characteristics it says to set this to 00 if the sampling frequency is less than 500kHz and to set it to 01 when the sampling frequency is between 500kHz and 1MHz. In my programs the sampling frequency will always be less than 500kHz.

The remaining three registers can be used to write protect some of the ADC registers. I am not using this facility.