svghmi/svghmi.c
branchsvghmi
changeset 2768 31785529a657
parent 2767 302347f48193
child 2771 361366b891ca
equal deleted inserted replaced
2767:302347f48193 2768:31785529a657
     2 #include "iec_types_all.h"
     2 #include "iec_types_all.h"
     3 #include "POUS.h"
     3 #include "POUS.h"
     4 #include "config.h"
     4 #include "config.h"
     5 #include "beremiz.h"
     5 #include "beremiz.h"
     6 
     6 
       
     7 #define DEFAULT_REFRESH_PERIOD_MS 100
     7 #define HMI_BUFFER_SIZE %(buffer_size)d
     8 #define HMI_BUFFER_SIZE %(buffer_size)d
     8 
     9 
     9 /* PLC reads from that buffer */
    10 /* PLC reads from that buffer */
    10 static char rbuf[HMI_BUFFER_SIZE];
    11 static char rbuf[HMI_BUFFER_SIZE];
    11 
    12 
    12 /* PLC writes to that buffer */
    13 /* PLC writes to that buffer */
    13 static char wbuf[HMI_BUFFER_SIZE];
    14 static char wbuf[HMI_BUFFER_SIZE];
    14 
    15 
    15 static pthread_mutex_t wbuf_mutex = PTHREAD_MUTEX_INITIALIZER;
    16 %(extern_variables_declarations)s
    16 static pthread_mutex_t rbuf_mutex = PTHREAD_MUTEX_INITIALIZER;
       
    17 
    17 
    18 %(extern_variables_declarations)s
    18 #define ticktime_ns %(PLC_ticktime)d;
       
    19 uint16_t ticktime_ms (ticktime_ns>1000000)?
       
    20                      ticktime_ns/1000000:
       
    21                      1;
       
    22 
       
    23 typedef enum {
       
    24     buf_free = 0,
       
    25     buf_set,
       
    26     buf_tosend
       
    27 } buf_state_t;
       
    28 
       
    29 int global_write_dirty = 0;
    19 
    30 
    20 typedef const struct {
    31 typedef const struct {
    21     void *ptr;
    32     void *ptr;
    22     __IEC_types_enum type;
    33     __IEC_types_enum type;
    23     uint32_t buf_index;
    34     uint32_t buf_index;
    24     uint32_t flags;
    35 
       
    36     /* publish/write/send */
       
    37     int wlock;
       
    38     /* zero means not subscribed */
       
    39     uint16_t refresh_period_ms;
       
    40     uint16_t age_ms;
       
    41 
       
    42     buf_state_t wstate;
       
    43 
       
    44     /* retrieve/read/recv */
       
    45     int rlock;
       
    46     buf_state_t rstate;
       
    47 
    25 } hmi_tree_item_t;
    48 } hmi_tree_item_t;
    26 
    49 
    27 static hmi_tree_item_t hmi_tree_item[] = {
    50 static hmi_tree_item_t hmi_tree_item[] = {
    28 %(variable_decl_array)s
    51 %(variable_decl_array)s
    29 };
    52 };
    49     void *real_value_p = NULL;
    72     void *real_value_p = NULL;
    50     char flags = 0;
    73     char flags = 0;
    51 
    74 
    52     void *visible_value_p = UnpackVar(dsc, &real_value_p, &flags);
    75     void *visible_value_p = UnpackVar(dsc, &real_value_p, &flags);
    53 
    76 
    54     memcpy(dest_p, visible_value_p, __get_type_enum_size(dsc->type));
    77     /* Try take lock */
       
    78     long was_locked = AtomicCompareExchange(&dsc->wlock, 0, 1);
       
    79 
       
    80     if(was_locked) {
       
    81         /* was locked. give up*/
       
    82         return;
       
    83     }
       
    84 
       
    85     if(dsc->wstate == buf_set)
       
    86         /* if being subscribed */
       
    87         if(dsc->refresh_period_ms){
       
    88             if(dsc->age_ms + ticktime_ms < dsc->refresh_period_ms){
       
    89                 dsc->age_ms += ticktime_ms;
       
    90             }else{
       
    91                 dsc->wstate = buf_tosend;
       
    92             }
       
    93         }
       
    94     }
       
    95     
       
    96     /* if new value differs from previous one */
       
    97     if(memcmp(dest_p, visible_value_p, __get_type_enum_size(dsc->type)) != 0){
       
    98         /* copy and flag as set */
       
    99         memcpy(dest_p, visible_value_p, __get_type_enum_size(dsc->type));
       
   100         if(dsc->wstate == buf_free) {
       
   101             dsc->wstate = buf_set;
       
   102             dsc->age_ms = 0;
       
   103         }
       
   104         global_write_dirty = 1;
       
   105     }
       
   106 
       
   107     /* unlock - use AtomicComparExchange to have memory barrier */
       
   108     AtomicCompareExchange(&dsc->wlock, 1, 0);
       
   109 }
       
   110 
       
   111 struct timespec sending_now;
       
   112 struct timespec next_sending;
       
   113 void send_iterator(hmi_tree_item_t *dsc)
       
   114 {
       
   115     while(AtomicCompareExchange(&dsc->wlock, 0, 1)) sched_yield();
       
   116 
       
   117     // check for variable being modified
       
   118     if(dsc->wstat == buf_tosend){
       
   119         // send 
       
   120 
       
   121         // TODO write to some socket
       
   122 
       
   123         dsc->wstate = buf_free; 
       
   124     }
       
   125 
       
   126     AtomicCompareExchange(&dsc->wlock, 1, 0);
    55 }
   127 }
    56 
   128 
    57 void read_iterator(hmi_tree_item_t *dsc)
   129 void read_iterator(hmi_tree_item_t *dsc)
    58 {
   130 {
    59     void *src_p = &rbuf[dsc->buf_index];
   131     void *src_p = &rbuf[dsc->buf_index];
    60     void *real_value_p = NULL;
   132     void *real_value_p = NULL;
    61     char flags = 0;
   133     char flags = 0;
    62 
   134 
    63     void *visible_value_p = UnpackVar(dsc, &real_value_p, &flags);
   135     void *visible_value_p = UnpackVar(dsc, &real_value_p, &flags);
    64 
   136 
       
   137 
    65     memcpy(visible_value_p, src_p, __get_type_enum_size(dsc->type));
   138     memcpy(visible_value_p, src_p, __get_type_enum_size(dsc->type));
    66 }
   139 }
    67 
   140 
    68 int __init_svghmi()
   141 int __init_svghmi()
    69 {
   142 {
    70     bzero(rbuf,sizeof(rbuf));
   143     bzero(rbuf,sizeof(rbuf));
    71     bzero(wbuf,sizeof(wbuf));
   144     bzero(wbuf,sizeof(wbuf));
       
   145     
       
   146     // create - connection endpoint
       
   147     //        - sending thread
       
   148     //        - sending semaphore
       
   149     //        - recv thread
    72 
   150 
    73     return 0;
   151     return 0;
    74 }
   152 }
    75 
   153 
    76 void __cleanup_svghmi()
   154 void __cleanup_svghmi()
    77 {
   155 {
    78 }
   156 }
    79 
   157 
    80 void __retrieve_svghmi()
   158 void __retrieve_svghmi()
    81 {
   159 {
    82     if(!pthread_mutex_lock(&rbuf_mutex)){
   160     traverse_hmi_tree(read_iterator);
    83         traverse_hmi_tree(read_iterator);
       
    84         pthread_mutex_unlock(&rbuf_mutex);
       
    85     }
       
    86 }
   161 }
    87 
   162 
    88 void __publish_svghmi()
   163 void __publish_svghmi()
    89 {
   164 {
    90     if(!pthread_mutex_lock(&wbuf_mutex)){
   165     global_write_dirty = 0;
    91         pthread_mutex_unlock(&wbuf_mutex);
   166     traverse_hmi_tree(write_iterator);
       
   167     if(global_write_dirty) {
       
   168         // TODO : set emaphore to wakeup sending thread
    92     }
   169     }
       
   170 
    93 }
   171 }
    94 
   172 
       
   173 void sending_thread_proc(void* args){
       
   174 
       
   175     // TODO : wait for 
       
   176     //        - semaphore
       
   177     //        - next autonomous send thread wakeup. (impl as wait timeout ?) 
       
   178 
       
   179     traverse_hmi_tree(send_iterator);
       
   180 }