Jump to content
PTB

Stellaris fast analog reads

Recommended Posts

@JKabat @Rei Vilo

 

Hi John and Rei,

 

All that HWREG and Bit Shifting is beyond my current experience level. I'm getting seriously confused whenever I try to understand the syntax of it all. I'm Sure one day it will make sense.

 

One thing I did get a handle on was John's Logic of splitting the command in to 2 separate routines. So in the spirit of "fast_analogInit" and "fast_analogRead" I split the original "analogRead" command

into a not so fast version set.

 

"brisk_analogInit" and "brisk_analogRead" :)

///**************************************************************************
///
///                                   Brisk Analog Init Routine
///
///**************************************************************************

  uint16_t brisk_analogInit(uint8_t pin) {
    uint8_t port = digitalPinToPort(pin);
    uint32_t channel = digitalPinToADCIn(pin);
    if (pin == NOT_ON_ADC) { //invalid ADC pin
        return 0;
    }
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    ROM_GPIOPinTypeADC((uint32_t) portBASERegister(port), digitalPinToBitMask(pin));
    ROM_ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 3, 0, channel | ADC_CTL_IE | ADC_CTL_END);
    ROM_ADCSequenceEnable(ADC0_BASE, 3);
    return(1);
}


///**************************************************************************
///
///                                   Brisk Analog Read Routine
///
///**************************************************************************
    
    
uint16_t brisk_analogRead(void) {
    uint16_t value[1];
    ROM_ADCIntClear(ADC0_BASE, 3);
    ROM_ADCProcessorTrigger(ADC0_BASE, 3);
    while(!ROM_ADCIntStatus(ADC0_BASE, 3, false))
    {
    }
	ROM_ADCIntClear(ADC0_BASE, 3);
    ROM_ADCSequenceDataGet(ADC0_BASE, 3, (unsigned long*) value);
    return value[0];
}

These "brisk" routines were then called instead of the "fast" routines and it worked and there was a noticeable improvement over the normal analog read.

Number of Samples : 255

Sample Starttime : 49989005

Sample Endtime : 49991704

Sample Array Set Duration time in microseconds  : 2699


That's 1 reading every ~10.6 microseconds instead of one every ~14.4 microseconds. Which seems to be about a 25% improvement.

 

So its better, but I would love to see what the "fast" routines can do.

 

Cheers

 

PTB

Share this post


Link to post
Share on other sites

In France, we use the same logic but from Le Discours de la méthode (1637) by Descartes, more precisely the second rule:  

 

 

 

Diviser chacune des difficultés en autant de parcelles qu'il se pourrait et qu'il serait requis pour les mieux résoudre. 

— Discours de la Méthode, 1637

 

or in English

 

To divide each of the difficulties under examination into as many parts as possible, and as might be necessary for its adequate solution.
 

—Discourse on the Method, 1637

 

One can't imagine how modern and well suited for programming Descartes precepts are :)

Share this post


Link to post
Share on other sites

@@PTB @@Rei Vilo

 

Possible fix for fast_analog read:

 

Replace:

while (!(HWREG(ADC0_BASE + ADC_O_ISC) & (0x10001 << SEQUENCER))) {}

 

 

with:

