А у меня случалось на похожем примере: опрос матричной клавиатуры, первая строка кнопок "активируется" нулём с порта "B0", через кнопку - нуль поступает на pinB5.
cbi portB,0 ;активировать строку кнопок (0 активный = нажато)
nop ;cbi происходит в 2 такта поэтому pin здесь заценивать рано
sbic pinB,5 ;кнопка 1 = 0? (зажата?)
rjmp b2 ;НЕТ, к следующей кнопке ;...или далее
Как результат при отсутствии "nop" не работали все первые кнопки в строках.
sbiw сама отработает за два такта и ничего не будет отложено "на потом". Там всё нормально.
А вот с кнопками у вас именно аппаратная беда - емкость входа, выставили значение и пройдёт сотни наносекунд пока оно установится, поэтому нужны какие-то задржки. Кстати когда плата загрязнится одного нопа может оказаться недостаточно - это потенциально проблемное место, работа которого зависит от "RACE CONDITION". Поэтому я делаю наоборот - сначала читаю кнопки с ПРЕДЫДУЩЕЙ линии, потом меняю линию опроса - к следующему такту(через 1-2мс) всё давно уже устаканится.
CBI PORTB,0
RCALL PAUSE_RET ; 7 тактов
SBIC PINB,5
;..............
;..............
;..............
RET
;********************************
PAUSE_RET:
RET
;********************************
Серый_ писал(а):в данном случае "по научному" нужно ставить "nop"?
sbiw x,1 ;минуснуть 1 из пары (выполнится за 2 такта)
nop ;(поэтому пустотакт перед отправкой куда-либо)
out ocr1AH,xH ;отправить
out ocr1AL,xL
NOP не нужен. Вот режим работы модуля сравнения имеет значение, т.к. OCR1 может принять данные не только напрямую, а ещё и защёлкнуться в буфере. Перенос содержимого буфера в OCR1 произойдет при выполнении условия режима работы.
Коллеги, есть ли способ сдвинуть 4-байтовое число на 4 бита быстрее 16 тактов.
Для определённости пусть используются 4 старших регистра, а сдвиг вправо.
Сомнения терзают из-за наличия командочки swap...
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
[uquote="akl",url="/forum/viewtopic.php?p=3541340#p3541340"]Для "устаканивания" данных вместо NOPов обычно хватает... PAUSE_RET:[/uquote]
В общем да, было так:
Спойлерsbi portB,0 ;деактивация 1-й строки
cbi portB,1 ;и сразу активация 2-й строки
Были ложные срабатывания в 1-ом столбце (по нажатию первых кнопок любой строки). Между данными командами вклинил:
rcall bl_zvon ;блокировка звона меж строк
bl_zvon:
nop
ret ;и того 3+1+4 такта
Ложных срабатываний не выдавил при всём желании. Что до "блокировки звона" по кнопке 2...3mS, то все последующие нажатия блокируются на 0,5сек. по таймеру (оно же отвечает и за "турбирование" кнопок).
Перед применением swap нужно в текущем регистре на место младшего ниббла поместить младший ниббл старшего регистра. И уложиться в меньше 3-х тактов, т.е. в два или один. Хороша задачка.
Коллеги, есть ли способ сдвинуть 4-байтовое число на 4 бита быстрее 16 тактов.
Для определённости пусть используются 4 старших регистра, а сдвиг вправо.
Сомнения терзают из-за наличия командочки swap...[/uquote]
Для одиночного байта
SWAP Rd - обмен тетрадами
и
XCH Z,Rd - для обмена только с ОЗУ по указателю в Z (но не во всех подгруппах МК и для АВРстудио 4.19 неведомое)
плюсиком макрос обмена между регистрами
pyzhman, BOB51, как работает swap и про обмен xor-ом я знаю. Спасибо за напоминание.
[uquote="pyzhman",url="/forum/viewtopic.php?p=3541454#p3541454"]Хороша задачка.[/uquote]Да, есть такое. Решил, вот, поискать на просторах интернета, да людей поспрашивать прежде чем предпринять попытку изобрести велосипед.
PS: Что-то "велосипед" на swap-е меньше 17 тактов не выходит. Видать никак...
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
SWAP - быстрый обмен тетрадами.
(7-4) <-> (3-0) в текущем регистре меняются местами тетрады.
Использовался для скоростных преобразований в двоично-десятичной математике (Упакованный двоично-десятичный формат, ежли склероз не изменяет). Также удобен при формировании тетрадных цифирек под БИС с аппаратным дешифратором семисегментного кода.
На сегодня такие алгоритмы весьма редко применяются, ибо почти всюду используется табличный знакогенератор, да и быстродействие МК заметно возросло.
Из современных СБИС в которых возможно встретиться с режимом тетрадного дешифратора - MAX7219 к примеру.
[uquote="Starichok51",url="/forum/viewtopic.php?p=3542126#p3542126"]4 байта сдвинуть 4 раза и без swap займет 16 циклов (а не тактов).[/uquote]
Именно поэтому я и спрашивал про быстрее 16 циклов/тактов.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Тогда уж просто умножение на 16 одним разом. Равноценно сдвигу влево на 4 бита.
Но... с занесением младших нулей, а не замена тетрад - придется добавлять несколько команд
для помещения старшей тетрады на новое место.
Хотя... как алгоритм... ЗАСЛУЖИВАЕТ ВНИМАНИЯ, особо в тех МК, где есть аппаратное умножение.
Так тут и есть умножение на 16, которое "разбирает" регистр на две тетрады с одновременным обнулением второй. Причем для сдвига влево или вправо меняется только порядок сборки тетрад в байты.
Да, если результат умножения байта собрать в один регистр, то получается точный эквивалент SWAP. Естественно, смысла в этом нет - что может быть быстрее одноциклового SWAP. А вот использовать умножение на 16 для выделения чистых тетрад без дополнительных ANDI очень даже быстро.
У меня были подобные задачи по смещению части битового поля для ЖКИ индикаторов на основе NJU6432 и KS0035...
Там весьма помудрить порой приходится - помимо прочего зависит и от конкретной привязки сегментов к ячейкам ОЗУ (при изготовлении индикатора).
Здравствуйте.
Коротко о себе и моём уровне подготовки:
Я перевожу один проект под свои нужды. Основная цель - замена дисплея на цветной TFT.
Хоть я и радиолюбитель с определённым стажем, но мой род занятий и образование не связаны с электроникой и тем более программированием. Так же нет возможности "развиваться в команде" - то есть одиночество абсолютное.
Тем не менее три месяца тотального красноглазия над AVR Assembler-ом дало ощутимые плоды.
Суть проблемы такая:
При выводе текста на дисплеи бОльших размеров моноширинный шрифт смотрится (мяхко говоря) неуклюже. (кстати шрифты делаю сам, практически в ручную, на коленке, попиксельно).
Решил использовать пропорциональный шрифт и создать свою таблицу ASCII. Полный знак примерно 8x16px. Три нижних строки пустые для вывода хвостов от всяких q, y, g, ... щ, ц, ... и запятых.
Ну и естественно вопрос: как реализовать нахождение шрифта в таблице символов и получить ширину символа при выводе.
Готовых решений не прошу.
Буду признателен за любую информацию, которая укажет правильное направление.
Да в общем-то, так же, как и на Си или другом языке. Традиционно есть 2 подхода:
1. При описании каждого символа шрифта указываетс его ширина. Т.е. в массиве байтов, описывающих пикселы символа первый байт задает ширину этого символа.
2. Создается отдельная таблица, в которой хранится ширина и адрес начала символа в знакогенераторе, а сам знакогенератор в отдельной таблице
Оба подхода вынуждают использовать не традиционный массив с одинаковыми элементами, а "хитрый" массив (точнее - по сути список), в котором размер всех элементов разный, а значит адрес доступа к любому элементу уже невозможно вычислить простым умножением размера на номер элемента.
Поэтому в первом подходе приходится "сканировать" знакогенератор с самого первого символа, всякий раз вычисляя адрес начала следующего (первый байт - количество столбцов, умножаем на количество строк, прибавляем 1 и получаем адрес следующего символа) до тех пор, пока не найдется нужный. Процесс доступа долгий, зато создание знакогенератора простое.
Во втором случае наличие отдельной таблицы с размерами и адресами начала символа в знакогенераторе (т.е. по сути это таблица индексов, как в базах данных) резко ускоряет доступ к символам: все элементы этой таблицы одинаковы по размеру, поэтому вычисление реального адреса символа в шрифте осуществляется просто. Но создавать знакогенератор по этому принципу гораздо сложнее.
Так же в первом случае сложновато делать знакогенератор для шрифтов с "пропуском символов", например, не всегда нужна псевдографика или там латинские символы... Потому что в этом случае надо помимо сканирования списка символов еще и отслеживать "дыры". Во втором случае это проще: в индексной таблице просто пропускаются "лишние" позиции, и все.
Кстати, есть специальные программы для создания пиксельных шрифтов, поддерживающих ОБА способа, и позволяющих практически мышкой нарисовать любой знакогенератор и получить на выходе исходник со всеми данными на любом языке программирования, в т.ч. и ассемблере. Рекомендую поискать. Ключевые слова LCD font editor или generator
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...