Topic : Communication with LCD display on REva eval board

Forum : ST7/STM8

Original Post
Post Information Post
June 15, 2009 - 6:22pm
Guest

Hi,

I'm using a REva starter kit including a

- REva mother board v3.3 with RLink
- REva STM8S208RB daughter board

I'd like to be able to use the LCD on the eval board to display output but after
spending quite a bit of time looking at all the documention (for the REva board itself as well as the ST7549T LCD controller), it's still not clear to me how to communicate with it.

There is an example provided in the STM8S firmware library ("Communicate with a monochrome LCD") that says it uses the spi peripheral to communicate with an LCD peripheral like the one on the eval board. When I compile and run the example, the first 4 LEDs light up and flash. Since the LCD is connected to the first 4 LEDs that seems sensible, however, nothing happens with the LCD itself.

Is this example actually designed to be used with an external LCD?

Does the board configuration need to be changed to send messages to the onboard LCD with SPI? For example, should the serial clock (SCK) pin from the communications area be connected to the LED0 pin (i.e. the D0 pin on the LCD microcontroller)? Or can everything be set in software?

Cheers
Claire

Replies
Post Information Post
+1
0
-1
June 16, 2009 - 9:22am
Raisonance Support Team

Hi Claire,

You raised a good remark: We do not provide an ST7/STM8 example that exhibits the LCD and MEMS functionality.

We have an half-finished example that still needs some work before being released. Until this is available, you can install the (free) RKit-ARM and retrieve the MEMS2LCD example designed for STM32 devices. As the STM32 ST library is very near from the STM8 library, porting from one to the other should not be too difficult.

If that can help I attach the code from the (unreleased) MEMS2LCD STM8 example, although it is no validated yet and may not work correctly.

#include 
#include    // This defines the _nop_() intrinsic function

//
// LCD mapping:
// The LCD ST7549T is connected with 3-pin SPI interface as follows:
// -----------------------
//   LCD pin | REva signal
// ----------+------------
//   D0      | LED0
//   D1      | LED1
//   CSB     | LED2
//   RESB    | LED3
// -----------------------
//

#ifdef __RCSTM8__

#define _RomVar code
// LCD signal SCK is mapped on LED0 on REva
#define LCD_SCK_SET     (*(char*)0x5005 |=  0x01)
#define LCD_SCK_RESET   (*(char*)0x5005 &= ~0x01)
// LCD signal MOSI is mapped on LED1 on REva
#define LCD_MOSI_SET    (*(char*)0x5005 |=  0x02)
#define LCD_MOSI_RESET  (*(char*)0x5005 &= ~0x02)
// LCD signal CS is mapped on LED2 on REva
#define LCD_CS_SET      (*(char*)0x5005 |=  0x04)
#define LCD_CS_RESET    (*(char*)0x5005 &= ~0x04)
// LCD signal RST is mapped on LED3 on REva
#define LCD_RST_SET     (*(char*)0x5005 |=  0x08)
#define LCD_RST_RESET   (*(char*)0x5005 &= ~0x08)

#else

#define _RomVar static const
// LED0
#define LCD_PORT_SCK  GPIO0
#define LCD_PIN_SCK     0
// LED1
#define LCD_PORT_MOSI GPIO0
#define LCD_PIN_MOSI  1
// LED2
#define LCD_PORT_CS   GPIO1
#define LCD_PIN_CS    4
// LED3
#define LCD_PORT_RST  GPIO1
#define LCD_PIN_RST   5

#define DELAY_LCD_RESET 1

#endif

// The following is the character code table. Each character is mapped onto
// a 6x8 matrix.
// Note that some characters are missing. Most noticeably lowercase
// characters (but uppercase can be used instead), 0x20 (space), 0x7B {,
//  0x7C |, 0x7D } and 0x7E ~
// Characters below 0x21 are not available.
//
// Lines are composed of 102 columns, but only 96 of them are visible, which
// limits ourselves to 16 characters per line.

