SVGHMI: Fix browser side exception when some widget are not used, and are then discarded and not present in final SVG. In that case JS code was still making reference to discarded widget elements and was raising exception at init.
/*
Template C code used to produce target Ethercat C code
Copyright (C) 2011-2014: Laurent BESSARD, Edouard TISSERANT
Distributed under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
See COPYING file for copyrights details.
*/
#include <rtdm/rtdm.h>
#include <native/task.h>
#include <native/timer.h>
#include "ecrt.h"
#include "beremiz.h"
#include "iec_types_all.h"
// declaration of interface variables
%(located_variables_declaration)s
// process data
uint8_t *domain1_pd = NULL;
%(used_pdo_entry_offset_variables_declaration)s
const static ec_pdo_entry_reg_t domain1_regs[] = {
%(used_pdo_entry_configuration)s
{}
};
// Distributed Clock variables;
%(dc_variable)s
unsigned long long comp_period_ns = 500000ULL;
int comp_count = 1;
int comp_count_max;
#define DC_FILTER_CNT 1024
// EtherCAT slave-time-based DC Synchronization variables.
static uint64_t dc_start_time_ns = 0LL;
static uint64_t dc_time_ns = 0;
static uint8_t dc_started = 0;
static int32_t dc_diff_ns = 0;
static int32_t prev_dc_diff_ns = 0;
static int64_t dc_diff_total_ns = 0LL;
static int64_t dc_delta_total_ns = 0LL;
static int dc_filter_idx = 0;
static int64_t dc_adjust_ns;
static int64_t system_time_base = 0LL;
static uint64_t dc_first_app_time = 0LL;
unsigned long long frame_period_ns = 0ULL;
int debug_count = 0;
int slave_dc_used = 0;
void dc_init(void);
uint64_t system_time_ns(void);
RTIME system2count(uint64_t time);
void sync_distributed_clocks(void);
void update_master_clock(void);
RTIME calculate_sleeptime(uint64_t wakeup_time);
uint64_t calculate_first(void);
/*****************************************************************************/
%(pdos_configuration_declaration)s
long long wait_period_ns = 100000LL;
// EtherCAT
static ec_master_t *master = NULL;
static ec_domain_t *domain1 = NULL;
static int first_sent=0;
%(slaves_declaration)s
#define SLOGF(level, format, args...)\
{\
char sbuf[256];\
int slen = snprintf(sbuf , sizeof(sbuf) , format , ##args);\
LogMessage(level, sbuf, slen);\
}
/* EtherCAT plugin functions */
int __init_%(location)s(int argc,char **argv)
{
uint32_t abort_code;
size_t result_size;
abort_code = 0;
result_size = 0;
master = ecrt_request_master(%(master_number)d);
if (!master) {
SLOGF(LOG_CRITICAL, "EtherCAT master request failed!");
return -1;
}
if(!(domain1 = ecrt_master_create_domain(master))){
SLOGF(LOG_CRITICAL, "EtherCAT Domain Creation failed!");
goto ecat_failed;
}
// slaves PDO configuration
%(slaves_configuration)s
if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
SLOGF(LOG_CRITICAL, "EtherCAT PDO registration failed!");
goto ecat_failed;
}
ecrt_master_set_send_interval(master, common_ticktime__);
// slaves initialization
/*
%(slaves_initialization)s
*/
// configure DC SYNC0/1 Signal
%(config_dc)s
// select reference clock
#if DC_ENABLE
{
int ret;
ret = ecrt_master_select_reference_clock(master, slave0);
if (ret <0) {
fprintf(stderr, "Failed to select reference clock : %%s\n",
strerror(-ret));
return ret;
}
}
#endif
// extracting default value for not mapped entry in output PDOs
/*
%(slaves_output_pdos_default_values_extraction)s
*/
#if DC_ENABLE
dc_init();
#endif
if (ecrt_master_activate(master)){
SLOGF(LOG_CRITICAL, "EtherCAT Master activation failed");
goto ecat_failed;
}
if (!(domain1_pd = ecrt_domain_data(domain1))) {
SLOGF(LOG_CRITICAL, "Failed to map EtherCAT process data");
goto ecat_failed;
}
SLOGF(LOG_INFO, "Master %(master_number)d activated.");
first_sent = 0;
return 0;
ecat_failed:
ecrt_release_master(master);
return -1;
}
void __cleanup_%(location)s(void)
{
//release master
ecrt_release_master(master);
first_sent = 0;
}
void __retrieve_%(location)s(void)
{
// receive ethercat
if(first_sent){
ecrt_master_receive(master);
ecrt_domain_process(domain1);
%(retrieve_variables)s
}
}
/*
static RTIME _last_occur=0;
static RTIME _last_publish=0;
RTIME _current_lag=0;
RTIME _max_jitter=0;
static inline RTIME max(RTIME a,RTIME b){return a>b?a:b;}
*/
void __publish_%(location)s(void)
{
%(publish_variables)s
ecrt_domain_queue(domain1);
{
/*
RTIME current_time = rt_timer_read();
// Limit spining max 1/5 of common_ticktime
RTIME maxdeadline = current_time + (common_ticktime__ / 5);
RTIME deadline = _last_occur ?
_last_occur + common_ticktime__ :
current_time + _max_jitter;
if(deadline > maxdeadline) deadline = maxdeadline;
_current_lag = deadline - current_time;
if(_last_publish != 0){
RTIME period = current_time - _last_publish;
if(period > common_ticktime__ )
_max_jitter = max(_max_jitter, period - common_ticktime__);
else
_max_jitter = max(_max_jitter, common_ticktime__ - period);
}
_last_publish = current_time;
_last_occur = current_time;
while(current_time < deadline) {
_last_occur = current_time; //Drift backward by default
current_time = rt_timer_read();
}
if( _max_jitter * 10 < common_ticktime__ && _current_lag < _max_jitter){
//Consuming security margin ?
_last_occur = current_time; //Drift forward
}
*/
}
#if DC_ENABLE
if (comp_count == 0)
sync_distributed_clocks();
#endif
ecrt_master_send(master);
first_sent = 1;
#if DC_ENABLE
if (comp_count == 0)
update_master_clock();
comp_count++;
if (comp_count == comp_count_max)
comp_count = 0;
#endif
}
/* Test Function For Parameter (SDO) Set */
/*
void GetSDOData(void){
uint32_t abort_code, test_value;
size_t result_size;
uint8_t value[4];
abort_code = 0;
result_size = 0;
test_value = 0;
if (ecrt_master_sdo_upload(master, 0, 0x1000, 0x0, (uint8_t *)value, 4, &result_size, &abort_code)) {
SLOGF(LOG_CRITICAL, "EtherCAT failed to get SDO Value");
}
test_value = EC_READ_S32((uint8_t *)value);
SLOGF(LOG_INFO, "SDO Value %%d", test_value);
}
*/
int GetMasterData(void){
master = ecrt_open_master(0);
if (!master) {
SLOGF(LOG_CRITICAL, "EtherCAT master request failed!");
return -1;
}
return 0;
}
void ReleaseMasterData(void){
ecrt_release_master(master);
}
uint32_t GetSDOData(uint16_t slave_pos, uint16_t idx, uint8_t subidx, int size){
uint32_t abort_code, return_value;
size_t result_size;
uint8_t value[size];
abort_code = 0;
result_size = 0;
if (ecrt_master_sdo_upload(master, slave_pos, idx, subidx, (uint8_t *)value, size, &result_size, &abort_code)) {
SLOGF(LOG_CRITICAL, "EtherCAT failed to get SDO Value %%d %%d", idx, subidx);
}
return_value = EC_READ_S32((uint8_t *)value);
//SLOGF(LOG_INFO, "SDO Value %%d", return_value);
return return_value;
}
/*****************************************************************************/
void dc_init(void)
{
slave_dc_used = 1;
frame_period_ns = common_ticktime__;
if (frame_period_ns <= comp_period_ns) {
comp_count_max = comp_period_ns / frame_period_ns;
comp_count = 0;
} else {
comp_count_max = 1;
comp_count = 0;
}
/* Set the initial master time */
dc_start_time_ns = system_time_ns();
dc_time_ns = dc_start_time_ns;
/* by woonggy */
dc_first_app_time = dc_start_time_ns;
/*
* Attention : The initial application time is also used for phase
* calculation for the SYNC0/1 interrupts. Please be sure to call it at
* the correct phase to the realtime cycle.
*/
ecrt_master_application_time(master, dc_start_time_ns);
}
/****************************************************************************/
/*
* Get the time in ns for the current cpu, adjusted by system_time_base.
*
* \attention Rather than calling rt_timer_read() directly, all application
* time calls should use this method instead.
*
* \ret The time in ns.
*/
uint64_t system_time_ns(void)
{
RTIME time = rt_timer_read(); // wkk
if (unlikely(system_time_base > (SRTIME) time)) {
fprintf(stderr, "%%s() error: system_time_base greater than"
" system time (system_time_base: %%ld, time: %%llu\n",
__func__, system_time_base, time);
return time;
}
else {
return time - system_time_base;
}
}
/****************************************************************************/
// Convert system time to Xenomai time in counts (via the system_time_base).
RTIME system2count(uint64_t time)
{
RTIME ret;
if ((system_time_base < 0) &&
((uint64_t) (-system_time_base) > time)) {
fprintf(stderr, "%%s() error: system_time_base less than"
" system time (system_time_base: %%I64d, time: %%ld\n",
__func__, system_time_base, time);
ret = time;
}
else {
ret = time + system_time_base;
}
return (RTIME) rt_timer_ns2ticks(ret); // wkk
}
/*****************************************************************************/
// Synchronise the distributed clocks
void sync_distributed_clocks(void)
{
uint32_t ref_time = 0;
RTIME prev_app_time = dc_time_ns;
// get reference clock time to synchronize master cycle
if(!ecrt_master_reference_clock_time(master, &ref_time)) {
dc_diff_ns = (uint32_t) prev_app_time - ref_time;
}
// call to sync slaves to ref slave
ecrt_master_sync_slave_clocks(master);
// set master time in nano-seconds
dc_time_ns = system_time_ns();
ecrt_master_application_time(master, dc_time_ns);
}
/*****************************************************************************/
/*
* Return the sign of a number
* ie -1 for -ve value, 0 for 0, +1 for +ve value
* \ret val the sign of the value
*/
#define sign(val) \
({ typeof (val) _val = (val); \
((_val > 0) - (_val < 0)); })
/*****************************************************************************/
/*
* Update the master time based on ref slaves time diff
* called after the ethercat frame is sent to avoid time jitter in
* sync_distributed_clocks()
*/
void update_master_clock(void)
{
// calc drift (via un-normalised time diff)
int32_t delta = dc_diff_ns - prev_dc_diff_ns;
prev_dc_diff_ns = dc_diff_ns;
// normalise the time diff
dc_diff_ns = dc_diff_ns >= 0 ?
((dc_diff_ns + (int32_t)(frame_period_ns / 2)) %%
(int32_t)frame_period_ns) - (frame_period_ns / 2) :
((dc_diff_ns - (int32_t)(frame_period_ns / 2)) %%
(int32_t)frame_period_ns) - (frame_period_ns / 2) ;
// only update if primary master
if (dc_started) {
// add to totals
dc_diff_total_ns += dc_diff_ns;
dc_delta_total_ns += delta;
dc_filter_idx++;
if (dc_filter_idx >= DC_FILTER_CNT) {
dc_adjust_ns += dc_delta_total_ns >= 0 ?
((dc_delta_total_ns + (DC_FILTER_CNT / 2)) / DC_FILTER_CNT) :
((dc_delta_total_ns - (DC_FILTER_CNT / 2)) / DC_FILTER_CNT) ;
// and add adjustment for general diff (to pull in drift)
dc_adjust_ns += sign(dc_diff_total_ns / DC_FILTER_CNT);
// limit crazy numbers (0.1%% of std cycle time)
if (dc_adjust_ns < -1000) {
dc_adjust_ns = -1000;
}
if (dc_adjust_ns > 1000) {
dc_adjust_ns = 1000;
}
// reset
dc_diff_total_ns = 0LL;
dc_delta_total_ns = 0LL;
dc_filter_idx = 0;
}
// add cycles adjustment to time base (including a spot adjustment)
system_time_base += dc_adjust_ns + sign(dc_diff_ns);
}
else {
dc_started = (dc_diff_ns != 0);
if (dc_started) {
#if DC_ENABLE && DEBUG_MODE
// output first diff
fprintf(stderr, "First master diff: %%d\n", dc_diff_ns);
#endif
// record the time of this initial cycle
dc_start_time_ns = dc_time_ns;
}
}
}
/*****************************************************************************/
/*
* Calculate the sleeptime
*/
RTIME calculate_sleeptime(uint64_t wakeup_time)
{
RTIME wakeup_count = system2count (wakeup_time);
RTIME current_count = rt_timer_read();
if ((wakeup_count < current_count) || (wakeup_count > current_count + (50 * frame_period_ns))) {
fprintf(stderr, "%%s(): unexpected wake time! wc = %%lld\tcc = %%lld\n", __func__, wakeup_count, current_count);
}
return wakeup_count;
}
/*****************************************************************************/
/*
* Calculate the sleeptime
*/
uint64_t calculate_first(void)
{
uint64_t dc_remainder = 0LL;
uint64_t dc_phase_set_time = 0LL;
dc_phase_set_time = system_time_ns()+ frame_period_ns * 10;
dc_remainder = (dc_phase_set_time - dc_first_app_time) %% frame_period_ns;
return dc_phase_set_time + frame_period_ns - dc_remainder;
}
/*****************************************************************************/