Rev 1504 | Go to most recent revision | Details | 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 | //obsolete: replaced polling by PCINT callback |
||
| 104 | //Timer_SetTimeout(act_protectedOutput_DIAG_POLL_TIMER, act_protectedOutput_DIAG_POLL_TIMER_TIME_MS, TimerTypeFreeRunning, 0); |
||
| 105 | } |
||
| 106 | |||
| 107 | |||
| 108 | void act_protectedOutput_Process() { |
||
| 109 | #if 0 |
||
| 110 | if (Timer_Expired(act_protectedOutput_DIAG_POLL_TIMER)) { |
||
| 111 | // time to poll DIAG pin |
||
| 112 | readDiagPin(); |
||
| 113 | updateOutput(); |
||
| 114 | if (diagState == DIAG_ASSERTED) { |
||
| 115 | // if DIAG was asserted, init retry timer |
||
| 116 | if (act_protectedOutput_RETRY_TIMER_TIME_S > 0) { |
||
| 117 | Timer_SetTimeout(act_protectedOutput_RETRY_TIMER, act_protectedOutput_RETRY_TIMER_TIME_S*1000, TimerTypeOneShot, 0); |
||
| 118 | } |
||
| 119 | } |
||
| 120 | } |
||
| 121 | #endif |
||
| 122 | |||
| 123 | // shall we retry to set target output state? |
||
| 124 | if (Timer_Expired(act_protectedOutput_RETRY_TIMER)) { |
||
| 125 | // read DIAG pin again and update outputs accordingly |
||
| 126 | readDiagPin(); |
||
| 127 | updateOutput(); |
||
| 128 | // if DIAG was still asserted, initiate another timer run |
||
| 129 | Timer_SetTimeout(act_protectedOutput_RETRY_TIMER, act_protectedOutput_RETRY_TIMER_TIME_S*1000, TimerTypeOneShot, 0); |
||
| 130 | } |
||
| 131 | |||
| 132 | // shall we report diag status to CAN? |
||
| 133 | if (diagReportPending) { |
||
| 134 | StdCan_Msg_t txMsg; |
||
| 135 | StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS); |
||
| 136 | StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER); |
||
| 137 | txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_INPUT; |
||
| 138 | txMsg.Header.ModuleId = sns_input_ID; |
||
| 139 | txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PINSTATUS; |
||
| 140 | txMsg.Length = 2; |
||
| 141 | txMsg.Data[0] = 0; //TODO: add support for more channels |
||
| 142 | // we follow the standard SNS_INPUT format, but the data corresponds to the "health" rather than physical level |
||
| 143 | if (diagState == DIAG_NORMAL) { |
||
| 144 | txMsg.Data[1] = 1; //healthy, target output state stable |
||
| 145 | } else { |
||
| 146 | txMsg.Data[1] = 0; //not healthy, DIAG pin ASSERTED, not in target output state |
||
| 147 | } |
||
| 148 | while (StdCan_Put(&txMsg) != StdCan_Ret_OK); |
||
| 149 | diagReportPending = 0; |
||
| 150 | } |
||
| 151 | } |
||
| 152 | |||
| 153 | |||
| 154 | void act_protectedOutput_HandleMessage(StdCan_Msg_t *rxMsg) { |
||
| 155 | if ( StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_ACT && |
||
| 156 | StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_TO_OWNER && |
||
| 157 | rxMsg->Header.ModuleType == CAN_MODULE_TYPE_ACT_OUTPUT && |
||
| 158 | rxMsg->Header.ModuleId == act_protectedOutput_ID) |
||
| 159 | { |
||
| 160 | switch (rxMsg->Header.Command) { |
||
| 161 | |||
| 162 | case CAN_MODULE_CMD_PHYSICAL_SETPIN: |
||
| 163 | |||
| 164 | if (rxMsg->Length == 2) { |
||
| 165 | //TODO: add support for more channels |
||
| 166 | if (rxMsg->Data[0] == 0) { |
||
| 167 | outputTargetState = rxMsg->Data[1]; |
||
| 168 | readDiagPin(); |
||
| 169 | updateOutput(); |
||
| 170 | } |
||
| 171 | StdCan_Set_direction(rxMsg->Header, DIRECTIONFLAG_FROM_OWNER); |
||
| 172 | rxMsg->Length = 2; |
||
| 173 | while (StdCan_Put(rxMsg) != StdCan_Ret_OK); |
||
| 174 | } |
||
| 175 | break; |
||
| 176 | } |
||
| 177 | } |
||
| 178 | } |
||
| 179 | |||
| 180 | |||
| 181 | void act_protectedOutput_List(uint8_t ModuleSequenceNumber) |
||
| 182 | { |
||
| 183 | StdCan_Msg_t txMsg; |
||
| 184 | StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_ACT); |
||
| 185 | StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER); |
||
| 186 | txMsg.Header.ModuleType = CAN_MODULE_TYPE_ACT_OUTPUT; |
||
| 187 | txMsg.Header.ModuleId = act_protectedOutput_ID; |
||
| 188 | txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST; |
||
| 189 | txMsg.Length = 6; |
||
| 190 | |||
| 191 | txMsg.Data[0] = NODE_HW_ID_BYTE0; |
||
| 192 | txMsg.Data[1] = NODE_HW_ID_BYTE1; |
||
| 193 | txMsg.Data[2] = NODE_HW_ID_BYTE2; |
||
| 194 | txMsg.Data[3] = NODE_HW_ID_BYTE3; |
||
| 195 | |||
| 196 | txMsg.Data[4] = NUMBER_OF_MODULES; |
||
| 197 | txMsg.Data[5] = ModuleSequenceNumber; |
||
| 198 | |||
| 199 | while (StdCan_Put(&txMsg) != StdCan_Ret_OK); |
||
| 200 | } |
||
| 201 |