数码之家

 找回密码
 立即注册
搜索
查看: 4125|回复: 31

[Arduino] 好玩的Memory LCD

[复制链接]
发表于 2023-6-21 16:21:13 | 显示全部楼层 |阅读模式
本帖最后由 飞向狙沙 于 2023-6-21 16:24 编辑

偶然间看到一个屏幕,JDI的MemoryLCD,感觉跟以前诺基亚手机上用的日光屏应该是一个原理,外界光线越亮屏幕越清晰,和普通TFT的环境光越亮屏幕越不清晰正好相反,这玩意刷新率和残影效果吊打墨水屏,不知道为啥没火起来

效果:环境光无背光

效果:开闪光灯无背光

背光没接线,暂时没测,这个屏感觉两个有意思的点,一个就是上边说的日光效果,另一个就是没有驱动IC,没有缓存,电路直接刻再玻璃上,所以只能整行刷新,不能像普通屏幕一样单独刷新一个点,所以对单片机的ram要求比较高,或者外挂外部ram

既然是发到了单片机区,多少得整点代码
点屏使用了arduino的JDI_MIP_Display库,但是这个库有个缺点,不支持屏幕旋转,研究了一下,转屏也好实现
库实现原理是整一个和屏幕尺寸一样大的数组,写图案或者文字时先局部往数组里更新,最后再一次性全部刷新到屏幕,实现转屏只需要在图案往数组更新时按照屏幕旋转后的坐标更新到合适的

修改前的写像素点代码
  1. void JDI_MIP_Display::drawPixel(int16_t x, int16_t y, uint16_t color)
  2. {
  3.     if(x < 0 || x >= width() || y < 0 || y >= height()){
  4.         return;
  5.     }

  6.     int pixelIdx = ((width() / 2) * y) + (x / 2);

  7.     if(x % 2 == 0){
  8.         _backBuffer[pixelIdx] &= 0x0F;
  9.         _backBuffer[pixelIdx] |= (color & 0x0F) << 4;
  10.     }
  11.     else{
  12.         _backBuffer[pixelIdx] &= 0xF0;
  13.         _backBuffer[pixelIdx] |= color & 0x0F;
  14.     }
  15. }
复制代码
修改后的写像素点代码
  1. void JDI_MIP_Display::drawPixel(int16_t x, int16_t y, uint16_t color)
  2. {

  3.     if (x < 0 || x >= width() || y < 0 || y >= height())
  4.     {
  5.         return;
  6.     }
  7.     int16_t t;
  8.     switch (rotation)
  9.     {
  10.     case 1:
  11.         t = x;
  12.         x = WIDTH - 1 - y;
  13.         y = t;
  14.         break;
  15.     case 2:
  16.         x = WIDTH - 1 - x;
  17.         y = HEIGHT - 1 - y;
  18.         break;
  19.     case 3:
  20.         t = x;
  21.         x = y;
  22.         y = HEIGHT - 1 - t;
  23.         break;
  24.     default:
  25.         break;
  26.     }

  27.     int pixelIdx = ((WIDTH / 2) * y) + (x / 2);
  28.     // 一char8位,前4位后4位存两个像素点,判断x奇偶,确定x是前4位还是后4位
  29.     if (x % 2 == 0)
  30.     {
  31.         _backBuffer[pixelIdx] &= 0x0F;
  32.         _backBuffer[pixelIdx] |= (color & 0x0F) << 4;
  33.     }
  34.     else
  35.     {
  36.         _backBuffer[pixelIdx] &= 0xF0;
  37.         _backBuffer[pixelIdx] |= color & 0x0F;
  38.     }
  39. }
复制代码


