Subject:
|
Getting started; FFT; millisecond timing
|
Newsgroups:
|
lugnet.robotics.rcx.pbforth
|
Date:
|
Fri, 9 Apr 2004 19:12:20 GMT
|
Viewed:
|
4618 times
|
| |
| |
Hi everyone, my first posting. First off, heartfelt thanks to Ralph for pbForth.
Having recently (Jan 2004) got hold of Mindstorms 2.0 I thought I would lay out
the way I found to get up and running with pbForth. It took me a week or two to
figure it so who knows, this might help someone out there.
I am running a Lego RCX 2.0, with the USB infrared tower, off a Windows Me
system. My apologies in advance if there are any mistakes or omissions or if it
is all too obvious for words.
To install and use pbForth:
(1) Get Bricx Command Centre (the NQC environment) from
http://bricxcc.sourceforge.net/nqc/
The following applies to BricxCC Version 3 build 3.3.7.7 22 Jan 04
(2) Get the pbForth firmware pbforth.srec from Ralph's site
http://www.hempeldesigngroup.com/lego/pbForth/
(go to the static page, then Downloads). This is all the software you need to
run pbForth.
For the following stages, the RCX should be in range of the tower.
(3) Take the batteries out of the RCX leaving at least a minute for the
existing firmware to be erased. Put the batteries back in. Hit On-Off so you
see the standing man with a 1 at right but no time display.
(4) Start BricxCC with the Standard firmware option. Select Tools, Download
Firmware. In the browser that opens up select Alternate Firmware Files, navigate
to pbforth.srec and download it. The RCX display should count up to about 900
and then show "4th".
At this point the RCX is totally dead and none of the buttons will work!
(5) From BricxCC, select Tools, Close Communication. Then Tools, Find Brick.
This time select pbForth firmware.
(6) Still in BricxCC, open the pbForth console. This can be done from the View
menu or by hitting F2.
(7) Click on the red button at top left of the console. There may be some
"nonsense" characters shown. Hit Enter on your keyboard. RCX should reply "OK"
You can power down the RCX by entering POWER_OFF. The On-Off button wakes it up
again. Nothing will show on the LCD display but it will again respond OK when
you hit Enter in the console. To reload the standard firmware, you will need to
take the batteries out again.
That's it, you now have pbForth. All you need to do now is actually learn it.
For this I strongly recommend "Extreme Mindstorms" by Baum, Gasperi, Hempel and
Villa.
The book is a little out of date regarding pbForth. Ralph has kindly provided
a list of the current RCX-specific keywords on his pbForth weblog site,
mentioned above. The ANSI Forth specification is a mine of information; core
definitions start at
http://www.taygeta.com/forth/dpans6.htm
Better sign off here. Of course I'll be really grateful for the pbForth GUI when
it is fixed to work with the USB tower...
Oh, here is a FFT (Fast Fourier Transform) I wrote. It samples at 1
millisecond intervals (triggering off the 0-99 millisecond counter at EFD0). A
256 point transform computes in about 5 seconds. It might be speeded up; I've
found that / and */ are very slow... I really must sign off. Again, thanks
to Ralph
Pat
\ FFT1MS.TXT
\ FAST FOURIER TRANSFORM WITH 1,000 HZ LIGHT SAMPLING
\ AND HAMMING WINDOW
\ pbFORTH SCRIPT BY P.W.MILES MARCH 2004
\ LIGHT SENSOR ON 2 ( MIDDLE )
\ AN LED BICYCLE LAMP MAY SERVE AS A TEST SOURCE. MY LAMP FLASHES AT ABOUT
\ 85HZ ON A 50% DUTY CYCLE WHEN IN CONTINUOUS MODE
\ TO COLLECT DATA AND DISPLAY IT ENTER "n SAMPLE" (NO QUOTES) WITH
\ n = 2 TO 8 FOR A 4 TO 256 POINT DATA SET. THE DATA IS SCALED
\ AND THEN SENT TO THE CONSOLE DISPLAY.
\ TO DO AN FFT ON THE DATA ENTER "FFT"
\ TO DISPLAY FFT COMPLEX RESULTS ENTER "SHOW_DATA"
\ TO CREATE TEST DATA ENTER "n k TEST_DATA" EG "3 1 TEST_DATA"
\ ABOVE EXAMPLE PUTS AN IMPULSE IN BIN 1 AND 0s
\ ELSEWHERE FOR A TOTAL OF 8 SAMPLES. FFT SHOULD GIVE A COMPLEX
\ EXPONENTIAL OF 1 CYCLE. NB TYPING SHOW_DATA BEFORE FFT WILL
\ SHOW THE DATA IN BIT REVERSED ORDER. IN THIS EXAMPLE BIN 4
\ ONLY WILL BE NON ZERO (AS 4 = 100 <--> 001 = 1)
\ TYPING CLEAR WILL CLEAR THE PROGRAM MEMORY
MARKER CLEAR
HEX
0 RANGE_SET
\ SOME UTILITY ROUTINES NOT USED IN FFT
: .S ( -- )
\ NON-DESTRUCTIVE STACK PRINT
DEPTH ?DUP
IF 0 DO DEPTH 1 - I - PICK U. LOOP
THEN ." --" ;
: SHOW_POWER
\ PUTS BATTERY VOLTAGE ON LCD DISPLAY
RCX_POWER DUP 4001 POWER_GET @
55EA 30C */
3002 SWAP 3001 LCD_NUMBER LCD_REFRESH
;
\ FFT SPECIFICS START HERE
\ VALUES N AND 2^N
0 VALUE N
1 VALUE N2
\ RESERVE STORAGE FOR 256 COMPLEX VALUES
CREATE FFT_DATA 200 CELLS ALLOT
: BITREV
\ BIT REVERSAL ( K -- REV )
\ ( K -- K REV B1 B2)
0 1 N2 2 /
\ LOOP BITS 0 TO N-1 ( -- )
N 0 DO
\ ( K REV B1 B2 -- K REV B1 B2 F )
3 PICK 2 PICK AND
\ INCREMENT REVERSED BITS
IF ( F -- )
\ ( REV B1 B2 -- REV B1 B2 B2+REV )
DUP 3 PICK +
\ ( REV B1 B2 B2+REV -- B2+REV B2 REV B1 )
SWAP 2SWAP
\ ( B2+REV B2 REV B1 -- B2+REV B1 B2 )
ROT ROT DROP
THEN
\ UPDATE BIT VALUES ( B1 B2 -- 2*B1 B2/2 )
2 / SWAP 2 * SWAP
LOOP
\ ( K REV B1 B2 -- REV )
2DROP SWAP DROP
;
\ FFT COEFFICIENTS AKA TWIDDLE FACTORS EXP(-2 Pi i K / 256) K = 0 TO 63
\ COMPLEX CONJUGATES SCALED *-32768
\ COEFF FOR K >= 64 IS -RI RR WHERE COEFF(K-64) = RR RI
DECIMAL
CREATE RHO
-32768 , 0 , -32758 , -804 , -32729 , -1608 , -32679 , -2411 ,
-32610 , -3212 , -32522 , -4011 , -32413 , -4808 , -32286 , -5602 ,
-32138 , -6393 , -31972 , -7180 , -31786 , -7962 , -31581 , -8740 ,
-31357 , -9512 , -31114 , -10279 , -30853 , -11039 , -30572 , -11793 ,
-30274 , -12540 , -29957 , -13279 , -29622 , -14010 , -29269 , -14733 ,
-28899 , -15447 , -28511 , -16151 , -28106 , -16846 , -27684 , -17531 ,
-27246 , -18205 , -26791 , -18868 , -26320 , -19520 , -25833 , -20160 ,
-25330 , -20788 , -24812 , -21403 , -24279 , -22006 , -23732 , -22595 ,
-23170 , -23170 , -22595 , -23732 , -22006 , -24279 , -21403 , -24812 ,
-20788 , -25330 , -20160 , -25833 , -19520 , -26320 , -18868 , -26791 ,
-18205 , -27246 , -17531 , -27684 , -16846 , -28106 , -16151 , -28511 ,
-15447 , -28899 , -14733 , -29269 , -14010 , -29622 , -13279 , -29957 ,
-12540 , -30274 , -11793 , -30572 , -11039 , -30853 , -10279 , -31114 ,
-9512 , -31357 , -8740 , -31581 , -7962 , -31786 , -7180 , -31972 ,
-6393 , -32138 , -5602 , -32286 , -4808 , -32413 , -4011 , -32522 ,
-3212 , -32610 , -2411 , -32679 , -1608 , -32729 , -804 , -32758 ,
HEX
: @RHO
\ RETRIEVE THE Kth TWIDDLE FACTOR ( K -- RR RI )
DUP 40 <
IF
2 * CELLS RHO + 2@ SWAP
ELSE
40 - 2* CELLS RHO + 2@ SWAP NEGATE SWAP
THEN
;
: C*8000/
\ COMPLEX MULTIPLICATION WITH /Q Q=-32768 ( XR XI RR RI -- YR YI )
\ RR RI IS COMPLEX CONJ SO RI TERMS SIGN CHANGED
( XR XI RR RI -- XR XI RR RI XR*RR/Q )
3 PICK 2 PICK 8000 */
( XR XI RR RI XR*RR/Q -- XR XI RrhoR RI XR*RR/Q+XI*RI/Q)
3 PICK 2 PICK 8000 */ +
\ APPROX CORRECTION +1 FOR FRACTIONAL PARTS ( -- )
1 +
( XR XI RR RI YR -- XR XI RR RI YR XI*RR/Q )
3 PICK 3 PICK 8000 */
( XR XI RR RI YR XI*RR/Q -- XR XI RR RI YR XI*RR/Q-XR*RI/Q )
5 PICK 3 PICK 8000 */ -
\ APPROX CORRECTION +1 FOR FRACTIONAL PARTS ( -- )
1 +
( XR XI RR RI YR YI -- YR YI )
2SWAP 2DROP 2SWAP 2DROP
;
: BUTTERFLY
\ ( XR XI YR YI -- (XR+YR+1)/2 (XI+YI+1)/2 (XR-YR+1)/2 (XI-YI+1)/2 )
\ ( XR XI YR YI -- XR XI YI YR -- XR YR XI YI)
SWAP ROT ROT
\ ( XI YI -- (XI+YI+1)/2 (XI-YI+1)/2 )
OVER OVER + 1+ 2/ ROT ROT - 1+ 2/
\ 2SWAP AND REPEAT
( XR YR XI+YI XI-YI -- XI+YI XI-YI XR YR -- XI+YI XI-YI -- XR+YR XR-YR )
2SWAP OVER OVER + 1+ 2/ ROT ROT - 1+ 2/
( XI+YI XI-YI XR+YR XR-YR -- XR+YR XI+YI XR-YR XI-YI )
ROT 2SWAP SWAP 2SWAP
;
DECIMAL
: TEST_DATA
\ CREATE TEST DATA FOR N POINT FFT 0'S EXCEPT 100 100 AT K ( N K -- )
\ STORE N CALC 2^N AND STORE ( N K -- K )
SWAP DUP TO N 1 TO N2 0 DO N2 2 * TO N2 LOOP
\ BIT REVERSAL ( K -- K )
BITREV
FFT_DATA ( K -- K addr )
N2 0 DO ( -- )
( K addr -- K addr addr )
DUP I 2 * CELLS +
( K addr addr -- K addr addr K I -- K addr addr F )
2 PICK I =
IF ( K addr addr F -- K addr addr )
( K addr addr -- K addr addr 100 200 )
100 100
ELSE
( K addr addr -- K addr addr 0 0 )
0 0
THEN
( K addr addr X1 X2 -- K addr )
SWAP ROT 2!
LOOP
( K addr -- )
2DROP
;
HEX
: SHOW_DATA
\ PRINT OUT FFT DATA (USES N2)
DECIMAL
FFT_DATA ( -- addr )
N2 0 DO
I . DUP @ . CELL+ DUP @ . CR CELL+
LOOP
DROP ( addr -- )
HEX
;
: FFT
\ 2^N POINT FFT
\ USES APPARENT NON-STANDARD 2@ RETURNING X2 X1
\ (A FOLLOWING SWAP IS NEEDED)
\ ALSO NON-STANDARD 2! STORES X1 X2 AS X2 X1
\ N IN N, 2^N IN N2, REAL AND IMAG DATA AT FFT_DATA, COEFFS AT RHO
\ BUTTERFLY DEPTH D=2^I NUMBER OF BUTTERFLY SEQUENCES B=2^N/D/2
\ N BUTTERFLY PASSES
1 N2 2 / ( -- D B )
N 0 DO ( -- )
\ LOOP OVER B BUTTERFLY SEQUENCES
DUP 0 DO ( D B -- D B )
\ LOOP OVER D BUTTERFLIES IN SEQUENCE
OVER 0 DO ( D B -- D B )
\ ADDRESS OF UPPER I/P TO BUTTERFLY R+I ENTRY 2*D*J+I
\ ( D B -- D B D -- D B 2*{2*D*J+I} -- D B addr-u )
OVER 2 * J * I + 2 * CELLS FFT_DATA +
\ FETCH UPPER INPUT
\ ( addr-u -- addr_u XR XI )
DUP 2@ SWAP
\ ADDRESS OF LOWER I/P TO BUTTERFLY R+I ENTRY 2*D*J+I+D
\ ( D B addr-u XR XI -- D B XR XI addr-u addr-l )
ROT DUP 5 PICK 2 * CELLS +
\ FETCH LOWER INPUT
\ ( XR XI addr-u addr-l -- addr-u addr-l XR XI YR YI )
2SWAP 2 PICK 2@ SWAP
\ FETCH TWIDDLE FACTOR RHO^(B*I) AT RHO INDEX K=(B*I*256/N2)
\ ( D B addr-u addr_l XR XI YR YI --
\ D B addr-u addr_l XR XI YR YI RR RI )
6 PICK I * 100 N2 */ @RHO
\ COMPLEX MULT WITH CONJ AND SCALING ( YR YI RR RI -- YR YI )
C*8000/
\ BUTTERFLY WITH /2 ( XR XI YR YI -- XR+XR XI+XI XR-YR XI-YI )
BUTTERFLY
\ STORE - RESULT
\ ( addr-u addr_l XR+YR XI+YI XR-YR XI-YI
\ -- addr-u addr_l XR+YR XI+YI )
SWAP 4 PICK 2!
\ STORE + RESULT ( addr-u addr_l XR+YR XI+YI -- )
SWAP 3 PICK 2! 2DROP
LOOP
LOOP
\ UPDATE B AND D ( D B -- D*2 B/2 )
2 / SWAP 2 * SWAP
LOOP
( D B -- )
2DROP
;
: SAMPLE ( N -- )
\ REQUIRES N ON STACK INITIALLY
\ SOUND UP
3 4003 SOUND_PLAY
\ CONFIGURE LIGHT SENSOR SCALE 0-100
3 1 SENSOR_TYPE
80 1 SENSOR_MODE
\ STORE N ( N -- N N -- N )
DUP TO N
\ CALCULATE 2^N AND STORE IT ( N -- )
1 TO N2 0 DO N2 2 * TO N2 LOOP
\ GET 2^N LIGHT SAMPLES AT 1 MSEC INTERVALS OFFSET -50
\ FACTOR * 320 AND STORE IN BIT REVERSED ORDER
\ DUMMY LIGHT SAMPLE TO CLEAR REGISTER (?)
1 SENSOR_READ DROP 1 SENSOR_VALUE DROP
\ GET CURRENT MS TIMER ( -- T1 )
EFD0 C@
\ WAIT TILL IT TICKS ON
BEGIN
( T1 -- T1 T2 -- T2 T1 -- T2 T1 T2 -- T2 F )
EFD0 C@ SWAP OVER = INVERT
( T2 F -- T2 )
UNTIL
N2 0 DO
\ CHECK MS TIMER NOT TICKED ON ALREADY IF IT HAS SOUND DOWN
( T1 -- T1 T2 -- T2 T1 -- T2 T1 T2 -- T2 F )
EFD0 C@ SWAP OVER = INVERT
( T1 F -- T1 )
IF
2 4003 SOUND_PLAY
THEN
\ WAIT TILL MS TIMER TICKS ON
BEGIN
( T1 -- T1 T2 -- T2 T1 -- T2 T1 T2 -- T2 F )
EFD0 C@ SWAP OVER = INVERT
( T2 F -- T2 )
UNTIL
( -- LIGHT )
1 SENSOR_READ DROP 1 SENSOR_VALUE 32 - 140 *
\ PUT SAMPLE IN IMAG TERM ( SAMPLE -- SAMPLE )
I 2 * 1 + CELLS FFT_DATA + !
LOOP
\ DROP TIMER ( T1 -- )
DROP
\ FURTHER LOOP TO WINDOW AND DO BIT REVERSAL
N2 0 DO
\ FETCH SAMPLE FROM IMAG TERM ( -- SAMPLE )
I 2 * 1 + CELLS FFT_DATA + @
\ PRINT OUT UNWINDOWED SAMPLES IN NORMAL ORDER REPLACING BY ZEROS
( SAMPLE -- SAMPLE )
DUP DECIMAL I . . CR HEX I 2 * 1 + CELLS FFT_DATA + 0 SWAP !
\ HAMMING WINDOW 0.54 - 0.46 COS (2 PI I / 2^N)
\ 0.54*32768 = 17695 = HEX 451F SIMILARLY 0.46 --> HEX 3AE1
\ COS COEFFS SCALED BY -32768 ARE IN RHO INDEX I * 256 / 2^N
\ (MIRRORED FOR I > 255 SO USE ABS(I-N2/2) * 256 / N2) AND NEG
( -- -0.46*32768 )
-451F
( -- ABS{I-N2/2}*256/N2 )
I N2 2 / - ABS 100 N2 */ DUP 7F > IF DROP 7F THEN
( idx -- COS*32768 )
@RHO DROP
( COS*32768 -- -0.54*COS*32768 -- {-0.46+0.54*COS}*32768 )
3AE1 8000 */ -
( SAMPLE WINDOW -- SAMPLE)
8000 */
\ BIT REVERSAL ( SAMPLE -- SAMPLE REV )
I BITREV
\ STORE SAMPLE AS REAL
\ ( SAMPLE REV -- SAMPLE addr -- )
2 * CELLS FFT_DATA + !
LOOP
;
|
|
Message has 2 Replies:
3 Messages in This Thread:
- Entire Thread on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
|
|
|
|