[uquote="Demiurg",url="/forum/viewtopic.php?p=3883190#p3883190"]Предлагаю добить. Задачи: Произвольные порты, выбор активного уровня. Вы мне тут показали, что вроде как можно по индексу на порты вывести. Покажите макросы и добиваем совместными усилиями.[/uquote]
Шаблоны так не работают... Допустим есть такой список пинов:
Код: Выделить всё
using pins = PinList<PA6, PA4, PB3, PA2, PA1>;
Фактически pins - это тип, на данном этапе он никакого реального кода не генерит. Теперь вызовем метод write():
В этот момент создает экземпляр класса и в первую очередь внутри него из первоначального списка формируются индексированный список, т.е. пины нумеруются, потому что потом они будут из списков удаляться, а индекс будет нужен. Кроме того списки могут вместо пинов принимать другие списки, но в индексированном списке уже все разворачивается до одних пинов. Также создается список портов присутствующих в списке, проверяется наличие дубликатов пинов и вычисляет размер развернутого списка. Все эти дополнительные списки существуют чисто виртуально на этапе компиляции. Но основные расчеты начинаются когда дело доходит непосредственно до write(), там компилятор сортирует пины по портам и для каждого порта ищет последовательности пинов которые можно было бы получить за один заход по вычисленной маске. В данном случае для порта PA будет получена маска 0x16(для PA4, PA2, PA1), 0x40(для PA6) и еще одна специфическая маска для портов STM32. Для AVR, насколько помню, получилось бы что-то типа такого:
Код: Выделить всё
PORTA = PORTA & ~(0x16 | 0x40) | ((val << 1) & 0x16) | ((val << 2) & 0x40);
Естественно это эффективнее, чем:
Код: Выделить всё
PORTA &= ~(0x16 | 0x40);
if(val & 0x01) PORTA |= (1 << 1);
if(val & 0x02) PORTA |= (1 << 2);
if(val & 0x08) PORTA |= (1 << 4);
if(val & 0x10) PORTA |= (1 << 6);
А препроцессор просто подменяет один ничего для него не значащий текст на другой, потому никакими макросами шаблоны не заменишь.