To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.robotics.rcx.pbforthOpen lugnet.robotics.rcx.pbforth in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / RCX / pbFORTH / 628
627  |  629
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:
  Re: Getting started; FFT; millisecond timing
 
(...) Thanks, Patrick. I just took the plunge into pbForth and I was stuck. After downloading the firmware, I couldn't get Ralph's console nor Hyperterminal to give me an "OK" response. I couldn't figure out how to get to the Bricxcc pbForth (...) (20 years ago, 10-Oct-04, to lugnet.robotics.rcx.pbforth)
  Re: Getting started; FFT; millisecond timing
 
Thanks for your posting of 9 April 2004. It was very useful. Jordon (20 years ago, 15-Oct-04, to lugnet.robotics.rcx.pbforth)

3 Messages in This Thread:


Entire Thread on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact
    

Custom Search

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR