text: Welcome to the Parallax Discussion Forums, sign-up to participate.
  \ ###########################################################
  \ # str>bt -- Send string to BT terminal
  \ # Uses fds.fth
  \ # To use enter name of string variable (svn) then str>bt
  \ # element [0] must contain string length
  \ #
  \ # Example below uses the string 'greeting'
  \ # Type: greeting str>bt <ret>
  \ # The words between these comments and str>bt are not needed
  \ # if the string variable is defined elsewhere.
  \ #############################################################
  : place over over >r >r char+ swap chars cmove r> r> c! ; \ st const to st variable
  : length$ count swap drop ;
  create greeting 64 chars allot \ define string greeting
  s" Hello! This is bluetooth. " greeting place \ make string variable
  greeting length$ greeting C! \ get string length & store
  : str>bt ( string name with length in zero element -- )
  9 8 0 115200 fds_start ( rxpin txpin mode 115200 -- cognum )
  drop ( str variable name )
  2dup c@ ( svn svn cnt )
  1+ 1 do ( svn svn )
  i + c@ fds_tx ( svn )
  dup ( svn svn )
  2drop
  13 fds_tx ( send CR )
  100 ms ( wait before stopping )
  fds_stop
  500 ms ( seems to minimize extra chars )
  1 30 lshift dira! ( turns terminal back on )
  ;
  \ ####################################################
  \ # bt>str - get string from bluetooth
  \ # Uses fds.fth
  \ # String is returned in bt$, length is in bt$[0]
  \ # Max length = 80 chars, ends input or
  \ # Carriage return ends input
  \ ####################################################
  create bt$ 81 chars allot
  : bt>str \ get a string from bluetooth, carrige return ends string input
  \
  9 8 0 115200 fds_start ( rxpin txpin mode 115200 )
  drop 0 bt$ c!
  begin
  fds_rx \ have ascii value
  dup 13 <> bt$ c@ 80 < and \ end on CR or on 80 char line
  while ( ascii )
  bt$ c@ 1 + bt$ c! bt$ bt$ c@ + c!
  repeat
  drop
  200 ms
  fds_stop
  300 ms
  1 30 lshift dira! ( turns terminal back on )
  ;
  Dave Hein wrote: »
  You're using do...next instead of do...loop. It should be do...loop or for...next. Maybe someday I'll add some error checking to the interpreter to check for matched words, but most Forth interpreters don't check for that, at least not on the Prop.
  Dave Hein wrote: »
  I derived the definitions for the for/next words from the do/loop words so they are very similar. do/loop is actually wrapped in an if..then pair so I could also pair the ?do word with loop. The if word compiles to jmp0, and the then word write the address after it to the word after _jmp0. The address just after the _jmp0 word is put on the stack during compilation, and the loop takes it off the stack. The next word doesn't use this address, so it was being left on the stack. I hope that isn't too much information, but I believe that's what was happening.
  create cgstk_btgb 80 allot
  create cgrtn_btgb 80 allot
  create cgcfg_btgb
  ' bluergb >body ,
  cgstk_btgb ,
  cgstk_btgb ,
  cgrtn_btgb ,
  cgrtn_btgb ,
  \ # words for starting
  : gocogbluergb forth @ cgcfg_btgb cognew dup cgnum_btgb ! ( red, blue, green Leds )
  10 ms ." 'bluergb' started in cog number " . ." , cogid stored in cgnum_btgb" cr ;
  : gobtrgbcog 0 cgnum_btgb ! go1cog gocogbluergb ; \ start bluetooth rbg
  twm47099 wrote: »
  What is in each cog? What is running in each cog?
  dat
  pfthconfig long @xboot_1+Q ' Initial word to execute
  long @stack+Q+16 ' Starting stack pointer
  long @stack+Q+16 ' Empty stack pointer value
  long @retstk+Q ' Starting return pointer
  long @retstk+Q ' Empty return pointer value
  create cgcfg_btgb
  ' bluergb >body ,
  cgstk_btgb ,
  cgstk_btgb ,
  cgrtn_btgb ,
  cgrtn_btgb ,
  twm47099 wrote: »
  What limits the size of the code that I can start in a separate cog?
  Loopy Byteloose wrote: »
  The real beauty of having 8 cogs is that you not only can run separate tasks simultaneously, but you that the tasks can stop running and free the cog for something completely different. Unlike preemptive multitasking that bumps one task to do another; you don't preempt. As long as your programming scheme doesn't use up all the available cogs, you march through a lot of multitasking without waiting for a turn..
  33 - 1 swap lshift outasetbit
  decimal
  : carray \ declare: #chars carray variable_name
  CREATE chars ALLOT \ to store or fetch from an element: ele# variable_name ! or @
  DOES> ( i -- 'char) SWAP chars + ;
  decimal
  variable cgnum_bjoy2
  variable butval
  variable bflg
  variable bflg2
  8 carray bt$
  : bluejoy2 \ works to get button or joystick code, decode it and use it
  \ JS controls rbgled, buttons control QS Leds
  \ and repeats until quit button (B4) in app is pressed
  0 bflg ! 1 bflg2 !
  16711680 outaclrbit \ sets QS Led pins to 0
  9 8 0 115200 fds_start ( rxpin txpin mode 115200 )
  drop 10 ms
  begin
  begin
  fds_rx 2 = until \ stall until STX (2) is received
  fds_rx 10 ms 2 bt$ c!
  2 bt$ c@ 55 < \ if byte 2 is 55 or 56 quit button (button 4) was pressed
  while
  2 bt$ c@ 3 < \ if byte 2 is < 3 that means x MSB Joystick word to use x and y
  rgbbox \ converts x & y to R B G hundreths increments
  \ ****** End of word to use x and y
  else \ byte 2 >= 3 means byte from button press & only that byte is data
  ( button code goes here, )
  16711680 dirasetbit \ set QS Leds to output
  16711680 outaclrbit \ turn off all
  2 bt$ c@ ( bt$2 )
  dup \ only need for btval ! below can delete both
  33 - 1 swap lshift outasetbit \ turn on led corresponding to button code
  0 bflg ! 5 ms
  begin bflg2 @ until 5 ms
  0 butval ! butval ! ( this takes a number of reads in other cogs to stabilize? )
  10 ms
  1 bflg ! 5 ms
  \ drop \ if button value is not used drop it
  ( end of button code )
  then
  repeat
  500 ms \ give it time to send -may not be needed here
  fds_stop
  1 30 lshift dira! \ turns terminal back on
  cgnum_rbgt @ cogstop \ stop rgbledtest's cog
  cgnum_bjoy2 @ dup 0 > if
  cogstop \ stop bluejoy2's cog
  else drop
  then
  ;
  create cgstk_bjoy2 80 allot
  create cgrtn_bjoy2 80 allot
  create cgcfg_bjoy2
  ' bluejoy2 >body ,
  cgstk_bjoy2 ,
  cgstk_bjoy2 ,
  cgrtn_bjoy2 ,
  cgrtn_bjoy2 ,
  \ # words for starting
  : gocogbluejoy2 forth @ cgcfg_bjoy2 cognew dup cgnum_bjoy2 ! ( starts the BT cog )
  10 ms ." 'bluejoy2' started in cog number " . ." , cogid stored in cgnum_bjoy2" cr ;
  : gobluejoy2 0 cgnum_bjoy2 ! go1cog gocogbluejoy2 ; \ go1gog starts rbg cog
  : .butv \ For printing butval - run from keyboard
  begin bflg @ until
  5 ms 0 bflg2 !
  5 ms butval @ . cr
  1 bflg2 ! 5 ms ;
  else \ byte 2 >= 3 means byte from button press & only that byte is data ( button code goes here, )
  ( button code goes here, )
  16711680 dirasetbit \ set QS Leds to output
  16711680 outaclrbit \ turn off all
  2 bt$ @ dup case
  49 of 33 - 1 swap lshift outasetbit endof
  50 ... ( continue of statements for 50, 51, 52, 53, 54 )
  endcase
  : .butv begin bflg @ until 5 ms \ by stopping bluejoy2 cog bflg is printed correctly
  fds_stop
  1 30 lshift dira! \ turns terminal back on
  cgnum_bjoy2 @ cogstop
  0 bflg2 ! 5 ms butval @ dup . 1 bflg2 ! 5 ms \ False flag, print butval, True flag
  48 -
  case \ test "case"
  1 of ." button 1 on " cr endof
  2 of ." button 1 off " cr endof
  3 of ." button 2 on " cr endof
  4 of ." button 2 off " cr endof
  5 of ." button 3 on " cr endof
  6 of ." button 3 off " cr endof
  endcase
  gocogbluejoy2 \ restart bluejoy2 cog
  ;
  : .btv \ by stopping bluejoy2 cog bflg is printed correctly
  begin bflg @ until 5 ms \ wait until other cog finishes storing, then stop other cog
  fds_stop
  1 30 lshift dira! \ turns terminal back on
  cgnum_bjoy2 @ cogstop \ completes stopping of other cog
  0 bflg2 ! 5 ms butval @ dup . \ False flag, print butval
  1 bflg2 ! 5 ms \ Tell other cog ok to STORE
  48 - dup . cr
  dup 1 =
  if
  ." button 1 on " cr
  else dup 2 = if ." button 1 off " cr
  else dup 3 = if ." button 2 on " cr
  else dup 4 = if ." button 2 off " cr
  else dup 5 = if ." button 3 on " cr
  else dup 6 = if ." button 3 off " cr
  then then then then then then
  drop 10 ms
  gocogbluejoy2 \ restart bluejoy2 cog
  ;
  ( rgbcathv100.fth Uses Common Cathode RBG Led )
  \ # Method uses 1 ctr and 1 cog and time shares (3ms) each color
  \ # 'go1cog' to start and adjust color intensities (see below)
  \ # 'stop1cog' to stop
  \ #
  \ # Can Input values for each color using variables to pass values
  \ # - After counter is running and terminal shows 'ok',
  \ # then enter decimal integer value from 1 to 10 and 'rv', 'bv', or 'gv'.
  \ # These defined words take the value, scale it, and store it in
  \ # 3 variables rval, bval, or gval. The running cog fetches the variable and
  \ # stores it in frqx.
  \ #
  \ # Can use more than d 10 steps for each color
  \ # For 20 steps store BFFF333 in r10th, b10th, and g10th
  \ # For 100 steps store 26663D7 in r100th, b100th, and g100th
  \ # and use rvh, bvh, and gvh
  \ #
  \ # RGBBOX is the word to translate a 2D joystick input (x = -100 to 100, y = -100 to 100)
  \ # into x, y, z values ( 0 to 100 ) that are input to rvh, bvh, gvh
  \ #
  \ # (c) T. Montemarano 2014, MIT License
  \ #######################################################################
  decimal
  12 constant redpin \ anodes on three pins
  13 constant blupin
  14 constant grnpin
  variable rval \ used to transfer intensity values for frqx between cogs
  variable gval
  variable bval
  6 26 lshift redpin + constant rctra \ values for dutycycle-se ctrx for each color
  6 26 lshift blupin + constant bctra
  6 26 lshift grnpin + constant gctra
  1 redpin lshift constant rdira \ values for dira for each color
  1 blupin lshift constant bdira
  1 grnpin lshift constant gdira
  hex
  17ffe666 constant r10th \ 1/10 of max - min for intensity
  17ffe666 constant g10th \ can change to balance colors
  17ffe666 constant b10th \ or to increase number of steps
  \ -------- Words for interactive intensity adjustment
  : rv r10th * dup rval ! .x ; \ calcs, stores & prints rval
  : bv b10th * dup bval ! .x ;
  : gv g10th * dup gval ! .x ;
  26663d7 constant r100th \ 1/100 of max - min for intensity
  26663d7 constant g100th \ can change to balance colors
  26663d7 constant b100th \ or to change number of steps
  : rvh r100th * rval ! ; \ for 1/100 increments, does not print value
  : bvh b100th * bval ! ; \ these words are primarly for BLUEJOY
  : gvh g100th * gval ! ;
  \ --------
  : rbgledtest ( starts 1 cog and 1 ctr to run red, blue, and green )
  77ff7ffe dup rval ! \ This starts all at mid brightness
  dup bval !
  gval !
  begin ( start endless loop for timesharing each color on 1 ctr )
  \ --------------- Turn on red
  gdira diraclrbit \ set green pin to input
  rval @ frqa! \ load red intensity setting into frqa
  rctra ctra! \ set ctra to red pin
  rdira dirasetbit \ turn on red - set red pin to output
  3 ms \ keep on for 3ms
  \ --------------- Turn on blue
  rdira diraclrbit \ set red pin to input
  bval @ frqa! \ load blue setting in frqa
  bctra ctra! \ set ctra to blue pin
  bdira dirasetbit \ turn on blue - set blue pin to output
  3 ms
  \ --------------- Turn on green
  bdira diraclrbit
  gval @ frqa!
  gctra ctra!
  gdira dirasetbit
  3 ms
  again
  ;
  \ # Set up for starting words in new cogs from Dave Hein
  decimal
  create cgstk_rbgt 80 allot
  create cgrtn_rbgt 80 allot
  variable cgnum_rbgt
  create cgcfg_rbgt
  ' rbgledtest >body ,
  cgstk_rbgt ,
  cgstk_rbgt ,
  cgrtn_rbgt ,
  cgrtn_rbgt ,
  \ # words for starting
  : gocogrbgtest forth @ cgcfg_rbgt cognew dup cgnum_rbgt ! ( red, blue, green Leds )
  ." 'rbgledtest' started in cog number " . ." , cogid stored in cgnum_rbgt" cr ;
  : go1cog gocogrbgtest ; \ start rbgledtest in new cog
  : stop1cog cgnum_rbgt @ cogstop ; \ stop rbgledtest & free cog
  : bb 16 lshift dup bval ! .x cr ; \ these 3 words directly enter values for FRQA to
  : gg 16 lshift dup gval ! .x cr ; \ check min and max values and determine increment to use
  : rr 16 lshift dup rval ! .x cr ; \ in R(GB)10th and R(GB)100th
  decimal
  : rgbbox ( x y -- calcs z, scales and calls rvh, bvh, gvh )
  \ x and y on stack range from -100 to +100
  100 + swap 100 + ( y' x' )
  2 / gvh dup 2 / rvh 2 / 100 swap - bvh
  ;
  \ #########################################################################
  \ # BLUEJOY3
  \ # Uses Android Bluetooth JS Commander to control devices.
  \ # This version uses button value to select function.
  \ # Button 1 - RBG Led color mix
  \ # Button 2 - Std Servo
  \ # Button 3 - Reserved (probably CR servos)
  \ # The buttons also turn on QuickStart Leds 16 - 23
  \ # The app sends the following:
  \ # For button press: 3 chars STX(2), Button value(49-56), ETX(3)
  \ # For Joystick:
  \ # 6 chars: STX, xMSB, xLSB, yMSB, yLSB, ETX.
  \ # The values in app are -100 to +100 for x and y.
  \ # When received the values need to be decoded.
  \ # Decode x and y by left shifting MSB 7 bits, adding to LSB, and subtracting 200.
  \ # Results in x & y values from -100 (x-left or y-down) to +100 (x-right, y-up).
  \ # A number can be sent to the app. The sending format is: STX, Button, Data, ETX
  \ # General format is
  \ # For this word Button = 0, Data = value + 4. (All buttons on, data = mode )
  \ # Forth code used is: 2 fds_tx 0 fds_tx funflg @ 4 + fds_tx 3 fds_tx
  \ #
  \ # RGBCATH.FTH uses a common cathode RBG Led with pins: Red (12), Blue (13), Green (14)
  \ #
  \ # Note CARRAY. It results in a string array being used as ELE# VARNAME @ or !
  \ # without requiring explicit adding the element number to the base.
  \ # However, the element number is REQUIRED for all elements including the zero element.
  \ #
  \ # Before Loading this -- 1. INCLUDE FDS.FTH,
  \ # 2. INCLUDE RGBCATH.FTH
  \ # Then Copy & Paste code from ( servobt ) to end
  \ #
  \ # To Start enter GOBLUEJOY3 starts go1cog, servobt, and bluejoy3.
  \ # Starts in RBG Led mode.
  \ # To Stop press Button 4
  \ #
  \ ##########################################################################
  \ ##########################################
  \ # SERVOBT
  \ # Controls one servo using android Bluetooth JS Commander
  \ # and BLUEJOY3
  \ # Connect BT - set JS - box, 50ms refresh, timeout off
  \ # Servo follows as JS is swiped horizontally
  \ #################################################
  ( servobt )
  decimal
  variable serval \ Servo pulse width in micro-sec
  variable serflg \ 1 = continue, 0 = stop cog
  11 constant serpin \ Servo is using pin 11
  : servobt ( cycles a servo using CTRa controlled by BT JS )
  clrctrcmd
  ctrncose setctrmode
  serpin setctrapin
  1 frqa! ldctra
  1 serpin lshift dirasetbit
  -600 microsec serval !
  1 serflg !
  begin
  serflg @ while
  serval @ phsa!
  20 ms
  repeat
  xctra
  cogid 0 > if cogid cogstop then \ if run in a new cog release the cog
  ;
  create cogstack8 80 allot
  create cogreturn8 80 allot
  variable cognum8
  create cogconfig8
  ' servobt >body ,
  cogstack8 ,
  cogstack8 ,
  cogreturn8 ,
  cogreturn8 ,
  \ This word starts a cog running the SERVOBT word
  : goservobt ( -- ) forth @ cogconfig8 cognew dup cognum8 !
  ." 'servobt' started in cog number " . ." cogid stored in cognum8" cr ;
  : xy>servo ( x y -- ) \ xy from JS to servo pulse width (spw),
  \ only need x, x is -100 to +100
  \ make x=0 to 200 then want spw = 2120 to 520 us )
  drop 100 + 8 * 2120 swap - -1 * microsec serval !
  ;
  : xx xy>servo serval @ dup . ." " 80 / . cr ; \ for testing
  ( bluejoy3 )
  decimal
  : carray \ declare: #chars carray variable_name
  CREATE chars ALLOT \ to store or fetch from an element: ele# var_name ! or @
  DOES> ( i -- 'char) SWAP chars + ;
  decimal
  variable cgnum_bjoy3
  variable butval
  variable funflg
  8 carray bt$
  : bluejoy3 \ works to get button or joystick code, decode it and use it
  \ JS controls rbgled and servo, buttons set mode and control QS Leds
  \ and repeats until quit button (B4) in app is pressed
  1 funflg ! \ set mode to RBG Led at start
  16711680 outaclrbit
  9 8 0 115200 fds_start ( rxpin txpin mode 115200 )
  drop 10 ms
  2 fds_tx 0 fds_tx funflg @ 4 + fds_tx 3 fds_tx \ send mode# 1, 2, or 3 to android
  5 ms
  fds_rx fds_rx drop drop \ get rid of the android response to the sent bytes on startup
  \ then resend same mode command to android, since no button change android will not echo
  2 fds_tx 0 fds_tx funflg @ 4 + fds_tx 3 fds_tx \ send mode# 1 to android
  begin
  begin \ stall until STX (2) is received
  fds_rx 2 =
  until
  fds_rx 10 ms 2 bt$ c!
  2 bt$ c@ 56 <> \ if byte 2 is 56 quit button was pressed
  while
  2 bt$ c@ 3 < \ if byte 2 is < 3 byte 2 is MSB of Joystick x-value words to use JS x and y ( x y onstack ) ******************
  funflg @ 1 = if
  rgbbox then \ converts x & y to R B G hundreths increments
  funflg @ 2 = if
  xy>servo then \ converts x to 0 - 180 deg for servo
  funflg @ 3 = if
  rgbbox then \ reserved for button 3, temp use for rgb
  \ ****** End of word calls to use JS x and y ***************************
  else \ byte 2 >= 3 means byte from button press & only that byte is data
  \ *** button code starts here, button value is in bt$ element 2, not on stack ****
  16711680 dirasetbit \ set QS Leds to output
  16711680 outaclrbit \ turn off all
  2 bt$ c@
  dup
  33 - 1 swap lshift outasetbit \ turn on led corresponding to button code
  0 butval ! butval !
  butval @ 48 - 2 /mod + funflg ! \ set JS mode ( 1=RBGLed, 2=Std Servo, 3=xxxx )
  10 ms
  2 fds_tx 0 fds_tx funflg @ 4 + fds_tx 3 fds_tx \ send mode# 1, 2, or 3 to android
  \ *** end of button code ***************************************************
  then
  repeat
  0 serflg ! \ ****** This line sets a flag=0 that tells SERVOBT to end
  fds_stop
  1 30 lshift dira! \ turns terminal back on
  cgnum_rbgt @ cogstop \ stop rgbledtest's cog
  cgnum_bjoy3 @ dup 0 > if
  cogstop \ stop bluejoy3's cog
  else drop
  then
  ;
  create cgstk_bjoy3 80 allot
  create cgrtn_bjoy3 80 allot
  create cgcfg_bjoy3
  ' bluejoy3 >body ,
  cgstk_bjoy3 ,
  cgstk_bjoy3 ,
  cgrtn_bjoy3 ,
  cgrtn_bjoy3 ,
  \ # words for starting
  : gobj3quiet ( silent start bluejoy3 cog )
  0 cgnum_bjoy3 ! go1cog goservobt forth @ cgcfg_bjoy3 cognew cgnum_bjoy3 ! 10 ms ;
  : gocogbluejoy3 forth @ cgcfg_bjoy3 cognew dup cgnum_bjoy3 !
  10 ms ." 'bluejoy3' started in cog number " . ." , cogid stored in cgnum_bjoy3" cr ;
  \ Word below starts rbg, servo, and bluejoy3
  : gobluejoy3 0 cgnum_bjoy3 ! go1cog goservobt gocogbluejoy3 ; \ start bluejoy3 in new cog
  : gobj3 go1cog goservobt bluejoy3 ; \ don't start newcog for bluejoy3
  repeat until not lockset(semID) ' ***Fix Wait for lock, set
  longmove(@minutes, @m, 3) ' Copy timestamp vars
  lockclr(semID) ' ***Fix Clear lock
  : lockret ( locknum ... ) 0cfc0005 cogx1 drop ;
  : lockset ( locknum -- previous set/unset condition ) 0c7c0006 cogx1 ;
  : lockclr ( locknum -- previous set/unset condition ) 0c7c0007 cogx1 ;
  create bt$ 241 chars allot
  : bt>str \ get a string from serial
  \
  9 8 0 9600 fds_start ( rxpin txpin mode 115200 ) ( I had to drop baud to 9600 to get complete data sets )
  drop 0 bt$ c!
  begin
  fds_rx \ have ascii value
  bt$ c@ 241 < \ end on 240 char
  while
  bt$ c@ 1 + bt$ c! bt$ bt$ c@ + c!
  repeat
  drop
  200 ms
  fds_stop
  300 ms
  1 30 lshift dira! ( turns terminal back on )
  ;
  #include <propeller.h>
  extern _Driver _FullDuplexSerialDriver;
  _Driver *_driverlist[] = {
  &_SimpleSerialDriver,
  NULL
  };
  I have a new question about some strange behavior I am seeing when I use the cut and paste method of loading new definitions into pfth.
  Loading some colon definitions result in a value being added to the stack. In other words starting with an empty stack, cutting and pasting some colon words (everything is between : and ; ) results in a value being printed if i type '.s'
  It seems that loading any definition that transmits a character using fds_tx leaves a value on the stack. The value seems to be an address. Loading definitions that only use fds_rx does not leave anything on the stack. Some examples below that I use to receive or transmit a string through Bluetooth.
  First the code that does leave a value on the stack. I've included some preliminary code that makes the string that will be transmitted. After I loaded the preliminary code, I checked the stack and it was empty. Then I loaded the colon definition str>bt and there was a value (d22356) on the stack.
  The follwing code gets a string from the bluetooth device. When I load that the stack is empty as expected. Right now all I do is add an imediate "drop" after the closing semi colon when I load definitions that leave a value on the stack. Any ideas whats happening?
  Thanks
  Tom
  Thanks, that was a pretty stupid mistake that I've copied to a number of words. Don't know how I missed it, (and kept missing it), but maybe it has something to do with my habit of coding at 3 AM. For some reason the code works, but that's probably why I was also getting an extra character printed to the regular terminal when I switched back from Bluetooth.
  Tom
  That does make sense. I also found that I had to change the starting index when I switched from 'do next' to 'do loop'. I appreciate the info you give re how you developed pfth. I'm trying to understand how the Prop works and learn a bit of PASM.
  Today's dumb question: What is happening at the Propeller level when I start a new cog in pfth? Some observations - I use the method you showed in an earlier post for each cog I open. For example the code below has a word 'gobtrgbcog' that starts 2 words, each in a different cog. (gocog1 starts a word 'rbgledtest' that controls an RGB Led in its own cog, and gocogbluergb starts a word 'bluergb' in its own cog) . I run rbgledtest in a separate cog so that I can enter keyboard commands that store values in R B G variables that are read by rbgledtest and set the intensities of the different colors. Running bluergb in its own cog allows the same thing except from a bluetooth terminal. I can actually enter the color values from either/both the Teraterm terminal or the BT terminal while the code is running in the 2 other cogs. I do make sure that the BT cog is stopped after I reset the terminal (fds_stop 1 30 lshift dira! ) but before the ending ; or else I lose control and have to reset.
  This is powerful, but confusing. Each of the words running in separate cogs are using words, constants, and variables that are defined before the new cog is started. The stacks for each cog are also defined outside of the cogs they are supporting.
  What is in each cog? What is running in each cog? What limits the size of the code that I can start in a separate cog?
  Thanks again,
  Tom
  Additional cogs use a configuration structure defined in the Forth dictionary, such as your example. The expression " ' bluergb >body " is used to get the address of list of execution tokens for bluergb. Possibly in a future version of pfth this will be simplified to just " ' bluergb ". The starting and empty values for the stacks are just set to the address given by cgstk_btgb and cgrtn_btgb. This is fine since there should be no chance of underflowing the stacks.
  The expression " forth @ cgcfg_btgb cognew " puts the addresses of the Forth kernel and the configuration structure on the stack, and then starts the cog with cognew.
  Note that the data stack could be preloaded with calling parameters prior to starting up a cog, which would require that the starting value be greater than the empty value.
  Since the word that is executed is located in hub RAM, the size is limited by the size of hub RAM. A separate cog can run a very small program, or it can run a large program that uses most of the 32K of RAM. All of the cogs can execute from the same dictionary words because these are only read from memory, and not modified.
  Any variables that are shared and modified by one or more cogs require some form of coordination among the cogs. The coordination could be as simple as allowing only one code to write to a variable, or could use locks to allow more than one cog to modify a variable..
  I didn't mention the code necessary to run limited duration tasks on an independent cog.
  It is quite simple, obviously you need to call COGSTOP. But you first have to call COGID from within the task so that COGSTOP will correctly know which cog to stop. Once you get the hang of this, pfth Forth becomes really powerful at getting high speed use of the Propeller.
  I have a problem with a pfth program I wrote that takes data from an android app that acts as a joystick and also has 4 buttons. It sends joystick values and button values via bluetooth. There was some discussion of it here:-***C***-and-a-nice-App
  The app and some info is here:
  The author had published an arduino sketch which gave the data format that was sent by the BT device.
  The format for buttons is 3 bytes: STX (2), 1-byte data, ETX (3). The data byte is a value from 49 to 56. Turning button 1 on = 49, Turning button 1 off = 50. Button 2 on = 51, Off = 52, continue for buttons 3 and 4.
  The format for Joystick is 6 bytes: STX, high byte x, low byte x, high byte y, low byte y, ETX.
  The Joystick values -100 to +100 for x and y are encoded so that a premature 3 won't occur.
  After receiving the value from BT, the x and y is decoded: x = (7 lshift(xHi ) + xLo) - 200 {same for y}
  I've been able to write a Simple IDE C program that reads the joystick and controls the colors of an RBG Led and controls a standard servo. It reads the button values and toggles the LEDs on the quickstart board.
  I've also written pfth words that uses fds.fth to receive the Joystick value from the BT app and also controls a servo or the RBG led and receives the button values and sets the QS leds.
  I run the bluetooth word and the RBG Led word (or servo word) in separate cogs.
  When running the RBG Led, the BT word puts x & y on the stack and calls a color calculating words. Those words store the r g b results into variables ( rval, bval, and gval). The RBG Led refreshing code (in its own cog) fetches rval, bval, and gval loads them into the counter frqa. I do something similar for the servo word. Both work well.
  But when I try to do the same with the button codes things don't work. I am able to take the button byte on the top of the stack and use this pfth routine in the BT word: to turn on the QS Led.
  But if I try to put it in a variable and use it in another cog, the value is not stable. Sometimes the value is the button value (49-56), other times it is a weird combination of digits or even just a blank. If I stop the program (pressing button 4 on the BT device ends the pfth program) and read the variable, it gives the correct value. I have also used an 80 byte string read routine to collect all the bytes sent by multiple button presses, and when I read the values out I see that the 3 byte reads (STX, val, ETX) are correct with no screwy values.
  I have tried using a '63 and' mask, but still can get 4 digit values. I suspect that there may be interference between the 2 cogs reading and writing the variable. I have tried to use flags to stop conflicts, and there has been a little improvement but not enough to be able to use the variable in another cog.
  I'd like to try to use locks. I see the "locknew" and "lockret" words in the propwords.fth file, but I don't see "lockset" or "lockclear". How would I use locks.
  I've included the BT word and the word that I use to try to print out the button value (.butv) below. This is my latest version with flags. I've tried adding time delays also. I'd appreciate any ideas.
  Thanks
  Tom
  1. After the lines: I added an if test for the bt$ + 2 greater than 48 and less than 55
  (with 'then' added before the existing then.) When I typed .butv sometimes it gave me a correct value and sometimes not.
  2. I tried adding a 'case' statement
  That didn't work at all, locked out the keyboard, and pressing buttons (including the quit button) did nothing. I had to reset.
  3. I added code to the ".butv" word that stopped fds and the bluejoy2 cog. Then printed "butval", tested a case statement and restarted the bluejoy2 cog. That worked. The new ".butv" word definition is:
  I still don't understand why the joystick values can be used in a different cog, but the button values can't be unless the BT cog is stopped??
  Tom
  I changed the case statements to a series of IF ELSE THEN statements as shown below, and that works.
  The RGB Led and servo control run in different cogs. I can run the bluetooth word in its own cog or in the main cog. Plus my version of pfth uses the SD card reader which takes an additional cog. I think that when the bluetooth code calls FDS another cog may be started, but I'm not sure. So that's 3 to 5 cogs being used.
  The RGB Led and servo use counters, so my counter words are "include"ed from the SD card. These words are shown in post 284 of this thread.
  The RGBLed code, servo code, and bluetooth code are listed below. The only interaction between the bluetooth code and RGBLed and Servo codes are the 1 word calls (RGBBOX and XY>Servo) in the Joystick part of the BT code, the 2 lines of code to stop the rgbled and servo code, and the words (GO1COG and GOSERVOBT) in the starting words (GOBLUEJOY3 or GOBJ3) so using the BT code to control other devices should be straight forward.
  Tom
  {delete this paragraph:
  It needs to be loaded before BLUEJOY3. It wasn't defined in my earlier utility words post. The definition is:
  : cs depth dup 0> if 0 do drop loop then ;
  Edit 4/29 -- I deleted the "cs" (clear stack) in the bluejoy3 definition above. I never like to clear the stack in a word. But the android app sends characters in response to code sent to it. When I added the line at the begining that sent the mode # 1 to the android device (to display), the transmission includes the buttons state. When there is a change in button state, the android app sends the button values back to the propeller. That resulted in a variable number of bytes coming into the forth program and an uncertain button state. The result was that the stack could fill with unused values. By adding a duplcate line sending the mode and button state fixes that, and I was able to get rid of the cs word.
  I am trying to learn to use LOCKS in pfth. The example I am basing my efforts on is in:
  Programming & Customizing the Multicore Propeller Microcontroller, page 97.
  The following spin code is used to prevent conflicts with a different cog while transferring minutes, seconds, ms from the cog that counts to the main cog that does something with the results.
  In the pfth propwords.fth file you have defined 'locknew' and 'lockret' but not lockset or lockclr.
  (I think there may be a typo in lockret which is defined as:
  Based on my reading of the PASM opcode lockret I think the hex value should be 0c7c0005, but since I have no experience with PASM, I could be mistaken.
  I would like to get some idea of how lockset and lockclr could be defined.and used.
  Again based on my lack of PASM knowledge I would guess that they could be defined as:
  A couple of questions:
  1. Am I correct in the hex opcodes?
  2. Am I correct on the return values?
  If not please HELP!
  Thanks, I really appreciate the effort you put into pfth and the help you have given.
  Tom
  I'll look into it myself, but I won't be able to work on it until sometime next week.
  Thanks. I looked at cog1funct in the spin file, and I have a lot to learn before I can even understand what the existing code is doing. I'm still working through the Prop Education Manual and the early chapters of Programming & Customizing the Multicore Propeller Microcontroller. One of the things I do is translate the spin programs into pfth words. I feel that if I can do that I understand what the Spin code is doing. I also find when writing new code that I can write pseudo code and more easily code that in pfth. Once I get the pfth words working I can translate them into Spin or C. (I find going directly from pseudo code into Spin and C is still somewhat difficult.) But I still have trouble following what a PASM routine is doing. But it is a goal.
  Tom
  One of the things I am working on now is interfacing the Pixy ( and ) vision sensor to the Propeller. The Pixy uses a hue-based color filtering algorithm to detect and track objects.
  Pixy has a number of possible interface connections including SPI (for direct connect to Arduino), I2C, UART, and DAC. The SPI, I2C, and UART can transmit data (signature number -- 1 to 7), x-position, y-position, object width, and object height) for a number of different objects. The objects are transmitted in a frame in priority of size order. Every 20ms the Pixy starts a new frame of objects and can transmit up to 135 objects per frame. At this point in time, I don't see any way to stop or start the data transmission in software.
  The DAC is much more limited. The Pixy can send out a voltage (0 - 3.3v) linearly proportional to the X or Y position (not both) of the largest object (only) that it has a color signature for. I have gotten that mode working in C (Simple IDE using the ADC on the Activity Board).
  I chose to use pfth for working with the UART since I can interactively collect data and then view / manipulate it as I choose. My experience with the UART (using FDS.fth are discussed here
  in posts 15 and 16.
  The format of the data is 7 or 8 words (LSB, MSB):
  1. 0x55, 0xaa - sync word starts a new block of data from an object. Two sync words signify the start of a new frame. A new frame can cancel the transmission of data for a block in progress.
  2. Checksum (sum of values from words 3 - 7.
  3. Color signature number (1 - 7)
  4. x position of center
  5. y position of center
  6. width
  7. height
  The code I am using to collect the values is here:
  After collecting 240 bytes into bt$ that word stops, and I just use another word to print out the value of each element in hex. Then I look for a 4 byte series ( 55, aa, 55, aa) to indicate the start of a new frame, and separate each block to see the quality of the data.
  Summarizing the posts I linked to, at 115,200 baud, I did not collect any whole blocks of data. Reducing the baud to 19200 ( the default of the Pixy, although the wiki states that it can go up to 230,000) I received some good blocks, but not a full frame. At that baud, I should be able to receive approx 3 blocks of data before a new frame starts. Reducing the baud to 9600 resulted in collecting good data. But the slow baud anly allows receiving 1 block per frame. The Pixy priority of sending means that only the block corresponding the the largest object will be transmitted.
  I recall you writing that you were working on a fast forth, and was wondering if if that was getting close to being issued, and if you thought it would be fast enough to capture more than 1 block of data using the code above.
  Some other questions:
  Do you have any suggestions for faster code in pfth in place of what I'm doing?
  Would SPI or I2C be any better (faster) than FDS?
  I generally use forth to help me figure out how to interface to something new. It almost seems like programming in psuedo code since I don't have to concern myself with all of the fine details of the other languages, but now that I understand what the Pixy is sending, I will write some code in Spin and C (Simple IDE) using their serial methods. Do you think they will be (could be) significantly faster?
  Thanks again for your help.
  Tom
  A tight loop in Spin code that call the RX method will max out at about 57600 baud. I've been able to achieve higher speeds with Spin by either using a larger receive buffer or by writing an RXBLOCK method that transfers blocks of data from the receive buffer using BYTEMOVE. I think C should be able to handle 115200 without any problems.
  I pursued the Fast Forth interpreter for a while, but I stopped working on it after testing in on the chess program, and it ran at about the same speed as pfth. I was able to achieve higher speeds with Fast on small tight loops, where it ran at about the same speed as Tachyon. I also wrote a Forth compiler for Fast that would fold small words into larger words, and improve performance that way. I may post an update on Fast at some point, but I've lost interest in pursuing it any further.
  Thanks for the response.
  Am I correct in assuming that when the fds receive buffer fills that any subsequent bytes are just lost, as opposed to replacing the bytes in the buffer?
  Also could I expect any increase in speed connecting using an I2C or SPI interface? (The Pixy has both).
  I wrote a short C program (using Simple IDE defaults) using the serial library function that just reads a value into an integer and then prints the value to the Simple IDE terminal. I was able to increase the baud to 19200 and get 3 to 4 blocks of data per frame, but with some occasional errors. At 14400 baud, I got 2 to 3 per frame without any errors.
  Tom
  PropGCC uses a simple serial driver by default. You would need to use _FullDuplexSerialDriver instead to handle higher rates. This is done by including the following code in your program.