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.

Widgets disappearing after few taps

Hi there, i hope someone could get back to me with this problem as soon as possible because im supposed to finish up my school's final year project and have it presented in less than 24hours time.

I've came up with this program being able to display waveform input from function generator and calculates the breathing rate per minute and displaying it within a tap on the pushbutton of the LCD screen.

However, im experiencing a problem with my CLEAR button.

It clears well for the first time, does its job.
However, in next few times, it gave me a problem which was my LCD's widgets went missing after being tapped on the second, third time.

LCD Display: Kentec Display EB-LM4F120-L35
Microcontroller: Tiva C Series TM4C123G

//**************************************************************************************
/*
 * This program is written by student of Biomedical Engineering (Diploma) in
 * Ngee Ann Polytechnic, Tan Michelle (Student Number: S10128640) as part of
 * the requirement of the final year project - Asthma Sensing Mat.
 *
 * Supervisor: Mr. Johnny Chee (chj)
 *
 * This main.c comprises of ADC, peak detection, displaying of waveforms ranging from
 * 0v-3.3v, recording waveform data, displaying recorded waveform data,
 * split screen display function as well as the clearing of recorded/running wavefroms.
 */
//**************************************************************************************
#include <stdint.h>
#include <stdbool.h>
#include "driverlib/fpu.h" //floating point unit
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/adc.h"
#include "driverlib/sysctl.h"
#include "grlib/grlib.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"
#include "inc/tm4c123gh6pm.h"
#include "Kentec320x240x16_ssd2119_8bit.h"
#include "grlib/widget.h"
#include "grlib/canvas.h"
#include "grlib/pushbutton.h"
#include "touch.h"
#include "conversion.h"
#include "Wave.h"
#include "displayDraw.h"
#include "ClrScreen.h"
#include "widgetPaint.h"
#include "timer.h"

tContext sContext; //initialize tContext
tRectangle sRect; //initialize tRectangle

extern tCanvasWidget g_sBackground;
extern tPushButtonWidget g_sSingleBtn;
extern tPushButtonWidget g_sDualBtn;
extern tPushButtonWidget g_sClearBtn;
extern tPushButtonWidget g_sMainBtn;
extern tPushButtonWidget g_sDisplayBtn;
extern tPushButtonWidget g_sStartBtn;
extern tPushButtonWidget g_sStopBtn;
extern tPushButtonWidget g_sBreathingRateDisplayBtn;

uint32_t count=1; //to count the number 'x-values'
uint32_t ADCDisplayFlag; // determines where the breathing will be displayed in both screens
uint32_t DisplayFlag; // determines where the waveform and recording breath per minute will be displayed in DUAL screen
uint32_t clearFlag;// determines which screen to be cleared
uint32_t startFlag; // determines which screen to start waveform plotting
uint32_t ui32ADCOutput; //declare ADC Output
uint32_t ui32ADCOutputArr[240]; //to store ADC values for plotting of graph
uint32_t ui32ADCOutput1;
uint32_t ui32ADC0Value[4]; //array of ADC values for averaging signal
uint32_t ui32BreathingRateArr[1];
uint32_t ui32BreathingRate;
uint32_t ui32Period;
uint32_t x=1; //initial value of X which will be used to plot the X-axis of graph
uint32_t y; //variable Y for graph plotting of Y-axis
uint32_t z; //variable Z for graph plotting of Y-axis from the recorded array (ui32ADCOutputArr[240])
uint32_t GraphPlotFlag; //to set flag for enabling graph plotting and stopping it 1
uint32_t uiPkPkInterval;
uint32_t ui32LongValue;
uint8_t aui8DisplayValue[5]; // Array to store 5 byte
uint8_t aui8DisplayValue2[5];// Array to store 5 byte

int iPkPkAmplitude;
unsigned char ucCycleDetected;

#ifdef DEBUG
void__error__(char *pcFilename, uint32_t ulLine){
}
#endif

