将(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像素)。
这一点最好用一个例子来证明:
-
字节
00000001
(2^0
)表示一列八个像素,其中列顶部的第一个像素为ON(1
)。 -
字节
00001001
(2^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
(或只是一个整数运算)。我已经更新了代码。
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(尽管我在数据表中看不到它,所以它可能没有…)整数数学替代方案可能更快:)
速度是否更快只能通过测试来保证,但正如我在评论中所说,这可能会成为一个瓶颈,你看起来就像是过早优化的另一个受害者。
这里最大的瓶颈是您的框架。