Shop OBEX P1 Docs P2 Docs Learn Events
Any explanation for weird memory behavior? — Parallax Forums

Any explanation for weird memory behavior?

StephenMooreStephenMoore Posts: 188
edited 2012-06-10 15:42 in Propeller 1
Why doesn't this code rotate the array? It loads up the array with the last value only. That is it it fails to copy the first element. Any ideas anyoune?
CON
    _clkmode = xtal1 + pll16x                           
    _xinfreq = 5_000_000


     _RED    = $FF0000           '' Offer up some basic color schemes
     _GREEN  = $00FF00
     _BLUE   = $0000FF
     _PINK   = $FF0F0F
     _LTGRN  = $0FFF0F
     _LTBLU  = $0F0FFF
     _YELLO  = $FFFF00
     _MAGEN  = $FF00FF
     _CYAN   = $00FFFF
     
     NUMLED       = 50
     NUMLETTER    = 5
     LEDPERLETTER = NUMLED/NUMLETTER
    
OBJ
         
        pst     :       "Parallax Serial Terminal"

VAR
long  RGB[NUMLED]
long  colorArray[NUMLETTER + 1]


PUB LED

pst.start(115200) 
                              
setColorArray 
rotateColorArray 


PRI rotateColorArray | idx        
                                                  
  long[@colorArray][NUMLETTER] := long[@colorArray][0]        '' set last value in array = to first value 
  
  pst.hex(long[@colorArray][NUMLETTER], 6)
  pst.char($0D)
    
  repeat idx from 1 to (NUMLETTER )                           '' rotate values down
   long[@colorArray][idx-1] := long[@colorArray][idx]       