void SingleButtonPress(tWidget *pWidget);
void DualButtonPress(tWidget *pWidget);
void ClearButtonPress(tWidget *pWidget);
void MainButtonPress(tWidget *pWidget);
void DisplayButtonPress(tWidget *pWidget);
void StartButtonPress(tWidget *pWidget);
void StopButtonPress(tWidget *pWidget);
void BreathingRateButtonPress(tWidget *pWidget);

Canvas(g_sHeading, &g_sBackground, 0, &g_sSingleBtn,
		&g_sKentec320x240x16_SSD2119, 65, 50, 180, 20,
		(CANVAS_STYLE_FILL | CANVAS_STYLE_OUTLINE | CANVAS_STYLE_TEXT ),
		ClrBlack, ClrWhite, ClrWhite, g_psFontCm12, "MENU SELECTION:", 0, 0);

Canvas(g_sBackground, WIDGET_ROOT, 0, &g_sHeading,
		&g_sKentec320x240x16_SSD2119, 0, 23, 320, (240 - 100),
		CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0);

RectangularButton(g_sSingleBtn, &g_sHeading, &g_sDualBtn, 0,
		&g_sKentec320x240x16_SSD2119, 240, 180, 70, 25,
		(PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT |
				PB_STYLE_FILL), ClrBlack, ClrWhite, ClrTurquoise, ClrTurquoise,
				g_psFontCmss14b, "SINGLE", 0, 0, 0, 0, SingleButtonPress);

RectangularButton(g_sDualBtn, &g_sHeading, &g_sMainBtn, 0,
		&g_sKentec320x240x16_SSD2119, 240, 210, 70, 25,
		(PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT |
				PB_STYLE_FILL), ClrBlack, ClrWhite, ClrTurquoise, ClrTurquoise,
				g_psFontCmss14b, "DUAL", 0, 0, 0, 0, DualButtonPress);

RectangularButton(g_sMainBtn, &g_sHeading, &g_sDisplayBtn, 0,
		&g_sKentec320x240x16_SSD2119, 0, 180, 70, 25,
		(PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT |
				PB_STYLE_FILL), ClrBlack, ClrWhite, ClrYellow, ClrYellow,
				g_psFontCmss14b, "MENU", 0, 0, 0, 0, MainButtonPress);

RectangularButton(g_sDisplayBtn, &g_sHeading, &g_sClearBtn, 0,
		&g_sKentec320x240x16_SSD2119, 0, 210, 70, 25,
		(PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT |
				PB_STYLE_FILL), ClrBlack, ClrWhite, ClrYellow, ClrYellow,
				g_psFontCmss14b, "DISPLAY", 0, 0, 0, 0, DisplayButtonPress);

RectangularButton(g_sClearBtn, &g_sHeading, &g_sBreathingRateDisplayBtn, 0,
		&g_sKentec320x240x16_SSD2119, 80, 180, 70, 25,
		(PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT |
				PB_STYLE_FILL), ClrBlack, ClrWhite, ClrOrange, ClrOrange,
				g_psFontCmss14b, "CLEAR", 0, 0, 0, 0, ClearButtonPress);

RectangularButton(g_sBreathingRateDisplayBtn, &g_sHeading, &g_sStartBtn, 0,
		&g_sKentec320x240x16_SSD2119, 80, 210, 70, 25,
		(PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT |
				PB_STYLE_FILL), ClrBlack, ClrWhite, ClrBlue, ClrBlue,
				g_psFontCmss14b, "BR/MIN", 0, 0, 0, 0, BreathingRateButtonPress);

RectangularButton(g_sStartBtn, &g_sHeading, &g_sStopBtn, 0,
		&g_sKentec320x240x16_SSD2119, 160, 180, 70, 25,
		(PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT |
				PB_STYLE_FILL), ClrBlack, ClrWhite, ClrLime, ClrLime,
				g_psFontCmss14b, "START", 0, 0, 0, 0, StartButtonPress);

RectangularButton(g_sStopBtn, &g_sHeading, 0, 0,
		&g_sKentec320x240x16_SSD2119, 160, 210, 70, 25,
		(PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT |
				PB_STYLE_FILL), ClrBlack, ClrWhite, ClrRed, ClrRed,
				g_psFontCmss14b, "STOP", 0, 0, 0, 0, StopButtonPress);

