UART

GTT TFT Support

Moderator: Mods

Post Reply
Haz
LCD Geek
Posts: 38
Joined: Wed Jun 28, 2017 8:52 am

UART

Post by Haz »

Hi,
I am trying to ge the LCDs to work with a UART connected to a MCU. I have the following LCD:
GTT43A-TPC-BLM-B0-H1-CT-V5
GTT70A-TPC-BLM-B0-H1-CT-V5

I have it all setup and configured through the GTT Designer to be a Serial connection.
This is the code:

Code: Select all

int uart_generic_read(gtt_device *device)
{
	(void)device;
	uint8_t c;

	/* Check if there is anything to read in the RX buffer */
	if(cyhal_uart_readable(&uartUserManagementDisp) == 0)
	{
		/* Return -1 is no character exists */
		return -1;
	}
	else
	{
		cyhal_uart_getc(&uartUserManagementDisp, &c, 10);
	}
	/* Return read character */
	return c;
}

int uart_generic_write(gtt_device *device, uint8_t *data, size_t length)
{
	(void)device;
	/* Write the passed data and return the actual length sent */
	cyhal_uart_write(&uartUserManagementDisp, data, &length);

	return length;
}

void my_gtt_event_key(gtt_device* device, uint8_t key, eKeypadRepeatMode type)
{
    (void)device;
    (void)key;
    (void)type;
    Log_Message(info, "event key\r\n");
}
void my_gtt_event_sliderchange(gtt_device* device, eTouchReportingType type, uint8_t slider, int16_t value)
{
    (void)device;
    (void)type;
    (void)slider;
    (void)value;
    Log_Message(info, "event slider change\r\n");
}
void my_gtt_event_touch(gtt_device* device, eTouchReportingType type, uint16_t x , uint16_t y)
{
    (void)device;
    Log_MessageVariadic(info, "Event Touch %d x=%d y=%d\r\n",type,x,y);
}

void my_gtt_event_regiontouch(gtt_device* device, eTouchReportingType type, uint8_t region)
{
    (void)device;
    Log_MessageVariadic(info, "Region Touch %d region=%d\r\n",type,region);
}

void my_gtt_event_baseobject_on_property_change(gtt_device* device, uint16_t ObjectID, uint16_t PropertyID)
{
    (void)device;
    (void)ObjectID;
    (void)PropertyID;
    Log_Message(info, "event on property change\r\n");
}

void my_gtt_event_visualobject_on_key(gtt_device* device, uint16_t ObjectID, uint8_t Row, uint8_t Col, uint8_t ScanCode, uint8_t Down)
{
    (void)device;
    (void)ObjectID;
    (void)Row;
    (void)Col;
    (void)Down;
    (void)ScanCode;
    Log_Message(info, "event on key\r\n");
}
void my_gtt_event_button_click(gtt_device* device, uint16_t ObjectID, uint8_t State)
{
    (void)device;
    (void)ObjectID;
    (void)State;
    Log_Message(info, "event button click\r\n");
}

gtt_events myEvents = {
    .sliderchange = my_gtt_event_sliderchange,
    .touch = my_gtt_event_touch,
    .regiontouch = my_gtt_event_regiontouch,
    .baseobject_on_property_change = my_gtt_event_baseobject_on_property_change,
    .visualobject_on_key = my_gtt_event_visualobject_on_key,
    .button_click = my_gtt_event_button_click
};


gtt_device gtt_device_instance = {
        .Write = uart_generic_write,
        .Read = uart_generic_read,
        .secured_packets = 1,
        .rx_buffer = rx_buffer,
        .rx_buffer_size = sizeof(rx_buffer),
        .tx_buffer = tx_buffer,
        .tx_buffer_size = sizeof(tx_buffer),
        .events = {
            .sliderchange = my_gtt_event_sliderchange,
            .touch = my_gtt_event_touch,
            .regiontouch = my_gtt_event_regiontouch,
            .baseobject_on_property_change = my_gtt_event_baseobject_on_property_change,
            .visualobject_on_key = my_gtt_event_visualobject_on_key,
            .button_click = my_gtt_event_button_click
        },
};
All I want for now is to log text on my terminal when something happens on the screen.
I added the clear screen

