BRT Community

Please login or register.

Login with username, password and session length
Advanced search  

News:

Welcome to the Bridgetek Community!

Please read our Welcome Note

Technical Support enquires
please contact the team
@ Bridgetek Support

Please refer to our website for detailed information on all our products - Bridgetek - Bridging Technology

Author Topic: implementing support for formated strings  (Read 11551 times)

Rudolph

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
implementing support for formated strings
« on: June 23, 2019, 05:29:25 PM »

Hi,

has anyone successfully implemented vararg functions for CMD_BUTTON, CMD_TEXT and CMD_TOGGLE?
I am looking into implementing it for CMD_TEXT and I am sort of stuck at the beginning.

The problem is, there is no way to tell how many arguments are supplied and of what type these are.
So if I understand this correctly you either have to work with a known set or arguments like numbers for which
you also provide the amount with which you are calling the function.

void EVE_cmd_text_numbers(int16_t x0, int16_t y0, int16_t font, uint16_t options, const char* text, num,...)

EVE_cmd_text_numbers(0,0,28,OPT_FORMAT,"foo bar %x.i",2,0xdeadbeef,8);

This approach seems lacking.

The other alternative would be to parse the string.
But then I could use snprintf() before using EVE_cmd_text() and be done.

A practical approach would be a function that adds a single uint32_t parameter that is transferred only if OPT_FORMAT is given.
Well, better than nothing, I am adding this for now.

Logged

pauljiao

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Re: implementing support for formated strings
« Reply #1 on: August 28, 2019, 10:27:03 AM »

BT815/6 has supported it natively.
Logged

Rudolph

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
Re: implementing support for formated strings
« Reply #2 on: August 30, 2019, 05:12:38 PM »

I know that BT81x supports varargs calling for CMD_BUTTON, CMD_TEXT and CMD_TOGGLE.
You still need a wrapper function to put out all the bits on the SPI.

But I can not find a way to implement a function in C
 cmd_text(int16_t x0, int16_t y0, int16_t font, uint16_t options, const char* text, ...)
that is sending the command, the string and all parameters thru SPI.

The varargs API requires that the type and number of arguments are known.
There is no way to just loop thru the arguments.

From the BT81x programming guide we know that only integer arguments are allowed and each argument has to
end up on the SPI as 32 bit value.
So we can get away with:
 x = (uint32_t) va_arg(arguments, int);

To determine the number of arguments however we either need to parse the string or add annother argument.
 cmd_text(int16_t x0, int16_t y0, int16_t font, uint16_t options, const char* text, num_args, ...)

Parsing the string makes the functionality mostly pointless since we could use sprintf() to do that.
And adding annother argument breaks existing code.

So I added EVE_cmd_text_var(), EVE_cmd_button_var() and EVE_cmd_toggle_var() functions that need the number
of additional arguments.

« Last Edit: August 31, 2019, 07:32:12 PM by Rudolph »
Logged

b2mishra

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: implementing support for formated strings
« Reply #3 on: October 04, 2019, 03:59:01 PM »

The library function Gpu_CoCmd_Text() takes care of the va args. It sends one parameter at a time.
Code: [Select]
void Gpu_CoCmd_Text(Gpu_Hal_Context_t *phost, int16_t x, int16_t y, int16_t font, uint16_t options, const char8_t* s, ...)
{
  va_list args;
  uint8_t i, num=0;
  uint8_t len = strlen(s);

  va_start(args, s);

#ifdef BT81X_ENABLE
  num = (options & OPT_FORMAT) ? (COUNT_ARGS(s)) : (0);
#endif

  Gpu_CoCmd_StartFunc(phost, CMD_SIZE * (3+ num) + ((len + 1 + 3) & ~3));
  Gpu_Copro_SendCmd(phost, CMD_TEXT);
  Gpu_Copro_SendCmd(phost, (((uint32_t)y << 16) | (x & 0xffff)));
  Gpu_Copro_SendCmd(phost, (((uint32_t)options << 16) | (font & 0xffff)));
  Gpu_CoCmd_SendStr(phost, s);

  for (i = 0; i < num; i++)
    Gpu_Copro_SendCmd(phost, (uint32_t)va_arg(args, uint32_t));

  Gpu_CoCmd_EndFunc(phost, CMD_SIZE * (3+ num) + ((len + 1 + 3) & ~3));
  va_end(args);
}
Logged

