这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » Let'sDo第2期任务+成果贴+墨水屏电子书功能初步实现

共5条 1/1 1 跳转至

Let'sDo第2期任务+成果贴+墨水屏电子书功能初步实现

助工
2024-07-27 14:40:41     打赏

前言

   这算是基础任务的最终实现环节了吧(不考虑传文本置板卡,板卡识别文本的前提下)。文本可以显示了,剩下的就是文本翻页逻辑的添加。

代码实现

功能定义

结合目前资源和基础任务要求,将按键定义如下:

KeyA向上翻页
KeyB向下翻页
KeyC文本切换

功能实

按键功能

   基于之前已经实现的按键检测功能,此处仅仅需要实现按键对应功能入口的设置,即按KeyA,调用向上翻页入口,按KeyB时,调用向下翻页入口,按KeyC时,调用文本切换入口。具体实现如下:

main.c

int main(void) {
  char key = 0x00, key_new;
  unsigned char txtIndex = 0;

  system_init();

  LED_init();
  key_init();
  epd_init();
  DEV_Delay_ms(2000);

  // main_EPD_test();

  while (true) {
    key_new = get_key();
    if (key == key_new) {
      continue;
    }

    key = key_new;

    if (key) {
      LED_ON();
    } else {
      LED_OFF();
    }

    switch (key) {
      case KEYA_MASK:
        epd_show(txtIndex, 2);
        break;

      case KEYB_MASK:
        epd_show(txtIndex, 1);
        break;

      case KEYC_MASK:
        txtIndex = (txtIndex ? 0 : 1);
        epd_show(txtIndex, 0);
        break;

      default:
        break;
    }
  }
  return 0;
}

翻页和文本切换实现

   文本翻页,说简单也简单,就是在上一版本文本显示的基础上,计算出新文本的偏移地址并显示即可。但实现并没有那么容易。其中遇到了不少问题,如:

   1. 不确定是否可以动态内存申请,只能做实验验证后看是否可导入。

       做实验验证后,发现有戏,直接写双向链表实现。

   2. 有点奇葩的是,keil工程中,char类型的变量,居然范围是0~255,不是-128~127,导致一次性写好的代码逻辑和预想的不一致

       编译环境问题,也没别的招,只能把char型数据按照unsigned char型数据计算了

   3. GB2312字库和ASCII字库的高度不一致,导致计算显示数量时误差大

       直接使用简化后的逻辑,GB2312字库,补8行空白,确保缩进一致。

   4. 显示屏刷新速度过慢(显示内容刷新了,但后台还在执行收尾动作,且收尾动作耗时过长),导致不知道实际操作状态

       保留前面点灯的按键按下亮灯,松开灭灯逻辑,让人有一定感知容忍度

   由于之前过程贴已提供前期的实现部分,因此这里仅提供有修改的部分,以期减少文本量。具体代码如下:

my_epd.c

void draw_fb_GB2132(int x, int y, int bankCode, int posCode) {
  const unsigned char *pData = NULL;
  unsigned char idxX, idxY;
  int lineData;
  int pos;

  pos = ((bankCode - 0xA1) * 94 + (posCode - 0xA1)) * (GB2312_FONT_H * GB2312_FONT_W / 8);

  pData = acHZK16C + pos;

  for (idxY = 0; idxY < GB2312_FONT_W; idxY++) {
    lineData = pData[idxY * 2];
    lineData = lineData << 8;
    lineData = lineData | pData[idxY * 2 + 1];

    for (idxX = 0; idxX < GB2312_FONT_H; idxX++) {
      if (lineData & (0x01 << idxX)) {
        draw_fb_point(x + GB2312_FONT_H - idxX, y + idxY);
      } else {
        clear_fb_point(x + GB2312_FONT_H - idxX, y + idxY);
      }
    }
  }

  for (idxY = GB2312_FONT_W; idxY < ASCII_FONT_W; idxY++) {
    for (idxX = 0; idxX < GB2312_FONT_H; idxX++) {
      clear_fb_point(x + GB2312_FONT_H - idxX, y + idxY);
    }
  }
}

int draw_fb(int x, int y, char *data) {
  int j, k, i = 0, dataLen = My_strlen(data);

  for (i = 0; i < dataLen;) {
    if (data[i] > 127) {
      // if (data[i] < 0) {
      if ((x + GB2312_FONT_H) > EPD_H) {
        x = 0;
        y += ASCII_FONT_W;
        if ((y + ASCII_FONT_W) > EPD_W) {
          goto RET;
        }
      }
      draw_fb_GB2132(x, y, data[i], data[i + 1]);

      x += GB2312_FONT_H;
      i += 2;
    } else {
      if ((x + ASCII_FONT_H) > EPD_H) {
        x = 0;
        y += ASCII_FONT_W;
        if ((y + ASCII_FONT_W) > EPD_W) {
          goto RET;
        }
      }
      draw_fb_ASCII(x, y, data[i]);

      x += ASCII_FONT_H;
      i++;
    }
  }

  // clear lase line screen
  if (x) {
    for (j = x; j < EPD_H; j++) {
      for (k = y; k < (y + ASCII_FONT_W); k++) {
        clear_fb_point(j, k);
      }
    }
    y += ASCII_FONT_W;
  }

RET:
  // clear other line
  for (j = 0; j < EPD_H; j++) {
    for (k = y; k < EPD_W; k++) {
      clear_fb_point(j, k);
    }
  }
  return i;
}

