mirror of
https://github.com/openbios/openfirmware.git
synced 2025-05-09 00:21:49 +08:00
OLPC XO-4 - improved the reliability of the audio test:
a) Instead of the real random number generator, use a LFSR-based PRNG, with a polynomial that happens to give a good spectrum for acoustic testing with OLPC speakers. In addition to working around a unit- dependent problem with the MMP3's hardware RNG, this also speeds up the test because the LFSR is faster than the hardware RNG. b) Store 16-bit "random" values in the audio buffer instead of using 32-bit random numbers and hoping that the top and bottom halves are uncorrelated. This seems to give better decorrelation of left and right signals. c) Hard-reset the audio subsystem by powering off/on the audio island between the acoustic and loopback tests, thus making the loopback test more repeatable. git-svn-id: svn://coreboot.org/openfirmware@3623 1552c027-8020-0410-b4b5-a757f869b4ce
This commit is contained in:
parent
a35ee0afb7
commit
311899d7e2
@ -741,6 +741,15 @@ h# 10.0000 h# 8000 - h# 4000 - dictionary-size !
|
||||
|
||||
fload ${BP}/cpu/arm/saverom.fth \ Save the dictionary for standalone startup
|
||||
|
||||
fload ${BP}/forth/lib/lfsr.fth
|
||||
0 value lfsr-state
|
||||
: init-audio-noise ( -- )
|
||||
random-long to lfsr-state
|
||||
\ Use a polynomial with a 32-bit period
|
||||
lfsr-polynomials d# 32 na+ @ to lfsr-poly
|
||||
;
|
||||
: audio-noise ( -- n ) lfsr-state lfsr-step dup to lfsr-state ;
|
||||
|
||||
fload ${BP}/dev/hdaudio/noiseburst.fth \ audio-test support package
|
||||
|
||||
\ Because visible doesn't work sometimes when calling back from Linux
|
||||
|
@ -182,6 +182,14 @@ true value use-audio-pll?
|
||||
then
|
||||
false
|
||||
;
|
||||
\ This is a grotesque workaround for a hardware problem. The audio
|
||||
\ subsystem (SSPA + ADMA) works reasonably reliably right after the
|
||||
\ audio island is powered on, but subsequent tries tend to get
|
||||
\ confused about which channel is which, and possibly about the
|
||||
\ initial SSPA FIFO contents. Resetting between test phases makes
|
||||
\ the test work more reliably. Attempts to get help from the vendor,
|
||||
\ over a long period of time, were unsuccessful.
|
||||
: reset-audio ( -- ) audio-clock-off d# 50 ms audio-clock-on drop ;
|
||||
|
||||
: reset-rx ( -- ) h# 8000.0002 h# 0c sspa! ;
|
||||
|
||||
|
@ -479,6 +479,8 @@ fload ${BP}/cpu/x86/pc/saveabs.fth
|
||||
fload ${BP}/forth/lib/selstr.fth
|
||||
|
||||
fload ${BP}/cpu/x86/pc/olpc/via/padlock.fth \ Via security engine
|
||||
alias init-audio-noise noop
|
||||
alias audio-noise random-long
|
||||
fload ${BP}/dev/hdaudio/noiseburst.fth \ audio-test support package
|
||||
|
||||
fload ${BP}/ofw/inet/loadtcp.fth
|
||||
|
@ -620,14 +620,18 @@ fload ${BP}/forth/lib/tones.fth
|
||||
[then]
|
||||
|
||||
: prepare-signal ( -- out-adr, len in-adr,len )
|
||||
init-audio-noise
|
||||
\ Doing the noise 16 bits at a time does a better job
|
||||
\ of decorrelating the channels compared to storing
|
||||
\ a 32-bit "random" number
|
||||
[ifdef] debug-analyzer?
|
||||
debug-analyzer? if
|
||||
pb /pb d# 1000 d# 48000 make-2tones
|
||||
else
|
||||
pb /pb bounds do random-long i l! /l +loop
|
||||
pb /pb bounds do audio-noise i w! /w +loop
|
||||
then
|
||||
[else]
|
||||
pb /pb bounds do random-long i l! /l +loop
|
||||
pb /pb bounds do audio-noise i w! /w +loop
|
||||
[then]
|
||||
pb /pb -stereo-wmean
|
||||
pb wa1+ /pb -stereo-wmean
|
||||
|
@ -227,6 +227,7 @@ true value allow-swapping?
|
||||
: automatic-test ( -- )
|
||||
analysis-parameters " set-analysis-parameters" $call-analyzer
|
||||
acoustic-test
|
||||
[ifdef] reset-audio reset-audio [then]
|
||||
loopback-test
|
||||
;
|
||||
: selftest ( -- error? )
|
||||
|
143
forth/lib/lfsr-memtest.fth
Normal file
143
forth/lib/lfsr-memtest.fth
Normal file
@ -0,0 +1,143 @@
|
||||
\ See license at end of file
|
||||
purpose: Linear feedback shift register memory tests
|
||||
|
||||
[ifdef] arm-assembler
|
||||
code lfsr-fill ( adr seed polynomial -- adr' )
|
||||
\ tos:polynomial
|
||||
ldmia sp!,{r0,r1} \ r0:seed r1:adr
|
||||
mov r2,r0 \ r2:lfsr
|
||||
begin
|
||||
str r2,[r1],#4
|
||||
movs r2,r2,lsr #1
|
||||
eorcs r2,r2,tos
|
||||
cmp r2,r0
|
||||
= until
|
||||
mov tos,r1
|
||||
c;
|
||||
code random-fill ( adr len data index polynomial -- )
|
||||
ldmia sp!,{r1,r2,r3,r4} \ tos:poly r1:index r2:data r3:len r4:adr
|
||||
|
||||
movs r3,r3,lsr #2 \ Convert to longword count
|
||||
nxteq
|
||||
|
||||
sub r0,r3,#1 \ r0:remaining count
|
||||
|
||||
\ r3:address-lfsr r4:data-lfsr r5:data-poly
|
||||
set r5,#0x80200003 \ 32-bit polynomial
|
||||
|
||||
begin
|
||||
\ Compute new data value with an LFSR step
|
||||
movs r2,r2,lsr #1
|
||||
eorcs r2,r2,r5
|
||||
|
||||
\ Compute new address index, discarding values >= len
|
||||
begin
|
||||
movs r1,r1,lsr #1
|
||||
eorcs r1,r1,tos
|
||||
cmp r1,r3
|
||||
u< until
|
||||
|
||||
\ Write the "random" value to the "random" address (adr[index])
|
||||
str r2,[r4,r1,lsl #2]
|
||||
|
||||
decs r0,#1
|
||||
0= until
|
||||
|
||||
pop tos,sp
|
||||
c;
|
||||
code random-check ( adr len data index remain polynomial -- false | adr len data index remain true )
|
||||
ldmia sp!,{r0,r1,r2,r3,r4} \ tos:poly r0:remain r1:index r2:data r3:len r4:adr
|
||||
|
||||
cmp r0,#0
|
||||
moveq tos,#0 \ Return false
|
||||
nxteq
|
||||
|
||||
mov r7,r3,lsr #2 \ Convert to longword count
|
||||
|
||||
set r5,#0x80200003 \ 32-bit polynomial
|
||||
|
||||
begin
|
||||
\ Compute new data value with an LFSR step
|
||||
movs r2,r2,lsr #1
|
||||
eorcs r2,r2,r5
|
||||
|
||||
\ Compute new address index, discarding values >= len
|
||||
begin
|
||||
movs r1,r1,lsr #1
|
||||
eorcs r1,r1,tos
|
||||
cmp r1,r7
|
||||
u< until
|
||||
|
||||
\ Read the value at the "random" address (adr[index])
|
||||
ldr r6,[r4,r1,lsl #2]
|
||||
|
||||
\ Compare it to the calculated value
|
||||
cmp r6,r2
|
||||
|
||||
decne r0,#1
|
||||
stmnedb sp!,{r0,r1,r2,r3,r4} \ Push results
|
||||
mvnne tos,#0 \ True on top of stack
|
||||
nxtne
|
||||
|
||||
decs r0,#1
|
||||
0= until
|
||||
|
||||
mov tos,#0
|
||||
c;
|
||||
[then]
|
||||
: round-up-log2 ( n -- log2 )
|
||||
dup log2 ( n log2 )
|
||||
tuck 1 swap lshift ( log2 n 2^log2 )
|
||||
> - ( log2' )
|
||||
;
|
||||
|
||||
defer .lfsr-mem-error
|
||||
: (.lfsr-mem-error) ( adr len data index remain -- adr len data index remain )
|
||||
push-hex
|
||||
." Error at address " 4 pick 2 pick la+ dup 8 u.r ( adr len data index remain err-adr )
|
||||
." - expected " 3 pick 8 u.r ( adr len data index remain err-adr )
|
||||
." got " l@ 8 u.r cr
|
||||
pop-base
|
||||
;
|
||||
' (.lfsr-mem-error) to .lfsr-mem-error
|
||||
|
||||
: random-test ( adr len -- )
|
||||
dup /l <= if 2drop exit then ( adr len #bits )
|
||||
dup /l / round-up-log2 ( adr len #bits )
|
||||
polynomials swap la+ l@ ( adr len polynomial )
|
||||
|
||||
3dup 1 1 rot random-fill ( adr len polynomial )
|
||||
|
||||
>r ( adr len r: polynomial )
|
||||
1 1 third /l / 1- ( adr len data index remain r: polynomial )
|
||||
begin ( adr len data index remain r: polynomial )
|
||||
r@ random-check ( false | adr len data index remain true r: polynomial )
|
||||
while ( adr len data index remain r: polynomial )
|
||||
.lfsr-mem-error ( adr len data index remain r: polynomial )
|
||||
repeat ( r: polynomial )
|
||||
r> drop
|
||||
;
|
||||
|
||||
\ LICENSE_BEGIN
|
||||
\ Copyright (c) 2010 FirmWorks
|
||||
\
|
||||
\ Permission is hereby granted, free of charge, to any person obtaining
|
||||
\ a copy of this software and associated documentation files (the
|
||||
\ "Software"), to deal in the Software without restriction, including
|
||||
\ without limitation the rights to use, copy, modify, merge, publish,
|
||||
\ distribute, sublicense, and/or sell copies of the Software, and to
|
||||
\ permit persons to whom the Software is furnished to do so, subject to
|
||||
\ the following conditions:
|
||||
\
|
||||
\ The above copyright notice and this permission notice shall be
|
||||
\ included in all copies or substantial portions of the Software.
|
||||
\
|
||||
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
\
|
||||
\ LICENSE_END
|
@ -1,12 +1,7 @@
|
||||
\ See license at end of file
|
||||
purpose: Linear feedback shift register code and related memory tests
|
||||
|
||||
0 value lfsr-state
|
||||
|
||||
0 value lfsr-poly
|
||||
: lfsr-step ( state -- state' )
|
||||
dup 2/ swap 1 and if lfsr-poly xor then
|
||||
;
|
||||
|
||||
[ifdef] arm-assembler
|
||||
code lfsr-step ( state -- state' )
|
||||
@ -17,89 +12,6 @@ code lfsr-step ( state -- state' )
|
||||
eor tos,tos,r0
|
||||
then
|
||||
c;
|
||||
code lfsr-fill ( adr seed polynomial -- adr' )
|
||||
\ tos:polynomial
|
||||
ldmia sp!,{r0,r1} \ r0:seed r1:adr
|
||||
mov r2,r0 \ r2:lfsr
|
||||
begin
|
||||
str r2,[r1],#4
|
||||
movs r2,r2,lsr #1
|
||||
eorcs r2,r2,tos
|
||||
cmp r2,r0
|
||||
= until
|
||||
mov tos,r1
|
||||
c;
|
||||
code random-fill ( adr len data index polynomial -- )
|
||||
ldmia sp!,{r1,r2,r3,r4} \ tos:poly r1:index r2:data r3:len r4:adr
|
||||
|
||||
movs r3,r3,lsr #2 \ Convert to longword count
|
||||
nxteq
|
||||
|
||||
sub r0,r3,#1 \ r0:remaining count
|
||||
|
||||
\ r3:address-lfsr r4:data-lfsr r5:data-poly
|
||||
set r5,#0x80200003 \ 32-bit polynomial
|
||||
|
||||
begin
|
||||
\ Compute new data value with an LFSR step
|
||||
movs r2,r2,lsr #1
|
||||
eorcs r2,r2,r5
|
||||
|
||||
\ Compute new address index, discarding values >= len
|
||||
begin
|
||||
movs r1,r1,lsr #1
|
||||
eorcs r1,r1,tos
|
||||
cmp r1,r3
|
||||
u< until
|
||||
|
||||
\ Write the "random" value to the "random" address (adr[index])
|
||||
str r2,[r4,r1,lsl #2]
|
||||
|
||||
decs r0,#1
|
||||
0= until
|
||||
|
||||
pop tos,sp
|
||||
c;
|
||||
code random-check ( adr len data index remain polynomial -- false | adr len data index remain true )
|
||||
ldmia sp!,{r0,r1,r2,r3,r4} \ tos:poly r0:remain r1:index r2:data r3:len r4:adr
|
||||
|
||||
cmp r0,#0
|
||||
moveq tos,#0 \ Return false
|
||||
nxteq
|
||||
|
||||
mov r7,r3,lsr #2 \ Convert to longword count
|
||||
|
||||
set r5,#0x80200003 \ 32-bit polynomial
|
||||
|
||||
begin
|
||||
\ Compute new data value with an LFSR step
|
||||
movs r2,r2,lsr #1
|
||||
eorcs r2,r2,r5
|
||||
|
||||
\ Compute new address index, discarding values >= len
|
||||
begin
|
||||
movs r1,r1,lsr #1
|
||||
eorcs r1,r1,tos
|
||||
cmp r1,r7
|
||||
u< until
|
||||
|
||||
\ Read the value at the "random" address (adr[index])
|
||||
ldr r6,[r4,r1,lsl #2]
|
||||
|
||||
\ Compare it to the calculated value
|
||||
cmp r6,r2
|
||||
|
||||
decne r0,#1
|
||||
stmnedb sp!,{r0,r1,r2,r3,r4} \ Push results
|
||||
mvnne tos,#0 \ True on top of stack
|
||||
nxtne
|
||||
|
||||
decs r0,#1
|
||||
0= until
|
||||
|
||||
mov tos,#0
|
||||
c;
|
||||
[then]
|
||||
0 [if] \ This is for testing the period of various polynomials
|
||||
code lfsr-period ( polynomial -- period )
|
||||
\ tos:polynomial
|
||||
@ -127,6 +39,11 @@ code lfsr-step ( state -- state' )
|
||||
ax push
|
||||
c;
|
||||
[then]
|
||||
[ifndef] lfsr-step
|
||||
: lfsr-step ( state -- state' )
|
||||
dup 2/ swap 1 and if lfsr-poly xor then
|
||||
;
|
||||
[then]
|
||||
|
||||
0 [if]
|
||||
\ Given a list of bit numbers for the polynomial taps, compute the mask value
|
||||
@ -146,7 +63,8 @@ c;
|
||||
\ Polynomials for maximal length LFSRs for different bit lengths
|
||||
\ The values come from the Wikipedia article for Linear Feedback Shift Register and from
|
||||
\ http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
|
||||
create polynomials \ #bits period
|
||||
create lfsr-polynomials
|
||||
\ #bits period
|
||||
h# 0 , \ 0 0
|
||||
h# 1 , \ 1 1
|
||||
h# 3 , \ 2 3
|
||||
@ -181,38 +99,6 @@ h# 20000029 , \ 30 3fffffff
|
||||
h# 48000000 , \ 31 7fffffff
|
||||
h# 80200003 , \ 32 ffffffff
|
||||
|
||||
: round-up-log2 ( n -- log2 )
|
||||
dup log2 ( n log2 )
|
||||
tuck 1 swap lshift ( log2 n 2^log2 )
|
||||
> - ( log2' )
|
||||
;
|
||||
|
||||
defer .lfsr-mem-error
|
||||
: (.lfsr-mem-error) ( adr len data index remain -- adr len data index remain )
|
||||
push-hex
|
||||
." Error at address " 4 pick 2 pick la+ dup 8 u.r ( adr len data index remain err-adr )
|
||||
." - expected " 3 pick 8 u.r ( adr len data index remain err-adr )
|
||||
." got " l@ 8 u.r cr
|
||||
pop-base
|
||||
;
|
||||
' (.lfsr-mem-error) to .lfsr-mem-error
|
||||
: random-test ( adr len -- )
|
||||
dup /l <= if 2drop exit then ( adr len #bits )
|
||||
dup /l / round-up-log2 ( adr len #bits )
|
||||
polynomials swap la+ l@ ( adr len polynomial )
|
||||
|
||||
3dup 1 1 rot random-fill ( adr len polynomial )
|
||||
|
||||
>r ( adr len r: polynomial )
|
||||
1 1 third /l / 1- ( adr len data index remain r: polynomial )
|
||||
begin ( adr len data index remain r: polynomial )
|
||||
r@ random-check ( false | adr len data index remain true r: polynomial )
|
||||
while ( adr len data index remain r: polynomial )
|
||||
.lfsr-mem-error ( adr len data index remain r: polynomial )
|
||||
repeat ( r: polynomial )
|
||||
r> drop
|
||||
;
|
||||
|
||||
\ LICENSE_BEGIN
|
||||
\ Copyright (c) 2010 FirmWorks
|
||||
\
|
||||
|
Loading…
x
Reference in New Issue
Block a user