Subversion Repositories HomeAutomation

Rev

Rev 1511 | Rev 1528 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
1503 myhrman 1
/*-----------------------------------------------------------------------------
2
 * Includes
3
 *---------------------------------------------------------------------------*/
4
#include "act_protectedOutput.h"
5
 
6
 
7
/*-----------------------------------------------------------------------------
8
 * Defines
9
 *---------------------------------------------------------------------------*/
10
#define OUTPUT_ON       (act_protectedOutput_OUTPUT_PIN_ACTIVE_STATE)
11
#define OUTPUT_OFF      (1 - OUTPUT_ON)
12
#define OUTPUT_PIN      act_protectedOutput_OUTPUT_PIN
13
 
14
#define DIAG_ASSERTED   (act_protectedOutput_DIAG_PIN_ASSERTED_STATE)
15
#define DIAG_NORMAL     (1 - DIAG_ASSERTED)
16
#define DIAG_PIN        act_protectedOutput_DIAG_PIN
17
 
18
 
19
/*-----------------------------------------------------------------------------
20
 * Types
21
 *---------------------------------------------------------------------------*/
22
 
23
 
24
/*-----------------------------------------------------------------------------
25
 * Variables
26
 *---------------------------------------------------------------------------*/
27
static uint8_t outputTargetState = OUTPUT_OFF;
28
static uint8_t diagState = DIAG_NORMAL;
29
 
30
// is there a recent status change that we should report via CAN?
31
static uint8_t diagReportPending = 0;
32
 
33
 
34
/*-----------------------------------------------------------------------------
35
 * Internal Function Prototypes
36
 *---------------------------------------------------------------------------*/
37
static void updateOutput(void);
38
static void readDiagPin(void);
39
static void pcIntCallback(uint8_t id, uint8_t status);
40
 
41
 
42
/*-----------------------------------------------------------------------------
43
 * Function Implementations
44
 *---------------------------------------------------------------------------*/
45
 
46
static void updateOutput() {
47
    if (outputTargetState == OUTPUT_OFF) {
48
        gpio_set_statement(OUTPUT_OFF, OUTPUT_PIN);
49
    }
50
    else if (outputTargetState == OUTPUT_ON) {
51
        if (diagState == DIAG_NORMAL) {
52
            gpio_set_statement(OUTPUT_ON, OUTPUT_PIN);
53
        }
54
        else {
55
            // DIAG override, we cannot set ON state right now
56
            gpio_set_statement(OUTPUT_OFF, OUTPUT_PIN);
57
        }
58
    }
59
}
60
 
61
 
62
static void readDiagPin() {
63
    diagState = gpio_get_state(DIAG_PIN);
64
}
65
 
66
 
67
static void pcIntCallback(uint8_t id, uint8_t status) {
68
    // new state of the DIAG pin?
69
    if (id == act_protectedOutput_DIAG_PIN_PCINT) {
70
        diagState = status;
71
        updateOutput();
72
        // DIAG asserted?
73
        if (diagState == DIAG_ASSERTED) {
74
            // if retry-timer mechanism is enabled, initiate timer
75
            if (act_protectedOutput_RETRY_TIMER_TIME_S > 0) {
76
                Timer_SetTimeout(act_protectedOutput_RETRY_TIMER, act_protectedOutput_RETRY_TIMER_TIME_S*1000, TimerTypeOneShot, 0);
77
            }
78
            // if the retry-mechanism is disabled, change the target output state to OFF
79
            else {
80
                outputTargetState = OUTPUT_OFF;
81
            }
82
        }
83
        // something interesting obviously happened. let's report it
84
        diagReportPending = 1;
85
    }
86
}
87
 
88
 