while (!(HWREG(ADC0_BASE + ADC_O_RIS) & (0x10000 | (1 << SEQUENCE))) {}


This MAY fix the problem! 

Regards

John

Share this post


Link to post
Share on other sites

@JKabat @Rei Vilo

 

Hi John,

 

That appears to have fixed that line. Small typo... just had to add the R to SEQUENCE.

 

It is still hanging... but further down the code.

 

I sprinkled a heap of "Serial.println"s through the code as a temporary tracing measure. It appears to run the whole code but wont exit the subroutine.

 

Edit: Ignore this bit..... works ok with the equivalent "brisk" version posted earlier

Is that because the function declaration is a void and it is trying to return a value.    =>  uint16_t fast_analogRead(void) {

??

 

Here is the output from the Serial Monitor

 

 


1

2

3

4

5

6

7

8

9

10

11

12

13

11

12

13

11

12

13

11

12

13

11

12

13

11

12

13

11

12

13

11

12

13

14

0

 

And here is the code which shows where those printlines are.......

 

// 
// LM4F_ADC 
//
// Description of the project
// Developed with [embedXcode](http://embedXcode.weebly.com)
// 
// Author	 	Rei VILO
// 				Rei Vilo
//
// Date			21/07/13 09:42
// Version		<#version#>
// 
// Copyright	(c) Rei VILO, 2013
// Licence		CC = BY NC SA
//
// See			ReadMe.txt for references
//


// Core library for code-sense
#if defined(WIRING) // Wiring specific
#include "Wiring.h"
#elif defined(MAPLE_IDE) // Maple specific
#include "WProgram.h"   
#elif defined(MPIDE) // chipKIT specific
#include "WProgram.h"
#elif defined(DIGISPARK) // Digispark specific
#include "Arduino.h"
#elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific
#include "Energia.h"
#elif defined(CORE_TEENSY) // Teensy specific
#include "WProgram.h"
#elif defined(ARDUINO) && (ARDUINO >= 100) // Arduino 1.0 and 1.5 specific
#include "Arduino.h"
#elif defined(ARDUINO) && (ARDUINO < 100) // Arduino 23 specific
#include "WProgram.h"
#else // error
#error Platform not defined
#endif

// Include application, user and local libraries

// Define variables and constants
///
/// @file	Fast_Analog_Read.ino
/// @brief	Main sketch
///
/// @details	Fast Analog Read Investigations for Stellaris LM4F
///

//
// Stellaris Pin Assignments
// =========================
//PE_3    //Sensor Analog Read
//PA_5    //Trigger Analog Signal Pulse
//PF_4    //Push Button to Start

//
// Libraries
// =========
#include "Energia.h"
#include "SPI.h"
#include "inc/lm4f120h5qr.h"


#include "inc/hw_adc.h"
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"

#include "driverlib/adc.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"



// Constants from adc.c
#define ADC_SEQ                 (ADC_O_SSMUX0)
#define ADC_SEQ_STEP            (ADC_O_SSMUX1 - ADC_O_SSMUX0)
#define ADC_SSMUX               (ADC_O_SSMUX0 - ADC_O_SSMUX0)
#define ADC_SSEMUX              (ADC_O_SSEMUX0 - ADC_O_SSMUX0)
#define ADC_SSCTL               (ADC_O_SSCTL0 - ADC_O_SSMUX0)
#define ADC_SSFIFO              (ADC_O_SSFIFO0 - ADC_O_SSMUX0)
#define ADC_SSFSTAT             (ADC_O_SSFSTAT0 - ADC_O_SSMUX0)
#define ADC_SSOP                (ADC_O_SSOP0 - ADC_O_SSMUX0)
#define ADC_SSDC                (ADC_O_SSDC0 - ADC_O_SSMUX0)


//
// Global Constants
// ================
const byte SampleQty = 255;               // number of samples  
const uint16_t buttonPin = PUSH1;         // the number of the pushbutton pin
const uint16_t ledPin =  GREEN_LED;       // the number of the LED pin
const uint16_t TriggerPin = PA_5;         // Analog Signal Trigger connected to digital pin PA_5


//
// Global Variables
// ================

uint16_t SampleTest;
uint16_t buttonState = 0;         // variable for reading the pushbutton status
uint16_t Sample[SampleQty];       // Array variable to store the value coming from the sensor
unsigned long SampleStartTime;
unsigned long SampleEndTime;
unsigned long SampleDuration;


//
// JKabat
// ================
unsigned long faBase;
uint16_t faMask;
#define SEQUENCER   3


// Prototypes
  uint16_t fast_analogInit(uint8_t pin);
  uint16_t fast_analogRead(void);


///**************************************************************************
///
///                                   Setup code
///
///**************************************************************************
void setup() {
Serial.begin(9600) ;               //Debugging initialize the serial communication:
pinMode(ledPin, OUTPUT);           // initialize the LED pin as an output:    
pinMode(buttonPin, INPUT_PULLUP);  // initialize the pushbutton pin as an input:
pinMode(TriggerPin, OUTPUT);       // initialize the Trigger pin as an output:    
}//end setup

///**************************************************************************
///
///                                   Loop code
///
///**************************************************************************
void loop() {
buttonState = digitalRead(buttonPin);  // read the state of the pushbutton value:
if (buttonState == LOW) {     
digitalWrite(ledPin, HIGH);            // turn LED on:
Serial.println("1");
fast_analogInit(PE_3);                 // JKabat
Serial.println("2");
SampleStartTime = micros();
digitalWrite(TriggerPin, HIGH);        // Start the Analog Signal 
for (uint16_t i=0;i<SampleQty;i++)
 {
//  Sample[i]=analogRead(PE_3);                                  // Original Analog Read
Serial.println("3");
Sample[i] = fast_analogRead();                                   // JKabat
Serial.println("fast_analogRead call completed");
Serial.println(Sample[i]);
 } 
SampleEndTime = micros();
//Dump results to serial monitor
for (uint16_t i=0;i<SampleQty;i++)
{
  Serial.println(Sample[i]);
} 
Serial.print("Number of Samples : ");
Serial.println(SampleQty);
Serial.print("Sample Starttime : ");
Serial.println(SampleStartTime);
Serial.print("Sample Endtime : ");
Serial.println(SampleEndTime);
SampleDuration = SampleEndTime - SampleStartTime;
Serial.print("Sample Array Set Duration time in microseconds  : ");
Serial.println(SampleDuration);
}// end if 
delay(1000);
digitalWrite(ledPin, LOW);  // turn LED off:
}//end loop


///**************************************************************************
///
///                                   Fast Analog Read Routine
///
///**************************************************************************
uint16_t fast_analogRead(void) {
    uint32_t value[1];
    
    unsigned long *pulBuffer = &value[0];
    unsigned long ulCount;
    unsigned long ulBase = faBase;
    
    Serial.println("4");
//    ROM_ADCIntClear(ADC0_BASE, 3);
//
// Clear the interrupt.
//
    HWREG(ADC0_BASE + ADC_O_ISC) = 1 << SEQUENCER;
    Serial.println("5");    
//    ROM_ADCProcessorTrigger(ADC0_BASE, 3);
//
// Generate a processor trigger for this sample sequence.
//
    HWREG(ADC0_BASE + ADC_O_PSSI) |= ((SEQUENCER & 0xffff0000) | 
                                         (1 << (SEQUENCER & 0xf)));
     Serial.println("6"); 
//    while (!ROM_ADCIntStatus(ADC0_BASE, 3, false)) {}
while (!(HWREG(ADC0_BASE + ADC_O_RIS) & (0x10000 | (1 << SEQUENCER)))) {}



//    ROM_ADCIntClear(ADC0_BASE, 3);
//
// Clear the interrupt.
//
 Serial.println("7"); 
    HWREG(ADC0_BASE + ADC_O_ISC) = 1 << SEQUENCER;
//    ROM_ADCSequenceDataGet(ADC0_BASE, 3, (unsigned long *)value);
    
    //
    // Get the offset of the sequence to be read.
    //
     Serial.println("8"); 
    ulBase += ADC_SEQ + (ADC_SEQ_STEP * SEQUENCER);
    
    //
    // Read samples from the FIFO until it is empty.
    //
     Serial.println("9"); 
    ulCount = 0;
     Serial.println("10"); 
    while (!(HWREG(ulBase + ADC_SSFSTAT) & ADC_SSFSTAT0_EMPTY) && (ulCount < 8)) {
           Serial.println("11"); 
        //
        // Read the FIFO and copy it to the destination.
        //
        *pulBuffer++ = HWREG(ulBase + ADC_SSFIFO);
             Serial.println("12"); 
        
        //
        // Increment the count of samples read.
        //
        ulCount++;
             Serial.println("13"); 
    }
    Serial.println("14"); 
    Serial.println(value[0]); 
    return value[0];
}    

///**************************************************************************
///
///                                   Fast Analog Init Routine
///
///**************************************************************************
  uint16_t fast_analogInit(uint8_t pin) {
    uint8_t port = digitalPinToPort(pin);
    uint16_t value[1];
    uint32_t channel = digitalPinToADCIn(pin);
    if (pin == NOT_ON_ADC) {                    //invalid ADC pin
        return(0);
    }
    faBase = (uint32_t)portBASERegister(port);
    faMask = digitalPinToBitMask(pin);
    
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    ROM_GPIOPinTypeADC((uint32_t)portBASERegister(port), digitalPinToBitMask(pin));
    ROM_ADCSequenceConfigure(ADC0_BASE, SEQUENCER, ADC_TRIGGER_PROCESSOR, 0);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 0, channel | ADC_CTL_IE | ADC_CTL_END);
    ROM_ADCSequenceEnable(ADC0_BASE, SEQUENCER);
    
    
    return(1);
}

There may be another problem at play as well. When I run the routine with the normal analogread it returns ~ 114 as the reading.

This is currently returning (nearly returning) zero as can be seen by the last successful printline listed.

 

I'm going to do some more testing. It seems to be going in the right direction though.

 

Cheers

 

PTB

Share this post


Link to post
Share on other sites

@@PTB,

 

Just some more fracking errors on my part. :rolleyes:  What happened is I forgot to change ulbase to ADC0_BASE as ulBase is something else. It was reading the wrong device (gpio) and returning the 0 that it read. The void is not the problem as it returns uint16_t. I will say that you seem to be getting it. The debug is exactly what I do for a quick and dirty test.

 

That is what happens when you do things on the fly. I currently don't have a test board as all mine are in use.  I am waiting for the new Tiva boards as I need USB OTG and/or host capability to talk to the face (android tablet) on my robot.

 

Change from:

while (!(HWREG(ulBase + ADC_SSFSTAT) & ADC_SSFSTAT0_EMPTY) && (ulCount < 8)) {
Serial.println("11");
//
// Read the FIFO and copy it to the destination.
//
*pulBuffer++ = HWREG(ulBase + ADC_SSFIFO);
Serial.println("12");

 

to:

while (!(HWREG(ADC0_BASE + ADC_SSFSTAT) & ADC_SSFSTAT0_EMPTY) && (ulCount < 8)) {
Serial.println("11");
//
// Read the FIFO and copy it to the destination.
//
*pulBuffer++ = HWREG(ADC0_BASE + ADC_SSFIFO);
Serial.println("12");

 

 

Regards

John

Share this post


Link to post
Share on other sites

@JKabat @Rei Vilo

 

No worries ;). Very hard to test code without a platform.

 

Still no worky. I am wondering whether pulBuffer needs to be fed into value[0] somehow.

I don't think value[0] was translated over.

 

I think that might be it. If not pulBuffer.... I suspect some other variable needs to feed it.

 

Cheers

 

PTB

 

p.s. adding these lines to the end printed the following

Serial.println(ulCount);Serial.println(ulBase);Serial.println(*pulBuffer);
810738894400

Share this post


Link to post
Share on other sites

@@PTB,

 

I begin to see where I erred! I forgot to include the sequencer in the read of the fifo. :wacko:  The clue to this was the ucount was 8 not 1. this indicates the we were reading an 8 deep FIFO not a single one.  (Sequencer 0) Also since value is only one entry were were overwriting something following it. That is why it never returned!

 

So one more fix:

change value to:

   uint16_t value[8];

just to be safe.

 

change the end as follows:

    //    // Get the offset of the sequence to be read.    //    ulBase = ADC0_BASE + (ADC_SEQ + (ADC_SEQ_STEP * SEQUENCER));    //    // Read samples from the FIFO until it is empty.    //    ulCount = 0;    while(!(HWREG(ulBase + ADC_SSFSTAT) & ADC_SSFSTAT0_EMPTY) && (ulCount < 8))    {        //        // Read the FIFO and copy it to the destination.        //        value[ulcount] = HWREG(ulBase + ADC_SSFIFO);        //        // Increment the count of samples read.        //        ulCount++;    }    return(value[0];

Share this post


Link to post
Share on other sites

@JKabat @Rei Vilo

John,

 

That has done the trick.!!! Good Job. Not quite the speed I was hoping for but it compiles, runs and has added a slight further speed boost.

I will clean up all the detritus through the code before I post latest. Hopefully later tonight.

 

I used "uint32_t value[8];" instead of "uint16_t value[8];" as it wouldn't compile otherwise. Also there was one instance of "ulcount" instead of "ulCount".

 

The expected readings appear to be correct and here's the results........

Number of Samples : 255
Sample Starttime : 12000006
Sample Endtime : 12002462
Sample Array Set Duration time in microseconds  : 2456


 1 Sample every ~9.6 microseconds. By my thinking about a 33% boost over the normal analogread.

 

Great Work !!!!! B)

 

Cheers

 

PTB

 

PS. Would a different FIFO (1 deep only) give a nice boost. Is that feasible or am I talking through my hat.

 

Share this post


Link to post
Share on other sites

And Here's the Code

// 
// LM4F_ADC 
//
// Description of the project
// Developed with [embedXcode](http://embedXcode.weebly.com)
// 
// Author	 	Rei VILO
// 				Rei Vilo
//
// Date			21/07/13 09:42
// Version		<#version#>
// 
// Copyright	(c) Rei VILO, 2013
// Licence		CC = BY NC SA
//
// See			ReadMe.txt for references
//


// Core library for code-sense
#if defined(WIRING) // Wiring specific
#include "Wiring.h"
#elif defined(MAPLE_IDE) // Maple specific
#include "WProgram.h"   
#elif defined(MPIDE) // chipKIT specific
#include "WProgram.h"
#elif defined(DIGISPARK) // Digispark specific
#include "Arduino.h"
#elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific
#include "Energia.h"
#elif defined(CORE_TEENSY) // Teensy specific
#include "WProgram.h"
#elif defined(ARDUINO) && (ARDUINO >= 100) // Arduino 1.0 and 1.5 specific
#include "Arduino.h"
#elif defined(ARDUINO) && (ARDUINO < 100) // Arduino 23 specific
#include "WProgram.h"
#else // error
#error Platform not defined
#endif

// Include application, user and local libraries

// Define variables and constants
///
/// @file	Fast_Analog_Read.ino
/// @brief	Main sketch
///
/// @details	Fast Analog Read Investigations for Stellaris LM4F
///

//
// Stellaris Pin Assignments
// =========================
//PE_3    //Sensor Analog Read
//PA_5    //Trigger Analog Signal Pulse
//PF_4    //Push Button to Start

//
// Libraries
// =========
#include "Energia.h"
#include "SPI.h"
#include "inc/lm4f120h5qr.h"


#include "inc/hw_adc.h"
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"

#include "driverlib/adc.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"



// Constants from adc.c
#define ADC_SEQ                 (ADC_O_SSMUX0)
#define ADC_SEQ_STEP            (ADC_O_SSMUX1 - ADC_O_SSMUX0)
#define ADC_SSMUX               (ADC_O_SSMUX0 - ADC_O_SSMUX0)
#define ADC_SSEMUX              (ADC_O_SSEMUX0 - ADC_O_SSMUX0)
#define ADC_SSCTL               (ADC_O_SSCTL0 - ADC_O_SSMUX0)
#define ADC_SSFIFO              (ADC_O_SSFIFO0 - ADC_O_SSMUX0)
#define ADC_SSFSTAT             (ADC_O_SSFSTAT0 - ADC_O_SSMUX0)
#define ADC_SSOP                (ADC_O_SSOP0 - ADC_O_SSMUX0)
#define ADC_SSDC                (ADC_O_SSDC0 - ADC_O_SSMUX0)

#define SEQUENCER   3


//
// Global Constants
// ================
const byte SampleQty = 255;               // number of samples  
const uint16_t buttonPin = PUSH1;         // the number of the pushbutton pin
const uint16_t ledPin =  GREEN_LED;       // the number of the LED pin
const uint16_t TriggerPin = PA_5;         // Analog Signal Trigger connected to digital pin PA_5


//
// Global Variables
// ================

uint16_t SampleTest;
uint16_t buttonState = 0;         // variable for reading the pushbutton status
uint16_t Sample[SampleQty];       // Array variable to store the value coming from the sensor
unsigned long SampleStartTime;
unsigned long SampleEndTime;
unsigned long SampleDuration;

unsigned long faBase;
uint16_t faMask;

//
// Prototypes
// ==========
  uint16_t fast_analogInit(uint8_t pin);
  uint16_t fast_analogRead(void);


///**************************************************************************
///
///                                   Setup code
///
///**************************************************************************
void setup() {
Serial.begin(9600) ;               //Debugging initialize the serial communication:
pinMode(ledPin, OUTPUT);           // initialize the LED pin as an output:    
pinMode(buttonPin, INPUT_PULLUP);  // initialize the pushbutton pin as an input:
pinMode(TriggerPin, OUTPUT);       // initialize the Trigger pin as an output:    
}//end setup

///**************************************************************************
///
///                                   Loop code
///
///**************************************************************************
void loop() {
buttonState = digitalRead(buttonPin);  // read the state of the pushbutton value:
if (buttonState == LOW) {     
digitalWrite(ledPin, HIGH);            // turn LED on:
fast_analogInit(PE_3);                 // JKabat
SampleStartTime = micros();
digitalWrite(TriggerPin, HIGH);        // Start the Analog Signal 
for (uint16_t i=0;i<SampleQty;i++)
 {
//  Sample[i]=analogRead(PE_3);                                  // Original Analog Read
Sample[i] = fast_analogRead();                                   // JKabat
 } 
SampleEndTime = micros();
//Dump results to serial monitor
for (uint16_t i=0;i<SampleQty;i++)
{
  Serial.println(Sample[i]);
} 
Serial.print("Number of Samples : ");
Serial.println(SampleQty);
Serial.print("Sample Starttime : ");
Serial.println(SampleStartTime);
Serial.print("Sample Endtime : ");
Serial.println(SampleEndTime);
SampleDuration = SampleEndTime - SampleStartTime;
Serial.print("Sample Array Set Duration time in microseconds  : ");
Serial.println(SampleDuration);
}// end if 
delay(1000);
digitalWrite(ledPin, LOW);  // turn LED off:
}//end loop


///**************************************************************************
///
///                                   Fast Analog Read Routine
///
///**************************************************************************
uint16_t fast_analogRead(void) {
    uint32_t value[8];
    unsigned long *pulBuffer = &value[0];
    unsigned long ulCount;
    unsigned long ulBase = faBase;
    HWREG(ADC0_BASE + ADC_O_ISC) = 1 << SEQUENCER;
    HWREG(ADC0_BASE + ADC_O_PSSI) |= ((SEQUENCER & 0xffff0000) | (1 << (SEQUENCER & 0xf)));
    while (!(HWREG(ADC0_BASE + ADC_O_RIS) & (0x10000 | (1 << SEQUENCER)))) {}
    HWREG(ADC0_BASE + ADC_O_ISC) = 1 << SEQUENCER;
    ulBase = ADC0_BASE + (ADC_SEQ + (ADC_SEQ_STEP * SEQUENCER));
    ulCount = 0;
    while(!(HWREG(ulBase + ADC_SSFSTAT) & ADC_SSFSTAT0_EMPTY) && (ulCount < 8)) {
    value[ulCount] = HWREG(ulBase + ADC_SSFIFO);
    ulCount++;
    }
    return value[0];
}    

///**************************************************************************
///
///                                   Fast Analog Init Routine
///
///**************************************************************************
    uint16_t fast_analogInit(uint8_t pin) {
    uint8_t port = digitalPinToPort(pin);
    uint16_t value[1];
    uint32_t channel = digitalPinToADCIn(pin);
    if (pin == NOT_ON_ADC) {                    //invalid ADC pin
        return(0);
    }
    faBase = (uint32_t)portBASERegister(port);
    faMask = digitalPinToBitMask(pin);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    ROM_GPIOPinTypeADC((uint32_t)portBASERegister(port), digitalPinToBitMask(pin));
    ROM_ADCSequenceConfigure(ADC0_BASE, SEQUENCER, ADC_TRIGGER_PROCESSOR, 0);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 0, channel | ADC_CTL_IE | ADC_CTL_END);
    ROM_ADCSequenceEnable(ADC0_BASE, SEQUENCER);
    return(1);
}

