Кривые Безье

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Добавил в библиотеку Adafruit_GFX функции для вывода элементов векторной графики.

Кривые безье по трем и четырем точкам.

Видео

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Измененные файлы библиотеки Adafruit_GFX

Демо код

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

void setup()   {                
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  display.display();
  delay(2000);
}

void loop() {
  // Clear the buffer.
  display.clearDisplay();

  // draw curve 3 point
  display.drawCurve3p(0,0,128,0,128,64,WHITE);
  display.display();
  delay(1000);
  display.clearDisplay();

  // draw curve 4 point
  display.drawCurve4p(0,0,127,100,127,0,0,63,WHITE);
  display.display();
  delay(1000);
  display.clearDisplay();

  // scale curve symbol
  float x=0;
  while (x<1){
    display.clearDisplay(); 
    display.drawCurve4p(64*x,63*x,30*x,63*x,30*x,32*x,64*x,32*x,WHITE);
    display.drawCurve4p(30*x,10*x,30*x,0*x,80*x,0*x,64*x,63*x,WHITE);
    display.display();
    x=x+0.1;
  }
  delay(3000);
  display.clearDisplay(); 
}



 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Молодец! Замечания нужны? Или ну их нафиг?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

На Ваше усмотрение.

Знаю что код кривоват и на костылях.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, тогда нафиг. Захотите - обратитесь.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

С помощью онлаин векторного редактора получил координаты кривых и опорных точек векторного изображения "Рыба"

занес эти данные в массив и написал небольшой код который переберая массив с координатами строит изображение

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

void setup()   {                
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  display.display();
  delay(2000);
}

void loop() {
  // Clear the buffer.
  display.clearDisplay();
  // draw fish
  byte fish[]={//векторное описание контура рыбы
    4,2,12,14,12,20,18,29,18,4,29,18,34,17,40,20,43,24,4,43,24,44,23,52,24,51,23,\
  4,51,23,45,22,46,17,50,16,4,50,16,54,12,61,11,65,7,4,65,7,67,6,68,4,69,2,4,69,2,76,6,80,12,84,19,\
  4,84,19,90,17,95,18,102,20,4,102,20,110,22,114,25,118,30,4,118,30,121,32,122,38,118,39,\
  4,118,39,104,44,91,45,79,46,4,79,46,77,45,73,46,76,48,4,76,48,71,52,70,55,68,56,4,\
  68,56,71,52,70,54,69,53,4,69,53,64,56,60,58,52,62,4,52,62,52,54,53,51,57,46,4,\
  57,46,60,43,56,44,69,43,4,69,43,64,44,58,41,53,37,4,53,37,44,34,35,40,28,41,4,\
  28,41,23,44,18,46,11,47,4,11,47,8,45,10,39,13,36,4,13,36,15,33,21,32,26,28,4,\
  26,28,28,23,18,22,16,20,4,16,20,11,18,5,15,2,12,0          };
  double m=1;//масштаб
  byte st=0;//шаги по массиву
  unsigned long startTime=millis();
  while (fish[st]!=0){//перебираем до конца массив (в конце массива 0)
    if(fish[st]==3){//если кривая задана 3 точками
      display.drawCurve3p(fish[st+1],fish[st+2],fish[st+3],fish[st+4],fish[st+5],fish[st+6],WHITE);
      st=st+7;
    }
    if(fish[st]==4){//если кривая задана 4 точками
      display.drawCurve4p(fish[st+1]*m,fish[st+2]*m,fish[st+3]*m,fish[st+4]*m,fish[st+5]*m,fish[st+6]*m,fish[st+7]*m,fish[st+8]*m,WHITE);
      st=st+9;
    }
  }
  unsigned long totalTime = millis()-startTime;
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println(totalTime);
  display.display();
  delay(15000);
  display.clearDisplay();
}

в дальнейшем оформлю в отдельную функцию которая будет принимать ссылку на массив с данными и строить по ним изображение с заданным масштабом в заданных координатах и с произвольным углом наклона.

Немного подкорректировал функции построения кривых в измененной библиотеке Adafruit_GFX (ссылка в перврм посте)

Пример функции построения кривой Безье по четырем точкам.

//curve 4 point
void Adafruit_GFX::drawCurve4p(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3,
 uint16_t color) {
	 int preX=x0;
	 int preY=y0;
	 float x=0;
	 //оптимизация
	 float step = 0.02;//шаг
	 float d1=sqrt(pow(x1-x0,2)+pow(y1-y0,2));
	 float d2=sqrt(pow(x2-x1,2)+pow(y2-y1,2));
	 float d3=sqrt(pow(x3-x2,2)+pow(y3-y2,2));
	 float sumD=d1+d2+d3;//расстояние между точками задающими кривую
	 	 if (sumD<20){
		 step = 0.5;
		}
	 	 if (sumD<15){
		 step = 0.25;
		}	
	 	 if (sumD<=10){
		 step =0.1;
		}	
		
   while (x<1) {
	int newX=(pow(1-x,3)*x0) + (3*pow(1-x,2)*x*x1)+(3*(1-x))*pow(x,2)*x2+(pow(x,3)*x3);
	int newY= (pow(1-x,3)*y0) + (3*pow(1-x,2)*x*y1)+(3*(1-x))*pow(x,2)*y2+(pow(x,3)*y3);

	drawLine( preX ,preY ,newX,newY, color);   //   P = (1−t)^3P1 + 3(1−t)2tP2 +3(1−t)t2P3 + t3P4
	x+=step;
	preX=newX;
	preY=newY;
   }
     drawLine(preX,preY,x3, y3, color); 

 }

Вот что получилось. В верхнем левом углу время в мс затраченое на прорисовку

Без оптимизации - шаг 1%

С шагом 5%

С шагом 10%

С переменным шагом в зависимости от протяженности кривой

С шагом 100% - просто прямыми

Встала задача написать парсер или конвектор векторных файлов SVG в вид пригодный для вставки в код (массив с координатами и типом объектов. Например в коде выше перед кривой безье 4го порядка в массиве стоит 4).

Если кто сталкивался с таким вопросом подскажите существует ли какойнибудь настраиваемый конвтер под свои нужды или это можно провернуть в Excel или еще какими инструментами. Может кто ради спортивного интереса...

SVG фаил Рыбки

b707
Offline
Зарегистрирован: 26.05.2017

yul-i-an пишет:

Встала задача написать парсер или конвектор векторных файлов SVG в вид пригодный для вставки в код (массив с координатами и типом объектов. Например в коде выше перед кривой безье 4го порядка в массиве стоит 4).

я так понял, что внутри SVG этот массив уже есть, задача состоит только в переводе длинных числе с десятичной точкой в целые?

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

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

У меня так и высчитываются не все точки кривой, а с опрелеленным шагом, а между ними прямые строятся. На картинках выше влияние шага между точками на качество.
Хранить координаты начала, конца и опорных точек дешевле чем все точки перегиба ломаной.

b707
Offline
Зарегистрирован: 26.05.2017

yul-i-an пишет:
Хранить координаты начала, конца и опорных точек дешевле чем все точки перегиба ломаной.

ну тут выбор - либо хранить больше точек, но рисовать их быстрее, либо хранить меньше, но зато считать в процессе.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Если точки хранить то при увеличение масштаба будут видны точки перегиба

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

На просторах всемирной нашел слелующий мануал по SVG https://svg-art.ru/?page_id=907
Буду курить.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Продолжаю игру в одни ворота.

На электронных таблицах сделал небольшой парсер SVG.

В ячейку A1 вставляется текст из фала SVG (строка с описанием <path), далее удаляютя лишние атрибуты,пробелы заменяютя на ",", служебные символы заменяются на коды команд для прорисовки кривых и линий.

В итоге в ячейке А15 получаем строку пригодную для вставли в код.

Пример

На входе <path d="M52.4997,60.6994 C53.1002,55.8261 54.5076,50.791 57.6491,46.6092 C60.6512,43.8629 65.4965,43.945 69.5432,43.0055 C63.8733,41.8427 58.5806,39.7839 53.3876,37.6056 C44.8875,34.7841 36.2354,38.8494 28.5736,41.7015 C22.8849,43.7802 17.2577,46.2326 11.1321,47.262 C7.11377,45.1269 10.4697,39.0696 13.2954,36.512 C16.873,32.9799 22.1688,31.1551 26.0473,27.9298 C27.7536,23.3741 19.8918,22.2533 16.3598,20.4632 C10.8827,18.5667 6.22887,15.4605 2.06499,11.9923 C11.7349,11.5614 20.2888,15.1535 29.0141,17.9416 C33.7335,19.2481 38.1847,22.0856 42.5974,23.9032 C44.6205,23.8954 51.4858,25.044 50.8016,23.2798 C45.6555,23.1053 46.1713,18.0142 49.6344,15.9958 C54.7244,12.9326 60.9297,11.1242 65.1671,7.06673 C67.0262,5.92546 68.0045,3.13386 69.5756,2.25301 C76.3504,6.30221 80.3141,12.6896 84.0519,18.7468 C90.1385,19.7985 96.2854,20.6515 102.489,20.9089 C108.547,23.0273 113.72,26.7192 118.464,30.4686 C122.058,32.5424 123.016,38.1854 118.13,39.3174 C106.075,44.2829 92.6153,45.8009 79.3408,46.2781 C77.4706,46.1772 75.8421,46.3342 75.8296,48.2146 C74.6604,50.8926 74.1824,54.0047 71.9813,56.1852 C69.5521,55.7101 71.8534,50.2377 69.3586,52.8378 C64.4513,56.9117 58.5489,59.9669 52.4997,62.6991 C52.4997,62.0326 52.4997,61.366 52.4997,60.6994 z" id="imagebot_6" fill-opacity="null" stroke-opacity="null" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="null" stroke-width="3" stroke="#000000" fill="#ccc"/>

На выходе 52.4997,60.6994,4,53.1002,55.8261,54.5076,50.791,57.6491,46.6092,4,60.6512,43.8629,65.4965,43.945,69.5432,43.0055,4,63.8733,41.8427,58.5806,39.7839,53.3876,37.6056,4,44.8875,34.7841,36.2354,38.8494,28.5736,41.7015,4,22.8849,43.7802,17.2577,46.2326,11.1321,47.262,4,7.11377,45.1269,10.4697,39.0696,13.2954,36.512,4,16.873,32.9799,22.1688,31.1551,26.0473,27.9298,4,27.7536,23.3741,19.8918,22.2533,16.3598,20.4632,4,10.8827,18.5667,6.22887,15.4605,2.06499,11.9923,4,11.7349,11.5614,20.2888,15.1535,29.0141,17.9416,4,33.7335,19.2481,38.1847,22.0856,42.5974,23.9032,4,44.6205,23.8954,51.4858,25.044,50.8016,23.2798,4,45.6555,23.1053,46.1713,18.0142,49.6344,15.9958,4,54.7244,12.9326,60.9297,11.1242,65.1671,7.06673,4,67.0262,5.92546,68.0045,3.13386,69.5756,2.25301,4,76.3504,6.30221,80.3141,12.6896,84.0519,18.7468,4,90.1385,19.7985,96.2854,20.6515,102.489,20.9089,4,108.547,23.0273,113.72,26.7192,118.464,30.4686,4,122.058,32.5424,123.016,38.1854,118.13,39.3174,4,106.075,44.2829,92.6153,45.8009,79.3408,46.2781,4,77.4706,46.1772,75.8421,46.3342,75.8296,48.2146,4,74.6604,50.8926,74.1824,54.0047,71.9813,56.1852,4,69.5521,55.7101,71.8534,50.2377,69.3586,52.8378,4,64.4513,56.9117,58.5489,59.9669,52.4997,62.6991,4,52.4997,62.0326,52.4997,61.366,52.4997,60.69,0

Все еще очень сыро (предстоит еще много работы), не все команды выполняютя. На данный момент гарантированно выводятся изображения состоящие из кривых Безье четвертого порядка.

b707
Offline
Зарегистрирован: 26.05.2017

yul-i-an, если я правильно понял, пока ваш парсинг SVG заключается лишь в замене буквы "C" на цифру "4"?

Мне кажется вы не с того начали. Как раз букву "С" я бы из массива не убирал. Ваша идея кодировать начало кривой Безье просто цифрой "3" или "4" - на мой взгляд не слишком удачна, можно перепутать с координатами. Почему бы не оставить кодирование буквами, как это сделано в SVG - тогда и обработка этих данных в программе будет понятнее и проще.

Гораздо важнее конвертировать дробные координаты точек в целые, не потеряв точности.

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

b707 пишет:

yul-i-an, если я правильно понял, пока ваш парсинг SVG заключается лишь в замене буквы "C" на цифру "4"?

Мне кажется вы не с того начали. Как раз букву "С" я бы из массива не убирал. Ваша идея кодировать начало кривой Безье просто цифрой "3" или "4" - на мой взгляд не слишком удачна, можно перепутать с координатами. Почему бы не оставить кодирование буквами, как это сделано в SVG - тогда и обработка этих данных в программе будет понятнее и проще.

Гораздо важнее конвертировать дробные координаты точек в целые, не потеряв точности.

 

На грабли с совпадением координат и команд я уже наступал, теперь просто если допустим код 4 это значит кривая 4 порядка, задается 4мя парами координат, значит следующий код команды будет через 7 ячеек массива и т.д.

Про дробные тоже пока думаю, надо алгоритм отработать пока.

b707
Offline
Зарегистрирован: 26.05.2017

yul-i-an пишет:

На грабли с совпадением координат и команд я уже наступал, теперь просто если допустим код 4 это значит кривая 4 порядка, задается 4мя парами координат, значит следующий код команды будет через 7 ячеек массива и т.д.

ну тогда хотя бы перед теми числами, которые на самом деле не цифры, а команды - вставляйте перевод строки:

52.4997,60.6994,
4,53.1002,55.8261,54.5076,50.791,57.6491,46.6092,
4,60.6512,43.8629,65.4965,43.945,69.5432,43.0055,
4,63.8733,41.8427,58.5806,39.7839,53.3876,37.6056,
4,44.8875,34.7841,36.2354,38.8494,28.5736,41.7015,
4,22.8849,43.7802,17.2577,46.2326,11.1321,47.262,
4,7.11377,45.1269,10.4697,39.0696,13.2954,36.512,
4,16.873,32.9799,22.1688,31.1551,26.0473,27.9298,
4,27.7536,23.3741,19.8918,22.2533,16.3598,20.4632,
4,10.8827,18.5667,6.22887,15.4605,2.06499,11.9923,
4,11.7349,11.5614,20.2888,15.1535,29.0141,17.9416,
4,33.7335,19.2481,38.1847,22.0856,42.5974,23.9032,
4,44.6205,23.8954,51.4858,25.044,50.8016,23.2798,
4,45.6555,23.1053,46.1713,18.0142,49.6344,15.9958,
4,54.7244,12.9326,60.9297,11.1242,65.1671,7.06673,
4,67.0262,5.92546,68.0045,3.13386,69.5756,2.25301,
4,76.3504,6.30221,80.3141,12.6896,84.0519,18.7468,
4,90.1385,19.7985,96.2854,20.6515,102.489,20.9089,
4,108.547,23.0273,113.72,26.7192,118.464,30.4686,

хотя я оставил бы букву С - так удобнее

 

Честно говоря, не пойму, нафига это надо. Полный интерпретатор SVG для ардуины будете писать?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Началось с добавления кривых Безье в Adafruit_GFX, ну раз кривые есть то и векторную графику выводить можно.

Полный интепритатор писать не буду, там очень много нюансов, а вот иконки для меню, логотипы и т.п. выводить, особенно если масштабировать необходимо, допустим меню листаем крупные иконки, при входе впункт меню иконку уменьшаем в уголок. Чтобы бинарные картинки не хранить...

Да и академический интерес присутствует.

Думал может на G код переключится... Дальше видно будет.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Помогите не замыленым глазом, сам уже с толку сбился.

Работает

 while (fish[st]!=0){
//вставить код поворота
 if (fish[st]==4){//если кривая 4 порядка
      display.drawCurve4p(fish[st-2]*m,fish[st-1]*m,fish[st+1]*m,fish[st+2]*m,fish[st+3]*m,fish[st+4]*m,fish[st+5]*m,fish[st+6]*m,WHITE);
//st=st+7;
 }
  st=st+7;
}

Не работает

 while (fish[st]!=0){
//вставить код поворота
 if (fish[st]==4){//если кривая 4 порядка
      display.drawCurve4p(fish[st-2]*m,fish[st-1]*m,fish[st+1]*m,fish[st+2]*m,fish[st+3]*m,fish[st+4]*m,fish[st+5]*m,fish[st+6]*m,WHITE);
st=st+7;
 }
//  st=st+7;
}

Если вынести прирощение шага за IF то все ок, если приращивать в IF то не работает. Разницы не вижу.

Смысл такой хотел - в зависимости от содержания fish[st] и выполнения соответсвующего действия перемещатся на определенный шаг.

