Changed allocation of display framebuffers from dynamic to static. Reorganised code in some of the display drivers.

This commit is contained in:
Silvano Seva 2022-08-10 12:26:04 +02:00
parent f1dbfbfe1f
commit 57349cba80
7 changed files with 158 additions and 190 deletions

View File

@ -87,13 +87,14 @@
#define LCD_FSMC_ADDR_DATA 0x60040000
/*
* LCD framebuffer, dynamically allocated.
* Pixel format is RGB565, 16 bit per pixel
* LCD framebuffer, statically allocated and placed in the "large" RAM block
* starting at 0x20000000 and accessible by the DMA.
* Pixel format is RGB565, 16 bit per pixel.
*/
static uint16_t *frameBuffer;
static uint16_t __attribute__((section(".bss2"))) frameBuffer[SCREEN_WIDTH * SCREEN_HEIGHT];
using namespace miosix;
Thread *lcdWaiting = 0;
static Thread *lcdWaiting = 0;
void __attribute__((used)) DmaImpl()
{
@ -126,14 +127,8 @@ static inline __attribute__((__always_inline__)) void writeData(uint8_t val)
void display_init()
{
/* Allocate and clear framebuffer, setting all pixels to 0xFFFF makes the
* screen white.
*
* TODO: handle the case when memory allocation fails!
*/
frameBuffer = ((uint16_t *) malloc(SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(uint16_t)));
memset(frameBuffer, 0xFF, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(uint16_t));
/* Clear framebuffer, setting all pixels to 0x00 makes the screen white */
memset(frameBuffer, 0x00, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(uint16_t));
/*
* Turn on DMA2 and configure its interrupt. DMA is used to transfer the
@ -435,8 +430,6 @@ void display_init()
void display_terminate()
{
free(frameBuffer);
/* Shut off FSMC and deallocate framebuffer */
RCC->AHB3ENR &= ~RCC_AHB3ENR_FSMCEN;
__DSB();

View File

@ -30,32 +30,18 @@
#include <SPI2.h>
/*
* LCD framebuffer, allocated on the heap by display_init().
* Pixel format is black and white, one bit per pixel
* LCD framebuffer, statically allocated and placed in the "large" RAM block
* starting at 0x20000000.
* Pixel format is black and white, one bit per pixel.
*/
static uint8_t *frameBuffer;
#define FB_SIZE (((SCREEN_HEIGHT * SCREEN_WIDTH) / 8 ) + 1)
static uint8_t __attribute__((section(".bss2"))) frameBuffer[FB_SIZE];
void display_init()
{
/*
* Framebuffer size, in bytes, with compensating for eventual truncation
* error in division by rounding to the nearest greater integer.
*/
unsigned int fbSize = (SCREEN_HEIGHT * SCREEN_WIDTH)/8;
if((fbSize * 8) < (SCREEN_HEIGHT * SCREEN_WIDTH)) fbSize += 1;
fbSize *= sizeof(uint8_t);
/* Allocate framebuffer */
frameBuffer = (uint8_t *) malloc(fbSize);
if(frameBuffer == NULL)
{
puts("*** LCD ERROR: cannot allocate framebuffer! ***");
return;
}
/* Clear framebuffer, setting all pixels to 0x00 makes the screen white */
memset(frameBuffer, 0x00, fbSize);
memset(frameBuffer, 0x00, FB_SIZE);
/*
* Initialise SPI2 for external flash and LCD
@ -114,11 +100,6 @@ void display_init()
void display_terminate()
{
if(frameBuffer != NULL)
{
free(frameBuffer);
}
spi2_terminate();
}

View File

@ -29,33 +29,44 @@
#include <hwconfig.h>
#include <SPI2.h>
/*
* LCD framebuffer, allocated on the heap by display_init().
* Pixel format is black and white, one bit per pixel
* LCD framebuffer, statically allocated and placed in the "large" RAM block
* starting at 0x20000000.
* Pixel format is black and white, one bit per pixel.
*/
static uint8_t *frameBuffer;
#define FB_SIZE (((SCREEN_HEIGHT * SCREEN_WIDTH) / 8 ) + 1)
static uint8_t __attribute__((section(".bss2"))) frameBuffer[FB_SIZE];
/**
* \internal
* Send one row of pixels to the display.
* Pixels in framebuffer are stored "by rows", while display needs data to be
* sent "by columns": this function performs the needed conversion.
*
* @param row: pixel row to be be sent.
*/
void display_renderRow(uint8_t row)
{
for(uint16_t i = 0; i < 64; i++)
{
uint8_t out = 0;
uint8_t tmp = frameBuffer[(i * 16) + (15 - row)];
for(uint8_t j = 0; j < 8; j++)
{
out |= ((tmp >> (7-j)) & 0x01) << j;
}
spi2_sendRecv(out);
}
}
void display_init()
{
/*
* Framebuffer size, in bytes, with compensating for eventual truncation
* error in division by rounding to the nearest greater integer.
*/
unsigned int fbSize = (SCREEN_HEIGHT * SCREEN_WIDTH)/8;
if((fbSize * 8) < (SCREEN_HEIGHT * SCREEN_WIDTH)) fbSize += 1;
fbSize *= sizeof(uint8_t);
/* Allocate framebuffer */
frameBuffer = (uint8_t *) malloc(fbSize);
if(frameBuffer == NULL)
{
puts("*** LCD ERROR: cannot allocate framebuffer! ***");
return;
}
/* Clear framebuffer, setting all pixels to 0x00 makes the screen white */
memset(frameBuffer, 0x00, fbSize);
memset(frameBuffer, 0x00, FB_SIZE);
/*
* Initialise SPI2 for external flash and LCD
@ -79,18 +90,17 @@ void display_init()
gpio_setPin(LCD_CS);
gpio_clearPin(LCD_RS);
gpio_clearPin(LCD_RST); /* Reset controller */
gpio_clearPin(LCD_RST); // Reset controller
delayMs(50);
gpio_setPin(LCD_RST);
delayMs(50);
gpio_clearPin(LCD_CS);
gpio_clearPin(LCD_RS); /* RS low -> command mode */
gpio_clearPin(LCD_RS);// RS low -> command mode
spi2_sendRecv(0xAE); // SH110X_DISPLAYOFF,
spi2_sendRecv(0xd5); // SH110X_SETDISPLAYCLOCKDIV, 0x51,
spi2_sendRecv(0x51);
//spi2_sendRecv(0x20); // SH110X_MEMORYMODE,
spi2_sendRecv(0x81); // SH110X_SETCONTRAST, 0x4F,
spi2_sendRecv(0x4F);
spi2_sendRecv(0xAD); // SH110X_DCDC, 0x8A,
@ -115,31 +125,9 @@ void display_init()
void display_terminate()
{
if(frameBuffer != NULL)
{
free(frameBuffer);
}
spi2_terminate();
}
void display_renderRow(uint8_t row)
{
uint8_t *buf = (frameBuffer);
for(uint16_t i=0; i<64; i++)
{
uint8_t out=0, tmp=buf[i*16 + 15-row];
for(uint8_t j=0; j<8; j++)
{
out|=((tmp>>(7-j))&1)<<j;
}
spi2_sendRecv(out);
}
}
void display_renderRows(uint8_t startRow, uint8_t endRow)
{
gpio_clearPin(LCD_CS);
@ -159,7 +147,7 @@ void display_renderRows(uint8_t startRow, uint8_t endRow)
void display_render()
{
display_renderRows(0, SCREEN_WIDTH / 8 - 1);
display_renderRows(0, (SCREEN_WIDTH / 8) - 1);
}
bool display_renderingInProgress()

View File

@ -29,28 +29,53 @@
#include <SPI2.h>
/*
* LCD framebuffer, allocated on the heap by display_init().
* Pixel format is black and white, one bit per pixel
* LCD framebuffer, statically allocated and placed in the "large" RAM block
* starting at 0x20000000.
* Pixel format is black and white, one bit per pixel.
*/
static uint8_t *frameBuffer;
#define FB_SIZE (((SCREEN_HEIGHT * SCREEN_WIDTH) / 8 ) + 1)
static uint8_t __attribute__((section(".bss2"))) frameBuffer[FB_SIZE];
/**
* \internal
* Send one row of pixels to the display.
* Pixels in framebuffer are stored "by rows", while display needs data to be
* sent "by columns": this function performs the needed conversion.
*
* @param row: pixel row to be be sent.
*/
static void display_renderRow(uint8_t row)
{
/* magic stuff */
uint8_t *buf = (frameBuffer + 128 * row);
for (uint8_t i = 0; i<16; i++)
{
uint8_t tmp[8] = {0};
for (uint8_t j = 0; j < 8; j++)
{
uint8_t tmp_buf = buf[j*16 + i];
int count = __builtin_popcount(tmp_buf);
while (count > 0)
{
int pos = __builtin_ctz(tmp_buf);
tmp[pos] |= 1UL << j;
tmp_buf &= ~(1 << pos);
count--;
}
}
for (uint8_t s = 0; s < 8; s++)
{
(void) spi2_sendRecv(tmp[s]);
}
}
}
void display_init()
{
/* Framebuffer size, in bytes */
unsigned int fbSize = (SCREEN_HEIGHT * SCREEN_WIDTH)/8;
if((fbSize * 8) < (SCREEN_HEIGHT * SCREEN_WIDTH)) fbSize += 1; /* Compensate for eventual truncation error in division */
fbSize *= sizeof(uint8_t);
/* Allocate framebuffer */
frameBuffer = (uint8_t *) malloc(fbSize);
if(frameBuffer == NULL)
{
puts("*** LCD ERROR: cannot allocate framebuffer! ***");
return;
}
/* Clear framebuffer, setting all pixels to 0x00 makes the screen white */
memset(frameBuffer, 0x00, fbSize);
memset(frameBuffer, 0x00, FB_SIZE);
gpio_setMode(LCD_CS, OUTPUT);
gpio_setMode(LCD_RST, OUTPUT);
@ -83,37 +108,7 @@ void display_init()
void display_terminate()
{
if(frameBuffer != NULL)
{
free(frameBuffer);
}
}
void display_renderRow(uint8_t row)
{
/* magic stuff */
uint8_t *buf = (frameBuffer + 128 * row);
for (uint8_t i = 0; i<16; i++)
{
uint8_t tmp[8] = {0};
for (uint8_t j = 0; j < 8; j++)
{
uint8_t tmp_buf = buf[j*16 + i];
int count = __builtin_popcount(tmp_buf);
while (count > 0)
{
int pos = __builtin_ctz(tmp_buf);
tmp[pos] |= 1UL << j;
tmp_buf &= ~(1 << pos);
count--;
}
}
for (uint8_t s = 0; s < 8; s++)
{
(void) spi2_sendRecv(tmp[s]);
}
}
}
void display_renderRows(uint8_t startRow, uint8_t endRow)

View File

@ -28,12 +28,19 @@
#include "hwconfig.h"
/*
* LCD framebuffer, allocated on the heap by display_init().
* LCD framebuffer, statically allocated.
* Pixel format is black and white, one bit per pixel
*/
static uint8_t *frameBuffer;
#define FB_SIZE (((SCREEN_HEIGHT * SCREEN_WIDTH) / 8 ) + 1)
static uint8_t frameBuffer[FB_SIZE];
void sendByteToController(uint8_t value)
/**
* \internal
* Send one byte to display controller, via bit banging.
*
* @param value: byte to be sent.
*/
static void sendByteToController(uint8_t value)
{
for(uint8_t i = 0; i < 8; i++)
{
@ -53,24 +60,44 @@ void sendByteToController(uint8_t value)
}
}
/**
* \internal
* Send one row of pixels to the display.
* Pixels in framebuffer are stored "by rows", while display needs data to be
* sent "by columns": this function performs the needed conversion.
*
* @param row: pixel row to be be sent.
*/
static void display_renderRow(uint8_t row)
{
/* magic stuff */
uint8_t *buf = (frameBuffer + 128 * row);
for (uint8_t i = 0; i<16; i++)
{
uint8_t tmp[8] = {0};
for (uint8_t j = 0; j < 8; j++)
{
uint8_t tmp_buf = buf[j*16 + i];
int count = __builtin_popcount(tmp_buf);
while (count > 0)
{
int pos = __builtin_ctz(tmp_buf);
tmp[pos] |= 1UL << j;
tmp_buf &= ~(1 << pos);
count--;
}
}
for (uint8_t s = 0; s < 8; s++)
{
sendByteToController(tmp[s]);
}
}
}
void display_init()
{
/* Framebuffer size, in bytes */
unsigned int fbSize = (SCREEN_HEIGHT * SCREEN_WIDTH)/8;
if((fbSize * 8) < (SCREEN_HEIGHT * SCREEN_WIDTH)) fbSize += 1; /* Compensate for eventual truncation error in division */
fbSize *= sizeof(uint8_t);
/* Allocate framebuffer */
frameBuffer = (uint8_t *) malloc(fbSize);
if(frameBuffer == NULL)
{
puts("*** LCD ERROR: cannot allocate framebuffer! ***");
return;
}
/* Clear framebuffer, setting all pixels to 0x00 makes the screen white */
memset(frameBuffer, 0x00, fbSize);
gpio_setMode(LCD_CS, OUTPUT);
gpio_setMode(LCD_RST, OUTPUT);
gpio_setMode(LCD_RS, OUTPUT);
@ -102,37 +129,11 @@ void display_init()
void display_terminate()
{
if(frameBuffer != NULL)
{
free(frameBuffer);
}
}
void display_renderRow(uint8_t row)
{
/* magic stuff */
uint8_t *buf = (frameBuffer + 128 * row);
for (uint8_t i = 0; i<16; i++)
{
uint8_t tmp[8] = {0};
for (uint8_t j = 0; j < 8; j++)
{
uint8_t tmp_buf = buf[j*16 + i];
int count = __builtin_popcount(tmp_buf);
while (count > 0)
{
int pos = __builtin_ctz(tmp_buf);
tmp[pos] |= 1UL << j;
tmp_buf &= ~(1 << pos);
count--;
}
}
for (uint8_t s = 0; s < 8; s++)
{
sendByteToController(tmp[s]);
}
}
gpio_setMode(LCD_CS, INPUT);
gpio_setMode(LCD_RST, INPUT);
gpio_setMode(LCD_RS, INPUT);
gpio_setMode(LCD_CLK, INPUT);
gpio_setMode(LCD_DAT, INPUT);
}
void display_renderRows(uint8_t startRow, uint8_t endRow)

View File

@ -50,7 +50,6 @@ _main_stack_top = 0x20000000 + _main_stack_size;
ASSERT(_main_stack_size % 8 == 0, "MAIN stack size error");
/* Mapping the heap into the large 128KB RAM */
_end = _main_stack_top;
_heap_end = 0x20020000; /* end of available ram */
/* identify the Entry Point */
@ -176,6 +175,12 @@ SECTIONS
} > smallram
_bss_end = .;
/*_end = .;*/
/*PROVIDE(end = .);*/
.bss2 :
{
*(.bss2)
. = ALIGN(8);
} > largeram
_end = .;
PROVIDE(end = .);
}

View File

@ -50,7 +50,6 @@ _main_stack_top = 0x10000000 + _main_stack_size;
ASSERT(_main_stack_size % 8 == 0, "MAIN stack size error");
/* Mapping the heap into the large 128KB RAM */
_end = 0x20000000;
_heap_end = 0x20020000; /* end of available ram */
/* identify the Entry Point */
@ -175,6 +174,12 @@ SECTIONS
} > smallram
_bss_end = .;
/*_end = .;*/
/*PROVIDE(end = .);*/
.bss2 :
{
*(.bss2)
. = ALIGN(8);
} > largeram
_end = .;
PROVIDE(end = .);
}