Subversion Repositories HomeAutomation

Rev

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

  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();
  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.         }
  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);
  127.         txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
  128.         txMsg.Header.ModuleId = act_protectedOutput_ID;
  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 &&
  147.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT &&
  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);
  176.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
  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.  
  192.