跳转至

U8g2

u8g2适配

给u8g2适配串口屏的代码:

// note: u8g2适配参考文档 https://github.com/olikraus/u8g2/wiki/internal#new-displays
extern const u8x8_display_info_t u8x8_sdl_192x64_info;
class BoardPanelGui : public PanelGui {
public:
  BOOL init(HwSerialPort *sp)
  {
    _sp = sp;
    return PanelGui::init();
  }
  uint8_t _buf[192*64/8];
  HwSerialPort *_sp;
protected:
  BOOL initDisplayBuffer() override
  {
    u8x8_t *u8x8 = u8g2.getU8x8();
    u8x8_SetupDefaults(u8x8);
    u8x8->display_cb = u8x8_d_sdl_192x64;

    /* setup display info */
    u8x8_SetupMemory(u8x8);
    u8g2_SetupBuffer(u8g2.getU8g2(), _buf, 8, u8g2_ll_hvline_vertical_top_lsb, &u8g2_cb_r0);
    return TRUE;
  }
private:
  static uint8_t u8x8_d_sdl_192x64(u8x8_t *u8g2, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  {
    BoardPanelGui* THIS = (BoardPanelGui*) BoardPanelGui::getInstance();

    uint8_t x, y, c, w, h;
    uint8_t *ptr;
    switch(msg) {
      case U8X8_MSG_DISPLAY_SETUP_MEMORY:
        C_LOG("U8X8_MSG_DISPLAY_SETUP_MEMORY");
        u8g2->display_info = &u8x8_sdl_192x64_info;
        u8g2->x_offset = u8x8_sdl_192x64_info.default_x_offset;
        break;
      case U8X8_MSG_DISPLAY_INIT:
        // u8x8_d_helper_display_init(u8g2);
        break;
      case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
        break;
      case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
        break;
      case U8X8_MSG_DISPLAY_SET_CONTRAST:
        break;
      case U8X8_MSG_DISPLAY_DRAW_TILE:
        // C_LOG("U8X8_MSG_DISPLAY_DRAW_TILE");
        x = ((u8x8_tile_t *)arg_ptr)->x_pos;
        x *= 8;
        x += u8g2->x_offset;

        y = ((u8x8_tile_t *)arg_ptr)->y_pos;
        y *= 8;

        c = ((u8x8_tile_t *)arg_ptr)->cnt;
        w = c*8;
        h = 8;
        assert(arg_int == 1);

        ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
        // C_LOG("u8g_sdl_set_multiple_8pixel(%d,%d,%d,ptr)", x, y, c*8);
        send_uart2lcd(x, y, w, h, ptr, w*h/8);
        break;
      default:
        return 0;
    }
    return 1;
  }

  static void trans_uart2lcd_fmt(UINT8 *buf, const UINT8 *dat, int width)
  {
    int cnt_byte = 0, cnt_bits = 0;
    for (int i = 0; i < 8; i++) {
      for (int j = 0; j < width; j++) {
        if (dat[j] & BIT(i)) {
          BIT_SET(buf[cnt_byte], cnt_bits);
        }
        else {
          BIT_CLR(buf[cnt_byte], cnt_bits);
        }

        if (++cnt_bits >= 8) {
          cnt_bits = 0;
          cnt_byte++;
        }
      }
    }
  }

  static void send_uart2lcd(int x, int y, int w, int h, const uint8_t *dat, int datlen)
  {
    BoardPanelGui* THIS = (BoardPanelGui*) BoardPanelGui::getInstance();
    UINT8 t[2048];
    memset(t, 0, sizeof(t));
    t[0] = 'l';
    t[1] = 'c';
    t[2] = 'd';
    t[3] = x;
    t[4] = y;
    t[5] = w;
    t[6] = h;
    trans_uart2lcd_fmt(&t[7], dat, w);

    ssize_t s = 7 + datlen;
    int byte_interval_us = 1e6 / THIS->_sp->getBaudrate() * 11;
    THIS->_sp->write(t, s);
    usleep(byte_interval_us*(s+4));
  }
};