Куб Alexgyver Русский шрифты.

Warcan
Offline
Зарегистрирован: 23.05.2018

Добрый вечер!

Сделал куб по проекту Алекса, но там нет поддержки русского языка. А очень хочется сделать с поддержкой русского. К сожалению я не программировал ардуино до этого, да и не программировал ни когда за исключением каких-то мелочей. 

https://alexgyver.ru/arduino-led-cube/

Куб заработал, но вот с кодом я не смог решить своими силами. По этому прошу помощи.

  {0x02, 0x02, 0x02, 0x02, 0x0C, 0x02, 0x02, 0x02},        
 // } 0x7d 125
  {0x00, 0x00, 0x00, 0x46, 0x49, 0x31, 0x00, 0x00},        
 // ~ 0x7e 126

  {0x7e, 0x09, 0x09, 0x09, 0x7e}, // А 192

Вот кусочек файла fonts.h. Я заметил что английские буквы делались в разрешении 8х8, а вот русские 5х8. Хотя я думаю это от куда-то скопировано и всё. Не правили русские шрифты. Я попробовал создать сам русские буквы. На сайте http://arduino.on.kg/matrix-font . И меня постигла неудача, куб по русски не стал писать. Я пробовал подставить код английских букв русским, но результат тот-же. Я попробовал в редакторе создать английскую букву и понял что они не соответствуют тому что записано в файле fonts.h . Прошу вас помочь разобраться. Спасибо

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Тут гайвера нет. Спросите у него, там где он есть :)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ну так и делай 8х8

0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

 

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Подрисовал несколько символов:

  {0x18, 0x24, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42}, // А 192
  {0x7e, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3e}, // Б
  {0x3E, 0x42, 0x42, 0x3E, 0x42, 0x42, 0x42, 0x3E}, // В
  {0x7e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}, // Г
  {0x18, 0x24, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42}, // Д
  {0x7E, 0x02, 0x02, 0x3E, 0x02, 0x02, 0x02, 0x7E}, // Е
  {0x92, 0x92, 0x54, 0x38, 0x54, 0x92, 0x92, 0x92}, // Ж

Каждое число это одна строка символа начиная с верхней. !!! Младший бит идет первым !!!

https://wokwi.com/projects/331788669107044948

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Komandir пишет:

Подрисовал несколько символов:

  {0x18, 0x24, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42}, // А 192
  {0x7e, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3e}, // Б
  {0x3E, 0x42, 0x42, 0x3E, 0x42, 0x42, 0x42, 0x3E}, // В
  {0x7e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}, // Г
  {0x18, 0x24, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42}, // Д
  {0x7E, 0x02, 0x02, 0x3E, 0x02, 0x02, 0x02, 0x7E}, // Е
  {0x92, 0x92, 0x54, 0x38, 0x54, 0x92, 0x92, 0x92}, // Ж

Каждое число это одна строка символа начиная с верхней. !!! Младший бит идет первым !!!

https://wokwi.com/projects/331788669107044948

Там у тебя много букафф )))

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

ua6em а разве за количество букафф не доплачивают ???

Warcan я сделал страничку в Excel - сможете сами нарисовать шрифт. Куда скинуть ?

Warcan
Offline
Зарегистрирован: 23.05.2018

Попробовал ваши буквы вставить. Но хочет показывать. Видимо гдето в коде что то не то

/*
   Светодиодный куб 8x8x8 на Arduino NANO и сдвиговых регистрах 74HC595
   Версия 2:
   - Добавлен режим игры "Змейка"
   - Добавлена бета версии игры "Танки"
   - Добавлена игра "Туннель"
   - Поправлена динамическая индикация
   - Добавлена инверсия текста

   Разработал VECT, модифицировал AlexGyver
   http://AlexGyver.ru/LEDcube/
   https://github.com/AlexGyver/GyverLibs
   2018 AlexGyver
*/

#define INVERT_Y 1    // инвертировать по вертикали (если дождь идёт вверх)
#define INVERT_X 0    // инвертировать по горизонтали (если текст не читается)
#define MIRROR_FONT 1 // зеркалить текст

#define POT_X 1       // джойстик Х
#define POT_Y 0       // джойстик У

//#define POT_X2 6       // джойстик Х2
//#define POT_Y2 7       // джойстик У2

#define BTN_UP A2     // отдельаня кнопка (вверх)
#define BTN_DWN A3    // кнопка джойстика

#define SNAKE_START 4 // начальная длина змейки

// текст для режима текста
String disp_text = "АБВГДЕЖЗ";

#define XAXIS 0
#define YAXIS 1
#define ZAXIS 2

#define POS_X 0
#define NEG_X 1
#define POS_Z 2
#define NEG_Z 3
#define POS_Y 4
#define NEG_Y 5

#define BUTTON1 18
#define BUTTON2 19

#define RED_LED 5
#define GREEN_LED 7

#define TOTAL_EFFECTS 14  // количество эффектов

/*
   Эффекты по порядку:
   - Дождь
   - Плоскости
   - Лифты
   - Куб масштаб центр
   - Куб масштаб угол
   - Случайное заполнение
   - Бегущий текст
   - Ночник
   - Бегущая волна заполненная
   - Бегущая волна тонкая
   - Кубик рикошеты
   - Змейка
*/

//  некоторые названия режимов
#define RAIN 0
#define PLANE_BOING 1
#define SEND_VOXELS 2
#define WOOP_WOOP 3
#define CUBE_JUMP 4
#define GLOW 5
#define TEXT 6
#define LIT 7
#define SNAKE 11
#define SHOOTER 12
#define TUNNEL 13

// таймеры режимов
#define RAIN_TIME 260
#define PLANE_BOING_TIME 220
#define SEND_VOXELS_TIME 140
#define WOOP_WOOP_TIME 350
#define CUBE_JUMP_TIME 200
#define GLOW_TIME 8
#define TEXT_TIME 200
#define CLOCK_TIME 500
#define WALKING_TIME 100
#define SNAKE_TIME 700
#define SHOOTER_TIME 400
#define TUNNEL_TIME 300

#include <SPI.h>
#include "GyverButton.h"    // либа для кнопок
#include "GyverHacks.h"     // либа для быстрйо записи в порт
#include "GyverTimer.h"     // либа для таймеров
#include "fonts.h"          // шрифт

GButton butt1(BUTTON1);
GButton butt2(BUTTON2);
GButton butt_up(BTN_UP);
GButton butt_dwn(BTN_DWN);
GTimer_ms tankTimer(100);

// переменные
boolean showResult;
byte lastMode;
uint32_t millTimer;
uint8_t cube[8][8];
int8_t currentEffect;
uint16_t timer;
uint16_t modeTimer;
bool loading;
int8_t pos;
int8_t vector[3];
int16_t coord[3];
byte score;

void setup() {
  Serial.begin(9600);

  SPI.begin();
  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
  //pinMode(RED_LED, OUTPUT);
  //pinMode(GREEN_LED, OUTPUT);
  randomSeed(analogRead(0));
  //digitalWrite(GREEN_LED, HIGH);

  butt1.setStepTimeout(100);    // настрйока интервала инкремента (по умолчанию 800 мс)
  butt2.setStepTimeout(100);    // настрйока интервала инкремента (по умолчанию 800 мс)

  loading = true;
  currentEffect = TEXT;
  changeMode();
}

