簡體   English   中英

為LCD屏幕旋轉1位圖

[英]Rotating 1 bit bitmap for lcd screen

我在微控制器(Arduino Mega)的陣列中存儲了一些Hitachi HD44780 LCD控制器的自定義字符。 字符基本上是位圖,其顏色深度為一位,寬度為5像素,高度為8像素。

為了盡可能節省寶貴的內存,我決定存儲輪換的數據。 否則我會在每行浪費三位。 因此,例如,É的存儲方式如下:

---#####   0x1F
-#-#-#-#   0x55
#--#-#-#   0x95
---#-#-#   0x15
---#---#   0x11

輸出應如下所示:

-----#--   0x04
----#---   0x08
--------   0x00
---#####   0x1F
---#----   0x10
---####-   0x1E
---#----   0x10
---#####   0x1F

我的問題是,將其轉換為É的最有效方法是什么。 我們在這里談論的是只有8 KB RAM的16 MHz處理器,因此,使其保持盡可能快和小巧是關鍵。 編程語言是C(++)。

我的個人想法是創建所需的8字節數組,並從左到右掃描行,並使用一些位掩碼設置位。 這就是為什么我還鏡像字母的原因,以便可以輕松地將位掩碼右移並將其用於兩個數組。

基本上掃描第一個輸入字節,相應地設置輸出數組的第3位,掃描第二行,設置輸出數組的第4位,依此類推。

但是,有沒有更好的方法來實現這一目標?

首先,謝謝。 這是我幾個月來最有趣的問題。

因此,空間是制約因素。 正如我所看到的,主要的問題是位提取和插入會付出一定的代價,這將很快吞噬代碼存儲器。 循環從5個字節的數組中提取一位,然后插入8個字節的數組中,可能需要大量的可執行代碼來完成。

我建議表示數據的另一種方法是支持一種游程長度編碼。 可以將輸出字符視為單個位字符串,由0 / 1s的流組成,然后由其他0 / 1s的流組成,直到填充64位為止。

實際上,您正在編碼狀態更改,而不是實際的位模式。 數據將為1位寬,表示0或1,長度為3位寬,表示長度1..8。

因此與

-----#--   0x04
----#---   0x08
--------   0x00
---#####   0x1F

編碼將是

  • 0101-0位,總共6位位置,編碼為6-1(------)
  • 1000-1位,共1位,編碼為1-1(#)
  • 0101-0位,總共6位位置,編碼為6-1(------)
  • 1000-1位,共1位,編碼為1-1(#)
  • 0111-0位,總共8位位置,編碼為8-1(--------)
  • 0101-0位,總共6位位置,編碼為6-1(------)
  • 1100-1位,共5位,編碼為5-1(#####)

這是3.5個字節,而不是4個字節進行編碼。


主題的一種變化是不對每個字節的前3位進行編碼。 當可執行代碼出現時,它會自動將三個0放入其中。 這將使上面的小示例的編碼成本下降到約2.5個字節,而這會花費一些額外的可執行代碼。

我認為這樣做的好處是,您每次都從一個字節的半字節中精確地提取一些位,然后將它們放入單個字節的位中。 IMNSHO將獲得最大的收益。

有沒有更好的方法來實現這一目標?

與其以旋轉方式保存字符位圖,不如將其打包為5個字節。

要在編譯時打包:

  1. 創建32個常量(或eunm

     #define L_____ 0 #define L____X 1 #define L___X_ 2 ... #define LXXXX_ 30 #define LXXXXX 31 
  2. 制作宏

     #define PACK8_5(a,b,c,d,e,f,g,h) \\ ((((((uint64_t)(a) << 5) + (b)) << 5) + (c)) << 5) + (d) ... #define UNPACK40_5(a) \\ ((a) >> 32) & 31, ((a) >> 24) & 31, ((a) >> 16) & 31, ((a) >> 8) & 31, (a) & 31 #define CHBM(a,b,c,d,e,f,g,h) (UNPACK40_5(PACK8_5((a),(b),(c),(d),(e),(f),(g),(h)))) 
  3. 制作字符位圖。 這樣做的好處是源代碼看起來像字符位圖。

     unsigned char letter[5] = { CHBM( \\ L__X__, \\ L_X___, \\ L_____, \\ LXXXXX, \\ LX____, \\ LXXXX_, \\ LX____, \\ LXXXXX) }; 

在運行時打開包裝-可能有多種方法。 下面是一個簡單的想法。

void unpack5to8(unsigned char dest[8], const unsigned char src[5]) {
  uint64_t pack = src[0];
  for (unsigned i=1; i<5; i++) {
    pack <<= 8;
    pack += src[i];
  }
  for (unsigned i=8; i>0; ) {
    i--;
    dest[i] = pack & 31;
    pack >>= 5;
  }

另一個想法是使用更多的代碼,但使用32位變量。 這是OP可以配置不同代碼的位置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM