Jump to content
43oh

patolin_01

Members
  • Content Count

    2
  • Joined

  • Last visited

Posts posted by patolin_01

  1. Well, here is my 2 cents.

     

    Im working on a kind of DSO using the stellaris launchpad, and visual basic 2010.

     

    Right now, the stellaris can sample in 1 channel (pin PA7) at different speeds, selectable via serial port commands. Right now, it can sample at 1Msps (890Ksps real), 500Ksps, 250Ksps, 125Ksps using ADC interrupt, and 64ksps, 32ksps, 16ksps, 8ksps, and 2 ksps using timer interrupt.

     

    My code samples a 4096 samples buffer, and when receives the "c" command, it sends the values stored in the buffer in ASCII over the serial port, and the its plotted on the VB app. pretty simple, but for me resulted very useful.

     

    Here is my code

    // stelarisDSO v1.0
    // 2013-07-20
    // buffer de 4096 muestras
    // 
    
    #include "Energia.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "driverlib/debug.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/adc.h"
    #include "driverlib/timer.h"
    
    #define numDatos 4095
    
    int i=0;
    int j=1;
    int adc[numDatos];
    unsigned char dataReady=0;
    unsigned long ulADC0Value[1];
    int datosListos=0;
    int datoActual=0;
    
    
    
    
    void setup() {
      int i;
      Serial.begin(115200);
      pinMode(RED_LED, OUTPUT);
      pinMode(BLUE_LED, OUTPUT);
      pinMode(GREEN_LED, OUTPUT);
     
      
      for (i=0;i<=4;i++) {
        digitalWrite(GREEN_LED,1);
        digitalWrite(RED_LED,1);
        digitalWrite(BLUE_LED,1);
        delay(100);
        digitalWrite(GREEN_LED,0);
        digitalWrite(RED_LED,0);
        digitalWrite(BLUE_LED,0);
        delay(100);
      }
      
       
      
      Serial.println("Stellaris DSO");
      Serial.println("(c) 2013 www.patolin.com");
      Serial.println("Inicio OK. ");
      Serial.print(SysCtlClockGet());
      Serial.println(" hz");
      
      initADC(0,0);  
      ADCIntDisable(ADC0_BASE, 3);
      initTimer(500);
      
    }
    
    
    
    
    
    
    void loop() {
      int valor;
      unsigned timerADC=500;
      unsigned velADC=0;
      unsigned char serialIn;
      char tipoSampling=1;   // 0=ADC int, 1=TIMER int
      
      // esperamos comando para la velocidad de muestreo
      while (1) {
        if (Serial.available()==1) {
            serialIn=Serial.read();
            
            switch (serialIn) {
               case 's':
                   // status
                   Serial.println("Ok."); 
                   break;
               case 'c':
                   // devuelve los datos del buffer
                   
                   
                    // esperamos a los datos
                   while (!datosListos) {}
                   // paramos las interrupciones
                   TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
                   ADCIntDisable(ADC0_BASE, 3);
                     datosListos=0;
                     datoActual=0;
                     //enviamos los datos por el puerto serie
                     Serial.println(numDatos);
                     for (i=0;i<=(numDatos-1);i++) {
                         Serial.println(adc[i]);
                     }
                   // reiniciamos las interrupciones
                   if (tipoSampling==1) {
                     TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
                   } else {
                     ADCIntEnable(ADC0_BASE, 3);
                   }
                   break;
               case '1':
                   // 1ksps
                   timerADC=500;
                   tipoSampling=1;
                   break;
               case '2':
                   // 2ksps
                   timerADC=1000;
                   tipoSampling=1;
                   break;
               case '3':
                   // 4ksps
                   timerADC=2000;
                   tipoSampling=1;
                   break;
               case '4':
                   // 8ksps
                   timerADC=4000;
                   tipoSampling=1;
                   break;    
               case '5':
                   // 16ksps
                   timerADC=8000;
                   tipoSampling=1;
                   break;
               case '6':
                   // 32ksps
                   timerADC=16000;
                   tipoSampling=1;
                   break;
               case '7':
                   // 64ksps
                   timerADC=32000;
                   tipoSampling=1;
                   break;
               case '8':
                   // 125ksps
                   timerADC=0000;
                   velADC=0;
                   tipoSampling=0;
                   break;
               case '9':
                   // 250ksps
                   timerADC=0000;
                   velADC=1;
                   tipoSampling=0;
                   break;
               case 'A':
                   // 500ksps
                   timerADC=0000;
                   velADC=2;
                   tipoSampling=0;
                   break;
               case 'B':
                   // 1Msps
                   timerADC=0000;
                   velADC=3;
                   tipoSampling=0;
                   break;
               
            }
            // inicializamos el timer o el ADC segun el caso
            datosListos=0;
            datoActual=0;
            if (tipoSampling==0) {
                // ADC por interrupcion
                TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
                initADC(velADC,1);
                digitalWrite(RED_LED, 0x00);  
                digitalWrite(BLUE_LED, 0x01);
            } else {
                ADCIntDisable(ADC0_BASE, 3);
                initTimer(timerADC);
                digitalWrite(RED_LED, 0x00);  
                digitalWrite(BLUE_LED, 0x00);
            }
          }  
      }
      
    }
    
    
    int capturaADC() {
        ADCIntClear(ADC0_BASE, 3);
        ADCProcessorTrigger(ADC0_BASE, 3);
        while(!ADCIntStatus(ADC0_BASE, 3, false)) { }	
        ADCSequenceDataGet(ADC0_BASE, 3, ulADC0Value);
        return (int)ulADC0Value[0];
    }
    
    
    
    void Timer0IntHandler()
    {
      TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
      digitalWrite(RED_LED, j&0x01);  
      j++;
      adc[datoActual]=capturaADC();
      datoActual++;
      
      if (datoActual>numDatos) {
         datosListos=1; 
         datoActual=0;
      }
    }
    
    void ADC0IntHandler() {
       ADCIntClear(ADC0_BASE,3);
       ADCSequenceDataGet(ADC0_BASE, 3, ulADC0Value);
       adc[datoActual]=(int)ulADC0Value[0];  
       datoActual++;
       if (datoActual>numDatos) { datoActual=0;  datosListos=1; ADCIntDisable(ADC0_BASE, 3);}
    }
    
    void initTimer(unsigned Hz)
    {
      SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
      TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
      unsigned long ulPeriod = (SysCtlClockGet() / Hz) / 2;
      TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod -1);
      IntEnable(INT_TIMER0A);
      TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
      TimerIntRegister(TIMER0_BASE, TIMER_A, Timer0IntHandler);
      TimerEnable(TIMER0_BASE, TIMER_A);
      
    }
    
    void initADC(int velocidad, int trigger) {
            /* 
              Velocidad: 0=1msps,1=500ksps,2=250ksps,3=125ksps
              trigger: 0=processor, 1=always
            */
              
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
            switch(velocidad) {
               case 3:
                   SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS);
                   break;
               case 2:
                   SysCtlADCSpeedSet(SYSCTL_ADCSPEED_500KSPS);
                   break;
               case 1:
                   SysCtlADCSpeedSet(SYSCTL_ADCSPEED_250KSPS);
                   break;
               case 0:
                   SysCtlADCSpeedSet(SYSCTL_ADCSPEED_125KSPS);
                   break;
               default:
                   SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS);
                   break;
            }
    	
            ADCSequenceDisable(ADC0_BASE, 3);
            if (trigger==0) {
              ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
              
            } else {
              ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_ALWAYS, 0);  
              
              
            }
    	ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END); 
    	//ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END); //Secuencia de ejemplo para el medidor de temperatura interno
            ADCIntRegister(ADC0_BASE, 3, ADC0IntHandler);
            ADCIntEnable(ADC0_BASE, 3);
    	ADCSequenceEnable(ADC0_BASE, 3);
            ADCProcessorTrigger(ADC0_BASE, 3);
            
    }
    

    Im writing a detailed post for my blog, so I hope it can be useful for you guys. You can check a preview (in spanish) in http://patolin.com/blog/2013/07/07/osciloscopio-con-stellaris-launchpad-actualizacion/

     

    Here is a capture image, of a RC transmitter PPM frame, at 125Ksps, 10 bits, using a 4096 sample buffer

     

    dso1.png

  2. The real problem arround here, is the interrupt routines definition in the startup.gcc

     

    I have been fighting for 2 weeks with Energia, trying to enable the timer 0 and the interrupt based ADC. But when I declare the interrupt functions on the startup.gcc file, the code compiles without problem, and its loaded into the stellaris without errors, or freezings, like the ones that brownfox is having.

     

    My code idea was to sample a signal at full speed (1Msps) and have a constant clock signal at 1hz, all interrupt based. Actually Im sampling at 950Ksps, filling a 2048 samples block, without DMA. Im trying to make a DSO like board for my laptop, so its a good start. 

     

    The code, and some explanation (spanish post, so open google translate in a new window  :D ) is in this url http://patolin.com/blog/2013/05/16/stellaris-launchpad-y-energia-programando-un-cortex-m3-facilmente/

     

    Honestly, using CCS for the stellaris, was not so funny for me. I dont like eclipse, and its pretty slow in my not-so-top-notch laptop, so Energia makes the things more easy for me, and I think that it will help more people to use the launchpads

×
×
  • Create New...