Страница 1 из 1
Tiny2313 Random() на ASMе
Добавлено: Пн сен 21, 2009 22:41:11
czuryk
Приведите пожалуйста код, реализующий на ASM для Tiny2313 простой генератор псевдослучайных чисел. Снимать шумы не хочу, хочется иметь простое программное решение.
Из этой темы
http://kazus.ru/forums/showthread.php?t=8950&page=2, я к сожалению мало что понял...
Буду очень рад помощи!
Спасибо!
Добавлено: Пн сен 21, 2009 23:08:19
Yellow Tiger
Зачем же далеко ходить? И здесь было, минимум, две темы такого содержания.
Там, в частности, давались ссылки:
теория
данные для организации ГПСЧ
код на Си
А если еще погуглить на "Linear Feedback Shift Registers" или "LFSR"...

Добавлено: Вт сен 22, 2009 22:58:30
czuryk
Спасибо за ответ, но к сожалению мне он не сильно помог, попробовал я покурить LFSR, но к сожалению мне пока это мало понятно. с++ я знаю пока еще хуже АСМа, чтобы иметь возможность переложить самому на АСМ.
Не у кого нет готового решения реализации на ASM для tiny2313 хотя бы способа предложенного ARV, в теме
http://radiokot.ru/forum/viewtopic.php?t=7603
Добавлено: Вт сен 22, 2009 23:18:00
Meteor
Вопрос коррекции полета. Нужна именно псевдослучайная последовательность или просто случайное число из диапазона от А до В? М-последовательности (ГПСЧ) имеют цикличность зависящую от охватов обратными связями. И какие требования к числам?Если ГПСЧ, то длина цикла, диапазон чисел...
Добавлено: Ср сен 23, 2009 00:12:29
Yellow Tiger
czuryk писал(а):Не у кого нет готового решения реализации на ASM...
Так ведь пример-то все равно придется соотносить с теорией, чтобы не вслепую писать. Скажем, для 24 бит выйдет что-то типа такого:
Код: Выделить всё
.DSEG
; Store SEED value here -
_random_b1: .BYTE 0x1
_random_b2: .BYTE 0x1
_random_b3: .BYTE 0x1
.CSEG
rand:
clr r15 ; accumulator/flag
lds r30,_random_b1
sbrc r30,0x02; check for 1-st tap
inc r15 ; note if found 1
lds r30,_random_b2
sbrc r30,0x00; check for 2-nd tap
inc r15 ; note if found 1
sbrc r30,0x06; check for 3-rd tap
inc r15 ; note if found 1
lds r30,_random_b3
sbrc r30,0x07; check for 4-th tap
inc r15 ; note if found 1
clc
sbrc r15,0x00
sec
; Shift right through Carry - C > B3 > C > B2 > C > B1
ror r30 ; already contains (_random_)B3
sts _random_b3,r30 ; save it
lds r30,_random_b2 ; get B2
ror r30 ; ...
sts _random_b2,r30
lds r30,_random_b1
ror r30
sts _random_b1,r30 ; now R30 contains RetVal (random)
ret
Но "передирать" вслепую - пустое занятие, нужно бы соотнести с тем, что написано про LFSR. И не забыть про начальную величину в трех байтах (SEED).
Добавлено: Вт сен 29, 2009 13:27:28
czuryk
Сегодня наконец то занялся вплотную...
При подстановки начальных значений - вообще не работает, без низ работает, но как оказалось - совсем не так как мне надо. Легко просматривается циклический сдвиг. Никакой случайности!
Код: Выделить всё
.include "tn2313def.inc"
.list
.def temp = R16
.def work = R17
.equ kdel2 = 0x30
//.equ kdel2 = 0xFF
.dseg ; Выбираем сегмент ОЗУ
.org 0x60 ; Устанавливаем текущий адрес сегмента
buf: .byte 1
_random_b1: .BYTE 0x1
_random_b2: .BYTE 0x1
_random_b3: .BYTE 0x1
; ---------- Начало програмного кода
.cseg ; Выбор сегмента программного кода
.org 0 ; Установка текущего адреса в ноль
; ---------- Переопределение векторов прерываний
start:
rjmp init ; Переход в начало программы
reti ; Внешнее прерывание 0
reti ; Внешнее прерывание 1
reti ; Таймер/счетчик 1, захват
reti ; Таймер/счетчик 1, совпадение, канал A
reti ; Таймер/счетчик 1, прерывание по переполнению
reti ; Таймер/счетчик 0, прерывание по переполнению
reti ; Прерывание UART прием завершен
reti ; Прерывание UART регистр данных пуст
reti ; Прерывание UART передача завершена
reti ; Прерывание по компаратору
reti ; Прерывание по изменению на любом контакте
reti ; Таймер/счетчик 1, совпадение, Канал B
rjmp tim0 ; Таймер/счетчик 0, совпадение, Канал B
reti ; Таймер/счетчик 1, совпадение, Канал A
reti ; USI готовность к старту
reti ; USI переполнение
reti ; EEPROM Готовность
reti ; Переполнение охранного таймера
; ---------- Модуль инициализации
init:
; ---------- Инициализация стека
ldi temp, RAMEND; Выбор адреса вершины стека
out SPL, temp ; Запись его в регистр стека
; ---------- Инициализация портов BB
// ldi temp, 0 ; Записываем ноль в регистр temp
ldi temp, 0xFF ; Записываем число $FF в регистр temp
out DDRD, temp ; Записываем этот ноль во DDRD (порт PD на ввод)
ldi temp, 0xFF ; Записываем число $FF в регистр temp
out DDRB, temp ; Записываем temp в DDRB (порт PB на вывод)
ldi temp, 0xFF ; Записываем число $FF в регистр temp
out DDRA, temp ; Записываем temp в DDRA (порт PA на вывод)
out PORTB, temp ; Записываем temp в PORTB (потушить светодиод)
out PORTD, temp ; Записываем temp в PORTD (включаем внутренний резистор)
out PORTA, temp ; Записываем temp в PORTD (включаем внутренний резистор)
; ---------- Инициализация таймера T0
// ldi temp, 0x0D ; Код конфигурации записываем в temp
ldi temp, 0x01 ; Код конфигурации записываем в temp
out TCCR0B, temp ; Переносим его в регистр конфигурации таймера
ldi temp, kdel2;
out OCR0A, temp ;
; --------- Определение маски прерываний
ldi temp, 0b01000001; Байт маски. Разрешено одно прерывание (№4)
out TIMSK, temp ; Записываем маску
; ---------- Инициализация компаратора
ldi temp, 0x80 ; Выключение компаратора
out ACSR, temp
; ---------- Начало основного цикла
main:
sei ; Разрешение прерываний
m1:
rjmp m1 ; Пустой бесконечный цикл
; =====================
; Программа обработки прерываний
; =====================
tim0:
push temp ; Сохраняем регистр temp
rcall rand
lds temp, _random_b3 ;
out PORTB, temp
ldi temp, 0 ; Младший полубайт кода совпадения
out TCNT0, temp ;
pop temp ; Восстановление регистра temp
reti
rand:
push temp ; Сохраняем регистр temp
push work ; Сохраняем регистр temp
clr temp ; очищаем r15
lds work, _random_b1 ; Загружаем в r30 содержимое ячейки памяти _random_b1
sbrc work, 0x02 ; Пропуск следующей комманды, если 1-й бит = "0"
inc temp ; Увеличиваем r15
lds work, _random_b2 ; Загружаем в r30 содержимое ячейки памяти _random_b2
sbrc work, 0x00 ; Пропуск следующей комманды, если 0-й бит = "0"
inc temp ; Увеличиваем r15
sbrc work, 0x06 ; Пропуск следующей комманды, если 6-й бит = "0"
inc temp ; Увеличиваем r15
lds work, _random_b3 ; Загружаем в r30 содержимое ячейки памяти _random_b3
sbrc work, 0x07 ; Пропуск следующей комманды, если 7-й бит = "0"
inc temp ; Увеличиваем r15
clc ; Очищаем флаг "С"
sbrc temp, 0x00 ; Если r15 четное:
sec ; Устанавливаем флаг "C"
; Shift right through Carry - C > B3 > C > B2 > C > B1
ror work ; Циклический сдвиг содержимого регистра вправо. 7-й разряд переходит в C
sts _random_b3, work ; Сохраняем r30 в ячейки памяти _random_b3
lds work, _random_b2 ; Загружаем в r30 содержимое ячейки памяти _random_b2
ror work ; Циклический сдвиг содержимого регистра вправо. 7-й разряд переходит в C
sts _random_b2, work ; Сохраняем r30 в ячейки памяти _random_b2
lds work, _random_b1 ; Загружаем в r30 содержимое ячейки памяти _random_b1
ror work ; Циклический сдвиг содержимого регистра вправо. 7-й разряд переходит в C
sts _random_b1, work ; Сохраняем r30 в ячейки памяти _random_b1
lds r20, _random_b1 ;
lds r21, _random_b2 ;
lds r22, _random_b3 ;
pop work ; Восстановление регистра temp
pop temp ; Восстановление регистра temp
ret
Добавлено: Ср сен 30, 2009 14:16:30
czuryk
Не у кого больше нет никаких вариантов?
Я нашел еще один пример, но там тот же сдвиг... :(
Очень бы не хотелось делать его с таймером и с набором констант так как это сожрет большую часть тини2313...
Добавлено: Ср сен 30, 2009 14:58:57
GP1
тогда только один выход - цеплять на компаратор шумогенератор.
Добавлено: Ср сен 30, 2009 16:35:56
czuryk
Да... я уже это понял... написал прогамму на двух таймерах, на симуляторе есть небольшая непредсказуемость, но на железе все линейно, синхронизированно по кварцу. Рандома и близко нет.
Можно попросить кого либо из участников форума скинуть схему генератора белого шума (на стабиллитроне илю резюке) для tiny2313 и кусок ASM кода, который снимал бы показание с АЦП микросхемы...
Буду много благодарен:)
Добавлено: Ср сен 30, 2009 23:19:15
Yellow Tiger
czuryk писал(а):При подстановки начальных значений - вообще не работает, без низ работает, но как оказалось - совсем не так как мне надо. Легко просматривается циклический сдвиг. Никакой случайности!
А может ты просто не умеешь их готовить?
Вот последовательность, выданная тем самым кодом, при инициализации seed'ом = 0x2734:

