Subversion Repositories HomeAutomation

Rev

Rev 1512 | Rev 1532 | 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
 *---------------------------------------------------------------------------*/
1528 myhrman 10
#define OUTPUT0_ON      (act_protectedOutput_OUTPUT0_PIN_ACTIVE_STATE)
11
#define OUTPUT0_OFF     (1 - OUTPUT0_ON)
12
#define OUTPUT0_PIN     act_protectedOutput_OUTPUT0_PIN
1503 myhrman 13
 
1528 myhrman 14
#define OUTPUT1_ON      (act_protectedOutput_OUTPUT1_PIN_ACTIVE_STATE)
15
#define OUTPUT1_OFF     (1 - OUTPUT1_ON)
16
#define OUTPUT1_PIN     act_protectedOutput_OUTPUT1_PIN
17
 
18
#define OUTPUT2_ON      (act_protectedOutput_OUTPUT2_PIN_ACTIVE_STATE)
19
#define OUTPUT2_OFF     (1 - OUTPUT2_ON)
20
#define OUTPUT2_PIN     act_protectedOutput_OUTPUT2_PIN
21
 
22
#define OUTPUT3_ON      (act_protectedOutput_OUTPUT3_PIN_ACTIVE_STATE)
23
#define OUTPUT3_OFF     (1 - OUTPUT3_ON)
24
#define OUTPUT3_PIN     act_protectedOutput_OUTPUT3_PIN
25
 
1503 myhrman 26
#define DIAG_ASSERTED   (act_protectedOutput_DIAG_PIN_ASSERTED_STATE)
27
#define DIAG_NORMAL     (1 - DIAG_ASSERTED)
28
#define DIAG_PIN        act_protectedOutput_DIAG_PIN
29
 
30
 
31
/*-----------------------------------------------------------------------------
32
 * Types
33
 *---------------------------------------------------------------------------*/
34
 
35
 
36
/*-----------------------------------------------------------------------------
37
 * Variables
38
 *---------------------------------------------------------------------------*/
1528 myhrman 39
 
40
static uint8_t outputStateTarget[act_protectedOutput_NR_OUTPUT_PINS];
41
 
1503 myhrman 42
static uint8_t diagState = DIAG_NORMAL;
43
 
44
// is there a recent status change that we should report via CAN?
45
static uint8_t diagReportPending = 0;
46
 
47
 
48
/*-----------------------------------------------------------------------------
49
 * Internal Function Prototypes
50
 *---------------------------------------------------------------------------*/
51
static void updateOutput(void);
52
static void readDiagPin(void);
53
static void pcIntCallback(uint8_t id, uint8_t status);
54
 
55
 
56
/*-----------------------------------------------------------------------------
57
 * Function Implementations
58
 *---------------------------------------------------------------------------*/
59
 
60
static void updateOutput() {
1528 myhrman 61
 
62
    #if act_protectedOutput_NR_OUTPUT_PINS >= 1
63
    if (outputStateTarget[0] == 0) {
64
        gpio_set_statement(OUTPUT0_OFF, OUTPUT0_PIN);
1503 myhrman 65
    }
1528 myhrman 66
    else if (outputStateTarget[0] == 1) {
1503 myhrman 67
        if (diagState == DIAG_NORMAL) {
1528 myhrman 68
            gpio_set_statement(OUTPUT0_ON, OUTPUT0_PIN);
1503 myhrman 69
        }
70
        else {
71
            // DIAG override, we cannot set ON state right now
1528 myhrman 72
            gpio_set_statement(OUTPUT0_OFF, OUTPUT0_PIN);
1503 myhrman 73
        }
74
    }
1528 myhrman 75
    #endif
76
 
77
    #if act_protectedOutput_NR_OUTPUT_PINS >= 2
78
    if (outputStateTarget[1] == 0) {
79
        gpio_set_statement(OUTPUT1_OFF, OUTPUT1_PIN);
80
    }
81
    else if (outputStateTarget[1] == 1) {
82
        if (diagState == DIAG_NORMAL) {
83
            gpio_set_statement(OUTPUT1_ON, OUTPUT1_PIN);
84
        }
85
        else {
86
            // DIAG override, we cannot set ON state right now
87
            gpio_set_statement(OUTPUT1_OFF, OUTPUT1_PIN);
88
        }
89
    }
90
    #endif
91
 
92
    #if act_protectedOutput_NR_OUTPUT_PINS >= 3
93
    if (outputStateTarget[2] == 0) {
94
        gpio_set_statement(OUTPUT2_OFF, OUTPUT2_PIN);
95
    }
96
    else if (outputStateTarget[2] == 1) {
97
        if (diagState == DIAG_NORMAL) {
98
            gpio_set_statement(OUTPUT2_ON, OUTPUT2_PIN);
99
        }
100
        else {
101
            // DIAG override, we cannot set ON state right now
102
            gpio_set_statement(OUTPUT2_OFF, OUTPUT2_PIN);
103
        }
104
    }
105
    #endif
106
 
107
    #if act_protectedOutput_NR_OUTPUT_PINS >= 4
108
    if (outputStateTarget[3] == 0) {
109
        gpio_set_statement(OUTPUT3_OFF, OUTPUT3_PIN);
110
    }
111
    else if (outputStateTarget[3] == 1) {
112
        if (diagState == DIAG_NORMAL) {
113
            gpio_set_statement(OUTPUT3_ON, OUTPUT3_PIN);
114
        }
115
        else {
116
            // DIAG override, we cannot set ON state right now
117
            gpio_set_statement(OUTPUT3_OFF, OUTPUT3_PIN);
118
        }
119
    }
120
    #endif
1503 myhrman 121
}
122
 
