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.

MSP-EXP430FG4618 - how to redirect printf output in IAR C, using DLIB, to LCD?

Dear Sirs,

I'm trying to printf to LCD, modifying  the original TI's example for LCD from slac129a.zip

As told in IAR's help, I've added own version of write.c file to my project and customized it as follows:

#include <LCD.h>

...

static UInt8 currentPos=0;
...
int MyLowLevelPutchar(int x)
{
dispChar(currentPos,x);
currentPos++;
return x;
}
...


Then I'm using simple printf call like

 printf("12345678");

But LCD shows nothing :(

But when I simply call

dispChar(0,0);

it shows zero in the right-most position.

 

Where is my mistake? Can you give me working example of redirecting printf output to LCD (or may be UART) when DLIB is used, so no putchar/getchar are defined.

 

Regards,

Ilia

  • Ilia,

    Maybe change "MyLowLevelPutchar" to be "putchar".

    By using the name "putchar", you'll cause the linker to find your version of putchar before searching dlib for its version of putchar.

    Let us know if it works.

    Jeff

  • Thanks a lot for attention to my problem, Jeff,

    Unfortunately, it doesn't work :)

    "Putchar" redefinition based approach works fine with CLIB, wile I'm trying to use DLIB. In this case, as to IAR's docs, I should write own version of  "__write" function. The template for this function is placed in C:\Program Files\IAR Systems\Embedded Workbench 5.4 Kickstart\430\src\lib\dlib\write.c

    As it's small I publish it here:

     /*******************
    *
    * Copyright 1998-2003 IAR Systems. All rights reserved.
    *
    * $Revision: 38614 $
    *
    * This is a template implementation of the "__write" function used by
    * the standard library. Replace it with a system-specific
    * implementation.
    *
    * The "__write" function should output "size" number of bytes from
    * "buffer" in some application-specific way. It should return the
    * number of characters written, or _LLIO_ERROR on failure.
    *
    * If "buffer" is zero then __write should perform flushing of
    * internal buffers, if any. In this case "handle" can be -1 to
    * indicate that all handles should be flushed.
    *
    * The template implementation below assumes that the application
    * provides the function "MyLowLevelPutchar". It should return the
    * character written, or -1 on failure.
    *
    ********************/

    #include <yfuns.h>

    _STD_BEGIN

    #pragma module_name = "?__write"

    int MyLowLevelPutchar(int x); //<-AS TO DOCS, I SHOULD DEFINE THIS FUNCTION THAT WILL BE CALLED FROM __write TO OUTPUT SINGLE CHAR 

    // AS YOU CAN SEE, THE NAME OF THIS FUNCTION IS NOT STRICT 



    /*
    * If the __write implementation uses internal buffering, uncomment
    * the following line to ensure that we are called with "buffer" as 0
    * (i.e. flush) when the application terminates.
    */

    size_t __write(int handle, const unsigned char * buffer, size_t size)
    {
    /* Remove the #if #endif pair to enable the implementation */ <-- I'VE DONE THIS
    #if 0


    size_t nChars = 0;

    if (buffer == 0)
    {
    /*
    * This means that we should flush internal buffers. Since we
    * don't we just return. (Remember, "handle" == -1 means that all
    * handles should be flushed.)
    */
    return 0;
    }

    /* This template only writes to "standard out" and "standard err",
    * for all other file handles it returns failure. */
    if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR)
    {
    return _LLIO_ERROR;
    }

    for (/* Empty */; size != 0; --size)
    {
      if (MyLowLevelPutchar(*buffer++) < 0) //<-- HERE MY FUNCTION IS CALLED.
    {
    return _LLIO_ERROR;
    }

    ++nChars;
    }

    return nChars;

    #else //<-- DELETED AS IMPLEMENTATION IS ENABLED

    /* Always return error code when implementation is disabled. */
    return _LLIO_ERROR;

    #endif
    }

    _STD_END

     

    So, please, any ideas about how to make it work. If possible, with code examples, please!

    Regards,

    Ilia

  • Hi Ilia,

    I'm happy to try to help.

    It appears they are having you modify dlib code.  Have you rebuilt dlib after modifying write.c ?

    Jeff

  • Hi Jeff,

    Jeff Tenney said:
    It appears they are having you modify dlib code.  Have you rebuilt dlib after modifying write.c ?

    IAR allows not to rebuild whole library in order to replace IO modules - they say about this in manual. All you need is just add modified template to your project and rebuild the project.

    I've solved my problem :) I've done it! Now it works! :)

    The solution was simple (even stupid :) ):

    1)first of all, as DLIB consumes much more stack, you should set it to 250 bytes instead of default 80. But this was not the main problem.

    2)In LCD.c from slac129a.zip dispChar function gets two parameters: position in LCD buffer and THE INDEX OF CHARACTER in the internal table LCD_Char_Map which defines which segments of LCD should be on or off for particular character. The keyword is INDEX but not the ASCII code. While printf operates with ASCII, so when I write

    printf("12345678'); it actually calls (via __write, then MyLowLevelPutchar) dispChar with arguments ''1'=(UInt8 = 0x31 as 0x31 is ASCII code for char '1' ).

    But in dispChar we see:

    void dispChar(UInt8 pos, UInt8 index)
    {
    LCDMEM[pos + LCD_MEM_OFFSET] &= ~LCD_Char_Map[8];

    if( pos < LCD_NUM_DIGITS )
    {
         if( index < LCD_MAX_CHARS ) //<-- THIS CODE CHECKS THE BOUNDS FOR INDEX
    {
      LCDMEM[pos + LCD_MEM_OFFSET] |= LCD_Char_Map[index]; //<-- THIS NEVER WORKS FOR DIGITS IN ASCII AS CODE OF '0' IS 0x30
    }
    }
    }

    So the simplest way to make it work is to add something like:

    if (index >= '0' && index <= '9') index = index - '0';

    before checking of boundaries:

    void dispChar(UInt8 pos, UInt8 index)
    {
    LCDMEM[pos + LCD_MEM_OFFSET] &= ~LCD_Char_Map[8];

    if( pos < LCD_NUM_DIGITS )
    {
    if (index >= '0' && index <= '9') index = index - '0';
    if( index < LCD_MAX_CHARS )
    {
    LCDMEM[pos + LCD_MEM_OFFSET] |= LCD_Char_Map[index];
    }
    }
    }
     

    So, thanks a lot one more time - the solution is found now! Small problem still persists: characters are printed in reverse order, when writing code:

    printf("1234567");

    actually on LCD we see

    7654321

    So you need not increase but decrease currentPos from leftmost position index to 0.

    Regards,

    Ilia

**Attention** This is a public forum