void loop() {
  butt1.tick();
  butt2.tick();

  if (butt1.isClick()) {
    currentEffect++;
    if (currentEffect >= TOTAL_EFFECTS) currentEffect = 0;
    changeMode();
  }
  if (butt2.isClick()) {
    currentEffect--;
    if (currentEffect < 0) currentEffect = TOTAL_EFFECTS - 1;
    changeMode();
  }

  if (butt1.isStep()) {                                 // если кнопка была удержана (это для инкремента)
    modeTimer += 10;
  }
  if (butt2.isStep()) {                                 // если кнопка была удержана (это для инкремента)
    modeTimer -= 10;
  }

  switch (currentEffect) {
    case RAIN: rain(); break;
    case PLANE_BOING: planeBoing(); break;
    case SEND_VOXELS: sendVoxels(); break;
    case WOOP_WOOP: woopWoop(); break;
    case CUBE_JUMP: cubeJump(); break;
    case GLOW: glow(); break;
    case TEXT:
      if (showResult) {
        String result = String(score);
        text(result, result.length());
      } else {
        text(disp_text, disp_text.length());
      }
      break;
    case LIT: lit(); break;
    case 8: sinusFill(); break;
    case 9: sinusThin(); break;
    case 10: walkingCube(); break;
    case 11: snake(); break;
    case 12: shooter(); break;
    case 13: tunnel(); break;
  }
  renderCube();
}

void changeMode() {
  clearCube();
  loading = true;
  timer = 0;
  randomSeed(millis());
  digitalWrite(RED_LED, HIGH);
  digitalWrite(GREEN_LED, LOW);
  delay(500);
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, HIGH);

  switch (currentEffect) {
    case RAIN: modeTimer = RAIN_TIME; break;
    case PLANE_BOING: modeTimer = PLANE_BOING_TIME; break;
    case SEND_VOXELS: modeTimer = SEND_VOXELS_TIME; break;
    case WOOP_WOOP: modeTimer = WOOP_WOOP_TIME; break;
    case CUBE_JUMP: modeTimer = CUBE_JUMP_TIME; break;
    case GLOW: modeTimer = GLOW_TIME; break;
    case TEXT: modeTimer = TEXT_TIME; break;
    case LIT: modeTimer = CLOCK_TIME; break;
    case 8: modeTimer = RAIN_TIME; break;
    case 9: modeTimer = RAIN_TIME; break;
    case 10: modeTimer = WALKING_TIME; break;
    case 11: modeTimer = SNAKE_TIME; break;
    case 12: modeTimer = SHOOTER_TIME; break;
    case 13: modeTimer = TUNNEL_TIME; break;
  }
}

void renderCube() {
  for (uint8_t i = 0; i < 8; i++) {
    setPin(SS, LOW);
    if (INVERT_Y) SPI.transfer(0x01 << (7 - i));
    else SPI.transfer(0x01 << i);

    for (uint8_t j = 0; j < 8; j++) {
      if (INVERT_X) SPI.transfer(cube[7 - i][j]);
      else SPI.transfer(cube[i][j]);
    }
    setPin(SS, HIGH);
    delayMicroseconds(50);
  }

  // вырубаем всё
  setPin(SS, LOW);
  SPI.transfer(0x00);
  setPin(SS, HIGH);
}

int8_t tank1[2], tank2[2];
boolean bullet1_f, bullet2_f;
int8_t bullet1[3], bullet2[3];
int8_t planePos;
byte planeType, prevType;
boolean planeFlag;

void tunnel() {
  if (loading) {
    clearCube();
    loading = false;
    tank1[0] = 0;
    tank1[1] = 0;
    score = 0;
    planePos = 7;
    planeFlag = false;
  }
  timer++;


  if (tankTimer.isReady()) {
    clearCube();
    if (timer > modeTimer) {
      timer = 0;

      planePos--;

      if (planePos == 1) {  // проверка на столкновение с кубом
        boolean gameOver = false;
        switch (planeType) {
          case 0: gameOver = checkPlane(0, 4, 1, 7);
            break;
          case 1: gameOver = checkPlane(3, 7, 1, 7);
            break;
          case 2: gameOver = checkPlane(2, 5, 1, 7);
            break;
          case 3: gameOver = checkPlane(0, 7, 0, 4);
            break;
          case 4: gameOver = checkPlane(0, 7, 3, 7);
            break;
          case 5: gameOver = checkPlane(0, 7, 2, 5);
            break;
          case 6:
            // проверка сложной фигуры, флаг gameOver не превысит 1
            gameOver += checkPlane(0, 1, 0, 7);
            gameOver += checkPlane(6, 7, 0, 7);
            gameOver += checkPlane(2, 5, 0, 2);
            gameOver += checkPlane(2, 5, 6, 7);
            break;
          case 7:
            // проверка сложной фигуры, флаг gameOver не превысит 1
            gameOver += checkPlane(0, 3, 0, 7);
            gameOver += checkPlane(3, 7, 0, 3);
            break;
          case 8:
            // проверка сложной фигуры, флаг gameOver не превысит 1
            gameOver += checkPlane(5, 7, 0, 7);
            gameOver += checkPlane(0, 4, 4, 7);
            break;
        }
        if (gameOver) {
          showResult = true;
          lastMode = TUNNEL;
          currentEffect = TEXT;
          changeMode();                             // всё по новой
          return;                                   // выходим из функции snake()
        } else {
          score++;
        }
      }

      if (planePos < 0) {
        planeFlag = false;
      }

      if (!planeFlag) {
        planeFlag = true;
        while (planeType == prevType) {   // генерируем, пока не будет отличаться от прежнего
          planeType = random(0, 9);
        }
        prevType = planeType;
        planePos = 7;
      }
    }

    if (planeFlag) {
      switch (planeType) {
        case 0: generatePlane(0, 4, 1, 7, planePos);
          break;
        case 1: generatePlane(3, 7, 1, 7, planePos);
          break;
        case 2: generatePlane(2, 5, 1, 7, planePos);
          break;
        case 3: generatePlane(0, 7, 0, 4, planePos);
          break;
        case 4: generatePlane(0, 7, 3, 7, planePos);
          break;
        case 5: generatePlane(0, 7, 2, 5, planePos);
          break;
        case 6: generatePlane(0, 1, 0, 7, planePos);
          generatePlane(6, 7, 0, 7, planePos);
          generatePlane(2, 5, 0, 2, planePos);
          generatePlane(2, 5, 6, 7, planePos);
          break;
        case 7: generatePlane(0, 3, 0, 7, planePos);
          generatePlane(3, 7, 0, 3, planePos);
          break;
        case 8: generatePlane(5, 7, 0, 7, planePos);
          generatePlane(0, 4, 4, 7, planePos);
          break;
      }
    }

    if (analogRead(POT_Y) > 800) tank1[0] -= 1;
    if (analogRead(POT_Y) < 300) tank1[0] += 1;
    if (analogRead(POT_X) > 800) tank1[1] -= 1;
    if (analogRead(POT_X) < 300) tank1[1] += 1;

    for (byte i = 0; i < 2; i++) {
      // выход за 0
      if (tank1[i] < 0) tank1[i] = 0;

      // выход за 7 (кубик 2х2х2 поэтому до 6)
      if (tank1[i] > 6) tank1[i] = 6;
    }

    // рисуем кубик
    for (byte i = 0; i < 2; i++)
      for (byte j = 0; j < 2; j++)
        for (byte k = 0; k < 2; k++)
          setVoxel(tank1[0] + i, tank1[1] + j, 0 + k);
  }
}

// рисует пластинку по 4 углам и глубина k
void generatePlane(byte fromX, byte toX, byte fromY, byte toY, byte k) {
  for (byte i = fromX; i <= toX; i++)
    for (byte j = fromY; j <= toY; j++)
      setVoxel(i, j, k);
}

