master/slave.c
branchstable-1.0
changeset 1619 0d4119024f55
parent 1618 5cff10efb927
child 1621 4bbe090553f7
equal deleted inserted replaced
1618:5cff10efb927 1619:0d4119024f55
     6  *
     6  *
     7  *  This file is part of the IgH EtherCAT Master.
     7  *  This file is part of the IgH EtherCAT Master.
     8  *
     8  *
     9  *  The IgH EtherCAT Master is free software; you can redistribute it
     9  *  The IgH EtherCAT Master is free software; you can redistribute it
    10  *  and/or modify it under the terms of the GNU General Public License
    10  *  and/or modify it under the terms of the GNU General Public License
    11  *  as published by the Free Software Foundation; version 2 of the License.
    11  *  as published by the Free Software Foundation; either version 2 of the
       
    12  *  License, or (at your option) any later version.
    12  *
    13  *
    13  *  The IgH EtherCAT Master is distributed in the hope that it will be
    14  *  The IgH EtherCAT Master is distributed in the hope that it will be
    14  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  *  GNU General Public License for more details.
    17  *  GNU General Public License for more details.
    17  *
    18  *
    18  *  You should have received a copy of the GNU General Public License
    19  *  You should have received a copy of the GNU General Public License
    19  *  along with the IgH EtherCAT Master; if not, write to the Free Software
    20  *  along with the IgH EtherCAT Master; if not, write to the Free Software
    20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    21  *
    22  *
       
    23  *  The right to use EtherCAT Technology is granted and comes free of
       
    24  *  charge under condition of compatibility of product made by
       
    25  *  Licensee. People intending to distribute/sell products based on the
       
    26  *  code, have to sign an agreement to guarantee that products using
       
    27  *  software based on IgH EtherCAT master stay compatible with the actual
       
    28  *  EtherCAT specification (which are released themselves as an open
       
    29  *  standard) as the (only) precondition to have the right to use EtherCAT
       
    30  *  Technology, IP and trade marks.
       
    31  *
    22  *****************************************************************************/
    32  *****************************************************************************/
    23 
    33 
    24 /**
    34 /**
    25    \file
    35    \file
    26    EtherCAT slave methods.
    36    EtherCAT slave methods.
    36 #include "command.h"
    46 #include "command.h"
    37 #include "master.h"
    47 #include "master.h"
    38 
    48 
    39 /*****************************************************************************/
    49 /*****************************************************************************/
    40 
    50 
       
    51 extern const ec_code_msg_t al_status_messages[];
       
    52 
       
    53 /*****************************************************************************/
       
    54 
    41 int ec_slave_fetch_categories(ec_slave_t *);
    55 int ec_slave_fetch_categories(ec_slave_t *);
    42 int ec_slave_fetch_strings(ec_slave_t *, const uint8_t *);
       
    43 int ec_slave_fetch_general(ec_slave_t *, const uint8_t *);
       
    44 int ec_slave_fetch_sync(ec_slave_t *, const uint8_t *, size_t);
       
    45 int ec_slave_fetch_pdo(ec_slave_t *, const uint8_t *, size_t, ec_pdo_type_t);
       
    46 int ec_slave_locate_string(ec_slave_t *, unsigned int, char **);
       
    47 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
    56 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
       
    57 ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *,
       
    58                                  const char *, size_t);
    48 
    59 
    49 /*****************************************************************************/
    60 /*****************************************************************************/
    50 
    61 
    51 /** \cond */
    62 /** \cond */
    52 
    63 
    53 EC_SYSFS_READ_ATTR(ring_position);
    64 EC_SYSFS_READ_ATTR(ring_position);
    54 EC_SYSFS_READ_ATTR(coupler_address);
    65 EC_SYSFS_READ_ATTR(coupler_address);
    55 EC_SYSFS_READ_ATTR(vendor_name);
    66 EC_SYSFS_READ_ATTR(vendor_name);
    56 EC_SYSFS_READ_ATTR(product_name);
    67 EC_SYSFS_READ_ATTR(product_name);
    57 EC_SYSFS_READ_ATTR(product_desc);
    68 EC_SYSFS_READ_ATTR(product_desc);
       
    69 EC_SYSFS_READ_ATTR(sii_name);
    58 EC_SYSFS_READ_ATTR(type);
    70 EC_SYSFS_READ_ATTR(type);
       
    71 EC_SYSFS_READ_WRITE_ATTR(state);
    59 
    72 
    60 static struct attribute *def_attrs[] = {
    73 static struct attribute *def_attrs[] = {
    61     &attr_ring_position,
    74     &attr_ring_position,
    62     &attr_coupler_address,
    75     &attr_coupler_address,
    63     &attr_vendor_name,
    76     &attr_vendor_name,
    64     &attr_product_name,
    77     &attr_product_name,
    65     &attr_product_desc,
    78     &attr_product_desc,
       
    79     &attr_sii_name,
    66     &attr_type,
    80     &attr_type,
       
    81     &attr_state,
    67     NULL,
    82     NULL,
    68 };
    83 };
    69 
    84 
    70 static struct sysfs_ops sysfs_ops = {
    85 static struct sysfs_ops sysfs_ops = {
    71     .show = &ec_show_slave_attribute,
    86     .show = ec_show_slave_attribute,
    72     .store = NULL
    87     .store = ec_store_slave_attribute
    73 };
    88 };
    74 
    89 
    75 static struct kobj_type ktype_ec_slave = {
    90 static struct kobj_type ktype_ec_slave = {
    76     .release = ec_slave_clear,
    91     .release = ec_slave_clear,
    77     .sysfs_ops = &sysfs_ops,
    92     .sysfs_ops = &sysfs_ops,
    78     .default_attrs = def_attrs
    93     .default_attrs = def_attrs
    79 };
    94 };
    80 
    95 
    81 /** \endcond */
    96 /** \endcond */
    82 
       
    83 /*****************************************************************************/
       
    84 
       
    85 const ec_code_msg_t al_status_messages[];
       
    86 
    97 
    87 /*****************************************************************************/
    98 /*****************************************************************************/
    88 
    99 
    89 /**
   100 /**
    90    Slave constructor.
   101    Slave constructor.
   132     slave->sii_tx_mailbox_size = 0;
   143     slave->sii_tx_mailbox_size = 0;
   133     slave->sii_mailbox_protocols = 0;
   144     slave->sii_mailbox_protocols = 0;
   134     slave->type = NULL;
   145     slave->type = NULL;
   135     slave->registered = 0;
   146     slave->registered = 0;
   136     slave->fmmu_count = 0;
   147     slave->fmmu_count = 0;
       
   148     slave->eeprom_group = NULL;
       
   149     slave->eeprom_image = NULL;
       
   150     slave->eeprom_order = NULL;
   137     slave->eeprom_name = NULL;
   151     slave->eeprom_name = NULL;
   138     slave->eeprom_group = NULL;
   152     slave->requested_state = EC_SLAVE_STATE_UNKNOWN;
   139     slave->eeprom_desc = NULL;
   153     slave->current_state = EC_SLAVE_STATE_UNKNOWN;
       
   154     slave->state_error = 0;
       
   155     slave->online = 1;
   140 
   156 
   141     ec_command_init(&slave->mbox_command);
   157     ec_command_init(&slave->mbox_command);
   142 
   158 
   143     INIT_LIST_HEAD(&slave->eeprom_strings);
   159     INIT_LIST_HEAD(&slave->eeprom_strings);
   144     INIT_LIST_HEAD(&slave->eeprom_syncs);
   160     INIT_LIST_HEAD(&slave->eeprom_syncs);
   198         }
   214         }
   199 
   215 
   200         kfree(pdo);
   216         kfree(pdo);
   201     }
   217     }
   202 
   218 
       
   219     if (slave->eeprom_group) kfree(slave->eeprom_group);
       
   220     if (slave->eeprom_image) kfree(slave->eeprom_image);
       
   221     if (slave->eeprom_order) kfree(slave->eeprom_order);
   203     if (slave->eeprom_name) kfree(slave->eeprom_name);
   222     if (slave->eeprom_name) kfree(slave->eeprom_name);
   204     if (slave->eeprom_group) kfree(slave->eeprom_group);
       
   205     if (slave->eeprom_desc) kfree(slave->eeprom_desc);
       
   206 
   223 
   207     // free all SDOs
   224     // free all SDOs
   208     list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
   225     list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
   209         list_del(&sdo->list);
   226         list_del(&sdo->list);
   210         if (sdo->name) kfree(sdo->name);
   227         if (sdo->name) kfree(sdo->name);
   490 /*****************************************************************************/
   507 /*****************************************************************************/
   491 
   508 
   492 /**
   509 /**
   493    Fetches data from slave's EEPROM.
   510    Fetches data from slave's EEPROM.
   494    \return 0 in case of success, else < 0
   511    \return 0 in case of success, else < 0
       
   512    \todo memory allocation
   495 */
   513 */
   496 
   514 
   497 int ec_slave_fetch_categories(ec_slave_t *slave /**< EtherCAT slave */)
   515 int ec_slave_fetch_categories(ec_slave_t *slave /**< EtherCAT slave */)
   498 {
   516 {
   499     uint16_t word_offset, cat_type, word_count;
   517     uint16_t word_offset, cat_type, word_count;
   630 {
   648 {
   631     unsigned int i;
   649     unsigned int i;
   632 
   650 
   633     if (ec_slave_locate_string(slave, data[0], &slave->eeprom_group))
   651     if (ec_slave_locate_string(slave, data[0], &slave->eeprom_group))
   634         return -1;
   652         return -1;
   635     if (ec_slave_locate_string(slave, data[1], &slave->eeprom_name))
   653     if (ec_slave_locate_string(slave, data[1], &slave->eeprom_image))
   636         return -1;
   654         return -1;
   637     if (ec_slave_locate_string(slave, data[3], &slave->eeprom_desc))
   655     if (ec_slave_locate_string(slave, data[2], &slave->eeprom_order))
       
   656         return -1;
       
   657     if (ec_slave_locate_string(slave, data[3], &slave->eeprom_name))
   638         return -1;
   658         return -1;
   639 
   659 
   640     for (i = 0; i < 4; i++)
   660     for (i = 0; i < 4; i++)
   641         slave->sii_physical_layer[i] =
   661         slave->sii_physical_layer[i] =
   642             (data[4] & (0x03 << (i * 2))) >> (i * 2);
   662             (data[4] & (0x03 << (i * 2))) >> (i * 2);
   822         udelay(100); // wait a little bit...
   842         udelay(100); // wait a little bit...
   823 
   843 
   824         if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
   844         if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
   825             return;
   845             return;
   826         if (unlikely(ec_master_simple_io(slave->master, command))) {
   846         if (unlikely(ec_master_simple_io(slave->master, command))) {
       
   847             slave->current_state = EC_SLAVE_STATE_UNKNOWN;
   827             EC_WARN("Acknowledge checking failed on slave %i!\n",
   848             EC_WARN("Acknowledge checking failed on slave %i!\n",
   828                     slave->ring_position);
   849                     slave->ring_position);
   829             return;
   850             return;
   830         }
   851         }
   831 
   852 
   832         end = get_cycles();
   853         end = get_cycles();
   833 
   854 
   834         if (likely(EC_READ_U8(command->data) == state)) {
   855         if (likely(EC_READ_U8(command->data) == state)) {
       
   856             slave->current_state = state;
   835             EC_INFO("Acknowleged state 0x%02X on slave %i.\n", state,
   857             EC_INFO("Acknowleged state 0x%02X on slave %i.\n", state,
   836                     slave->ring_position);
   858                     slave->ring_position);
   837             return;
   859             return;
   838         }
   860         }
   839 
   861 
   840         if (unlikely((end - start) >= timeout)) {
   862         if (unlikely((end - start) >= timeout)) {
       
   863             slave->current_state = EC_SLAVE_STATE_UNKNOWN;
   841             EC_WARN("Failed to acknowledge state 0x%02X on slave %i"
   864             EC_WARN("Failed to acknowledge state 0x%02X on slave %i"
   842                     " - Timeout!\n", state, slave->ring_position);
   865                     " - Timeout!\n", state, slave->ring_position);
   843             return;
   866             return;
   844         }
   867         }
   845     }
   868     }
   895     ec_command_t *command;
   918     ec_command_t *command;
   896     cycles_t start, end, timeout;
   919     cycles_t start, end, timeout;
   897 
   920 
   898     command = &slave->master->simple_command;
   921     command = &slave->master->simple_command;
   899 
   922 
       
   923     slave->requested_state = state;
       
   924 
   900     if (ec_command_npwr(command, slave->station_address, 0x0120, 2)) return -1;
   925     if (ec_command_npwr(command, slave->station_address, 0x0120, 2)) return -1;
   901     EC_WRITE_U16(command->data, state);
   926     EC_WRITE_U16(command->data, state);
   902     if (unlikely(ec_master_simple_io(slave->master, command))) {
   927     if (unlikely(ec_master_simple_io(slave->master, command))) {
   903         EC_ERR("Failed to set state 0x%02X on slave %i!\n",
   928         EC_ERR("Failed to set state 0x%02X on slave %i!\n",
   904                state, slave->ring_position);
   929                state, slave->ring_position);
   913         udelay(100); // wait a little bit
   938         udelay(100); // wait a little bit
   914 
   939 
   915         if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
   940         if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
   916             return -1;
   941             return -1;
   917         if (unlikely(ec_master_simple_io(slave->master, command))) {
   942         if (unlikely(ec_master_simple_io(slave->master, command))) {
       
   943             slave->current_state = EC_SLAVE_STATE_UNKNOWN;
   918             EC_ERR("Failed to check state 0x%02X on slave %i!\n",
   944             EC_ERR("Failed to check state 0x%02X on slave %i!\n",
   919                    state, slave->ring_position);
   945                    state, slave->ring_position);
   920             return -1;
   946             return -1;
   921         }
   947         }
   922 
   948 
   924 
   950 
   925         if (unlikely(EC_READ_U8(command->data) & 0x10)) { // state change error
   951         if (unlikely(EC_READ_U8(command->data) & 0x10)) { // state change error
   926             EC_ERR("Failed to set state 0x%02X - Slave %i refused state change"
   952             EC_ERR("Failed to set state 0x%02X - Slave %i refused state change"
   927                    " (code 0x%02X)!\n", state, slave->ring_position,
   953                    " (code 0x%02X)!\n", state, slave->ring_position,
   928                    EC_READ_U8(command->data));
   954                    EC_READ_U8(command->data));
   929             state = EC_READ_U8(command->data) & 0x0F;
   955             slave->current_state = EC_READ_U8(command->data);
       
   956             state = slave->current_state & 0x0F;
   930             ec_slave_read_al_status_code(slave);
   957             ec_slave_read_al_status_code(slave);
   931             ec_slave_state_ack(slave, state);
   958             ec_slave_state_ack(slave, state);
   932             return -1;
   959             return -1;
   933         }
   960         }
   934 
   961 
   935         if (likely(EC_READ_U8(command->data) == (state & 0x0F)))
   962         if (likely(EC_READ_U8(command->data) == (state & 0x0F))) {
       
   963             slave->current_state = state;
   936             return 0; // state change successful
   964             return 0; // state change successful
       
   965         }
   937 
   966 
   938         if (unlikely((end - start) >= timeout)) {
   967         if (unlikely((end - start) >= timeout)) {
       
   968             slave->current_state = EC_SLAVE_STATE_UNKNOWN;
   939             EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n",
   969             EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n",
   940                    state, slave->ring_position);
   970                    state, slave->ring_position);
   941             return -1;
   971             return -1;
   942         }
   972         }
   943     }
   973     }
  1098     EC_INFO("    Vendor-ID: 0x%08X, Product code: 0x%08X\n",
  1128     EC_INFO("    Vendor-ID: 0x%08X, Product code: 0x%08X\n",
  1099             slave->sii_vendor_id, slave->sii_product_code);
  1129             slave->sii_vendor_id, slave->sii_product_code);
  1100     EC_INFO("    Revision number: 0x%08X, Serial number: 0x%08X\n",
  1130     EC_INFO("    Revision number: 0x%08X, Serial number: 0x%08X\n",
  1101             slave->sii_revision_number, slave->sii_serial_number);
  1131             slave->sii_revision_number, slave->sii_serial_number);
  1102 
  1132 
       
  1133     if (slave->eeprom_group)
       
  1134         EC_INFO("    Group: %s\n", slave->eeprom_group);
       
  1135     if (slave->eeprom_image)
       
  1136         EC_INFO("    Image: %s\n", slave->eeprom_image);
       
  1137     if (slave->eeprom_order)
       
  1138         EC_INFO("    Order#: %s\n", slave->eeprom_order);
  1103     if (slave->eeprom_name)
  1139     if (slave->eeprom_name)
  1104         EC_INFO("    Name: %s\n", slave->eeprom_name);
  1140         EC_INFO("    Name: %s\n", slave->eeprom_name);
  1105     if (slave->eeprom_group)
       
  1106         EC_INFO("    Group: %s\n", slave->eeprom_group);
       
  1107     if (slave->eeprom_desc)
       
  1108         EC_INFO("    Description: %s\n", slave->eeprom_desc);
       
  1109 
  1141 
  1110     if (!list_empty(&slave->eeprom_syncs)) {
  1142     if (!list_empty(&slave->eeprom_syncs)) {
  1111         EC_INFO("    Sync-Managers:\n");
  1143         EC_INFO("    Sync-Managers:\n");
  1112         list_for_each_entry(sync, &slave->eeprom_syncs, list) {
  1144         list_for_each_entry(sync, &slave->eeprom_syncs, list) {
  1113             EC_INFO("      %i: 0x%04X, length %i, control 0x%02X, %s\n",
  1145             EC_INFO("      %i: 0x%04X, length %i, control 0x%02X, %s\n",
  1207 /*****************************************************************************/
  1239 /*****************************************************************************/
  1208 
  1240 
  1209 /**
  1241 /**
  1210    Formats attribute data for SysFS read access.
  1242    Formats attribute data for SysFS read access.
  1211    \return number of bytes to read
  1243    \return number of bytes to read
  1212    \ingroup RealTimeInterface
       
  1213 */
  1244 */
  1214 
  1245 
  1215 ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */
  1246 ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */
  1216                                 struct attribute *attr, /**< attribute */
  1247                                 struct attribute *attr, /**< attribute */
  1217                                 char *buffer /**< memory to store data */
  1248                                 char *buffer /**< memory to store data */
  1235             return sprintf(buffer, "%s\n", slave->type->product_name);
  1266             return sprintf(buffer, "%s\n", slave->type->product_name);
  1236     }
  1267     }
  1237     else if (attr == &attr_product_desc) {
  1268     else if (attr == &attr_product_desc) {
  1238         if (slave->type)
  1269         if (slave->type)
  1239             return sprintf(buffer, "%s\n", slave->type->description);
  1270             return sprintf(buffer, "%s\n", slave->type->description);
       
  1271     }
       
  1272     else if (attr == &attr_sii_name) {
       
  1273         if (slave->eeprom_name)
       
  1274             return sprintf(buffer, "%s\n", slave->eeprom_name);
  1240     }
  1275     }
  1241     else if (attr == &attr_type) {
  1276     else if (attr == &attr_type) {
  1242         if (slave->type) {
  1277         if (slave->type) {
  1243             if (slave->type->special == EC_TYPE_BUS_COUPLER)
  1278             if (slave->type->special == EC_TYPE_BUS_COUPLER)
  1244                 return sprintf(buffer, "coupler\n");
  1279                 return sprintf(buffer, "coupler\n");
  1245             else
  1280             else
  1246                 return sprintf(buffer, "normal\n");
  1281                 return sprintf(buffer, "normal\n");
  1247         }
  1282         }
  1248     }
  1283     }
       
  1284     else if (attr == &attr_state) {
       
  1285         switch (slave->current_state) {
       
  1286             case EC_SLAVE_STATE_INIT:
       
  1287                 return sprintf(buffer, "INIT\n");
       
  1288             case EC_SLAVE_STATE_PREOP:
       
  1289                 return sprintf(buffer, "PREOP\n");
       
  1290             case EC_SLAVE_STATE_SAVEOP:
       
  1291                 return sprintf(buffer, "SAVEOP\n");
       
  1292             case EC_SLAVE_STATE_OP:
       
  1293                 return sprintf(buffer, "OP\n");
       
  1294             default:
       
  1295                 return sprintf(buffer, "UNKNOWN\n");
       
  1296         }
       
  1297     }
  1249 
  1298 
  1250     return 0;
  1299     return 0;
  1251 }
  1300 }
  1252 
  1301 
  1253 /*****************************************************************************/
  1302 /*****************************************************************************/
  1254 
  1303 
  1255 /**
  1304 /**
  1256    Application layer status messages.
  1305    Formats attribute data for SysFS write access.
  1257 */
  1306    \return number of bytes processed, or negative error code
  1258 
  1307 */
  1259 const ec_code_msg_t al_status_messages[] = {
  1308 
  1260     {0x0001, "Unspecified error"},
  1309 ssize_t ec_store_slave_attribute(struct kobject *kobj, /**< slave's kobject */
  1261     {0x0011, "Invalud requested state change"},
  1310                                  struct attribute *attr, /**< attribute */
  1262     {0x0012, "Unknown requested state"},
  1311                                  const char *buffer, /**< memory with data */
  1263     {0x0013, "Bootstrap not supported"},
  1312                                  size_t size /**< size of data to store */
  1264     {0x0014, "No valid firmware"},
  1313                                  )
  1265     {0x0015, "Invalid mailbox configuration"},
  1314 {
  1266     {0x0016, "Invalid mailbox configuration"},
  1315     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
  1267     {0x0017, "Invalid sync manager configuration"},
  1316 
  1268     {0x0018, "No valid inputs available"},
  1317     if (attr == &attr_state) {
  1269     {0x0019, "No valid outputs"},
  1318         if (!strcmp(buffer, "INIT\n")) {
  1270     {0x001A, "Synchronisation error"},
  1319             slave->requested_state = EC_SLAVE_STATE_INIT;
  1271     {0x001B, "Sync manager watchdog"},
  1320             slave->state_error = 0;
  1272     {0x0020, "Slave needs cold start"},
  1321             return size;
  1273     {0x0021, "Slave needs INIT"},
  1322         }
  1274     {0x0022, "Slave needs PREOP"},
  1323         else if (!strcmp(buffer, "PREOP\n")) {
  1275     {0x0023, "Slave needs SAVEOP"},
  1324             slave->requested_state = EC_SLAVE_STATE_PREOP;
  1276     {}
  1325             slave->state_error = 0;
  1277 };
  1326             return size;
       
  1327         }
       
  1328         else if (!strcmp(buffer, "SAVEOP\n")) {
       
  1329             slave->requested_state = EC_SLAVE_STATE_SAVEOP;
       
  1330             slave->state_error = 0;
       
  1331             return size;
       
  1332         }
       
  1333         else if (!strcmp(buffer, "OP\n")) {
       
  1334             slave->requested_state = EC_SLAVE_STATE_OP;
       
  1335             slave->state_error = 0;
       
  1336             return size;
       
  1337         }
       
  1338 
       
  1339         EC_ERR("Failed to set slave state!\n");
       
  1340     }
       
  1341 
       
  1342     return -EINVAL;
       
  1343 }
  1278 
  1344 
  1279 /******************************************************************************
  1345 /******************************************************************************
  1280  *  Realtime interface
  1346  *  Realtime interface
  1281  *****************************************************************************/
  1347  *****************************************************************************/
  1282 
  1348