This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

HOW TO CONTROL REAL TIME SIGNAL THROUGH PUSH BUTTON WIDGET INTERRUPT??

Other Parts Discussed in Thread: ADS1196

Hi all,  

I'm working on a project in which I'm  plotting a real time ECG Signal on my Touch TFT  through sensors connected to the ADC.

My problem is that once I Initiate the ECG Signal Acquisition , All the  Push button widgets on the canvas freeze and start flickering and only the signal keeps on getting plotted continuously.  I want to control the real time signal through my button widgets.

For example, increase/ decrease the sweep speed through touch Pushbutton widgets. ( one push button to increase the sweep & the other button is to decrease the sweep speed). My Application is totally touch based and I do not want use any external keypad. I Know my solution is related to Software/Touchscreen  interrupts but I don't know how to create it.

I'am posting my code below . It is just a part of my code. I need support as it is a  very important project for me.

My Touch TFT is controlled by TM4C129X MCU.


#include "common.h"
#include "homeUI.h"
#include "pixbuf.h"
#include "driverlib/sysctl.h"
#include "inc/hw_sysctl.h"
#include "utils/ustdlib.h"
#include "driverlib/adc.h"
#include "grlib/Container.h"


 extern volatile uint32_t ui32SysClock;
 extern volatile uint32_t adcResult;

            int x1=6;
              int y1;

              int y2;
            
void gui_Init()//function called from main
{

    /* Initialize Graphics Driver*/
    DisplayInit(ui32SysClock);

    GrRaster16BppDriverInit(g_pui32DisplayBuffer);
    GrContextInit(&guiMainContext, &g_sGrRaster16BppDriver);


    FillScreen(ClrBlack);
    TouchScreenInit(ui32SysClock);
    TouchScreenCallbackSet(WidgetPointerMessage);
    WidgetAdd(WIDGET_ROOT, (tWidget *)&guiBackGround);
    //WidgetAdd(WIDGET_ROOT, (tWidget *)&guiAcquisitionPage);
    WidgetPaint(WIDGET_ROOT);
    WidgetMessageQueueProcess();
    void Adc_Read();
    void StartSignal(tWidget *psWidget, tContext *psContext);
    void DecSweep(tWidget *psWidget);
    void IncSignalSweep(tWidget *psWidget, tContext *psContext);
   void IncSweep(tWidget *psWidget);
   void DecSignalSweep(tWidget *psWidget, tContext *psContext);
}



Canvas(guiBackGround, WIDGET_ROOT, 0, &guiSweepIncButton, &g_sGrRaster16BppDriver,
       X_OFFSET, Y_OFFSET, 800, 480,
       CANVAS_STYLE_APP_DRAWN,
                                  0, 0, 0, 0, 0, 0, StartSignal);

Canvas(guiSplashImageCanvas, &guiBackGround, 0 , &guiSweepDecButton, &g_sGrRaster16BppDriver,
       X_OFFSET, Y_OFFSET, 800, 480,
       CANVAS_STYLE_APP_DRAWN, 0, 0, 0, 0, 0, 0, StartSignal);


Canvas(guiSplashImageCanvas1, &guiBackGround, 0 , 0, &g_sGrRaster16BppDriver,
       X_OFFSET, Y_OFFSET, 800, 480,
       CANVAS_STYLE_APP_DRAWN, 0, 0, 0, 0, 0, 0, DecSignalSweep);

Canvas(guiSplashImageCanvas2, &guiBackGround, 0 ,  0, &g_sGrRaster16BppDriver,
       X_OFFSET, Y_OFFSET, 800, 480,
       CANVAS_STYLE_APP_DRAWN, 0, 0, 0, 0, 0, 0, IncSignalSweep);
       