int get_next_text(int x, int y, char *data) {
  int i = 0, dataLen = My_strlen(data);

  for (i = 0; i < dataLen;) {
    if (data[i] > 127) {
      if ((x + GB2312_FONT_H) > EPD_H) {
        x = 0;
        y += ASCII_FONT_W;
        if ((y + ASCII_FONT_W) > EPD_W) {
          goto RET;
        }
      }

      x += GB2312_FONT_H;
      i += 2;
    } else {
      if ((x + ASCII_FONT_H) > EPD_H) {
        x = 0;
        y += ASCII_FONT_W;
        if ((y + ASCII_FONT_W) > EPD_W) {
          goto RET;
        }
      }

      x += ASCII_FONT_H;
      i++;
    }
  }

RET:
  return i;
}

struct epd_pos {
  int pos;
  struct epd_pos *next;
  struct epd_pos *prev;
};

struct epd_pos *posTbl = NULL, *currentPos = NULL;

void posTbl_free(struct epd_pos *tbl) {
  struct epd_pos *nextTbl;

  if (tbl == NULL) {
    return;
  }

  while (tbl->next) {
    nextTbl = tbl->next;
    free(tbl);
    tbl = nextTbl;
  }

  free(tbl);
  return;
}

void posTbl_link(struct epd_pos *tbl, struct epd_pos *new_node) {
  while (tbl->next) {
    tbl = tbl->next;
  }

  tbl->next      = new_node;
  new_node->prev = tbl;
  return;
}

int epd_show(unsigned char txtIndex, char direction) {
  char *pText;
  static unsigned char lastIndex = 0xFF;
  static unsigned int showCount  = 0;
  static int pos                 = 0;
  int textLen;
  struct epd_pos *new_node, *oldPos = currentPos;

  if (txtIndex == 0) {
    pText   = rj_dzs;  // doc1
  } else {
    pText   = dx_dzs;  // doc2
  }
  textLen = My_strlen(pText);

  if (lastIndex != txtIndex) {
    posTbl_free(posTbl);

    posTbl       = (struct epd_pos *)malloc(sizeof(struct epd_pos));
    posTbl->prev = NULL;
    posTbl->next = NULL;
    posTbl->pos  = 0;
    currentPos   = posTbl;
  }

  if (direction == 1) {
    if (currentPos->next) {
      // Saved pos, just goto next pos
      currentPos = currentPos->next;

    } else if (currentPos->pos < (textLen - 1)) {
      // Find for new pos
      pos = currentPos->pos + get_next_text(0, 0, pText + currentPos->pos);
      if (pos <= (textLen - 1)) {
        new_node = (struct epd_pos *)malloc(sizeof(struct epd_pos));

        new_node->pos  = pos;
        new_node->next = NULL;
        posTbl_link(currentPos, new_node);

        currentPos = new_node;
      }
    }
  } else if (direction == 2) {
    // just jump to prev pos if exist
    if (currentPos->prev) {
      currentPos = currentPos->prev;
    }
  }

  // update display
  if ((oldPos != currentPos) || (lastIndex != txtIndex)) {
    draw_fb(0, 0, pText + currentPos->pos);

    showCount++;
    if (showCount > 40) {
      showCount = 0;
      updata_to_epd(DISPLAY_ALL);
    } else {
      updata_to_epd(DISPLAY_PART);
    }
  }

  // update flag
  lastIndex = txtIndex;

  return pos;
}
my_epd.h
int epd_show(unsigned char txtIndex, char direction);

最终显示效果

   其实这位置使用动图或者视频看效果更好,但奈何无环境录制视频,因此直接贴图片。


最终代码

https://www.bilibili.com/video/BV1fHaXenEcz/







关键词: 墨水     电子书     成果     实现    

院士
2024-07-27 14:45:02     打赏
2楼

楼主这也太快了吧!

我这开箱帖子还没有发布呢


专家
2024-07-27 19:25:25     打赏
3楼

感谢分享


专家
2024-07-27 19:58:01     打赏
4楼

感谢分享


高工
2024-07-27 20:07:36     打赏
5楼

感谢分享


共5条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]