Хотел примерно так

 while (fish[st]!=0){
//вставить код поворота
 if (fish[st]==4){//если кривая 4 порядка
      display.drawCurve4p(fish[st-2]*m,fish[st-1]*m,fish[st+1]*m,fish[st+2]*m,fish[st+3]*m,fish[st+4]*m,fish[st+5]*m,fish[st+6]*m,WHITE);
st=st+7;
 }
if (fish[st+2]==2){//если прямая
      display.drawLine(fish[st]*m,fish[st+1]*m,fish[st+3]*m,fish[st+4]*m,WHITE);
st=st+3;
 }
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

yul-i-an пишет:
Если точки хранить то при увеличение масштаба будут видны точки перегиба

А дисплей какого разрешения Вы собираетесь использовать совместно с Ардуиной?

(Это к тому, что все универсальные решения - неоптимальны. Иногда - сильно неоптимальны)

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

andriano пишет:

yul-i-an пишет:
Если точки хранить то при увеличение масштаба будут видны точки перегиба

А дисплей какого разрешения Вы собираетесь использовать совместно с Ардуиной?

(Это к тому, что все универсальные решения - неоптимальны. Иногда - сильно неоптимальны)


Это я понимаю. Думаю раз начал надо добить до стабильной работы, темболее кое какие результаты получены.
Но с кодом из поста выше всеравно недоганяю - какая разница где прирашивать шаг в IF или за его прилом?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

В общем парсер особо и не понадобился

В дефайнах определил команды SVG, и лишние пробелы заменил на запятые в NotePad++

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

//SVG Команды
#define M 1 //стартовая точка
#define L 2 //линия
#define Q 3 //кривая 3 порядка
#define C 4 //кривая 4 порядка
#define S 5 //кривая S типа
#define z 10 //замкнуть контур со стартовой точкой
#define Z 10 //замкнуть контур со стартовой точкой
//добавить фигуры (круг, прямоугольник элипс и т.п.

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
  int st=0;//шаги по массиву
  
void setup()   {                
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 
  display.display();
  delay(250);
}

void loop() {
  display.clearDisplay();
byte dataSVG[] ={//векторное описание контура в конце массива ставить 0
//SVG 1,55.003,23.405,2,55.003,37.893,2,65.26,27.64,4,65.26,25.828,65.951,24.022,67.326,22.635,4,70.106,19.864,74.601,19.864,77.35,22.635,4,80.121,25.401,80.121,29.89,77.35,32.662,4,75.973,34.037,74.155,34.734,72.335,34.734,2,62.101,44.982,2,76.59,44.982,4,77.88,43.702,79.644,42.906,81.601,42.906,4,85.501,42.906,88.679,46.085,88.679,49.993,4,88.679,53.899,85.501,57.081,81.601,57.081,4,79.644,57.081,77.88,56.283,76.59,55.009,2,62.1,55.009,2,72.329,65.253,4,74.153,65.253,75.971,65.947,77.344,67.339,4,80.118,70.098,80.118,74.589,77.344,77.349,4,74.594,80.123,70.105,80.123,67.319,77.349,4,65.947,75.977,65.255,74.157,65.255,72.346,2,55,62.094,2,55,76.593,4,56.271,77.869,57.084,79.647,57.084,81.606,4,57.084,85.512,53.907,88.683,49.986,88.683,4,46.067,88.683,42.892,85.516,42.892,81.606,4,42.892,79.647,43.703,77.874,44.973,76.593,2,44.973,62.094,2,34.738,72.346,4,34.738,74.158,34.033,75.973,32.654,77.349,4,29.885,80.121,25.403,80.121,22.63,77.349,4,19.855,74.585,19.855,70.096,22.63,67.337,4,24.007,65.947,25.844,65.251,27.642,65.251,2,37.899,55.009,2,23.414,55.009,4,22.125,56.285,20.342,57.081,18.399,57.081,4,14.482,57.081,11.303,53.901,11.303,49.993,5,14.48,42.906,18.399,42.906,4,20.339,42.906,22.124,43.702,23.414,44.982,2,37.902,44.982,2,27.646,34.736,4,25.849,34.736,24.014,34.039,22.634,32.665,4,19.859,29.893,19.859,25.405,22.634,22.638,4,25.407,19.867,29.89,19.867,32.661,22.638,4,34.036,24.024,34.744,25.833,34.744,27.643,2,44.979,37.895,2,44.979,23.407,4,43.709,22.12,42.897,20.354,42.897,18.384,4,42.897,14.476,46.072,11.305,49.993,11.305,4,53.912,11.305,57.09,14.473,57.09,18.384,4,57.088,20.356,56.274,22.119,55.003,23,0
//девушка 1,40.6197,113.58,4,39.8295,113.562,39.4148,113.832,39.1837,112.592,4,38.647,111.139,38.6525,107.635,37.3861,107.439,4,37.3069,109.471,37.4411,111.511,37.4821,113.543,4,35.679,113.571,36.7431,110.701,36.211,109.499,4,36.1617,107.523,34.8468,105.808,34.6334,103.907,4,35.2577,103.199,35.9436,101.988,35.9697,101.009,4,35.7069,99.5928,35.022,98.3534,34.3808,97.1047,4,32.9327,95.0918,32.0064,92.7622,31.137,90.4511,4,30.7167,88.5296,29.8603,86.637,30.2732,84.6437,4,30.2061,83.7752,30.6068,82.7781,30.3142,81.9674,4,29.0412,80.2648,28.7402,78.0451,27.2986,76.4404,4,26.2754,74.9252,25.3109,73.0111,23.203,73.8973,4,22.534,73.6392,20.3907,74.4397,20.5975,73.4286,4,20.8845,72.3681,18.7301,73.4146,18.2091,72.5871,4,16.8533,70.5827,17.2083,74.3381,16.9353,75.2141,4,16.8439,77.6164,16.0537,79.88,15.4592,82.1808,4,15.0007,84.379,15.2709,86.6053,15.4415,88.8101,4,15.4061,91.3178,14.5413,93.7406,14.4798,96.2567,4,14.1732,99.8444,15.1302,103.376,15.1768,106.955,4,16.0835,108.539,16.0388,110.43,15.694,112.238,4,15.599,112.928,15.7108,113.869,14.7202,113.543,4,13.6439,113.422,11.2993,113.85,11.3953,112.49,4,11.4186,111.679,11.1455,111.474,10.7747,110.337,4,9.69462,108.408,11.0822,106.899,11.3562,105.259,4,11.8901,103.264,11.0197,101.326,11.0719,99.3039,4,10.6069,96.0983,9.91082,92.9206,9.58373,89.687,4,8.77207,87.963,9.02368,86.2409,9.26596,84.393,4,9.90616,81.3765,9.78222,77.7208,9.92293,74.6605,4,8.84569,73.9793,7.5448,73.8358,5.65962,73.6653,4,3.48742,74.1844,4.33263,71.7028,4.15837,70.3106,4,4.56001,66.9232,4.65692,63.5172,4.80602,60.115,4,4.79484,58.7591,5.24866,58.5187,4.81627,59.0796,4,3.31782,58.1105,2.31513,55.0027,4.72775,54.4948,4,6.73314,53.727,6.89714,51.2519,7.24753,49.4282,4,7.64917,46.8954,8.36764,44.4353,9.43463,42.1056,4,10.9629,38.4685,12.124,34.6925,12.8117,30.8057,4,13.1714,28.941,13.6728,27.109,14.7286,25.5192,4,15.5719,23.7337,16.5355,23.4747,18.047,22.9565,4,18.5847,21.1953,17.8373,18.7957,18.2818,16.7903,4,18.4281,14.3069,18.7561,11.7033,20.1493,9.58325,4,21.3169,8.17892,23.2114,7.76237,24.9326,8,4,26.9846,7.75678,28.5436,9.14248,29.3888,10.886,4,30.4949,12.773,30.3142,15.0477,31.0634,17.0802,4,31.4259,19.1517,32.5786,20.967,32.8069,23.0702,4,32.9327,25.0151,35.2997,25.6515,35.665,27.573,4,36.2502,29.8832,36.6183,32.2445,37.2985,34.536,4,37.7048,37.2375,38.8184,39.8076,38.7709,42.5753,4,39.1213,43.4764,38.3292,43.8035,37.6713,44.1893,4,36.1868,44.6981,35.3192,45.8815,33.7164,46.3885,4,31.8955,47.3045,30.4558,48.6595,30.3095,50.8009,4,30.2322,52.5332,31.6095,54.0671,32.1667,55.7025,4,34.0677,59.5083,35.0052,63.8098,37.6918,67.199,4,37.7999,68.8717,35.2838,69.2883,34.0892,69.9928,4,33.0921,70.3618,33.2253,71.0915,33.6764,71.8565,4,34.6586,74.2533,35.5531,76.7302,35.6249,79.3479,4,35.9874,83.1993,37.2836,86.8718,38.0645,90.6468,4,38.9265,94.2159,39.3505,97.8688,40.425,101.391,4,40.4688,103.451,42.7658,103.898,42.2496,106.023,4,42.5012,106.927,42.7323,108.912,43.9596,109.443,4,46.4635,110.225,45.1281,113.972,42.7947,113.664,4,42.0697,113.636,41.3447,113.608,40.6197,113.5,0
//глобус 1,44.042,53.332,2,44.933,49.73,2,50.375,41.023,2,47.506,42.408,2,41.866,36.075,2,42.855,35.679,2,48,40.429,2,52.651,33.503,2,51.265,33.008,2,49.979,34.492,2,48,32.315,2,48.891,31.722,2,51.562,32.513,2,54.828,30.04,2,57.103,30.04,39.551,5.303,2,36.819,6.2925,2,40.48,10.646,2,36.621,15.297,2,35.434,14.307,2,36.819,13.219,2,33.158,12.229,2,28.508,18.166,2,30.19,18.463,2,30.784,20.64,2,32.466,18.364,2,32.169,16.583,2,33.257,14.505,2,34.148,14.505,2,32.96,16.781,2,33.851,17.968,2,33.752,20.442,2,28.013,22.025,2,24.352,24.301,2,25.045,27.269,2,21.483,26.873,2,20.889,29.05,2,20.196,30.435,2,21.384,31.128,2,21.977,31.524,2,24.055,31.623,2,25.539,28.852,2,26.331,28.852,2,26.925,27.962,2,29.596,27.071,2,32.268,30.633,2,33.257,29.644,2,30.784,26.675,2,31.773,26.675,2,35.533,31.722,2,36.621,28.852,2,38.106,28.654,2,38.501,25.29,2,43.449,26.28,2,43.35,27.467,2,37.71,29.545,2,38.402,31.227,2,42.36,30.435,2,42.261,34.096,2,39.491,35.086,2,35.335,34.393,2,34.643,35.581,2,29.992,34.294,2,29.893,32.018,2,19.702,33.206,2,19.207,35.383,2,15.645,37.559,2,14.853,42.309,2,18.712,47.85,2,27.024,49.136,2,29.497,50.126,2,29.102,51.808,2,31.179,53.589,2,31.575,54.578,2,30.388,55.766,2,33.257,56.953,0
//конь 1,71.6164,131.025,4,67.1768,131.176,60.6791,128.883,65.2185,123.766,4,70.1606,121.817,64.3401,115.361,69.293,112.319,4,73.2685,106.658,78.6714,101.489,80.3019,94.5757,4,80.0487,89.8874,74.4524,87.1127,77.1223,81.9234,4,74.5029,73.6192,75.1082,64.061,79.8898,56.5962,4,83.95,49.6629,88.8795,42.3165,88.3596,33.9263,4,83.2674,36.0527,77.8772,37.9158,72.2729,36.9501,4,67.0041,36.4608,62.2787,40.7272,56.9043,38.4074,4,51.4564,37.2755,48.2159,29.9912,52.2779,25.733,4,56.7169,21.9413,63.2389,21.8193,67.4723,17.5876,4,73.0579,12.9607,78.2243,6.70247,85.9226,5.88449,4,89.3251,5.10552,90.7844,1.68647,92.6679,-0.875788,4,94.233,3.18801,96.9553,6.78147,101.052,8.58305,4,109.384,13.409,111.458,23.6117,114.53,31.9988,4,116.802,38.5673,118.695,45.4253,122.499,51.2893,4,122.539,54.1037,118.269,55.2933,121.153,58.5926,4,122.653,67.5408,122.718,76.7038,122.585,85.7567,4,120.055,90.1868,117.751,95.1316,121.126,100.216,4,123.38,106.43,128.994,110.506,131.756,116.37,4,133.317,119.406,128.712,123.815,134.45,123.051,4,139.689,125.823,135.458,132.59,130.247,130.622,4,110.717,131.118,91.1442,131.614,71.6164,131.025,2,71.6164,131.025,0
//слон 1,59.7917,106.506,4,59.9504,102.933,67.1495,104.694,63.1862,101.213,4,64.5082,96.9189,68.6132,94.0591,71.0943,90.3755,4,72.9964,87.2397,77.2809,83.4605,75.2092,79.5832,4,71.4044,77.5511,72.4841,73.0329,77.1378,74.0252,4,80.1304,71.2651,80.3365,66.6547,81.3491,62.8966,4,82.2683,58.3987,82.8307,53.8193,82.684,49.2238,4,77.229,49.2371,71.6715,48.9757,66.4103,47.4963,4,67.4295,43.4207,73.9985,44.2966,76.69,41.7929,4,74.1891,39.5437,81.7458,39.7687,79.7685,36.2114,4,79.6328,32.1373,76.4232,30.9584,73.852,27.988,4,70.4169,23.3462,75.8022,18.7082,78.7933,15.57,4,82.1272,12.1593,85.9402,8.52541,86.9606,3.70139,4,85.5877,2.57323,82.4515,0.957911,85.6517,-0.584311,4,90.0224,-1.32526,94.6852,-1.41554,98.9687,-0.200004,4,101.812,2.57019,94.6291,2.72127,97.7195,6.21408,4,101.384,10.6051,96.4435,12.8712,93.5266,15.4093,4,91.8288,17.554,86.7614,20.3824,87.6332,22.6054,4,92.5945,22.4324,95.4853,17.6295,99.0242,14.786,4,102.906,9.80749,106.661,17.8527,109.143,20.5867,4,112.201,24.73,110.091,30.2989,105.485,32.0783,4,103.201,34.4307,101.684,41.1315,107.15,40.1339,4,110.324,41.2877,104.047,41.412,107.65,42.4786,4,110.045,43.3981,119.384,45.4996,114.239,48.3183,4,109.873,49.3054,105.362,49.2647,100.926,48.8661,4,100.653,55.6043,101.616,62.3159,103.601,68.7612,4,104.094,70.5949,104.587,72.4286,105.08,74.2622,4,107.452,74.2153,112.35,73.6967,110.086,77.6025,4,105.325,80.2285,108.239,85.7547,110.878,88.8983,4,114.15,93.0347,119.029,96.9071,119.238,102.57,4,120.547,103.35,124.902,105.493,123.642,107.17,4,102.797,107.063,81.9397,107.479,61.1052,106.715,2,60.3817,106.649,2,59.7917,106.506,2,59.7917,106.506,2,59.7917,106.506,10,0
//слон 1,60,107,4,60,103,68,105,64,102,4,65,97,69,95,72,91,4,73,88,78,84,76,80,4,72,78,73,74,78,75,4,81,72,81,67,82,63,4,83,59,83,54,83,50,4,78,50,72,49,67,48,4,68,44,74,45,77,42,4,75,40,82,40,80,37,4,80,33,77,31,74,28,4,71,24,76,19,79,16,4,83,13,86,9,87,4,4,86,3,83,1,86,0,4,91,-1,95,-1,99,0,4,102,3,95,3,98,7,4,102,11,97,13,94,16,4,92,18,87,21,88,23,4,93,23,96,18,100,15,4,103,10,107,18,110,21,4,113,25,111,31,106,33,4,104,35,102,42,108,41,4,111,42,105,42,108,43,4,111,44,120,46,115,49,4,110,50,106,50,101,49,4,101,56,102,63,104,69,4,105,71,105,73,106,75,4,108,75,113,74,111,78,4,106,81,109,86,111,89,4,115,94,120,97,120,103,4,121,104,125,106,124,108,4,103,108,82,108,62,107,2,61,107,2,60,107,2,60,107,2,60,107,0
//заяц 1,57.59,19.64,4,57.59,19.64,57.59,19.64,57.59,19.64,4,54.13,13.5,48.5,8.89,41.8,6.71,4,41.77,6.7,41.7,6.67,41.59,6.64,4,38.79,8.9,37.04,10.32,36.34,10.88,4,35.08,11.9,34.02,13.13,33.2,14.52,4,32.21,16.2,31.31,17.72,30.53,19.05,4,29.02,21.61,27.88,24.38,27.14,27.27,4,26.67,29.14,25.48,33.82,23.59,41.3,1,48,22.64,4,48,22.64,48,22.64,48,22.64,4,42.46,24.85,37.47,28.24,33.38,32.58,4,32.07,33.97,28.81,37.43,23.59,42.97,1,51.59,11.3,4,51.59,11.3,51.59,11.3,51.59,11.3,4,59.03,5.73,69.35,6.14,76.33,12.29,4,76.63,12.55,77.38,13.22,78.59,14.28,2,82.5,20.79,4,82.5,20.79,82.5,20.79,82.5,20.79,4,87.66,32.07,85.48,45.34,76.98,54.37,4,76.52,54.85,75.39,56.05,73.59,57.97,4,69.51,57.39,66.96,57.02,65.94,56.87,4,53.51,55.09,43.21,46.33,39.45,34.35,4,39.11,33.27,38.27,30.59,36.92,26.3,1,80.59,16.3,4,81.99,16.05,82.87,15.89,83.22,15.82,4,86.34,15.26,89.38,14.3,92.25,12.97,4,92.25,12.97,92.25,12.97,92.25,12.97,2,107.92,14.97,4,107.59,14.73,107.38,14.59,107.3,14.53,4,99.97,9.32,91.69,5.62,82.92,3.64,4,82.92,3.64,82.92,3.64,82.92,3.64,4,82.92,3.64,82.92,3.64,82.92,3.64,4,80.53,6.09,77.48,7.79,74.14,8.54,4,73.89,8.6,73.26,8.74,72.25,8.97,1,66.59,43.97,2,58.41,42.18,2,52.92,39.3,2,50.59,33.61,2,52.92,27.64,0//4,52.92,27.64,52.92,27.64,52.92,27.64,4,57.71,31.6,61.82,36.3,65.1,41.58,4,65.3,41.9,65.8,42.7,66.59,4.0,0
//рыба 1,52.4997,60.6994,4,53.1002,55.8261,54.5076,50.791,57.6491,46.6092,4,60.6512,43.8629,65.4965,43.945,69.5432,43.0055,4,63.8733,41.8427,58.5806,39.7839,53.3876,37.6056,4,44.8875,34.7841,36.2354,38.8494,28.5736,41.7015,4,22.8849,43.7802,17.2577,46.2326,11.1321,47.262,4,7.11377,45.1269,10.4697,39.0696,13.2954,36.512,4,16.873,32.9799,22.1688,31.1551,26.0473,27.9298,4,27.7536,23.3741,19.8918,22.2533,16.3598,20.4632,4,10.8827,18.5667,6.22887,15.4605,2.06499,11.9923,4,11.7349,11.5614,20.2888,15.1535,29.0141,17.9416,4,33.7335,19.2481,38.1847,22.0856,42.5974,23.9032,4,44.6205,23.8954,51.4858,25.044,50.8016,23.2798,4,45.6555,23.1053,46.1713,18.0142,49.6344,15.9958,4,54.7244,12.9326,60.9297,11.1242,65.1671,7.06673,4,67.0262,5.92546,68.0045,3.13386,69.5756,2.25301,4,76.3504,6.30221,80.3141,12.6896,84.0519,18.7468,4,90.1385,19.7985,96.2854,20.6515,102.489,20.9089,4,108.547,23.0273,113.72,26.7192,118.464,30.4686,4,122.058,32.5424,123.016,38.1854,118.13,39.3174,4,106.075,44.2829,92.6153,45.8009,79.3408,46.2781,4,77.4706,46.1772,75.8421,46.3342,75.8296,48.2146,4,74.6604,50.8926,74.1824,54.0047,71.9813,56.1852,4,69.5521,55.7101,71.8534,50.2377,69.3586,52.8378,4,64.4513,56.9117,58.5489,59.9669,52.4997,62.6991,4,52.4997,62.0326,52.4997,61.366,52.4997,60.69,0
//лет мышь 1,39.0893,150.388,4,38.8349,146.012,38.2627,138.482,31.9396,142.114,4,29.0135,143.203,20.2281,145.973,24.4759,140.249,4,22.1476,134.546,12.6739,143.035,12.0218,139.072,4,17.1173,133.602,9.56564,127.59,4.2283,131.468,4,0.944028,132.373,-5.75158,138.1,-7.06218,136.284,4,-4.01189,132.418,2.85889,124.504,-5.42805,122.131,4,-14.4332,120.089,-22.3457,126.289,-30.1764,129.673,4,-32.5263,131.508,-35.5174,131.188,-32.5943,128.134,4,-22.453,112.394,-6.53633,100.544,11.1241,94.5227,4,15.4051,93.1315,21.9966,90.0513,22.1257,97.0785,4,24.7729,103.546,26.6562,111.632,33.4731,114.96,4,41.3243,119.325,35.6964,102.36,43.8301,108.769,4,47.2532,110.989,54.578,106.756,55.5821,109.135,4,53.5876,111.989,52.6517,117.055,57.9213,114.451,4,67.0724,110.851,73.7938,102.787,78.2998,94.302,4,83.0067,93.5948,87.6867,97.159,91.9785,99.0525,4,106.231,107.122,115.026,122.371,118.761,137.917,4,114.882,135.737,111.122,131.328,106.421,129.594,4,101.41,127.09,95.758,126.649,90.2495,126.821,4,87.6679,129.898,86.1433,133.718,88.3872,137.54,4,90.3407,144.863,82.1552,135.02,79.1998,134.352,4,73.6817,130.407,68.3951,136.366,69.6058,141.966,4,68.358,143.045,64.5095,140.157,62.2484,140.492,4,57.5993,139.091,54.3248,141.109,57.1255,145.944,4,53.0246,145.443,47.034,139.12,43.4072,145.074,4,41.8261,146.561,41.0115,149.524,39.0893,150.388,2,39.0893,150.388,10,0
//мышь 1,0.99942,221.573,4,19.9753,216.358,39.8931,215.851,59.3752,213.794,4,81.8712,211.594,105.27,211.843,126.523,202.859,4,140.615,197.19,144.587,180.516,145.445,166.247,4,149.298,141.745,162.977,116.306,185.713,106.802,4,194.524,102.075,207.446,108.045,214.483,103.637,4,205.945,91.9588,224.346,78.4507,232.086,90.9953,4,241.993,93.4428,252.223,86.8655,254.494,77.3635,4,263.418,84.3792,272.048,93.8754,282.709,99.2943,4,292.855,103.146,306.889,116.877,293.889,126.644,4,285.142,136.197,271.493,135.131,262.339,143.16,4,253.136,150.769,253.949,163.852,257.559,174.291,4,258.146,185.686,267.241,187.32,275.269,190.326,4,276.589,197.442,265.789,199.478,260.508,201.185,4,249.132,203.118,238.244,198.283,229.712,190.59,4,221.954,180.858,212.691,191.571,215.292,201.159,4,202.184,212.362,226.087,206.489,228.931,213.955,4,217.596,218.319,204.599,216.019,192.632,215.822,4,176.931,216.053,163.717,205.614,148.63,202.945,4,139.317,206.434,131.382,214.44,120.965,215.539,4,90.3677,220.841,59.1923,220.399,28.2944,222.132,4,19.3438,222.026,9.32206,223.647,0.9994,221.573,2,0.99942,221.573,10,0
//кот 1,46.6288,130.594,4,41.345,126.472,35.3041,129.032,29.4878,128.723,4,24.3938,124.357,18.2008,129.646,13.4001,125.443,4,7.1919,119.905,17.954,116.438,15.6584,109.864,4,15.4007,100.4,11.3477,91.8268,7.08711,83.8728,4,4.06979,77.5487,5.1393,70.2811,4.16827,63.5137,4,0.682347,58.6547,-2.79951,52.6391,1.34831,46.6358,4,6.03354,41.5731,3.83124,34.9129,1.9901,29.0583,4,6.72745,30.4518,12.1651,36.7983,18.3976,35.5278,4,22.6362,32.7981,25.2093,35.4966,25.9164,40.4927,4,28.1384,46.9089,29.4351,55.6832,36.4473,57.7526,4,43.8123,59.8555,52.0588,60.3226,57.8837,66.4924,4,68.5352,76.4713,73.474,92.2026,73.0562,107.365,4,74.021,114.456,82.9188,110.693,87.3217,111.739,4,94.7053,111.411,101.793,113.73,108.94,115.322,4,115.318,117.019,120.721,111.654,126.715,111.011,4,127.727,117.211,119.859,119.794,115.561,121.705,4,110.459,123.875,104.937,123.926,99.6966,122.335,4,88.3671,119.51,76.3592,120.251,65.5934,125.219,4,59.7829,127.359,54.1406,131.41,47.8198,130.904,2,46.6288,130.594,2,46.6288,130.594,2,46.6288,130.594,10,0
//1,34.0795,106.845,4,37.5747,104.546,29.6438,102.601,28.4661,100.429,4,24.9998,96.1658,23.9199,90.4988,22.9541,85.2356,4,24.6139,82.4075,23.9416,79.4857,24.543,76.5464,4,27.4832,72.1822,29.1098,67.0623,32.0646,62.7138,4,35.3551,63.4083,38.9131,66.0779,42.2094,67.0923,4,45.1852,72.4419,39.743,76.8966,40.3829,82.0757,4,41.631,86.9044,38.2873,90.9285,37.6153,95.4288,4,37.6387,99.6861,41.5103,103.996,45.7412,101.069,4,45.5265,97.9643,39.4913,97.0019,42.1931,92.6356,4,43.0821,88.1213,45.9961,84.5071,48.1994,80.7148,4,46.9545,76.2681,48.6114,70.6316,51.4163,67.2982,4,54.2642,70.0494,56.2313,74.887,56.667,78.7394,4,56.7222,83.1556,62.6025,86.111,62.4907,91.3122,4,62.93,95.9105,65.0835,100.289,68.0699,102.782,4,69.6315,106.028,79.3217,104.334,74.1607,100.478,4,69.8989,96.6324,64.9954,92.5536,64.3482,86.4244,4,62.5802,82.7861,66.6441,77.6306,61.6532,76.1108,4,61.9625,71.1806,60.6566,65.5841,63.4662,61.1865,4,67.5132,57.7279,73.4401,57.4715,77.3106,53.6454,4,82.0072,50.5318,84.6734,45.4306,86.1758,40.1444,4,88.4518,37.5948,91.9865,32.0838,95.9189,34.9488,4,99.777,37.3345,96.9295,31.333,99.145,30.0088,4,97.3168,23.4117,89.8969,26.5789,85.2659,24.933,4,81.0614,22.1171,76.7081,23.7406,73.6416,26.9571,4,71.345,27.992,72.5874,30.7009,74.8405,29.6819,4,73.2244,35.0509,70.9969,40.9593,66.0984,44.1387,4,60.478,46.598,57.343,39.3119,54.0057,36.1495,4,50.3631,32.5843,48.1047,27.3827,43.5168,24.9352,4,37.1354,23.3193,32.2871,28.9228,27.4675,32.0779,4,22.6844,34.4726,16.9411,35.6561,13.6779,40.327,4,8.26261,46.8358,11.6956,56.6558,6.00129,63.0563,4,3.65585,66.6056,-1.50794,69.1618,-0.798354,74.0399,4,1.71664,79.264,-0.487494,85.4991,0.88577,91.1198,4,1.90065,95.1819,3.40334,100.4,8.3228,101.003,4,12.1929,103.457,14.3008,98.3172,10.2029,96.8287,4,5.25627,94.6308,4.58031,88.4442,4.18291,83.692,0//4,3.09186,78.9894,6.81799,75.8782,8.35683,72.1872,4,7.05733,68.5817,11.6397,63.6809,14.5461,64.4108,4,12.3739,67.7478,9.20243,72.078,14.3439,74.8265,4,14.2764,74.9951,15.0983,71.7462,16.4222,70.77,4,16.2246,68.2246,13.6428,66.0576,16.3813,63.4822,4,21.1858,60.2786,20.1268,69.5713,19.1292,72.2063,4,19.0764,76.2528,13.6529,79.4666,16.4222,83.5217,4,19.4561,88.5231,20.8796,94.2648,22.0438,99.9313,4,23.7143,104.632,27.9345,108.07,33.2118,106.855,2,34.0795,106.845,2,34.0795,106.845,10,0
//1,72.61,15.87,2,77.58,10,2,83.03,15.87,2,80.66,21.49,2,81.04,22.32,2,81.34,22.96,2,81.64,23.59,2,81.96,24.22,2,82.28,24.85,2,82.6,25.47,2,82.94,26.09,2,83.28,26.7,2,83.63,27.31,2,83.99,27.91,2,84.35,28.51,2,84.72,29.1,2,85.1,29.69,2,85.49,30.28,2,85.88,30.86,2,86.28,31.43,2,86.68,32,2,87.1,32.57,2,87.51,33.13,2,87.94,33.68,2,88.37,34.23,2,88.81,34.78,2,89.26,35.31,2,89.71,35.85,2,90.17,36.38,2,90.64,36.9,2,91.11,37.41,2,91.59,37.93,2,92.07,38.43,2,92.56,38.93,2,93.06,39.42,2,93.56,39.91,2,94.07,40.39,2,94.59,40.87,2,95.11,41.34,2,95.63,41.8,2,96.17,42.26,2,96.71,42.71,2,97.25,43.16,2,97.8,43.6,2,98.36,44.03,2,108.59,51.88,2,91.58,50.95,2,90.69,50.9,2,89.79,50.86,2,88.89,50.83,2,88,50.79,2,87.1,50.77,2,86.2,50.75,2,85.31,50.73,2,84.41,50.72,2,83.51,50.72,2,82.62,50.72,2,81.72,50.73,2,80.82,50.74,2,79.93,50.75,2,79.03,50.77,2,78.13,50.8,2,77.24,50.83,2,76.34,50.87,2,75.45,50.91,2,74.55,50.96,2,73.66,51.01,2,72.76,51.07,2,71.87,51.13,2,70.97,51.2,2,70.08,51.27,2,69.19,51.35,2,68.3,51.43,2,67.4,51.52,2,66.51,51.62,2,65.62,51.72,2,64.73,51.82,2,63.84,51.93,2,62.95,52.04,2,62.06,52.16,2,61.17,52.29,2,60.29,52.42,2,59.4,52.56,2,58.51,52.7,2,57.63,52.84,2,56.74,52.99,2,55.86,53.15,2,47.29,54.69,2,40.66,60.3,2,35.92,54.69,2,42.32,49.32,2,39,43.71,2,32.14,47.28,2,29.3,40.9,2,37.58,37.83,2,36.63,30.43,2,28.59,29.15,2,29.3,19.7,2,37.58,21.49,2,40.66,16.64,2,37.58,11.02,2,44.45,6.42,2,48,13.32,2,55.33,11.53,2,55.33,4.64,2,64.09,4.64,2,64.09,12.55,2,72.61,10,0
//квадрат M,82,3,4,90,3,96,9,96,17,L,96,45,C,96,53,90,59,82,59,L,53,59,C,45,59,39,53,39,45,L,39,3,C,61,3,73,3,82,3,z,0
//дракон
M,44.92,52.64,C,45.39,51.82,45.69,51.31,45.8,51.1,C,48.22,46.9,52.28,43.9,57.01,42.84,C,57.13,42.81,57.44,42.75,57.92,42.64,L,73.92,51.64,C,74.2,51.71,74.37,51.75,74.44,51.77,C,76.67,52.32,79.02,51.91,80.92,50.64,C,80.92,50.64,80.92,50.64,80.92,50.64,L,86.59,55.3,L,91.59,55.3,L,92.92,61.96,C,93.47,60.25,93.81,59.19,93.95,58.76,C,95.1,55.17,95.32,51.34,94.59,47.64,C,94.59,47.64,94.59,47.64,94.59,47.64,C,94.23,47.53,94.01,47.47,93.93,47.44,C,90.73,46.5,88.08,44.28,86.59,41.3,C,86.59,41.3,86.59,41.3,86.59,41.3,L,84.13,41.78,L,84.13,41.78,L,81.92,40.3,L,76.59,31.5,C,75.86,31.18,75.41,30.98,75.23,30.9,C,67.85,27.66,61.31,22.74,56.15,16.54,C,54.43,14.47,50.13,9.31,43.25,1.04,C,44.62,3.52,45.48,5.07,45.82,5.69,C,49.96,13.22,54.8,20.34,60.25,26.97,C,60.25,26.97,60.25,26.97,60.25,26.97,C,56.26,28.28,53.59,29.16,52.26,29.59,C,50.92,30.03,50.92,29.45,52.26,27.84,C,51.29,28.39,50.68,28.73,50.44,28.87,C,46.78,30.95,43.41,33.51,40.44,36.49,C,40,36.93,38.91,38.02,37.16,39.77,L,37.16,39.85,L,32.3,48.97,C,32.66,49.03,32.89,49.07,32.98,49.08,C,37.09,49.75,41.11,50.95,44.92,52.64,C,44.92,52.64,44.92,52.64,44.92,52.64,M,74.64,33.61,L,76.64,35.36,C,76.64,35.36,76.64,35.36,76.64,35.36,C,77.46,37.13,77.89,39.06,77.89,41.01,C,77.89,41.06,77.89,41.17,77.89,41.36,C,77.76,41.3,77.69,41.27,77.66,41.25,C,75.15,40.04,73.18,37.94,72.14,35.36,C,72.14,35.36,72.14,35.36,72.14,35.36,L,74.64,33.61,Z,0
//arduLogo M,30.52,62.21,L,29.73,59.41,L,25.31,59.41,L,24.49,62.21,L,20.92,62.21,L,25.45,47.21,L,29.87,47.21,L,34.4,62.21,L,30.52,62.21,Z,M,28.88,56.39,L,27.55,51.73,L,26.2,56.39,L,28.88,56.39,Z,0\
//1,31.03,29.27,2,46.6,29.27,2,46.6,34.73,2,31.03,34.73,2,31.03,29.27,10,M,113.32,44.68,C,118.57,36.34,118.23,25.65,112.46,17.66,C,108.42,12.08,114.29,20.21,112.37,17.54,C,102.16,3.41,81.39,2.65,70.17,15.98,C,69.43,16.87,67.56,19.09,64.57,22.64,C,61.79,19.34,60.06,17.27,59.36,16.45,C,47.94,2.88,26.81,3.66,16.42,18.03,C,14.56,20.6,21.21,11.41,17.29,16.83,C,11.17,25.3,10.89,36.66,16.58,45.43,C,20.51,51.47,14.64,42.43,16.51,45.32,C,26.21,60.25,47.67,61.31,58.81,47.42,C,59.57,46.46,61.5,44.06,64.57,40.23,C,66.97,43.5,68.47,45.55,69.07,46.37,C,80.2,61.59,103.17,60.8,113.22,44.84,C,114.97,42.05,109.11,51.37,113.32,44.68,Z,M,105.06,42.5,C,111.92,34.1,109.12,21.49,99.34,16.77,C,96.54,15.42,103.18,18.62,99.34,16.77,C,91.21,12.86,81.45,15.28,76.1,22.55,C,75.16,23.83,72.82,27.01,69.07,32.1,C,73.37,37.53,76.06,40.93,77.13,42.29,C,84.24,51.26,97.82,51.37,105.06,42.5,C,107.75,39.21,102.24,45.96,105.06,42.5,Z,M,23.9,42.5,C,17.03,34.1,19.83,21.49,29.61,16.77,C,32.41,15.42,25.77,18.62,29.61,16.77,C,37.74,12.86,47.51,15.28,52.85,22.55,C,53.79,23.83,56.13,27.01,59.88,32.1,C,55.58,37.53,52.89,40.93,51.82,42.29,C,44.72,51.26,31.14,51.37,23.9,42.5,C,21.2,39.21,26.72,45.96,23.9,42.5,Z,
//M,83.77,34.49,L,88.37,34.49,0//L,88.37,39.43,L,93.34,39.43,L,93.34,34.49,L,98.18,34.49,L,98.18,29.43,L,93.34,29.43,L,93.34,24.57,L,88.37,24.57,L,88.37,29.43,L,83.77,29.43,L,83.77,34.49,Z,0
//линия M,0,0,L,10,10,0
};

  byte startPoint[2];//начальная точка линии
  double m=1;//масштаб от 0 к 1
//  double angle=0;//угол поворота
//  angle=angle*(PI/180);//перевод угла в радианы
  unsigned long startTime=millis();
 //строим картинку по массиву
  while (dataSVG[st]!=0){//пока массив не закончился
  if (dataSVG[st]==1){//SVG M
  //запоминаем точку начала кривой для замыкания контура
    startPoint[0]=dataSVG[st+1];//координата Х
    startPoint[1]=dataSVG[st+2];//координата У
    st=st+3;//переходим к след команде
 }  
 if (dataSVG[st]==4){//SVG C кривая 4 порядка
    display.drawCurve4p(dataSVG[st-2]*m,dataSVG[st-1]*m,dataSVG[st+1]*m,dataSVG[st+2]*m,dataSVG[st+3]*m,dataSVG[st+4]*m,dataSVG[st+5]*m,dataSVG[st+6]*m,WHITE);
    st=st+7;
 }
  if (dataSVG[st]==5){//SVG S ПОКА НЕ РАБОТАЕТ необходимо добавить
  //вычисление зеркальной опорной точки
    //display.drawLine(dataSVG[st-2]*m,dataSVG[st-1]*m,dataSVG[st+3]*m,dataSVG[st+4]*m,WHITE);
    display.drawCurve4p(dataSVG[st-2]*m,dataSVG[st-1]*m,dataSVG[st-4]*m,((dataSVG[st-3]*m)+(dataSVG[st-1]*m)),dataSVG[st+1]*m,dataSVG[st+2]*m,dataSVG[st+3]*m,dataSVG[st+4]*m,WHITE);
    st=st+5;
 }
  if (dataSVG[st]==3){//SVG Q кривая 3 порядка НЕ ПРОВЕРЯЛ
    display.drawCurve3p(dataSVG[st-2]*m,dataSVG[st-1]*m,dataSVG[st+1]*m,dataSVG[st+2]*m,dataSVG[st+3]*m,dataSVG[st+4]*m,WHITE);
    st=st+5;
 }
 
  if (dataSVG[st]==2){//SVG L если прямая
    display.drawLine(dataSVG[st-2]*m,dataSVG[st-1]*m,dataSVG[st+1]*m,dataSVG[st+2]*m,WHITE);
    st=st+3;
 }
  if (dataSVG[st]==10){//SVG z замкнуть контур
    display.drawLine(dataSVG[st-2]*m,dataSVG[st-1]*m,startPoint[0]*m,startPoint[1]*m,WHITE);
    st=st+1;
 }
//раскоментировать для просмотра прорисовки
//  display.display();
//  delay(50);
 }
st=0;//сброс шагов обхода массива
  //ОПЫТ с врвщением
/* while (dataSVG[st]!=0){//перебираем до конца массив (в конце массива 0)
    if(dataSVG[st]==3){//если кривая задана 3 точками
      display.drawCurve3p(dataSVG[st+1],dataSVG[st+2],dataSVG[st+3],dataSVG[st+4],dataSVG[st+5],dataSVG[st+6],WHITE);
      st=st+7;
    }
    if(dataSVG[st]==4){//если кривая задана 4 точками
    if(angle!=0){
//    byte newPoint[7];//массив для новых координат
    for(byte i=0; i<8; i=i+2){
    newPoint[i]=(dataSVG[st+1+i]*cos(angle))-(dataSVG[st+2+i]*sin(angle));
    newPoint[i+1]=(dataSVG[st+1+i]*sin(angle))+(dataSVG[st+2+i]*cos(angle));
    if (newPoint[i]<=0){
    newPoint[i]=0;}  
    if (newPoint[i+1]<=0){
    newPoint[i]=0;}
    }
    }
if(angle!=0){
display.drawCurve4p(newPoint[0]*m,newPoint[1]*m,newPoint[2]*m,newPoint[3]*m,newPoint[4]*m,newPoint[5]*m,newPoint[6]*m,newPoint[7]*m,WHITE);
}else
{
      display.drawCurve4p(dataSVG[st+1]*m,dataSVG[st+2]*m,dataSVG[st+3]*m,dataSVG[st+4]*m,dataSVG[st+5]*m,dataSVG[st+6]*m,dataSVG[st+7]*m,dataSVG[st+8]*m,WHITE);
}
      st=st+9;
    }
  }*/
  //вывод на экран времени затраченного на прорисовку
  unsigned long totalTime = millis()-startTime;
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println(totalTime);
  //display.println(angle);
  display.display();
  delay(5000);
  display.clearDisplay();
}

Векторный редактор вызает файлы в абсолютной системе координат

Остались проблеммы с выводом S кривых (описание SVG команд)

Необходимо добавить квадрат, круг, эллипс и т.п.

Длинные комбинации команд приводят к зависанию...

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

yul-i-an пишет:

Длинные комбинации команд приводят к зависанию...

Неаккуратки с памятью?

Logik
Offline
Зарегистрирован: 05.08.2014

А про вывод крупных шрифтов не думали? А то в растровых очень расточительно получается крупные буквы хранить.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Сегодня думал уже. Надо както все это дело оптимизировать.
С контурами шрифтов проблем не будет, а вот для заливки надо буфер делать в нем строить контур, заливать и выводить как битмап.

Logik
Offline
Зарегистрирован: 05.08.2014

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

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

ЕвгенийП пишет:

yul-i-an пишет:

Длинные комбинации команд приводят к зависанию...

Неаккуратки с памятью?

Подскажите что можно предпринять.

Хочу прорисовку попробовать как в этой статье

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, как я могу подсказать,это надо садиться и погружаться в код с головой. так с наскоку чего там наподсказываешь.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Вот отыскал инфу по векторнфм шрифтам https://m.habr.com/post/119608

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Попробовал выводить векторные цифры. Пришлось отрисовать цифры в векторном редакторе. Вот что примерно получилось

выводил шум АЦП

ВИДЕО

Код

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

//SVG Команды
#define M 10 //стартовая точка
#define L 20 //линия
#define Q 30 //кривая 3 порядка
#define C 40 //кривая 4 порядка
#define S 50 //кривая S типа
#define V 60 //вертикальная линия
#define z 100 //замкнуть контур со стартовой точкой
#define Z 100 //замкнуть контур со стартовой точкой
//добавить фигуры (круг, прямоугольник элипс и т.п.

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
int st=0;//шаги по массиву
//позиция курсора
byte cx=0;
byte cy=0;
//масштаб
double m=1.5;
//символы в векторном формате
byte dig1[]={
  M,10,20,L,10,0,L,0,5,0};
byte dig2[]={
  M,10,20,L,0,20,L,0,12.5,L,2,10,L,8,10,L,10,7.5,L,10,2.5,L,8,0,L,0,0,0};
byte dig3[]={
  M,8,10,L,4,10,M,0,20,L,8,20,L,10,17.5,L,10,12.5,L,8,10,L,10,7.5,L,10,2.5,L,8,0,L,0,0,0};
byte dig4[]={
  M,10,20,L,10,0,M,10,12.5,L,2,12.5,L,0,10,L,0,0,0};
byte dig5[]={
  M,0,20,L,8,20,L,10,17.5,L,10,12.5,L,8,10,L,0,10,L,0,0,L,10,0,0};
byte dig6[]={
  M,10,2.5,L,8,0,L,2,0,L,0,2.5,L,0,17.5,L,2,20,L,8,20,L,10,17.5,L,10,12.5,L,8,10,L,0,10,0};
byte dig7[]={
  M,0,20,L,10,7.5,L,10,0,L,0,0,0};
byte dig8[]={
  M,10,7.5,L,10,2.5,L,8,0,L,2,0,L,0,2.5,L,0,7.5,L,2,10,L,7.75,10,L,10,7.5,Z,M,2,10,L,0,12.5,L,0,17.5,L,2,20,L,8,20,L,10,17.5,L,10,12.5,L,8,10,0};
byte dig9[]={
  M,0,17.5,L,2,20,L,8,20,L,10,17.5,L,10,2.5,L,8,0,L,2,0,L,0,2.5,L,0,7.5,L,2,10,L,10,10,0};
byte dig0[]={
  M,0,17.5,L,2,20,L,8,20,L,10,17.5,L,10,2.5,L,8,0,L,2,0,L,0,2.5,L,0,17.5,Z,0};
byte dot[]={
  M,6,17.5,L,6,15,L,4,15,L,4,17.5,L,6,17.5,Z,0};
byte dDot[]={
  M,6,17.5,L,6,15,L,4,15,L,4,17.5,L,6,17.5,Z,M,6,5,L,6,2.5,L,4,2.5,L,4,5,L,6,5,Z,0};


void setup()   {                
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 
  display.display();
  delay(250);
}

void loop() {
  display.clearDisplay();
  int a,b,c;
  int n = analogRead(0);
  a = n/100;
  b = (n % 100)/10;
  c = n % 10;
  unsigned long startTime=millis();
  //выводим число
  if (a !=0){
    drawSym(a);
  }
  drawSym(b);
  drawSym(c);
  cx=0;

  display.setTextSize(4);
  display.setTextColor(WHITE);
  display.setCursor(0,35);
  display.println(n);
  //вывод на экран времени затраченного на прорисовку
  unsigned long totalTime = millis()-startTime;
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(80,50);
  display.println(totalTime);
  //display.println(angle);
  display.display();
  delay(500);
  display.clearDisplay();
}

void drawSym(byte x){
    switch (x) {
  case 0:
    drawVector(dig0,cx,cy,m);
    break;
  case 1:
    drawVector(dig1,cx,cy,m);
    break;
  case 2:
    drawVector(dig2,cx,cy,m);
    break;
  case 3:
    drawVector(dig3,cx,cy,m);
    break;
  case 4:
    drawVector(dig4,cx,cy,m);
    break;
  case 5:
    drawVector(dig5,cx,cy,m);
    break;
  case 6:
    drawVector(dig6,cx,cy,m);
    break;
  case 7:
    drawVector(dig7,cx,cy,m);
    break;
  case 8:
    drawVector(dig8,cx,cy,m);
    break;
  case 9:
    drawVector(dig9,cx,cy,m);
    break;
    //    default:
  }
      cx=cx+14;
}

void drawVector(byte vector[],byte x,byte y,double m){
  byte startPoint[2];//начальная точка линии
 //строим картинку по массиву
  while (vector[st]!=0){//пока массив не закончился
  if (vector[st]==10){//SVG M
  //запоминаем точку начала кривой для замыкания контура
    startPoint[0]=(vector[st+1]+x);//координата Х
    startPoint[1]=(vector[st+2]+y);//координата У
    st=st+3;//переходим к след команде
 }  
   if (vector[st]==20){//SVG L если прямая
    display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+1]+x)*m,(vector[st+2]+y)*m,WHITE);
    st=st+3;
 }
   if (vector[st]==30){//SVG Q кривая 3 порядка НЕ ПРОВЕРЯЛ
    display.drawCurve3p((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+1]+x)*m,(vector[st+2]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
    st=st+5;
 }
 if (vector[st]==40){//SVG C кривая 4 порядка
    display.drawCurve4p((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+1]+x)*m,(vector[st+2]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,(vector[st+5]+x)*m,(vector[st+6]+y)*m,WHITE);
    st=st+7;
 }
  if (vector[st]==50){//SVG S ПОКА НЕ РАБОТАЕТ необходимо добавить
  //вычисление зеркальной опорной точки
    //display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
    display.drawCurve4p((vector[st-2]+x)*m,(vector[st-1]+y)*m,vector[st-4]*m,((vector[st-3]*m)+((vector[st-1]+y)*m)),(vector[st+1]+x)*m,(vector[st+2]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
    st=st+5;
 }
    if (vector[st]==60){//SVG V если прямая
    display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st-2]+x)*m,(vector[st+2]+y)*m,WHITE);
    st=st+3;
 }
 

  if (vector[st]==100){//SVG z замкнуть контур
    display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,startPoint[0]*m,startPoint[1]*m,WHITE);
    st=st+1;
 }