#define ASCII_TABLE_OFFSET 0x21
#define ASCII_LETTERS_MIN_OFFSET 0x61

code unsigned char AsciiMainTable[64 * 6] =
{
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x21 !
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x22 "
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x23 #
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x24 $
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x25 %
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x26 &
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x27 '
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x28 (
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x29 )
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x2A *
    0x08, 0x08, 0x3E, 0x08, 0x08, 0x00,  // ASCII 0x2B +
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x2C ,
    0x08, 0x08, 0x08, 0x08, 0x08, 0x00,  // ASCII 0x2D -
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x2E .
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x2F /
    0x3E, 0x45, 0x49, 0x51, 0x3E, 0x00,  // ASCII 0x30 0
    0x11, 0x21, 0x7F, 0x01, 0x01, 0x00,  // ASCII 0x31 1
    0x21, 0x43, 0x45, 0x49, 0x31, 0x00,  // ASCII 0x32 2
    0x41, 0x49, 0x49, 0x49, 0x36, 0x00,  // ASCII 0x33 3
    0x0C, 0x14, 0x24, 0x7F, 0x04, 0x00,  // ASCII 0x34 4
    0x79, 0x49, 0x49, 0x49, 0x06, 0x00,  // ASCII 0x35 5
    0x06, 0x19, 0x29, 0x49, 0x06, 0x00,  // ASCII 0x36 6
    0x43, 0x44, 0x48, 0x50, 0x60, 0x00,  // ASCII 0x37 7
    0x36, 0x49, 0x49, 0x49, 0x36, 0x00,  // ASCII 0x38 8
    0x30, 0x49, 0x4A, 0x4C, 0x38, 0x00,  // ASCII 0x39 9
    0x00, 0x00, 0x36, 0x36, 0x00, 0x00,  // ASCII 0x3A :
    0x00, 0x01, 0x37, 0x36, 0x00, 0x00,  // ASCII 0x3B ;
    0x00, 0x04, 0x0A, 0x11, 0x00, 0x00,  // ASCII 0x3C <
    0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,  // ASCII 0x3D =
    0x00, 0x11, 0x0A, 0x04, 0x00, 0x00,  // ASCII 0x3E >
    0x00, 0x30, 0x40, 0x4D, 0x30, 0x00,  // ASCII 0x3F ?
    0x3E, 0x41, 0x5D, 0x5D, 0x3C, 0x00,  // ASCII 0x40 @
    0x1F, 0x24, 0x44, 0x24, 0x1F, 0x00,  // ASCII 0x41 A
    0x7F, 0x49, 0x49, 0x49, 0x36, 0x00,  // ASCII 0x42 B
    0x3E, 0x41, 0x41, 0x41, 0x41, 0x00,  // ASCII 0x43 C
    0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00,  // ASCII 0x44 D
    0x7F, 0x49, 0x49, 0x49, 0x41, 0x00,  // ASCII 0x45 E
    0x7F, 0x48, 0x48, 0x48, 0x40, 0x00,  // ASCII 0x46 F
    0x3E, 0x41, 0x49, 0x49, 0x2E, 0x00,  // ASCII 0x47 G
    0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00,  // ASCII 0x48 H
    0x00, 0x41, 0x7F, 0x41, 0x00, 0x00,  // ASCII 0x49 I
    0x06, 0x01, 0x41, 0x7E, 0x40, 0x00,  // ASCII 0x4A J
    0x7F, 0x08, 0x14, 0x22, 0x41, 0x00,  // ASCII 0x4B K
    0x7F, 0x01, 0x01, 0x01, 0x01, 0x00,  // ASCII 0x4C L
    0x7F, 0x20, 0x10, 0x20, 0x7F, 0x00,  // ASCII 0x4D M
    0x7F, 0x10, 0x08, 0x04, 0x7F, 0x00,  // ASCII 0x4E N
    0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00,  // ASCII 0x4F O
    0x7F, 0x48, 0x48, 0x48, 0x30, 0x00,  // ASCII 0x50 P
    0x3E, 0x41, 0x43, 0x47, 0x3D, 0x00,  // ASCII 0x51 Q
    0x7F, 0x48, 0x48, 0x4C, 0x33, 0x00,  // ASCII 0x52 R
    0x31, 0x49, 0x49, 0x49, 0x06, 0x00,  // ASCII 0x53 S
    0x40, 0x40, 0x7F, 0x40, 0x40, 0x00,  // ASCII 0x54 T
    0x7E, 0x01, 0x01, 0x01, 0x7E, 0x00,  // ASCII 0x55 U
    0x7C, 0x02, 0x01, 0x02, 0x7C, 0x00,  // ASCII 0x56 V
    0x7F, 0x02, 0x04, 0x02, 0x7F, 0x00,  // ASCII 0x57 W
    0x63, 0x14, 0x08, 0x14, 0x63, 0x00,  // ASCII 0x58 X
    0x60, 0x10, 0x0F, 0x10, 0x60, 0x00,  // ASCII 0x59 Y
    0x43, 0x45, 0x49, 0x51, 0x61, 0x00,  // ASCII 0x5A Z
    0x00, 0x00, 0x7F, 0x41, 0x00, 0x00,  // ASCII 0x5B [
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,  // ASCII 0x5C \
    0x00, 0x41, 0x7F, 0x00, 0x00, 0x00,  // ASCII 0x5D ]
    0x10, 0x20, 0x40, 0x20, 0x10, 0x00,  // ASCII 0x5E ^
    0x01, 0x01, 0x01, 0x01, 0x01, 0x00,  // ASCII 0x5F _
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA   // ASCII 0x60 `
};