123
 
124
static void readDiagPin() {
125
    diagState = gpio_get_state(DIAG_PIN);
126
}
127
 
128
 
129
static void pcIntCallback(uint8_t id, uint8_t status) {
130
    // new state of the DIAG pin?
131
    if (id == act_protectedOutput_DIAG_PIN_PCINT) {
132
        diagState = status;
133
        updateOutput();
134
        // DIAG asserted?
135
        if (diagState == DIAG_ASSERTED) {
136
            // if retry-timer mechanism is enabled, initiate timer
137
            if (act_protectedOutput_RETRY_TIMER_TIME_S > 0) {
138
                Timer_SetTimeout(act_protectedOutput_RETRY_TIMER, act_protectedOutput_RETRY_TIMER_TIME_S*1000, TimerTypeOneShot, 0);
139
            }
140
            // if the retry-mechanism is disabled, change the target output state to OFF
141
            else {
1528 myhrman 142
                for (uint8_t i=0; i<act_protectedOutput_NR_OUTPUT_PINS; i++) {
143
                    outputStateTarget[i] = 0;
144
                }
1503 myhrman 145
            }
146
        }
147
        // something interesting obviously happened. let's report it
148
        diagReportPending = 1;
149
    }
150
}
151
 
152
 
153
void act_protectedOutput_Init() {
1528 myhrman 154
    /*
155
     * Configure DIAG input pin
156
     */
1503 myhrman 157
    if (act_protectedOutput_DIAG_PIN_PULL_ENABLED) {
158
        // if DIAG is asserted low, we need pull-up
159
        gpio_set_statement(act_protectedOutput_DIAG_PIN_ASSERTED_STATE == 0 ? 1 : 0, DIAG_PIN);
160
    }
161
    gpio_set_in(DIAG_PIN);
162
    Pcint_SetCallbackPin(act_protectedOutput_DIAG_PIN_PCINT, DIAG_PIN, &pcIntCallback);
163
 
1528 myhrman 164
    /*
165
     * Configure OUTPUT pins
166
     */
167
    #if act_protectedOutput_NR_OUTPUT_PINS >= 1
168
    gpio_set_statement(OUTPUT0_OFF, OUTPUT0_PIN);
169
    gpio_set_out(act_protectedOutput_OUTPUT0_PIN);
170
    #endif
1503 myhrman 171
 
1528 myhrman 172
    #if act_protectedOutput_NR_OUTPUT_PINS >= 2
173
    gpio_set_statement(OUTPUT1_OFF, OUTPUT1_PIN);
174
    gpio_set_out(act_protectedOutput_OUTPUT1_PIN);
175
    #endif
176
 
177
    #if act_protectedOutput_NR_OUTPUT_PINS >= 3
178
    gpio_set_statement(OUTPUT2_OFF, OUTPUT2_PIN);
179
    gpio_set_out(act_protectedOutput_OUTPUT2_PIN);
180
    #endif
181
 
182
    #if act_protectedOutput_NR_OUTPUT_PINS >= 4
183
    gpio_set_statement(OUTPUT3_OFF, OUTPUT3_PIN);
184
    gpio_set_out(act_protectedOutput_OUTPUT3_PIN);
185
    #endif
186
 
187
    for (uint8_t i=0; i<act_protectedOutput_NR_OUTPUT_PINS; i++) {
188
        outputStateTarget[i] = 0;
189
    }
190
 
1503 myhrman 191
    diagState = DIAG_NORMAL;
192
}
193
 