//раскоментировать для просмотра прорисовки
//  display.display();
//  delay(50);
 }
st=0;//сброс шагов обхода массива
}

Думаю к кодеровке символов нужно добовлять информацию о ширине символа для расчета отступов (если шрифт не моноширинный)

Logik
Offline
Зарегистрирован: 05.08.2014

Помоему и так очень неплохо. И 11-12 мсек - хороший результат. Жаль сейчас совсем нет времени, а то бы поигрался и я.

Logik
Offline
Зарегистрирован: 05.08.2014

Посмотрел поподробней. Цифры прорисованы исключительно прямыми. Это имеет свои + и -. Минус в том, больше примитивов и менее качественная картинка. Но зато общет прямых быстрей и можна толщину линии у буквы менять просто проведя вместо одной линии несколько паралельных на малом расстоянии.

Вобщем думаю что на прямых - нормально.

Для повышения качества символа и экономии места интересно иметь кодировки отдельных элементов символов в виде "библиотеки", т.е. отдельно качественно прорисовать кружки, дуги и т.д и хранить их один раз гдето в одном месте. Ну понятно что нижний круг у "8" и у "6" одинаковы,  зачем его каждый раз описывать, достаточно сослатся, например при прорисовки "8" на последовательность команд рисующих нижний кружек для "6". А для "5" возможно взять часть из этого кружка.... Или хранить отдельно загогулину "5" и отдельно недостающую этой загогулине до кружка часть. Тогда загогулина "5" будет использоватся для "3", "5", "6", "8", но для "6" и "8" к ней недостающее добавится. Ну и буквы "S", "d" и т.д уже не потребуют подробного описания этих мест. Наверно это уже не совсем SVG будет, а SVG++ )))