完整的cpp文件
  1. // MIT License
  2. //
  3. // Copyright(c) 2021 Giovanni Bertazzoni <nottheworstdev@gmail.com>
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files(the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions :
  11. //
  12. // The above copyright notice and this permission notice shall be included in all
  13. // copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. // SOFTWARE.

  22. #include <JDI_MIP_Display.h>

  23. JDI_MIP_Display::JDI_MIP_Display() : Adafruit_GFX(DISPLAY_WIDTH, DISPLAY_HEIGHT)
  24. {
  25.     _scs = PIN_SCS;
  26.     _disp = PIN_DISP;
  27.     _frontlight = PIN_FRONTLIGHT;
  28. }

  29. void JDI_MIP_Display::begin()
  30. {
  31.     _background = COLOR_BLACK;

  32.     digitalWrite(_scs, LOW);
  33.     pinMode(_scs, OUTPUT);
  34.     pinMode(_disp, OUTPUT);
  35.     pinMode(_frontlight, OUTPUT);
  36.     memset(&_backBuffer[0], (char)((_background & 0x0F) | ((_background & 0x0F) << 4)), sizeof(_backBuffer));
  37. #ifdef DIFF_LINE_UPDATE
  38.     memset(&_dispBuffer[0], (char)((_background & 0x0F) | ((_background & 0x0F) << 4)), sizeof(_dispBuffer));
  39. #endif
  40.     SPI.begin();
  41. }

  42. void JDI_MIP_Display::refresh()
  43. {
  44.     for (int i = 0; i < HEIGHT; i++)
  45.     {
  46.         int lineIdx = HALF_WIDTH * i;
  47.         char *line_cmd;
  48. #ifdef DIFF_LINE_UPDATE
  49.         if (compareBuffersLine(lineIdx) == true)
  50.             continue;
  51.         memcpy(&_dispBuffer[lineIdx], &_backBuffer[lineIdx], HALF_WIDTH);
  52.         line_cmd = &_dispBuffer[lineIdx];
  53. #else
  54.         line_cmd = &_backBuffer[lineIdx];
  55. #endif
  56.         sendLineCommand(line_cmd, i);
  57.     }
  58. }

  59. bool JDI_MIP_Display::compareBuffersLine(int lineIndex)
  60. {
  61. #ifdef DIFF_LINE_UPDATE
  62.     for (int i = 0; i < HALF_WIDTH; i++)
  63.     {
  64.         int pixelIdx = lineIndex + i;
  65.         if (_backBuffer[pixelIdx] != _dispBuffer[pixelIdx])
  66.             return false;
  67.     }
  68. #endif
  69.     return true;
  70. }

  71. void JDI_MIP_Display::clearScreen()
  72. {
  73.     digitalWrite(_scs, HIGH);
  74.     SPI.transfer(CMD_ALL_CLEAR);
  75.     SPI.transfer(0x00);
  76.     digitalWrite(_scs, LOW);
  77. }

  78. void JDI_MIP_Display::sendLineCommand(char *line_cmd, int line)
  79. {
  80.     if ((line < 0) || (line >= HEIGHT))
  81.     {
  82.         return;
  83.     }

  84.     digitalWrite(_scs, HIGH);
  85.     SPI.transfer(CMD_UPDATE);
  86.     SPI.transfer(line + 1);

  87.     for (int i = 0; i < HALF_WIDTH; i++)
  88.     {
  89.         SPI.transfer(line_cmd[i]);
  90.     }

  91.     SPI.transfer(0x00);
  92.     SPI.transfer(0x00);
  93.     digitalWrite(_scs, LOW);
  94. }

  95. void JDI_MIP_Display::drawPixel(int16_t x, int16_t y, uint16_t color)
  96. {

  97.     if (x < 0 || x >= width() || y < 0 || y >= height())
  98.     {
  99.         return;
  100.     }
  101.     int16_t t;
  102.     switch (rotation)
  103.     {
  104.     case 1:
  105.         t = x;
  106.         x = WIDTH - 1 - y;
  107.         y = t;
  108.         break;
  109.     case 2:
  110.         x = WIDTH - 1 - x;
  111.         y = HEIGHT - 1 - y;
  112.         break;
  113.     case 3:
  114.         t = x;
  115.         x = y;
  116.         y = HEIGHT - 1 - t;
  117.         break;
  118.     default:
  119.         break;
  120.     }

  121.     int pixelIdx = ((WIDTH / 2) * y) + (x / 2);
  122.     // 一char8位,前4位后4位存两个像素点,判断x奇偶,确定x是前4位还是后4位
  123.     if (x % 2 == 0)
  124.     {
  125.         _backBuffer[pixelIdx] &= 0x0F;
  126.         _backBuffer[pixelIdx] |= (color & 0x0F) << 4;
  127.     }
  128.     else
  129.     {
  130.         _backBuffer[pixelIdx] &= 0xF0;
  131.         _backBuffer[pixelIdx] |= color & 0x0F;
  132.     }
  133. }

  134. void JDI_MIP_Display::setBackgroundColor(uint16_t color)
  135. {
  136.     _background = color;
  137. }

  138. void JDI_MIP_Display::displayOn()
  139. {
  140.     digitalWrite(_disp, HIGH);
  141. }

  142. void JDI_MIP_Display::displayOff()
  143. {
  144.     digitalWrite(_disp, LOW);
  145. }

  146. void JDI_MIP_Display::frontlightOn()
  147. {
  148.     digitalWrite(_frontlight, HIGH);
  149. }

  150. void JDI_MIP_Display::frontlightOff()
  151. {
  152.     digitalWrite(_frontlight, LOW);
  153. }
复制代码



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

打赏

参与人数 5家元 +150 收起 理由
hongo + 30 原創內容
fu691 + 30
亲爱的混蛋 + 30
亚历山大 + 30
jf201006 + 30 謝謝分享

查看全部打赏

发表于 2023-6-21 16:43:45 | 显示全部楼层
这个万能排线板子不错
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-21 16:48:11 | 显示全部楼层
alangxl 发表于 2023-6-21 16:43
这个万能排线板子不错

随便从立创广场找的,方便测试屏幕了
回复 支持 反对

使用道具 举报

发表于 2023-6-21 17:27:33 来自手机浏览器 | 显示全部楼层
看中这个万能板了,能分享下广场链接吗,谢谢了!
回复 支持 反对

使用道具 举报

发表于 2023-6-21 23:46:10 来自手机浏览器 | 显示全部楼层
我有个带GPS模块的stm32f103rbt6的手表。用的就是memoeyLCD屏幕。
回复 支持 反对

使用道具 举报

发表于 2023-6-22 06:50:17 来自手机浏览器 | 显示全部楼层
这个屏有背光吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-22 09:48:03 来自手机浏览器 | 显示全部楼层
261307853 发表于 2023-6-21 17:27
看中这个万能板了,能分享下广场链接吗,谢谢了!

https://oshwhub.com/WOSHI6666444444/40pin-ping-mu-zhuan-jie-ban
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-22 09:48:44 来自手机浏览器 | 显示全部楼层
wfzdm 发表于 2023-6-22 06:50
这个屏有背光吗?

有,测评接线不方便就没接
回复 支持 反对

使用道具 举报

发表于 2023-6-22 16:21:41 | 显示全部楼层
万能板不错
回复 支持 反对

使用道具 举报

发表于 2023-6-22 16:23:55 来自手机浏览器 | 显示全部楼层
大佬,怎样分离触摸屏的?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-23 14:55:47 来自手机浏览器 | 显示全部楼层
sharkzyn 发表于 2023-6-22 16:23
大佬,怎样分离触摸屏的?

钼丝,很好分
回复 支持 反对

使用道具 举报

发表于 2023-6-23 16:19:41 | 显示全部楼层
俺只能看懂窗格和线条
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-23 17:26:45 来自手机浏览器 | 显示全部楼层
亚历山大 发表于 2023-6-23 16:19
俺只能看懂窗格和线条

不重要,开心就好,垃圾佬得到的是小便宜,失去的是青春
回复 支持 3 反对 0

使用道具 举报

发表于 2023-6-24 21:57:08 来自手机浏览器 | 显示全部楼层
我的手表用的是半反射的屏,应该算是这种不过有些颜色不怎么自然…
回复 支持 反对

使用道具 举报

发表于 2023-6-25 09:18:21 | 显示全部楼层

万能板不错
回复 支持 反对

使用道具 举报

发表于 2023-6-25 13:46:07 | 显示全部楼层
虽然没看懂但是这个数据必须加分支持
回复 支持 反对

使用道具 举报

发表于 2023-6-25 22:51:01 来自手机浏览器 | 显示全部楼层
这个MemoryLCD,是不是半反射半透射的屏幕呀?
以前的老款GBA,就是反射屏,没有背光,必须要有环境光才能看得清。后来的GBASP高亮机,就升级成背光屏了,但是在强光线的户外就看不清晰了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-26 08:43:06 | 显示全部楼层
threecai 发表于 2023-6-25 22:51
这个MemoryLCD,是不是半反射半透射的屏幕呀?
以前的老款GBA,就是反射屏,没有背光,必须要有环境光才能 ...

对,半反半透,外界光线越强越清晰,不过本身也支持背光,黑暗环境也能用,跟墨水屏效果差不多
回复 支持 反对

使用道具 举报

发表于 2023-6-26 21:11:54 | 显示全部楼层
看到老兄在老王上评论了 谢谢分享
回复 支持 反对

使用道具 举报

发表于 2023-6-26 21:41:28 | 显示全部楼层
原机是个什么设备?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-8 06:50 , Processed in 0.187200 second(s), 14 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表