void DisplayButtonPress(tWidget *pWidget){ //displaying of recorded data (ui32ADCOutputArr[x])

	if(DisplayFlag==2){
		while (x < count){
			x++;
			z=(150-(ui32ADCOutputArr[x]/17));
			GrContextForegroundSet(&sContext, ClrPink);
			GrPixelDraw(&sContext, x, z);

			ui32LongValue = convertIntHextoLongBCD(ui32BreathingRateArr[0]);
			convertIntToAsciiHex4(ui32LongValue, &aui8DisplayValue2[0]);
			GrContextForegroundSet(&sContext, ClrWhite);
			GrContextFontSet(&sContext, &g_sFontCmss12b);
			GrStringDraw(&sContext, (const char*) aui8DisplayValue2, -1, 250, 6, 0);

			GrContextForegroundSet(&sContext, ClrWhite);
			GrContextFontSet(&sContext, &g_sFontCmss12b);
			GrStringDraw(&sContext, "br/min", -1, 280, 6, 0);
		}
	}
}

void BreathingRateButtonPress(tWidget *pWidget){ //displaying of ADC value of PK-PK amplitude (iPkPkAmplitude)

	if(ADCDisplayFlag==1){
		ui32BreathingRate = ((60/(uiPkPkInterval*0.02))*2);
		ui32LongValue = convertIntHextoLongBCD(ui32BreathingRate);
		convertIntToAsciiHex4(ui32LongValue, &aui8DisplayValue[0]);

		ui32BreathingRateArr[0]=ui32BreathingRate;

		GrContextForegroundSet(&sContext, ClrWhite);
		GrContextFontSet(&sContext, &g_sFontCmss12b);
		GrStringDraw(&sContext, (const char*) aui8DisplayValue, -1, 240, 6, 0);

		GrContextForegroundSet(&sContext, ClrWhite);
		GrContextFontSet(&sContext, &g_sFontCmss12b);
		GrStringDraw(&sContext, "br/min", -1, 270, 6, 0);
	}
	else if (ADCDisplayFlag==2){
		ui32BreathingRate = ((60/(uiPkPkInterval*0.02))*2);
		ui32LongValue = convertIntHextoLongBCD(ui32BreathingRate);
		convertIntToAsciiHex4(ui32LongValue, &aui8DisplayValue[0]);

		GrContextForegroundSet(&sContext, ClrWhite);
		GrContextFontSet(&sContext, &g_sFontCmss12b);
		GrStringDraw(&sContext, (const char*) aui8DisplayValue, -1, 240, 100, 0);

		GrContextForegroundSet(&sContext, ClrWhite);
		GrContextFontSet(&sContext, &g_sFontCmss12b);
		GrStringDraw(&sContext, "br/min", -1, 270, 100, 0);
	}
}

void StartButtonPress(tWidget *pWidget){ //start graph plotting in SPLIT (1) display
	if(startFlag==1){
		x=1;
		GraphPlotFlag = 1;
	}
	else if(startFlag==2){
		x=1;
		GraphPlotFlag=2;
	}
}

void ClearButtonPress(tWidget *pWidget){ //clear plotted graph as well as recorded data (ui32ADCOutputArr[x]) in SPLIT (1) display

	if(clearFlag==1){
		DrawSplit1Display();
		x=1;
		AddPaintWidget();

		while (x<count){
			x++;
			ui32ADCOutputArr[x] = 0;
		}
	}
	else if (clearFlag==2){
		DrawSplit2Display();
		x=1;
		AddPaintWidget();

		while (x<count){
			x++;
			ui32ADCOutputArr[x] = 0;
		}
	}
}
void StopButtonPress(tWidget *pWidget){ //stops graph plotting in both SPLIT (1) display and SPLIT (2) display
	GraphPlotFlag = 0;
	x=1;
}

void SingleButtonPress(tWidget *pWidget){ //splits screen into 1 display (current running waveform)
	ADCDisplayFlag=1;
	clearFlag=1;
	startFlag=1;
	DrawSplit1Display();
	AddPaintWidget();
}