Длину последовательности мерять сейчас лениво, но распределение для выборки из всего-лишь 1000 чисел весьма неплохое.
А по ссылке, которую я давал, можно выбирать параметры ГПСЧ с длиной последовательности и для гурманов тоже...

Добавлено: Чт окт 01, 2009 09:59:48
czuryk
Готовить умею, но первый блин оказался комом :)
Посли двух дней стучание головой об стену, мне пришла простая идея, которая отлично сработала! :idea:
Старая функция обработки прерывания по таймеру теперь меняется на примерно эту:
Код: Выделить всё
push temp ; Сохраняем регистр temp
rnd_repeat: ; Выполняем 3 полных байтовых сдвига
rcall rand
inc rndcnt
cpi rndcnt, 24
brlt rnd_repeat
ldi rndcnt, 0
lds temp, _random_b3 ;
out PORTB, temp
ldi temp, 0 ;
out TCNT1H, temp ; Обнуляем TIMER1
out TCNT1L, temp ; Обнуляем TIMER1
pop temp ; Восстановление регистра temp
reti
и проблема решена.
Теперь если у меня например подключено к PORTB восем светодиодов, то больше при рандоме не наблюдается эффект сдвига.
Если же RANDOM число "не визуально", то можно обойтись без этого.
Добавлено: Чт окт 01, 2009 19:00:45
Yellow Tiger
czuryk писал(а):...и проблема решена.
Ну, что ж, и слава богу. Вот только, я вижу - ты так и оставил тот код, который я накропал исключительно в иллюстративных целях... ну, ладно, раз читать лениво, то...

