野火科技
直播中

知之为知之zhl

4年用户 99经验值
擅长:可编程逻辑 电源/新能源
私信 关注

鲁班猫0 AWTRIX 控制端固件修改烧录

灯光板到了才发现AWTRIX时钟使用的灯光板和我画的灯板扫描顺序不太一样,固件需要修改。

我画的的扫描顺序:

scan.png

原版的扫描顺序:

scan1.png

查阅 AWTRIX 的代码可以看到采用的是 FastLED_NeoMatrix 这个库,这个库是用 C++ 写的库,不过代码结构比较清晰,找出画点的函数 FastLED_NeoMatrix::drawPixel,函数实现如下

void FastLED_NeoMatrix::drawPixel(int16_t x, int16_t y, uint16_t color) {

  if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return;

  _leds[XY(x,y)] = passThruFlag ? passThruColor : expandColor(color);
}

其中 XY(x,y) 函数就是把屏幕的坐标点转换为_leds数组的索引,跳到XY(x,y)函数中查看。

int FastLED_NeoMatrix::XY(int16_t x, int16_t y) {

  // Beware, this returns a special out of bounds value, you need an extra
  // safety pixel at the end of your array to host this, or if you use
  // drawPixel, the value willl get rejected.
  if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return numpix-1;

  int16_t t;
  switch(rotation) {
   case 1:
    t = x;
    x = WIDTH  - 1 - y;
    y = t;
    break;
   case 2:
    x = WIDTH  - 1 - x;
    y = HEIGHT - 1 - y;
    break;
   case 3:
    t = x;
    x = y;
    y = HEIGHT - 1 - t;
    break;
  }

  int tileOffset = 0, pixelOffset;

  if(remapFn) { // Custom X/Y remapping function
    pixelOffset = (*remapFn)(x, y);
  } else {      // Standard single matrix or tiled matrices

    uint8_t  corner = type & NEO_MATRIX_CORNER;
    uint16_t minor, major, majorScale;

    if(tilesX) { // Tiled display, multiple matrices
      uint16_t tile;

      minor = x / matrixWidth;            // Tile # X/Y; presume row major to
      major = y / matrixHeight,           // start (will swap later if needed)
      x     = x - (minor * matrixWidth);  // Pixel X/Y within tile
      y     = y - (major * matrixHeight); // (-* is less math than modulo)

      // Determine corner of entry, flip axes if needed
      if(type & NEO_TILE_RIGHT)  minor = tilesX - 1 - minor;
      if(type & NEO_TILE_BOTTOM) major = tilesY - 1 - major;

      // Determine actual major axis of tiling
      if((type & NEO_TILE_AXIS) == NEO_TILE_ROWS) {
        majorScale = tilesX;
      } else {
        _swap_uint16_t(major, minor);
        majorScale = tilesY;
      }

      // Determine tile number
      if((type & NEO_TILE_SEQUENCE) == NEO_TILE_PROGRESSIVE) {
        // All tiles in same order
        tile = major * majorScale + minor;
      } else {
        // Zigzag; alternate rows change direction.  On these rows,
        // this also flips the starting corner of the matrix for the
        // pixel math later.
        if(major & 1) {
          corner ^= NEO_MATRIX_CORNER;
          tile = (major + 1) * majorScale - 1 - minor;
        } else {
          tile =  major      * majorScale     + minor;
        }
      }

      // Index of first pixel in tile
      tileOffset = tile * matrixWidth * matrixHeight;

    } // else no tiling (handle as single tile)

    // Find pixel number within tile
    minor = x; // Presume row major to start (will swap later if needed)
    major = y;

    // Determine corner of entry, flip axes if needed
    if(corner & NEO_MATRIX_RIGHT)  minor = matrixWidth  - 1 - minor;
    if(corner & NEO_MATRIX_BOTTOM) major = matrixHeight - 1 - major;

    // Determine actual major axis of matrix
    if((type & NEO_MATRIX_AXIS) == NEO_MATRIX_ROWS) {
      majorScale = matrixWidth;
    } else {
      _swap_uint16_t(major, minor);
      majorScale = matrixHeight;
    }

    // Determine pixel number within tile/matrix
    if((type & NEO_MATRIX_SEQUENCE) == NEO_MATRIX_PROGRESSIVE) {
      // All lines in same order
      pixelOffset = major * majorScale + minor;
    } else {
      // Zigzag; alternate rows change direction.
      if(major & 1) pixelOffset = (major + 1) * majorScale - 1 - minor;
      else          pixelOffset =  major      * majorScale     + minor;
    }
  }

  return(tileOffset + pixelOffset);
}

这段代码就是根据当前的旋转方向等信息来计算偏移从而确定其索引。

其中有很重要的一行代码

if(remapFn) { // Custom X/Y remapping function
    pixelOffset = (*remapFn)(x, y);
  }

这行代码调用了一个回调函数,通过回调函数可以实现对于计算数组索引方法的自定义

我画的屏幕是横S形状的扫描方式,简单数学计算可以得到坐标和索引的变换关系为:

y 为偶数时 index = 32 * y;

y 为奇数时 index = 32 * y + 31 - x;

写一个转换函数

uint16_t remapDisp(uint16_t x, uint16_t y) {
  if (y % 2) {

      return (32 * y + x);
  } else {
      return (32 * y + (31 - x));
  }
}

然后初始化函数 matrixInit 中添加一行注册代码,注册到XY函数的回调

matrix->setRemapFunction(remapDisp);

用 VSCode 中的 PIO 插件编译一下

build.png

烧录到ESP8266接上控制板,正常点亮。

normal.jpg

PS:灯光板的大小超了这个木盒子,把四个角切掉,飞线解决;栅格板是用fashion360画,3D打印的,均光板直接剪的A4纸。

cut.png

回帖(1)

dianzi

2023-4-20 09:32:48
横向变竖向了
举报

更多回帖

发帖
×
20
完善资料,
赚取积分