Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Oto System IO Data Structures and Configuration Workflow

Tech 2
TYPE Tag_DigitalIn_Cfg :
STRUCT
    nSlotNo     : INT := 0;   (* Slot index: 0 = onboard, 1..4 = expansion slots *)
    nPinNo      : INT := 0;   (* Pin index: 0 to (max pin per module -1) *)
    nActiveEdge : INT := 0;   (* Trigger level: 0 = low, 1 = high *)
    uNoteRef    : UINT := 0;  (* Reference to descriptive text ID *)
    nDebounceTarget : INT := CNST_DIN_DEBOUNCE_CNT;

    bPrevRaw    : BOOL := 0;
    bCurrRaw    : BOOL := 0;
    nCurrDebounce : INT := 0;
    nStoredDebounce : INT := 0;
END_STRUCT
END_TYPE
TYPE Tag_DigitalOut_Cfg :
STRUCT
    nActive     : INT := 1;
    nSlotNo     : INT := 0;
    nPinNo      : INT := 0;
    nActiveEdge : INT := 0;
    uNoteRef    : UINT := 0;

    nCheckEn    : INT := 0;    (* Output verification toggle: 0 = off, 1 = on *)
    nCheckInIdx : INT := 0;    (* Index of linked input in status array for feedback check *)
    lrPreCheckDel_S : LREAL := 0;
    lrCheckDel_S    : LREAL := 0;
END_STRUCT
END_TYPE
TYPE Tag_DigitalIn_Stat :
STRUCT
    bValidState : BOOL;  (* Filtered and normalized input state: 1 = active *)
END_STRUCT
END_TYPE
TYPE Tag_DigitalOut_Stat :
STRUCT
    bRequestedState : BOOL;
    bValidatedState : BOOL;
END_STRUCT
END_TYPE
VAR_GLOBAL CONSTANT
    CNST_DIN_DEBOUNCE_CNT     : INT := 3;
END_VAR

VAR_GLOBAL
    STS_DIN                   : ARRAY[1..CNST_DIN_TOTAL] OF Tag_DigitalIn_Stat;
    STS_DOUT                  : ARRAY[1..CNST_DOUT_TOTAL] OF Tag_DigitalOut_Stat;

    g_atDIN_Cfg               : ARRAY[1..CNST_DIN_TOTAL] OF Tag_DigitalIn_Cfg;
    g_atDOUT_Cfg              : ARRAY[1..CNST_DOUT_TOTAL] OF Tag_DigitalOut_Cfg;
END_VAR
VAR_GLOBAL CONSTANT
    CNST_DIN_TOTAL            : INT := 52;
    CNST_DOUT_TOTAL           : INT := 28;
END_VAR

VAR_GLOBAL
END_VAR
Init_DIN;
Init_DOUT;
idxExpSlot := 1;
FOR idxAll := 1 TO CNST_DIN_TOTAL DO
    g_atDIN_Cfg[idxAll].uNoteRef := idxAll + 12000;
    IF idxAll <= CNST_LOCAL_DIN_CNT THEN
        g_atDIN_Cfg[idxAll].nSlotNo := 0;
        g_atDIN_Cfg[idxAll].nPinNo := idxAll - 1;
        g_atDIN_Cfg[idxAll].nActiveEdge := 0;
    ELSE
        nOffset := idxAll - CNST_LOCAL_DIN_CNT - (idxExpSlot - 1)*CNST_EXP_DIN_PER_SLOT - 1;
        g_atDIN_Cfg[idxAll].nSlotNo := idxExpSlot;
        g_atDIN_Cfg[idxAll].nPinNo := nOffset;
        g_atDIN_Cfg[idxAll].nActiveEdge := 1;
        IF nOffset >= (CNST_EXP_DIN_PER_SLOT - 1) THEN
            idxExpSlot := idxExpSlot + 1;
        END_IF
    END_IF
END_FOR

fh := SysFileOpen(g_str_DINCfgPath, 'w');
IF fh = 0 THEN
    ALARM_FILE_WRITE_DIN := TRUE;
ELSE
    szCfg := SIZEOF(g_atDIN_Cfg);
    IF szCfg <> SysFileWrite(fh, ADR(g_atDIN_Cfg[1]), szCfg) THEN
        ALARM_FILE_WRITE_DIN := TRUE;
    END_IF
    SysFileClose(fh);