89
void act_protectedOutput_Init() {
90
    if (act_protectedOutput_DIAG_PIN_PULL_ENABLED) {
91
        // if DIAG is asserted low, we need pull-up
92
        gpio_set_statement(act_protectedOutput_DIAG_PIN_ASSERTED_STATE == 0 ? 1 : 0, DIAG_PIN);
93
    }
94
    gpio_set_in(DIAG_PIN);
95
    Pcint_SetCallbackPin(act_protectedOutput_DIAG_PIN_PCINT, DIAG_PIN, &pcIntCallback);
96
 
97
    gpio_set_statement(OUTPUT_OFF, OUTPUT_PIN);
98
    gpio_set_out(act_protectedOutput_OUTPUT_PIN);
99
 
100
    outputTargetState = OUTPUT_OFF;
101
    diagState = DIAG_NORMAL;
102
}
103
 
104
 
105
void act_protectedOutput_Process() {
106
 
107
    // shall we retry to set target output state?
108
    if (Timer_Expired(act_protectedOutput_RETRY_TIMER)) {
109
        // read DIAG pin again and update outputs accordingly
110
        readDiagPin();
111
        updateOutput();
1512 myhrman 112
        if (diagState == DIAG_ASSERTED) {
113
            // if DIAG was still asserted, initiate another timer run
114
            Timer_SetTimeout(act_protectedOutput_RETRY_TIMER, act_protectedOutput_RETRY_TIMER_TIME_S*1000, TimerTypeOneShot, 0);
115
        }
116
        else {
117
            // things went back to normal. report this
118
            diagReportPending = 1;
119
        }
1503 myhrman 120
    }
121
 
122
    // shall we report diag status to CAN?
123
    if (diagReportPending) {
124
        StdCan_Msg_t txMsg;
125
        StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
126
        StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
1511 arune 127
        txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
1504 myhrman 128
        txMsg.Header.ModuleId = act_protectedOutput_ID;
1503 myhrman 129
        txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PINSTATUS;
130
        txMsg.Length = 2;
131
        txMsg.Data[0] = 0; //TODO: add support for more channels
132
        // we follow the standard SNS_INPUT format, but the data corresponds to the "health" rather than physical level
133
        if (diagState == DIAG_NORMAL) {
134
            txMsg.Data[1] = 1;  //healthy, target output state stable
135
        } else {
136
            txMsg.Data[1] = 0;  //not healthy, DIAG pin ASSERTED, not in target output state
137
        }
138
        while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
139
        diagReportPending = 0;
140
    }
141
}
142
 
143
 
144
void act_protectedOutput_HandleMessage(StdCan_Msg_t *rxMsg) {
145
    if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_ACT &&
146
        StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_TO_OWNER &&
1511 arune 147
        rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT &&
1503 myhrman 148
        rxMsg->Header.ModuleId == act_protectedOutput_ID)
149
    {
150
        switch (rxMsg->Header.Command) {
151
 
152
            case CAN_MODULE_CMD_PHYSICAL_SETPIN:
153
 
154
                if (rxMsg->Length == 2) {
155
                    //TODO: add support for more channels
156
                    if (rxMsg->Data[0] == 0) {
157
                        outputTargetState = rxMsg->Data[1];
158
                        readDiagPin();
159
                        updateOutput();
160
                    }              
161
                    StdCan_Set_direction(rxMsg->Header, DIRECTIONFLAG_FROM_OWNER);
162
                    rxMsg->Length = 2;
163
                    while (StdCan_Put(rxMsg) != StdCan_Ret_OK);
164
                }
165
                break;
166
        }
167
    }
168
}
169
 
170
 
171
void act_protectedOutput_List(uint8_t ModuleSequenceNumber)
172
{
173
    StdCan_Msg_t txMsg;
174
    StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_ACT);
175
    StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
1511 arune 176
    txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
1503 myhrman 177
    txMsg.Header.ModuleId = act_protectedOutput_ID;
178
    txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
179
    txMsg.Length = 6;
180
 
181
    txMsg.Data[0] = NODE_HW_ID_BYTE0;
182
    txMsg.Data[1] = NODE_HW_ID_BYTE1;
183
    txMsg.Data[2] = NODE_HW_ID_BYTE2;
184
    txMsg.Data[3] = NODE_HW_ID_BYTE3;
185
 
186
    txMsg.Data[4] = NUMBER_OF_MODULES;
187
    txMsg.Data[5] = ModuleSequenceNumber;
188
 
189
    while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
190
}
191