//информацию о ширине символа для расчета отступов (если шрифт не моноширинный)

Ну моноширотный у растровых никого не смущает. А если очень хочется - ширину символа легко определить по ходу прорисовки.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Эти дни эксперементировал, закончилось все тем что катострофически не хватает памяти. Необходимо описание символов переносить в PROGMEM или сжимать, и распоковывать по необходимости.

Код кому интересно

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//#include <avr/pgmspace.h>

//SVG Команды
#define M 10 //стартовая точка
#define L 20 //линия
#define Q 30 //кривая 3 порядка
#define C 40 //кривая 4 порядка
#define S 50 //кривая S типа
#define V 60 //вертикальная линия
#define z 100 //замкнуть контур со стартовой точкой
#define Z 100 //замкнуть контур со стартовой точкой
//добавить фигуры (круг, прямоугольник элипс и т.п.

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
int st=0;//шаги по массиву
//позиция курсора
byte cx=0;
byte cy=0;
//масштаб
double m=0.5;//минимально читаемый 0.2
//символы в векторном формате
byte dig1[]  ={
  M,10,16,L,10,0,L,0,5,0};
byte dig2[]  ={
  M,0,0,L,8,0,L,10,2,L,10,6,L,8,8,L,2,8,L,0,10,L,0,16,L,10,16,0};
byte dig3[]  ={
  M,0,0,L,8,0,L,10,2,L,10,6,L,8,8,L,10,10,L,10,14,L,8,16,L,0,16,M,4,8,L,8,8,0};
byte dig4[] ={
  M,0,0,L,0,6,L,2,8,L,10,8,M,10,0,L,10,16,0};
byte dig5[]={
  M,10,0,L,0,0,L,0,8,L,8,8,L,10,10,L,10,14,L,8,16,L,0,16,0};
byte dig6[]={
  M,10,2,L,8,0,L,2,0,L,0,2,L,0,14,L,2,16,L,8,16,L,10,14,L,10,10,L,8,8,L,0,8,0};
byte dig7[]={
  M,0,0,L,10,0,L,10,4,L,0,16,0};
byte dig8[]={
  M,2,0,L,8,0,L,10,2,L,10,6,L,8,8,L,10,10,L,10,14,L,8,16,L,2,16,L,0,14,L,0,10,L,2,8,L,0,6,L,0,2,Z,M,2,8,L,8,8,0};
byte dig9[]={
  M,10,8,L,2,8,L,0,6,L,0,2,L,2,0,L,8,0,L,10,2,L,10,14,L,8,16,L,2,16,L,0,14,0};
byte dig0[]={
  M,8,0,L,2,16,M,0,2,L,2,0,L,8,0,L,10,2,L,10,14,L,8,16,L,2,16,L,0,14,Z,0};
byte dot[]={
  M,6,17.5,L,6,15,L,4,15,L,4,17.5,L,6,17.5,Z,0};
byte dDot[]={
  M,6,17.5,L,6,15,L,4,15,L,4,17.5,L,6,17.5,Z,M,6,5,L,6,2.5,L,4,2.5,L,4,5,L,6,5,Z,0};
byte minus[]={
  M,10,10,L,0,10,0};
byte A[]={
  M,0,16,L,5,0,L,10,16,M,2,11,L,8,11,0};  
byte B[]={
  M,0,8,L,0,0,L,8,0,L,10,2,L,10,6,L,8,8,L,10,10,L,10,14,L,8,16,L,0,16,L,0,8,L,8,8,0};  
byte lC[]={
  M,10,2,L,8,0,L,2,0,L,0,2,L,0,14,L,2,16,L,8,16,L,10,14,0};
byte D[]={
  M,0,0,L,8,0,L,10,2,L,10,14,L,8,16,L,0,16,Z,0};
byte E[]={
  M,10,0,L,0,0,L,0,16,L,10,16,M,0,8,L,8,8,0};
byte F[]={
  M,10,0,L,0,0,L,0,16,M,0,8,L,8,8,0};
byte G[]={
  M,10,2,L,8,0,L,2,0,L,0,2,L,0,14,L,2,16,L,8,16,L,10,14,L,10,8,L,6,8,0};  
/*byte H[]={
  M,0,0,L,0,16,M,10,0,L,10,16,M,0,8,L,10,8,0};
  byte I[]={
  M,0,0,L,8,0,M,4,0,L,4,16,M,0,16,L,8,16,0};
byte J[]={
  M,0,0,L,8,0,L,8,14,L,6,16,L,2,16,L,0,14,0};
byte K[]={
  M,0,0,L,0,16,M,8,0,L,0,8,L,8,16,0};  */
void setup()   {                
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 
  display.display();
  delay(100);
}

void loop() {
  display.clearDisplay();
  int a,b,c;
  int n = analogRead(0);
  //int n=123;
  a = n/100;
  b = (n % 100)/10;
  c = n % 10;
  unsigned long startTime=millis();
  //выводим число
  if (a !=0){
    drawSym(a);
  }
  drawSym(b);
  drawSym(c);
  //вывод текста
  printVF("ABCD");
  cx=0;//курсор в начало
  /*  display.setTextSize(4);
   display.setTextColor(WHITE);
   display.setCursor(0,35);
   display.println(n);*/
  //вывод на экран времени затраченного на прорисовку
  unsigned long totalTime = millis()-startTime;
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(80,50);
  display.println(totalTime);
  //display.println(angle);
  display.display();
  delay(100);
  display.clearDisplay();
}

функция вывода чисел (эксперемент)

void drawSym(byte x){
  //  byte interval=13;
  switch (x) {
  case 0:
    drawVector(dig0,cx,cy,m);
    break;
  case 1:
    drawVector(dig1,cx,cy,m);
    break;
  case 2:
    drawVector(dig2,cx,cy,m);
    break;
  case 3:
    drawVector(dig3,cx,cy,m);
    break;
  case 4:
    drawVector(dig4,cx,cy,m);
    break;
  case 5:
    drawVector(dig5,cx,cy,m);
    break;
  case 6:
    drawVector(dig6,cx,cy,m);
    break;
  case 7:
    drawVector(dig7,cx,cy,m);
    break;
  case 8:
    drawVector(dig8,cx,cy,m);
    break;
  case 9:
    drawVector(dig9,cx,cy,m);
    break;
/*  case A:
    drawVector(A,cx,cy,m);
    break;*/
    //    default:
  }
  //     cx=cx+interval;
}

Функция вывода текста

//вывод текста
void printVF(char txt[]){
  byte symN=0;
  //  char txt[]="DAFB";//строка для вывода
  while (txt[symN]!='\0'){
    char sym;//для хранения символа
    sym=txt[symN];
    sym=sym-0;
    switch (sym) {
    case 65://A
      drawVector(A,cx,cy,m);
      break;
    case 66://B
      drawVector(B,cx,cy,m);
      break; 
    case 67://C
      drawVector(lC,cx,cy,m);
      break;   
    case 68:
      drawVector(D,cx,cy,m);
      break;
    case 69:
      drawVector(E,cx,cy,m);
      break;
    case 70:
      drawVector(F,cx,cy,m);
      break;
    case 71:
      drawVector(G,cx,cy,m);
      break;
    }
    symN=symN+1;
  }
}

Функция прорисовки кривых

void drawVector(byte vector[],byte x,byte y,double m){
    byte interval=13;
  byte startPoint[2];//начальная точка линии
  //double 
  //m=1.0;//масштаб от 0 к 1
//  double angle=0;//угол поворота
//  angle=angle*(PI/180);//перевод угла в радианы

 //строим картинку по массиву
  while (vector[st]!=0){//пока массив не закончился
  if (vector[st]==10){//SVG M
  //запоминаем точку начала кривой для замыкания контура
    startPoint[0]=(vector[st+1]+x);//координата Х
    startPoint[1]=(vector[st+2]+y);//координата У
    st=st+3;//переходим к след команде
 }  
   if (vector[st]==20){//SVG L если прямая
    display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+1]+x)*m,(vector[st+2]+y)*m,WHITE);
    st=st+3;
 }
   if (vector[st]==30){//SVG Q кривая 3 порядка НЕ ПРОВЕРЯЛ
    display.drawCurve3p((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+1]+x)*m,(vector[st+2]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
    st=st+5;
 }
 if (vector[st]==40){//SVG C кривая 4 порядка
    display.drawCurve4p((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+1]+x)*m,(vector[st+2]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,(vector[st+5]+x)*m,(vector[st+6]+y)*m,WHITE);
    st=st+7;
 }
  if (vector[st]==50){//SVG S ПОКА НЕ РАБОТАЕТ необходимо добавить
  //вычисление зеркальной опорной точки
    //display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
    display.drawCurve4p((vector[st-2]+x)*m,(vector[st-1]+y)*m,vector[st-4]*m,((vector[st-3]*m)+((vector[st-1]+y)*m)),(vector[st+1]+x)*m,(vector[st+2]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
    st=st+5;
 }
    if (vector[st]==60){//SVG V если прямая
    display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st-2]+x)*m,(vector[st+2]+y)*m,WHITE);
    st=st+3;
 }
 

  if (vector[st]==100){//SVG z замкнуть контур
    display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,startPoint[0]*m,startPoint[1]*m,WHITE);
    st=st+1;
 }
//раскоментировать для просмотра прорисовки
//  display.display();
//  delay(50);
 }
st=0;//сброс шагов обхода массива
      cx=cx+interval;
}

В принципе реально все сделать, но нужно продумать оптимизацию. Векторный текст крупного размера выглядит более привлекательно чем растровый ИМХО.

В итоге мой OLED 128х64 "надул кеды" как говорится. Стал показывать черезстрочно растягивая изображение по вертикали.

Пришлось эксперемент оставить.

Идет зима, есть более важные задачи по отоплению. Экран заказан новый, будем подождать.

Кому интересно можете развить идею.

b707
Offline
Зарегистрирован: 26.05.2017

yul-i-an пишет:

В итоге мой OLED 128х64 "надул кеды" как говорится. Стал показывать черезстрочно растягивая изображение по вертикали.

кстати, так тоже неплохо...

 

ИМХО, сама идея не слишком подходит для МК. вычислять кривые Безье в реале, чтобы только построить текст - это что-то из разряда многократноизбыточного кода, типа Гугля.

ИМХО, более плодотворная идея - на основе КБ на ПК написать генератор векторных шрифтов для ардуины, которым под конкретный дисплей генерить готовые к применению шрифты нужных размеров в виде традиционного битового массива.

Logik
Offline
Зарегистрирован: 05.08.2014

С растровыми шрифтами, т.е. "в виде традиционного битового массива" хоть правильней их таки растровыми называть, все класно пока они мелкие 5*8, 8*12. А когда крупные нужны - плохо. Например 30*48 - это 180 байт на символ. Только цифры и минимум символов - уже на пару КБ, еще ладно, а буквы уже десятки КБ, невлазят в МК. Приходится масштабировать, так  вылазят угловатые кубики вместо пикселей :( А векторные тут выручили бы конкретно.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Большие растровые шрифты можно легко сжать простеньким и достаточно эффективно реализуемым Хаффманом - отлично сжимаются.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Вчера тоже думал над двухступенчатым сжатием. Сначала пары 00-А 01-B 10-C 11-D а потом Хаффманом.
Хотя может подход не совсем верный.
Вот если на внешней памяти разместить шрифты то проблемм не будет. Или их както в PROGMEM затолкать, но не пробовал там както мутно для меня все.

Logik
Offline
Зарегистрирован: 05.08.2014

yul-i-an пишет:
Или их както в PROGMEM затолкать

Однозначно надо, в любых вариантах только в PROGMEM.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

yul-i-an пишет:
Хотя может подход не совсем верный. Вот если на внешней памяти разместить шрифты то проблемм не будет. Или их както в PROGMEM затолкать, но не пробовал там както мутно для меня все.
На большом компе сжать и затолкать в PROGMEM, а расжимать уже ардуиной

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Разбирался с PROGMEM. В итоге память заметно освободилась (пока только цифры перенес).

const PROGMEM byte dig0[]={
  M,8,0,L,2,16,M,0,2,L,2,0,L,8,0,L,10,2,L,10,14,L,8,16,L,2,16,L,0,14,Z,0};

Написал такой код

            int len = sizeof(dig0);//определяем длину массива (dig0-массив с векторами цифра 0)
            byte bufer[len];//создаем буфер для чтения массива из PROGMEM
            byte b, k;//переменные
            for (k = 0; k < len; k++)
            {
              b =  pgm_read_byte_near(dig0 + k);//читаем из PROGMEM
              bufer[k] = b;//заносим в буфер
            }
            drawVector(bufer, cx, cy, m);//выводим на экран из буфера

Теперь его нужно в функцию оформить в которую будет передаватся ссылка на массив. Сообразить не могу как.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А так что не работает 

void func(byte dig0[]) {
  int len = sizeof(dig0);//определяем длину массива (dig0-массив с векторами цивра 0)
  byte bufer[len];//создаем буфер для чтения массива из PROGMEM
  byte b, k;//переменные
  for (k = 0; k < len; k++)
  {
    b =  pgm_read_byte_near(dig0 + k);//читаем из PROGMEM
    bufer[k] = b;//заносим в буфер
  }
  drawVector(bufer, cx, cy, m);//выводим на экран из буфера
}

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Нет. Так не получается.

Хотел так передавать

void drawSym(byte x) {
  switch (x) {
    case 0:
      PMRead(dig0);
      break;
    case 1:
      PMRead(dig1);
      break;
    case 2:
      PMRead(dig2);
      break;
    case 3:
      PMRead(dig3);
      break;
//
//и т.д.
//
}

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Вот так заработало если так можно выразится, виснет после каждого вывода

void drawSym(byte x) {
int len;
 switch (x) {
    case 0:
      len = sizeof(dig0);//определяем длину массива
      PMRead(dig0, len);
      break;
    case 1:
      len = sizeof(dig0);//определяем длину массива
      PMRead(dig1, len);
      break;
    case 2:
      len = sizeof(dig0);//определяем длину массива
      PMRead(dig2,len);
      break;
//и т.д.
}

Чтение из PROGMEM

void PMRead( byte x[], int l ) {
  int len = l;//определяем длину массива
  byte bufer[len];//создаем буфер для чтения массива из PROGMEM
  byte b, k;//переменные
  for (k = 0; k < len; k++)
  {
    b =  pgm_read_byte_near(x + k);//читаем из PROGMEM
    bufer[k] = b;//заносим в буфер
  }
  drawVector(bufer, cx, cy, m);//выводим на экран из буфера
}

Надо думать дальше...

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Нашел ошибку в посте #40 в первом листинге в функцию PMRead передовал длину массива для всех цифр от dig0. Исправил на соответствующие, все заработало.

void drawSym(byte x) {
  int len;
  switch (x) {
    case 0:
      len = sizeof(dig0);//определяем длину массива
      PMRead(dig0, len);
      break;
    case 1:
      len = sizeof(dig1);//определяем длину массива
      PMRead(dig1, len);
      break;
    case 2:
      len = sizeof(dig2);//определяем длину массива
      PMRead(dig2, len);
      break;
    case 3:
      len = sizeof(dig3);//определяем длину массива
      PMRead(dig3, len);
      break;
    case 4:
      len = sizeof(dig4);//определяем длину массива
      PMRead(dig4, len);
      break;
    case 5:
      len = sizeof(dig5);//определяем длину массива
      PMRead(dig5, len);
      break;
    case 6:
      len = sizeof(dig6);//определяем длину массива
      PMRead(dig6, len);
       break;
    case 7:
      len = sizeof(dig7);//определяем длину массива
      PMRead(dig7, len);
      break;
    case 8:
      len = sizeof(dig8);//определяем длину массива
      PMRead(dig8, len);
      break;
    case 9:
      len = sizeof(dig9);//определяем длину массива
      PMRead(dig9, len);
      break;
    default:
      return;
  }
}

Итог - вывод 10 символов занимает от 7-11 мс в масштабе 0.7, в масштабе 1:1 9 символов 4-6мс

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Полностью ввел заглавные латинские и цифры

Видео

Дисплею совсем поплохело, через не продолжительное время работы мерцать стал, хотя может код виновен... Ели у кого появится желание проверить отпишитесь о результате

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <avr/pgmspace.h>

//SVG Команды
#define M 10 //стартовая точка
#define L 20 //линия
#define Q 30 //кривая 3 порядка
#define C 40 //кривая 4 порядка
#define S 50 //кривая S типа
#define V 60 //вертикальная линия
#define z 100 //замкнуть контур со стартовой точкой
#define Z 100 //замкнуть контур со стартовой точкой
//добавить фигуры (круг, прямоугольник элипс и т.п.

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
int st = 0; //шаги по массиву
//позиция курсора
byte cx = 0;
byte cy = 0;
//масштаб
double m = 0.8;

//символы в векторном формате
const PROGMEM byte space[]  = {
  0
};
const PROGMEM byte dig1[]  = {
  M, 10, 16, L, 10, 0, L, 0, 5, 0
};
const PROGMEM byte dig2[]  = {
  M, 0, 0, L, 8, 0, L, 10, 2, L, 10, 6, L, 8, 8, L, 2, 8, L, 0, 10, L, 0, 16, L, 10, 16, 0
};
const PROGMEM byte dig3[]  = {
  M, 0, 0, L, 8, 0, L, 10, 2, L, 10, 6, L, 8, 8, L, 10, 10, L, 10, 14, L, 8, 16, L, 0, 16, M, 4, 8, L, 8, 8, 0
};
const PROGMEM byte dig4[] = {
  M, 0, 0, L, 0, 6, L, 2, 8, L, 10, 8, M, 10, 0, L, 10, 16, 0
};
const PROGMEM byte dig5[] = {
  M, 10, 0, L, 0, 0, L, 0, 8, L, 8, 8, L, 10, 10, L, 10, 14, L, 8, 16, L, 0, 16, 0
};
const PROGMEM byte dig6[] = {
  M, 10, 2, L, 8, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 8, 16, L, 10, 14, L, 10, 10, L, 8, 8, L, 0, 8, 0
};
const PROGMEM byte dig7[] = {
  M, 0, 0, L, 10, 0, L, 10, 4, L, 0, 16, 0
};
const PROGMEM byte dig8[] = {
  M, 2, 0, L, 8, 0, L, 10, 2, L, 10, 6, L, 8, 8, L, 10, 10, L, 10, 14, L, 8, 16, L, 2, 16, L, 0, 14, L, 0, 10, L, 2, 8, L, 0, 6, L, 0, 2, Z, M, 2, 8, L, 8, 8, 0
};
const PROGMEM byte dig9[] = {
  M, 10, 8, L, 2, 8, L, 0, 6, L, 0, 2, L, 2, 0, L, 8, 0, L, 10, 2, L, 10, 14, L, 8, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM byte dig0[] = {
  M, 8, 0, L, 2, 16, M, 0, 2, L, 2, 0, L, 8, 0, L, 10, 2, L, 10, 14, L, 8, 16, L, 2, 16, L, 0, 14, Z, 0
};
const PROGMEM byte dot[] = {
  M, 6, 17.5, L, 6, 15, L, 4, 15, L, 4, 17.5, L, 6, 17.5, Z, 0
};
const PROGMEM byte dDot[] = {
  M, 6, 17.5, L, 6, 15, L, 4, 15, L, 4, 17.5, L, 6, 17.5, Z, M, 6, 5, L, 6, 2.5, L, 4, 2.5, L, 4, 5, L, 6, 5, Z, 0
};
const PROGMEM byte minus[] = {
  M, 10, 10, L, 0, 10, 0
};
const PROGMEM byte A[] = {
  M, 0, 16, L, 5, 0, L, 10, 16, M, 2, 11, L, 8, 11, 0
};
const PROGMEM byte B[] = {
  M, 0, 8, L, 0, 0, L, 8, 0, L, 10, 2, L, 10, 6, L, 8, 8, L, 10, 10, L, 10, 14, L, 8, 16, L, 0, 16, L, 0, 8, L, 8, 8, 0
};
const PROGMEM byte lC[] = {
  M, 10, 2, L, 8, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 8, 16, L, 10, 14, 0
};
const PROGMEM byte D[] = {
  M, 0, 0, L, 8, 0, L, 10, 2, L, 10, 14, L, 8, 16, L, 0, 16, Z, 0
};
const PROGMEM byte E[] = {
  M, 10, 0, L, 0, 0, L, 0, 16, L, 10, 16, M, 0, 8, L, 8, 8, 0
};
const PROGMEM byte F[] = {
  M, 10, 0, L, 0, 0, L, 0, 16, M, 0, 8, L, 8, 8, 0
};
const PROGMEM byte G[] = {
  M, 10, 2, L, 8, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 8, 16, L, 10, 14, L, 10, 8, L, 6, 8, 0
};
const PROGMEM byte H[] = {
  M, 0, 0, L, 0, 16, M, 10, 0, L, 10, 16, M, 0, 8, L, 10, 8, 0
};
const PROGMEM byte I[] = {
  M, 0, 0, L, 8, 0, M, 4, 0, L, 4, 16, M, 0, 16, L, 8, 16, 0
};
const PROGMEM byte J[] = {
  M, 0, 0, L, 8, 0, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM byte K[] = {
  M, 0, 0, L, 0, 16, M, 8, 0, L, 0, 8, L, 8, 16, 0
};
const PROGMEM byte lL[] = {
  M, 0, 0, L, 0, 16, L, 8, 16, 0
};
const PROGMEM byte lM[] = {
  M, 0, 16, L, 0, 0, L, 4, 10, L, 8, 0, L, 8, 16, 0
};
const PROGMEM byte lN[] = {
  M, 0, 16, L, 0, 0, L, 8, 16, L, 8, 0, 0
};
const PROGMEM byte lO[] = {
  M, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, 0
};
const PROGMEM byte lP[] = {
  M, 0, 16, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 0, 8, 0
};
const PROGMEM byte lQ[] = {
  M, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, M, 4, 14, L, 8, 16, 0
};
const PROGMEM byte lR[] = {
  M, 0, 16, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 0, 8, L, 8, 16, 0
};
const PROGMEM byte lS[] = {
  M, 8, 0, L, 2, 0, L, 0, 2, L, 0, 6, L, 2, 8, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM byte lT[] = {
  M, 0, 0, L, 8, 0, M, 4, 0, L, 4, 16, 0
};
const PROGMEM byte lU[] = {
  M, 0, 0, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 0, 0
};
const PROGMEM byte lV[] = {
  M, 0, 0, L, 4, 16, L, 8, 0, 0
};
const PROGMEM byte lW[] = {
  M, 0, 0, L, 2, 16, L, 4, 6, L, 6, 16, L, 8, 0, 0
};
const PROGMEM byte lX[] = {
  M, 0, 0, L, 8, 16, M, 8, 0, L, 0, 16, 0
};
const PROGMEM byte lY[] = {
  M, 0, 0, L, 4, 8, L, 4, 16, M, 4, 8, L, 8, 0, 0
};
const PROGMEM byte lZ[] = {
  M, 0, 0, L, 8, 0, L, 0, 16, L, 8, 16, 0
};
void setup()   {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  delay(100);
}

void loop() {
  display.clearDisplay();
  int a, b, c;
  int n = analogRead(0);
//установка курсора
  cx = 0;
  cy = 0;
  unsigned long startTime = millis();
  //вывод INT
  printVF(n);
  //вывод текста
  cx = 0;
  cy = 20;
  printVF("HELLO WORLD");
   //вывод на экран времени затраченного на прорисовку
  unsigned long totalTime = millis() - startTime;
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(100, 0);
  display.println(totalTime);
  //display.println(angle);
  display.display();
  delay(300);
  display.clearDisplay();
}

//чтение и прорисовка из PROGMEM
void PMRead( byte x[], int l ) {
  int len = l;//получаем длину массива
  byte bufer[len];//создаем буфер для чтения массива из PROGMEM
  byte b, k;//переменные
  for (k = 0; k < len; k++)
  {
    b =  pgm_read_byte_near(x + k);//читаем из PROGMEM
    bufer[k] = b;//заносим в буфер
  }
  drawVector(bufer, cx, cy, m);//выводим на экран из буфера
}

void drawVector(byte vector[], byte x, byte y, double m) {
  byte interval = 13;
  byte startPoint[2];//начальная точка линии
  //строим картинку по массиву
  while (vector[st] != 0) { //пока массив не закончился
    if (vector[st] == 10) { //SVG M
      //запоминаем точку начала кривой для замыкания контура
      startPoint[0] = (vector[st + 1] + x); //координата Х
      startPoint[1] = (vector[st + 2] + y); //координата У
      st = st + 3; //переходим к след команде
    }
    if (vector[st] == 20) { //SVG L если прямая
      display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, WHITE);
      st = st + 3;
    }
    if (vector[st] == 30) { //SVG Q кривая 3 порядка НЕ ПРОВЕРЯЛ
      display.drawCurve3p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, WHITE);
      st = st + 5;
    }
    if (vector[st] == 40) { //SVG C кривая 4 порядка
      display.drawCurve4p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, (vector[st + 5] + x)*m, (vector[st + 6] + y)*m, WHITE);
      st = st + 7;
    }
    if (vector[st] == 50) { //SVG S ПОКА НЕ РАБОТАЕТ необходимо добавить
      //вычисление зеркальной опорной точки
      //display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
      display.drawCurve4p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, vector[st - 4]*m, ((vector[st - 3]*m) + ((vector[st - 1] + y)*m)), (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, WHITE);
      st = st + 5;
    }
    if (vector[st] == 60) { //SVG V если прямая
      display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st - 2] + x)*m, (vector[st + 2] + y)*m, WHITE);
      st = st + 3;
    }


    if (vector[st] == 100) { //SVG z замкнуть контур
      display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, startPoint[0]*m, startPoint[1]*m, WHITE);
      st = st + 1;
    }
  }
  st = 0; //сброс шагов обхода массива
  cx = cx + interval;//курсор на следующий символ
}

