Subversion Repositories HomeAutomation

Rev

Rev 1538 | 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
 
1532 myhrman 11
// make sure all config params are present
1528 myhrman 12
 
1532 myhrman 13
#ifndef act_protectedOutput_CH_COUNT
14
#error Config value missing: "act_protectedOutput_CH_COUNT"
15
#endif
1528 myhrman 16
 
1532 myhrman 17
#ifndef act_protectedOutput_EEPROM_ENABLED
18
#error Config value missing: "act_protectedOutput_EEPROM_ENABLED"
19
#endif
1528 myhrman 20
 
1532 myhrman 21
#if act_protectedOutput_CH_COUNT >= 1
22
#ifndef act_protectedOutput_CH0
23
#error Config value missing: "act_protectedOutput_CH0"
24
#endif
25
#ifndef act_protectedOutput_CH0_POLARITY
26
#error Config value missing: "act_protectedOutput_CH0_POLARITY"
27
#endif
28
#endif
29
 
30
#if act_protectedOutput_CH_COUNT >= 2
31
#ifndef act_protectedOutput_CH1
32
#error Config value missing: "act_protectedOutput_CH1"
33
#endif
34
#ifndef act_protectedOutput_CH1_POLARITY
35
#error Config value missing: "act_protectedOutput_CH1_POLARITY"
36
#endif
37
#endif
38
 
39
#if act_protectedOutput_CH_COUNT >= 3
40
#ifndef act_protectedOutput_CH2
41
#error Config value missing: "act_protectedOutput_CH2"
42
#endif
43
#ifndef act_protectedOutput_CH2_POLARITY
44
#error Config value missing: "act_protectedOutput_CH2_POLARITY"
45
#endif
46
#endif
47
 
48
#if act_protectedOutput_CH_COUNT >= 4
49
#ifndef act_protectedOutput_CH3
50
#error Config value missing: "act_protectedOutput_CH3"
51
#endif
52
#ifndef act_protectedOutput_CH3_POLARITY
53
#error Config value missing: "act_protectedOutput_CH3_POLARITY"
54
#endif
55
#endif
56
 
57
#if act_protectedOutput_CH_COUNT >= 5
58
#error Config value out of range: "act_protectedOutput_CH_COUNT"
59
#endif
60
 
61
#define CH0_ON      (act_protectedOutput_CH0_POLARITY)
62
#define CH0_OFF     (1 - CH0_ON)
63
#define CH0_PIN     act_protectedOutput_CH0
64
 
65
#define CH1_ON      (act_protectedOutput_CH1_POLARITY)
66
#define CH1_OFF     (1 - CH1_ON)
67
#define CH1_PIN     act_protectedOutput_CH1
68
 
69
#define CH2_ON      (act_protectedOutput_CH2_POLARITY)
70
#define CH2_OFF     (1 - CH2_ON)
71
#define CH2_PIN     act_protectedOutput_CH2
72
 
73
#define CH3_ON      (act_protectedOutput_CH3_POLARITY)
74
#define CH3_OFF     (1 - CH3_ON)
75
#define CH3_PIN     act_protectedOutput_CH3
76
 
77
#define DIAG_ASSERTED   (act_protectedOutput_DIAG_PIN_POLARITY)
1503 myhrman 78
#define DIAG_NORMAL     (1 - DIAG_ASSERTED)
79
#define DIAG_PIN        act_protectedOutput_DIAG_PIN
80
 
81
 
82
/*-----------------------------------------------------------------------------
83
 * Types
84
 *---------------------------------------------------------------------------*/
85
 
86
 
1532 myhrman 87
#if act_protectedOutput_EEPROM_ENABLED == 1
88
#include "act_protectedOutput_eeprom.h"
89
struct eeprom_act_protectedOutput EEMEM eeprom_act_protectedOutput =
90
{
91
    {
92
        ///TODO: Define initialization values on the EEPROM variables here, this will generate a *.eep file that can be used to store this values to the node, can in future be done with a EEPROM module and the make-scrips. Write the values in the exact same order as the struct is defined in the *.h file.
93
#if act_protectedOutput_CH_COUNT >= 1
94
        0x00,
95
#endif
96
#if act_protectedOutput_CH_COUNT >= 2
97
        0x00,
98
#endif
99
#if act_protectedOutput_CH_COUNT >= 3
100
        0x00,
101
#endif
102
#if act_protectedOutput_CH_COUNT >= 4
103
        0x00,
104
#endif
105
    },
106
 
107
};
108
#endif
109
 
