Studio 5000 - SWPB or similar function for a SINT array?

sterky

Member
Join Date
Jul 2023
Location
ontario
Posts
18
Howdy, I am currently struggling with an array of values that I want to re-arrange in a programmatic way. My program is a mix of ladder and STX, with some tricks to make user input of array values on the HMI a little less of a headache.

To start I have a string that the user can edit, formatted;
Code:
"1,2,3#4,6,5#7,8#9"

I then convert the string to a 2 dim array of sint[20,4], formatted;
Code:
array[0,0] = 1 
array[0,1] = 2
array[0,2] = 3

array[1,0] = 4
array[1,1] = 6
array[1,2] = 5

array[2,0] = 7
array[2,1] = 8

array[3,0] = 9

all other array values = 0;


For some of the User input, they would need to modify the order of each array. Rather than have them retype the order, I'd like to rearrange it as follows
Reversed order of the 1st dim array values
Code:
array[0,0] = 3 
array[0,1] = 2
array[0,2] = 1

array[1,0] = 5
array[1,1] = 6
array[1,2] = 4

array[2,0] = 8
array[2,1] = 7

array[3,0] = 9

I was looking at the SWPB (Swap Byte), but not sure if it will accomplish what I need since my bytes are across array elements. Maybe some ladder with some FIFOs, if I can get it to reverse with the empty 0 elements offsetting the reversal of values.


Seems like something simple but curious if someone has a different approach besides STX for loops.

P.S. I'll need to reassemble the reversed string too, to inform the user of the change in order.
 
I see major faults in your future

Anyway, there's no trick to use here as you can't address a single row of a multi-dimensional array. Just loop over the user buffer, outputting the re-ordered array into a 2nd array. then copy it back to the user buffer.

But if you really want a trick, you could run bubble sort in ascending/descending order on the rows.
 
are the digits always in the range 0-9, i.e. are the comma- and #-delimited numbers always single digits?


Actually that does not matter, because all that needs to be done is

  1. reverse each phrase sub-string between the # delimiters,
  2. then reverse each numeric sub-string between each [,,] or [,#] or [#,] pair delimiter.
E.g.

1,23,456#789,0,12#34,567#8 <= Original string
654,32,1#21,0,987#765,43#8 <= Reverse inter-# phrases
456,23,1#12,9,789#567,34#8 <= Reverse numbers

And an intermediate 2D array is not needed, just a single SINT to hold the temporary value for the swap (and even that is not actually needed, but memory is cheap and that is another story).

So summat like this:
Code:
string := '1,23,456#789,0,12#34,567#8';
total_length := 26;
FOR pass := 0 TO 1 DO          (* pass 0:swap phrases; pass 1:swap digits *)
  hi := -1;                    (* implicit delimiter "before" string *)
  WHILE hi < total_length DO   (* implicit delimiter "after" string *)
    lo := hi;                  (* delimiter before string *)
    hi := lo + 1;              (* initialize delimiter search *)
    WHILE hi < total_length DO (* search for next delimiter *)
      IF string.data[hi] = 35  (* # character is a delimiter on both passes *)
      THEN
        EXIT;
      END_IF;
      IF  pass = 1
      AND string.data[hi] = 44 (* , is a delimiter on pass 1 only *)
      THEN
        EXIT;
      END_IF;
      hi := hi + 1;            (* delimiter not found yet, increment search index *)
    END_WHILE;
    sublo := lo + 1;           (* index of left end of sub-string *)
    subhi := hi - 1;           (* index of right end of sub-string *)
    WHILE sublo < subhi DO     (* swap characters in sub-string *)
      string_temp := string.data[sublo];
      string.data[sublo] := string.data[subhi];
      string.data[subhi] := string_temp;
      sublo := sublo + 1;
      subhi := subhi - 1;
    END_WHILE;
  END_WHILE;
END_FOR;
 
Definitely not swap byte. There is no swap data equivalent instruction across array elements. Easiest is just do a bubble sort. I do them all the time for arrays in CLX.
 
Pascal equivalent of my previous post that works

  • string characters can be accessed and compared without SINT .data[...] and ASCII codes
  • BREAK instead of EXIT to get out of a loop.
  • BEGIN..END instead of END_IF, END_FOR and END_WHILE.
 
I see major faults in your future

Oh yeah, been faulting the simulator a fair bit. šŸ˜…
Have been adding variable limiters to protect array dimensions as I go but I'm gonna have QA try to find any I'm missing before the operator finds it. I did build my own onscreen keypad to limit the expected characters.

but as the saying goes, "Each time you idiot proof a system, someone builds a better idiot"


Actually that does not matter, because all that needs to be done is

  1. reverse each phrase sub-string between the # delimiters,
  2. then reverse each numeric sub-string between each [,,] or [,#] or [#,] pair delimiter.
E.g.

1,23,456#789,0,12#34,567#8 <= Original string
654,32,1#21,0,987#765,43#8 <= Reverse inter-# phrases
456,23,1#12,9,789#567,34#8 <= Reverse numbers

And an intermediate 2D array is not needed, just a single SINT to hold the temporary value for the swap (and even that is not actually needed, but memory is cheap and that is another story).

So summat like this:
Code:
string := '1,23,456#789,0,12#34,567#8';
total_length := 26;
FOR pass := 0 TO 1 DO          (* pass 0:swap phrases; pass 1:swap digits *)
  hi := -1;                    (* implicit delimiter "before" string *)
  WHILE hi < total_length DO   (* implicit delimiter "after" string *)
    lo := hi;                  (* delimiter before string *)
    hi := lo + 1;              (* initialize delimiter search *)
    WHILE hi < total_length DO (* search for next delimiter *)
      IF string.data[hi] = 35  (* # character is a delimiter on both passes *)
      THEN
        EXIT;
      END_IF;
      IF  pass = 1
      AND string.data[hi] = 44 (* , is a delimiter on pass 1 only *)
      THEN
        EXIT;
      END_IF;
      hi := hi + 1;            (* delimiter not found yet, increment search index *)
    END_WHILE;
    sublo := lo + 1;           (* index of left end of sub-string *)
    subhi := hi - 1;           (* index of right end of sub-string *)
    WHILE sublo < subhi DO     (* swap characters in sub-string *)
      string_temp := string.data[sublo];
      string.data[sublo] := string.data[subhi];
      string.data[subhi] := string_temp;
      sublo := sublo + 1;
      subhi := subhi - 1;
    END_WHILE;
  END_WHILE;
END_FOR;

After taking the weekend to think about it, I just include the reverse array and reversing string logic in the original deconstruction logic FOR loop.

Ends up being fairly compact as once the first dimension is deconstructed since I have the number of used elements handy in a variable, so I have another FOR loop that copies in reverse and builds the reversed string with DTOS and adds , and # with individual COP.

Then the overall for loop moves on to the next 2nd dimension.
 

Similar Topics

I'm trying to compare strings in Studio 5000 on an Allen Bradley 1769-L33ER and came across this weird incorrect string comparison. Neither of the...
Replies
3
Views
92
Hello everyone, I'm new here, I hope someone can help me. I've been trying to install EDS files to my Studio 5000 with the EDS tool installer but...
Replies
3
Views
133
Hi Everyone, I am facing an issue while installing the STUDIO 5000 in my windows 10 PC. During installation I am getting an error that " Error...
Replies
4
Views
201
I am connecting to a remote device. When attempting to upload I receive an error that states: Error: Auto_Functions: The Import was aborted due...
Replies
3
Views
197
Back
Top Bottom