А фокус этот, с прокруткой 24 бит - был прямо указан по тем ссылкам, корень которых я привел вначале.

Добавлено: Чт окт 01, 2009 20:22:04
czuryk
Я кое что почитал по ссылкам, просто с англишем у меня плохо... А вернее есть пробелы в техническом английском.
На русском я так материалов и не нашел.
С другой стороны - хоть утешение, что сам допер до прокрутки:)
А код подправлять я не вижу особого смысла - пробовал только упрощать снижая количество регистров до 1-го, но получилось не очень.
Будет побольше времени погоняю в отладчике еще, попытаюсь получше разобраться :)
Да мне в принципе 3 регистра устраивает, своего рода универсальная функция - нужно двухрегистровое число - пожалуйста, однорегистровое - нате:)
P/S Но если тебе не трудно, поясни что значит TAP и Feedback functions из мана мне ее описание показалось очень туманным.
Добавлено: Чт окт 01, 2009 21:11:27
Yellow Tiger
czuryk писал(а):...поясни что значит TAP и Feedback ...
Ну, это как раз самое простое; feedback - обратная связь, то есть тот метод, который читает значения из заданных разрядов и формирует из них следующий бит, подаваемый в регистр, а TAP - это, в данном случае, один из используемых разрядов. Где написано "
24 bits, 4 taps" - читаем "
всего разрядов - 24, из них 4 используются для формирования нового бита (ОС)".
Добавлено: Пт окт 02, 2009 06:01:09
rime2000
czuryk писал(а):
На русском я так материалов и не нашел.
http://rain.ifmo.ru/cat/view.php/theory ... 005/stream
http://orel-lsr.narod.ru/LAB6/tv_sdr.html
czuryk писал(а):А код подправлять я не вижу особого смысла - пробовал только упрощать снижая количество регистров до 1-го, но получилось не очень.
чем меньше длина регистра, тем быстрее начнутся повторения
в случае с 24 битами код начнет повторятся через 16777215 циклов, в случае с 8 битами - через 255.
czuryk писал(а):
P/S Но если тебе не трудно, поясни что значит TAP и Feedback functions из мана мне ее описание показалось очень туманным.
да, в некоторые термины сложно выникнуть непосвященным... у меня в свое время пару часов ушло чтоб вникнуть во всю эту кухню с регистрами...на самом деле все просто...на примере одного регистра (8 бит), так как тебе не знакома криптография, то выбираешь с потолка номера битов, пусть будет первый и шестой - это и будут твои TAP - точки съема. Согласно вашего примера, если в каждом из выбранных ТАРах стоит единица, то инкрементируется счетчик. Т.е. результатом одного сдвига есть сумма выбранных тобой ТАРов, тобишь первого и шестого бита. И от этой суммы зависит будет ли установлен флаг переноса или нет, который потом пойдет обратно в 7 бит регистра. Т.е. получается уже целая функция - это и есть Feedback, дословно - функция с обратной связью. Т.е. у тебя есть обратная связь с тем, что выходит из регистра и результатом возвращается в начало.
а вообще, можно не вникать в это, а взять любой описанный алгоритм и реализовать его, тот же RC4 очень легок в реализации.
Добавлено: Пт окт 02, 2009 12:29:41
czuryk
Спасибо за пояснения! Я все таки хочу попробовать разобраться.
Но назрел еще один вопрос по существующему алгоритму.
Можно ли задать диапазоны для этой функции рандома, например от
0 до 5000 или от 500 до 1000 (пример в десятичной форме)
т.е. значения был во втором примере были бы, если: _random_b1-младний байт, _random_b2-старший: 01F4-03E8.
Очень не хочется запускать RANDOM в цикле и после проверять его выход на условие больше-меньше и если результат неудовлетворительный повторять генерацию нового числа.
Добавлено: Пт окт 02, 2009 14:48:23
rime2000
для задания диапазона потребуется вводить операцию по модулю, но так как ты ни в криптографии ни в программировании не силен, то может тебе стоит просто в месте инкремента r15 сделать проверку, если он достиг какого-то числа, то вместо инкремента делать декримент. В любом случае твой алгорит даже не приближается к криптостойкости, так что очередная линейность в функции хуже не сделает. Ты лучше напиши поподробнее цели своей задачи и функции этого ГПСЧ, я смогу набросать тебе ченить попроличней.
Добавлено: Пт окт 02, 2009 15:28:35
czuryk
Программист мне кажется я не такой уж и плохой, просто до этого на Delphi да PHP писал, АСМом занялся две недели назад.
Сделал чуть проще.
После получения результата копирую из _random_b2 не весь байт целиком, а только два последний бита, т.к. максимальное число кот. мне нужно - 3. Это избавило меня от "буксовки алгоритма в поиске "правильного числа".
Мне шифрование делать не нужно, все гораздо проще:)
Я делаю что-то наподобии гирлянды на 8 светодиодах. Которые с помошью ШИМ плавно загораются и гаснут.
Для этого у меня два массива - первый текущие позиции модуляции, второй - смещение к которому нужно прийти. Разброс от 1-1000.
Программа должна работать так:
При запуске заполняет массив текущих позиций с помощью RANDOM от 0..1000, и присваивает массиву смещения те же значения.
В следующем шаге для каждого элемента срабатывает условие по которому определяется что смещение достигнуто и срабатывает RANDOM для установки нового смещения и в следующих кольцах цикла происходит увеление позиции модуляции ШИМ (или уменьшение), приближаясь к смешению, при достижении котогого все повторяется снова.
Вот собственно и все. Сам алгоритм простой и должен быть понятен, код выкладывать смысла не вижу. Но если что, могу предоставить уточнения.
Добавлено: Пт окт 02, 2009 17:01:24
rime2000
да, твое решение вполне нормальное и в условиях постановки задачи вполне оправдано. Надо было сразу постановку задачи выдать, а то мысли фсякие сразу в голову лезут в силу профессии...