void delay(unsigned int n)
{
    while (n--)
        _nop_();
}

void LCD_SendDataCmd(unsigned short val)
{
    unsigned short i;

    // Reset CS to activate communication to LCD
    LCD_CS_RESET;

    for (i = 0x100; i != 0; i >>= 1)     //send 9 bits
    {
        LCD_SCK_RESET;
        if (val & i)
            LCD_MOSI_SET;
        else
            LCD_MOSI_RESET;
        LCD_SCK_SET;
    }

    LCD_MOSI_SET;           // Data line set to 1
    LCD_CS_SET;             // Desactivate communication
}

void LCD_init(void)
{
    // TODO set appropriate I/O pins as output
    *(char*)0x5007 = 0xFF;    // PBDDR
    *(char*)0x5008 = 0xFF;    // PBCR1
    *(char*)0x5009 = 0x00;    // PBCR2


    // Reset the LCD controller
    LCD_RST_RESET;           //rst at 0
    delay(3000);
    LCD_RST_SET;             //rst at 1

// The "Function set" LCD instruction has the following format:
// Bit 7    0
// Bit 6    0
// Bit 5    1
// Bit 4    MX (0 for normal, 1 for reverse X direction)
// Bit 3    MY (0 for normal, 1 for reverse Y direction)
// Bit 2    PD (1 for Power-Down mode)
// Bit 1    H1  H1:H0 permits selection of a different LCD instruction block
// Bit 0    H0

    LCD_SendDataCmd(0x23);       // Select instruction block H1H0 = 11b
    LCD_SendDataCmd(0x0F);       // Frame rate control 137Hz
    LCD_SendDataCmd(0x95);       // Boost efficiency level 3; Voltage multiplier*3

    LCD_SendDataCmd(0x22);       // Select instruction block H1H0 = 10b
    LCD_SendDataCmd(0x04);       // Partial screen enable COM0~66 [PS=0-->MUX=68]
    LCD_SendDataCmd(0x12);       // Start from common 16
    LCD_SendDataCmd(0x09);       // Partial screen size [WS=1-->MUX=1:33]

    LCD_SendDataCmd(0x21);       // Select instruction block H1H0 = 01b
    LCD_SendDataCmd(0x12);       // LCD bias ratio 9 = 1:65/1:68
    LCD_SendDataCmd(0x8F);       // Set VOP value
    LCD_SendDataCmd(0x73);       // Set start line=51 (0x40+51 = 0x73)

    LCD_SendDataCmd(0x20);       // Select instruction block H1H0 = 00b
    LCD_SendDataCmd(0x05);       // Set VOP programming range HIGH (a2=6.75V)
    LCD_SendDataCmd(0x0c);       // Normal display control [D=1; E=0]

    LCD_SendDataCmd(0x83);       // Set X address of RAM to 3 ([0:101])
    LCD_SendDataCmd(0x40);       // Set Y address of RAM to 0 ([0:9])
}