boolean checkPlane(byte fromX, byte toX, byte fromY, byte toY) {
  for (byte i = fromX; i <= toX; i++)
    for (byte j = fromY; j <= toY; j++) {
      for (byte x = 0; x < 2; x++)
        for (byte y = 0; y < 2; y++)
          if (i == (tank1[0] + x) && j == (tank1[1] + y)) return true;
    }
  return false;
}

void shooter() {
  if (loading) {
    clearCube();
    loading = false;
    tank1[0] = 0;
    tank1[1] = 0;
    tank2[0] = 0;
    tank2[1] = 0;
  }

  timer++;
  if (timer > modeTimer) {
    timer = 0;
    if (bullet1_f) {
      bullet1[2] += 1;
      if (bullet1[2] > 7) {
        bullet1_f = false;
      } else {
        setVoxel(bullet1[0], bullet1[1], bullet1[2]);
      }
    }
  }

  if (tankTimer.isReady()) {
    clearCube();
    if (analogRead(POT_Y) > 800) tank1[0] -= 1;
    if (analogRead(POT_Y) < 300) tank1[0] += 1;
    if (analogRead(POT_X) > 800) tank1[1] -= 1;
    if (analogRead(POT_X) < 300) tank1[1] += 1;

    if (!digitalRead(BTN_UP) && !bullet1_f) {
      bullet1_f = true;
      bullet1[0] = tank1[0] + 1;
      bullet1[1] = tank1[1] + 1;
      bullet1[2] = 1;
    }

    for (byte i = 0; i < 2; i++) {
      if (tank1[i] < 0) tank1[i] = 0;
      if (tank2[i] < 0) tank2[i] = 0;

      if (tank1[i] > 5) tank1[i] = 5;
      if (tank2[i] > 5) tank2[i] = 5;
    }

    for (byte i = 0; i < 3; i++) {
      for (byte j = 0; j < 3; j++) {
        setVoxel(tank1[0] + i, tank1[1] + j, 0);
      }
    }
    setVoxel(tank1[0] + 1, tank1[1] + 1, 1);
  }
}

boolean appleGen = true;
boolean appleEaten = false;
byte snakeArray[100][3];
byte snakeLength;
int8_t head[3];
int8_t butt[3];
byte apple[3];
enum direction {UP, DOWN, LEFT, RIGHT, FORWARD, BACKWARD, STOP} dir;

void snake() {
  if (loading) {
    loading = false;
    millTimer = millis();
    appleGen = true;
    appleEaten = false;
    dir = FORWARD;
    head[0] = 0;
    head[1] = 7;
    head[2] = SNAKE_START - 1;
    snakeLength = SNAKE_START;
    butt[0] = 0;
    butt[1] = 7;
    butt[2] = 0;
    for (byte i = 0; i < SNAKE_START; i++) {
      snakeArray[i][0] = 0;
      snakeArray[i][1] = 7;
      snakeArray[i][2] = i;
      setVoxel(0, 7, i);
    }
  }
  butt_up.tick();
  butt_dwn.tick();

  // опрос кнопок и выбор направления
  // с учётом запрета двигаться назад (в змею)
  if (butt_up.isPress())
    if (dir != DOWN)
      dir = UP;

  if (butt_dwn.isPress())
    if (dir != UP)
      dir = DOWN;

  if (analogRead(POT_Y) > 800)
    if (dir != RIGHT)
      dir = LEFT;

  if (analogRead(POT_Y) < 300)
    if (dir != LEFT)
      dir = RIGHT;

  if (analogRead(POT_X) > 800)
    if (dir != FORWARD)
      dir = BACKWARD;

  if (analogRead(POT_X) < 300)
    if (dir != BACKWARD)
      dir = FORWARD;

  // таймер движения
  if (millis() - millTimer >= modeTimer) {
    millTimer = millis();

    // движение головы змеи в трёх плоскостях, изменяем координату
    switch (dir) {
      case UP: head[1] -= 1;
        break;
      case DOWN: head[1] += 1;
        break;
      case LEFT: head[0] -= 1;
        break;
      case RIGHT: head[0] += 1;
        break;
      case FORWARD: head[2] += 1;
        break;
      case BACKWARD: head[2] -= 1;
        break;
    }

    if (appleGen) {
      appleGen = false;

      byte success = false;
      while (!success) {      // бесконечный цикл генерации яблока
        // генерируем случайные координаты X Y Z
        apple[0] = random(0, 8);
        apple[1] = random(0, 8);
        apple[2] = random(0, 8);

        // проверяем на совпадение со змеёй
        success = true;
        for (byte i = 0; i < snakeLength; i++) {
          for (byte j = 0; j < 3; j++) {          // для трёх координат
            if (snakeArray[i][j] == apple[j]) {   // проверяем на совпадение с координатами тела змеи
              success = false;
              break;
            }
          }
        }
      }
      setVoxel(apple[0], apple[1], apple[2]);     // рисуем яблоко
    }

    // проверка на столкновение с собой
    for (byte i = 0; i < snakeLength; i++) {
      if (snakeArray[i][0] == head[0] &&
          snakeArray[i][1] == head[1] &&
          snakeArray[i][2] == head[2]) {
        showResult = true;
        lastMode = SNAKE;
        score = snakeLength - SNAKE_START;
        currentEffect = TEXT;
        changeMode();                             // всё по новой
        appleEaten = false;
        return;                                   // выходим из функции snake()
      }
    }

    appleEaten = true;                            // делаем предположение, что координата головы совпала с яблоком
    for (byte i = 0; i < 3; i++) {                // для всех трёх осей поочереди
      if (head[i] != apple[i])                    // если хоть одна координата головы не совпадает с яблоком
        appleEaten = false;                       // предположение неверно
      if (head[i] < 0 || head[i] > 7) {           // если удар головой в стену
        showResult = true;
        lastMode = SNAKE;
        score = snakeLength - SNAKE_START;
        currentEffect = TEXT;
        changeMode();                             // всё по новой
        appleEaten = false;
        return;                                   // выходим из функции snake()
      }

      butt[i] = snakeArray[0][i];                 // хвост принимает координаты из массива змеи (из ячейки 0)
      snakeArray[snakeLength][i] = head[i];       // массив змеи принимает координаты головы змеи в ячейку с длиной змеи
    }

    if (!appleEaten) {                              // если яблоко съедено
      for (byte i = 0; i < snakeLength; i++) {      // для всей длины змеи
        for (byte j = 0; j < 3; j++) {              // для трёх координат
          snakeArray[i][j] = snakeArray[i + 1][j];  // смещаем массив змеи на один шаг влево
        }
      }
      clearVoxel(butt[0], butt[1], butt[2]);        // стираем хвост
    } else {
      snakeLength++;                                // длина змеи увеличилась
      appleEaten = false;                           // опустить флаг
      appleGen = true;                              // разрешаем генерацию нового яблока
    }

    setVoxel(head[0], head[1], head[2]);            // рисуем новое положение головы змеи
  }
}