Rudolph

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
Re: implementing support for formated strings
« Reply #4 on: October 07, 2019, 07:20:31 PM »

While a funtion named Gpu_CoCmd_Text() does not exist in my own code library for EVE ( https://github.com/RudolphRiedel/FT800-FT813 ),  you left out the most interesting part. :-)

Code: [Select]
/* Count number of arguments in Cmd_Text for string format*/
uint8_t COUNT_ARGS(const char* str)
{
uint8_t count = 0;
const char *tmp = str;

while (tmp = strstr(tmp, "%"))
{
if (*(tmp + 1) == '%') {
tmp += 2;
}
else {
count++;
tmp++;
}
}
return count;
}

I might borrow this one since it is a portable way to do this.

However, my solution might be a little more inconveniant, but it is definately faster. :-)
A COUNT_ARGS() that is resolved during compilation would be sweet.
Logged

pauljiao

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Re: implementing support for formated strings
« Reply #5 on: August 15, 2022, 02:36:59 PM »

 The function COUNT_ARGS is not right, when the parameters are like :

"%*d"
"%.*d"
"%*.*d"

which uses an extra argument for each '*'.
See the picture enclosed
Logged

Rudolph

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
Re: implementing support for formated strings
« Reply #6 on: August 15, 2022, 07:35:27 PM »

I kept using two functions for this.

Code: [Select]
void EVE_cmd_text(int16_t x0, int16_t y0, int16_t font, uint16_t options, const char* text)
...

void EVE_cmd_text_var(int16_t x0, int16_t y0, int16_t font, uint16_t options, const char* text, uint8_t num_args, ...)
{
 eve_begin_cmd(CMD_TEXT);

 spi_transmit((uint8_t)(x0));
 spi_transmit((uint8_t)(x0 >> 8));
 spi_transmit((uint8_t)(y0));
 spi_transmit((uint8_t)(y0 >> 8));

 spi_transmit((uint8_t)(font));
 spi_transmit((uint8_t)(font >> 8));
 spi_transmit((uint8_t)(options));
 spi_transmit((uint8_t)(options >> 8));

 private_string_write(text);

 if(options & EVE_OPT_FORMAT)
 {
  va_list arguments;
  uint8_t counter;

  va_start(arguments, num_args);

  for(counter=0;counter<num_args;counter++)
  {
    uint32_t data;

    data = (uint32_t) va_arg(arguments, int);
    spi_transmit_32(data);
  }
  va_end(arguments);
 }
EVE_cs_clear();
}

Adding a parser to count the number of arguments really felt like too much overhead.
The varargs API is plainly just broken in my opinion and that has nothing to do with EVE, you do not get the numer of entries in the list and what happens when you call va_arg() beyond the list is undefined.
Logged

Rudolph

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
Re: implementing support for formated strings
« Reply #7 on: October 30, 2022, 09:03:43 PM »

MISRA-C 2012 is giving me a hard time for using stdarg.h, va_start, va_end and va_arg - "required".
So varargs needs to go.

I am thinking about using an array of uint32_t as argument since this is what the functions are needing anyways.

void EVE_cmd_text_var(int16_t x0, int16_t y0, int16_t font, uint16_t options, const char* text, uint8_t num_args, uint32_t arguments[])


uint32_t arguments[16U];

arguments[0U] = 0xBEEFBABEUL;
arguments[1U] = 0xCAFEB0BAUL;
arguments[2U] = 23UL;
 
EVE_cmd_text_var_burst(20, 120, 28, EVE_OPT_FORMAT, "same data: 0x%08x 0x%08x 0x%04x", 3, arguments);

Thoughts?

Logged