Rpi Headless Osmc, SPI Display mit fbtft im Framebuffer beschreiben RGB 65k

Einfaches Snippet das einen im Binärfile hinterlegten BMP Font(RGB565) im Framebuffer scrollt. Jeder Buchstabe hat in der Datei seinen Startblock Ascii-Code*Width*Heigth und jede Fontgröße wiederum ihren Startblock. (Gepackt mit einem kleinen Tool für Grafiken in SPI-Flashes)

mywindows

Als Grundlage installiert man rpi-update mit integriertem fbtft und aktiviert SPI.

Dann kann man zB. für das kleine HY28B display folgend Treiber laden:

modprobe dma fbtft

modprobe fbtft_device name=hy28b fbtft_device.speed=10000000 fbtft_device.rotate=90 fbtft_device.mode=3

 

 

//#include "font.h"
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <string.h>
#include <fstream>
using namespace std;
unsigned int BinToNum(char* b, int bytes)
{
    unsigned int tmpx = 0;
    unsigned int pw = 1;
    for (int i = 0; i < bytes; i++)
    {
        tmpx += ((unsigned char)b[i] * pw);
        pw = pw * 256;
    }
    return tmpx;
}
int width = 320;
int height = 240;
int ColorBits = 16;
int size = 0;
unsigned short int* matrix;
char* fbp = 0;
int x = 0, y = 0;
long int location = 0;
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;

// Liest MultiImageDatei in Array ein, Buchstaben in verschiedenen Groessen
// jeweils nach Ascii-Code sortiert.
int Open(const char* path)
{
    int pad = 0;
    unsigned int sof = 0;
    unsigned int tx = 0;
    char tmp[4] = { 0, 0, 0, 0 };
    fstream file;
    file.open(path, ios::in);
    if (file.fail())
    {
        width = height = ColorBits = size = 0;
        return -1;
    }
    else
    {
        printf("The Filesizen");
        file.seekg(0, file.end);
        size = file.tellg();
        // Initialize Matrix//
        printf("The Filematrixn");
        matrix = new (unsigned short int[size / 2]);
        sof = 0;
        int counter = 0;
        while (sof < size)
        {
            file.seekg(sof, ios::beg);
            file.read(tmp, (int)(ColorBits / 8));
            tx = BinToNum(tmp, (int)(ColorBits / 8));
            matrix[counter] = tx;
            sof += (int)(ColorBits / 8);
            counter++;
        }
        file.close();
        return 1;
    }
}
// Framebuffer Ausschnitte auf Framebuffer selbst kopieren(Scrolling Ansatz)
int blockcpfb(int source_x, int source_y, int width, int height, int dest_x, int dest_y)
{
    for (int y = 0; y < height; y++)
        for (int x = 0; x < width; x++)
        {
            location = (source_x + x) * (vinfo.bits_per_pixel / 8) + (source_y + y) * 640;

            unsigned short int t = *((unsigned short int*)(fbp + location));
            location = (dest_x + x) * (vinfo.bits_per_pixel / 8) + (dest_y + y) * 640;
            *((unsigned short int*)(fbp + location)) = t;
        }
}
// Kopiert Image/Buchstabe ueber  Startblock aus Tabelle von array in
// Framebuffer
int blockcp(int start, int width, int height, int dest_x, int dest_y)
{
    for (int y = 0; y < height; y++)
        for (int x = 0; x < width; x++)
        {
            location = (dest_x + x) * (vinfo.bits_per_pixel / 8) + (dest_y + y) * 640;
            unsigned short int t = matrix[(y * width) + start + x];

            *((unsigned short int*)(fbp + location)) = t;
        }
}
// schneidet aus dem angegebenem Bildsource aus dem Array einen Bereich aus.
int blockcpclipping(int start, int width, int height, int dest_x, int dest_y, int clipx, int clipy,
    int clipwidth, int clipheight)
{
    for (int y = 0; y < height; y++)
        for (int x = 0; x < width; x++)
        {
            if (x > clipx && y > clipy && x < clipx + clipwidth && y < clipy + clipheight)
            {
                location = (dest_x + x) * (vinfo.bits_per_pixel / 8) + (dest_y + y) * 640;
                unsigned short int t = matrix[(y * width) + start + x];

                *((unsigned short int*)(fbp + location)) = t;
            }
        }
}

// munmap(fbp, screensize);
int main()
{
    // Open the file for reading and writing
    fbfd = open("/dev/fb1", O_RDWR);
    if (fbfd == -1)
    {
        perror("Error: cannot open framebuffer device");
        exit(1);
    }
    printf("The framebuffer device was opened successfully.n");
    // Get fixed screen information
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1)
    {
        perror("Error reading fixed information");
        exit(2);
    }
    // Get variable screen information
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1)
    {
        perror("Error reading variable information");
        exit(3);
    }
    printf("%dx%d, %dbppn", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
    // Figure out the size of the screen in bytes
    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    // Map the device to memory
    fbp = (char*)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if ((int)fbp == -1)
    {
        perror("Error: failed to map framebuffer device to memory");
        exit(4);
    }
    printf("The framebuffer device was mapped to memory successfully.n");
    x = 320;
    y = 240;
    // Where we are going to put the pixel
    // Figure out where in memory to put the pixel
    if (Open("font.bin") == 1)
    {
    }

    string s = " Guns n Roses ";
    int z = 0;

    for (int c = 0; c <= ((int)s.length() - 4); c++)
    {
        string tmp = s.substr(c, 4);
        string::iterator i;

        for (i = tmp.begin(); i != tmp.end(); i++)
        {
            // berechnet Startblock aus Ascii Code und kopiert Buchstaben.
            blockcp((8330 * (((int)*i) - 32)), 70, 119, 40 + z * 70, 0);
            z++;
        }
    }
    int charspalte = 1;
    int mychar = 0;
    z = 70;
    char tmp = s.at(mychar);
    while (1)
    {
        blockcpfb(1, 0, 319, 119, 0, 0);
        //Einzelne Linien dem Scroll folgend einkopieren(Neuer Buchstabe erscheint komplett)
        // blockcpclipping( (8330*(((int)tmp)-32)),70, 119,320,
        // 0,charspalte,0,1,119);

        if (z == 70)
        {
            char tmp = s.at(mychar);
            blockcp((8330 * (((int)tmp) - 32)), 70, 119, 320 - 70, 0);
            z = 0;
            mychar++;
            charspalte = 1;
            if (mychar == s.length())
            {
                mychar = 0;
            }
        }
        else
        {
            charspalte++;
            z++;
        }
    }

    close(fbfd);
    return 0;
}