Shop OBEX P1 Docs P2 Docs Learn Events
Needm help converting a Basic Stamp program to the Propeller — Parallax Forums

Needm help converting a Basic Stamp program to the Propeller

jknightandkarrjknightandkarr Posts: 234
edited 2016-03-17 20:08 in Propeller 1
I need help converting a BS2 program to the Propeller. I have both the BS2 and Prop versions code below, I am at an impass on the BS2's */ command. BS2 editor states it multiples and returns the middle 16-bits of the variables and/or constants. The Propeller seams to have only * & ** Multiply and return lower or upper 32 bits. So far I have not gotten into stuff like this, so I am not able to figure out how to write the original 'GrafVal = (RawVal - LoScale) */ Scale' for use with the Propeller chip... The only idea I have is something like:
GrafVal := (RawVal-LowScale)
GrafVal := GrafVal * Scale
GravVal := GrafVal >> 8

But I am almost posative that won't do the same thing. Any suggestions? Thanks.

Original Code: Stamp Works V2.1.pdf, on pg41
' {$STAMP BS2}
' {$PBASIC 2.5}
'SW21-EX05-LED.BS2

LEDs      VAR OUTL
LEDsDIRs  VAR DIRL

Pot       PIN 15

DotGraf   CON 0
BarGraf   CON 1
GraphMode CON BarGraf
IsOn      CON 1
IsOff     CON 0
LoScale   CON 10
HiScale   CON 695
Span      CON HiScale - LoScale
Scale     CON $FFFF / Span

rawVal    VAR Word
GrafVal   VAR Byte
HiBit     VAR Byte
NewBar    VAR Byte

Reset:
  LEDsDirs = %11111111

Main:
  DO
    GOSUB Read_Pot
    GrafVal = (RawVal - LoScale) */ Scale
    GOSUB Show_Graph
    PAUSE 50
  LOOP

Read_Pot:
  HIGH Pot
  PAUSE 1
  RCTIME Pot, 1, RawVal
  RETURN

Show_Graph:
  HiBit = DCD (GrafVal / 32)
  IF (GraphMode = BarGraf) THEN
    NewBar = 0
    IF (GrafVal > 0) THEN
      DO WHILE (HiBit > 0)
        NewBar = NewBar << 1
        NewBar.BIT0 = IsOn
        HiBit = HiBit >> 1
      LOOP
    ENDIF
    LEDs= NewBar
  ELSE
    LEDs = HiBit
  ENDIF
  RETURN

