一般OLED的分辨率为128 * 64,使用 uint64_t 貌似可以大幅度提高性能
原理:
STM32是小端模式,也就是个位存放在低地址
例如对于 uint64_t = 0x1122334455667788ULL
在内存中的位置为:

0x11   0x22   0x33   ... 0x88
[0x00] [0x01] [0x02] ... [0x07]

把OLED的刷屏方向改成按列刷新

        COL0   COL1   ......... COL127 
PAGE0   [0x00] [0x08] ......... [0x0388]
PAGE1   [0x01] [0x09] ......... [0x0389]
        ................................
PAGE6   [0x06] [0x0E] ......... [0x038E]
PAGE7   [0x07] [0x0F] ......... [0x038F]

测试一下,代码如下:

#include <stdio.h>
#include <stdint.h>

int main(void) {
    uint64_t a[2] = {
        0x0011223344556677ULL,
        0x8899AABBCCDDEEFFULL,
    };

    uint8_t* b = (uint8_t*)a;
    for (int i = 0; i < 16; i++) {
        printf("%d: 0x%02X\r\n", i, b[i]);
    }
    return 0;
}

运行结果:(这是在Windows里跑的,Windows也是小端)

0: 0x77
1: 0x66
2: 0x55
3: 0x44
4: 0x33
5: 0x22
6: 0x11
7: 0x00
8: 0xFF
9: 0xEE
10: 0xDD
11: 0xCC
12: 0xBB
13: 0xAA
14: 0x99
15: 0x88

--------------------------------
Process exited after 0.02992 seconds with return value 0 (0 ms cpu time, 2904 KB mem used).

Press ANY key to exit...

图像缓冲区

OLED 一般使用全屏缓冲区

#define OLED_WIDTH 128
#define OLED_HEIGHT 64

// uint8_t buf[OLED_WIDTH * OLED_HEIGHT / 8];
uint64_t buf[OLED_WIDTH]; 

#define MASK_SET(x, mask) buf[x] |= (mask);
#define MASK_CLR(x, mask) buf[x] &= ~ (mask);

画点

/* 需要检测x,y在合理的范围内 */
void oled_draw_pixel(int x, int y, int col) {
    if (x < 0 || x >= OLED_WIDTH || y < 0 || y >= OLED_HEIGHT) {
        return;
    }
    if (col) {
        MASK_SET(x, 1ULL << y);  // ULL: 64位
    } else {
        MASK_CLR(x, 1ULL << y);
    }
}

void oled_set_pixel(int x, int y) {
    MASK_SET(x, 1ULL << y);
}

void oled_clr_pixel(int x, int y) {
    MASK_CLR(x, 1ULL << y);
}

读点

int oled_get_pixel(int x, int y) {
    return (buf[x] >> y) & 0x01;
}

竖线

/* 超高性能 */
void oled_vline(int x, int y, int h, int col) {
    uint64_t mask = ((1ULL << h) - 1ULL) << y;
    if (col) {
        MASK_SET(x, mask);
    } else {
        MASK_CLR(x, mask);
    }
}

横线

/* 也很快 */
void oled_hline(int x, int y, int w, int col) {
    uint64_t mask = 1ULL << y;
    if (col) {
        while (w--) {
            MASK_SET(x++, 1ULL << y);
        };
    } else {
        while (w--) {
            MASK_CLR(x++, 1ULL << y);
        };
    }
}

矩形

void oled_rect(int x, int y, int w, int h, int col) {
  oled_vline(x, y, h, col);
  oled_vline(x + w - 1, y, h, col);
  oled_hline(x + 1, y, w - 2, col);
  oled_hline(x + 1, y + h - 1, w - 2, col);
}

画图

画圆

void draw_circle(int x0, int y0, int r, int col) {
    int x = r;
    int y = 0;
    int err = 0;

    while (x >= y) {
        // 画圆上的8个对称点
        set_pixel(x0 + x, y0 + y, col);
        set_pixel(x0 + y, y0 + x, col);
        set_pixel(x0 - y, y0 + x, col);
        set_pixel(x0 - x, y0 + y, col);
        set_pixel(x0 - x, y0 - y, col);
        set_pixel(x0 - y, y0 - x, col);
        set_pixel(x0 + y, y0 - x, col);
        set_pixel(x0 + x, y0 - y, col);

        // 更新y和误差
        y += 1;
        if (err <= 0) {
            err += 2 * y + 1;
        }
        // 更新x和误差
        if (err > 0) {
            x -= 1;
            err -= 2 * x + 1;
        }
    }
}

标签: none

添加新评论