110
 
1503 myhrman 111
/*-----------------------------------------------------------------------------
112
 * Variables
113
 *---------------------------------------------------------------------------*/
1528 myhrman 114
 
1537 myhrman 115
static uint8_t chTargetState[act_protectedOutput_CH_COUNT];
1503 myhrman 116
static uint8_t diagState = DIAG_NORMAL;
117
 
118
// is there a recent status change that we should report via CAN?
119
static uint8_t diagReportPending = 0;
120
 
121
 
122
/*-----------------------------------------------------------------------------
123
 * Internal Function Prototypes
124
 *---------------------------------------------------------------------------*/
1537 myhrman 125
static void updateOutput(uint8_t skipDiagCheck);
1503 myhrman 126
static void readDiagPin(void);
127
static void pcIntCallback(uint8_t id, uint8_t status);
128
 
129
 
130
/*-----------------------------------------------------------------------------
131
 * Function Implementations
132
 *---------------------------------------------------------------------------*/
133
 
1537 myhrman 134
static void updateOutput(uint8_t skipDiagCheck) {
1528 myhrman 135
 
1532 myhrman 136
    #if act_protectedOutput_CH_COUNT >= 1
1537 myhrman 137
    if (chTargetState[0] == 0) {
1532 myhrman 138
        gpio_set_statement(CH0_OFF, CH0_PIN);
1503 myhrman 139
    }
1537 myhrman 140
    else if (chTargetState[0] == 1) {
141
        if (diagState == DIAG_NORMAL || skipDiagCheck) {
1532 myhrman 142
            gpio_set_statement(CH0_ON, CH0_PIN);
1503 myhrman 143
        }
144
        else {
145
            // DIAG override, we cannot set ON state right now
1532 myhrman 146
            gpio_set_statement(CH0_OFF, CH0_PIN);
1503 myhrman 147
        }
148
    }
1528 myhrman 149
    #endif
150
 
1532 myhrman 151
    #if act_protectedOutput_CH_COUNT >= 2
1537 myhrman 152
    if (chTargetState[1] == 0) {
1532 myhrman 153
        gpio_set_statement(CH1_OFF, CH1_PIN);
1528 myhrman 154
    }
1537 myhrman 155
    else if (chTargetState[1] == 1) {
156
        if (diagState == DIAG_NORMAL || skipDiagCheck) {
1532 myhrman 157
            gpio_set_statement(CH1_ON, CH1_PIN);
1528 myhrman 158
        }
159
        else {
160
            // DIAG override, we cannot set ON state right now
1532 myhrman 161
            gpio_set_statement(CH1_OFF, CH1_PIN);
1528 myhrman 162
        }
163
    }
164
    #endif
165
 
1532 myhrman 166
    #if act_protectedOutput_CH_COUNT >= 3
1537 myhrman 167
    if (chTargetState[2] == 0) {
1532 myhrman 168
        gpio_set_statement(CH2_OFF, CH2_PIN);
1528 myhrman 169
    }
1537 myhrman 170
    else if (chTargetState[2] == 1) {
171
        if (diagState == DIAG_NORMAL || skipDiagCheck) {
1532 myhrman 172
            gpio_set_statement(CH2_ON, CH2_PIN);
1528 myhrman 173
        }
174
        else {
175
            // DIAG override, we cannot set ON state right now
1532 myhrman 176
            gpio_set_statement(CH2_OFF, CH2_PIN);
1528 myhrman 177
        }
178
    }
179
    #endif
180
 
1532 myhrman 181
    #if act_protectedOutput_CH_COUNT >= 4
1537 myhrman 182
    if (chTargetState[3] == 0) {
1532 myhrman 183
        gpio_set_statement(CH3_OFF, CH3_PIN);
1528 myhrman 184
    }
1537 myhrman 185
    else if (chTargetState[3] == 1) {
186
        if (diagState == DIAG_NORMAL || skipDiagCheck) {
1532 myhrman 187
            gpio_set_statement(CH3_ON, CH3_PIN);
1528 myhrman 188
        }
189
        else {
190
            // DIAG override, we cannot set ON state right now
1532 myhrman 191
            gpio_set_statement(CH3_OFF, CH3_PIN);
1528 myhrman 192
        }
193
    }
194
    #endif
1503 myhrman 195
}
196
 
