summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-07-24 16:23:31 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-07-24 16:23:31 -0600
commit8a6a9af27e061d79a719b415d86e7ac10c326e0f (patch)
tree3b08adfaf7c3f9833d42d96f8bfff49070e39cbc
parent6a9152b8c7acd23fa1e815b66330d272a8630a16 (diff)
downloadnuttx-8a6a9af27e061d79a719b415d86e7ac10c326e0f.tar.gz
nuttx-8a6a9af27e061d79a719b415d86e7ac10c326e0f.tar.bz2
nuttx-8a6a9af27e061d79a719b415d86e7ac10c326e0f.zip
Added burstmode ADC conversion mode, with CONFIG_ADC_BURSTMODE option in Kconfig. From Max
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_adc.c231
1 files changed, 223 insertions, 8 deletions
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_adc.c b/nuttx/arch/arm/src/lpc17xx/lpc17_adc.c
index 8dbee61fd..00bca0c44 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_adc.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_adc.c
@@ -158,6 +158,8 @@ static void adc_reset(FAR struct adc_dev_s *dev)
regval |= SYSCON_PCONP_PCADC;
putreg32(regval, LPC17_SYSCON_PCONP);
+ /* Power up before we access hardware */
+
putreg32(ADC_CR_PDN, LPC17_ADC_CR);
regval = getreg32(LPC17_SYSCON_PCLKSEL0);
@@ -165,39 +167,70 @@ static void adc_reset(FAR struct adc_dev_s *dev)
regval |= (SYSCON_PCLKSEL_CCLK8 << SYSCON_PCLKSEL0_ADC_SHIFT);
putreg32(regval, LPC17_SYSCON_PCLKSEL0);
+#ifdef CONFIG_ADC_BURSTMODE
+ clkdiv = LPC17_CCLK / 3 / 65 / priv->sps;
+
+//putreg32(0x04, LPC17_ADC_INTEN); /* Enable only last channel interrupt */
+ putreg32(0x100, LPC17_ADC_INTEN); /* Enable only global interrupt */
+
+ putreg32((priv->mask) | /* Select channels 0 to 7 on ADC0 */
+// (clkdiv) << 8) | /* CLKDIV = divisor to make the samples
+// * per second conversion rate */
+ ((32) << 8) | /* CLKDIV = divisor to make the faster
+ * conversion rate */
+ (0 << 16) | /* BURST = 0, BURST capture all selected
+ * channels */
+ (1 << 17) | /* Reserved bit = 0 */
+ (1 << 21) | /* PDN = 1, normal operation */
+ (1 << 26) | (0 << 25) | (0 << 24) | /* START = at MAT0 signal */
+ (1 << 27), /* EDGE = 1 (CAP/MAT signal rising
+ * trigger A/D conversion) */
+ LPC17_ADC_CR);
+
+#else /*CONFIG_ADC_BURSTMODE*/
+
clkdiv = LPC17_CCLK / 8 / 65 / priv->sps;
clkdiv <<= 8;
clkdiv &= 0xff00;
putreg32(ADC_CR_PDN | ADC_CR_BURST | clkdiv | priv->mask, LPC17_ADC_CR);
+#endif /*CONFIG_ADC_BURSTMODE*/
+
if ((priv->mask & 0x01) != 0)
{
lpc17_configgpio(GPIO_AD0p0);
}
+
if ((priv->mask & 0x02) != 0)
{
lpc17_configgpio(GPIO_AD0p1);
}
+
if ((priv->mask & 0x04) != 0)
{
lpc17_configgpio(GPIO_AD0p2);
}
+
if ((priv->mask & 0x08) != 0)
{
lpc17_configgpio(GPIO_AD0p3);
}
+
if ((priv->mask & 0x10) != 0)
{
lpc17_configgpio(GPIO_AD0p4);
}
+
if ((priv->mask & 0x20) != 0)
{
lpc17_configgpio(GPIO_AD0p5);
}
+
if ((priv->mask & 0x40) != 0)
{
lpc17_configgpio(GPIO_AD0p6);
}
+
if ((priv->mask & 0x80) != 0)
{
lpc17_configgpio(GPIO_AD0p7);
@@ -276,6 +309,7 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
if (enable)
{
+#ifndef CONFIG_ADC_BURSTMODE
#ifdef CONFIG_ADC_CHANLIST
/* Trigger interrupt at the end of conversion on the last A/D channel
* in the channel list.
@@ -288,6 +322,11 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
putreg32(ADC_INTEN_GLOBAL, LPC17_ADC_INTEN);
#endif
+#else /*CONFIG_ADC_BURSTMODE*/
+ /* Enable only global interrupt */
+
+ putreg32(0x100, LPC17_ADC_INTEN);
+#endif /*CONFIG_ADC_BURSTMODE*/
}
else
{
@@ -320,6 +359,7 @@ static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
static int adc_interrupt(int irq, void *context)
{
+#ifndef CONFIG_ADC_BURSTMODE
#ifdef CONFIG_ADC_CHANLIST
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_adcdev.ad_priv;
@@ -359,23 +399,198 @@ static int adc_interrupt(int irq, void *context)
unsigned char ch;
int32_t value;
- regval = getreg32(LPC17_ADC_GDR);
- ch = (regval >> 24) & 0x07;
- priv->buf[ch] += regval & 0xfff0;
+ regval = getreg32(LPC17_ADC_GDR);
+ ch = (regval >> 24) & 0x07;
+ priv->buf[ch] += regval & 0xfff0;
priv->count[ch]++;
if (priv->count[ch] >= CONFIG_ADC0_AVERAGE)
{
- value = priv->buf[ch] / priv->count[ch];
- value <<= 15;
+ value = priv->buf[ch] / priv->count[ch];
+ value <<= 15;
adc_receive(&g_adcdev,ch,value);
- priv->buf[ch] = 0;
- priv->count[ch] = 0;
+ priv->buf[ch] = 0;
+ priv->count[ch] = 0;
}
return OK;
#endif
+#else /*CONFIG_ADC_BURSTMODE*/
+
+ FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_adcdev.ad_priv;
+ volatile uint32_t regVal, regVal2, regVal3;
+
+//lpc17_gpiowrite(LPCXPRESSO_GPIO0_21, 1); /* Set pin P0.21 */
+
+ /* Teste si une interruption a bien eu lieu */
+
+ regVal2 = getreg32(LPC17_ADC_STAT); /* Read ADSTAT will clear the interrupt flag */
+ if ((regVal2) & (1<<16))
+ {
+ if ((priv->mask & 0x01) != 0)
+ {
+ regVal = getreg32(LPC17_ADC_DR0);
+#ifdef CONFIG_ADC_DIRECT_ACCESS
+ /* Store the data value plus the status bits */
+
+ ADC0Buffer0[0] = regVal;
+ ADC0IntDone = 1;
+#else /* CONFIG_ADC_DIRECT_ACCESS */
+#ifdef CONFIG_ADC_WORKER_THREAD
+ /* Store the data value plus the status bits */
+
+ ADC0Buffer0[0] = regVal;
+ ADC0IntDone = 1;
+
+#else /* CONFIG_ADC_WORKER_THREAD */
+ if ((regVal) & (1 << 31))
+ {
+ adc_receive(&g_adcdev, 0, (regVal >> 4) & 0xFFF);
+ }
+
+#endif /* CONFIG_ADC_WORKER_THREAD */
+#endif /* CONFIG_ADC_DIRECT_ACCESS */
+
+#ifdef CONFIG_ADC_DEBUG_DAC
+ /* Adjust the binary value to the lpc1768's register format (plus high
+ * speed profile in bit 16)
+ */
+
+// putreg32(((((regVal >> 4) & 0xFFF) << 6)| 0x10000) & 0xffff, LPC17_DAC_CR);
+#endif /*CONFIG_ADC_DEBUG_DAC*/
+ }
+
+ if ((priv->mask & 0x02) != 0)
+ {
+ regVal = getreg32(LPC17_ADC_DR1);
+
+#ifdef CONFIG_ADC_DIRECT_ACCESS
+ /* Store the data value plus the status bits */
+
+ ADC1Buffer0[0] = regVal;
+ ADC0IntDone = 1;
+
+#else /*CONFIG_ADC_DIRECT_ACCESS*/
+#ifdef CONFIG_ADC_WORKER_THREAD
+ /* Store the data value plus the status bits */
+
+ ADC1Buffer0[0] = regVal;
+ ADC0IntDone = 1;
+
+#else /*CONFIG_ADC_WORKER_THREAD*/
+ if ((regVal) & (1 << 31))
+ {
+ adc_receive(&g_adcdev, 1, (regVal >> 4) & 0xFFF);
+ }
+
+#endif /*CONFIG_ADC_WORKER_THREAD*/
+#endif /*CONFIG_ADC_DIRECT_ACCESS*/
+ }
+
+ if ((priv->mask & 0x04) != 0)
+ {
+ regVal = getreg32(LPC17_ADC_DR2);
+
+#ifdef CONFIG_ADC_DIRECT_ACCESS
+ /* Store the data value plus the status bits */
+
+ ADC2Buffer0[0] = regVal;
+ ADC0IntDone = 1;
+
+#else /*CONFIG_ADC_DIRECT_ACCESS*/
+#ifdef CONFIG_ADC_WORKER_THREAD
+ /* Store the data value plus the status bits */
+
+ ADC2Buffer0[0] = regVal;
+ ADC0IntDone = 1;
+
+#else /*CONFIG_ADC_WORKER_THREAD*/
+ if ((regVal) & (1 << 31))
+ {
+ adc_receive(&g_adcdev, 2, (regVal >> 4) & 0xFFF);
+ }
+
+#endif /*CONFIG_ADC_WORKER_THREAD*/
+#endif /*CONFIG_ADC_DIRECT_ACCESS*/
+ }
+
+#ifdef CONFIG_ADC_WORKER_THREAD
+ /* Store the data value plus the status bits */
+
+ ADC2Buffer0[0] = regVal;
+ ADC0IntDone = 1;
+
+#else /* CONFIG_ADC_WORKER_THREAD */
+ if ((priv->mask & 0x08) != 0)
+ {
+ regVal = getreg32(LPC17_ADC_DR3);
+ if ((regVal) & (1 << 31))
+ {
+ adc_receive(&g_adcdev, 3, (regVal >> 4) & 0xFFF);
+ }
+ }
+
+ if ((priv->mask & 0x10) != 0)
+ {
+ regVal = getreg32(LPC17_ADC_DR4);
+ if ((regVal) & (1 << 31))
+ {
+ adc_receive(&g_adcdev, 4, (regVal >> 4) & 0xFFF);
+ }
+ }
+
+ if ((priv->mask & 0x20) != 0)
+ {
+ regVal = getreg32(LPC17_ADC_DR5);
+ if ((regVal) & (1 << 31))
+ {
+ adc_receive(&g_adcdev, 5, (regVal >> 4) & 0xFFF);
+ }
+ }
+
+ if ((priv->mask & 0x40) != 0)
+ {
+ regVal = getreg32(LPC17_ADC_DR6);
+ if ((regVal) & (1 << 31))
+ {
+ adc_receive(&g_adcdev, 6, (regVal >> 4) & 0xFFF);
+ }
+ }
+
+ if ((priv->mask & 0x80) != 0)
+ {
+ regVal = getreg32(LPC17_ADC_DR7);
+ if ((regVal) & (1 << 31))
+ {
+ adc_receive(&g_adcdev, 7, (regVal >> 4) & 0xFFF);
+ }
+ }
+
+#endif /*CONFIG_ADC_WORKER_THREAD*/
+#ifdef CONFIG_ADC_WORKER_THREAD
+ if (ADC0IntDone == 1)
+ {
+ work_queue(HPWORK, &priv->irqwork, (worker_t)adc_irqworker, (FAR void *)priv, 0);
+ }
+
+#endif /*CONFIG_ADC_WORKER_THREAD*/
+
+ regVal3 = getreg32(LPC17_ADC_GDR); /* Read ADGDR clear the DONE and OVERRUN bits */
+ putreg32((priv->mask) | /* Select channels 0 to 7 on ADC0 */
+ ((32) << 8) | /* CLKDIV = 16 */
+ (0 << 16) | /* BURST = 1, BURST capture all selected channels */
+ (1 << 17) | /* Reserved bit = 0 */
+ (1 << 21) | /* PDN = 1, normal operation */
+ (1 << 26) | (0 << 25) | (0 << 24) | /* START = at MAT0 signal */
+ (1 << 27), /* EDGE = 1 (CAP/MAT signal rising trigger A/D
+ * conversion) */
+ LPC17_ADC_CR);
+
+//lpc17_gpiowrite(LPCXPRESSO_GPIO0_21, 0); /* Reset pin P0.21 */
+//irqrestore(saved_state);
+ return OK;
+#endif /*CONFIG_ADC_BURSTMODE*/
}
/****************************************************************************
@@ -389,7 +604,7 @@ static int adc_interrupt(int irq, void *context)
* Initialize the adc
*
* Returned Value:
- * Valid can device structure reference on succcess; a NULL on failure
+ * Valid can device structure reference on success; a NULL on failure
*
****************************************************************************/