void DualButtonPress(tWidget *pWidget){ //splits screen into 2 display (current running waveform and recorded waveform)
	ADCDisplayFlag=2;
	clearFlag=2;
	startFlag=2;
	DisplayFlag=2;
	DrawSplit2Display();
	AddPaintWidget();
}

void MainButtonPress(tWidget *pWidget){ //returns to menu selection screen
	clearFlag=0;
	startFlag=0;
	ADCDisplayFlag=0;
	ClrScreen();
	WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sBackground);
	WidgetPaint(WIDGET_ROOT);
	AddPaintWidget();
}

int main(void){

	Wave_init(); //initialise to detect peak and trough
	Wave_setGapThreshold(25); //set hysteresis threshold for peak & trough detection

	SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);	 //Configure the system clock to run at 40MHz
	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //enable port E
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); //enable port F

	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3); //the pins connected to the LEDs as outputs
	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //configures Timer 0 as a 32-bit timer in periodic mode
	TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);

	ui32Period = (SysCtlClockGet() / 50) / 2; //50 interrupts a second, 0.02s per interrupt
	TimerLoadSet(TIMER0_BASE, TIMER_A, ui32Period -1);

	ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
	ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0);
	ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH0);
	ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0);
	ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0|ADC_CTL_IE|ADC_CTL_END);

	TouchScreenInit(); //initialise touchscreen function file
	TouchScreenCallbackSet(WidgetPointerMessage);

	WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sBackground);
	WidgetPaint(WIDGET_ROOT);

	Kentec320x240x16_SSD2119Init(); //initialise Kentec Display file
	GrContextInit(&sContext, &g_sKentec320x240x16_SSD2119);
	ClrScreen();

	GrFlush(&sContext);

	ClrScreen();

	IntEnable(INT_TIMER0A);
	TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); //enabling timer 0 subtimer A
	IntMasterEnable();
	TimerEnable(TIMER0_BASE, TIMER_A);

	while(1){
		WidgetMessageQueueProcess();
	}
}

void Timer0Inthandler(void){
	timer();

	if(GraphPlotFlag == 1){
		x++;
		if(x>319){
			GraphPlotFlag = 0; //stops graph plotting
		}
		else{
			count++; // count number of 'X-values'
			y=(215-(ui32ADCOutput/17)); //Y-axis pixel value
			ui32ADCOutputArr[x]= ui32ADCOutput;
			GrContextForegroundSet(&sContext, ClrGoldenrod);
			GrPixelDraw(&sContext, x, y);
		}
	}
	else if (GraphPlotFlag == 2){
		x++;
		if(x>319){
			ClearDualDisplay();
			x=1;//restart plotting to beginning of x-axis
		}
		else{
			ui32ADCOutput1=(ui32ADCOutput/2); //to minimize the waveform to fit into the smaller display range set
			y=(190-(ui32ADCOutput1/17)); //Y-axis pixel value
			GrContextForegroundSet(&sContext, ClrGoldenrod);
			GrPixelDraw(&sContext, x, y);
		}
	}

	ucCycleDetected=Wave_detectPkTr(ui32ADCOutput); //1=Peak detected

	if (ucCycleDetected>0){ //1=peak detected; 2=trough detected

		if(ucCycleDetected ==1){
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x02);
		}
		else if(ucCycleDetected == 2){
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x00); //Cycle deteced, Red LED will be turned on
		}
		uiPkPkInterval=Wave_getPkPkInterval();
	}
}

