Просьба ко всем, особенно у кого есть оригинальная MEGA уделить 1 минуту времени, запустить приведенный ниже скетч на своем девайсе и посмотреть цифру которую он выдаст в мониторе порта. Заранее спасибо. Код (Text): #define DATA_PIN 13 #define LATCH_PIN 12 #define CLOCK_PIN 11 #define kadrTime 100 // мс на кадр #define kadrov 4 // колво кадров byte masRG [4][8][8] = { 0, 0, 0, 0, 0, 0, 0, 0, // 1 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 3, 3, 3, 3, 1, 0, 0, 1, 3, 2, 2, 3, 1, 0, 0, 1, 3, 2, 2, 3, 1, 0, 0, 1, 3, 3, 3, 3, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, //2 1, 3, 3, 3, 3, 3, 3, 1, 1, 3, 2, 2, 2, 2, 3, 1, 1, 3, 2, 0, 0, 2, 3, 1, 1, 3, 2, 0, 0, 2, 3, 1, 1, 3, 2, 2, 2, 2, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, // 3 3, 2, 2, 2, 2, 2, 2, 3, 3, 2, 0, 0, 0, 0, 2, 3, 3, 2, 0, 1, 1, 0, 2, 3, 3, 2, 0, 1, 1, 0, 2, 3, 3, 2, 0, 0, 0, 0, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, // 4 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 1, 1, 1, 1, 0, 2, 2, 0, 1, 3, 3, 1, 0, 2, 2, 0, 1, 3, 3, 1, 0, 2, 2, 0, 1, 1, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; long unsigned int ts; // таймер кадров byte kadrV; // видимый кадр // для подсчета fps long unsigned int ttt; unsigned int sss = 0; unsigned int fps = 0; void setup() { pinMode(DATA_PIN, OUTPUT); pinMode(CLOCK_PIN, OUTPUT); pinMode(LATCH_PIN, OUTPUT); kadrV = 0; ts = millis(); Serial.begin(9600); } void loop() { if ((millis() - ts) >= kadrTime) { // циклическое чередование кадров kadrV++; if (kadrV >= kadrov) kadrV = 0; ts = millis(); } setKadr_RG(masRG, kadrV); // отрисовка кадра // подсчет fps fps++; if ((millis() - ttt) > 2000) { Serial.println(fps); while (true); } } void setKadr_RG (byte mRG[2][8][8], byte kadr) { // отрисовка кадра byte bytSTR; byte mR; byte mG; for (byte s = 0; s <= 7; s++) { bytSTR = 0; bitSet(bytSTR, s); for (byte i = 0; i <= 7; i++) { bitWrite(mR, i, !(bitRead(mRG[kadr][s][i], 0))); bitWrite(mG, i, !(bitRead(mRG[kadr][s][i], 1))); } digitalWrite(LATCH_PIN, LOW); writeByte(bytSTR); writeByte(mR); writeByte(mG); digitalWrite(LATCH_PIN, HIGH); } } void writeByte(byte byteW) { // аналог shiftOut, работает чуть быстрее for (int i = 7; i >= 0; i--) { digitalWrite(DATA_PIN, (bitRead(byteW, i))); digitalWrite(CLOCK_PIN, HIGH); digitalWrite(CLOCK_PIN, LOW); } }
Не за что, удачи, код не смотрел. Немного поменяв, получил - 2112, можно наверно еще оптимизировать. Сколько надо получить? UPD. Решил немного просмотреть, очень странные строки. Код (Text): long unsigned int ts; // таймер кадров Код (Text): long unsigned int ttt; Что за тип данных, long или int?
Длинный инт беззнаковый 0 / 4 294 967 295 Что именно оптимизировали? Надо бы чтоб работоспособность не пропала при этом. Собственно этим кодом я скорее проверял производительность платы, которая у меня вызывала сомнения. Действительно неродная Мега выдала 375, а родная Уно 458. Завтра поменяю Мегу на другую, проверенную. Но все равно интересно что вы оптимизировали ускорив программу в 4,5 раза при этом ничего не сломав, скопируйте пожалуйста.
Могу ошибаться, пользуюсь uint32_t для unsigned long, но в ардуине вроде объявляется так Код (Text): unsigned long time; Глянул тут - https://www.arduino.cc/en/Reference/UnsignedLong. Сделал только прямой доступ к портам на AVR .ino Код (Text): #include "FastIO.h" #define DATA_PIN 13 #define LATCH_PIN 12 #define CLOCK_PIN 11 #define kadrTime 100 // мс на кадр #define kadrov 4 // колво кадров byte masRG [4][8][8] = { 0, 0, 0, 0, 0, 0, 0, 0, // 1 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 3, 3, 3, 3, 1, 0, 0, 1, 3, 2, 2, 3, 1, 0, 0, 1, 3, 2, 2, 3, 1, 0, 0, 1, 3, 3, 3, 3, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, //2 1, 3, 3, 3, 3, 3, 3, 1, 1, 3, 2, 2, 2, 2, 3, 1, 1, 3, 2, 0, 0, 2, 3, 1, 1, 3, 2, 0, 0, 2, 3, 1, 1, 3, 2, 2, 2, 2, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, // 3 3, 2, 2, 2, 2, 2, 2, 3, 3, 2, 0, 0, 0, 0, 2, 3, 3, 2, 0, 1, 1, 0, 2, 3, 3, 2, 0, 1, 1, 0, 2, 3, 3, 2, 0, 0, 0, 0, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, // 4 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 1, 1, 1, 1, 0, 2, 2, 0, 1, 3, 3, 1, 0, 2, 2, 0, 1, 3, 3, 1, 0, 2, 2, 0, 1, 1, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; long unsigned int ts; // таймер кадров byte kadrV; // видимый кадр // для подсчета fps long unsigned int ttt; unsigned int sss = 0; unsigned int fps = 0; void setup() { MC_SET_PIN_OUTPUT(DATA_PIN); MC_SET_PIN_OUTPUT(CLOCK_PIN); MC_SET_PIN_OUTPUT(LATCH_PIN); kadrV = 0; ts = millis(); Serial.begin(9600); } void loop() { if ((millis() - ts) >= kadrTime) { // циклическое чередование кадров kadrV++; if (kadrV >= kadrov) kadrV = 0; ts = millis(); } setKadr_RG(masRG, kadrV); // отрисовка кадра // подсчет fps fps++; if ((millis() - ttt) > 2000) { Serial.println(fps); while (true); } } void setKadr_RG (byte mRG[2][8][8], byte kadr) { // отрисовка кадра byte bytSTR; byte mR; byte mG; for (byte s = 0; s <= 7; s++) { bytSTR = 0; bitSet(bytSTR, s); for (byte i = 0; i <= 7; i++) { bitWrite(mR, i, !(bitRead(mRG[kadr][s][i], 0))); bitWrite(mG, i, !(bitRead(mRG[kadr][s][i], 1))); } MC_WRITE_PIN(LATCH_PIN, LOW); writeByte(bytSTR); writeByte(mR); writeByte(mG); MC_WRITE_PIN(LATCH_PIN, HIGH); } } void writeByte(byte byteW) { // аналог shiftOut, работает чуть быстрее for (int i = 7; i >= 0; i--) { MC_WRITE_PIN(DATA_PIN, (bitRead(byteW, i))); MC_WRITE_PIN(CLOCK_PIN, HIGH); MC_WRITE_PIN(CLOCK_PIN, LOW); } } FastIO.h в прищепке. Может еще можно что-то сделать, вопрос надо ли. Но уже туплю.
А, ну долгий стандартный доступ к портам это вопрос известный, да. Но пока критического момента не наступило, пользуюсь ими. За библиотеку спасибо, я ей буду пользоваться. Кононично объявлять unsigned long time;, но компилятор понимает и long unsignet time; видел в каком то примере, так и написал.
Можно пробовать работу с байтами, как на AVR, возможно будет быстрее, не проверял. Так же в циклах for использовать не ++, а --. Но раз не критично, можно забыть, лишний раз усложнять код не стоит. Меня удивило в строке - long unsigned int ts, long и int одновременно. Отправил на почту, это урезанный и измененный код Код (Text): Based on: fastio.h - https://github.com/MarlinFirmware/Marlin/tree/Release/Marlin Там больший список AVR процессоров и другая стилистика, исправлял под себя, когда разбирался в нужных мне функциях. Если Arduino IDE в туже папку, рядом с ino. UPD. Библиотека отличная, она сделана очень достойно и заточена под платы ардуино, так как принимает номера пинов ардуины.
В папку библиотек, не поймет, руки не доходят сделать в виде библиотеки. Иногда Arduino IDE тупит, просто добавьте вкладку назовите FastIO.h и скопируйте содержание файла.
Да нормально он подгрузился из папки со скетчем. Вопрос чисто из любопытства: посмотрел бегло этот файл, там самого кода и нет, сплошные определения и переопределения, как он вообще работает то? Да, и почему -- быстрее чем ++?
А не заметил, если коротко, он работает на ## (очень мощный инструмент препроцессора Си, ознакомится можно тут), прямого доступа к портам, битовых операций, определения самого процессора, макросов плюс константы, которые содержат сами порты. Все под определенные процессоры AVR. Если все эти темы, хотя бы бегло просмотреть, все сложится.
Поразительная разница в скорости! Почему в IDE это не используют? Из за проблем с совместимостью с другими процессорами?
Если Вы просто, будете использовать простой прямой доступ (можно ознакомится тут), скорость будет одинаковая, может быть немного быстрее этой библиотеки. Она позволяет переносить код на разные процессоры AVR, те которых нет, можно дописать. Почему ее нет в стандартной IDE, а зачем? Кому надо, тот разберется с конкретным процессором/найдет библиотеку и т.д. UPD. Сложно сказать почему ее нет среди стандартных. Возможно из-за каких-то тонкостей о которых не знаю. Если меня не устраивает скорость, иду в Си, кто-то опускается в ассемблер, такой код сложнее и требует больших знаний. Порой проще взять более мощный процессор, туже DUE и т.д.
С последним абзацем согласен, то же самое написано и по вашей ссылке: "Ваше время дорого, не так ли? А время компьютера очень дешево, соизмеримо со стоимостью потребленного им электричества." Но, как минимум, надо знать, что есть возможность прилично ускорить при необходимости некоторые критические части программы. Мало ли какие задачи могут внезапно возникнуть. Для LCD 16x2 есть такой же чудо-файлик? )
Видимо вчера пропустил, не заметил. Подумал, что Вам нужна именно скорость, поэтому и предложил данную библиотеку. Если нет необходимости в скорости, то нет смысла использовать такие библиотеки. Мне всегда не нравится, если я использую код или библиотеку и у меня нет понимания как она работает. Всегда разбираюсь, хотя бы те методы с которыми работаю. Речь идет только о циклах. Это сборная информация из сети, сам еще не добрался проверять, к примеру вот составные части 1, 2, всех статей не упомню. Нет, не было необходимости.
Когда в цикле используется --, происходит сравнение с нулем, это одна инструкция. В случае ++ происходит сравнение с некоторым значением, которое для сравнения нужно сперва загрузить в регистр, получается уже две инструкции.
1) В библиотеке Wiring, а не в IDE! IDE - это просто редактор текста с кнопочками. 2) Откоровенно никакая переносимость кода между разными контроллерами. Подход Wiring с универсальными функциями довольно хреновый по скорости, да еще с добавлением новых контроллеров будет становиться только хуже. Гораздо правильнее генерировать универсальный код с помощью шаблонов C++ с небольшой примесью макросов. Что-то похожее сделано, например, в библиотеке USB Host Shield 2.0 (см. avrpins.h). Так генерируется не универсальные функции, содержащие логику для вычисления портов и битов для всех контроллеров сразу, а только для текущего контроллера, что намного эффективнее и по скорости и по памяти тоже. При этом сохраняется переносимость кода и внешне он не усложняется. А этот FastIO - это еще ерунда, так, зачатки какие-то.
Используются шаблоны следующим образом. Сначала объявляются шаблонные классы для отдельных функций контроллера. Для ввода-вывода, например, это шаблон класса пина, который параметризуется портом и битом, этот класс содержит методы работы с одним битом (чтение, установка, инверсия, подтяжка, и т.п.). Потом пишется шаблон устройства и параметризуется классами пинов. В результате вы переезжая с контроллера на контроллер каждый раз генерируете только нужный код, а весь остальной так и остается в исходнике.