freddofrog
Member
Darren, below is the source code for FC397 which shows an example of using any pointers as well as AR1 (address register 1). FC397 extracts the bit number, byte number and area type for an I, Q or M. It returns "?" if the area is not one of the above. (Other areas can be extracted, I've just not included them in this example). Also included is the source code for FC398 which calls FC397 with four different areas. If you cut/paste this into a source code file and then compile, it should generate these two blocks in your blocks folder. Call FC398 from OB1 and then monitor FC398.
FUNCTIONFC 397 : VOID
TITLE =Find byte and bit address ofI, Q, or M
VAR_INPUT
pIOAddress : ANY ;
END_VAR
VAR_OUTPUT
iByteAddress : INT ;
iBitAddress : INT ;
cAreaIQorM : CHAR ; //area I,Q or M or ?
END_VAR
BEGIN
NETWORK
TITLE =decode input pointertype and get byte/bit address
L P##pIOAddress; //point to input parameter
LAR1 ;
LB [AR1,P#6.0]; //get address area
L W#16#81; // I area ?
==I ;
JC inpu;
TAK ;
L W#16#82; // Q area ?
==I ;
JC outp;
TAK ;
L W#16#83; // M area ?
==I ;
JC mflg;
L '?'; // not any of the above
T #cAreaIQorM;
JU nof;
inpu: L 'I';
T #cAreaIQorM;
JU nof;
outp: L 'Q';
T #cAreaIQorM;
JU nof;
mflg: L 'M';
T #cAreaIQorM;
JU nof;
nof: LB [AR1,P#9.0]; //lower 3 bits of byte 9 of area is bit address
AW W#16#7;
T #iBitAddress; //bit address
LD [AR1,P#6.0];
AD DW#16#3FFFF; //mask off operand area
SRD 3; //and shift to get byte address
T #iByteAddress;
SET ; //ENO = 1
SAVE ; END_FUNCTION
FUNCTIONFC 398 : VOID
TITLE =test FC397
VERSION : 0.1
VAR_TEMP
iByteAddress : INT ;
iBitAddress : INT ;
cArea : CHAR ;
END_VAR
BEGIN
NETWORK
TITLE =call FC397 with 4 different pointers
CALLFC 397 (
pIOAddress :=I 9.3,
iByteAddress := #iByteAddress,
iBitAddress := #iBitAddress,
cAreaIQorM := #cArea);
CALLFC 397 (
pIOAddress :="IntAutoLoad",
iByteAddress := #iByteAddress,
iBitAddress := #iBitAddress,
cAreaIQorM := #cArea);
CALLFC 397 (
pIOAddress :="bBowedRollReverseQ",
iByteAddress := #iByteAddress,
iBitAddress := #iBitAddress,
cAreaIQorM := #cArea);
CALLFC 397 (
pIOAddress := DB100.DBX 30.6,
iByteAddress := #iByteAddress,
iBitAddress := #iBitAddress,
cAreaIQorM := #cArea);
END_FUNCTION
this is a poor example of pointer control. Right at the very start of the code when the address register was loaded, you should of performed a SLW 3 and started the P# pointer calls at 0.0 instead of 6.0
EG
L #VLT_ADDRESS // Load drive base address in I/O Area
SLW 3
LAR1 // Load address register AR1 with drive base address
L PIW [AR1,P#0.0] // Move Drive Status Word from I/O Area
T #VLT_STATUS // into the instance data word (ZCD_ZSW)
L PIW [AR1,P#2.0] // Move Main Actual Value from I/O Area
T #VLT_MAV // into the instance data word (PZD_HIW)
L PIW [AR1,P#4.0] // Move PCD 3 Value from I/O Area
T #VLT_PCD3 // into the instance data word (PZD_HIW)
Last edited: