News:

  • August 20, 2026, 01:05:26 PM

Login with username, password and session length

Author Topic: User Data Type definitions, Heap-Items and Data-Blocks  (Read 41737 times)

Mike Nash

  • Hero Member
  • *****
  • Posts: 652
User Data Type definitions, Heap-Items and Data-Blocks
« on: September 20, 2017, 06:49:34 PM »
I just finished reading almost every word of the update pdf on the v2.1 changes. That has certainly been a lot of work Host has accomplished. I am sure I will need to re-read it several times to benefit the most from it. I wasn't even aware of some of the issues that were fixed.

I'm really happy I hadn't yet tried to get all my menus rearranged after having to load/reload Windows on 3 different computers. This update came out just in time for me on that.

I have a question regarding the UDT Structure vs heap-item in the recipe example of the pdf. I see that the RecipeStruct becomes the structure for the CurrentRecipe heap item, but I don't think I fully get the difference. I can address the RecipeStruct structures directly via RecipeStruct1.itemname or indirectly via RecipeStruct[V100].itemname so the heap-item benefits me how? I'm not sure I am seeing the benefit other than no array designation.

And this is my first Windows 10 computer ever that I am typing this on. Oddly, I find it less annoying than Win7.

franji1

  • Bit Weenie
  • Host Moderator
  • Hero Member
  • *****
  • Posts: 3843
    • Host Engineering
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #1 on: September 20, 2017, 11:54:43 PM »
I have a question regarding the UDT Structure vs heap-item in the recipe example of the pdf. I see that the RecipeStruct becomes the structure for the CurrentRecipe heap item, but I don't think I fully get the difference. I can address the RecipeStruct structures directly via RecipeStruct1.itemname or indirectly via RecipeStruct[V100].itemname so the heap-item benefits me how? I'm not sure I am seeing the benefit other than no array designation.

Let's look at it using a built-in structure, PID.  I can create a block of 16 PID Structs, called MyPID.  I can address MyPID0..MyPID15 in a PID instruction.  I can even use a FOR/NEXT loop with V0 0..15 with PID instruction with MyPID[V0] (this is how we tested 1000 PID loops without needing 1000 PID instructions - HA!)

I can also create PID heap-items.  CookerABC.  ChillerXYZ.

I can look at MyPID4.PV or MyPID[V100].PV or CookerABC.PV or ChillerXYZ.PV.

I did all this with the structure definition PID Struct.  1 data block of 16, and 2 heap-items.  I could actually create another data-block of 100 PIDs called MyOtherPID, and now I have MyOtherPID0..MyOtherPID99, in addition to the other block of 16 and 2 heap-items.

Back to RecipeStruct.  I defined a User Data Type structure definition called RecipeStruct.  That just defines the data-type, not a data-block or heap-item.  I can then create a data-block of 100 of them called Recipe, so I have Recipe0..Recipe99.  But I then also create a heap-item of a RecipeStruct called CurrentRecipe.  This heap-item is what my program actually uses for control.  So, at the beginning of the batch, I use V42 as my recipe selector, where V42 equals 0..99.  Say I picked recipe #11 (so my HMI stuck 11 in V42).  I then MEMCOPY RecipeStruct[V42] into heap-item CurrentRecipe.  After the MEMCOPY, CurrentRecipe contains the values that were in Recipe11.  CurrentRecipe.CookTime is what I use in my TMR.

Heap-Items are just single instance (non-ID, non-array) structures.  Program Structs, Task Structs, PID Structs, RampSoak Structs and many system structures are typically heap-items.  But you could create a data-block of PID structs or RampSoak structs, or even Program Struct or Task Struct data-blocks.