Cheers

 

PTB

Share this post


Link to post
Share on other sites

This is my results:

Number of Samples : 255                                               
Sample Starttime : 378625230                                          
Sample Endtime : 378625913                                            
Sample Array Set Duration time in microseconds  : 683

1 Sample every ~2.68 microseconds :D

 

driverlib/sysctl.h - have function for ADC SPEED:

SysCtlADCSpeedSet(unsigned long ulSpeed)

 

available value:

#define SYSCTL_ADCSPEED_1MSPS   0x00000F00  // 1,000,000 samples per second
#define SYSCTL_ADCSPEED_500KSPS 0x00000A00  // 500,000 samples per second
#define SYSCTL_ADCSPEED_250KSPS 0x00000500  // 250,000 samples per second
#define SYSCTL_ADCSPEED_125KSPS 0x00000000  // 125,000 samples per second

Default is: SYSCTL_ADCSPEED_125KSPS 0x00000000 // 125,000 samples per second

 

so...You must add a one line:

ROM_SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS);

before return(1);

in fast_analogInit(uint8_t pin):

    ...
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 0, channel | ADC_CTL_IE | ADC_CTL_END);
    ROM_ADCSequenceEnable(ADC0_BASE, SEQUENCER);

    ROM_SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS);
    
    return(1);
}

