Отличная статья

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

Для тех, кто интересуется современным С++ - отличная статья: https://habr.com/ru/post/428846/

Прямо и бездумно применить не получится, т.к. у нас нет std (а кто умеет ставить, те "бездумно" ничего не применяют), но почитать, понять и почерпнуть идеи - самое оно.

Мне очень понравилось.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

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

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

BOOM пишет:

на то, что актуально 

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

Вот, например, в дисплее вот из этой темы раскладка символов вот такая:

Обратите внимание на кирилицу. Буквы расположены как и где попало. Чтобы вывести их на дисплее необходима нормальная такая программа перекодировки. Например, вот такая, как utf8rus в этом постене подойдёт.

Но, допустим, что у нас есть правильная программа, которая подходит. Пусть она тоже называется utf8rus. Дальше что? А дальше мы пишем примерно так:

display.print(utf8rus("Понедельник"));

И вроде всё работает, но !!!

Во-первых строка "Понедельник" занимает в памяти вдвое больше места, чем надо, т.к. русские буквы двухбайтовые, а на дисплей мы выводим по одному байту для каждой буквы (их нам даёт utf8rus).

Во-вторых, прежде, чем вывести, мы вызываем преобразователь utf8rus - а это и расход программной памяти, и задерка времени исполнения!

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

Как этого избежать? Можно, например, в строке писать не буквы, а сразу коды букв в кодировке экрана. Тогда преобразование не нужно и байтов будет будет расходоваться ровно столько, сколько реально нужно. Но, посмотрите как ужасно при этом будет выглядеть строка! Ведь вместе того, что у нас написано выше, мы получим нечто вот такое:


display.print("\250\157\275\145\343\145\273\304\275\270\272");

Это безобразие, конечно, выведет нам слово "Понедельник" и не использует ни одного лишнего байта, но, согласитесь, писать тексты в таком стиле (а особенно править их, если захочется) - это как-то не очень красиво (не "для девочек", в общем).

Так вот, я, как добропорядочная девочка, задаю на форуме вопрос: А можно писать просто

display.print("Понедельник");

ну, на худой конец

display.print("Понедельник"_rus);

ИЛИ

display.print(RUS("Понедельник"));

но чтобы при этом память расходовалась как во втором примере выше, и чтобы никаких перекодировок во время выполнения не происходило?

Ответ девочке: можно, милая, можно! Можно, чтобы перекодировкой занимался компилятор, а в код пихались уже готовые для вывода на дисплей данные. И можно это при помощи техники, описанной в той статье.

Ну, согласитесь, вполне ардуиновская задача и совсем не редкая и не высосанная из пальца!

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

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

Ответ девочке: можно, милая, можно! Можно, чтобы перекодировкой занимался компилятор, а в код пихались уже готовые для вывода на дисплей данные. И можно это при помощи техники, описанной в той статье.

Ну, согласитесь, вполне ардуиновская задача и совсем не редкая и не высосанная из пальца!

отличная задача, спасибо за иллюстрацию...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Не вырывайте из контекста мои слова :-)

