Subversion Repositories HomeAutomation

Rev

Rev 1504 | 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.     //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.  
  202.