Subversion Repositories HomeAutomation

Rev

Rev 1512 | Rev 1532 | 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 OUTPUT0_ON      (act_protectedOutput_OUTPUT0_PIN_ACTIVE_STATE)
  11. #define OUTPUT0_OFF     (1 - OUTPUT0_ON)
  12. #define OUTPUT0_PIN     act_protectedOutput_OUTPUT0_PIN
  13.  
  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.  
  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.  *---------------------------------------------------------------------------*/
  39.  
  40. static uint8_t outputStateTarget[act_protectedOutput_NR_OUTPUT_PINS];
  41.  
  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() {
  61.  
  62.     #if act_protectedOutput_NR_OUTPUT_PINS >= 1
  63.     if (outputStateTarget[0] == 0) {
  64.         gpio_set_statement(OUTPUT0_OFF, OUTPUT0_PIN);
  65.     }
  66.     else if (outputStateTarget[0] == 1) {
  67.         if (diagState == DIAG_NORMAL) {
  68.             gpio_set_statement(OUTPUT0_ON, OUTPUT0_PIN);
  69.         }
  70.         else {
  71.             // DIAG override, we cannot set ON state right now
  72.             gpio_set_statement(OUTPUT0_OFF, OUTPUT0_PIN);
  73.         }
  74.     }
  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
  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 {
  142.                 for (uint8_t i=0; i<act_protectedOutput_NR_OUTPUT_PINS; i++) {
  143.                     outputStateTarget[i] = 0;
  144.                 }
  145.             }
  146.         }
  147.         // something interesting obviously happened. let's report it
  148.         diagReportPending = 1;
  149.     }
  150. }
  151.  
  152.  
  153. void act_protectedOutput_Init() {
  154.     /*
  155.      * Configure DIAG input pin
  156.      */
  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.    
  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
  171.    
  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.  
  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();
  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.         }
  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);
  217.         txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
  218.         txMsg.Header.ModuleId = act_protectedOutput_ID;
  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 &&
  237.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT &&
  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) {
  245.                     uint8_t channel = rxMsg->Data[0];
  246.                     if (channel >= 0 && channel < act_protectedOutput_NR_OUTPUT_PINS) {
  247.                         outputStateTarget[channel] = rxMsg->Data[1];
  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);
  266.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
  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.  
  282.