В процессе дальнейшего копания возникла ещё одна проблемка. Попробовал сделать кольцевой сдвиг символа влево. Задумка такова - в оперативке по метке Kod зарезервировано 8 байт. Там лежит построчно закодированный символ. Temp5 - счётчик и указатель на номер строки при передаче. Они совпадают. Извлекаем в Temp6 первый байт, отправляем в max7219, выполняем кольцевой сдвиг и возвращаем в оперативку с пост-инкрементом и снова по кругу. Получился такой код
Спойлер
BOB хотел сказать, что ваши 8 байт являются видеопамятью. Каждые Х мС времени подпрограмма вывода выводит всё содержимое этой видеопамяти в ваш модуль 8Х8. А вы, когда ВАМ надо эту видеопамять модифицируете.
Легче заново набросок сделать, чем в чужом, фрагментами представленном коде, разбираться.
Тем более, что в данном случае надо еще и к даташиту на MAX7219 плотненько возвернуться. Да со структурой привязки пикселей уточнить (теоретически там 8 колонок по 8 вертикальных точек в колонке - блок данных "на боку" - в наличии такой матрицы на данный момент нету за ненадобностью - могу лишь "теоретизировать").
Да и МК для меня не "базовый" - хотя в примитиве с программным SPI что на тиньку2313, что на мегу8 лаподрыг особо отличаться не должен...
Разве что без привязки к МК то уже библиотечка получается...
BOB51 писал(а): более рационально менять содержимое буфера видеопамяти, а затем делать пакетный вывод
Тогда надо будет вытащить байт из оперативки, модифицировать, вернуть обратно, а потом ещё раз вытаскивать для отправки. Как по мне - вытащил, отправил, модифицировал, вернул более оптимально. По поводу
BOB51 писал(а):в данном случае надо еще и к даташиту на MAX7219 плотненько возвернуться. Да со структурой привязки пикселей уточнить
это всё не нужно. По работе с MAX7219 вопросов нет. Вывод реализован без вопросов. Вопрос в модификации. Почему после первого прохода я получаю из оперативки немодифицированные данные?
Вообще-то данные из ячейки видеобуфера вытаскиваются однократно на каждое обращение к СБИС контроллера.
Тем более, что у АВРок косвенное чтение памяти имеется.
А вот отсылка блока из двух байт при каждом обращении к СБИС (адрес и данные) выполняется.
Полный цикл - пересылка блока 8*2=16 байт по SPI заметно длиннее всех имеющихся обращений к ОЗУ.
Касательно обработки содержимого видеобуфера - это уже на усмотрение автора.
В зависимости от задачи можно обработку и в регистровом файле делать.
Допустим блок видеобуфера в ОЗУ имеет вот такое размещение:
а вот относительно дисплея... шаблон развернется "боком":
Это как первая подсказка к алгоритму обработки.
И еще одно замечание -
Если для циклических процессов (бегущие точки или полоски, разнообразные сдвиги) еще можно применить программные решения, то для версий мультипликации гораздо выгоднее применять ряд из "кадров", размещенных или в ПЗУ или во внешней ЕЕПРОМ.
Прекрасно!
А теперь попробуйте используя только один байт буферного регистра вывести на индикацию вот такую трассу (или картинку при достаточной скорости смены информации):
стрелочки показывают последовательность обхода светящейся точкой поля матрицы.
(направление обхода может быть и обратным).
Подсказка - смотреть специфику адресации MAX7219.
Что имеется ввиду?
А вообще, для комфортной работы понядобится два РОН. Если совсем изаратиться и одного может хватить. Больше ведь никаких требований к алгоритму не вадвинуто. Самое тупое решение - через LDI кидаем в РОН нужное значение и засылаем его в SPDR.
В данном случае имеется ввиду чисто программный синтез картинки - без "заготовки в ПЗУ".
Продвижка точки только алгоритмом программы при использовании одного байта временного хранения данных, а не матрицы 8*8.
ессно и счетчики и подпрограмма вывода будут присутствовать - но то и для обычного алгоритма применяется.
И чего там военного? Начинаем с правого верхнего угла. Кидаем в РОН, пусть будет R16, 0b00000001. В счётчик тоже ложим единицу.
Прогоняем отправку 0b00000001 восемь раз. Счётчик одновременно служит номером строки.
Когда достигли 8 - цикл со сдвигом R16 влево, декриментом счётчика и отправкой данных.
Когда достигли 1 - цикл аналогичный первому, без изменения R16.
Когда достигли 8 - цикл со сдвигом R16 вправо, декриментом счётчика и отправкой данных.
Мы вернулись в правый верхний угол.
Перед отправкой данных вызываем подпрограмму очистки дисплея.
Вот и возврат к вопросу правильно выбранных координат.
Поскольку возможно получить две трактовки привязки строк и колонок - надо перед публикацией оговаривать что принимаем за строку, а что за колонку.
Колонка - вертикальный ряд (аналогия позиции знакоместа и соответственно адресу ОЗУ MAX7219), а строка - горизонталь (аналогия позициям сегментов в знакоместе).
Почему так удобнее - смотрим вариант "беглой строчки" - перемещение вертикальной колонки, привязанной к адресу ячейки ОЗУ MAX7219 гораздо удобнее выполняется в буфере видеопамяти.
При том, что можно как угодно привязку делать. Это уже подбор более оптимального варианта на вкусы разработчика.
Если у вас одиночный модуль, тогда да, его можно вертеть как угодно. А если линейка из четырёх модулей, тут уже всё зафиксировано. А если трудно запомнить, что адрес это столбец, а отправляемый байт строка - не надо и начинать писать программы.
Как раз для нескольких модулей более выгодно "классическое" распределение точек (принятое в MAX7219) - по вертикали "сегментные", а по горизонтали "позиционные".
Строкой принято называть развертку по горизонтали.
Или развертку пакета из энного числа байт позиционного ("сегментного") кода в результате которого на дисплее отображается строка символов.
Хотя... терминология без схемы - штука весьма вредная (общепринятой обязательной не существует).
Посему и требуется вместе с прожкой выкладывать точную привязку и собственную, принятую для конкретной программы систему обозначений.
Иначе алгоритмы обработки у каждого из занимающихся одним и тем же вопросом будут кардинально отличаться (и в то же время быть справедливы для каждой из конкретных схем).
А вот чего там на самом деле, когда матрицы в едином блоке на общей платке смонтированы - это надо конкретную платку смотреть и проверять.
Понимаю что не в тему но в лом искать подходящую, что-то они все закрытые.
Видно АВР совсем не в моде нынче..
Надо стало быстрое деление константы 32767 на переменную 16 бит.
Придумал вот такую делилку.
Она проста, понятна, легко может быть приспособлена под любую разрядность
Для сравнения, делилка 16\16 из АВР аппноты тратит 260 тактов
DivU_TempHL_BT: ; TempH:L делимое (потом здесь будет удвоенный остаток)-
ldi Cnt, 1 ; -Buff:Temp делитель, R1:R0 округленный результат
mov One, Cnt
clr R1 clr R0
mov R2, One ; начальное значение маски для записи единиц в результат-
clr R3 clr Zero ; -она же будет счетчиком в цикле деления
cpi Temp, 128
cpc Buff, Zero
brsh shl
cpi Temp, 32 ; чтоб не повиснуть при делении на 0 :
cpc Buff, Zero
brsh swdv
ldi Temp, 32
swdv:
mov Buff, Temp ; для ускорения работы, если делитель <128-
clr Temp ; -можно сдвинуть делитель влево сразу на 8 бит
mov R3, One ; -и маску тоже
clr R2
shl:
sbrc Buff, 6
rjmp dv
lsl Temp rol Buff ; сделать делитель близким к делимому
lsl R2 rol R3 ; при этом приготовить маску
rjmp shl
dv:
cp Temp_L, Temp ; в цикле, сравнить делимое и делитель
cpc Temp_H, Buff
brlo shr
sub Temp_L, Temp ; если можно то вычесть
sbc Temp_H, Buff
or R1, R3 ; и маской внести единицу в результат
or R0, R2
shr:
lsr R3 ror R2 ; в любом случае, сдвинуть 1 в маске вправо
brcs edv ; (пока она совсем не обнулится, тогда выйти из цикла)
lsr Buff ror Temp ; и сдвинуть вправо делитель
rjmp dv
edv:
lsl Temp_L rol Temp_H ; удвоить остаток
cp Temp, Temp_L ; сравнить его с делителем
cpc Buff, Temp_H
adc R0, Zero ; округлить
adc R1, Zero
ret ; 185 тактов макс. время, мин. время 31 тактов
Добрый день. Решил всё-таки освоить ассемблер для AVR. И как следовало ожидать - грабли полезли отовсюду. Простые инструкции проходят. Но даже присвоить литеральный псевдоним регистру - нет. Да многе чего. Компилятор просто пишет "не знаю что это такое" и падает. Вот сделал сложение двух 32-разрядных чисел, получилось. Инкремент 8-разрядных тоже работает. Я создаю файл с расширением S, а в файле на C/C++ функцию со спецификаторами доступа, либо напрямую с помощью ассемблерных вставок. В протеусе скомпоновал "испытательный стенд" из двух 7-сегментных индикаторов на ТМ1637 и контроллера ATtiny84.
На github.com(ссылка) есть библиотека которую мне хотелось бы местами использовать. Как говорится в релизе
"ТРЕБОВАНИЯ И ЗАВИСИМОСТИ:"
"Данная реализация написана на языке ассемблера "AVRASM2". Соответственно, она предназначена для разработки программных прошивок (firmware) на языке ассемблер, для микроконтроллеров Atmel AVR (8-bit)." ссылка на библиотеку
Но, что-то идет не так. main.cppСпойлер
В файле... uint32_t n = add32(222222,333333); tm1637_1::output(n);// = 555555
НО шаг вправо, шаг влево - сплошные грабли. То - не то, это - не это. Извините за глупый вопрос - куда копать?
Есть два разных варианта:
"чистый ассемблер" - avrasm2
и
ассемблерные вставки в рамках Си
подход соответственно будет также различным.
Если с "чистым вариантом" особо проблем нету, то с ассемблерными вставками только СИшники помочь могут...