Andre Ahmed
Andre Ahmed

Reputation: 1891

Writing a non-blocking code for FSMC LCD

I'm trying to interface an STM32F1 with LCD using the FSMC. I was trying to do double buffer animation, and copy the frame buffer array to the LCD-Buffer. The thing is when writing a blocking code like the following, it will consume a the CPU a lot of waiting cycles, due to the interface,..etc. Is there another idea or a work around ?

void LCD_Flip(void) {
    //   LCD_SetCursor(0x00, 0x0000);
    static u8 s_chState = 0;

    switch (s_chState) {
    case LCD_FLIP_START:
        s_chState = LCD_FLIP_INIT;
        break;
    case LCD_FLIP_INIT:
        s_chState = LCD_FLIP_REFRESH;
        break;

    case LCD_FLIP_REFRESH:
        LCD_WriteRegister(32, 0);
        LCD_WriteRegister(33, 0);
        LCD_WriteRegister(0x0050,0x00);//GRAM horizontal start position
        LCD_WriteRegister(0x0051,fbWidth - 1);//GRAM horizontal end position
        LCD_WriteRegister(0x0052,0);//Vertical GRAM Start position
        LCD_WriteRegister(0x0053,fbHeight - 1);//Vertical GRAM end position
        LCD_WriteIndex(0x0022);

        for (uint16_t pixel = 0; pixel < fbHeight * fbWidth; pixel++) {

            *(__IO uint16_t *) (Bank1_LCD_D) = frameBuffer[pixel];
        }

        break;
    }

}

I tried to write a small FSM with a simple counter that is used in the super-loop main, that keeps increment, until you get to the end of the frame buffer, then you stop copying, but it seems that operation is so fast that the LCD controller can handle.

Something like that:

case LCD_FLIP_REFRESH:
        LCD_WriteRegister(32, 0);
        LCD_WriteRegister(33, 0);
        LCD_WriteRegister(0x0050,0x00);//GRAM horizontal start position
        LCD_WriteRegister(0x0051,fbWidth - 1);//GRAM horizontal end position
        LCD_WriteRegister(0x0052,0);//Vertical GRAM Start position
        LCD_WriteRegister(0x0053,fbHeight - 1);//Vertical GRAM end position
        LCD_WriteIndex(0x0022);



        static int pixel = 0;
           if ( pixel > fbWidth*fbHeight )
            {
                pixel = 0;
            }
        *(__IO uint16_t *) (Bank1_LCD_D) = frameBuffer[pixel];
         pixel++;
        break;
    }

Upvotes: 1

Views: 1201

Answers (1)

user149341
user149341

Reputation:

Use the DMA controller. It can copy memory to a peripheral address for you, then generate an interrupt when it's done.

It's documented in Chapter 13 of the STM32F1 reference manual.

Upvotes: 2

Related Questions