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 |