void walkingCube() {
  if (loading) {
    clearCube();
    loading = false;
    for (byte i = 0; i < 3; i++) {
      // координата от о до 700!
      coord[i] = 300;
      vector[i] = random(3, 8) * 15;
    }
  }
  timer++;
  if (timer > modeTimer) {
    timer = 0;
    clearCube();
    for (byte i = 0; i < 3; i++) {
      coord[i] += vector[i];
      if (coord[i] < 1) {
        coord[i] = 1;
        vector[i] = -vector[i];
        vector[i] += random(0, 6) - 3;
      }
      if (coord[i] > 700 - 100) {
        coord[i] = 700 - 100;
        vector[i] = -vector[i];
        vector[i] += random(0, 6) - 3;
      }
    }

    int8_t thisX = coord[0] / 100;
    int8_t thisY = coord[1] / 100;
    int8_t thisZ = coord[2] / 100;

    setVoxel(thisX, thisY, thisZ);
    setVoxel(thisX + 1, thisY, thisZ);
    setVoxel(thisX, thisY + 1, thisZ);
    setVoxel(thisX, thisY, thisZ + 1);
    setVoxel(thisX + 1, thisY + 1, thisZ);
    setVoxel(thisX, thisY + 1, thisZ + 1);
    setVoxel(thisX + 1, thisY, thisZ + 1);
    setVoxel(thisX + 1, thisY + 1, thisZ + 1);
  }
}

void sinusFill() {
  if (loading) {
    clearCube();
    loading = false;
  }
  timer++;
  if (timer > modeTimer) {
    timer = 0;
    clearCube();
    if (++pos > 10) pos = 0;
    for (uint8_t i = 0; i < 8; i++) {
      for (uint8_t j = 0; j < 8; j++) {
        int8_t sinZ = 4 + ((float)sin((float)(i + pos) / 2) * 2);
        for (uint8_t y = 0; y < sinZ; y++) {
          setVoxel(i, y, j);
        }
      }
    }
  }
}

void sinusThin() {
  if (loading) {
    clearCube();
    loading = false;
  }
  timer++;
  if (timer > modeTimer) {
    timer = 0;
    clearCube();
    if (++pos > 10) pos = 0;
    for (uint8_t i = 0; i < 8; i++) {
      for (uint8_t j = 0; j < 8; j++) {
        int8_t sinZ = 4 + ((float)sin((float)(i + pos) / 2) * 2);
        setVoxel(i, sinZ, j);
      }
    }
  }
}

void rain() {
  if (loading) {
    clearCube();
    loading = false;
  }
  timer++;
  if (timer > modeTimer) {
    timer = 0;
    shift(NEG_Y);
    uint8_t numDrops = random(0, 5);
    for (uint8_t i = 0; i < numDrops; i++) {
      setVoxel(random(0, 8), 7, random(0, 8));
    }
  }
}

uint8_t planePosition = 0;
uint8_t planeDirection = 0;
bool looped = false;

void planeBoing() {
  if (loading) {
    clearCube();
    uint8_t axis = random(0, 3);
    planePosition = random(0, 2) * 7;
    setPlane(axis, planePosition);
    if (axis == XAXIS) {
      if (planePosition == 0) {
        planeDirection = POS_X;
      } else {
        planeDirection = NEG_X;
      }
    } else if (axis == YAXIS) {
      if (planePosition == 0) {
        planeDirection = POS_Y;
      } else {
        planeDirection = NEG_Y;
      }
    } else if (axis == ZAXIS) {
      if (planePosition == 0) {
        planeDirection = POS_Z;
      } else {
        planeDirection = NEG_Z;
      }
    }
    timer = 0;
    looped = false;
    loading = false;
  }

  timer++;
  if (timer > modeTimer) {
    timer = 0;
    shift(planeDirection);
    if (planeDirection % 2 == 0) {
      planePosition++;
      if (planePosition == 7) {
        if (looped) {
          loading = true;
        } else {
          planeDirection++;
          looped = true;
        }
      }
    } else {
      planePosition--;
      if (planePosition == 0) {
        if (looped) {
          loading = true;
        } else {
          planeDirection--;
          looped = true;
        }
      }
    }
  }
}

uint8_t selX = 0;
uint8_t selY = 0;
uint8_t selZ = 0;
uint8_t sendDirection = 0;
bool sending = false;

void sendVoxels() {
  if (loading) {
    clearCube();
    for (uint8_t x = 0; x < 8; x++) {
      for (uint8_t z = 0; z < 8; z++) {
        setVoxel(x, random(0, 2) * 7, z);
      }
    }
    loading = false;
  }

  timer++;
  if (timer > modeTimer) {
    timer = 0;
    if (!sending) {
      selX = random(0, 8);
      selZ = random(0, 8);
      if (getVoxel(selX, 0, selZ)) {
        selY = 0;
        sendDirection = POS_Y;
      } else if (getVoxel(selX, 7, selZ)) {
        selY = 7;
        sendDirection = NEG_Y;
      }
      sending = true;
    } else {
      if (sendDirection == POS_Y) {
        selY++;
        setVoxel(selX, selY, selZ);
        clearVoxel(selX, selY - 1, selZ);
        if (selY == 7) {
          sending = false;
        }
      } else {
        selY--;
        setVoxel(selX, selY, selZ);
        clearVoxel(selX, selY + 1, selZ);
        if (selY == 0) {
          sending = false;
        }
      }
    }
  }
}

uint8_t cubeSize = 0;
bool cubeExpanding = true;

void woopWoop() {
  if (loading) {
    clearCube();
    cubeSize = 2;
    cubeExpanding = true;
    loading = false;
  }

  timer++;
  if (timer > modeTimer) {
    timer = 0;
    if (cubeExpanding) {
      cubeSize += 2;
      if (cubeSize == 8) {
        cubeExpanding = false;
      }
    } else {
      cubeSize -= 2;
      if (cubeSize == 2) {
        cubeExpanding = true;
      }
    }
    clearCube();
    drawCube(4 - cubeSize / 2, 4 - cubeSize / 2, 4 - cubeSize / 2, cubeSize);
  }
}

uint8_t xPos;
uint8_t yPos;
uint8_t zPos;

void cubeJump() {
  if (loading) {
    clearCube();
    xPos = random(0, 2) * 7;
    yPos = random(0, 2) * 7;
    zPos = random(0, 2) * 7;
    cubeSize = 8;
    cubeExpanding = false;
    loading = false;
  }

  timer++;
  if (timer > modeTimer) {
    timer = 0;
    clearCube();
    if (xPos == 0 && yPos == 0 && zPos == 0) {
      drawCube(xPos, yPos, zPos, cubeSize);
    } else if (xPos == 7 && yPos == 7 && zPos == 7) {
      drawCube(xPos + 1 - cubeSize, yPos + 1 - cubeSize, zPos + 1 - cubeSize, cubeSize);
    } else if (xPos == 7 && yPos == 0 && zPos == 0) {
      drawCube(xPos + 1 - cubeSize, yPos, zPos, cubeSize);
    } else if (xPos == 0 && yPos == 7 && zPos == 0) {
      drawCube(xPos, yPos + 1 - cubeSize, zPos, cubeSize);
    } else if (xPos == 0 && yPos == 0 && zPos == 7) {
      drawCube(xPos, yPos, zPos + 1 - cubeSize, cubeSize);
    } else if (xPos == 7 && yPos == 7 && zPos == 0) {
      drawCube(xPos + 1 - cubeSize, yPos + 1 - cubeSize, zPos, cubeSize);
    } else if (xPos == 0 && yPos == 7 && zPos == 7) {
      drawCube(xPos, yPos + 1 - cubeSize, zPos + 1 - cubeSize, cubeSize);
    } else if (xPos == 7 && yPos == 0 && zPos == 7) {
      drawCube(xPos + 1 - cubeSize, yPos, zPos + 1 - cubeSize, cubeSize);
    }
    if (cubeExpanding) {
      cubeSize++;
      if (cubeSize == 8) {
        cubeExpanding = false;
        xPos = random(0, 2) * 7;
        yPos = random(0, 2) * 7;
        zPos = random(0, 2) * 7;
      }
    } else {
      cubeSize--;
      if (cubeSize == 1) {
        cubeExpanding = true;
      }
    }
  }
}