Code: Select all

/* Clear the screen */
gtt_clear_screen(gtt);
and the code hangs.

when I debug, I get the following issue which is where the program hangs:
in gtt_packet_builder

Code: Select all

void gtt_packetbuilder_send(gtt_device *device)
{
	if (device->secured_packets)
	{
		size_t index = 0;
		do
		{
			device->Write(device, device->tx_buffer, device->tx_index);
			index = [highlight=yellow]gtt_parser_waitpacket(device, 251);[/highlight]
		} while (device->rx_buffer[index] != 0);
	}
	else
	{
		device->Write(device, device->tx_buffer, device->tx_index);
	}
	packetStarted = 0;
}
within the gtt_parser-waitpacket

in gtt_parser.c

Code: Select all

size_t gtt_parser_waitpacket(gtt_device *device,int packetType)
{
	gtt_waitlist_item *item = &device->waitlist[device->wait_idx++];
	item->Command = packetType;
	item->SubCommand = 0;
	item->Done = 0;
	while (!item->Done)
		[highlight=yellow]gtt_parser_process(device);[/highlight]
	size_t result = item->PacketStart;
	device->Parser.Index = item->PacketStart;
	device->wait_idx--;
	return result;
}
and ultimately ends in this call always returning a -1. So no char in the buffer.

Code: Select all

uint8_t gtt_parser_process(gtt_device *device)
{
	int Res = device->Read(device);
	[highlight=yellow]if (Res != -1)[/highlight]
.
.
.
}
Can you help me look into this? I am trying to see if this is a initialization issue, a setup issue, or a function/code issue.

I am only calling the clear screen command. I am not calling gtt_parser_process(gtt); in a loop.

Which leads me to my other question.
with UART, do i need to poll, or can I just tie an interrupt to my UART, and the interrupt will call gtt_parser_process(gtt) everytime a char is received?

Thanks,
H-

Haz
LCD Geek
Posts: 38
Joined: Wed Jun 28, 2017 8:52 am

Re: UART

Post by Haz »

Ok, got it working.
Started over and got it working.

It was a wiring issue. Which leads me to the next two questions:
1. With UART, do i need to poll, or can I just tie an interrupt to my UART, and the interrupt will call gtt_parser_process(gtt) everytime a char is received?
2. Is there a way I can tell if the LCD is ready? I don;t want to interface with the LCD if it is not connected or not ready because it is still loading. My thought is add an ECHO of FF after the splash screen loads. That would tell me that it is all done.
When my UART gets this FF, they it sets a isReady flag and the rest goes.

My splash screen is the last line on the autoexec.

Does that solve my problem?

I will try it, but if there is a better solution or a built in function to support what i want to do, please tell me

Raquel
Matrix Orbital
Matrix Orbital
Posts: 796
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Re: UART

Post by Raquel »

Hello H,

Thank you for posting on the forum.

The default setting for serial communication on the GTT is 115200 baud, hardware flow control on.
Do you have all the 4 pins connected (RX/TX/CTS/RTS) connected to your MCU? I see that you have this figured out now, though :)

You can have your UART hardware level via ISR, and place the data in a buffer.
But the gtt_parser_process(gtt) should be polled in your main loop.

Yes, an echo command is a good command to use to check if the GTT is ready, or when you are trying to make sure you are in synch with the display.

Thank you,
Raquel
Raquel Malinis
Design and Development
Matrix Orbital

Haz
LCD Geek
Posts: 38
Joined: Wed Jun 28, 2017 8:52 am

Re: UART

Post by Haz »

I am running freeRTOS. so unless there is something to do, the task is blocked. I can unblock it with a timer, but that would be a bit of a waste to just unblock to check and there is nothing there. That's why I was thinking about if there is anything which comes in the UART, then I know there is communication from the LCD to the MCU, so then call gtt_parser_process.
So instead of polling, it would be somehow interrupt driven. then even if my system is in sleep mode, the UART will wake it up when it receives anything, then call the parser.

Raquel
Matrix Orbital
Matrix Orbital
Posts: 796
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Re: UART

Post by Raquel »