197
 
198
static void readDiagPin() {
199
    diagState = gpio_get_state(DIAG_PIN);
200
}
201
 
202
 
203
static void pcIntCallback(uint8_t id, uint8_t status) {
204
    // new state of the DIAG pin?
205
    if (id == act_protectedOutput_DIAG_PIN_PCINT) {
1538 arune 206
        //diagState = status;
207
        readDiagPin();
1537 myhrman 208
        updateOutput(0);
1503 myhrman 209
        // DIAG asserted?
210
        if (diagState == DIAG_ASSERTED) {
211
            // if retry-timer mechanism is enabled, initiate timer
212
            if (act_protectedOutput_RETRY_TIMER_TIME_S > 0) {
213
                Timer_SetTimeout(act_protectedOutput_RETRY_TIMER, act_protectedOutput_RETRY_TIMER_TIME_S*1000, TimerTypeOneShot, 0);
214
            }
215
            // if the retry-mechanism is disabled, change the target output state to OFF
216
            else {
1532 myhrman 217
                for (uint8_t i=0; i<act_protectedOutput_CH_COUNT; i++) {
1537 myhrman 218
                    chTargetState[i] = 0;
1528 myhrman 219
                }
1537 myhrman 220
#if act_protectedOutput_EEPROM_ENABLED == 1
221
                // output states changed, store to EE after this timer delay
222
                Timer_SetTimeout(act_protectedOutput_STORE_VALUE_TIMEOUT, act_protectedOutput_STORE_VALUE_TIMEOUT_TIME_S*1000, TimerTypeOneShot, 0);
223
#endif
1503 myhrman 224
            }
225
        }
226
        // something interesting obviously happened. let's report it
227
        diagReportPending = 1;
228
    }
229
}
230
 
231
 