bool glowing;
uint16_t glowCount = 0;

void glow() {
  if (loading) {
    clearCube();
    glowCount = 0;
    glowing = true;
    loading = false;
  }

  timer++;
  if (timer > modeTimer) {
    timer = 0;
    if (glowing) {
      if (glowCount < 448) {
        do {
          selX = random(0, 8);
          selY = random(0, 8);
          selZ = random(0, 8);
        } while (getVoxel(selX, selY, selZ));
        setVoxel(selX, selY, selZ);
        glowCount++;
      } else if (glowCount < 512) {
        lightCube();
        glowCount++;
      } else {
        glowing = false;
        glowCount = 0;
      }
    } else {
      if (glowCount < 448) {
        do {
          selX = random(0, 8);
          selY = random(0, 8);
          selZ = random(0, 8);
        } while (!getVoxel(selX, selY, selZ));
        clearVoxel(selX, selY, selZ);
        glowCount++;
      } else {
        clearCube();
        glowing = true;
        glowCount = 0;
      }
    }
  }
}

uint8_t charCounter = 0;
uint8_t charPosition = 0;

void text(String someText, byte textLength) {
  if (loading) {
    clearCube();
    charPosition = -1;
    charCounter = 0;
    loading = false;
  }
  timer++;
  if (timer > modeTimer) {
    timer = 0;

    shift(NEG_Z);
    charPosition++;

    if (charPosition == 7) {
      charCounter++;
      if (charCounter > textLength - 1) {
        charCounter = 0;
        if (showResult) {         // если играли в змейку и проиграли
          showResult = false;     // опустить флаг
          currentEffect = lastMode;     // включить прошлый режим
          changeMode();           // активировать режим
          return;                 // покинуть функцию text
        }
      }
      charPosition = 0;
    }
    if (charPosition == 0) {
      for (uint8_t i = 0; i < 8; i++) {
        byte thisFont = getFont(someText[charCounter], i);
        byte mirrorFont = 0;
        for (byte i = 0; i < 7; i++) {
          if (thisFont & (1 << 6 - i)) mirrorFont |= (1 << i);
          else mirrorFont |= (0 << i);
        }
        if (MIRROR_FONT) cube[i][0] = mirrorFont;
        else cube[i][0] = thisFont;
      }
    }
  }
}

void lit() {
  if (loading) {
    clearCube();
    for (uint8_t i = 0; i < 8; i++) {
      for (uint8_t j = 0; j < 8; j++) {
        cube[i][j] = 0xFF;
      }
    }
    loading = false;
  }
}

void setVoxel(uint8_t x, uint8_t y, uint8_t z) {
  cube[7 - y][7 - z] |= (0x01 << x);
}

void clearVoxel(uint8_t x, uint8_t y, uint8_t z) {
  cube[7 - y][7 - z] ^= (0x01 << x);
}

bool getVoxel(uint8_t x, uint8_t y, uint8_t z) {
  return (cube[7 - y][7 - z] & (0x01 << x)) == (0x01 << x);
}

void setPlane(uint8_t axis, uint8_t i) {
  for (uint8_t j = 0; j < 8; j++) {
    for (uint8_t k = 0; k < 8; k++) {
      if (axis == XAXIS) {
        setVoxel(i, j, k);
      } else if (axis == YAXIS) {
        setVoxel(j, i, k);
      } else if (axis == ZAXIS) {
        setVoxel(j, k, i);
      }
    }
  }
}

void shift(uint8_t dir) {

  if (dir == POS_X) {
    for (uint8_t y = 0; y < 8; y++) {
      for (uint8_t z = 0; z < 8; z++) {
        cube[y][z] = cube[y][z] << 1;
      }
    }
  } else if (dir == NEG_X) {
    for (uint8_t y = 0; y < 8; y++) {
      for (uint8_t z = 0; z < 8; z++) {
        cube[y][z] = cube[y][z] >> 1;
      }
    }
  } else if (dir == POS_Y) {
    for (uint8_t y = 1; y < 8; y++) {
      for (uint8_t z = 0; z < 8; z++) {
        cube[y - 1][z] = cube[y][z];
      }
    }
    for (uint8_t i = 0; i < 8; i++) {
      cube[7][i] = 0;
    }
  } else if (dir == NEG_Y) {
    for (uint8_t y = 7; y > 0; y--) {
      for (uint8_t z = 0; z < 8; z++) {
        cube[y][z] = cube[y - 1][z];
      }
    }
    for (uint8_t i = 0; i < 8; i++) {
      cube[0][i] = 0;
    }
  } else if (dir == POS_Z) {
    for (uint8_t y = 0; y < 8; y++) {
      for (uint8_t z = 1; z < 8; z++) {
        cube[y][z - 1] = cube[y][z];
      }
    }
    for (uint8_t i = 0; i < 8; i++) {
      cube[i][7] = 0;
    }
  } else if (dir == NEG_Z) {
    for (uint8_t y = 0; y < 8; y++) {
      for (uint8_t z = 7; z > 0; z--) {
        cube[y][z] = cube[y][z - 1];
      }
    }
    for (uint8_t i = 0; i < 8; i++) {
      cube[i][0] = 0;
    }
  }
}

void drawCube(uint8_t x, uint8_t y, uint8_t z, uint8_t s) {
  for (uint8_t i = 0; i < s; i++) {
    setVoxel(x, y + i, z);
    setVoxel(x + i, y, z);
    setVoxel(x, y, z + i);
    setVoxel(x + s - 1, y + i, z + s - 1);
    setVoxel(x + i, y + s - 1, z + s - 1);
    setVoxel(x + s - 1, y + s - 1, z + i);
    setVoxel(x + s - 1, y + i, z);
    setVoxel(x, y + i, z + s - 1);
    setVoxel(x + i, y + s - 1, z);
    setVoxel(x + i, y, z + s - 1);
    setVoxel(x + s - 1, y, z + i);
    setVoxel(x, y + s - 1, z + i);
  }
}

void lightCube() {
  for (uint8_t i = 0; i < 8; i++) {
    for (uint8_t j = 0; j < 8; j++) {
      cube[i][j] = 0xFF;
    }
  }
}

void clearCube() {
  for (uint8_t i = 0; i < 8; i++) {
    for (uint8_t j = 0; j < 8; j++) {
      cube[i][j] = 0;
    }
  }
}

 

Warcan
Offline
Зарегистрирован: 23.05.2018

warcan@mail.ru

Нарисую конечно сам. Спасибо! 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Выслал. Рисуйте 1 (единичками) там где нужны точки и 0 (ноликами) или очищайте там где не нужны.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Русские буквы кодируются двумя символами, а английские одним.

Вот так надо добавить функцию для перекодировки в Windows-1251 и через неё объявлять выводимую строку... https://wokwi.com/projects/331788669107044948

String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}

String disp_text = utf8rus("Test-АБВГДЕЖ");

 

Warcan
Offline
Зарегистрирован: 23.05.2018

Огромное спасибо за файл для шрифта. Я с помощью него создал шрифты. Но в прямую это не заработало. Вот что у меня получилось. Но бейте особо я первый раз шрифт рисовал.

