#include // Constants for the RNG #define LCG_A 25173 #define LCG_C 13849 //#define LCG_M 65536 // register names #define MulResultLB r18 #define MulResultHB r19 #define ArgLB r24 #define ArgHB r25 #define RetLB r24 #define RetHB r25 #define TmpLB r22 #define TmpHB r23 /** * Returns an uint16_t (pseudo) random number in R24:R25. * * The Method calculates an random number with a linear congruence generator (LCG). * It uses the formula * * X(n+1) = (LCG_A*X(n) + LCG_C) modulo m * * to generate pseudo random numbers. * * Function needs 22 cycles + return (4) (=26 cycles). * We do not need the modulo operation because we have set m to 2^16. * * A more detailed description can be found in: * * - Donald E. Knuth, The Art of Computer Programming * - Dale Grover, Digital Signal Processing and the Microcontroller */ .text .global RandLCG .type RandLCG,@function RandLCG: ; // save used registers push r0 ; // do a 16x16 bit multiplication ; // al * bl , ah * bl, bh * al ; // (LCG_A * X) ldi TmpLB, lo8(LCG_A) ldi TmpHB, hi8(LCG_A) ; // multiply the low bytes mul TmpLB, ArgLB ; // copy the result from r0:r1 to r16:r17 movw MulResultLB, r0 ; // multiply high byte with low byte mul TmpHB, ArgLB ; // add result to r17 add MulResultHB, r0 ; // the last multiply mul ArgHB, TmpLB add MulResultHB, r0 ; // now we have the result in MulResult ; // now add the constant ldi TmpLB, lo8(LCG_C) ldi TmpHB, hi8(LCG_C) add MulResultLB, TmpLB adc MulResultHB, TmpHB ; // move the result to the return registers so that gcc can use them movw RetLB, MulResultLB ; // restore registers pop r0 clr r1 ; // and return ret