// Функция преобразования числа в строку (не моя, нашел в сети)
char* printVF(int n)
{
  char s[40], t, *temp;
  int i, k;
  int sign = 0;
  i = 0;
  k = n;
  if (k<0)
  {
    sign = 1;
    k = -k;
  }
  do {
    t = k % 10;
    k = k / 10;
    s[i] = t | 0x30;
    i++;
  } while (k>0);
  if (sign == 1)
  {
    s[i] = '-';
    i++;
  }
  temp = new char[i];
  k = 0;
  i--;
  while (i >= 0) {
    temp[k] = s[i]+1;
    i--; k++;
  }
  temp[k] = '\0';
  printVF(temp);
  //return(temp);
}

//вывод текста
void printVF(char txt[]) {
  int len;
  byte symN = 0;
  while (txt[symN] != '\0') {
    char sym;//для хранения символа
    sym = txt[symN];
    sym = sym - 0;
    switch (sym) {
      case 32:
        len = sizeof(space);//определяем длину массива
        PMRead(space, len);
        break;
      case 49:
        len = sizeof(dig0);//определяем длину массива
        PMRead(dig0, len);
        break;
      case 50:
        len = sizeof(dig1);//определяем длину массива
        PMRead(dig1, len);
        break;
      case 51:
        len = sizeof(dig2);//определяем длину массива
        PMRead(dig2, len);
        break;
      case 52:
        len = sizeof(dig3);//определяем длину массива
        PMRead(dig3, len);
        break;
      case 53:
        len = sizeof(dig4);//определяем длину массива
        PMRead(dig4, len);
        break;
      case 54:
        len = sizeof(dig5);//определяем длину массива
        PMRead(dig5, len);
        break;
      case 55:
        len = sizeof(dig6);//определяем длину массива
        PMRead(dig6, len);
        break;
      case 56:
        len = sizeof(dig7);//определяем длину массива
        PMRead(dig7, len);
        break;
      case 57:
        len = sizeof(dig8);//определяем длину массива
        PMRead(dig8, len);
        break;
      case 58:
        len = sizeof(dig9);//определяем длину массива
        PMRead(dig9, len);
        break;
      case 65://A
        len = sizeof(A);//определяем длину массива
        PMRead(A, len);
        break;
      case 66://B
        len = sizeof(B);//определяем длину массива
        PMRead(B, len);
        break;
      case 67://C
        len = sizeof(lC);//определяем длину массива
        PMRead(lC, len);
        break;
      case 68:
        len = sizeof(D);//определяем длину массива
        PMRead(D, len);
        break;
      case 69:
        len = sizeof(E);//определяем длину массива
        PMRead(E, len);
        //drawVector(E, cx, cy, m);
        break;
      case 70:
        len = sizeof(F);//определяем длину массива
        PMRead(F, len);
        //drawVector(F, cx, cy, m);
        break;
      case 71:
        len = sizeof(G);//определяем длину массива
        PMRead(G, len);
        //drawVector(G, cx, cy, m);
        break;
      case 72:
        len = sizeof(H);//определяем длину массива
        PMRead(H, len);
        //drawVector(H,cx,cy,m);
        break;
      case 73:
        len = sizeof(I);//определяем длину массива
        PMRead(I, len);
        //drawVector(I,cx,cy,m);
        break;
      case 74:
        len = sizeof(J);//определяем длину массива
        PMRead(J, len);
        //drawVector(J,cx,cy,m);
        break;
      case 75:
        len = sizeof(K);//определяем длину массива
        PMRead(K, len);
        //drawVector(K,cx,cy,m);
        break;
      case 76:
        len = sizeof(lL);//определяем длину массива
        PMRead(lL, len);
        break;
      case 77:
        len = sizeof(lM);//определяем длину массива
        PMRead(lM, len);
        break;
      case 78:
        len = sizeof(lN);//определяем длину массива
        PMRead(lN, len);
        break;
      case 79:
        len = sizeof(lO);//определяем длину массива
        PMRead(lO, len);
        break;
      case 80:
        len = sizeof(lP);//определяем длину массива
        PMRead(lP, len);
        break;
      case 81:
        len = sizeof(lQ);//определяем длину массива
        PMRead(lQ, len);
        break;
      case 82:
        len = sizeof(lR);//определяем длину массива
        PMRead(lR, len);
        break;
      case 83:
        len = sizeof(lS);//определяем длину массива
        PMRead(lS, len);
        break;
      case 84:
        len = sizeof(lT);//определяем длину массива
        PMRead(lT, len);
        break;
      case 85:
        len = sizeof(lU);//определяем длину массива
        PMRead(lU, len);
        break;
      case 86:
        len = sizeof(lV);//определяем длину массива
        PMRead(lV, len);
        break;
      case 87:
        len = sizeof(lW);//определяем длину массива
        PMRead(lW, len);
        break;
      case 88:
        len = sizeof(lX);//определяем длину массива
        PMRead(lX, len);
        break;
      case 89:
        len = sizeof(lY);//определяем длину массива
        PMRead(lY, len);
        break;
      case 90:
        len = sizeof(lZ);//определяем длину массива
        PMRead(lZ, len);
        break;
      default:
        return;
    }
    symN = symN + 1;
  }
  //symN = symN + 1;
}

Если что по упрощению есть предлогайте.

Logik
Offline
Зарегистрирован: 05.08.2014

Помоему на видео просто великолепно! 

Упрощать есть что. Нужно завести массив указателей, пусть simbols , на массивы от spase до lz. Это позволит избавится от длинного свича, заменив его на PMRead(simbols[sym-32]); Если порыть либы то найдется коечего 

типа

#define PGM_P const prog_char *

#define PGM_VOID_P const prog_void *

extern PGM_VOID_P memchr_P(PGM_VOID_P, int __val, size_t __len) __ATTR_CONST__;
extern int memcmp_P(const void *, PGM_VOID_P, size_t) __ATTR_PURE__;
extern size_t strlcpy_P (char *, PGM_P, size_t );
extern size_t strlen_P(PGM_P) __ATTR_CONST__; /* program memory can't change */
 

И т.д.

Я себе массив указателей на строки в progmem так делал.


const char SubMenuLogCaption[] PROGMEM ="Журнал";
const char SubMenuLog1[] PROGMEM ="Просмотр";
const char SubMenuLog2[] PROGMEM ="Очистить текущее";
const char SubMenuLog3[] PROGMEM ="Выгрузить";
const char SubMenuLog4[] PROGMEM ="Очистить все";

PGM_P const SubMenuLog[] PROGMEM = {SubMenuLogCaption, SubMenuLog1, SubMenuLog2, SubMenuLog3, SubMenuLog4};


byte SSD1306::drawStringP(uint8_t x, uint8_t y, const char *c)
{
	return drawStringBase(x, y, fn2, pgm_read_byte(c));
}

byte SSD1306::drawStringPP(uint8_t x, uint8_t y, const char* const* c, byte i)
{
    PGM_P p;
    memcpy_P(&p, &c[i], sizeof(PGM_P));  //указатель на строку в PROGMEM
    return drawStringP(x, y, p);
}

myOLED.drawStringPP(...,SubMenuLog,i); //массив строк и номер строки в нем

Вам массив указателей не на строку а на массив, оно будет подобным.

И длину передавать не нужно, прочто цикл стр.185-189 вести не по условию длины, а пока не прочитаем 0. Гдето так.

  for (k = 0; ; k++)
  {
     b =  pgm_read_byte_near(x + k);//читаем из PROGMEM
     bufer[k] = b;//заносим в буфер
     if(!b)
       break;
  }
yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Спасибо за информацию. Буду копать дальше. Пока с выводом переменных заморачивался.

 

void printVF(int n)
{
  char buffer [12];
  itoa (n, buffer, 10);
  printVF(buffer);
}

void printVF(double n)
{
  char buffer [12];
  int a; //числитель
  int b; //знаменатель
  //округляем
  int c = n * 100;
  //получаем числитель
  a = (c / 100) % 1000;
  itoa (a, buffer, 10);
  printVF(buffer);
  printVF(".");
  //получем знаменатель
  b = abs(c % 100);
  itoa (b, buffer, 10);
  printVF(buffer);
}

Костыль на костыле. Может кто преобразовываль числа с плавающей точкой в строки?

Logik
Offline
Зарегистрирован: 05.08.2014

Этого валом в сети, первое попавшее https://www.geeksforgeeks.org/convert-floating-point-number-string/

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

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

Сейчас добавляю недостающие символы к шрифту.

Видео прорисовки векторного шрифта на OLED (умышленно замедленное программно)

Код кому интересно

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <avr/pgmspace.h>

