благодаря комментарию выше оптимизировал операции с шестёркой. Теперь текст летит на ардуино нано как водяной понос =)
это хорошо) Можешь кстати по два раза выкладывать, в последнее время тут любят баяны часовой давности выкладывать)
ну так я готов их выслушать! Только спешу напомнить, что умножение и остаток от деления на числа "из степени двойки" компилятор оптимизирует самостоятельно, а деление у меня в коде заменено на сдвиг. Если есть что-то ещё - пишите!
дело в том, что размер блока виртуальных пикселей был сделан 4х6, а операции деления и остатка от деления с числами не из степеней двойки (2 4 8 16 32) выполняются в 20 раз медленнее, потому что у ардуинки нет аппаратного деления. Все остальные вычисления оптимизированы до степеней двойки, поэтому только лишь вот эта шестёрка добавляет около 150 миллисекунд!!!! к расчётам позиций пикселей при отрисовке часов
Возможно вам стоило бы подкинуть в программу функцию ускоренного деления на 6 через умножение на заранее посчитанную целочисленную константу.
Ну и вызывать свою функцию вместо оператора деления.
Вот тут немного тема раскрыта:
https://habr.com/ru/post/147096/
о, супер, спасибо! Я как раз сейчас сидел гуглил про быстрое деление на 6, но ничего вменяемого не нашёл)
Для ардуино с 16-битными регистрами деление на 6 будет примерно так (я не проверял, только прикинул):
final int cpuRegisterSize = 16;
final int b = 3;
final int L = 2; // 2**L >= b
final int N = (cpuRegisterSize – L) / 2; // ==7
final int B = ((1 << (N + L)) / b) + 1;
final int shiftSize = N + L + 1; // additional '+1' to move from div3 to div6
private static int divideBy6(int a) {
return (a * B) >> shiftSize;
}
private static int modBy6(int a) {
return a - divideBy6(a) * 6;
}
я не очень вник в статью, загуглил - нашёл более короткое объяснение. В моём случае до чисел 150 деление на 6 можно записать так:
x = (i * 342) >> 11;
выполняется в ячейке 2 байта. Точно там же можно найти остаток
val - x * 6
код ускорен в два раза, спасибо за наводку)
Для ардуино с 16-битными регистрами деление на 6 будет примерно так (я не проверял, только прикинул):
final int cpuRegisterSize = 16;
final int b = 3;
final int L = 2; // 2**L >= b
final int N = (cpuRegisterSize – L) / 2; // ==7
final int B = ((1 << (N + L)) / b) + 1;
final int shiftSize = N + L + 1; // additional '+1' to move from div3 to div6
private static int divideBy6(int a) {
return (a * B) >> shiftSize;
}
private static int modBy6(int a) {
return a - divideBy6(a) * 6;
}
А остаток прямо всегда нужен?
Можно при желании сделать его вычисляемым опционально.
способы разные есть красиво оформить
С точки зрения оптимизации чего? Если захочется вывести другую графику, текст или анимацию - это сидеть опять руками всё переделывать и хранить кадры в памяти? Это не похоже как минимум на оптимизацию памяти и на оптимизацию ручной работы ;)
Не соглашусь. В эту задачу входят подзадачи "нарисуй шрифт" и "расположи его на экране", а делать это на матрице, которая не является ровной сеткой - эксплуатация дизайнера, который будет рисовать и перерисовывать шрифты, в том числе если захочется подвинуть цифру на один сегмент в сторону ;)
не, это уже получается медленнее ~ на 30%, потому что вместо одной аппаратной операции умножения у нас три операции - два сдвига и одно сложение
Arduino & Pi
1.4K поста20.6K подписчиков
Правила сообщества
В нашем сообществе запрещается:
• Добавлять посты не относящиеся к тематике сообщества, либо не несущие какой-либо полезной нагрузки (флуд)
• Задавать очевидные вопросы в виде постов, не воспользовавшись перед этим поиском
• Выкладывать код прямо в посте - используйте для этого сервисы ideone.com, gist.github.com или схожие ресурсы (pastebin запрещен)
• Рассуждать на темы политики
• Нарушать установленные правила Пикабу