END_IF
fh := 0;
idxExpSlot := 1;
FOR idxAll := 1 TO CNST_DOUT_TOTAL DO
    g_atDOUT_Cfg[idxAll].uNoteRef := idxAll + 13000;
    IF idxAll <= CNST_LOCAL_DOUT_CNT THEN
        g_atDOUT_Cfg[idxAll].nSlotNo := 0;
        g_atDOUT_Cfg[idxAll].nPinNo := idxAll - 1;
        g_atDOUT_Cfg[idxAll].nActiveEdge := 0;
    ELSE
        nOffset := idxAll - CNST_LOCAL_DOUT_CNT - (idxExpSlot - 1)*CNST_EXP_DOUT_PER_SLOT - 1;
        g_atDOUT_Cfg[idxAll].nSlotNo := idxExpSlot;
        g_atDOUT_Cfg[idxAll].nPinNo := nOffset;
        g_atDOUT_Cfg[idxAll].nActiveEdge := 1;
        IF nOffset >= (CNST_EXP_DOUT_PER_SLOT - 1) THEN
            idxExpSlot := idxExpSlot + 1;
        END_IF
    END_IF
END_FOR

fh := SysFileOpen(g_str_DOUTCfgPath, 'w');
IF fh = 0 THEN
    ALARM_FILE_WRITE_DOUT := TRUE;
ELSE
    szCfg := SIZEOF(g_atDOUT_Cfg);
    IF szCfg <> SysFileWrite(fh, ADR(g_atDOUT_Cfg[1]), szCfg) THEN
        ALARM_FILE_WRITE_DOUT := TRUE;
    END_IF
    SysFileClose(fh);
END_IF
fh := 0;
VAR_GLOBAL
    g_fbIOConfig        : IO_CONFIG;
    g_fbIOConfig_Ctrl   : IO_CONFIG_CTRL;
END_VAR
ReadIOCount;
ReadIOSlotAssign;
ReadIOUserLinks;
ReadIOSetMode;
UserLinkProcess;
SaveIOCfgFiles;
diFileSize := SysFileGetSize(str_IOCountPath);
diExpectedSize := 4;
IF diFileSize <> diExpectedSize THEN
    ALARM_GET[10,9] := TRUE;
    bReadFail[1] := TRUE;
ELSE
    dwFileSize := DINT_TO_DWORD(diFileSize);
    fh := SysFileOpen(str_IOCountPath, 'r');
    IF fh = 0 THEN
        ALARM_GET[10,9] := TRUE;
        bReadFail[2] := TRUE;
    ELSE
        IF dwFileSize <> SysFileRead(fh, ADR(IOCount[1]), dwFileSize) THEN
            ALARM_FILE_READ := TRUE;
            ALARM_GET[10,9] := TRUE;
            bReadFail[3] := TRUE;
        END_IF
        SysFileClose(fh);
    END_IF
END_IF
fh := 0;
FOR idxSlot := 1 TO IOCount[1] DO
    FOR idxPin := 1 TO 16 DO
        nLinkIdx := 16*idxSlot + idxPin - 16;
        nUserTarget := IO_UserLinks[nLinkIdx];
        IF nUserTarget <> 0 THEN
            IF IO_SetMode[nLinkIdx] = 0 THEN
                IF GTN_GetDiPhysicCustom(1, IO_SlotAssign[idxSlot], MC_GPI, idxPin, ADR(abRawValues[idxPin]), 1) <> 0 THEN
                    ALARM_GET_DI := TRUE;
                    ALARM_GET[7,1] := TRUE;
                END_IF
                IF nUserTarget = 56 THEN
                    IF nDebounceStep = 0 THEN
                        nDebounceStep := 1;
                        bDebouncePrev := abRawValues[idxPin];
                    ELSE
                        IF nDebounceStep < 2 THEN
                            IF bDebouncePrev = abRawValues[idxPin] THEN
                                nDebounceStep := nDebounceStep + 1;
                            ELSE
                                nDebounceStep := 0;
                            END_IF
                        END_IF
                    END_IF
                    IF nDebounceStep = 2 THEN
                        g_arUserVars[nUserTarget] := 1 - abRawValues[idxPin];
                        nDebounceStep := 0;
                    END_IF
                ELSE
                    g_arUserVars[nUserTarget] := 1 - abRawValues[idxPin];
                END_IF
            ELSE
                nSetVal := BOOL_TO_INT(g_arUserVars[nUserTarget] = 0);
                IF GTN_SetDoPhysicCustom(1, IO_SlotAssign[idxSlot], MC_GPO, idxPin, ADR(nSetVal), 1) <> 0 THEN
                    ALARM_SET_DO := TRUE;
                    ALARM_GET[9,1] := TRUE;
                END_IF
            END_IF
        END_IF
    END_FOR