Sounds like a plan :)
I cannot think of a reason of not calling the gtt_parser_process from ISR, it will return right away anyway when there is no complete packet yet.
I think we just got used to having resources and left it polling in the main loop.

Best Regards,
Raquel Malinis
Design and Development
Matrix Orbital

Haz
LCD Geek
Posts: 38
Joined: Wed Jun 28, 2017 8:52 am

Re: UART

Post by Haz »

I will interrupt in the UART and notify the task to check the parser, that way, I am not doing anything in the ISR itself.

I will post what I get. I am in a debug mess on something else, but will get to it and let you know if anyone is interested in the future.
Thanks for the quick replies.
H-

Haz
LCD Geek
Posts: 38
Joined: Wed Jun 28, 2017 8:52 am

Re: UART

Post by Haz »

So I tried it and it worked:
Here is the code. Obviously, someone will need to modify to fit their application MCU and compiler.
I put an Echo command to execute as part of a script post loading of the first screen. Basically the display sends 0xFF when it is done initializing and I wait for that.
I check the input buffer of the UART, and if nothing yet, I wait for 100ms and try again.
It will either time out after 5000ms (5sec load is long), or the LCD does send the 0xFF.
Once the LCD is known to be ready, it will depend on the mode.
If INT mode, then enable the UART interrupt, and all it does is notify the main task that there is something in the UART (RX not empty). The task then runs the parser. I don't run the parser in the Interrupt routine. Too long potentially.
My turn on time is between 2800 and 3000 (yes, I have graphics). I don't have the FET to control turn on, I am doing it by hand until I get the final hardware. I am working on a kit now. But it works.
If the mode is POLLING, then I just create a software timer in FreeRTOS, and triggers it every 25ms. It notifies the same task as above to run the parser.

Code: Select all

		/* Wait for the display to turn initialize */
		uint8_t count = TIMEOUT_DISPLAY_COUNT;
		/* Set systemMode to be interrupt driven */
		systemMode = MODE_INT;
//		/* Turn on the Display */
//		//TODO: turn EN on
//		//Check if EN is on, turn off and restart the LCD
		/* Incoming Character */
		uint8_t cIn;
		/* Flag for Display Ready status */
		bool isReady = FALSE;
		do
		{
			/* Delay */
			vTaskDelay(pdMS_TO_TICKS(TIMEOUT_DISPLAY_MS));
			/* check if we received something */
			while(Cy_SCB_UART_GetNumInRxFifo(uartUserManagementDisp.base ) != 0)
			{
				cyhal_uart_getc(&uartUserManagementDisp, &cIn, 10);
				if(cIn == 0xFF)
				{
					isReady = TRUE;
					break;
				}
			}
			/* Decrement count */
			count -= 1;
		}while (isReady != TRUE || count == 0);
		/* Clear the buffers */
		cyhal_uart_clear(&uartUserManagementDisp);
		/* Check reason for the break */
		if(count != 0 && isReady == TRUE)
		{
			Log_Message(info, "Display 1 Connected\r\n");
			/* The Display hardware is connected */
			xEventGroupSetBits(xEventGroup_UserManagementTaskStatus, ebBIT_TASK_STATUS_USERMANAGEMENT_DISP1_READY);
			/* Display the Display startup delay for info purposes */
			Log_MessageVariadic(info, "Display initialization occurred in %d ms (resolution is %d ms)\r\n", TIMEOUT_DISPLAY_MS*(TIMEOUT_DISPLAY_COUNT - count), TIMEOUT_DISPLAY_MS);
			/* Load the Login screen */
			gtt_run_script(gttDisp1,"MustangElectronicDisplay_SystemManagement\\Screen_Login\\Screen_Login.bin");
		}
		else
		{
			/* Loop exited due to a Timeout event */
			/* Disp1 is not connected */
			Log_Message(info, "Display 1 Not Connected\r\n");
			xEventGroupSetBits(xEventGroup_UserManagementErrorStatus, ebBIT_ERROR_STATUS_USERMANAGEMENT_DISP1_NOT_CONNECTED);
		}
		/* Setup the interrupt or the polling mode for the LCDs */
		if(systemMode == MODE_INT)
		{
			/* Register the call-back function */
			cyhal_uart_register_callback(&uartUserManagementDisp, UartDisp1_Isr, 0);
			/* Enable the interrupt */
			cyhal_uart_enable_event(&uartUserManagementDisp, CYHAL_UART_IRQ_RX_NOT_EMPTY , 7, TRUE);
		}
		else if(systemMode == MODE_POLLING)
		{
			/* Start the timer for Display Refresh */
			if(xDisp1RefreshTimer == NULL)
			{
				xDisp1RefreshTimer = xTimerCreate("Disp1 Refresh", 	/* A text name, purely to help debugging. */
						pdMS_TO_TICKS(DISP1_REFRESH_TIMER),		/* The timer period, in ticks */
						pdTRUE, 				/* This is a periodic timer, so xAutoReload is set to pdTRUE. */
						( void * ) 0, 			/* The ID is not used, so can be set to anything. */
						disp1RefreshTimerCallback);/* The callback function that switches the LED off. */
			}
			/* Start the created timer.  A block time of zero is used */
			if(xDisp1RefreshTimer != NULL)
			{
				xTimerStart(xDisp1RefreshTimer, 0);
				Log_Message(info, "Disp1 Refresh Timer Started\r\n");
			}
			else
			{
				xEventGroupSetBits(xEventGroup_UserManagementErrorStatus, ebBIT_ERROR_STATUS_USERMANAGEMENT_REFRESH_TIMER);
				Log_Message(info, "Disp1 Refresh Timer Not Started\r\n");
			}
		}
	}