RectangularButton(guiSweepIncButton,&guiBackGround, 0, 0, &g_sGrRaster16BppDriver,
            45, 35, 250, 50,
                                PB_STYLE_OUTLINE | PB_STYLE_TEXT |PB_STYLE_FILL|PB_STYLE_RELEASE_NOTIFY , ClrCornsilk, ClrWhite, ClrRed,
                              ClrBlack, g_psFontCmss36b, "Sweep Increase", 0,
                              0, 0, 0, IncSweep);
RectangularButton(guiSweepDecButton,&guiBackGround, 0, 0, &g_sGrRaster16BppDriver,
            450, 400, 280, 50,
                                PB_STYLE_OUTLINE | PB_STYLE_TEXT |PB_STYLE_FILL|PB_STYLE_RELEASE_NOTIFY, ClrCornsilk, ClrWhite, ClrRed,
                              ClrBlack, g_psFontCmss36b, "Sweep Decrease", 0,
                              0, 0, 0, DecSweep);

void StartSignal(tWidget *psWidget, tContext *psContext)
{


                     y1=y2;
                    Adc_Read();
             y2= adcResult;
                GrContextForegroundSet(psContext, ClrCyan);
                    GrLineDraw(psContext, x1,y1,x1+1,y2);
                    GrLineDraw(psContext, x1,y1,x1+1+1,y2);
                    if (x1<=800)
                    {
                        x1=x1+1;

                    }
                    else
                    {
                        x1=0;
                        FillScreen(ClrBlack);
                        GrFlush(psContext);
                    }

SysCtlDelay(500000);
               
                     WidgetAdd((tWidget *)&guiBackGround, (tWidget *)&guiSplashImageCanvas);
                  WidgetPaint(WIDGET_ROOT);

}


                