END_FOR

awWin[1] := awWin1;
awWin[2] := awWin2;
awWin[3] := awWin3;
awWin[4] := awWin4;

IF IOCount[2] <> 0 THEN
    FOR idxGlink := 1 TO IOCount[2] DO
        FOR idxGlinkIn := 1 TO 16 DO
            nLinkIdx := 32*idxGlink + idxGlinkIn - 32 + 16*IOCount[1];
            nUserTarget := IO_UserLinks[nLinkIdx];
            IF nUserTarget <> 0 THEN
                g_arUserVars[nUserTarget] := WORD_TO_REAL(SHR(awWin[idxGlink], idxGlinkIn-1) AND 16#0001);
            END_IF
        END_FOR
        FOR idxGlinkOut := 17 TO 32 DO
            nLinkIdx := 32*idxGlink + idxGlinkOut - 32 + 16*IOCount[1];
            nUserTarget := IO_UserLinks[nLinkIdx];
            IF nUserTarget <> 0 THEN
                nOutBitPos := idxGlinkOut - 17;
                bCurrentBit := (SHR(awGlinkOut[idxGlink], nOutBitPos) AND 16#0001) <> 0;
                bRequestedBit := g_arUserVars[nUserTarget] = 1;
                IF bCurrentBit AND NOT bRequestedBit THEN
                    awGlinkOut[idxGlink] := awGlinkOut[idxGlink] - REAL_TO_WORD(EXPT(2, nOutBitPos));
                ELSIF NOT bCurrentBit AND bRequestedBit THEN
                    awGlinkOut[idxGlink] := awGlinkOut[idxGlink] + REAL_TO_WORD(EXPT(2, nOutBitPos));
                END_IF
            END_IF
        END_FOR
    END_FOR
END_IF

awGlinkOut1 := awGlinkOut[1];
awGlinkOut2 := awGlinkOut[2];
awGlinkOut3 := awGlinkOut[3];
awGlinkOut4 := awGlinkOut[4];
fh := SysFileOpen(str_IOSlotPath, 'w');
IF fh = 0 THEN
    ALARM_FILE_WRITE := TRUE;
ELSE
    szWrite := 32;
    IF szWrite <> SysFileWrite(fh, ADR(IO_SlotAssign[1]), szWrite) THEN
        ALARM_FILE_WRITE := TRUE;
    END_IF
    SysFileClose(fh);
END_IF
fh := 0;

fh := SysFileOpen(str_IOUserLinksPath, 'w');
IF fh = 0 THEN
    ALARM_FILE_WRITE := TRUE;
ELSE
    szWrite := 640;
    IF szWrite <> SysFileWrite(fh, ADR(IO_UserLinks[1]), szWrite) THEN
        ALARM_FILE_WRITE := TRUE;
    END_IF
    SysFileClose(fh);
END_IF
fh := 0;

fh := SysFileOpen(str_IOCountPath, 'w');
IF fh = 0 THEN
    ALARM_FILE_WRITE := TRUE;
ELSE
    szWrite := 4;
    IF szWrite <> SysFileWrite(fh, ADR(IOCount[1]), szWrite) THEN
        ALARM_FILE_WRITE := TRUE;
    END_IF
    SysFileClose(fh);
END_IF
fh := 0;

fh := SysFileOpen(str_IOSetModePath, 'w');
IF fh = 0 THEN
    ALARM_FILE_WRITE := TRUE;
ELSE
    szWrite := 400;
    IF szWrite <> SysFileWrite(fh, ADR(IO_SetMode[1]), szWrite) THEN
        ALARM_FILE_WRITE := TRUE;
    END_IF
    SysFileClose(fh);
END_IF
fh := 0;

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.