Share this post


Link to post
Share on other sites

@@reaper7,

 

That is what I was going to suggest. Just overloaded here a work today.

 

@@PTB

one thing you may want to do after applying @@reaper7s fix is to place the code for fastAnalogRead in place of the call.  Anlternativly you should move the read and init routines up befor loop and place the __inline__ attribute on them.  Sorry I am at work preparing for a trip and am not sure of the exact format. If you copy the code in place of fast... assign the result to sample[i++]= HWREG(ulBase + ADC_SSFIFO);  in place of value[ulcount]. 

If you switch to another sequencer (o has an 8 deep fifo) this will handle the results automatically. You may have to modify some setting in fastAdcInit(pin) to get multiple reads.

 

update:

Use sequencer 0.

 

I am not sure if all 8 steps need to be configured but you may need to add the following to init:

ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 0, channel | ADC_CTL_IE );

ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 1, channel | ADC_CTL_IE );

ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 2, channel | ADC_CTL_IE );

ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 3, channel | ADC_CTL_IE);

ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 4, channel | ADC_CTL_IE);

ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 5, channel | ADC_CTL_IE);

ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 6, channel | ADC_CTL_IE);

ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 7, channel | ADC_CTL_IE | ADC_CTL_END);

 

(late edit: You may (or may not) neet to remove the" | ACD_CTL_IE" from all but the last entry. Only use this for SEQUENCER 0)

 

 