void AddPaintWidget(void){ //adding & painting of widgets
	WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sDisplayBtn);
	WidgetPaint((tWidget *)&g_sDisplayBtn);
	WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sMainBtn);
	WidgetPaint((tWidget *)&g_sMainBtn);
	WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sDualBtn);
	WidgetPaint((tWidget *)&g_sDualBtn);
	WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sSingleBtn);
	WidgetPaint((tWidget *)&g_sSingleBtn);
	WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sStartBtn);
	WidgetPaint((tWidget *)&g_sStartBtn);
	WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sClearBtn);
	WidgetPaint((tWidget *)&g_sClearBtn);
	WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sStopBtn);
	WidgetPaint((tWidget *)&g_sStopBtn);
	WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sBreathingRateDisplayBtn);
	WidgetPaint((tWidget *)&g_sBreathingRateDisplayBtn);
}
void DrawSplit1Display(void){ //Drawing of SPLIT (1) Display on LCD
	ClrScreen();
	sRect.i16XMin = 1;
	sRect.i16YMin = 1;
	sRect.i16XMax = 318;
	sRect.i16YMax = 238;
	GrContextForegroundSet(&sContext, ClrWhite);
	GrContextFontSet(&sContext, &g_sFontCmss16b);
	GrStringDraw(&sContext, "Current", -1, 10, 2, 0);

	sRect.i16XMin = 158;
	sRect.i16YMin = 1;
	sRect.i16XMax = 318;
	sRect.i16YMax = 21;
	GrContextForegroundSet(&sContext, ClrWhite);
	GrContextFontSet(&sContext, &g_sFontCmss12b);
	GrStringDraw(&sContext, "BREATHING", -1, 160, 1, 0);
	GrStringDraw(&sContext, "RATE:", -1, 180, 11, 0);
	GrRectDraw(&sContext, &sRect);

	sRect.i16XMin = 0;
	sRect.i16YMin = 170;
	sRect.i16XMax = 319;
	sRect.i16YMax = 170;
	GrContextForegroundSet(&sContext , ClrHotPink);
	GrRectDraw(&sContext, &sRect);
}

Those are my codes and the codes for my different functions, hoping someone can help me with this problem.


Thankyou!

  • Michelle Tan said:

    Experiencing a problem with my CLEAR button.  It clears well for the first time, does its job.
    However, in next few times, it gave me a problem which was my LCD's widgets went missing

    Hate when that happens!  While we feel your (rushed) pain - none here caused/contributed...

    I'm inexpert w/vendors Graphic code but suggest that your providing the following info. may well assist others:

    0) The fact that "CLEAR" works correctly upon first use - and subsequently fails - suggests that the "CLEAR" code may disrupt/break one or more critical program linkages.  "CLEAR" may also "break" the screen initializations which existed prior to, first "CLEAR."  Your writing is too brief to fully/properly describe just what "CLEAR" is supposed to do.  It would be useful to note if all other buttons perform correctly - especially upon their multiple (re-use).

    a) Is this a new issue w/your CLEAR button?  Had it worked previously?

    b) If CLEAR had past worked - what (recent) changes have occurred which may be responsible?

    c) Do all other buttons work properly?  Have you tested each/every one?  (recently)

    d) Should all other buttons work - might your careful compare/contrast of the code for a working button vs. CLEAR button assist your troubleshooting?

    e) While colorful, "Went missing" (apparently all widgets) may not be as descriptive/helpful as you intend.  As a guess - do widgets present upon your screen "disappear" when you "CLEAR?"  What else happens to the screen?  Do only widgets make up your screen?  If possible - adding several "non-widgets" prior to "CLEAR" and then observing "CLEAR's" impact upon non-widgets - may provide further clues to those familiar w/vendor's Graphic code.

    Perhaps, "lesson learned" - such issues always better resolve when discovered "earlier" rather than "zero hour!"

  • Firstly, ive broken the widget function down in simpler function and it works fine. Only when ive made more widgets, it started to have problem.

    And all my other widgets are doing fine.

    Clear button erases my widgets ONLY. 

    I do have other graphics like drawing lines etc etc.

    It clears my plotted graph using ADC values and supposed to paint my widgets and graphics after that.

    It does that function after the first 1-2 taps and after that,it clears the plotted graph, draws the lines and boxes that i want but not the widgets.

  • Michelle Tan said:
    Only when ive made more widgets, it started to have problem.

    This may indicate a too small, "stack."  Try increasing stack size by 4x or more.

    Should that fail - I'd start, "backing out" the newer widgets (those created after your note of this issue) and perhaps there's an issue w/one or more new widgets... (swag)