Я говорил о том, что актуально в конкретный момент (времени) для меня. Это же хобби (увлечение для души, так сказать). К примеру, вчера нашёл очень интересную для меня библиотеку для dds (si5351). Хотя последний год (или полтора уже) все пытаюсь понять как программировать самому эти пресловутые микросхемы. Но не получается, не понимаю как по диаграммам и временным данным можно код писать (может из-за возраста, может просто не обучаем в этом). А спрашивать стыдно. Имею примерное представление о развитии темы, где мои вопросы будут глупее «а как диодом помигать». (((

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Сложная (для меня например) статья :(
Выше пример с перекодированием строки для lcd месяц назад решил десятком строк.....но да, надо учиться делать правильно.

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

andycat пишет:
пример с перекодированием строки для lcd месяц назад решил десятком строк.....
В смысле перекодирование во время исполнения? Или на этапе компиляции?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

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

andycat пишет:
пример с перекодированием строки для lcd месяц назад решил десятком строк.....
В смысле перекодирование во время исполнения? Или на этапе компиляции?


Исполнения конечно, то что в статье это пока для меня высшая материя....

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

andycat пишет:
Сложная (для меня например) статья :( .

основная идея статьи простая - компилятор теперь умеет выполнять не только простенькие команды типа #include или #ifndef, а практически все многообразие С++ - с классами, наследованием, шаблонами, перегрузкой операторв  - но все это не во время выполнения, а на этапе компиляции

Единственное ограничение - обьекты, очевидно, должны быть статичными и известными компилятору

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Пропустил тему, а жаль, позвольте реанимировать.

Задача перекодировки неудачная - я бы не стал так делать (через вариативные шаблоны). И очень сложно, и точно, байт в байт, всё равно не получится.

Когда мне нужно было выводить на русифицированный LCD, я просто добавил свою программку в тулчейн IDE. Эта программка просматривала все исходники и выполняла перекодировку нужных строк. Разумеется, она это делает уже в фолдере build - оригинальные исходники не трогает.

В результате у меня было написано типа

display.print("Понедельник");

а компилятор видел уже перекодированное

display.print("\250\157\275\145\343\145\273\304\275\270\272");

И все дела. Простенько и со вкусом. Программку могу найти, если кому интересно. И рассказать как её в тулчейн добавить.

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

Ворота пишет:

И рассказать как её в тулчейн добавить.

это интересно

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

b707 пишет:

Ворота пишет:

И рассказать как её в тулчейн добавить.

это интересно

1.
Пишешь программу (консольное приложение), которая получает (через argv / argc) один аргумент - имя папки "built/sketch". В этой папке в момент вызова программы будут лежать все исходники скетча (все, которые были в папке скетча) уже после предварительной обработки IDE, т.е. в .ino файл уже будет называть .ino.cpp, в нём будет вставлено #include <Arduino.h>, и все прочие прелести.

2.
Помещаешь эту программу в место, где ей можно исполняться (в моём случае она лежит в папке D:\IDEAddOns - полный путь "D:\IDEAddOns\prepreproc.exe"

3.
В файле platforms.txt размещаешь строку типа

recipe.hooks.sketch.prebuild.0.pattern="D:\IDEAddOns\prepreproc.exe" "{build.path}\sketch"

Ноль здесь - порядок вызова на случай, если таких программ несколько и нужно несколько таких строк. Поле текстовое, т.е. если программ 10 и больше, лучше писать 00, 01 и т.п. иначе 10 окажется впереди 2.

Собственно всё, она вызывается после IDE'шной обработки, но до компиляции и может делать с файлами что хочет.

Я для перекодировки строк, проходился по всем файлам с расширениями .cpp, .c, .h, .hpp и .S, в каждом искал скобки вида

static constexpr char beginToken[] = "<%UTF82LCD";
static constexpr char endToken[] = "%>";

сами скобки удалял, а всё, что внутри просматривал и каждую русскую букву заменял на \ххх

Если надо, могу и текст показать, но он не особо откомментирован - делался по-быстрому, на коленке.

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

угу. а если записать в  platforms.txt

recipe.hooks.sketch.postbuild.0.pattern = "{runtime.platform.path}/postbuild.bat" {build.source.path} {build.path} {build.project_name} {source_file}
 
 
а рядом с ним сделать postbuild.bat в котором
 
SET bak=%1.bak\%date%
 
If Not Exist "%bak%" MD "%bak%"
 
SET t=%time:~0,8%
SET hr=%t%
 
if "%t:~0,1%" equ " " set hr=0%t:~1,7%
if "%t:~1,1%" equ ":" set hr=0%t:~0,7%
 
set "t=%hr::=_%"
SET rar=%bak%\%t%
 
"c:\Program Files (x86)\Arduino\WinRAR.exe" a %rar% %1
 
то получим систему автоматического резервного копирования исходников всех удачно собранных скетчей.
Ох скока же раз она меня выручала )))

 

Morroc
Offline
Зарегистрирован: 24.10.2016

BOOM пишет:
Но не получается, не понимаю как по диаграммам и временным данным можно код писать

Зачем ? По диаграммам вам нужно сделать единственную функцию (ну или две) для обмена данными и то если стандартная wire вам почему то не подходит, на этом диаграммы и временные данные заканчиваются и начинается математика dds, с ней вы опять же можете поступить по разному - использовать готовую библиотеку (большинство так и делают и нужны веские аргументы для написания самому) или расчитать все коэффициенты в калькуляторе производителя (его же можно использовать для проверки собственной митематики). Основной код синтезатора вообще не связан с управлением dds (для ad эта часть десяток строк кода).

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

Ворота пишет:

Я для перекодировки строк, проходился по всем файлам с расширениями .cpp, .c, .h, .hpp и .S, в каждом искал скобки вида

static constexpr char beginToken[] = "<%UTF82LCD";
static constexpr char endToken[] = "%>";

сами скобки удалял, а всё, что внутри просматривал и каждую русскую букву заменял на \ххх

вот эту часть не догнал - откуда в исходниках эти скобки? Вроде как в сообщении #9 ты писал. что в коде у тебя просто строки кириллицей:

display.print("Понедельник");

а теперь вдруг какие-то скобки появились...

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

b707 пишет:

вот эту часть не догнал - откуда в исходниках эти скобки? Вроде как в сообщении #9 ты писал. что в коде у тебя просто строки кириллицей:

display.print("Понедельник");

а теперь вдруг какие-то скобки появились...

Не, ну это было "образно" - на уровне идеи, в реале-то я скобки ставил, иначе как понять какую кириллицу надо перекодировать, а какую не надо (например, если в сериал выводить кириллицей, то там не надо ничего перекодировать).

Скобки ставились не прямо на строку, а на большой кусок кода. Например, функция для вывода на экран или блок констант - целиком в одной паре скобок. Внутри скобок - все кириллические символы перекодируются (некириллические  идут на выход как есть), а вне скобок - всё идёт как есть.

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

Ворота пишет:

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

понял, спасибо

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

если вернутся к исходной теме - применению constexpr - мой самый первый опыт.

Задачка - посчитать сумму элементов массива на этапе компиляции (чтобы использовать вычисленное значение при обьявлении другого массива)

решено так:

#include <stdio.h>

#define NUMS 4
constexpr int numms[NUMS] = {1,2,3,4};

constexpr int summ_nums(int n) 
{
 return n>=NUMS ? 0 : (numms[n] + summ_nums(n+1));
}

constexpr int a = summ_nums(0);

int ARR[a];

int main() {
printf("a = %d", a);
}

Работает.

Готов выслушать глум и замечания :)

 

 

 

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

b707 пишет:

constexpr int summ_nums(int n) 
{
 return n>=NUMS ? 0 : (numms[n] + summ_nums(n+1));
}

То, что в constexpr функции единственным оператором может быть return (а constexpr конструктор обязан быть пустым) - это ограничение C++11. Если поставите в platform.txt вместо "-std=gnu++11" что нибудь типа "-std=gnu++14" или "-std=gnu++17" или "-std=gnu++1z", то можно будет писать нормальные функции и непустые конструкторы.

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

Сейчас я это тестирую на дистрибутиве линукса 14 года, так что C++17 мне недоступно :)

но надо будет попробовать :)