Use at your own risk as I am unable to test this.

Edited by JKabat

Share this post


Link to post
Share on other sites

@@jkabat @@Rei Vilo @@reaper7

 

This speed is getting very close to what i was hoping. Way cool.

Unfortunately I think its going to be a day or 2 before I can have a further play with this.

 

A library for this would be great. I was kind of hoping that would come about.

 

Great job guys. My head is still spinning from this badboy.

I've learnt a lot in this thread but my comprehension of it is still pretty hazy.

 

Cheers

 

PTB

Share this post


Link to post
Share on other sites

@JKabat @Rei Vilo @reaper7

 

I dunno John... Its still 3 microseconds too slow. :lol:

Sensational ! You definitely appear to know your stuff.

Number of Samples : 255
Sample Starttime : 11000011
Sample Endtime : 11000269
Sample Array Set Duration time in microseconds  : 258

I also tried your "Late Edit" (Complete with disclaimer) ;)  but that slowed it down so I took it back out.

Number of Samples : 255
Sample Starttime : 27725011
Sample Endtime : 27727786
Sample Array Set Duration time in microseconds  : 2775

I did a little more housekeeping taking out some comments and unused defines and faMask as it appears to not be used.

 

Latest Code Here.....

// 
// LM4F_ADC 
// A Stellarisiti Collaborative effort 
// JKabat, Rei Vilo, reaper7, PTB.
//

