Shop OBEX P1 Docs P2 Docs Learn Events
My variable is getting squashed! — Parallax Forums

My variable is getting squashed!

The code in this method is killing me. See debug output:

Somehow z is gettting squashed on the second iteration of the inner most repeat. First iteration z is 0. Second iteration z is 102 which is out of bounds and should never get to that point as strlen in this instance is 1 and str_in contains a "P"

PUB read_8x8(str_in, strlen ): array_out | z, k, j, w

  z:=0

  repeat while z < strlen
    k:=0
    repeat while k < ascii_index
      ' find character in ascii aray
      if(str_in[z] == ascii[k*9])
        j:=0
       repeat while j < 8
          'load font info into array_out
          array_out[(z*8)+j] := ascii[((k*9)+1)+j]
          debug(udec(z))
          debug(udec(j))
          j++      
      k++
    z++

Comments

  • avsa242avsa242 Posts: 430
    edited 2021-03-01 14:05

    Greg,

    I think it's the line
    array_out[(z*8)+j] := ascii[((k*9)+1)+j]

    array_out is a long, but you're trying to modify the (z*8)'th element, which will start trampling on your local vars after byte #3. When z = 1 it would already be past byte #3.

  • @avsa242 said:
    [..] which will start trampling on your local vars after byte #3. When z = 1 it would already be past byte #3.

    Actually, since it's a long, any non-zero index will result in clobbery.

  • Since that is the return value I cant seem to declare it as an array.

  • JonnyMacJonnyMac Posts: 8,926
    edited 2021-03-01 18:28

    @"Greg LaPolla" said:
    Since that is the return value I cant seem to declare it as an array.

    You cannot pass arrays by value, only by reference (pointer).

  • Well ... Spin is not as dynamic as you want it to be. Inside of a function you can't "create" some memory for such an return array.

    Solution 1: use an array defined in dat or var section and do not return values, but the pointer to that dat section.
    Problem: When the function is called from several COGs at the same time, you might run in the same issue.

    Solution 2: move the function into an Object and define the output array in the VAR section. Each COG then needs it's own instance of the object.
    VAR sections are independent per object instance.
    Con: This memory would only be useful for that function.

    Solution 2: Not only provide the input, but also a buffer to write the result to by the caller. So, the function would change to str_in, str_out, str_len.
    Pro: This way the caller is master of that piece of memory and might use it for different things.

  • I agree with @MagIO2, and suggest you redefine your method header like this:

    pub read_8x8(p_str, len, p_fbuf)

    ... where p_fbuf is a pointer to your font buffer.

  • Can't seem to get working.

    Do I have to do do something with the pointer in the method before I can access it ?
    It just loops through the outer repeat and the if statement never is true.

     VAR
      byte output[96]
      byte buffer[32]
    
    .  . .
    
      buffer := string("PARALLAX")
    
      read_8x8(@buffer,8,@output)
    
    . . .
    
    
    PUB read_8x8(p_str, strlen, p_arr)| x, k, j
    
      x:=0
    
      repeat while x < strlen                                   ' Keep search within the confines of the length of the array
        k:=0
        repeat while k < ascii_index                            ' Stay within the ascii array during search
          ' find character in ascii array
          if(p_str[x] == ascii[k*9])                            ' Did we find it ?
            j:=0
            repeat while j < 8                                  ' Loop for each line of the 8x8 matrix
              'load font info into array_out
              p_arr[(x*8)+j] := ascii[((k*9)+1)+j]              ' Load the font into the array
              debug(udec(x))
              debug(uhex(ascii[((k*9)+1)+j]))
              debug(uhex(p_arr[(x*8)+j]))
              j++
          k++
        x++
    
    
  • AribaAriba Posts: 2,682

    To access the elements of an array via a pointer, you need to use byte[], word], long[], depending on the size of the array elements:

    if byte[p_str][x] == ascii[k*9]
    
    

    You don't show us how ascii[] is defined, i expect it's a byte array in a DAT section with words to search.
    You know that Spin has a built in strcomp() methode?

    Andy

  • string() also returns the address of the string, not the string itself, so the address-of (@) operator isn't needed when referencing buffer, so the line:

    read_8x8(@buffer,8,@output)
    should read
    read_8x8(buffer,8,@output)

  • I am still not able to get it to work.

    Should this work ?

    display := string("PARALLAX")
    
     q := 0
     repeat 8
       debug(uhex(byte[display][q]))
       q++
    
  • AribaAriba Posts: 2,682

    Should this work ?

    Yes this works fine for me

    CON
      _clkfreq  = 180_000_000
    
    PUB main() | display,q
     display := string("PARALLAX")
    
     q := 0
     repeat 8
       debug(uhex(byte[display][q]))
       q++
    
    
  • I see the issue. I had display declared in the var section as type byte display[32]. Changed it to what you have and it now works.

  • Try this variation of your test program when using Debug and working with strings in either PNut, PropTool 2.5.1+ or Flexprop 5.2.0+
    The 'zstr' Debug command is very helpful when displaying zero terminated strings.

    CON
      _clkfreq  = 180_000_000
    
    PUB main() | display,q
     display := string("PARALLAX")
    
     q := 0
     debug(zstr(display),"  String contents: ",zstr_(display))
     repeat 8
       debug("Char at byte[",udec_(q),"]: ",uhex_(byte[display][q]),"  String from [",udec_(q),"]: ",zstr_(@byte[display][q]))
       q++
    

Sign In or Register to comment.