Closed bvs7 closed 7 years ago
How You write ?
#include "SmallRpiScreen.h"
SmallRpiScreen::SmallRpiScreen()
{
int w, h, bpp;
init(&w, &h, &bpp);
}
SmallRpiScreen::SmallRpiScreen(int *w, int *h, int *bpp)
{
init(w,h,bpp);
}
SmallRpiScreen::~SmallRpiScreen()
{
debug("Starting SmallRpiScreen cleanup");
// Unmap framebuffer
munmap(fbp, len_fb);
// Restore orig screen
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_vinfo))
debug("Error restoring orig screen info");
debug("Restored orig screen");
// Unmap pages (sm screen specific)
munmap(fbpage, PAGES*len_fb);
// Restore cursor blink; close keyboard
if (kbfd >= 0) {
ioctl(kbfd, KDSETMODE, KD_TEXT);
close(kbfd);
debug("Restored orig keyboard");
}
// Close framebuffer
close(fbfd);
debug("Closed framebuffer device");
debug("Finished cleanup");
}
void SmallRpiScreen::draw_pixel(int x, int y, int c)
{
debug("Drawing pixel", 3);
// Calculate pixel's offset inside the buffer
unsigned int pix_offset = (x * vinfo.bits_per_pixel / 8)+ y * finfo.line_length;
//Do page calc (not in this implementation)
// Similar to fbpage[pix_offset] = c
//(Normally would use fbp and page offset)
*((short*)(fbpage + pix_offset + (page * len_fb))) = c;
}
void SmallRpiScreen::clear_screen(int c)
{
debug("Clearing Screen", 2);
memset(fbpage + (page * len_fb), c, len_fb);
}
void SmallRpiScreen::switch_page()
{
debug("Switching page", 2);
// Naive implementation because we don't have virtual fbp space
memcpy(fbp, fbpage + (page * len_fb), len_fb);
page = (page + 1) % PAGES;
}
int SmallRpiScreen::init(int *w, int *h, int *bpp)
{
FRAMEBUFFER = "/dev/fb1";
CONSOLE = "/dev/tty1";
PAGES = 1;
fbfd = 0; // Framebuffer file descriptor
kbfd = 0; // Keyboard file descriptor
len_fb = 0; // Length of framebuffer memory
fbp = 0; // Framebuffer pointer
fbpage = 0; // Pointer to the page memory location, because
// The small screen can't load in any virtua$
page = 0; // Current page being written to (always 0 for sm screen)
debug("Starting SmallRpiScreen init");
// Open framebuffer device file
fbfd = open(FRAMEBUFFER, O_RDWR);
if (fbfd == -1){
debug("Error: cannot open framebuffer device.");
return (-1);
}
debug("Framebuffer device opened");
// Open console and hide cursor (Do this in keyboard???)
kbfd = open(CONSOLE, O_WRONLY);
if (kbfd >= 0) {
ioctl(kbfd, KDSETMODE, KD_GRAPHICS);
}
else{
debug("Could not open console to disable cursor.");
return -1;
}
debug("Diabled cursor blink.");
// Get orig variable screen info
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)){
debug("Error reading orig vinfo");
return -1;
}
if(DEBUG >= 1) printf("Original info: %dx%d, %dbpp\n",
vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
// Store orig vinfo
memcpy(&orig_vinfo, &vinfo, sizeof(struct fb_var_screeninfo));
//Change vinfo (not in this implementation... but we can try)
/*vinfo.xres = *w;
vinfo.yres = *h;
vinfo.bits_per_pixel = *bpp;
vinfo.xres_virtual = *w;*/
vinfo.yres_virtual = vinfo.yres * 2;
// Set vinfo
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo)){
debug("Error setting vinfo");
return -1;
}
if(DEBUG >= 1) printf("New info: %dx%d, %dbpp\n %dx%d virtual\n",
vinfo.xres, vinfo.yres, vinfo.bits_per_pixel,
vinfo.xres_virtual, vinfo.yres_virtual);
// Get fix screen info
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)){
debug("Error reading finfo");
return -1;
}
if (DEBUG >= 1) printf("Fixed info: %d smem_len, %d line_length\n",
finfo.smem_len, finfo.line_length);
// Map framebuffer to user memory
len_fb = finfo.smem_len;
fbp = (char*) mmap(0, len_fb,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fbfd, 0);
if ((int)fbp == -1){
debug("Failed to map a pointer to fb");
return -1;
}
fbpage = (char*)malloc(len_fb*PAGES);
if ((int)fbpage == -1){
debug("Failed to allocate pages");
return -1;
}
*w = vinfo.xres;
*h = vinfo.yres;
*bpp = vinfo.bits_per_pixel;
debug("Finished init");
return 0;
}
int main(int argc, char *argv[])
{
int w = 320, h = 240, bpp = 16;
SmallRpiScreen sc(&w,&h,&bpp);
printf("\n-------------------\nDisplay: %dx%d\n", w, h);
int c;
for(c = 0; c <= 0b11011110; c += 0b01001010){
sc.clear_screen(c);
sc.switch_page();
sleep(1);
}
}
I'm writing to the framebuffer. I use the clear_screen function to prepare a page, then copy it to the framebuffer with switch_page. When the test code in main runs, the screen goes from black to gray to light gray to white, (one second each).
(Sorry about the wall of code)
Eg. 16 bit colors looks like this:
define White 0xFFFF
define Black 0x0000
define Blue 0x001F
define Blue2 0x051F
define Red 0xF800
define Magenta 0xF81F
define Green 0x07E0
define Cyan 0x7FFF
define Yellow 0xFFE0
or
u_int16_t GetColor(u_int16_t r,u_int16_t g, u_int16_t b)
{
return(((r<<8)& 0xF800) + ((g<<3) & 0x07E0) + ((b>>3) & 0x1F));
}
wher r,g,b is 0-255 and only high 5 or 6 bits are valid depending on color
try
*((u_int16_t *)(fbpage + pix_offset + (page * len_fb))) = (u_int16_t)c;
and check init sequence when You load fb module at startup
( what is oryginal info of vinfo.bits_per_pixel ??, display can be set as 8,16 colors etc.)
Thanks for the help. My function draw_pixel works well now. I think my clear_screen function was acting strange because memset applies its argument as an unsigned char.
Thanks again.
Closing issue since there has been no activity in a long time. Reopen if needed.
I've been using this blog to make a low level interface for output to my 2.2", 320x240 screen with an ili9341 .
I use ioctl to get the variable screen info from the framebuffer (x, y resolutions, bits per pixel).
This shows that the resolution is 320x240 and that bits per pixel is 16. I cannot change these (like I could for an HDMI output or something else). However, when I write 16 bits to a pixel of the framebuffer, only the last 8 bits are used with 3 bits red, 2 blue, and 3 green. How can I change this so I am back to 16 bit color?