// Include application, user and local libraries

// Define variables and constants
///
/// @file	Fast_Analog_Read.ino
/// @brief	Main sketch
///
/// @details	Fast Analog Read Investigations for Stellaris LM4F
///

//
// Stellaris Pin Assignments
// =========================
//PE_3    //Sensor Analog Read
//PA_5    //Trigger Analog Signal Pulse
//PF_4    //Push Button to Start

//
// Libraries
// =========
#include "Energia.h"
#include "SPI.h"
#include "inc/lm4f120h5qr.h"


#include "inc/hw_adc.h"
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"

#include "driverlib/adc.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"


//
// Constants from adc.c
// ====================
#define ADC_SEQ                 (ADC_O_SSMUX0)
#define ADC_SEQ_STEP            (ADC_O_SSMUX1 - ADC_O_SSMUX0)
#define ADC_SSFIFO              (ADC_O_SSFIFO0 - ADC_O_SSMUX0)
#define ADC_SSFSTAT             (ADC_O_SSFSTAT0 - ADC_O_SSMUX0)

#define SEQUENCER   0


//
// Global Constants
// ================
const byte SampleQty = 255;               // number of samples  
const uint16_t buttonPin = PUSH1;         // the number of the pushbutton pin
const uint16_t ledPin =  GREEN_LED;       // the number of the LED pin
const uint16_t TriggerPin = PA_5;         // Analog Signal Trigger connected to digital pin PA_5