//SVG Команды
#define M 10 //стартовая точка
#define L 20 //линия
#define Q 30 //кривая 3 порядка
#define C 40 //кривая 4 порядка
#define S 50 //кривая S типа
#define V 60 //вертикальная линия
#define z 100 //замкнуть контур со стартовой точкой
#define Z 100 //замкнуть контур со стартовой точкой
//добавить фигуры (круг, прямоугольник элипс и т.п.
void setCursorVF(byte, byte);
void printVF(char);
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
byte st = 0; //шаги по массиву
//позиция курсора
byte cx = 0;
byte cy = 0;
//масштаб
double m = 1; //минимально читаемый 0.4
const PROGMEM uint8_t space[]  = {
  0
};
const PROGMEM uint8_t d1[]  = {
  M, 8, 16, L, 8, 0, L, 0, 5, 0
};
const PROGMEM uint8_t d2[]  = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 2, 8, L, 0, 10, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t d3[]  = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, M, 2, 8, L, 6, 8, 0
};
const PROGMEM uint8_t d4[] = {
  M, 0, 0, L, 0, 6, L, 2, 8, L, 8, 8, M, 8, 0, L, 8, 16, 0
};
const PROGMEM uint8_t d5[] = {
  M, 8, 0, L, 0, 0, L, 0, 8, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t d6[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 10, L, 8, 8, L, 0, 8, 0
};
const PROGMEM uint8_t d7[] = {
  M, 0, 0, L, 8, 0, L, 8, 4, L, 0, 16, 0
};
const PROGMEM uint8_t d8[] = {
  M, 2, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, L, 0, 10, L, 2, 8, L, 0, 6, L, 0, 2, Z, M, 2, 8, L, 6, 8, 0
};
const PROGMEM uint8_t d9[] = {
  M, 8, 8, L, 2, 8, L, 0, 6, L, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM uint8_t d0[] = {
  M, 0, 6, L, 2, 0, L, 6, 0, L, 8, 6, L, 8, 10, L, 6, 16, L, 2, 16, L, 0, 10, Z, 0
};
const PROGMEM uint8_t dot[] = {
  M, 6, 16, L, 6, 15, L, 4, 15, L, 4, 16, Z, 0
};
const PROGMEM uint8_t dDot[] = {
  M, 6, 16, L, 6, 15, L, 4, 15, L, 4, 16, L, 6, 16, Z, M, 6, 5, L, 6, 2, L, 4, 2, L, 4, 5, Z, 0
};
const PROGMEM uint8_t minus[] = {
  M, 0, 10, L, 8, 10, 0
};
const PROGMEM uint8_t lA[] = {
  M, 0, 16, L, 4, 0, L, 8, 16, M, 2, 11, L, 6, 11, 0
};
const PROGMEM uint8_t lB[] = {
  M, 0, 8, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, L, 0, 8, L, 8, 8, 0
};
const PROGMEM uint8_t lC[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, 0
};
const PROGMEM uint8_t lD[] = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 0, 16, Z, 0
};
const PROGMEM uint8_t lE[] = {
  M, 8, 0, L, 0, 0, L, 0, 16, L, 8, 16, M, 0, 8, L, 6, 8, 0
};
const PROGMEM uint8_t lF[] = {
  M, 8, 0, L, 0, 0, L, 0, 16, M, 0, 8, L, 6, 8, 0
};
const PROGMEM uint8_t lG[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 8, L, 5, 8, 0
};
const PROGMEM uint8_t lH[] = {
  M, 0, 0, L, 0, 16, M, 8, 0, L, 8, 16, M, 0, 8, L, 8, 8, 0
};
const PROGMEM uint8_t lI[] = {
  M, 0, 0, L, 8, 0, M, 4, 0, L, 4, 16, M, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t lJ[] = {
  M, 0, 0, L, 8, 0, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM uint8_t lK[] = {
  M, 0, 0, L, 0, 16, M, 8, 0, L, 0, 8, L, 8, 16, 0
};
const PROGMEM uint8_t lL[] = {
  M, 0, 0, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t lM[] = {
  M, 0, 16, L, 0, 0, L, 4, 10, L, 8, 0, L, 8, 16, 0
};
const PROGMEM uint8_t lN[] = {
  M, 0, 16, L, 0, 0, L, 8, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lO[] = {
  M, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, 0
};
const PROGMEM uint8_t lP[] = {
  M, 0, 16, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 0, 8, 0
};
const PROGMEM uint8_t lQ[] = {
  M, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, M, 4, 14, L, 8, 16, 0
};
const PROGMEM uint8_t lR[] = {
  M, 0, 16, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 0, 8, M, 4, 8, L, 8, 16, 0
};
const PROGMEM uint8_t lS[] = {
  M, 8, 0, L, 2, 0, L, 0, 2, L, 0, 6, L, 2, 8, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t lT[] = {
  M, 0, 0, L, 8, 0, M, 4, 0, L, 4, 16, 0
};
const PROGMEM uint8_t lU[] = {
  M, 0, 0, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 0, 0
};
const PROGMEM uint8_t lV[] = {
  M, 0, 0, L, 4, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lW[] = {
  M, 0, 0, L, 2, 16, L, 4, 6, L, 6, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lX[] = {
  M, 0, 0, L, 8, 16, M, 8, 0, L, 0, 16, 0
};
const PROGMEM uint8_t lY[] = {
  M, 0, 0, L, 4, 8, L, 4, 16, M, 4, 8, L, 8, 0, 0
};
const PROGMEM uint8_t lZ[] = {
  M, 0, 0, L, 8, 0, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t la[] = {
  M, 2, 6, L, 6, 6, L, 8, 8, L, 8, 16, L, 2, 16, L, 0, 14, L, 0, 12, L, 2, 10, L, 8, 10, 0
};
const PROGMEM uint8_t lb[] = {
  M, 0, 0, L, 0, 16, L, 6, 16, L, 8, 14, L, 8, 10, L, 6, 6, L, 0, 6, 0
};
const PROGMEM uint8_t lc[] = {
  M, 8, 6, L, 2, 6, L, 0, 8, L, 0, 14, L, 2, 16, L, 8, 16, 0
};
const PROGMEM uint8_t ld[] = {
  M, 8, 0, L, 8, 16, L, 2, 16, L, 0, 14, L, 0, 8, L, 2, 6, L, 8, 6, 0
};
const PROGMEM uint8_t le[] = {
  M, 8, 16, L, 2, 16, L, 0, 14, L, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, L, 8, 12, L, 0, 12, 0
};
const PROGMEM uint8_t lf[] = {
  M, 0, 10, L, 6, 10, M, 2, 16, L, 2, 2, L, 4, 0, L, 6, 0, L, 8, 2, 0
};
const PROGMEM uint8_t lg[] = {
  M, 8, 12, L, 2, 12, L, 0, 10, L, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t lh[] = {
  M, 0, 0, L, 0, 16, M, 0, 6, L, 6, 6, L, 8, 8, L, 8, 16, 0
};
void setup()   {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  //delay(5);
}

void loop() {
  display.clearDisplay();
  int n = analogRead(0);
  setCursorVF(0, 0);
  //drawVector(BigB,0,0,1);
  unsigned long startTime = millis();
  printVF("Adc: ");
  //вывод INT
  printVF(n);
  //вывод текста
  setCursorVF(0, 20);
  printVF("defgh:-15.4");
  //вывод на экран времени затраченного на прорисовку
  unsigned long totalTime = millis() - startTime;
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(100, 0);
  display.println(totalTime);
  display.display();
  delay(250);
  display.clearDisplay();
}

void PMRead( byte x[], int l ) {
  byte len = l;//принимаем длину массива
  byte bufer[len];//создаем буфер для чтения массива из PROGMEM
  byte b, k;//переменные
  for (k = 0; k < len; k++)
  {
    b =  pgm_read_byte_near(x + k);//читаем из PROGMEM
    bufer[k] = b;//заносим в буфер
  }
  drawVector(bufer, cx, cy, m);//выводим на экран из буфера
}

void drawVector(uint8_t vector[], byte x, byte y, double m) {
  byte interval = 13;
  byte startPoint[2];//начальная точка линии
  //double
  //m=1.0;//масштаб от 0 к 1
  //  double angle=0;//угол поворота
  //  angle=angle*(PI/180);//перевод угла в радианы

  //строим картинку по массиву
  while (vector[st] != 0) { //пока массив не закончился
    if (vector[st] == 10) { //SVG M
      //запоминаем точку начала кривой для замыкания контура
      startPoint[0] = (vector[st + 1] + x); //координата Х
      startPoint[1] = (vector[st + 2] + y); //координата У
      st = st + 3; //переходим к след команде
    }
    if (vector[st] == 20) { //SVG L если прямая
      display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, WHITE);
      st = st + 3;
    }
    if (vector[st] == 30) { //SVG Q кривая 3 порядка НЕ ПРОВЕРЯЛ
      display.drawCurve3p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, WHITE);
      st = st + 5;
    }
    if (vector[st] == 40) { //SVG C кривая 4 порядка
      display.drawCurve4p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, (vector[st + 5] + x)*m, (vector[st + 6] + y)*m, WHITE);
      st = st + 7;
    }
    if (vector[st] == 50) { //SVG S ПОКА НЕ РАБОТАЕТ необходимо добавить
      //вычисление зеркальной опорной точки
      //display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
      display.drawCurve4p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, vector[st - 4]*m, ((vector[st - 3]*m) + ((vector[st - 1] + y)*m)), (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, WHITE);
      st = st + 5;
    }
    if (vector[st] == 60) { //SVG V если прямая
      display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st - 2] + x)*m, (vector[st + 2] + y)*m, WHITE);
      st = st + 3;
    }


    if (vector[st] == 100) { //SVG z замкнуть контур
      display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, startPoint[0]*m, startPoint[1]*m, WHITE);
      st = st + 1;
    }
    //раскоментировать для просмотра прорисовки
      display.display();
      delay(50);
  }
  st = 0; //сброс шагов обхода массива
  cx = cx + interval;
}


// Функция преобразования числа в строку
void printVF(int n)
{
  char buffer [12];
  itoa (n, buffer, 10);
  printVF(buffer);
}

void printVF(double n)
{
  char buffer [12];
  int a; //числитель
  int b; //знаменатель
  //округляем
  int c = n * 100;
  //получаем числитель
  a = (c / 100) % 1000;
  itoa (a, buffer, 10);
  printVF(buffer);
  printVF(".");
  //получем знаменатель
  b = abs(c % 100);
  itoa (b, buffer, 10);
  printVF(buffer);
}

// Функция преобразования числа в строку
void printVF(unsigned int n)
{
  char buffer [12];
  itoa (n, buffer, 10);
  printVF(buffer);
}

//вывод текста
void printVF(char txt[]) {
  byte len;
  byte symN = 0;
  while (txt[symN] != '\0') {
    char sym;//для хранения символа
    sym = txt[symN];
    sym = sym - 0;
    switch (sym) {
      case 32:
        len = sizeof(space);//определяем длину массива
        PMRead(space, len);
        break;
      case 45:
        len = sizeof(minus);//определяем длину массива
        PMRead(minus, len);
        break;
      case 46:
        len = sizeof(dot);//определяем длину массива
        PMRead(dot, len);
        break;
      case 48:
        len = sizeof(d0);//определяем длину массива
        PMRead(d0, len);
        break;
      case 49:
        len = sizeof(d1);//определяем длину массива
        PMRead(d1, len);
        break;
      case 50:
        len = sizeof(d2);//определяем длину массива
        PMRead(d2, len);
        break;
      case 51:
        len = sizeof(d3);//определяем длину массива
        PMRead(d3, len);
        break;
      case 52:
        len = sizeof(d4);//определяем длину массива
        PMRead(d4, len);
        break;
      case 53:
        len = sizeof(d5);//определяем длину массива
        PMRead(d5, len);
        break;
      case 54:
        len = sizeof(d6);//определяем длину массива
        PMRead(d6, len);
        break;
      case 55:
        len = sizeof(d7);//определяем длину массива
        PMRead(d7, len);
        break;
      case 56:
        len = sizeof(d8);//определяем длину массива
        PMRead(d8, len);
        break;
      case 57:
        len = sizeof(d9);//определяем длину массива
        PMRead(d9, len);
        break;
      case 58:
        len = sizeof(dDot);//определяем длину массива
        PMRead(dDot, len);
        break;
      case 65://A65
        len = sizeof(lA);//определяем длину массива
        PMRead(lA, len);
        break;
      case 66://B
        len = sizeof(lB);//определяем длину массива
        PMRead(lB, len);
        break;
      case 67://C
        len = sizeof(lC);//определяем длину массива
        PMRead(lC, len);
        break;
      case 68:
        len = sizeof(lD);//определяем длину массива
        PMRead(lD, len);
        break;
      case 69:
        len = sizeof(lE);//определяем длину массива
        PMRead(lE, len);
        break;
      case 70:
        len = sizeof(lF);//определяем длину массива
        PMRead(lF, len);
        break;
      case 71:
        len = sizeof(lG);//определяем длину массива
        PMRead(lG, len);
        break;
      case 72:
        len = sizeof(lH);//определяем длину массива
        PMRead(lH, len);
        break;
      case 73:
        len = sizeof(lI);//определяем длину массива
        PMRead(lI, len);
        break;
      case 74:
        len = sizeof(lJ);//определяем длину массива
        PMRead(lJ, len);
        break;
      case 75:
        len = sizeof(lK);//определяем длину массива
        PMRead(lK, len);
        break;
      case 76:
        len = sizeof(lL);//определяем длину массива
        PMRead(lL, len);
        break;
      case 77:
        len = sizeof(lM);//определяем длину массива
        PMRead(lM, len);
        break;
      case 78:
        len = sizeof(lN);//определяем длину массива
        PMRead(lN, len);
        break;
      case 79:
        len = sizeof(lO);//определяем длину массива
        PMRead(lO, len);
        break;
      case 80:
        len = sizeof(lP);//определяем длину массива
        PMRead(lP, len);
        break;
      case 81:
        len = sizeof(lQ);//определяем длину массива
        PMRead(lQ, len);
        break;
      case 82:
        len = sizeof(lR);//определяем длину массива
        PMRead(lR, len);
        break;
      case 83:
        len = sizeof(lS);//определяем длину массива
        PMRead(lS, len);
        break;
      case 84:
        len = sizeof(lT);//определяем длину массива
        PMRead(lT, len);
        break;
      case 85:
        len = sizeof(lU);//определяем длину массива
        PMRead(lU, len);
        break;
      case 86:
        len = sizeof(lV);//определяем длину массива
        PMRead(lV, len);
        break;
      case 87:
        len = sizeof(lW);//определяем длину массива
        PMRead(lW, len);
        break;
      case 88:
        len = sizeof(lX);//определяем длину массива
        PMRead(lX, len);
        break;
      case 89:
        len = sizeof(lY);//определяем длину массива
        PMRead(lY, len);
        break;
      case 90:
        len = sizeof(lZ);//определяем длину массива
        PMRead(lZ, len);
        break;
      case 97:
        len = sizeof(la);//определяем длину массива
        PMRead(la, len);
        break;
      case 98:
        len = sizeof(lb);//определяем длину массива
        PMRead(lb, len);
        break;
      case 99:
        len = sizeof(lc);
        PMRead(lc, len);
        break;
      case 100:
        len = sizeof(ld);
        PMRead(ld, len);
        break;
      case 101:
        len = sizeof(le);
        PMRead(le, len);
        break;
      case 102:
        len = sizeof(lf);
        PMRead(lf, len);
        break;
      case 103:
        len = sizeof(lg);
        PMRead(lg, len);
        break;
      case 104:
        len = sizeof(lh);
        PMRead(lh, len);
        break;
      default://если нет символа для вывода ставим пробел
        len = sizeof(space);//определяем длину массива
        PMRead(space, len);
        break;
    }
    symN = symN + 1;
  }
}

void setCursorVF(byte x, byte y){
  cx=x;
  cy=y;
}

Надо все это дело в отдельную библиотеку завернуть чтобы пользоватся проще было

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Попробовал написать растеризатор векторных шрифтов.

//#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//#include <avr/pgmspace.h>

//SVG Команды
#define M 10 //стартовая точка
#define L 20 //линия
#define Q 30 //кривая 3 порядка
#define C 40 //кривая 4 порядка
#define S 50 //кривая S типа
#define V 60 //вертикальная линия
#define z 100 //замкнуть контур со стартовой точкой
#define Z 100 //замкнуть контур со стартовой точкой
//добавить фигуры (круг, прямоугольник элипс и т.п.
//void setCursorVF(byte, byte);
//void printVF(char);
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
byte st = 0; //шаги по массиву
//позиция курсора
//byte cx = 0;
//byte cy = 0;
//масштаб
double m = 1; //минимально читаемый 0.4
//буфер растеризатора
#define cel 11
boolean buf[cel][cel];

uint8_t BigB[] = { M, 0, 10, L, 0, 3, L, 3, 0, L, 10, 0, L, 10, 10, L, 7, 10, L, 7, 3, L, 3, 3, L, 3, 10, Z, 0};
//drawCurve3p();
void line_DDA();
void setup()   {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  delay(5);
}

void loop() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 30);
  //byte h = 10, w = 10;
  //стереть буфер
  for (byte x = 0; x < cel; x++) {
    for (byte y = 0; y < cel; y++) {
      buf[x][y] = 0;
    }
  }
  display.println("clear bufer");
  display.display();
  delay(250);
 // unsigned long startTime = millis();
  drawVector(BigB, 0, 0, 1); //построение векторного изображения в буфере buf 10х10
  display.println("draw in bufer");
  display.display();
  delay(1000);
  //вывод на дисплей из буфера
 for (byte x = 0; x < cel; x++) {
    for (byte y = 0; y < cel; y++) {
      if (buf[x][y] == 1) {
        display.drawPixel(x, y, WHITE);
      }
    }
  }
  display.println("print no fill");
  display.display();
  delay(3000);

  fill(5, 1);
  for (byte x = 0; x < cel; x++) {
    for (byte y = 0; y < cel; y++) {
      if (buf[x][y] == 1) {
        display.drawPixel(x * m, y * m, WHITE);
      }
    }
  }
  display.println("print fill");
  display.display();
  delay(3000);


  //вывод на экран времени затраченного на прорисовку
 /* unsigned long totalTime = millis() - startTime;
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(100, 0);
  display.println(totalTime);
  display.display();

  delay(3000);
  display.clearDisplay();
  display.setCursor(0, 0);*/
}

void fill (byte x, byte y) {//заливка
  if (x >= 0 && x < cel && y >= 0 && y < cel && buf[x][y] != 1) {
    buf[x][y] = 1;
    fill (x + 1, y);
    fill (x - 1, y);
    fill (x, y + 1);
    fill (x, y - 1);
  }
}

//прямая по Безье
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
 uint16_t color) {
   float x=0;
   while (x<1) {
   setPixel(((1-x)*x0) + (x*x1)  , ((1-x)*y0) + (x*y1));//P = (1-t)P1 + tP2
   x+=0.1;
   }
 }
 
void setPixel(byte x, byte y){
  buf[x][y]=1;
}

//векторизатор
void drawVector(uint8_t vector[], byte x, byte y, double m) {
  byte interval = 13;
  byte startPoint[2];//начальная точка линии
  //строим картинку по массиву
  while (vector[st] != 0) { //пока массив не закончился
    if (vector[st] == 10) { //SVG M
      //запоминаем точку начала кривой для замыкания контура
      startPoint[0] = (vector[st + 1] + x); //координата Х
      startPoint[1] = (vector[st + 2] + y); //координата У
      st = st + 3; //переходим к след команде
    }
    if (vector[st] == 20) { //SVG L если прямая
      drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m,WHITE);
      st = st + 3;
    }
   /* if (vector[st] == 30) { //SVG Q кривая 3 порядка НЕ ПРОВЕРЯЛ
      drawCurve3p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, WHITE);
      st = st + 5;
    }*/
    /*if (vector[st] == 40) { //SVG C кривая 4 порядка
      drawCurve4p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, (vector[st + 5] + x)*m, (vector[st + 6] + y)*m, WHITE);
      st = st + 7;
    }*/
    /*if (vector[st] == 50) { //SVG S ПОКА НЕ РАБОТАЕТ необходимо добавить
      //вычисление зеркальной опорной точки
      //display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
      drawCurve4p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, vector[st - 4]*m, ((vector[st - 3]*m) + ((vector[st - 1] + y)*m)), (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, WHITE);
      st = st + 5;
    }*/
    /*if (vector[st] == 60) { //SVG V если прямая
      drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st - 2] + x)*m, (vector[st + 2] + y)*m, WHITE);
      st = st + 3;
    }*/


    if (vector[st] == 100) { //SVG z замкнуть контур
      drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, startPoint[0]*m, startPoint[1]*m, WHITE);
      st = st + 1;
    }
    //раскоментировать для просмотра прорисовки
     // display.display();
      //delay(50);
  }
  st = 0; //сброс шагов обхода массива
 // cx = cx + interval;
}

В итоге буфер под символ жрет память, вывод на дисплей символа 10х10 точек с заливкой занимает примерно 9-10 мс.

Инфу брал тут.

Logik
Offline
Зарегистрирован: 05.08.2014

Дошли руки, потестил с экраном SH1106, походу правил т.к. ребутилось. На таком скетче отрисовует за 15-17мсек.  Очень симпатично выходит. Жаль времени нет с безобразным свичем разделатся. Есть еще идеи по сжатию, но позже.

#include <SPI.h>
#include <Wire.h>
#include <avr/pgmspace.h>
#include <itoa.h>

#include "SH1106.h"
#define OLED_SCL_PIN 5
#define OLED_SDA_PIN 6
#define OLED_VCC_PIN 3
#define OLED_GND_PIN 4


ssd1306_i2c(OLED_SCL_PIN, OLED_SDA_PIN, myOLED) ;

//SVG Команды
#define M 10 //стартовая точка
#define L 20 //линия
#define Q 30 //кривая 3 порядка
#define C 40 //кривая 4 порядка
#define S 50 //кривая S типа
#define V 60 //вертикальная линия
#define z 100 //замкнуть контур со стартовой точкой
#define Z 100 //замкнуть контур со стартовой точкой
//добавить фигуры (круг, прямоугольник элипс и т.п.
void setCursorVF(byte, byte);
void printVF(char);