232
void act_protectedOutput_Init() {
1528 myhrman 233
    /*
1532 myhrman 234
     * Init target state vector, in case EEPROM is disabled
235
     */
236
    for (uint8_t i=0; i<act_protectedOutput_CH_COUNT; i++) {
1537 myhrman 237
        chTargetState[i] = 0;
1532 myhrman 238
    }
239
 
240
    /*
1528 myhrman 241
     * Configure DIAG input pin
242
     */
1503 myhrman 243
    if (act_protectedOutput_DIAG_PIN_PULL_ENABLED) {
244
        // if DIAG is asserted low, we need pull-up
1532 myhrman 245
        gpio_set_statement(act_protectedOutput_DIAG_PIN_POLARITY == 0 ? 1 : 0, DIAG_PIN);
1503 myhrman 246
    }
247
    gpio_set_in(DIAG_PIN);
248
    Pcint_SetCallbackPin(act_protectedOutput_DIAG_PIN_PCINT, DIAG_PIN, &pcIntCallback);
249
 
1528 myhrman 250
    /*
1538 arune 251
     * Read EEPROM data
1532 myhrman 252
     */
1535 myhrman 253
#if act_protectedOutput_EEPROM_ENABLED == 1
1534 myhrman 254
    if (EEDATA_OK) {
1532 myhrman 255
#if act_protectedOutput_CH_COUNT >= 1
1537 myhrman 256
      chTargetState[0] = eeprom_read_byte(EEDATA.ch0);
1532 myhrman 257
#endif
258
#if act_protectedOutput_CH_COUNT >= 2
1537 myhrman 259
      chTargetState[1] = eeprom_read_byte(EEDATA.ch1);
1532 myhrman 260
#endif
261
#if act_protectedOutput_CH_COUNT >= 3
1537 myhrman 262
      chTargetState[2] = eeprom_read_byte(EEDATA.ch2);
1532 myhrman 263
#endif
264
#if act_protectedOutput_CH_COUNT >= 4
1537 myhrman 265
      chTargetState[3] = eeprom_read_byte(EEDATA.ch3);
1532 myhrman 266
#endif
267
    }
268
    else {
269
        //The CRC of the EEPROM is not correct, store default values and update CRC
270
#if act_protectedOutput_CH_COUNT >= 1
271
        eeprom_write_byte_crc(EEDATA.ch0, 0x00, WITHOUT_CRC);
272
#endif
273
#if act_protectedOutput_CH_COUNT >= 2
274
        eeprom_write_byte_crc(EEDATA.ch1, 0x00, WITHOUT_CRC);
275
#endif
276
#if act_protectedOutput_CH_COUNT >= 3
277
        eeprom_write_byte_crc(EEDATA.ch2, 0x00, WITHOUT_CRC);
278
#endif
279
#if act_protectedOutput_CH_COUNT >= 4
280
        eeprom_write_byte_crc(EEDATA.ch3, 0x00, WITHOUT_CRC);
281
#endif
282
        EEDATA_UPDATE_CRC;
283
    }
284
#endif
285
 
286
    /*
1538 arune 287
     * Configure OUTPUT pins
1528 myhrman 288
     */
1532 myhrman 289
    #if act_protectedOutput_CH_COUNT >= 1
290
    gpio_set_statement(CH0_OFF, CH0_PIN);
291
    gpio_set_out(act_protectedOutput_CH0);
1528 myhrman 292
    #endif
1503 myhrman 293
 
1532 myhrman 294
    #if act_protectedOutput_CH_COUNT >= 2
295
    gpio_set_statement(CH1_OFF, CH1_PIN);
296
    gpio_set_out(act_protectedOutput_CH1);
1528 myhrman 297
    #endif
298
 
1532 myhrman 299
    #if act_protectedOutput_CH_COUNT >= 3
300
    gpio_set_statement(CH2_OFF, CH2_PIN);
301
    gpio_set_out(act_protectedOutput_CH2);
1528 myhrman 302
    #endif
303
 
1532 myhrman 304
    #if act_protectedOutput_CH_COUNT >= 4
305
    gpio_set_statement(CH3_OFF, CH3_PIN);
306
    gpio_set_out(act_protectedOutput_CH3);
1528 myhrman 307
    #endif
308
 
1503 myhrman 309
    diagState = DIAG_NORMAL;
310
}
311
 
312
 
313
void act_protectedOutput_Process() {
314
 
1535 myhrman 315
#if act_protectedOutput_EEPROM_ENABLED == 1
1534 myhrman 316
    if (Timer_Expired(act_protectedOutput_STORE_VALUE_TIMEOUT)) {
317
#if act_protectedOutput_CH_COUNT >= 1
1537 myhrman 318
        eeprom_write_byte_crc(EEDATA.ch0, chTargetState[0], WITHOUT_CRC);
1534 myhrman 319
#endif
320
#if act_protectedOutput_CH_COUNT >= 2
1537 myhrman 321
        eeprom_write_byte_crc(EEDATA.ch1, chTargetState[1], WITHOUT_CRC);
1534 myhrman 322
#endif
323
#if act_protectedOutput_CH_COUNT >= 3
1537 myhrman 324
        eeprom_write_byte_crc(EEDATA.ch2, chTargetState[2], WITHOUT_CRC);
1534 myhrman 325
#endif
326
#if act_protectedOutput_CH_COUNT >= 4
1537 myhrman 327
        eeprom_write_byte_crc(EEDATA.ch3, chTargetState[3], WITHOUT_CRC);
1534 myhrman 328
#endif
329
        EEDATA_UPDATE_CRC;
330
    }
1535 myhrman 331
#endif
1534 myhrman 332
 
1503 myhrman 333
    // shall we retry to set target output state?
334
    if (Timer_Expired(act_protectedOutput_RETRY_TIMER)) {
335
        // read DIAG pin again and update outputs accordingly
336
        readDiagPin();
1537 myhrman 337
#if act_protectedOutput_FORCED_RETRIES == 1
338
        // forced retry to set output states, regardless of DIAG
339
        updateOutput(1);
340
        // read DIAG pin again and hope we have a better flag
341
        readDiagPin();
342
#else
343
        // if DIAG allows it, retry to set the output states
344
        updateOutput(0);
345
#endif
1512 myhrman 346
        if (diagState == DIAG_ASSERTED) {
347
            // if DIAG was still asserted, initiate another timer run
348
            Timer_SetTimeout(act_protectedOutput_RETRY_TIMER, act_protectedOutput_RETRY_TIMER_TIME_S*1000, TimerTypeOneShot, 0);
349
        }
350
        else {
351
            // things went back to normal. report this
352
            diagReportPending = 1;
353
        }
1503 myhrman 354
    }
355
 
356
    // shall we report diag status to CAN?
357
    if (diagReportPending) {
358
        StdCan_Msg_t txMsg;
359
        StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
360
        StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
1511 arune 361
        txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
1504 myhrman 362
        txMsg.Header.ModuleId = act_protectedOutput_ID;
1503 myhrman 363
        txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PINSTATUS;
364
        txMsg.Length = 2;
365
        txMsg.Data[0] = 0; //TODO: add support for more channels
366
        // we follow the standard SNS_INPUT format, but the data corresponds to the "health" rather than physical level
367
        if (diagState == DIAG_NORMAL) {
368
            txMsg.Data[1] = 1;  //healthy, target output state stable
369
        } else {
370
            txMsg.Data[1] = 0;  //not healthy, DIAG pin ASSERTED, not in target output state
371
        }
372
        while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
373
        diagReportPending = 0;
374
    }
375
}
376
 