//
// Global Variables
// ================

uint16_t SampleTest;
uint16_t buttonState = 0;         // variable for reading the pushbutton status
uint16_t Sample[SampleQty];       // Array variable to store the value coming from the sensor
unsigned long SampleStartTime;
unsigned long SampleEndTime;
unsigned long SampleDuration;

unsigned long faBase;

//
// Prototypes
// ==========
  uint16_t fast_analogInit(uint8_t pin);
  uint16_t fast_analogRead(void);


///**************************************************************************
///
///                                   Setup code
///
///**************************************************************************
void setup() {
Serial.begin(9600) ;               //Debugging initialize the serial communication:
pinMode(ledPin, OUTPUT);           // initialize the LED pin as an output:    
pinMode(buttonPin, INPUT_PULLUP);  // initialize the pushbutton pin as an input:
pinMode(TriggerPin, OUTPUT);       // initialize the Trigger pin as an output:    
}//end setup

///**************************************************************************
///
///                                   Loop code
///
///**************************************************************************
void loop() {
buttonState = digitalRead(buttonPin);  // read the state of the pushbutton value:
if (buttonState == LOW) {     
digitalWrite(ledPin, HIGH);            // turn LED on:
fast_analogInit(PE_3);             
SampleStartTime = micros();
digitalWrite(TriggerPin, HIGH);        // Start the Analog Signal 
for (uint16_t i=0;i<SampleQty;i++)
 {
Sample[i] = fast_analogRead();                                  
 } 
SampleEndTime = micros();
//Dump results to serial monitor
for (uint16_t i=0;i<SampleQty;i++)
{
  Serial.println(Sample[i]);
} 
Serial.print("Number of Samples : ");
Serial.println(SampleQty);
Serial.print("Sample Starttime : ");
Serial.println(SampleStartTime);
Serial.print("Sample Endtime : ");
Serial.println(SampleEndTime);
SampleDuration = SampleEndTime - SampleStartTime;
Serial.print("Sample Array Set Duration time in microseconds  : ");
Serial.println(SampleDuration);
}// end if 
delay(1000);
digitalWrite(ledPin, LOW);  // turn LED off:
}//end loop


