将(x,y)坐标映射到字节数组中的位-尽可能快速有效

本文关键字:尽可能 有效 数组 到字节 映射 坐标 | 更新日期: 2023-09-27 18:30:07

我使用C#(在Netduino Plus上运行的.NET Micro Framework)来控制84 x 48像素的LCD屏幕。

LCD屏幕中的每个像素都有两种状态:1(ON)或0(OFF)。为了控制屏幕中的像素,我需要发送一个504 bytes数组,其中每个byte代表一列8像素(即,屏幕被"拆分"为6行84 x 8像素)。

这一点最好用一个例子来证明:

  • 字节000000012^0)表示一列八个像素,其中列顶部的第一个像素为ON(1)。

  • 字节000010012^0 + 2^3)表示另一列八个像素,其中从该列顶部起的第一个和第四个像素为ON

从中可以看出,按位AND操作将显示给定列中的哪些像素为ON或OFF。例如,查看给定列中8个像素中的第4个像素是否为ON:

00001001    AND
00001000
-----------------
00001000 > 0
∴ The 4th pixel is ON

问题是我需要能够使用(x,y)坐标来访问屏幕中的每个像素。例如,点(3,10)将表示屏幕左上角像素右侧的像素4和下方的像素11。类似地,点(83,47)将表示屏幕的右下像素。

我写了以下C#代码来实现这一点:

byte[] display = new byte[504];
// storing these means they don't need to be calculated every time:
byte[] base2 = { 1, 2, 4, 8, 16, 32, 64, 128 };
// Determine if the pixel is ON (true) or OFF (false)
public bool PixelState(Pixel px)
{
    return (display[GetColumn(px)] & base2[GetPxNum(px)]) > 0;
}
// Find the number of the pixel in its column of 8
private int GetPxNum(Pixel px)
{
    return px.y % 8;
}
// Find the index of the byte containing the bit representing the state of a pixel
private int GetColumn(Pixel px)
{
    return (px.y / 8 * 84) + px.x;
}
// Set a pixel's state
public void SetPixel(Pixel px, bool state)
{
    int col = GetColumn(px);
    int num = GetPxNum(px);
    if (state && !PixelState(px))
        display[col] += base2[num];
    else if (!state && PixelState(px))
        display[col] -= base2[num];
}
// Represents one (x,y) point
public struct Pixel
{
    public int x, y;
    public Pixel(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

由于这是在微控制器上运行的,我需要代码尽可能快速高效。这也是必要的,因为这些方法可以被快速连续调用多次来更新LCD屏幕中的像素。

因此,我的问题是如何使此代码更快、更高效?有更好的方法吗

EDIT:经过大量测试,我意识到我应该在GetColumn中使用Math.Floor(或只是一个整数运算)。我已经更新了代码。

将(x,y)坐标映射到字节数组中的位-尽可能快速有效

SetPixel:中的这个小片段

if (state && !PixelState(px))
    display[col] += base2[num];
else if (!state && PixelState(px))
    display[col] -= base2[num];

可替换为:

if (state)
    display[col] |= base2[num];
else
    display[col] &= (byte)~base2[num]; // You could precompute this inverse array too

如果你有足够的内存,预计算可能还可以,但说真的,现在uC的处理能力太强了。你真的会注意到一点转变或否定吗?


此外,您可能对不使用(double)Math.ceiling()感兴趣,因为您的微控制器可能没有浮点支持,因此必须对其进行仿真(从而导致性能下降。使用(float)会使其更好(单精度仿真更快),但更好的是:

return ( (px.y/8 + ((px.y%8)?1:0)) * 84 ) + px.x;

编辑:仔细看一下netduino,可能有一个FPU(尽管我在数据表中看不到它,所以它可能没有…)整数数学替代方案可能更快:)


速度是否更快只能通过测试来保证,但正如我在评论中所说,这可能会成为一个瓶颈,你看起来就像是过早优化的另一个受害者。

这里最大的瓶颈是您的框架。