PTB 27 Posted July 22, 2013 Author Share Posted July 22, 2013 @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 Quote Link to post Share on other sites
Rei Vilo 695 Posted July 22, 2013 Share Posted July 22, 2013 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 jkabat and PTB 2 Quote Link to post Share on other sites
jkabat 0 Posted July 23, 2013 Share Posted July 23, 2013 @@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 PTB 1 Quote Link to post Share on other sites
PTB 27 Posted July 24, 2013 Author Share Posted July 24, 2013 @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 Quote Link to post Share on other sites
jkabat 0 Posted July 24, 2013 Share Posted July 24, 2013 @@PTB, Just some more fracking errors on my part. 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 Quote Link to post Share on other sites
PTB 27 Posted July 24, 2013 Author Share Posted July 24, 2013 @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 Quote Link to post Share on other sites
jkabat 0 Posted July 25, 2013 Share Posted July 25, 2013 @@PTB, I begin to see where I erred! I forgot to include the sequencer in the read of the fifo. 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]; PTB 1 Quote Link to post Share on other sites
PTB 27 Posted July 26, 2013 Author Share Posted July 26, 2013 @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 !!!!! Cheers PTB PS. Would a different FIFO (1 deep only) give a nice boost. Is that feasible or am I talking through my hat. Quote Link to post Share on other sites
PTB 27 Posted July 26, 2013 Author Share Posted July 26, 2013 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 Rei Vilo and jkabat 2 Quote Link to post Share on other sites
reaper7 67 Posted July 26, 2013 Share Posted July 26, 2013 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 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); } Rei Vilo, PTB and jkabat 3 Quote Link to post Share on other sites
Rei Vilo 695 Posted July 26, 2013 Share Posted July 26, 2013 Let's do a library and request a pull at Energia GitHub repository! jkabat and PTB 2 Quote Link to post Share on other sites
reaper7 67 Posted July 26, 2013 Share Posted July 26, 2013 @@Rei Vilo - good idea, teamwork, published by PTB Quote Link to post Share on other sites
jkabat 0 Posted July 26, 2013 Share Posted July 26, 2013 (edited) @@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 July 26, 2013 by JKabat PTB 1 Quote Link to post Share on other sites
PTB 27 Posted July 27, 2013 Author Share Posted July 27, 2013 @@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 Quote Link to post Share on other sites
PTB 27 Posted July 28, 2013 Author Share Posted July 28, 2013 @JKabat @Rei Vilo @reaper7 I dunno John... Its still 3 microseconds too slow. 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 jkabat 1 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.