///**************************************************************************
///
///                                   Fast Analog Read Routine
///
///**************************************************************************
uint16_t fast_analogRead(void) {
    uint32_t value[8];
    unsigned long *pulBuffer = &value[0];
    unsigned long ulCount;
    unsigned long ulBase = faBase;
    HWREG(ADC0_BASE + ADC_O_ISC) = 1 << SEQUENCER;
    HWREG(ADC0_BASE + ADC_O_PSSI) |= ((SEQUENCER & 0xffff0000) | (1 << (SEQUENCER & 0xf)));
    while (!(HWREG(ADC0_BASE + ADC_O_RIS) & (0x10000 | (1 << SEQUENCER)))) {}
    HWREG(ADC0_BASE + ADC_O_ISC) = 1 << SEQUENCER;
    ulBase = ADC0_BASE + (ADC_SEQ + (ADC_SEQ_STEP * SEQUENCER));
    ulCount = 0;
    while(!(HWREG(ulBase + ADC_SSFSTAT) & ADC_SSFSTAT0_EMPTY) && (ulCount < 8)) {
    value[ulCount] = HWREG(ulBase + ADC_SSFIFO);
    ulCount++;
    }
    return value[0];
}    

///**************************************************************************
///
///                                   Fast Analog Init Routine
///
///**************************************************************************
    uint16_t fast_analogInit(uint8_t pin) {
    uint8_t port = digitalPinToPort(pin);
    uint16_t value[1];
    uint32_t channel = digitalPinToADCIn(pin);
    if (pin == NOT_ON_ADC) {                    //invalid ADC pin
        return(0);
    }
    faBase = (uint32_t)portBASERegister(port);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    ROM_GPIOPinTypeADC((uint32_t)portBASERegister(port), digitalPinToBitMask(pin));
    ROM_ADCSequenceConfigure(ADC0_BASE, SEQUENCER, ADC_TRIGGER_PROCESSOR, 0);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 0, channel | ADC_CTL_IE);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 1, channel | ADC_CTL_IE);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 2, channel | ADC_CTL_IE);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 3, channel | ADC_CTL_IE);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 4, channel | ADC_CTL_IE);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 5, channel | ADC_CTL_IE);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 6, channel | ADC_CTL_IE);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER, 7, channel | ADC_CTL_IE | ADC_CTL_END);
    ROM_ADCSequenceEnable(ADC0_BASE, SEQUENCER);
    ROM_SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS);
    return(1);
}

I was hoping for one sample per microsecond.... I don't think you could get much closer than this.

 

Cheers

 

PTB

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...