void LCD_Reset(void)
{
    LCD_SendDataCmd(0x20);       // H1H0 = 00b
    LCD_SendDataCmd(0x83);       // Set X address of RAM ([0:101])
    LCD_SendDataCmd(0x40);       // Set Y address of RAM ([0:9])
}

void LCD_Display_array(const unsigned char *pBuf, int size)
{
    int i;

    if (!pBuf)
        return;

    for ( i = 0; i < size ; i++)
        LCD_SendDataCmd(0x100 + pBuf[i]);
}

void LCD_Display_repeat(const unsigned char val, unsigned int count)
{
    while (count--)
        LCD_SendDataCmd(0x100 + val);
}

void LCD_Display_char(const char c)
{
#define IS_IN_RANGE(val, start, size) (((val)>=(start)) && ((val)<((start)+(size))))
#define DISPCHAR(val, offset, table) LCD_Display_array( (table)+(((val)-(offset))*6), 6 )

    if (c == ' ') // It's a space
        LCD_Display_repeat( 0x00, 6);

    else if (IS_IN_RANGE(c, ASCII_TABLE_OFFSET, 64)) // it's in the main table
        DISPCHAR(c, ASCII_TABLE_OFFSET, AsciiMainTable);

    else if (IS_IN_RANGE(c, ASCII_LETTERS_MIN_OFFSET, 26)) // a downcase letter
        DISPCHAR(c, ASCII_TABLE_OFFSET+0x20, AsciiMainTable);

    else // if not found, display horizontal lines
        LCD_Display_repeat(0x55, 6);
}

void LCD_Display_string(const char *string)
{
    char* pos;
    char screen_buffer[17*3+1];
    memset(screen_buffer, ' ', 17*3);
    screen_buffer[17*3] = 0 ;

    if (strlen(string) > 16 * 2) // 3 lines or more (we keep only 3 lines)
    {
        memcpy(screen_buffer, string + (16 * 2), strlen(string) - 16 * 2);
        memcpy(screen_buffer + 17, string + 16, 16);
        memcpy(screen_buffer + 17 * 2, string, 16);
        screen_buffer[strlen(string) + 2] = ' ';
    }
    else if (strlen(string) > 16) // 2 lines
    {
        memcpy(screen_buffer + 17, string + 16, strlen(string) - 16);
        memcpy(screen_buffer + 17 * 2, string, 16);
        screen_buffer[strlen(string) + 1] = ' ';
    }
    else // 1 line
    {
        memcpy(screen_buffer + 17 * 2, string, strlen(string));
    }

    for ( pos=screen_buffer; (*pos); pos++)
        LCD_Display_char(*pos);
}

void LCD_Fill_Blank(void)
{
    int i;

    for (i = 0 ; i < 102 * 4 ; i++)
        LCD_SendDataCmd(0x100);
}

void LCD_Fill_Lines(void)
{
    LCD_Display_repeat(0x55, 102 * 4);
}

void LCD_Clear(void)
{
    LCD_init();
    LCD_Fill_Blank();
    LCD_init();
}

Let us know if you manage to have it working.

Regards,
Bruno

+1
0
-1
June 18, 2009 - 8:39pm
Guest

Hi Bruno,

Thanks for the help - we didn't try to get the MEMS working but we were able to print to screen using the LCD file you posted.

Thanks again!
Claire