PRI setColorArray

    long[@colorArray][0] := _PINK
    long[@colorArray][1] := _YELLO
    long[@colorArray][2] := _LTGRN
    long[@colorArray][3] := _BLUE
    long[@colorArray][4] := _RED 


    pst.hex(long[@colorArray][0], 6)
    pst.char($0D)

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2012-06-10 00:09
    First you print element 0, then assign element 0 to element NUMLETTER, finally you print element NUMLETTER. I'd be worried if you didn't get the same result. FWIW, you can access colorArray directly, i.e. long[@colorArray][n] is the same as colorArray[n]. Makes it so much easier to read.

    IOW, the rotation function is perfectly fine.
    CON
      _clkmode = XTAL1|PLL16X                               
      _xinfreq = 5_000_000
    
      _RED    = $FF0000             '' Offer up some basic color schemes
      _GREEN  = $00FF00
      _BLUE   = $0000FF
      _PINK   = $FF0F0F
      _LTGRN  = $0FFF0F
      _LTBLU  = $0F0FFF
      _YELLO  = $FFFF00
      _MAGEN  = $FF00FF
      _CYAN   = $00FFFF
         
      NUMLED       = 50
      NUMLETTER    = 5
      LEDPERLETTER = NUMLED/NUMLETTER
        
    OBJ
      pst: "Parallax Serial Terminal"
    
    VAR
      long  RGB[NUMLED]
      long  colorArray[NUMLETTER + 1]
    
    PUB LED
    
      pst.start(115200)
      waitcnt(clkfreq*3 + cnt)
      pst.char(0)
                     
      setColorArray
      display
      pst.char(13)
    
      repeat 5
        rotateColorArray
        display
    
    PRI rotateColorArray | idx        
                                                      
      colorArray[NUMLETTER] := colorArray[0]                      '' set last value in array = to first value 
        
      repeat idx from 1 to NUMLETTER                              '' rotate values down
        colorArray[idx-1] := colorArray[idx]                    
    
    PRI display | idx
    
      repeat idx from 0 to NUMLETTER-1                            '' rotate values down
        pst.hex(colorArray[idx], 6)                             
        pst.char(32)
      pst.char(13)
    
    PRI setColorArray
    
      colorArray[0] := _PINK
      colorArray[1] := _YELLO
      colorArray[2] := _LTGRN
      colorArray[3] := _BLUE
      colorArray[4] := _RED          
    
    DAT
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-10 09:30
    BTW, you can do the rotate more efficiently with a longmove instruction. Also since your array is declared as a long, you don't need to use the long[@colorArray] notation, viz:
    colorArray[NUMLETTER] := colorArray[0] 
    longmove(@colorArray, @colorArray[1], NUMLETTER)
    

    -Phil
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-06-10 09:34
    You can use longmove to rotate an array.
    PUB rotateLongArray(arrayPtr, arraySize) | tempLong
      tempLong := long[arrayPtr]
      longmove(arrayPtr, arrayPtr + 4, arraySize - 1)
      long[arrayPtr + (4 * (arraySize - 1))] := tempLong
     
    

    Edit: I see Phil bet me to it.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-10 09:40
    I might've been first, but Duane did it right! I forgot the temp variable:
    temp := colorArray[0] 
    longmove(@colorArray, @colorArray[1], NUMLETTER)
    colorArray[NUMLETTER] := temp
    

    D'oh!

    -Phil
  • StephenMooreStephenMoore Posts: 188
    edited 2012-06-10 13:08
    Thank you gentlemen for your advice. I have simplified the array addressing and used longmove for rotation. However, the code is still doing the same thing... loading the value at colorArray[NUMLETTER] into every position.

    I have a string of 50 RGB leds grouped into letters of 10 leds each. When I use the rotateColorArray routine it all turns red. Here is the complete listing. It is really baffling to me because it should be working.

    CON
        _clkmode = xtal1 + pll16x                           
        _xinfreq = 5_000_000
    
    
          DQ    = 0                  '' Set WS2801 Data Pin
          CLK   = 1                  '' Set WS2801 Clock Pin
    
    
         _RED    = $FF0000           '' Offer up some basic color schemes
         _GREEN  = $00FF00
         _BLUE   = $0000FF
         _PINK   = $FF0F0F
         _LTGRN  = $0FFF0F
         _LTBLU  = $0F0FFF
         _YELLO  = $FFFF00
         _MAGEN  = $FF00FF
         _CYAN   = $00FFFF
         
    
    
         NUMLED       = 50
         NUMLETTER    = 5
         LEDPERLETTER = NUMLED/NUMLETTER
        
    OBJ
             
            SPI     :       "SPI_Asm"                               ''The Standalone SPI Assembly engine
            pst     :       "Parallax Serial Terminal"
    
    
    VAR
    long  RGB[NUMLED]
    long  colorArray[NUMLETTER + 1]
    
    
    PUB LED  | char
    
    
    
    
    '' -----[ Initialization ]--------------------------------------------------
    
    
    ''Serial communication Setup
        pst.start(115200)  '' Initialize serial communication to the PC through the USB connector
                                    '' To view Serial data on the PC use the Parallax Serial Terminal (PST) program.
    
    
        SPI.start(1,0)             '' Initialize SPI Engine with Clock Delay of 15 and Clock State of 1
    
    
    
    
         waitcnt(cnt+clkfreq*10/1000)                      '' Pause for 10ms
    repeat
      pst.char(pst#CS)
      pst.str(string("0 to reset color array, 1 to rotate array"))
      char := pst.charin
       case char
        "0":
         setColorArray
         letterColor
         loadLED
        "1":
         rotateColorArray
         letterColor
         loadLED
    
    
    PRI letterColor | letter, idx
     
     repeat letter from 0 to NUMLETTER-1 
       longfill(@RGB + letter * LEDPERLETTER * 4, colorArray[letter], LEDPERLETTER)
    
    
    PRI rotateColorArray | temp        
                                                      
      temp := colorArray[0]
      longmove(@colorArray, @colorArray[1], NUMLETTER-1)    
      colorArray[NUMLETTER] := temp
    
    
    PRI setColorArray
    
    
        colorArray[0] := _PINK
        colorArray[1] := _YELLO
        colorArray[2] := _LTGRN
        colorArray[3] := _BLUE
        colorArray[4] := _RED 
        
    PRI loadLED | idx
    
    
      repeat idx from 0 to NUMLED - 1   
       SPI.SHIFTOUT(DQ, CLK, SPI#MSBFIRST , 24, RGB[idx])  ''send color values
      
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-06-10 13:34
    You'll want to use:
    colorArray[NUMLETTER [COLOR=#ff0000]- 1[/COLOR]] := temp
    

    I don't know if that's the only problem, but it should help.
  • StephenMooreStephenMoore Posts: 188
    edited 2012-06-10 13:44
    That's got it!

    I really appreciate you guys who help out. You have talent and share it willingly: a great and rare commodity these days.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-10 13:47
    Duane Degn wrote:
    You'll want to use:

    Code:

    colorArray[NUMLETTER - 1] := temp

    I don't know if that's the only problem, but it should help.

    Why did that work? The dimension of colorArray is NUMLETTER + 1, so the last element is colorArray[NUMLETTER].

    -Phil
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-06-10 13:56
    Why did that work? The dimension of colorArray is NUMLETTER + 1, so the last element is colorArray[NUMLETTER].

    -Phil

    I didn't notice the size was "+1".

    But since only 4 elements had been shifted (from 1 through 4 to 0 through 3), then element #4 is the one I thought was supposed to receive the value from (the previous) element #0.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-10 14:00
    longmove(@colorArray, @colorArray[1], NUMLETTER) shifts five elements. I guess it depends on whether the OP wants the entire array involved in the rotation, or all but the last element.

    -Phil
  • StephenMooreStephenMoore Posts: 188
    edited 2012-06-10 14:03
    Though the array size was NUMLETTER+1 only NUMLETTER values were defined. With the code as it stands an array size of NUMLETTER works. Believe me I have been going round and round with this little program.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-10 14:19
    If the array dimension is NUMLETTER, there are NUMLETTER elements, indexed 0 .. NUMLETTER - 1. With a dimension of NUMLETTER + 1, there are NUMLETTER + 1 elements, indexed 0 .. NUMLETTER.

    You may have been thinking about strings, which are byte arrays whose size needs to be one greater than the number of actual characters, in order to accommodate the zero termination byte.

    -Phil
  • StephenMooreStephenMoore Posts: 188
    edited 2012-06-10 15:42
    I have another problem I am working on... Instead of just rotating the letter colors and resetting the LED string I would like to fade a transition. For example RGB and RGB2 are both 50 element long arrays with RGB data in the lower 3 bytes of each element.

    I need a strategy for fadeLED(@RGB, @RGB2).
    PUB led
    
          letterColor(@RGB2)           ' store color values in RGB2
          rotateColorArray                 ' rotate the color sequence
          letterColor(@RGB)              ' store new sequence in RGB
          fadeLED(@RGB, @RGB2)   ' SHIFTOUT routine to transition letters to new color values
    
    PRI fadeLED(ledArray1, ledArray2) | idx1, idx2, delta
    
    
     repeat idx1 from 0 to 20              ' start with twenty step trasnition
     
       repeat idx2 from 0 to NUMLED - 1
       
        delta := (ledArray1[idx2] - ledArray2[idx2]) / 20
        ledArray2[idx2] += delta
        
        SPI.SHIFTOUT(DQ, CLK, SPI#MSBFIRST , 24, ledArray2[idx2])  ''send color values
     
    PRI letterColor(ledPtr) | letter, idx
     
     repeat letter from 0 to NUMLETTER-1 
       longfill(ledPtr + letter * LEDPERLETTER * 4, colorArray[letter], LEDPERLETTER)
    
    
    PRI rotateColorArray | temp        
                                                      
      temp := colorArray[0]
      longmove(@colorArray, @colorArray[1], NUMLETTER-1)    
      colorArray[NUMLETTER-1] := temp
    
    
    


    It is not clear to me what the most aesthetic traverse of color space would be. Here is my attempt at it but it washes out color.

    PRI fadeLED(inc) | idx1, idx2, r1, g1 ,b1, r2, g2, b2
    
    
     repeat idx1 from 0 to inc              ' start with twenty step transition
        waitcnt(clkfreq / 5 + cnt)
         
       repeat idx2 from 0 to NUMLED - 1
       
         r1 :=  ((RGB[idx2]>>16)& $FF)
         g1 :=  ((RGB[idx2]>>8)& $FF)
         b1 :=  (RGB[idx2] & $FF)   
         r2 :=  ((RGB2[idx2]>>16)& $FF)
         g2 :=  ((RGB2[idx2]>>8)& $FF)
         b2 :=  (RGB2[idx2] & $FF)
         r2 += (r1-r2) / inc
         g2 += (g1-g2) / inc
         b2 += (b1-b2) / inc 
    
    
        RGB2[idx2] := r2<<16 | g2<<8 | b2
        
        SPI.SHIFTOUT(DQ, CLK, SPI#MSBFIRST , 24, RGB2[idx2])  ''send color values
    
Sign In or Register to comment.