Reputation: 33
so I have this question, I have been given a task to do a bombard game with AVR Studio. To be true, I have no clue on how to use AVR and my programming is not so good as well. I got my ships done somehow, but now I need a random number generator. Have been looking throughout Internet for about 2 days now, only found source codes in C, in Java, in absolutely every other language but not the one I need. Could anyone suggest me in what to write for the RAND? for now, my source code looks like this:
;ports
.equ PORTC = $15 ;port C address
.equ DDRC = $14
.equ PORTA = $15 ;port A address
.equ DDRA = $14
;registers
.def leds = r16 ;storing data for leds
.def temp = r18 ;Temporary storage register
.def save = r19 ;Temporary storage register for status registers
.def YL = r20 ;Defining low bite of Y
.def YH = r21 ;Defining high bite of Y
;
.equ SREG = $3F ;Status Register Address
.equ SPH = $3E ;High bite Stack Pointer address
.equ SPL = $3D ;Low bite Stack Pointer address
.equ RAMEND = $25F ;Stack Address
;Random number generator
ldi r16, $80
ldi r17, $C0
;Set stack pointer to registers
ldi temp,high(RAMEND)
out SPH,temp
ldi temp,low(RAMEND)
out SPL,temp
;Initialise output ports
ldi temp, $ff
out DDRC, temp
clear: clc
; clr leds
out PORTC, leds
rjmp SHIP2_prep
SHIP1_prep: ldi leds, $80
rjmp SHIPS
SHIP2_prep: ldi leds, $80
out PORTC, leds
ldi leds, $C0
rjmp SHIPS
SHIP3_prep: ldi leds, $80
out PORTC, leds
ldi leds, $C0
out PORTC, leds
ldi leds, $E0
rjmp SHIPS
;Rotate ships right
SHIPS: out PORTC, leds
; rcall delay
ror leds
brcs clear
rjmp SHIPS
;delay: in save,SREG
; ldi YH,high($FF9C)
; ldi YL,low($FF9C)
loop: sbiw Y,1
brne loop
out SREG, save
ret
Upvotes: 2
Views: 1425
Reputation: 67750
The question is more than a year old but I found it while looking for a bog-simple RNG for an AVR assembler project as well. I found it frustrating that StackOverflow had no solution! I've meanwhile found one I like so I'd like to contribute it.
DISCLAIMERS:
All that said, I found it amazing that this could be accomplished in essentially 6 lines of assembler code.
My algorithm is based on the C code shown in the Galois LFSR section of the Wikipedia article on linear feedback shift registers.
Lightly tested for quality.
To ensure I wasn't implementing garbage, I copied the C code, wrapped a bit of test code around it and assured myself that it was indeed producing sequences of length 65535 for at least a handful (5) of test seeds.
I ran my AVR assembler implementation (for AtTiny2313, but it should run on most AVR models) in the simulator in AtmelStudio with the same test seeds and verified that the first 20 numbers in each sequence were the same as in the C program.
Enough waffling! Here's my code:
.INCLUDE "tn2313def.inc"
start:
ldi xl, low(1234)
ldi xh, high(1234)
again: rcall galois
nop ; do something with rn here...
rjmp again
galois: ; subroutine for computing the next prime in X
lsr xh
ror xl
brsh noxor
ldi r17, $B4
eor xh, r17
noxor:
ret
The basic idea is easily extensible to generators with more bits and longer periods simply by increasing the number of registers and using a different suitable "tap polynomial" encoding than $B400.
Upvotes: 1