Sometimes you want a block of 100.  Sometimes just a bunch of single ones.  But you can do both, or even multiples of both (e.g. have internal subroutine structure names called MySubRecipe, then pass in the CALL Recipe11 into MySubRecipe heap-item, then the Subroutine MySub uses MySubRecipe to generate a STRING describing that recipe into MySubString that is a STRING heap-item, and then move MySubString into SS100 in the CALL Output parameter list.

This is advanced stuff, but heap-items are good for well-named single instance data items.  Data-blocks are good for having a block of something, like Timers or Counters, or especially where you want to do array indexing, like Recipe[V42].

BobO

  • Host Moderator
  • Hero Member
  • *****
  • Posts: 6172
  • Yes Pinky, Do-more will control the world!
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #2 on: September 21, 2017, 08:44:30 AM »
Probably should also offer some background. The primary justification for creating the heap was to give the system a place to allocate the potentially large number of singleton structures that go along with devices. We could have used block memory, but architecturally we are limited to 256 blocks, less really. So we created a new space optimized for storing singletons, and we called it heap because that's what it's commonly called in high level languages. We could have just as easily called them tags...because they are effectively the same.

So now we have two areas for allocation...what goes where? Simple types always go to block memory (can't put simple types on the heap), and system allocated structures always go to heap (that's what we made it for). User allocated structures (using built in types or user created types) can go either place. If the structure is independent and you don't need array indexing, use the heap. If you have a collection of more than one, and you need to index them, use block memory.
"It has recently come to our attention that users spend 95% of their time using 5% of the available features. That might be relevant." -BobO

Mike Nash

  • Hero Member
  • *****
  • Posts: 652
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #3 on: September 21, 2017, 10:41:23 AM »
Thanks gentlemen. After I posted I started thinking about the built-in structures and how we get to use those. I think what maybe threw me was the choice after filling in the info for the UDT of creating a memory block (array) or a structure (single) or neither. I picked memory block the first time and that of course stuck in my brain because it allowed me to have VFD1, VFD2, etc., which was one of the things I was wishing I had in prior versions.

Ironically, my current project isn't going to benefit from these great new features.  :(

But I sure like being able to add a range in documentation such as V1:0 to V3:15. Maybe next release we will see MyUDT1:Bicycle to MyUDT3:Airplane. Yeah, I did try something similar and I wasn't even sure how I would enter something like that so I understand why you didn't add that just yet.

DEBOUNCE is a great new feature, as well as FLASHER. Very clean and intuitive.

Mike Nash

  • Hero Member
  • *****
  • Posts: 652
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #4 on: October 14, 2017, 10:25:49 PM »
Another project to do and I want to try one more time to see if I can have a single UDT that can have both status (inputs) and command (outputs) type fields. I wish I could wait until Do-more can handle this more elegantly for me, but I need this before December anyway.

A MEMCOPY requires ALL of the UDT DWORDS to be copied at once. But I have ten words (5 DWORDS worth) of data being read and 10 being written. I want to read the ten inputs into, lets say, N0-N9 and write N10-N19 in the MRX and MWX instructions.

SO:
MRX N0-N9
MEMCOPY N0-N19 to MyHeapItem  (really want only N0-N9)
MEMCOPY MyHeapItem to N0-N19  (really want only N10-N19)
MWX N10-N19

isn't going to work as I'll be overwriting innies with outies and vice-versa. The alternative I see is writing every element individually, which would be hideous, especially for more than a single device.

Does anyone see a way to MASK, or AND or something to get the desired result? I can do it by having A MyUDTinnies and MyUDTouties and then MyHeapItemsInnies and MyHeapItemOuties (too long I know) but that means two heap items for each Modbus device.

Further, that single UDT is 80 fieldnames since the first two 16 bit words are mapped to 32 bits. The other eight 16 bit words are a mix of signed and unsigned data, then repeat for the outs.

Code: [Select]
"MBTCP" Structure Memory Layout (10 total DWORDs in length, DWORD Offset 0..9)
+------++----------------------------------------------------------------------------------------------------------------------------------++
|      || Most Significant                                                                                               Least Significant ||
|      ++----------------------------------------------------------------------------------------------------------------------------------++
|      ||                                                              DWORD                                                               ||
|      ++----------------------------------------------------------------++----------------------------------------------------------------++
|      ||                             WORD 1                             ||                             WORD 0                             ||
|      ++-------------------------------++-------------------------------++-------------------------------++-------------------------------++
|      ||             BYTE 3            ||             BYTE 2            ||             BYTE 1            ||             BYTE 0            ||
|DWORD ++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++
|Offset||b31|b30|b29|b28|b27|b26|b25|b24||b23|b22|b21|b20|b19|b18|b17|b16||b15|b14|b13|b12|b11|b10| b9| b8|| b7| b6| b5| b4| b3| b2| b1| b0||
+------++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++
Note: Every Bit Field layout only shows the Field # (no name).  See the list of Bit Field Names listed by Field # at the end.

+------++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++
|    0 || 32| 31| 30| 29| 28| 27| 26| 25|| 24| 23| 22| 21| 20| 19| 18| 17|| 16| 15| 14| 13| 12| 11| 10|  9||  8|  7|  6|  5|  4|  3|  2|  1||
+------++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++
|    1 ||  34                       .CurFbkPct                     SWORD ||  33                       .SpdFbkPct                     SWORD ||
+------++----------------------------------------------------------------++----------------------------------------------------------------++
|    2 ||  36                      .HealthStore                    UWORD ||  35                      .HealthWord                     UWORD ||
+------++----------------------------------------------------------------++----------------------------------------------------------------++
|    3 ||  38                      .UserValIn6                     SWORD ||  37                       .LastAlarm                     UWORD ||
+------++----------------------------------------------------------------++----------------------------------------------------------------++
|    4 ||  40                        .ArmAmps                      SWORD ||  39                      .UserValIn7                     SWORD ||
+------++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++
|    5 || 72| 71| 70| 69| 68| 67| 66| 65|| 64| 63| 62| 61| 60| 59| 58| 57|| 56| 55| 54| 53| 52| 51| 50| 49|| 48| 47| 46| 45| 44| 43| 42| 41||
+------++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++---+---+---+---+---+---+---+---++
|    6 ||  74                     .miniLinkVal2                    SWORD ||  73                     .miniLinkVal1                    SWORD ||
+------++----------------------------------------------------------------++----------------------------------------------------------------++
|    7 ||  76                     .miniLinkVal4                    SWORD ||  75                     .miniLinkVal3                    SWORD ||
+------++----------------------------------------------------------------++----------------------------------------------------------------++
|    8 ||  78                     .miniLinkVal6                    SWORD ||  77                     .miniLinkVal5                    SWORD ||
+------++----------------------------------------------------------------++----------------------------------------------------------------++
|    9 ||  80                     .miniLinkVal8                    SWORD ||  79                     .miniLinkVal7                    SWORD ||
+------++----------------------------------------------------------------++----------------------------------------------------------------++

List of Bit Fields by Field #
  #1 (dw 0: 0)  .CoastStop
  #2 (dw 0: 1)  .ProgramStop
  #3 (dw 0: 2)  .Disabled
  #4 (dw 0: 3)  .RunDemanded
  #5 (dw 0: 4)  .JogDemanded
  #6 (dw 0: 5)  .ReservedBit0I5
  #7 (dw 0: 6)  .Alarm
  #8 (dw 0: 7)  .ReservedBit0I7
  #9 (dw 0: 8)  .Running
 #10 (dw 0: 9)  .Enabled
 #11 (dw 0:10)  .ZeroSpeed
 #12 (dw 0:11)  .Healthy
 #13 (dw 0:12)  .Ready
 #14 (dw 0:13)  .ReservedBit0I13
 #15 (dw 0:14)  .ReservedBit0I14
 #16 (dw 0:15)  .ReservedBit0I15
 #17 (dw 0:16)  .Logic1Status
 #18 (dw 0:17)  .Logic2Status
 #19 (dw 0:18)  .Logic3Status
 #20 (dw 0:19)  .Logic4Status
 #21 (dw 0:20)  .Logic5Status
 #22 (dw 0:21)  .Logic6Status
 #23 (dw 0:22)  .FieldEnabled
 #24 (dw 0:23)  .WatchDogPulseIn
 #25 (dw 0:24)  .ReservedBit1I8
 #26 (dw 0:25)  .ReservedBit1I9
 #27 (dw 0:26)  .ReservedBit1I10
 #28 (dw 0:27)  .ReservedBit1I11
 #29 (dw 0:28)  .ReservedBit1I12
 #30 (dw 0:29)  .ReservedBit1I13
 #31 (dw 0:30)  .ReservedBit1I14
 #32 (dw 0:31)  .ReservedBit1I15
 #41 (dw 5: 0)  .RemEnable
 #42 (dw 5: 1)  .RemStart
 #43 (dw 5: 2)  .RemJog
 #44 (dw 5: 3)  .RemJogMode
 #45 (dw 5: 4)  .ReservedBit5o4
 #46 (dw 5: 5)  .ReservedBit5o5
 #47 (dw 5: 6)  .ReservedBit5o6
 #48 (dw 5: 7)  .ReservedBit5o7
 #49 (dw 5: 8)  .RemAlarmAck
 #50 (dw 5: 9)  .RemNotTrip
 #51 (dw 5:10)  .ReservedBit5o10
 #52 (dw 5:11)  .ReservedBit5o11
 #53 (dw 5:12)  .ReservedBit5o12
 #54 (dw 5:13)  .ReservedBit5o13
 #55 (dw 5:14)  .ReservedBit5o14
 #56 (dw 5:15)  .ReservedBit5o15
 #57 (dw 5:16)  .miniLINKLogOut1
 #58 (dw 5:17)  .miniLINKLogOut2
 #59 (dw 5:18)  .miniLINKLogOut3
 #60 (dw 5:19)  .miniLINKLogOut4
 #61 (dw 5:20)  .miniLINKLogOut5
 #62 (dw 5:21)  .miniLINKLogOut6
 #63 (dw 5:22)  .TripResetCmd
 #64 (dw 5:23)  .WatchDogPulseOut
 #65 (dw 5:24)  .ReservedBit6o8
 #66 (dw 5:25)  .ReservedBit6o9
 #67 (dw 5:26)  .ReservedBit6o10
 #68 (dw 5:27)  .ReservedBit6o11
 #69 (dw 5:28)  .ReservedBit6o12
 #70 (dw 5:29)  .ReservedBit6o13
 #71 (dw 5:30)  .ReservedBit6o14
 #72 (dw 5:31)  .ReservedBit6o15

BobO

  • Host Moderator
  • Hero Member
  • *****
  • Posts: 6172
  • Yes Pinky, Do-more will control the world!
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #5 on: October 14, 2017, 11:38:01 PM »
Create union fields for each DWORD of the struct, then it's just 5 assignments for each direction. If you need to do this more than once, put it in a subroutine.
"It has recently come to our attention that users spend 95% of their time using 5% of the available features. That might be relevant." -BobO

Mike Nash

  • Hero Member
  • *****
  • Posts: 652
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #6 on: October 15, 2017, 11:35:01 AM »
I did not realize I could have multiple fields in the structure referencing the same memory location.

I added back the 16 bit fields using Manual Memory Layout and was able to use a COPY instruction with 10 entries to get N0-N9 only into the structure.

I added 10 DWORD fields using manual and was able to use a COPY with 5 entries to get N0:D to N8:D into the structure. I do see all three structure field types showing the same data (bit, SWORD and DWORD).

Then I tried COPY N0:D to the SWORD and it worked, so I don't need the DWORD fields after all.

Then, duh, I tried COPY N0:D to the first bit type field and that works too. So I don't need the status SWORDs either for the bit fields.
(Edit on 10/26/2017 - This is not true. See my post dated 10/26/2017.

But to be fair to myself, Help pretty much found nothing on Unions. I did find something about it on C compilers on the web. I think my takeaway on this is that I can COPY to or from any DWORD in the structure using any field that lays on the 32 bit boundary starting bit, but also that it is going to be 32 bits copied either way.

It also means I can have a plethora of field names that all work exactly the same if manually setting the memory location. "Machine.Start" or "Machine.GoBabyGo", my choice, either or both. Kinda neat.

And most importantly for me, this looks doable without too much clutter.

But I don't yet see how a subroutine would help here with multiple devices. Is there some way to pass a pointer to the structure if they are individual heap items and not memory block arrays?
« Last Edit: October 26, 2017, 02:54:40 PM by Mike Nash »

BobO

  • Host Moderator
  • Hero Member
  • *****
  • Posts: 6172
  • Yes Pinky, Do-more will control the world!
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #7 on: October 15, 2017, 11:56:28 AM »
For now, the subroutine would require a memory block. We will eventually get data types passed as value or reference.
"It has recently come to our attention that users spend 95% of their time using 5% of the available features. That might be relevant." -BobO

Mike Nash

  • Hero Member
  • *****
  • Posts: 652
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #8 on: October 15, 2017, 12:33:21 PM »
I am just not seeing how the subroutine would help here with heap items rather than arrayed memory block.

On previous jobs, arrays would be ideal (VFD1.Start, VFD2.Start, VFD[V0].Start), but I think for this job I might prefer section names. There isn't currently some way to pass a value that would point to a heap item is there? I mean like decoding where MyHeapItem is in memory and then using that in the subroutine to point to MyHeapItem. Just wondering here.

BobO

  • Host Moderator
  • Hero Member
  • *****
  • Posts: 6172
  • Yes Pinky, Do-more will control the world!
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #9 on: October 15, 2017, 01:05:18 PM »
Yes, correct. It would require a memory block.

You are describing passing a structure by reference. The controller supports it, but the work to support it at DmD is considerable.
"It has recently come to our attention that users spend 95% of their time using 5% of the available features. That might be relevant." -BobO

franji1

  • Bit Weenie
  • Host Moderator
  • Hero Member
  • *****
  • Posts: 3843
    • Host Engineering
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #10 on: October 15, 2017, 02:03:44 PM »
Then, duh, I tried COPY N0:D to the first bit type field and that works too.
All that did was copy the 0/non-zero state of N0:D into the first bit type field.
It's basically doing a MOVE N0:D MyStruct.BitA

If N0:D is 0, then the .BitA is FALSE
otherwise, .BitA is TRUE

You will have to do that field by field (using union DWORDs).  If you do that in a subroutine (do not pass any parameters, just do it in a subroutine), then the code at the high level looks cleaner
MRX
CALL MySub
MWX

Mike Nash

  • Hero Member
  • *****
  • Posts: 652
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #11 on: October 15, 2017, 02:31:27 PM »
Then, duh, I tried COPY N0:D to the first bit type field and that works too.
All that did was copy the 0/non-zero state of N0:D into the first bit type field.
It's basically doing a MOVE N0:D MyStruct.BitA

If N0:D is 0, then the .BitA is FALSE
otherwise, .BitA is TRUE

Right, I think. I did this 5 times in the one COPY instruction to get all 32 BITs and 8 SWORDs copied (as 5 DWORDs). Another COPY does the other direction for the outgoing 32 BITS and 8 SWORDs. It's amazingly hard to keep all this straight when I have to actually write it out as text.

Quote
You will have to do that field by field (using union DWORDs).  If you do that in a subroutine (do not pass any parameters, just do it in a subroutine), then the code at the high level looks cleaner
MRX
CALL MySub
MWX
Since it is a single COPY instruction after MRX and another for MWX, it's not really bad. The Comms are in their own Program anyway.

But I would like an opinion on using the MRX success bit to trigger the COPY after the MRX. I don't think I can do that for MWX though since I am loading the data in to be sent.
I will have multiple Modbus TCP Client devices configured.

I have this incredible desire to say something about misspelling DWARF, but I won't.

franji1

  • Bit Weenie
  • Host Moderator
  • Hero Member
  • *****
  • Posts: 3843
    • Host Engineering
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #12 on: October 15, 2017, 02:37:51 PM »
But I would like an opinion on using the MRX success bit to trigger the COPY after the MRX. I don't think I can do that for MWX though since I am loading the data in to be sent.

That is a good way to do it, assuming that you also trigger the MRX based on the same MRX OnSuccess bit (or at least that is one of the enabling conditions for the MWX instruction).

MRX
If MRX.OnSuccss then {COPY; MWX;}

Mike Nash

  • Hero Member
  • *****
  • Posts: 652
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #13 on: October 15, 2017, 06:58:31 PM »
Thank you both for the help! I am hoping this means I am not doing anything here that might be challenged by future software/firmware updates.

BobO

  • Host Moderator
  • Hero Member
  • *****
  • Posts: 6172
  • Yes Pinky, Do-more will control the world!
Re: User Data Type definitions, Heap-Items and Data-Blocks
« Reply #14 on: October 15, 2017, 09:26:19 PM »
Thank you both for the help! I am hoping this means I am not doing anything here that might be challenged by future software/firmware updates.

Not at all.
"It has recently come to our attention that users spend 95% of their time using 5% of the available features. That might be relevant." -BobO