void DecSignalSweep(tWidget *psWidget, tContext *psContext)
{
    
     y1=y2;
                        Adc_Read();
                 y2= adcResult;
                    GrContextForegroundSet(psContext, ClrCyan);
                        GrLineDraw(psContext, x1,y1,x1+1,y2);
                        GrLineDraw(psContext, x1,y1,x1+1+1,y2);
                        if (x1<=800)
                        {
                            x1=x1+1;

                        }
                        else
                        {
                            x1=0;
                            FillScreen(ClrBlack);
                            GrFlush(psContext);
                        }


                      SysCtlDelay(1000000);
    
                                         WidgetPaint((tWidget *)&guiSplashImageCanvas1);
                                 


}

             void DecSweep(tWidget *psWidget)
             {
                
                 WidgetAdd((tWidget *)&guiBackGround, (tWidget *)&guiSplashImageCanvas1);
                 WidgetAdd((tWidget *)&guiSplashImageCanvas1, (tWidget *)&guiSweepIncButton);
                 WidgetAdd((tWidget *)&guiSplashImageCanvas1, (tWidget *)&guiSweepDecButton);
                 WidgetPaint((tWidget *)&guiSplashImageCanvas1);

             }
            

             void IncSignalSweep(tWidget *psWidget, tContext *psContext)
             {


                 y1=y2;
                                         Adc_Read();
                                  y2= adcResult;
                                     GrContextForegroundSet(psContext, ClrCyan);
                                         GrLineDraw(psContext, x1,y1,x1+1,y2);
                                         GrLineDraw(psContext, x1,y1,x1+1+1,y2);
                                         if (x1<=800)
                                         {
                                             x1=x1+1;

                                         }
                                         else
                                         {
                                             x1=0;
                                             FillScreen(ClrBlack);
                                             GrFlush(psContext);
                                         }


                                       SysCtlDelay(20000000);
                                     WidgetPaint((tWidget *)&guiSplashImageCanvas2);
                             

             }

             void OnSignal(tWidget *psWidget)
             {
                
                 WidgetAdd((tWidget *)&guiBackGround, (tWidget *)&guiSplashImageCanvas2);
                                  WidgetAdd((tWidget *)&guiSplashImageCanvas2, (tWidget *)&guiSweepIncButton);
                                  WidgetAdd((tWidget *)&guiSplashImageCanvas2, (tWidget *)&guiSweepDecButton);
                                  WidgetPaint((tWidget *)&guiSplashImageCanvas2);
             }


  • Hello Sumit

    How are you acquiring the ECG data? Is it through the ADC of the microcontroller and is there a timer involved?

    Regards
    Amit
  • Hi Amit,

    Thank you very much for looking into my query & replying to my post.

    As per your question I've designed my own general purpose biomedical instrumentation amplifier(Analog circuit) wherein I'm able to get biomedical signals like ECG/EEG/EMG/Temperature/Pressure etc. I get all the signals on oscilloscope and I'm developing a medical equipment in which I want to display the signal on TFT Screen.

    Initially I've connected my amplifier output to the ADC (PE5 Pin) of the TM4C129X MCU for testing purpose. In my final Application i'll be using ADS1196/1198 (Bio medical ADC) to display proper signal through I2C/SPI communication (I'l be needing support for that too :) ).

    Looking forward for a solution.
  • Hello Sumit,

    I believe you are using the DK-TM4C129x EVM. Is that correct? Which ADC instance (ADC0 or ADC1) are you using?

    Also is the ADC being triggered by the CPU or by a timer?

    Regards
    Amit
  • Below mentioned is my ADC Code

    void Adc_Init()
    {

    SysCtlPeripheralDisable(SYSCTL_PERIPH_ADC0);

    SysCtlPeripheralReset(SYSCTL_PERIPH_ADC0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0)));

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE)));
    GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_5);
    }


    void Adc_Read()
    {
    ADCSequenceDisable(ADC0_BASE, 3);
    ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);

    ADCSequenceStepConfigure(ADC0_BASE,3,0,ADC_CTL_CH8|ADC_CTL_IE|ADC_CTL_END);

    ADCSequenceEnable(ADC0_BASE, 3);
    ADCIntClear(ADC0_BASE, 3);
    ADCProcessorTrigger(ADC0_BASE, 3);

    while(!ADCIntStatus(ADC0_BASE, 3, false))
    {
    }
    ADCSequenceDataGet(ADC0_BASE, 3, ui32ADC0Value);
    adcResult= ui32ADC0Value[0];
    }


    Iam using TM4C123 launchpad as a debugger for my TFT. I've purchased the TFT from a vendor who has developed TFT's based on TM4C129X MCU. I mean to say that my TFT is controlled by TM4C129x MCU. All the drivers & libraries are written by the vendor. I'm just developing a customized user interface.
  • Hello Sumit,

    Is the touch detect driver for the TFT using the ADC on the TM4C129x board as well. Typically we do not support any custom drivers outside of TivaWare provided drivers.

    Regards
    Amit
  • Hi Amit,

    I'am not sure whether I understood your question or not but what I know is that The vendor written driver has nothing to do with the ADC. The TFT currently has two ADC pins AIN8 & AIN 20 as input channels. My vendor Provides Display products which are based on TI MCU.
  • Hello Sumit,

    I believe both the vendor library and your code are using the same ADC controller and that is what is causing the issue

    Regards
    Amit
  • If i use another ADC and send the signal data through I2C/SPI Comm, so will it be able to solve my problem?? Also, I want to know how to create push button widget interrupt ??
  • Hello Sumit,

    I can't say for sure since I do not have the same libraries as you are using. This is my suspicion of the issue that you are facing. A quick way to confirm that is to check the ADC0 and 1 to see which ADC instance and sequencer is being used for touch before configuring it for ECG signal capture,

    You can have a look at the grlib_demo to see how to create a Push Button.

    Regards
    Amit
  • Hi Amit,

    Thanks for guiding me  to how to check the ADC which was used with the touch screen.

    My second doubt is that How to check a push button touch inside a continuous while loop. I mean to say the Suppose I'm plotting a real time graph with ADC values and I want to change  the speed of the graph with another push button widget , then how to check another push button widget press in that continuous loop?  Below is my sample code with the comment highlighted in green  which i want to do.

    void IncSignalSweep(tWidget *psWidget, tContext *psContext)

                {

                    y1=y2;

                                            Adc_Read();

                                     y2= adcResult;

                                        GrContextForegroundSet(psContext, ClrCyan);

                                            GrLineDraw(psContext, x1,y1,x1+1,y2);

                                            GrLineDraw(psContext, x1,y1,x1+1+1,y2);

                                            if (x1<=800)

                                            {

                                                x1=x1+1;

                                            }

                                            else

                                            {

                                                x1=0;

                                                FillScreen(ClrBlack);

                                                GrFlush(psContext);

                                            }

                                          SysCtlDelay(20000000);

                                        WidgetPaint((tWidget *)&guiCanvas2);

                                // I need to keep on checking another button press here so that it comes out of the loop and if no button is pressed it comes back to this loop. (like an interrupt)

                }

  • Hello Sumit,

    You do not need to run it in a continuous loop. When a touch button push is detected, it will call its callback function where the change can be made.

    Regards
    Amit
  • Hi,
    Two suggestions if I may:
    a) Generally graphical applications are event-driven, so is the graphical
    module used by you (TI's) and there is a general queue receiving events
    and processing through a callback function. This queue should be used
    in a single place , usually while(1) inside main, as specified in
    documentation. (see also the examples in Tiva)
    So for your buttons, a single event should be sent to the queue,
    MessageQueueAdd (IIRC..)
    Same for results from other hardware modules - when ready and need to
    interact with the display, as for plotting something, send a message
    to the queue.
    Use interrupts as much as you can. Avoid software delays...
    b) Try finding out the software package for LM3S1695 micro - there
    was a nice oscilloscope-like application (yours is a dedicated one),
    understand it and apply it, useful ideas to use.

  • Hi Amit,

    I understand that I do not need to run it in a continuous loop( i corrected it in my code). I think Widgetpaint() is doing that.
    However,I'l be grateful if you could explain me with an example. This is the last step where i'm stuck in my coding. It's been two weeks since I'm stuck here!!!!!
  • HI Petrie,

    I really appreciate your reply to my concern.I'm just a beginner in coding. My expertise is in Analog Circuits. ( I've build many analog circuits in my career)

    Replying to your question
    a) Can you explain MessageQueueAdd (IIRC..) with a brief example?
    However, in my main function I'am Using while(1)
    {
    WidgetMessageQueueProcess();
    }

    b) May i get a web link to that application?
  • Hello Sumit,

    Please first go through the examples in TivaWare. They would help you understand the use of buttons better

    Regards
    Amit
  • Amit,

    You mean to say I should go thru grlib demo??
  • Hello Sumit,

    Yes. I mean the grlib_demo for the push button canvas.

    Regards
    Amit
  • Hi Petrei,

    Thanks for the suggestions!!! Your second suggestion worked for me. I was able to find a solution to my problem
    I found the oscilloscope boosterpack file and had a look at the code. I really got some nice ideas for my application.
  • Hi Amit,

    I went through the grlib demo example code & cleared lot of my doubts . thanks for the suggestion.
    I have a doubt. what is the exact difference between EPI & SPI ?? Which one is more suitable for external peripheral interface?? As in my application I'l be using three things
    1). My designed biomedical amplifier card (Analog signal)
    2). External ADC as i need a 24 bit resolution.
    3). TFT controlled by TM4C129x
  • Hello Sumit,

    EPI is a parallel bus and SPI is a serial bus. For #2 you would need SPI for sure. TFT if it is a raster panel would need LCD controller on the 212BGA part. If it is a LIDD (Smart) panel then it depends on what is the update rate on the screen you would need.

    Regards
    Amit
  • Alarm bells are ringing gently in the background.

    Hopefully you are not expecting 24 bit accuracy as well? Even 24 bit repeatability would be very challenging.

    Robert