Current Propeller version:
{{BS2 Bargraph.spin

Author:Joe R.
Version: 1.1 (March 6th, 2016
Updates: Ver 1.0-Original Release
             1.1-Added Values to adjust I/O Pins
             
Future Updates:-Add shift register support.
               -Add support for multiple pattern outputs for multiple
               bargraph displays.
               -Add multiple inputs. 1 for each bargraph display.
                                
Oridinal File: SW21-EX05-LED_Graph.BS2, Stamp Works Ver 2.1 Pg. 41
Discription: Creates a configurable dot or bar LED graph, such as one on a VU meter
or a digital non-numerical fuel or volt gauge display.
    
}}
CON

  _CLKMODE  = XTAL1 + PLL16X                            'Standard clock mode * crystal frequency = 80 MHz
  _XINFREQ  = 5_000_000

  DotGraf   = 0
  BarGraf   = 1
  GraphMode = BarGraf                                   'DotGraf or BarGraf
  IsOn      = 1 
  IsOff     = 0
  LowScale  = 10                                        'Low cap reading
  HighScale = 695                                       'High cap reading
  Span      = HighScale - LowScale                      '685 total cap range
  Scale     = $FFFF / Span                              '95=$FFFF/685
  Pot       = 12                                        'Input from RC network.
  
VAR

  WORD  RawVal                                          'Value from I/O Pins                                     '
  BYTE  HiBit, NewBar, GrafVal                                           '                                          '
  WORD  LEDs, LEDsDirs                                           '
  BYTE  LowDigitPin, HighDigitPin                       'The pins for specifying digits.
                                                        'Must be contiguous
                                                        'HighDigitPin can be from 0
                                                        'to 7 more than LowDigitPin
                                          '
PUB Settings(dLow, digits, s0, enabled)
'' Start the display
'' Parameters:
''   dLow - the pin number of the least significant digit
''   digits - the number of digits to display  (up to 8)
''   s0 - the pin number of segment 0
''   enabled - the initial enabled state
  LowDigitPin := dLow
  HighDigitPin := dLow + ((digits - 1) <# 16)           'Limit to 16 leds
  DIRA[LowDigitPin..HighDigitPin]~~                     'Set digit pins to outputs
  OUTA[LowDigitPin..HighDigitPin]~~                     'Turn off all digits
  DIRA[Pot]:=%1
  Start

PUB Start            

  REPEAT
    ReadPot
    grafVal := (rawVal - LowScale) */ Scale
    ShowGraph
    WAITCNT ((CLKFREQ/1000)*50+CNT)
  
PRI ReadPot

  OUTA[Pot]:=1
  WAITCNT (CLKFREQ/1000+CNT)
  RCTIME Pot, 1, rawValue
  RETURN

PRI ShowGraph

  HiBit:=|<(GrafVal/32)
  IF GrafVal=BarGraf
    NewBar:=0
    IF GrafVal>0
      REPEAT WHILE HiBit>0
        NewBar = NewBar << 1
        NewBar:=%000000000000001
        HiBit := HiBit >> 1
    ELSE
    Leds:=NewBar
  ELES
    Leds:=HiBit
  RETURN

Joe

Comments

  • Ok the help file for BS Editor 2.5.3 shows the following ex
    Value1 = 100
    Value1 = Value1 */ $0180
    Value =150

    Doing conventionally on a programming calc won't work, so I did
    DEC 100 * HEX 0180
    Got 38400 and then hit >> on the calc 8 times and got 150

    So, Will
    GrafVal := (RawVal-LowScale)
    GrafVal := GrafVal * Scale
    GravVal := GrafVal >> 8
    actually work??

    Joe
  • AribaAriba Posts: 2,690
    edited 2016-03-17 21:23
    Yes it will work but why do you write it on 3 lines?
    Just do:
    GrafVal := (RawVal-LowScale) * Scale >> 8
    
    or a bit slower but more readable:
    GrafVal := (RawVal-LowScale) * Scale / 256
    

    Andy
  • Ok, thanks. I am soo used to that from the ed labs txt, its normal for me. Gotta get used to the other. Thanks.

    Joe
  • Shouldn't the line:
    IF GrafVal=BarGraf
    be:
    IF GrafVal==BarGraf
    ?
  • Forgot about that. Thanks for telling me. Will change that.

    Joe
  • jknightandkarrjknightandkarr Posts: 234
    edited 2016-03-18 17:15
    I got the software to accept it and Propeller has the program, however, the LEDs are not doing anything, just staying lit. Here's current code after changes.
    CON
    
      _CLKMODE  = XTAL1 + PLL16X                            'Standard clock mode * crystal frequency = 80 MHz
      _XINFREQ  = 5_000_000
    
      DotGraf   = 0
      BarGraf   = 1
      GraphMode = 1'BarGraf                                   'DotGraf or BarGraf
      IsOn      = 1 
      IsOff     = 0
      LowScale  = 10                                        'Low cap reading
      HighScale = 695                                       'High cap reading
      Span      = HighScale - LowScale                      '685 total cap range
      Scale     = $FFFF / Span                              '95=$FFFF/685  95.67153
      Pot       = 15                                        'Input from RC network.
      
    VAR
    
      LONG  us
      WORD  RawVal                                          'Value from I/O Pins                                     '
      BYTE  HiBit, NewBar, GrafVal                                           '                                          '
      WORD  LEDs, LEDsDirs                                           '
      BYTE  LowDigitPin, HighDigitPin                       'The pins for specifying digits.
                                                            'Must be contiguous
                                                            'HighDigitPin can be from 0
                                                            'to 7 more than LowDigitPin
                                              '
    PUB Settings(dLow, digits, s0, enabled)
    '' Start the display
    '' Parameters:
    ''   dLow - the pin number of the least significant digit
    ''   digits - the number of digits to display  (up to 8)
    ''   s0 - the pin number of segment 0
    ''   enabled - the initial enabled state
      dLow:=0
      digits:=8
      us:= clkfreq / 1_000_000                              ' Clock cycles for 1 us
      LowDigitPin := dLow
      HighDigitPin := dLow + ((digits - 1) <# 16)           'Limit to 16 leds
      DIRA[LowDigitPin..HighDigitPin]~~                     'Set digit pins to outputs
      OUTA[LowDigitPin..HighDigitPin]~~                     'Turn off all digits
      DIRA[Pot]:=%1
      Start
    
    PUB Start            
      'GrafVal:=0
      'RawVal:=350
      
      REPEAT
        ReadPot
        RawVal:=ReadPot
        GrafVal := (RawVal-LowScale) * Scale >> 8
        'GrafVal := (RawVal-LowScale)
        'GrafVal := GrafVal * Scale
        'GravVal := GrafVal >> 8
        ShowGraph
        WAITCNT ((CLKFREQ/1000)*50+CNT)
      
    PRI ReadPot
    
      OUTA[Pot]:=1
      WAITCNT (CLKFREQ/1000+CNT)
      RawVal:= RCTIME (Pot, 1) 'rawValue returned
      'RawVal:=RCTIME()
      RETURN
    
    PRI ShowGraph
    
      HiBit:=|<(GrafVal/32)
      IF GrafVal==1 'BarGraf
        NewBar:=0
        IF GrafVal>0
          REPEAT WHILE HiBit>0
            NewBar:= NewBar << 1
            NewBar:=%000000000000001
            HiBit := HiBit >> 1
        ELSE
        Leds:=NewBar
      ELSE
        Leds:=HiBit
      RETURN
    
    PUB RCTIME (Pin,State) :Duration | ClkStart, ClkStop
    {{
       Reads RCTime on Pin starting at State, returns discharge time, returns in 1uS units
         dira[5]~~                 ' Set as output
         outa[5]:=1                ' Set high
         BS2.Pause(10)             ' Allow to charge
         x := RCTime(5,1)          ' Measure RCTime
         BS2.DEBUG_DEC(x)          ' Display
    }}
    
       DIRA[Pin]~
       ClkStart := cnt                                         ' Save counter for start time
       waitpne(State << pin, |< Pin, 0)                        ' Wait for opposite state to end
       clkStop := cnt                                          ' Save stop time
       Duration := (clkStop - ClkStart)/uS                      ' calculate in 1us resolution
    

    Going to see if I can spot any issues while waiting for assistance. I think I have the result from the ReadPot and RCTIME done correctly, but nothing I try changes anything...

    Joe
  • These two lines in ShowGraph:
            NewBar:= NewBar << 1
            NewBar:=%000000000000001
    
    look very suspicious. I think you meant to have "|=" on the second line (so as to OR in a low bit to NewBar, instead of replacing it).

  • Tracy AllenTracy Allen Posts: 6,664
    edited 2016-03-18 19:40
    Your way of doing the math is fine, yet FWIW you can do the same math with the Prop ** command. The idea is that you are taking a full scale value of, say, 0 to 635, and rescaling to a binary value in this case 0 to 256. Then find the top three bits of the result, a value 0 to 7. The DCD operator on the Stamp, or |< on the Prop then sets one bit in its result so that you end up with %1, %10, %100, ... %10000000.

    The Stamp version is displaying the result on a set of 8 LEDs. The logic is similar for 16 LEDs but you'd have to grab the top 4 bits. The Stamp version allows it to display either the single LED, or a bar of LEDs like %1, %11, %111 etc. %11111111

    With the ** operator, you have 32 bits to play with.
    CON
    Scale = $FFFF_FFFF / Span * 256 ' if Span = 685 then scale = 1_605_126_400
    then with the **
    GrafVal = (RawVal - LoScale) ** Scale
    rescales to a maximum value of 256. For example, if RawVal - LoScale = 400, then 400 ** 1605126400 = 149. Note that 400/685 = 149/256
    By your current method 400 * 95 >> 8 = 148, just a little more roundoff error from using $FFFF instead of $FFFFFFFF.

    For the display, if you want to get the full bar without a REPEAT loop, just calculate from the original hibit value,
    newbar := hiBit * 2 - 1 ' e.g. %10000 becomes %11111
  • Indentation in Spin is important - it's how conditional things like IF / ELSE and loops like FOR / REPEAT determine the scope of stuff. You have a line following an else that's not indented:
    PRI ShowGraph
    
      HiBit:=|<(GrafVal/32)
      IF GrafVal==1 'BarGraf
        NewBar:=0
        IF GrafVal>0
          REPEAT WHILE HiBit>0
            NewBar:= NewBar << 1
            NewBar:=%000000000000001
            HiBit := HiBit >> 1
        ELSE
        Leds:=NewBar     ' <<<<< This line should probably be indented
      ELSE
        Leds:=HiBit
      RETURN
    

    It's possible that line is always executing, since it's outside the scope of the ELSE statement. I also think ErSmith is right when he says your := should be an |=
    You could also make the code a little faster by using the <<= or >>= versions of shift which combine the shift and the assignment in a single operation, when you're not storing the result to a different variable.

    This would be the updated version with all changes:
    PRI ShowGraph
    
      HiBit := |<(GrafVal/32)
      IF GrafVal==1 'BarGraf
        NewBar := 0
        IF GrafVal>0
          REPEAT WHILE HiBit>0
            NewBar <<= 1
            NewBar |= 1
            HiBit >>= 1
        ELSE
          Leds := NewBar
      ELSE
        Leds := HiBit
      RETURN
    
  • jknightandkarrjknightandkarr Posts: 234
    edited 2016-03-19 16:59
    ersmith wrote: »
    These two lines in ShowGraph:
            NewBar:= NewBar << 1
            NewBar:=%000000000000001
    
    look very suspicious. I think you meant to have "|=" on the second line (so as to OR in a low bit to NewBar, instead of replacing it).

    I first wrote the program the same way in the BS2 editor. Like This?
            NewBar:= NewBar << 1
            NewBar|=%000000000000001
    
    Tried it and no change all leds still on...
    Your way of doing the math is fine, yet FWIW you can do the same math with the Prop ** command. The idea is that you are taking a full scale value of, say, 0 to 635, and rescaling to a binary value in this case 0 to 256. Then find the top three bits of the result, a value 0 to 7. The DCD operator on the Stamp, or |< on the Prop then sets one bit in its result so that you end up with %1, %10, %100, ... %10000000.

    The Stamp version is displaying the result on a set of 8 LEDs. The logic is similar for 16 LEDs but you'd have to grab the top 4 bits. The Stamp version allows it to display either the single LED, or a bar of LEDs like %1, %11, %111 etc. %11111111

    With the ** operator, you have 32 bits to play with.
    CON
    Scale = $FFFF_FFFF / Span * 256 ' if Span = 685 then scale = 1_605_126_400
    then with the **
    GrafVal = (RawVal - LoScale) ** Scale
    rescales to a maximum value of 256. For example, if RawVal - LoScale = 400, then 400 ** 1605126400 = 149. Note that 400/685 = 149/256
    By your current method 400 * 95 >> 8 = 148, just a little more roundoff error from using $FFFF instead of $FFFFFFFF.

    For the display, if you want to get the full bar without a REPEAT loop, just calculate from the original hibit value,
    newbar := hiBit * 2 - 1 ' e.g. %10000 becomes %11111

    I will try that n see if anything changes.
    JasonDorie wrote: »
    Indentation in Spin is important - it's how conditional things like IF / ELSE and loops like FOR / REPEAT determine the scope of stuff. You have a line following an else that's not indented:
    PRI ShowGraph
    
      HiBit:=|<(GrafVal/32)
      IF GrafVal==1 'BarGraf
        NewBar:=0
        IF GrafVal>0
          REPEAT WHILE HiBit>0
            NewBar:= NewBar << 1
            NewBar:=%000000000000001
            HiBit := HiBit >> 1
        ELSE
        Leds:=NewBar     ' <<<<< This line should probably be indented
      ELSE
        Leds:=HiBit
      RETURN
    

    It's possible that line is always executing, since it's outside the scope of the ELSE statement. I also think ErSmith is right when he says your := should be an |=
    You could also make the code a little faster by using the <<= or >>= versions of shift which combine the shift and the assignment in a single operation, when you're not storing the result to a different variable.

    This would be the updated version with all changes:
    PRI ShowGraph
    
      HiBit := |<(GrafVal/32)
      IF GrafVal==1 'BarGraf
        NewBar := 0
        IF GrafVal>0
          REPEAT WHILE HiBit>0
            NewBar <<= 1
            NewBar |= 1
            HiBit >>= 1
        ELSE
          Leds := NewBar
      ELSE
        Leds := HiBit
      RETURN
    
    That I didn't catch. Thank you! I fixed it, and tried <<=, >>= & still nada on changes...

    I am going to try the serial terminal and debug and try and see what thing is doing.

    Joe
Sign In or Register to comment.