byte st = 0; //шаги по массиву
//позиция курсора
byte cx = 0;
byte cy = 0;
//масштаб
double m = 1; //минимально читаемый 0.4
const PROGMEM uint8_t space[]  = {
  0
};
const PROGMEM uint8_t d1[]  = {
  M, 8, 16, L, 8, 0, L, 0, 5, 0
};
const PROGMEM uint8_t d2[]  = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 2, 8, L, 0, 10, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t d3[]  = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, M, 2, 8, L, 6, 8, 0
};
const PROGMEM uint8_t d4[] = {
  M, 0, 0, L, 0, 6, L, 2, 8, L, 8, 8, M, 8, 0, L, 8, 16, 0
};
const PROGMEM uint8_t d5[] = {
  M, 8, 0, L, 0, 0, L, 0, 8, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t d6[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 10, L, 8, 8, L, 0, 8, 0
};
const PROGMEM uint8_t d7[] = {
  M, 0, 0, L, 8, 0, L, 8, 4, L, 0, 16, 0
};
const PROGMEM uint8_t d8[] = {
  M, 2, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, L, 0, 10, L, 2, 8, L, 0, 6, L, 0, 2, Z, M, 2, 8, L, 6, 8, 0
};
const PROGMEM uint8_t d9[] = {
  M, 8, 8, L, 2, 8, L, 0, 6, L, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM uint8_t d0[] = {
  M, 0, 6, L, 2, 0, L, 6, 0, L, 8, 6, L, 8, 10, L, 6, 16, L, 2, 16, L, 0, 10, Z, 0
};
const PROGMEM uint8_t dot[] = {
  M, 6, 16, L, 6, 15, L, 4, 15, L, 4, 16, Z, 0
};
const PROGMEM uint8_t dDot[] = {
  M, 6, 16, L, 6, 15, L, 4, 15, L, 4, 16, L, 6, 16, Z, M, 6, 5, L, 6, 2, L, 4, 2, L, 4, 5, Z, 0
};
const PROGMEM uint8_t minus[] = {
  M, 0, 10, L, 8, 10, 0
};
const PROGMEM uint8_t lA[] = {
  M, 0, 16, L, 4, 0, L, 8, 16, M, 2, 11, L, 6, 11, 0
};
const PROGMEM uint8_t lB[] = {
  M, 0, 8, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, L, 0, 8, L, 8, 8, 0
};
const PROGMEM uint8_t lC[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, 0
};
const PROGMEM uint8_t lD[] = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 0, 16, Z, 0
};
const PROGMEM uint8_t lE[] = {
  M, 8, 0, L, 0, 0, L, 0, 16, L, 8, 16, M, 0, 8, L, 6, 8, 0
};
const PROGMEM uint8_t lF[] = {
  M, 8, 0, L, 0, 0, L, 0, 16, M, 0, 8, L, 6, 8, 0
};
const PROGMEM uint8_t lG[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 8, L, 5, 8, 0
};
const PROGMEM uint8_t lH[] = {
  M, 0, 0, L, 0, 16, M, 8, 0, L, 8, 16, M, 0, 8, L, 8, 8, 0
};
const PROGMEM uint8_t lI[] = {
  M, 0, 0, L, 8, 0, M, 4, 0, L, 4, 16, M, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t lJ[] = {
  M, 0, 0, L, 8, 0, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM uint8_t lK[] = {
  M, 0, 0, L, 0, 16, M, 8, 0, L, 0, 8, L, 8, 16, 0
};
const PROGMEM uint8_t lL[] = {
  M, 0, 0, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t lM[] = {
  M, 0, 16, L, 0, 0, L, 4, 10, L, 8, 0, L, 8, 16, 0
};
const PROGMEM uint8_t lN[] = {
  M, 0, 16, L, 0, 0, L, 8, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lO[] = {
  M, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, 0
};
const PROGMEM uint8_t lP[] = {
  M, 0, 16, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 0, 8, 0
};
const PROGMEM uint8_t lQ[] = {
  M, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, M, 4, 14, L, 8, 16, 0
};
const PROGMEM uint8_t lR[] = {
  M, 0, 16, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 0, 8, M, 4, 8, L, 8, 16, 0
};
const PROGMEM uint8_t lS[] = {
  M, 8, 0, L, 2, 0, L, 0, 2, L, 0, 6, L, 2, 8, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t lT[] = {
  M, 0, 0, L, 8, 0, M, 4, 0, L, 4, 16, 0
};
const PROGMEM uint8_t lU[] = {
  M, 0, 0, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 0, 0
};
const PROGMEM uint8_t lV[] = {
  M, 0, 0, L, 4, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lW[] = {
  M, 0, 0, L, 2, 16, L, 4, 6, L, 6, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lX[] = {
  M, 0, 0, L, 8, 16, M, 8, 0, L, 0, 16, 0
};
const PROGMEM uint8_t lY[] = {
  M, 0, 0, L, 4, 8, L, 4, 16, M, 4, 8, L, 8, 0, 0
};
const PROGMEM uint8_t lZ[] = {
  M, 0, 0, L, 8, 0, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t la[] = {
  M, 2, 6, L, 6, 6, L, 8, 8, L, 8, 16, L, 2, 16, L, 0, 14, L, 0, 12, L, 2, 10, L, 8, 10, 0
};
const PROGMEM uint8_t lb[] = {
  M, 0, 0, L, 0, 16, L, 6, 16, L, 8, 14, L, 8, 10, L, 6, 6, L, 0, 6, 0
};
const PROGMEM uint8_t lc[] = {
  M, 8, 6, L, 2, 6, L, 0, 8, L, 0, 14, L, 2, 16, L, 8, 16, 0
};
const PROGMEM uint8_t ld[] = {
  M, 8, 0, L, 8, 16, L, 2, 16, L, 0, 14, L, 0, 8, L, 2, 6, L, 8, 6, 0
};
const PROGMEM uint8_t le[] = {
  M, 8, 16, L, 2, 16, L, 0, 14, L, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, L, 8, 12, L, 0, 12, 0
};
const PROGMEM uint8_t lf[] = {
  M, 0, 10, L, 6, 10, M, 2, 16, L, 2, 2, L, 4, 0, L, 6, 0, L, 8, 2, 0
};
const PROGMEM uint8_t lg[] = {
  M, 8, 12, L, 2, 12, L, 0, 10, L, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t lh[] = {
  M, 0, 0, L, 0, 16, M, 0, 6, L, 6, 6, L, 8, 8, L, 8, 16, 0
};
void setup()   {
  pinMode(OLED_GND_PIN, OUTPUT);
  digitalWrite(OLED_GND_PIN, LOW);
  pinMode(OLED_VCC_PIN, OUTPUT);
  digitalWrite(OLED_VCC_PIN, HIGH);
  delay(1);
  myOLED.begin();
  myOLED.clrScr();
  myOLED.setFont( SSD1306::FONT_SIZE_1); 
  myOLED.drawString(2,5,"FontVect");
  delay(500);
  
  Serial.begin(57600);

}

void loop() {
  char c[12];
  uint8_t bufg[128*4];
  myOLED.clrScr();

  int n = analogRead(0);
  setCursorVF(0, 0);
  //drawVector(BigB,0,0,1);
    myOLED.InitFrame(0,2,128,4, myOLED.FRAME_MODE_BUFER, bufg);

  unsigned long startTime = millis();
    memset(bufg, 0, sizeof(bufg));

  printVF("Adc: ");
  //вывод INT
   printVF(n);
  //вывод текста
 // setCursorVF(0, 20);
 // printVF("defgh:-15.4");
  //вывод на экран времени затраченного на прорисовку
  

  myOLED.update();

  unsigned long totalTime = millis() - startTime;
  myOLED.setFont( SSD1306::FONT_SIZE_1);
  ltoa(totalTime,c,10);
  myOLED.drawString(2,6,c);  
  delay(25);
  myOLED.clrScr();
}

void PMRead(const byte x[], int l ) {
  byte len = l;//принимаем длину массива
  byte bufer[l+1];//создаем буфер для чтения массива из PROGMEM
  byte b, k;//переменные
 
  for (k = 0; k < len; k++)
  {
    b =  pgm_read_byte_near(x + k);//читаем из PROGMEM
    bufer[k] = b;//заносим в буфер
  }
  bufer[k]=0;
  
  drawVector(bufer, cx, cy, m);//выводим на экран из буфера
}

void drawVector(uint8_t vector[], byte x, byte y, double m) {
  byte interval = 13;
  byte startPoint[2];//начальная точка линии
  
///  Serial.print(st);Serial.print("  ");
//  Serial.print(vector[st]);Serial.print("  ");
//  Serial.print(x);Serial.print("  ");   Serial.println(y);
  
  //double
  //m=1.0;//масштаб от 0 к 1
  //  double angle=0;//угол поворота
  //  angle=angle*(PI/180);//перевод угла в радианы

  //строим картинку по массиву
  while (vector[st] != 0) { //пока массив не закончился
   if (vector[st] == 10) { //SVG M
      //запоминаем точку начала кривой для замыкания контура
      startPoint[0] = (vector[st + 1] + x); //координата Х
      startPoint[1] = (vector[st + 2] + y); //координата У
      st = st + 3; //переходим к след команде
    }
    else if (vector[st] == 20) { //SVG L если прямая
  //    display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, WHITE);
 myOLED.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m);
 st = st + 3;
    }
    else if (vector[st] == 30) { //SVG Q кривая 3 порядка НЕ ПРОВЕРЯЛ
  //    display.drawCurve3p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, WHITE);
      st = st + 5;
    }
    else if (vector[st] == 40) { //SVG C кривая 4 порядка
  //    display.drawCurve4p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, (vector[st + 5] + x)*m, (vector[st + 6] + y)*m, WHITE);
      st = st + 7;
    }
    else if (vector[st] == 50) { //SVG S ПОКА НЕ РАБОТАЕТ необходимо добавить
      //вычисление зеркальной опорной точки
      //display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
   //   display.drawCurve4p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, vector[st - 4]*m, ((vector[st - 3]*m) + ((vector[st - 1] + y)*m)), (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, WHITE);
      st = st + 5;
    }
    else if (vector[st] == 60) { //SVG V если прямая
   //   display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st - 2] + x)*m, (vector[st + 2] + y)*m, WHITE);
      st = st + 3;
    }


    else if (vector[st] == 100) { //SVG z замкнуть контур
     // display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, startPoint[0]*m, startPoint[1]*m, WHITE);
      st = st + 1;
    }
    //раскоментировать для просмотра прорисовки
 //     display.display();
 //     delay(50);
  }
    Serial.println("end");
  st = 0; //сброс шагов обхода массива
  cx = cx + interval;
}


// Функция преобразования числа в строку
void printVF(int n)
{
  char buffer [12];
  itoa (n, buffer, 10);
  printVF(buffer);
}

void printVF(double n)
{
  char buffer [12];
  int a; //числитель
  int b; //знаменатель
  //округляем
  int c = n * 100;
  //получаем числитель
  a = (c / 100) % 1000;
  itoa (a, buffer, 10);
  printVF(buffer);
  printVF(".");
  //получем знаменатель
  b = abs(c % 100);
  itoa (b, buffer, 10);
  printVF(buffer);
}

// Функция преобразования числа в строку
void printVF(unsigned int n)
{
  char buffer [12];
  itoa (n, buffer, 10);
  printVF(buffer);
}

//вывод текста
void printVF(char txt[]) {
  byte len;
  byte symN = 0;
  
    myOLED.drawString(0,0,txt);  


  while (txt[symN] != '\0') {
    char sym;//для хранения символа
    sym = txt[symN];
    sym = sym - 0;
    switch (sym) {
      case 32:
        len = sizeof(space);//определяем длину массива
        PMRead(space, len);
        break;
      case 45:
        len = sizeof(minus);//определяем длину массива
        PMRead(minus, len);
        break;
      case 46:
        len = sizeof(dot);//определяем длину массива
        PMRead(dot, len);
        break;
      case 48:
        len = sizeof(d0);//определяем длину массива
        PMRead(d0, len);
        break;
      case 49:
        len = sizeof(d1);//определяем длину массива
        PMRead(d1, len);
        break;
      case 50:
        len = sizeof(d2);//определяем длину массива
        PMRead(d2, len);
        break;
      case 51:
        len = sizeof(d3);//определяем длину массива
        PMRead(d3, len);
        break;
      case 52:
        len = sizeof(d4);//определяем длину массива
        PMRead(d4, len);
        break;
      case 53:
        len = sizeof(d5);//определяем длину массива
        PMRead(d5, len);
        break;
      case 54:
        len = sizeof(d6);//определяем длину массива
        PMRead(d6, len);
        break;
      case 55:
        len = sizeof(d7);//определяем длину массива
        PMRead(d7, len);
        break;
      case 56:
        len = sizeof(d8);//определяем длину массива
        PMRead(d8, len);
        break;
      case 57:
        len = sizeof(d9);//определяем длину массива
        PMRead(d9, len);
        break;
      case 58:
        len = sizeof(dDot);//определяем длину массива
        PMRead(dDot, len);
        break;
      case 65://A65
        len = sizeof(lA);//определяем длину массива
        PMRead(lA, len);
        break;
      case 66://B
        len = sizeof(lB);//определяем длину массива
        PMRead(lB, len);
        break;
      case 67://C
        len = sizeof(lC);//определяем длину массива
        PMRead(lC, len);
        break;
      case 68:
        len = sizeof(lD);//определяем длину массива
        PMRead(lD, len);
        break;
      case 69:
        len = sizeof(lE);//определяем длину массива
        PMRead(lE, len);
        break;
      case 70:
        len = sizeof(lF);//определяем длину массива
        PMRead(lF, len);
        break;
      case 71:
        len = sizeof(lG);//определяем длину массива
        PMRead(lG, len);
        break;
      case 72:
        len = sizeof(lH);//определяем длину массива
        PMRead(lH, len);
        break;
      case 73:
        len = sizeof(lI);//определяем длину массива
        PMRead(lI, len);
        break;
      case 74:
        len = sizeof(lJ);//определяем длину массива
        PMRead(lJ, len);
        break;
      case 75:
        len = sizeof(lK);//определяем длину массива
        PMRead(lK, len);
        break;
      case 76:
        len = sizeof(lL);//определяем длину массива
        PMRead(lL, len);
        break;
      case 77:
        len = sizeof(lM);//определяем длину массива
        PMRead(lM, len);
        break;
      case 78:
        len = sizeof(lN);//определяем длину массива
        PMRead(lN, len);
        break;
      case 79:
        len = sizeof(lO);//определяем длину массива
        PMRead(lO, len);
        break;
      case 80:
        len = sizeof(lP);//определяем длину массива
        PMRead(lP, len);
        break;
      case 81:
        len = sizeof(lQ);//определяем длину массива
        PMRead(lQ, len);
        break;
      case 82:
        len = sizeof(lR);//определяем длину массива
        PMRead(lR, len);
        break;
      case 83:
        len = sizeof(lS);//определяем длину массива
        PMRead(lS, len);
        break;
      case 84:
        len = sizeof(lT);//определяем длину массива
        PMRead(lT, len);
        break;
      case 85:
        len = sizeof(lU);//определяем длину массива
        PMRead(lU, len);
        break;
      case 86:
        len = sizeof(lV);//определяем длину массива
        PMRead(lV, len);
        break;
      case 87:
        len = sizeof(lW);//определяем длину массива
        PMRead(lW, len);
        break;
      case 88:
        len = sizeof(lX);//определяем длину массива
        PMRead(lX, len);
        break;
      case 89:
        len = sizeof(lY);//определяем длину массива
        PMRead(lY, len);
        break;
      case 90:
        len = sizeof(lZ);//определяем длину массива
        PMRead(lZ, len);
        break;
      case 97:
        len = sizeof(la);//определяем длину массива
        PMRead(la, len);
        break;
      case 98:
        len = sizeof(lb);//определяем длину массива
        PMRead(lb, len);
        break;
      case 99:
        len = sizeof(lc);
        PMRead(lc, len);
        break;
      case 100:
        len = sizeof(ld);
        PMRead(ld, len);
        break;
      case 101:
        len = sizeof(le);
        PMRead(le, len);
        break;
      case 102:
        len = sizeof(lf);
        PMRead(lf, len);
        break;
      case 103:
        len = sizeof(lg);
        PMRead(lg, len);
        break;
      case 104:
        len = sizeof(lh);
        PMRead(lh, len);
        break;
      default://если нет символа для вывода ставим пробел
        len = sizeof(space);//определяем длину массива
        PMRead(space, len);
        break;
    }
    symN = symN + 1;
  }
}

void setCursorVF(byte x, byte y){
  cx=x;
  cy=y;
}

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Только закончил весь латинский

//векторное описание символов
const PROGMEM uint8_t space[]  = {
  0
};
const PROGMEM uint8_t d1[]  = {
  M, 8, 16, L, 8, 0, L, 0, 5, 0
};
const PROGMEM uint8_t d2[]  = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 2, 8, L, 0, 10, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t d3[]  = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, M, 2, 8, L, 6, 8, 0
};
const PROGMEM uint8_t d4[] = {
  M, 0, 0, L, 0, 6, L, 2, 8, L, 8, 8, M, 8, 0, L, 8, 16, 0
};
const PROGMEM uint8_t d5[] = {
  M, 8, 0, L, 0, 0, L, 0, 8, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t d6[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 12, L, 8, 8, L, 0, 8, 0
};
const PROGMEM uint8_t d7[] = {
  M, 0, 0, L, 8, 0, L, 8, 4, L, 0, 16, 0
};
const PROGMEM uint8_t d8[] = {
  M, 2, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, L, 0, 10, L, 2, 8, L, 0, 6, L, 0, 2, Z, M, 2, 8, L, 6, 8, 0
};
const PROGMEM uint8_t d9[] = {
  M, 8, 8, L, 2, 8, L, 0, 6, L, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM uint8_t d0[] = {
  M, 0, 6, L, 2, 0, L, 6, 0, L, 8, 6, L, 8, 10, L, 6, 16, L, 2, 16, L, 0, 10, Z, 0
};
const PROGMEM uint8_t dot[] = {
  M, 4, 16, L, 4, 16, 0
};
const PROGMEM uint8_t dDot[] = {
  M, 4, 12, L, 4, 12, M, 4, 2, L, 4, 2, 0
};
const PROGMEM uint8_t minus[] = {
  M, 0, 10, L, 8, 10, 0
};
const PROGMEM uint8_t lA[] = {
  M, 0, 16, L, 4, 0, L, 8, 16, M, 2, 11, L, 6, 11, 0
};
const PROGMEM uint8_t lB[] = {
  M, 0, 8, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, L, 0, 8, L, 8, 8, 0
};
const PROGMEM uint8_t lC[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, 0
};
const PROGMEM uint8_t lD[] = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 0, 16, Z, 0
};
const PROGMEM uint8_t lE[] = {
  M, 8, 0, L, 0, 0, L, 0, 16, L, 8, 16, M, 0, 8, L, 6, 8, 0
};
const PROGMEM uint8_t lF[] = {
  M, 8, 0, L, 0, 0, L, 0, 16, M, 0, 8, L, 6, 8, 0
};
const PROGMEM uint8_t lG[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 8, L, 5, 8, 0
};
const PROGMEM uint8_t lH[] = {
  M, 0, 0, L, 0, 16, M, 8, 0, L, 8, 16, M, 0, 8, L, 8, 8, 0
};
const PROGMEM uint8_t lI[] = {
  M, 0, 0, L, 8, 0, M, 4, 0, L, 4, 16, M, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t lJ[] = {
  M, 0, 0, L, 8, 0, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM uint8_t lK[] = {
  M, 0, 0, L, 0, 16, M, 8, 0, L, 0, 8, L, 8, 16, 0
};
const PROGMEM uint8_t lL[] = {
  M, 0, 0, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t lM[] = {
  M, 0, 16, L, 0, 0, L, 4, 10, L, 8, 0, L, 8, 16, 0
};
const PROGMEM uint8_t lN[] = {
  M, 0, 16, L, 0, 0, L, 8, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lO[] = {
  M, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, 0
};
const PROGMEM uint8_t lP[] = {
  M, 0, 16, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 0, 8, 0
};
const PROGMEM uint8_t lQ[] = {
  M, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, M, 4, 14, L, 8, 16, 0
};
const PROGMEM uint8_t lR[] = {
  M, 0, 16, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 0, 8, M, 4, 8, L, 8, 16, 0
};
const PROGMEM uint8_t lS[] = {
  M, 8, 0, L, 2, 0, L, 0, 2, L, 0, 6, L, 2, 8, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t lT[] = {
  M, 0, 0, L, 8, 0, M, 4, 0, L, 4, 16, 0
};
const PROGMEM uint8_t lU[] = {
  M, 0, 0, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 0, 0
};
const PROGMEM uint8_t lV[] = {
  M, 0, 0, L, 4, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lW[] = {
  M, 0, 0, L, 2, 16, L, 4, 6, L, 6, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lX[] = {
  M, 0, 0, L, 8, 16, M, 8, 0, L, 0, 16, 0
};
const PROGMEM uint8_t lY[] = {
  M, 0, 0, L, 4, 8, L, 4, 16, M, 4, 8, L, 8, 0, 0
};
const PROGMEM uint8_t lZ[] = {
  M, 0, 0, L, 8, 0, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t la[] = {
  M, 2, 6, L, 6, 6, L, 8, 8, L, 8, 16, L, 2, 16, L, 0, 14, L, 0, 12, L, 2, 10, L, 8, 10, 0
};
const PROGMEM uint8_t lb[] = {
  M, 0, 0, L, 0, 16, L, 6, 16, L, 8, 14, L, 8, 10, L, 6, 6, L, 0, 6, 0
};
const PROGMEM uint8_t lc[] = {
  M, 8, 6, L, 2, 6, L, 0, 8, L, 0, 14, L, 2, 16, L, 8, 16, 0
};
const PROGMEM uint8_t ld[] = {
  M, 8, 0, L, 8, 16, L, 2, 16, L, 0, 14, L, 0, 8, L, 2, 6, L, 8, 6, 0
};
const PROGMEM uint8_t le[] = {
  M, 8, 16, L, 2, 16, L, 0, 14, L, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, L, 8, 12, L, 0, 12, 0
};
const PROGMEM uint8_t lf[] = {
  M, 0, 10, L, 6, 10, M, 2, 16, L, 2, 2, L, 4, 0, L, 6, 0, L, 8, 2, 0
};
const PROGMEM uint8_t lg[] = {
  M, 8, 13, L, 2, 13, L, 0, 12, L, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t lh[] = {
  M, 0, 0, L, 0, 16, M, 0, 6, L, 6, 6, L, 8, 8, L, 8, 16, 0
};
const PROGMEM uint8_t li[] = {
  M, 4, 5, L, 4, 16, M, 4, 1, L, 4, 1, 0
};
const PROGMEM uint8_t lj[] = {
  M, 4, 5, L, 4, 14, L, 2, 16, L, 0, 16, M, 4, 1, L, 4, 1, 0
};
const PROGMEM uint8_t lk[] = {
  M, 0, 0, L, 0, 16, M, 0, 10, L, 6, 6, M, 3, 9, L, 8, 16, 0
};
const PROGMEM uint8_t ll[] = {
  M, 4, 0, L, 4, 16, 0
};
const PROGMEM uint8_t lm[] = {
  M, 0, 16, L, 0, 6, L, 6, 6, L, 8, 8, L, 8, 16, M, 4, 6, L, 4, 16, 0
};
const PROGMEM uint8_t ln[] = {
  M, 0, 16, L, 0, 6, L, 6, 6, L, 8, 8, L, 8, 16, 0
};
const PROGMEM uint8_t lo[] = {
  M, 0, 7, L, 2, 6, L, 6, 6, L, 8, 8, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, 0
};
const PROGMEM uint8_t lp[] = {
  M, 0, 16, L, 0, 6, L, 6, 6, L, 8, 8, L, 8, 10, L, 6, 12, L, 0, 12, 0
};
const PROGMEM uint8_t lq[] = {
  M, 8, 6, L, 8, 16, M, 8, 10, L, 6, 12, L, 2, 12, L, 0, 10, L, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, 0
};
const PROGMEM uint8_t lr[] = {
  M, 0, 6, L, 0, 16, M, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, 0
};
const PROGMEM uint8_t ls[] = {
  M, 8, 8, L, 6, 6, L, 2, 6, L, 0, 8, L, 0, 9, L, 2, 11, L, 6, 11, L, 8, 13, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM uint8_t lt[] = {
  M, 2, 0, L, 2, 14, L, 4, 16, L, 6, 16, L, 8, 14, M, 0, 6, L, 6, 6, 0
};
const PROGMEM uint8_t lu[] = {
  M, 0, 6, L, 0, 14, L, 2, 16, L, 8, 16, L, 8, 6, 0
};
const PROGMEM uint8_t lv[] = {
  M, 0, 6, L, 4, 16, L, 8, 6, 0
};
const PROGMEM uint8_t lw[] = {
  M, 0, 6, L, 2, 16, L, 4, 10, L, 6, 16, L, 8, 6, 0
};
const PROGMEM uint8_t lx[] = {
  M, 0, 6, L, 8, 16, M, 8, 6, L, 0, 16, 0
};
const PROGMEM uint8_t ly[] = {
  M, 0, 6, L, 0, 10, L, 2, 12, L, 8, 12, M, 8, 6, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t lz[] = {
  M, 0, 6, L, 8, 6, L, 0, 16, L, 8, 16, 0
};

и switch дополнил

//вывод текста
void printVF(char txt[]) {
  byte symN = 0;
  while (txt[symN] != '\0') {
    char sym;//для хранения символа
    sym = txt[symN];
 sym = sym - 0;
    switch (sym) {
      case 32:
        PMRead(space, sizeof(space));
        break;
      case 45:
        PMRead(minus, sizeof(minus));//-
        break;
      case 46:
        PMRead(dot, sizeof(dot));//.
        break;
      case 48:
        PMRead(d0, sizeof(d0));
        break;
      case 49:
        PMRead(d1, sizeof(d1));
        break;
      case 50:
        PMRead(d2, sizeof(d2));
        break;
      case 51:
        PMRead(d3, sizeof(d3));
        break;
      case 52:
        PMRead(d4, sizeof(d4));
        break;
      case 53:
        PMRead(d5, sizeof(d5));
        break;
      case 54:
        PMRead(d6, sizeof(d6));
        break;
      case 55:
        PMRead(d7, sizeof(d7));
        break;
      case 56:
        PMRead(d8, sizeof(d8));
        break;
      case 57:
        PMRead(d9, sizeof(d9));
        break;
      case 58:
        PMRead(dDot, sizeof(dDot));//:
        break;
      case 65://A65
        PMRead(lA, sizeof(lA));
        break;
      case 66://B
        PMRead(lB, sizeof(lB));
        break;
      case 67://C
        PMRead(lC, sizeof(lC));
        break;
      case 68:
        PMRead(lD, sizeof(lD));
        break;
      case 69:
        PMRead(lE, sizeof(lE));
        break;
      case 70:
        PMRead(lF, sizeof(lF));
        break;
      case 71:
        PMRead(lG, sizeof(lG));
        break;
      case 72:
        PMRead(lH, sizeof(lH));
        break;
      case 73:
        PMRead(lI, sizeof(lI));
        break;
      case 74:
        PMRead(lJ, sizeof(lJ));
        break;
      case 75:
        PMRead(lK, sizeof(lK));
        break;
      case 76:
        PMRead(lL, sizeof(lL));
        break;
      case 77:
        PMRead(lM, sizeof(lM));
        break;
      case 78:
        PMRead(lN, sizeof(lN));
        break;
      case 79:
        PMRead(lO, sizeof(lO));
        break;
      case 80:
        PMRead(lP, sizeof(lP));
        break;
      case 81:
        PMRead(lQ, sizeof(lQ));
        break;
      case 82:
        PMRead(lR, sizeof(lR));
        break;
      case 83:
        PMRead(lS, sizeof(lS));
        break;
      case 84:
        PMRead(lT, sizeof(lT));
        break;
      case 85:
        PMRead(lU, sizeof(lU));
        break;
      case 86:
        PMRead(lV, sizeof(lV));
        break;
      case 87:
        PMRead(lW, sizeof(lW));
        break;
      case 88:
        PMRead(lX, sizeof(lX));
        break;
      case 89:
        PMRead(lY, sizeof(lY));
        break;
      case 90:
        PMRead(lZ, sizeof(lZ));
        break;
      case 97:
        PMRead(la, sizeof(la));
        break;
      case 98:
        PMRead(lb, sizeof(lb));
        break;
      case 99:
        PMRead(lc, sizeof(lc));
        break;
      case 100:
        PMRead(ld, sizeof(ld));
        break;
      case 101:
        PMRead(le, sizeof(le));
        break;
      case 102:
        PMRead(lf, sizeof(lf));
        break;
      case 103:
        PMRead(lg, sizeof(lg));
        break;
      case 104:
        PMRead(lh, sizeof(lh));
        break;
      case 105:
        PMRead(li, sizeof(li));
        break;
      case 106:
        PMRead(lj, sizeof(lj));
        break;
      case 107:
        PMRead(lk, sizeof(lk));
        break;
      case 108:
        PMRead(ll, sizeof(ll));
        break;
      case 109:
        PMRead(lm, sizeof(lm));
        break;
      case 110:
        PMRead(ln, sizeof(ln));
        break;
      case 111:
        PMRead(lo, sizeof(lo));
        break;
      case 112:
        PMRead(lp, sizeof(lp));
        break;
      case 113:
        PMRead(lq, sizeof(lq));
        break;
      case 114:
        PMRead(lr, sizeof(lr));
        break;
      case 115:
        PMRead(ls, sizeof(ls));
        break;
      case 116:
        PMRead(lt, sizeof(lt));
        break;
      case 117:
        PMRead(lu, sizeof(lu));
        break;
      case 118:
        PMRead(lv, sizeof(lv));
        break;
      case 119:
        PMRead(lw, sizeof(lw));
        break;
      case 120:
        PMRead(lx, sizeof(lx));
        break;
      case 121:
        PMRead(ly, sizeof(ly));
        break;
      case 122:
        PMRead(lz, sizeof(lz));
        break;
      default://если нет символа для вывода ставим пробел
        PMRead(space, sizeof(space));
        break;
    }
    symN = symN + 1;//переходим к следующему символу
  }
}

Еще сделал переход на новую строку если текст не лэзет и переход на новую строку после вывода аналог println в конце DrawVector добавил

  if (cx>(128/m)-16){
    nl();
  }

//переход на след строку
void nl() {
  cx = 0;
  cy = cy + 21;
}

Весь код

//#include <SPI.h>
//#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <avr/pgmspace.h>

//SVG Команды
#define M 10 //стартовая точка
#define L 20 //линия
#define Q 30 //кривая 3 порядка
#define C 40 //кривая 4 порядка
#define S 50 //кривая S типа
#define V 60 //вертикальная линия
#define z 100 //замкнуть контур со стартовой точкой
#define Z 100 //замкнуть контур со стартовой точкой
//добавить фигуры (круг, прямоугольник элипс и т.п.
void setCursorVF(byte, byte);
void printVF(char);
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
byte st = 0; //шаги по массиву
//позиция курсора
byte cx = 0;
byte cy = 0;
//масштаб
double m = 0.5; //минимально читаемый 0.5
//векторное описание символов
const PROGMEM uint8_t space[]  = {
  0
};
const PROGMEM uint8_t d1[]  = {
  M, 8, 16, L, 8, 0, L, 0, 5, 0
};
const PROGMEM uint8_t d2[]  = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 2, 8, L, 0, 10, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t d3[]  = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, M, 2, 8, L, 6, 8, 0
};
const PROGMEM uint8_t d4[] = {
  M, 0, 0, L, 0, 6, L, 2, 8, L, 8, 8, M, 8, 0, L, 8, 16, 0
};
const PROGMEM uint8_t d5[] = {
  M, 8, 0, L, 0, 0, L, 0, 8, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t d6[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 12, L, 8, 8, L, 0, 8, 0
};
const PROGMEM uint8_t d7[] = {
  M, 0, 0, L, 8, 0, L, 8, 4, L, 0, 16, 0
};
const PROGMEM uint8_t d8[] = {
  M, 2, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, L, 0, 10, L, 2, 8, L, 0, 6, L, 0, 2, Z, M, 2, 8, L, 6, 8, 0
};
const PROGMEM uint8_t d9[] = {
  M, 8, 8, L, 2, 8, L, 0, 6, L, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM uint8_t d0[] = {
  M, 0, 6, L, 2, 0, L, 6, 0, L, 8, 6, L, 8, 10, L, 6, 16, L, 2, 16, L, 0, 10, Z, 0
};
const PROGMEM uint8_t dot[] = {
  M, 4, 16, L, 4, 16, 0
};
const PROGMEM uint8_t dDot[] = {
  M, 4, 12, L, 4, 12, M, 4, 2, L, 4, 2, 0
};
const PROGMEM uint8_t minus[] = {
  M, 0, 10, L, 8, 10, 0
};
const PROGMEM uint8_t lA[] = {
  M, 0, 16, L, 4, 0, L, 8, 16, M, 2, 11, L, 6, 11, 0
};
const PROGMEM uint8_t lB[] = {
  M, 0, 8, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, L, 0, 8, L, 8, 8, 0
};
const PROGMEM uint8_t lC[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, 0
};
const PROGMEM uint8_t lD[] = {
  M, 0, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 0, 16, Z, 0
};
const PROGMEM uint8_t lE[] = {
  M, 8, 0, L, 0, 0, L, 0, 16, L, 8, 16, M, 0, 8, L, 6, 8, 0
};
const PROGMEM uint8_t lF[] = {
  M, 8, 0, L, 0, 0, L, 0, 16, M, 0, 8, L, 6, 8, 0
};
const PROGMEM uint8_t lG[] = {
  M, 8, 2, L, 6, 0, L, 2, 0, L, 0, 2, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 8, L, 5, 8, 0
};
const PROGMEM uint8_t lH[] = {
  M, 0, 0, L, 0, 16, M, 8, 0, L, 8, 16, M, 0, 8, L, 8, 8, 0
};
const PROGMEM uint8_t lI[] = {
  M, 0, 0, L, 8, 0, M, 4, 0, L, 4, 16, M, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t lJ[] = {
  M, 0, 0, L, 8, 0, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM uint8_t lK[] = {
  M, 0, 0, L, 0, 16, M, 8, 0, L, 0, 8, L, 8, 16, 0
};
const PROGMEM uint8_t lL[] = {
  M, 0, 0, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t lM[] = {
  M, 0, 16, L, 0, 0, L, 4, 10, L, 8, 0, L, 8, 16, 0
};
const PROGMEM uint8_t lN[] = {
  M, 0, 16, L, 0, 0, L, 8, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lO[] = {
  M, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, 0
};
const PROGMEM uint8_t lP[] = {
  M, 0, 16, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 0, 8, 0
};
const PROGMEM uint8_t lQ[] = {
  M, 0, 2, L, 2, 0, L, 6, 0, L, 8, 2, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, M, 4, 14, L, 8, 16, 0
};
const PROGMEM uint8_t lR[] = {
  M, 0, 16, L, 0, 0, L, 6, 0, L, 8, 2, L, 8, 6, L, 6, 8, L, 0, 8, M, 4, 8, L, 8, 16, 0
};
const PROGMEM uint8_t lS[] = {
  M, 8, 0, L, 2, 0, L, 0, 2, L, 0, 6, L, 2, 8, L, 6, 8, L, 8, 10, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t lT[] = {
  M, 0, 0, L, 8, 0, M, 4, 0, L, 4, 16, 0
};
const PROGMEM uint8_t lU[] = {
  M, 0, 0, L, 0, 14, L, 2, 16, L, 6, 16, L, 8, 14, L, 8, 0, 0
};
const PROGMEM uint8_t lV[] = {
  M, 0, 0, L, 4, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lW[] = {
  M, 0, 0, L, 2, 16, L, 4, 6, L, 6, 16, L, 8, 0, 0
};
const PROGMEM uint8_t lX[] = {
  M, 0, 0, L, 8, 16, M, 8, 0, L, 0, 16, 0
};
const PROGMEM uint8_t lY[] = {
  M, 0, 0, L, 4, 8, L, 4, 16, M, 4, 8, L, 8, 0, 0
};
const PROGMEM uint8_t lZ[] = {
  M, 0, 0, L, 8, 0, L, 0, 16, L, 8, 16, 0
};
const PROGMEM uint8_t la[] = {
  M, 2, 6, L, 6, 6, L, 8, 8, L, 8, 16, L, 2, 16, L, 0, 14, L, 0, 12, L, 2, 10, L, 8, 10, 0
};
const PROGMEM uint8_t lb[] = {
  M, 0, 0, L, 0, 16, L, 6, 16, L, 8, 14, L, 8, 10, L, 6, 6, L, 0, 6, 0
};
const PROGMEM uint8_t lc[] = {
  M, 8, 6, L, 2, 6, L, 0, 8, L, 0, 14, L, 2, 16, L, 8, 16, 0
};
const PROGMEM uint8_t ld[] = {
  M, 8, 0, L, 8, 16, L, 2, 16, L, 0, 14, L, 0, 8, L, 2, 6, L, 8, 6, 0
};
const PROGMEM uint8_t le[] = {
  M, 8, 16, L, 2, 16, L, 0, 14, L, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, L, 8, 12, L, 0, 12, 0
};
const PROGMEM uint8_t lf[] = {
  M, 0, 10, L, 6, 10, M, 2, 16, L, 2, 2, L, 4, 0, L, 6, 0, L, 8, 2, 0
};
const PROGMEM uint8_t lg[] = {
  M, 8, 13, L, 2, 13, L, 0, 12, L, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t lh[] = {
  M, 0, 0, L, 0, 16, M, 0, 6, L, 6, 6, L, 8, 8, L, 8, 16, 0
};
const PROGMEM uint8_t li[] = {
  M, 4, 5, L, 4, 16, M, 4, 1, L, 4, 1, 0
};
const PROGMEM uint8_t lj[] = {
  M, 4, 5, L, 4, 14, L, 2, 16, L, 0, 16, M, 4, 1, L, 4, 1, 0
};
const PROGMEM uint8_t lk[] = {
  M, 0, 0, L, 0, 16, M, 0, 10, L, 6, 6, M, 3, 9, L, 8, 16, 0
};
const PROGMEM uint8_t ll[] = {
  M, 4, 0, L, 4, 16, 0
};
const PROGMEM uint8_t lm[] = {
  M, 0, 16, L, 0, 6, L, 6, 6, L, 8, 8, L, 8, 16, M, 4, 6, L, 4, 16, 0
};
const PROGMEM uint8_t ln[] = {
  M, 0, 16, L, 0, 6, L, 6, 6, L, 8, 8, L, 8, 16, 0
};
const PROGMEM uint8_t lo[] = {
  M, 0, 7, L, 2, 6, L, 6, 6, L, 8, 8, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, Z, 0
};
const PROGMEM uint8_t lp[] = {
  M, 0, 16, L, 0, 6, L, 6, 6, L, 8, 8, L, 8, 10, L, 6, 12, L, 0, 12, 0
};
const PROGMEM uint8_t lq[] = {
  M, 8, 6, L, 8, 16, M, 8, 10, L, 6, 12, L, 2, 12, L, 0, 10, L, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, 0
};
const PROGMEM uint8_t lr[] = {
  M, 0, 6, L, 0, 16, M, 0, 8, L, 2, 6, L, 6, 6, L, 8, 8, 0
};
const PROGMEM uint8_t ls[] = {
  M, 8, 8, L, 6, 6, L, 2, 6, L, 0, 8, L, 0, 9, L, 2, 11, L, 6, 11, L, 8, 13, L, 8, 14, L, 6, 16, L, 2, 16, L, 0, 14, 0
};
const PROGMEM uint8_t lt[] = {
  M, 2, 0, L, 2, 14, L, 4, 16, L, 6, 16, L, 8, 14, M, 0, 6, L, 6, 6, 0
};
const PROGMEM uint8_t lu[] = {
  M, 0, 6, L, 0, 14, L, 2, 16, L, 8, 16, L, 8, 6, 0
};
const PROGMEM uint8_t lv[] = {
  M, 0, 6, L, 4, 16, L, 8, 6, 0
};
const PROGMEM uint8_t lw[] = {
  M, 0, 6, L, 2, 16, L, 4, 10, L, 6, 16, L, 8, 6, 0
};
const PROGMEM uint8_t lx[] = {
  M, 0, 6, L, 8, 16, M, 8, 6, L, 0, 16, 0
};
const PROGMEM uint8_t ly[] = {
  M, 0, 6, L, 0, 10, L, 2, 12, L, 8, 12, M, 8, 6, L, 8, 14, L, 6, 16, L, 0, 16, 0
};
const PROGMEM uint8_t lz[] = {
  M, 0, 6, L, 8, 6, L, 0, 16, L, 8, 16, 0
};


void setup()   {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  //delay(5);
}

void loop() {
  display.clearDisplay();
  int n = analogRead(0);
  setCursorVF(0, 0);
  unsigned long startTime = millis();
  printVF("ADC-0:");
  //вывод INT
  printVF(n);
  //вывод текста
  setCursorVF(0, 23);
  printVF("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  printVF("abcdefghijklmnopqrstuvwxyz");
  //printVFln("Test VvZz");
  //printVF("Test ln");
  //вывод на экран времени затраченного на прорисовку
  unsigned long totalTime = millis() - startTime;
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(100, 45);
  display.println(totalTime);
  display.display();
  delay(500);
  display.clearDisplay();
}

void PMRead( byte x[], int l ) {
  byte len = l;//принимаем длину массива
  byte bufer[len];//создаем буфер для чтения массива из PROGMEM
  byte b, k;//переменные
  for (k = 0; k < len; k++)
  {
    b =  pgm_read_byte_near(x + k);//читаем из PROGMEM
    bufer[k] = b;//заносим в буфер
  }
  drawVector(bufer, cx, cy, m);//выводим на экран из буфера
}

void drawVector(uint8_t vector[], byte x, byte y, double m) {
  byte interval = 13;
  byte startPoint[2];//начальная точка линии
  //double
  //m=1.0;//масштаб от 0 к 1
  //  double angle=0;//угол поворота
  //  angle=angle*(PI/180);//перевод угла в радианы

  //строим картинку по массиву
  while (vector[st] != 0) { //пока массив не закончился
    if (vector[st] == 10) { //SVG M
      //запоминаем точку начала кривой для замыкания контура
      startPoint[0] = (vector[st + 1] + x); //координата Х
      startPoint[1] = (vector[st + 2] + y); //координата У
      st = st + 3; //переходим к след команде
    }
    if (vector[st] == 20) { //SVG L если прямая
      display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, WHITE);
      st = st + 3;
    }
    if (vector[st] == 30) { //SVG Q кривая 3 порядка НЕ ПРОВЕРЯЛ
      display.drawCurve3p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, WHITE);
      st = st + 5;
    }
    if (vector[st] == 40) { //SVG C кривая 4 порядка
      display.drawCurve4p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, (vector[st + 5] + x)*m, (vector[st + 6] + y)*m, WHITE);
      st = st + 7;
    }
    if (vector[st] == 50) { //SVG S ПОКА НЕ РАБОТАЕТ необходимо добавить
      //вычисление зеркальной опорной точки
      //display.drawLine((vector[st-2]+x)*m,(vector[st-1]+y)*m,(vector[st+3]+x)*m,(vector[st+4]+y)*m,WHITE);
      display.drawCurve4p((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, vector[st - 4]*m, ((vector[st - 3]*m) + ((vector[st - 1] + y)*m)), (vector[st + 1] + x)*m, (vector[st + 2] + y)*m, (vector[st + 3] + x)*m, (vector[st + 4] + y)*m, WHITE);
      st = st + 5;
    }
    if (vector[st] == 60) { //SVG V если прямая
      display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, (vector[st - 2] + x)*m, (vector[st + 2] + y)*m, WHITE);
      st = st + 3;
    }
    if (vector[st] == 100) { //SVG z замкнуть контур
      display.drawLine((vector[st - 2] + x)*m, (vector[st - 1] + y)*m, startPoint[0]*m, startPoint[1]*m, WHITE);
      st = st + 1;
    }
    //раскоментировать для просмотра прорисовки
     // display.display();
    // delay(2);
  }
  st = 0; //сброс шагов обхода массива
  cx = cx + interval;
  if (cx>(128/m)-16){
    nl();
    //cx=0;
    //cy=cy+25;
  }
}


// Функция преобразования числа в строку
void printVF(int n)
{
  char buffer [12];
  itoa (n, buffer, 10);
  printVF(buffer);
}

void printVF(double n)
{
  char buffer [12];
  int a; //числитель
  int b; //знаменатель
  //округляем
  int c = n * 100;
  //получаем числитель
  a = (c / 100) % 1000;
  itoa (a, buffer, 10);
  printVF(buffer);
  printVF(".");
  //получем знаменатель
  b = abs(c % 100);
  itoa (b, buffer, 10);
  printVF(buffer);
}

// Функция преобразования числа в строку
void printVF(unsigned int n)
{
  char buffer [12];
  itoa (n, buffer, 10);
  printVF(buffer);
}

//вывод текста
void printVF(char txt[]) {
  byte symN = 0;
  while (txt[symN] != '\0') {
    char sym;//для хранения символа
    sym = txt[symN];
 sym = sym - 0;
    switch (sym) {
      case 32:
        PMRead(space, sizeof(space));
        break;
      case 45:
        PMRead(minus, sizeof(minus));//-
        break;
      case 46:
        PMRead(dot, sizeof(dot));//.
        break;
      case 48:
        PMRead(d0, sizeof(d0));
        break;
      case 49:
        PMRead(d1, sizeof(d1));
        break;
      case 50:
        PMRead(d2, sizeof(d2));
        break;
      case 51:
        PMRead(d3, sizeof(d3));
        break;
      case 52:
        PMRead(d4, sizeof(d4));
        break;
      case 53:
        PMRead(d5, sizeof(d5));
        break;
      case 54:
        PMRead(d6, sizeof(d6));
        break;
      case 55:
        PMRead(d7, sizeof(d7));
        break;
      case 56:
        PMRead(d8, sizeof(d8));
        break;
      case 57:
        PMRead(d9, sizeof(d9));
        break;
      case 58:
        PMRead(dDot, sizeof(dDot));//:
        break;
      case 65://A65
        PMRead(lA, sizeof(lA));
        break;
      case 66://B
        PMRead(lB, sizeof(lB));
        break;
      case 67://C
        PMRead(lC, sizeof(lC));
        break;
      case 68:
        PMRead(lD, sizeof(lD));
        break;
      case 69:
        PMRead(lE, sizeof(lE));
        break;
      case 70:
        PMRead(lF, sizeof(lF));
        break;
      case 71:
        PMRead(lG, sizeof(lG));
        break;
      case 72:
        PMRead(lH, sizeof(lH));
        break;
      case 73:
        PMRead(lI, sizeof(lI));
        break;
      case 74:
        PMRead(lJ, sizeof(lJ));
        break;
      case 75:
        PMRead(lK, sizeof(lK));
        break;
      case 76:
        PMRead(lL, sizeof(lL));
        break;
      case 77:
        PMRead(lM, sizeof(lM));
        break;
      case 78:
        PMRead(lN, sizeof(lN));
        break;
      case 79:
        PMRead(lO, sizeof(lO));
        break;
      case 80:
        PMRead(lP, sizeof(lP));
        break;
      case 81:
        PMRead(lQ, sizeof(lQ));
        break;
      case 82:
        PMRead(lR, sizeof(lR));
        break;
      case 83:
        PMRead(lS, sizeof(lS));
        break;
      case 84:
        PMRead(lT, sizeof(lT));
        break;
      case 85:
        PMRead(lU, sizeof(lU));
        break;
      case 86:
        PMRead(lV, sizeof(lV));
        break;
      case 87:
        PMRead(lW, sizeof(lW));
        break;
      case 88:
        PMRead(lX, sizeof(lX));
        break;
      case 89:
        PMRead(lY, sizeof(lY));
        break;
      case 90:
        PMRead(lZ, sizeof(lZ));
        break;
      case 97:
        PMRead(la, sizeof(la));
        break;
      case 98:
        PMRead(lb, sizeof(lb));
        break;
      case 99:
        PMRead(lc, sizeof(lc));
        break;
      case 100:
        PMRead(ld, sizeof(ld));
        break;
      case 101:
        PMRead(le, sizeof(le));
        break;
      case 102:
        PMRead(lf, sizeof(lf));
        break;
      case 103:
        PMRead(lg, sizeof(lg));
        break;
      case 104:
        PMRead(lh, sizeof(lh));
        break;
      case 105:
        PMRead(li, sizeof(li));
        break;
      case 106:
        PMRead(lj, sizeof(lj));
        break;
      case 107:
        PMRead(lk, sizeof(lk));
        break;
      case 108:
        PMRead(ll, sizeof(ll));
        break;
      case 109:
        PMRead(lm, sizeof(lm));
        break;
      case 110:
        PMRead(ln, sizeof(ln));
        break;
      case 111:
        PMRead(lo, sizeof(lo));
        break;
      case 112:
        PMRead(lp, sizeof(lp));
        break;
      case 113:
        PMRead(lq, sizeof(lq));
        break;
      case 114:
        PMRead(lr, sizeof(lr));
        break;
      case 115:
        PMRead(ls, sizeof(ls));
        break;
      case 116:
        PMRead(lt, sizeof(lt));
        break;
      case 117:
        PMRead(lu, sizeof(lu));
        break;
      case 118:
        PMRead(lv, sizeof(lv));
        break;
      case 119:
        PMRead(lw, sizeof(lw));
        break;
      case 120:
        PMRead(lx, sizeof(lx));
        break;
      case 121:
        PMRead(ly, sizeof(ly));
        break;
      case 122:
        PMRead(lz, sizeof(lz));
        break;
      default://если нет символа для вывода ставим пробел
        PMRead(space, sizeof(space));
        break;
    }
    symN = symN + 1;//переходим к следующему символу
  }
}

void printVFln(char txt[]) {
  printVF(txt);
  nl();
}

//установка курсора
void setCursorVF(byte x, byte y) {
  cx = x;
  cy = y;
}

//переход на след строку
void nl() {
  cx = 0;
  cy = cy + 21;
}

 

Logik
Offline
Зарегистрирован: 05.08.2014

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