const uint8_t fontHEX[][8] PROGMEM = {
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //   0x20 32
  {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02}, // ! 0x21 33
  {0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // " 0x22 34
  {0x28, 0x28, 0x7E, 0x14, 0x14, 0x3F, 0x0A, 0x0A}, // # 0x23 35
  {0x04, 0x1E, 0x05, 0x05, 0x0E, 0x14, 0x14, 0x0F}, // $ 0x24 36
  {0x46, 0x49, 0x29, 0x26, 0x90, 0x50, 0x48, 0x88}, // % 0x25 37
  {0x06, 0x09, 0x09, 0x26, 0x29, 0x11, 0x31, 0x4E}, // & 0x26 38
  {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' 0x27 39
  {0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02}, // ( 0x28 40
  {0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02}, // ) 0x29 41
  {0x15, 0x0E, 0x15, 0x04, 0x00, 0x00, 0x00, 0x00}, // * 0x2a 42
  {0x00, 0x08, 0x08, 0x08, 0x7F, 0x08, 0x08, 0x08}, // + 0x2b 43
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02}, // , 0x2c 44
  {0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00}, // - 0x2d 45
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02}, // . 0x2e 46
  {0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01}, // / 0x2f 47
  {0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E}, // 0 0x30 48
  {0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E}, // 1 0x31 49
  {0x0E, 0x11, 0x10, 0x08, 0x04, 0x02, 0x01, 0x1F}, // 2 0x32 50
  {0x0E, 0x11, 0x10, 0x0C, 0x10, 0x10, 0x11, 0x0E}, // 3 0x33 51
  {0x08, 0x0C, 0x0A, 0x09, 0x1F, 0x08, 0x08, 0x08}, // 4 0x34 52
  {0x1F, 0x01, 0x01, 0x0F, 0x10, 0x10, 0x11, 0x0E}, // 5 0x35 53
  {0x0C, 0x02, 0x01, 0x0F, 0x11, 0x11, 0x11, 0x0E}, // 6 0x36 54
  {0x1F, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02}, // 7 0x37 55
  {0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x11, 0x0E}, // 8 0x38 56
  {0x0E, 0x11, 0x11, 0x11, 0x1E, 0x10, 0x08, 0x06}, // 9 0x39 57
  {0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02}, // : 0x3a 58
  {0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02}, // ; 0x3b 59
  {0x00, 0x40, 0x30, 0x0C, 0x02, 0x0C, 0x30, 0x40}, // < 0x3c 60
  {0x00, 0x00, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x00}, // = 0x3d 61
  {0x00, 0x02, 0x0C, 0x30, 0x40, 0x30, 0x0C, 0x02}, // > 0x3e 62
  {0x07, 0x08, 0x08, 0x04, 0x02, 0x02, 0x00, 0x02}, // ? 0x3f 63
  {0x7C, 0x82, 0x39, 0x25, 0x25, 0x25, 0xF9, 0x02}, // @ 0x40 64
  {0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42}, // A 0x41 65
  {0x1E, 0x22, 0x22, 0x1E, 0x22, 0x22, 0x22, 0x1E}, // B 0x42 66
  {0x78, 0x04, 0x02, 0x02, 0x02, 0x02, 0x04, 0x78}, // C 0x43 67
  {0x1E, 0x22, 0x42, 0x42, 0x42, 0x42, 0x22, 0x1E}, // D 0x44 68
  {0x3E, 0x02, 0x02, 0x1E, 0x02, 0x02, 0x02, 0x3E}, // E 0x45 69
  {0x3E, 0x02, 0x02, 0x3E, 0x02, 0x02, 0x02, 0x02}, // F 0x46 70
  {0x78, 0x04, 0x02, 0x02, 0x72, 0x42, 0x44, 0x78}, // G 0x47 71
  {0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42}, // H 0x48 72
  {0x1C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C}, // I 0x49 73
  {0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1C}, // J 0x4a 74
  {0x22, 0x12, 0x0A, 0x06, 0x06, 0x0A, 0x12, 0x22}, // K 0x4b 75
  {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x3C}, // L 0x4c 76
  {0x63, 0x63, 0x55, 0x55, 0x49, 0x49, 0x41, 0x41}, // M 0x4d 77
  {0x46, 0x46, 0x4A, 0x4A, 0x52, 0x52, 0x62, 0x62}, // N 0x4e 78
  {0x1C, 0x22, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1C}, // O 0x4f 79
  {0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x02, 0x02}, // P 0x50 80
  {0x1C, 0x22, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1C}, // Q 0x51 81
  {0x1E, 0x22, 0x22, 0x22, 0x1E, 0x12, 0x22, 0x42}, // R 0x52 82
  {0x3C, 0x02, 0x02, 0x1C, 0x20, 0x20, 0x20, 0x1E}, // S 0x53 83
  {0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, // T 0x54 84
  {0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C}, // U 0x55 85
  {0x22, 0x22, 0x22, 0x14, 0x14, 0x14, 0x08, 0x08}, // V 0x56 86
  {0x91, 0x91, 0x91, 0xAA, 0xAA, 0xAA, 0x44, 0x44}, // W 0x57 87
  {0x22, 0x22, 0x14, 0x08, 0x08, 0x14, 0x22, 0x22}, // X 0x58 88
  {0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x08, 0x08}, // Y 0x59 89
  {0x3E, 0x20, 0x10, 0x08, 0x08, 0x04, 0x02, 0x3E}, // Z 0x5a 90
  {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, // [ 0x5b 91
  {0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04}, // \ 0x5c 92
  {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, // ] 0x5d 93
  {0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00}, // ^ 0x5e 94
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // _ 0x5f 95
  {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ` 0x60 96
  {0x00, 0x00, 0x1C, 0x20, 0x3C, 0x22, 0x22, 0x3C}, // a 0x61 97
  {0x02, 0x02, 0x1E, 0x22, 0x22, 0x22, 0x22, 0x1E}, // b 0x62 98
  {0x00, 0x00, 0x38, 0x04, 0x04, 0x04, 0x04, 0x38}, // c 0x63 99
  {0x20, 0x20, 0x3C, 0x22, 0x22, 0x22, 0x22, 0x3C}, // d 0x64 100
  {0x00, 0x00, 0x1C, 0x22, 0x3E, 0x02, 0x22, 0x1C}, // e 0x65 101
  {0x30, 0x08, 0x08, 0x1C, 0x08, 0x08, 0x08, 0x08}, // f 0x66 102
  {0x3C, 0x22, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x1C}, // g 0x67 103
  {0x02, 0x02, 0x02, 0x1E, 0x22, 0x22, 0x22, 0x22}, // h 0x68 104
  {0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, // i 0x69 105
  {0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x0C}, // j 0x6a 106
  {0x02, 0x02, 0x12, 0x0A, 0x06, 0x0A, 0x12, 0x22}, // k 0x6b 107
  {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, // l 0x6c 108
  {0x00, 0x00, 0x37, 0x49, 0x49, 0x49, 0x49, 0x49}, // m 0x6d 109
  {0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x22, 0x22}, // n 0x6e 110
  {0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x22, 0x1C}, // o 0x6f 111
  {0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x02, 0x02}, // p 0x70 112
  {0x3C, 0x22, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x20}, // q 0x71 113
  {0x00, 0x00, 0x34, 0x0C, 0x04, 0x04, 0x04, 0x04}, // r 0x72 114
  {0x00, 0x00, 0x38, 0x04, 0x0C, 0x30, 0x20, 0x1C}, // s 0x73 115
  {0x08, 0x08, 0x3C, 0x08, 0x08, 0x08, 0x08, 0x30}, // t 0x74 116
  {0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3C}, // u 0x75 117
  {0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08}, // v 0x76 118
  {0x00, 0x00, 0x49, 0x49, 0x55, 0x55, 0x22, 0x22}, // w 0x77 119
  {0x00, 0x00, 0x22, 0x14, 0x08, 0x08, 0x14, 0x22}, // x 0x78 120
  {0x00, 0x00, 0x12, 0x12, 0x12, 0x1C, 0x10, 0x0C}, // y 0x79 121
  {0x00, 0x00, 0x3C, 0x20, 0x10, 0x08, 0x04, 0x3C}, // z 0x7a 122
  {0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04}, // { 0x7b 123
  {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}, // | 0x7c 124
  {0x02, 0x02, 0x02, 0x02, 0x0C, 0x02, 0x02, 0x02}, // } 0x7d 125
  {0x00, 0x00, 0x00, 0x46, 0x49, 0x31, 0x00, 0x00}, // ~ 0x7e 126
  {0x18, 0x24, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42}, // А 192
  {0x7e, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3e}, // Б
  {0x3E, 0x42, 0x42, 0x3E, 0x42, 0x42, 0x42, 0x3E}, // В
  {0x7e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}, // Г
  {0x18, 0x24, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42}, // Д
  {0x7E, 0x02, 0x02, 0x7E, 0x02, 0x02, 0x02, 0x7E}, // Е
  {0x92, 0x92, 0x54, 0x38, 0x54, 0x92, 0x92, 0x92}, // Ж
  {0x38, 0x44, 0x40, 0x20, 0x40, 0x40, 0x44, 0x38}, // З
  {0x42, 0x62, 0x52, 0x52, 0x4A, 0x4A, 0x46, 0x42}, // И
  {0x5A, 0x62, 0x52, 0x52, 0x4A, 0x4A, 0x46, 0x42}, // Й
  {0x22, 0x12, 0x0A, 0x06, 0x06, 0x0A, 0x12, 0x22}, // К
  {0x7C, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x46}, // Л
  {0x63, 0x63, 0x55, 0x55, 0x49, 0x49, 0x41, 0x41}, // М
  {0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42}, // Н
  {0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18}, // О
  {0x7E, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42}, // П
  {0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x02, 0x02}, // Р
  {0x38, 0x44, 0x02, 0x02, 0x02, 0x02, 0x44, 0x38}, // С
  {0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, // Т
  {0x44, 0x44, 0x44, 0x78, 0x40, 0x40, 0x44, 0x38}, // У
  {0x7C, 0x92, 0x92, 0x92, 0x92, 0x7C, 0x10, 0x10}, // Ф
  {0x22, 0x22, 0x14, 0x08, 0x08, 0x14, 0x22, 0x22}, // Х
  {0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x7E, 0x40}, // Ц
  {0x44, 0x44, 0x44, 0x7C, 0x40, 0x40, 0x40, 0x40}, // Ч
  {0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x7F}, // Ш
  {0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0xFF, 0x80}, // Щ
  {0x06, 0x04, 0x04, 0x3C, 0x44, 0x44, 0x44, 0x3c}, // Ъ
  {0x42, 0x42, 0x42, 0x4E, 0x52, 0x52, 0x52, 0x4E}, // Ы
  {0x02, 0x02, 0x02, 0x3E, 0x42, 0x42, 0x42, 0x3E}, // Ь
  {0x3C, 0x42, 0x40, 0x7C, 0x40, 0x40, 0x42, 0x3C}, // Э
  {0x32, 0x4A, 0x4A, 0x4E, 0x4A, 0x4A, 0x4A, 0x32}, // Ю
  {0x7C, 0x42, 0x42, 0x7C, 0x50, 0x48, 0x44, 0x42}, // Я 223
  {0x00, 0x1C, 0x22, 0x20, 0x3C, 0x22, 0x22, 0x1C}, //a 224
  {0x06, 0x18, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x1C}, //б
  {0x00, 0x1E, 0x22, 0x22, 0x1E, 0x22, 0x22, 0x1E}, //в
  {0x00, 0x3E, 0x22, 0x02, 0x02, 0x02, 0x02, 0x02}, //г
  {0x00, 0x3C, 0x28, 0x24, 0x22, 0x3E, 0x22, 0x22}, //д
  {0x00, 0x1C, 0x22, 0x22, 0x3E, 0x02, 0x02, 0x1C}, //e
  {0x00, 0x2A, 0x2A, 0x2A, 0x1C, 0x2A, 0x2A, 0x2A}, //ж
  {0x00, 0x1C, 0x22, 0x20, 0x1C, 0x20, 0x22, 0x1C}, //з
  {0x00, 0x22, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x22}, //и
  {0x00, 0x2A, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x22}, //й
  {0x00, 0x22, 0x12, 0x0A, 0x06, 0x0A, 0x12, 0x22}, //к
  {0x00, 0x3C, 0x28, 0x28, 0x28, 0x28, 0x2A, 0x24}, //л
  {0x00, 0x22, 0x36, 0x2A, 0x22, 0x22, 0x22, 0x22}, //м
  {0x00, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22}, //н
  {0x00, 0x1C, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C}, //o
  {0x00, 0x3E, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22}, //п
  {0x00, 0x1E, 0x22, 0x22, 0x1E, 0x02, 0x02, 0x02}, //p
  {0x00, 0x1C, 0x22, 0x02, 0x02, 0x02, 0x22, 0x1C}, //c
  {0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, //т
  {0x00, 0x22, 0x22, 0x22, 0x3C, 0x20, 0x22, 0x1C}, //у
  {0x00, 0x08, 0x1C, 0x2A, 0x2A, 0x2A, 0x1C, 0x08}, //ф
  {0x00, 0x22, 0x14, 0x14, 0x08, 0x14, 0x14, 0x22}, //x
  {0x00, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3E, 0x20}, //ц
  {0x00, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x20}, //ч
  {0x00, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x3E}, //ш
  {0x00, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x3E, 0x20}, //щ
  {0x00, 0x06, 0x04, 0x04, 0x1C, 0x24, 0x24, 0x1C}, //ъ
  {0x00, 0x22, 0x22, 0x22, 0x2E, 0x32, 0x32, 0x2E}, //ы
  {0x00, 0x02, 0x02, 0x02, 0x0E, 0x12, 0x12, 0x0E}, //ь
  {0x00, 0x1C, 0x22, 0x20, 0x3C, 0x20, 0x22, 0x1C}, //э
  {0x00, 0x12, 0x2A, 0x2A, 0x2E, 0x2A, 0x2A, 0x12}, //ю
  {0x00, 0x3C, 0x22, 0x22, 0x3C, 0x28, 0x24, 0x22}, //я 225
};

/* АЛЬТЕРНАТИВНЫЙ РУССКИЙ КАПС!!! Проверяйте =)
  {0x7e,0x11,0x11,0x11,0x7e},                    //A
  {0x7f,0x49,0x49,0x49,0x33},                    //Б
  {0x7f,0x49,0x49,0x49,0x36},                    //В
  {0x7f,0x01,0x01,0x01,0x03},                    //Г
  {0xe0,0x51,0x4f,0x41,0xff},                    //Д
  {0x7f,0x49,0x49,0x49,0x41},                    //E
  {0x77,0x08,0x7f,0x08,0x77},                    //Ж
  {0x41,0x49,0x49,0x49,0x36},                    //З
  {0x7f,0x10,0x08,0x04,0x7f},                    //И
  {0x7c,0x21,0x12,0x09,0x7c},                    //Й
  {0x7f,0x08,0x14,0x22,0x41},                    //K
  {0x20,0x41,0x3f,0x01,0x7f},                    //Л
  {0x7f,0x02,0x0c,0x02,0x7f},                    //M
  {0x7f,0x08,0x08,0x08,0x7f},                    //H
  {0x3e,0x41,0x41,0x41,0x3e},                    //O
  {0x7f,0x01,0x01,0x01,0x7f},                    //П

  {0x7f,0x09,0x09,0x09,0x06},                    //P
  {0x3e,0x41,0x41,0x41,0x22},                    //C
  {0x01,0x01,0x7f,0x01,0x01},                    //T
  {0x47,0x28,0x10,0x08,0x07},                    //У
  {0x1c,0x22,0x7f,0x22,0x1c},                    //Ф
  {0x63,0x14,0x08,0x14,0x63},                    //X
  {0x7f,0x40,0x40,0x40,0xff},                    //Ц
  {0x07,0x08,0x08,0x08,0x7f},                    //Ч
  {0x7f,0x40,0x7f,0x40,0x7f},                    //Ш
  {0x7f,0x40,0x7f,0x40,0xff},                    //Щ
  {0x01,0x7f,0x48,0x48,0x30},                    //Ъ
  {0x7f,0x48,0x30,0x00,0x7f},                    //Ы
  {0x00,0x7f,0x48,0x48,0x30},                    //Э
  {0x22,0x41,0x49,0x49,0x3e},                    //Ь
  {0x7f,0x08,0x3e,0x41,0x3e},                    //Ю
  {0x46,0x29,0x19,0x09,0x7f},                    //Я
*/

// интерпретатор кода символа по ASCII в его номер в массиве fontHEX
uint8_t getFont(uint8_t font, uint8_t row) {
  font = font - '0' + 16;   // перевод код символа из таблицы ASCII в номер согласно нумерации массива
  if (font < 256) return pgm_read_byte(&(fontHEX[font][row]));   // для английских букв и символов
  else return fontHEX[font - 65][row];         // для русских букв и символов (смещение -65 по массиву)
}

 

Warcan
Offline
Зарегистрирован: 23.05.2018

Правильно ли я понимаю что мне надо в коде заменить 

String disp_text = "AlexGyver SHOW  SUBSCRIBE!"

на вот эту

String disp_text = utf8rus("Test-АБВГДЕЖ");

И вставить код который вы предоставили где-то в выше строки String disp_text. Попробовал сделать так и увы не заработало. Английский текст фразы читаем, а вот вместо русских букв какие-то полоски и всё. 

Или я что-то не так сделал.

String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };
 
  k = source.length(); i = 0;
 
  while (i < k) {
    n = source[i]; i++;
 
    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}
Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

А откуда взялось про pgm ???

202   if (font < 256) return pgm_read_byte(&(fontHEX[font][row]));   // для английских букв и символов
203   else return fontHEX[font - 65][row];         // для русских букв и символов (смещение -65 по массиву)

Это видимо вторая версия ... Откда тогда 256 ???

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
uint8_t getFont(uint8_t font, uint8_t row) {
  font = font - '0' + 16;   // перевод код символа из таблицы ASCII в номер согласно нумерации массива
  if (font < 126) return pgm_read_byte(&(fontHEX[font][row]));   // для английских букв и символов
  else return pgm_read_byte(&(fontHEX[font - 65][row]));         // для русских букв и символов (смещение -65 по массиву)
}

Вот так попробуйте для шрифта в PROGMEM...

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
        byte mirrorFont = 0;
        for (byte i = 0; i < 7; i++) {
          if (thisFont & (1 << 6 - i)) mirrorFont |= (1 << i);
          else mirrorFont |= (0 << i);
        }
        if (MIRROR_FONT) cube[i][0] = mirrorFont;
        else cube[i][0] = thisFont;

Вот тут у Алекса почему то зеркалится только 7 бит шрифта ! Так что если ваш шрифт попадает в крайний правый столбец, то будет лажа. А это else mirrorFont |= (0 << i); очередной шедевр ....

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
byte mirrorFont = 0;
for (byte i = 0; i < 8; i++) {
  if (thisFont & (1 << 7 - i)) mirrorFont |= (1 << i);
}
if (MIRROR_FONT) cube[i][0] = mirrorFont;
else cube[i][0] = thisFont;

Так ИМХО зеркалится все 8 бит ... 

Warcan
Offline
Зарегистрирован: 23.05.2018

Да стало читаться. Но буквы идут смещённые на одну вертикальную колонну вправо.

https://fex.net/ru/s/5mxsysv

Видео того что куб показывает.

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
Warcan
Offline
Зарегистрирован: 23.05.2018

Komandir пишет:

вот это надо поправить ! У Алекса без косяков не бывает !!!

Это я понимаю, по этому сюда и пришёл просить помощи. 

Подправил я как вы рекомендовали и всё стало работать нормально.

Но я вывел все символы и понял что придётся править много букв английских. Буду править.

А ещё подскажите пожалуйста, вот хотел бы исключить некоторые не нужные мне режимы. А в идеале ещё сделать так что бы они переключались по времени последовательно от одного к следующему.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Warcan пишет:

А ещё подскажите пожалуйста, вот хотел бы исключить некоторые не нужные мне режимы. А в идеале ещё сделать так что бы они переключались по времени последовательно от одного к следующему.

дай водицы попить, а то так есть хочется, что переночевать негде... )))

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Тут вас выручит самообразование в области C/C++ или платный раздел форума ...

Warcan
Offline
Зарегистрирован: 23.05.2018

Ещё раз спасибо за помощь. Ваш файл для создания шрифта очень помог. Подскажите пожалуйста у меня вроде получилось отключить режимы, вот вопрос правильно ли я понял что надо убирать их в этой части кода.

В частности я закомментировал режим волна и поправил номера case, в противном случае при переключении режимов с клавиш куб ничего не показывал при нажатии клавиши далее он показывал следующий режим. И ещё подправил вот это #define TOTAL_EFFECTS 10  // количество эффектов

Возможно это корявое решение, но пока я не способен на более правильное.

  switch (currentEffect) {
    case RAIN: rain(); break;
    case PLANE_BOING: planeBoing(); break;
    case SEND_VOXELS: sendVoxels(); break;
    case WOOP_WOOP: woopWoop(); break;
    case CUBE_JUMP: cubeJump(); break;
    case GLOW: glow(); break;
    case TEXT:
      if (showResult) {
        String result = String(score);
        text(result, result.length());
      } else {
        text(disp_text, disp_text.length());
      }
      break;
    case LIT: lit(); break;
//    case 8: sinusFill(); break;
    case 8: sinusThin(); break;
    case 9: walkingCube(); break;
    case 11: snake(); break;
    case 12: shooter(); break;
    case 13: tunnel(); break;
  }
  renderCube();
}

 

Warcan
Offline
Зарегистрирован: 23.05.2018

И ещё вопрос вот эта часть кода отвечает за смену режима работы куба. И попробую спросить можно ли сюда попробовать прикрутить автоматическую смену режимов работы куба? Что то вроде условия по таймеру.

void loop() {
  butt1.tick();
  butt2.tick();

  if (butt1.isClick()) {
    currentEffect++;
    if (currentEffect >= TOTAL_EFFECTS) currentEffect = 0;
    changeMode();
  }
  if (butt2.isClick()) {
    currentEffect--;
    if (currentEffect < 0) currentEffect = TOTAL_EFFECTS - 1;
    changeMode();
  }

  if (butt1.isStep()) {                                 // если кнопка была удержана (это для инкремента)
    modeTimer += 10;
  }
  if (butt2.isStep()) {                                 // если кнопка была удержана (это для инкремента)
    modeTimer -= 10;
  }

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Читаете статью "Blink без delay", берете оттуда код, вместо блинка вставляете currentEffect = (currentEffect + 1) % TOTAL_EFFECTS;