This is night and day on resources and "multi-tasking" in my setup. My task is blocked until I either get an interrupt or refresh every 25ms. I am using the interrupt for my actual implementation.

thanks,
H-

Raquel
Matrix Orbital
Matrix Orbital
Posts: 796
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Re: UART

Post by Raquel »

Good to hear you have things figured out, Haz.
Thank you for sharing your code and findings.

Best Regards,
Raquel Malinis
Design and Development
Matrix Orbital

Haz
LCD Geek
Posts: 38
Joined: Wed Jun 28, 2017 8:52 am

Re: UART

Post by Haz »

As I build up the project, I discovered some details which cause issues and I need help to figure them out.
Here is my Display Setting
Settings.png
Settings.png (15.31 KiB) Viewed 11472 times
I have a script which runs after the SplashScreen is on and Echos 'x'.

If you look at the protocol below, I see the 'x' which triggers my program to know that the LCD init is done. Wait 1.5s on the Splash screen and then run the scrips to change the screen to Login. All of this happens on the TX line of the LCD which is all exactly as expected.
What is not expected is the data which is coming back. Having no interaction on the screen, why am I getting anything on the screen.
Protocol.PNG
Protocol.PNG (68.5 KiB) Viewed 11472 times
I am also attaching the Serial XLS so you can see both channels and timing, along with the data being exchanged. Also attached my autoexec text file showing the comms setting.
Debug Serial.xls
(34 KiB) Downloaded 1186 times
autoexec.txt
(32.7 KiB) Downloaded 1216 times
The logic I have is I am expecting only communication from the LCD when a user event happened. I am running the parser when I get data from the LCD. so when I get data from the LCD, a call to the UART interrupt happens, and that notifies my FreeRTOS task to run the parser. That way my system can be asleep, backlight dimmed, until someone touches the screen.
Is there a way I can cut off any data from the screen unless it is something I m doing, like sending a command which send a response back, etc.

Thanks for the help.
H-

bigmaple
LCD?
Posts: 8
Joined: Tue Apr 14, 2020 5:10 am
Location: Western Pennsylvania

Re: UART

Post by bigmaple »

@Haz: Thanks for your post, it helped me with some of my basic newbie concerns on how to use the gtt_protocol library. One thing I don't understand in your code is why did you (void) the gtt_device in your generic read & write functions; as well as (void) on several items in your my_* functions?

Again, I really appreciate your posting your code so I could learn how it's done!
John

Haz
LCD Geek
Posts: 38
Joined: Wed Jun 28, 2017 8:52 am

Re: UART

Post by Haz »

I did that because I only have one LCD. If you have multiple, you will need to make sure you save this into your structure returned so you know which UART to use to address it.

Post Reply