377
 
378
void act_protectedOutput_HandleMessage(StdCan_Msg_t *rxMsg) {
379
    if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_ACT &&
380
        StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_TO_OWNER &&
1511 arune 381
        rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT &&
1503 myhrman 382
        rxMsg->Header.ModuleId == act_protectedOutput_ID)
383
    {
384
        switch (rxMsg->Header.Command) {
385
 
386
            case CAN_MODULE_CMD_PHYSICAL_SETPIN:
1532 myhrman 387
                /*
388
                 * This message is used to activate/deactivate
1538 arune 389
                 * an output channel.
1532 myhrman 390
                 */
1503 myhrman 391
                if (rxMsg->Length == 2) {
1528 myhrman 392
                    uint8_t channel = rxMsg->Data[0];
1532 myhrman 393
                    if (channel >= 0 && channel < act_protectedOutput_CH_COUNT) {
1537 myhrman 394
                        chTargetState[channel] = rxMsg->Data[1];
1503 myhrman 395
                        readDiagPin();
1537 myhrman 396
#if act_protectedOutput_FORCED_RETRIES == 1
397
                        updateOutput(1);
398
#else
399
                        updateOutput(0);
400
#endif
1535 myhrman 401
#if act_protectedOutput_EEPROM_ENABLED == 1
1537 myhrman 402
                        // output states changed, store to EE after this timer delay
1534 myhrman 403
                        Timer_SetTimeout(act_protectedOutput_STORE_VALUE_TIMEOUT, act_protectedOutput_STORE_VALUE_TIMEOUT_TIME_S*1000, TimerTypeOneShot, 0);
1535 myhrman 404
#endif
1537 myhrman 405
                    }
1503 myhrman 406
                    StdCan_Set_direction(rxMsg->Header, DIRECTIONFLAG_FROM_OWNER);
407
                    rxMsg->Length = 2;
408
                    while (StdCan_Put(rxMsg) != StdCan_Ret_OK);
409
                }
410
                break;
411
        }
412
    }
413
}
414
 
415
 
416
void act_protectedOutput_List(uint8_t ModuleSequenceNumber)
417
{
418
    StdCan_Msg_t txMsg;
419
    StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_ACT);
420
    StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
1511 arune 421
    txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
1503 myhrman 422
    txMsg.Header.ModuleId = act_protectedOutput_ID;
423
    txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
424
    txMsg.Length = 6;
425
 
1910 arune 426
    uint32_t HwId=BIOS_GetHwId();
427
    txMsg.Data[0] = HwId&0xff;
428
    txMsg.Data[1] = (HwId>>8)&0xff;
429
    txMsg.Data[2] = (HwId>>16)&0xff;
430
    txMsg.Data[3] = (HwId>>24)&0xff;
1503 myhrman 431
 
432
    txMsg.Data[4] = NUMBER_OF_MODULES;
433
    txMsg.Data[5] = ModuleSequenceNumber;
434
 
435
    while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
436
}
437