194
 
195
void act_protectedOutput_Process() {
196
 
197
    // shall we retry to set target output state?
198
    if (Timer_Expired(act_protectedOutput_RETRY_TIMER)) {
199
        // read DIAG pin again and update outputs accordingly
200
        readDiagPin();
201
        updateOutput();
1512 myhrman 202
        if (diagState == DIAG_ASSERTED) {
203
            // if DIAG was still asserted, initiate another timer run
204
            Timer_SetTimeout(act_protectedOutput_RETRY_TIMER, act_protectedOutput_RETRY_TIMER_TIME_S*1000, TimerTypeOneShot, 0);
205
        }
206
        else {
207
            // things went back to normal. report this
208
            diagReportPending = 1;
209
        }
1503 myhrman 210
    }
211
 
212
    // shall we report diag status to CAN?
213
    if (diagReportPending) {
214
        StdCan_Msg_t txMsg;
215
        StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
216
        StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
1511 arune 217
        txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
1504 myhrman 218
        txMsg.Header.ModuleId = act_protectedOutput_ID;
1503 myhrman 219
        txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PINSTATUS;
220
        txMsg.Length = 2;
221
        txMsg.Data[0] = 0; //TODO: add support for more channels
222
        // we follow the standard SNS_INPUT format, but the data corresponds to the "health" rather than physical level
223
        if (diagState == DIAG_NORMAL) {
224
            txMsg.Data[1] = 1;  //healthy, target output state stable
225
        } else {
226
            txMsg.Data[1] = 0;  //not healthy, DIAG pin ASSERTED, not in target output state
227
        }
228
        while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
229
        diagReportPending = 0;
230
    }
231
}
232
 
233
 
234
void act_protectedOutput_HandleMessage(StdCan_Msg_t *rxMsg) {
235
    if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_ACT &&
236
        StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_TO_OWNER &&
1511 arune 237
        rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT &&
1503 myhrman 238
        rxMsg->Header.ModuleId == act_protectedOutput_ID)
239
    {
240
        switch (rxMsg->Header.Command) {
241
 
242
            case CAN_MODULE_CMD_PHYSICAL_SETPIN:
243
 
244
                if (rxMsg->Length == 2) {
1528 myhrman 245
                    uint8_t channel = rxMsg->Data[0];
246
                    if (channel >= 0 && channel < act_protectedOutput_NR_OUTPUT_PINS) {
247
                        outputStateTarget[channel] = rxMsg->Data[1];
1503 myhrman 248
                        readDiagPin();
249
                        updateOutput();
250
                    }              
251
                    StdCan_Set_direction(rxMsg->Header, DIRECTIONFLAG_FROM_OWNER);
252
                    rxMsg->Length = 2;
253
                    while (StdCan_Put(rxMsg) != StdCan_Ret_OK);
254
                }
255
                break;
256
        }
257
    }
258
}
259
 
260
 
261
void act_protectedOutput_List(uint8_t ModuleSequenceNumber)
262
{
263
    StdCan_Msg_t txMsg;
264
    StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_ACT);
265
    StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
1511 arune 266
    txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
1503 myhrman 267
    txMsg.Header.ModuleId = act_protectedOutput_ID;
268
    txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
269
    txMsg.Length = 6;
270
 
271
    txMsg.Data[0] = NODE_HW_ID_BYTE0;
272
    txMsg.Data[1] = NODE_HW_ID_BYTE1;
273
    txMsg.Data[2] = NODE_HW_ID_BYTE2;
274
    txMsg.Data[3] = NODE_HW_ID_BYTE3;
275
 
276
    txMsg.Data[4] = NUMBER_OF_MODULES;
277
    txMsg.Data[5] = ModuleSequenceNumber;
278
 
279
    while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
280
}
281