Random number generator in AVR Studio (no C or any other programming language!)

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

Answers (1)

Carl Smotricz
Carl Smotricz

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:

  1. This is a very simple 16-bit RNG. It's extremely insecure cryptographically insofar as if the algorithm and current number (even in parts) are known, the next number can be reliably predicted. Also, the sequence of numbers it produces will repeat after 65535 numbers. It can be used for no-risk "toy" projects like that of the original question or mine.
  2. The sequence of numbers produced depends completely on the first, "seed" number. Same seed, same numbers, always. You'll want to find a "really" random source for that seed. I pull a number out of the 16-bit timer when the user presses a button.
  3. If the seed number is 0, the output will be an infinite sequence of 0's. To get a sequence of "useful" pseudo-random numbers you need to start with a number (any number) other than 0.
  4. In summary, if this code breaks, you get to keep both pieces.

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

Related Questions