/* * Query and display generic information about the DyIO device. */ void dyio_info(dyio_t *d) { int voltage; /* Print firmware revision. */ dyio_call(d, PKT_GET, ID_DYIO, "_rev", 0, 0); if (d->reply_len < 6) { printf("dyio-info: incorrect _rev reply: length %u bytes\n", d->reply_len); exit(-1); } printf("Firmware Revision: %u.%u.%u\n", d->reply[0], d->reply[1], d->reply[2]); /* Print voltage and power status. */ dyio_call(d, PKT_GET, ID_DYIO, "_pwr", 0, 0); if (d->reply_len < 5) { printf("dyio-info: incorrect _pwr reply: length %u bytes\n", d->reply_len); exit(-1); } voltage = (d->reply[2] << 8) | d->reply[3]; printf("Power Input: %.1fV, Override=%u\n", voltage / 1000.0, d->reply[4]); printf("Rail Power Source: Right=%s, Left=%s\n", d->reply[0] ? "Internal" : "External", d->reply[1] ? "Internal" : "External"); }
/* * Query and display information about the channels. */ void dyio_print_channels(dyio_t *d) { int num_channels, c; uint8_t chan_mode[MAX_CHANNELS], *p; int chan_value[MAX_CHANNELS]; /* Get current channel modes. */ dyio_call(d, PKT_GET, ID_BCS_IO, "gacm", 0, 0); if (d->reply_len < 1) { printf("dyio-info: incorrect gacm reply: length %u bytes\n", d->reply_len); exit(-1); } num_channels = d->reply[0]; memcpy(chan_mode, &d->reply[1], num_channels); /* Get current pin values. */ dyio_call(d, PKT_GET, ID_BCS_IO, "gacv", 0, 0); if (d->reply_len < 1) { printf("dyio-info: incorrect gacv reply: length %u bytes\n", d->reply_len); exit(-1); } for (c=0; c<num_channels; c++) { p = &d->reply[1 + c*4]; chan_value[c] = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; } printf("\nChannel Status:\n"); for (c=0; c<num_channels; c++) { printf(" %2u: %-20s = %u\n", c, mode_name(chan_mode[c]), chan_value[c]); } }
/* * Query and print a table of channel capabilities. */ void dyio_print_channel_features(dyio_t *d) { int num_channels, c, num_modes, i, m; uint8_t query[1], chan_feature[MAX_CHANNELS][MAX_MODES]; /* Get number of channels. */ dyio_call(d, PKT_GET, ID_BCS_IO, "gchc", 0, 0); if (d->reply_len < 4) { printf("dyio-info: incorrect gchc reply: length %u bytes\n", d->reply_len); exit(-1); } num_channels = d->reply[3]; memset(chan_feature, 0, sizeof(chan_feature)); /* Build a matrix of channel features. */ for (c=0; c<num_channels; c++) { /* Get a list of channel modes. */ query[0] = c; dyio_call(d, PKT_GET, ID_BCS_IO, "gcml", query, 1); if (d->reply_len < 1) { printf("dyio-info: incorrect gcml[%u] reply\n", c); exit(-1); } num_modes = d->reply[0]; for (i=0; i<num_modes; i++) { m = d->reply[1+i]; chan_feature[c][m] = 1; } } printf("\n"); printf("Channel Features: 1 1 1 1 1 1 1 1 1 1 2 2 2 2\n"); printf(" 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3\n"); for (m=MODE_DI; m<MAX_MODES; m++) { if (m == MODE_UNUSED) continue; printf(" %-22s", mode_name(m)); for (c=0; c<num_channels; c++) { printf("%c ", chan_feature[c][m] ? '+' : '.'); } printf("\n"); } }
/* * Set channel mode. */ void dyio_set_mode(int ch, int mode) { uint8_t query[3]; query[0] = ch; query[1] = mode; query[2] = 0; dyio_call(PKT_POST, ID_BCS_SETMODE, "schm", query, 3); if (dyio_replylen < 1) { printf("dyio-info: incorrect schm[%u] reply\n", ch); exit(-1); } }
/* * Set channel value. */ int dyio_get_value(int ch) { uint8_t query[1]; int value; query[0] = ch; dyio_call(PKT_GET, ID_BCS_IO, "gchv", query, 1); if (dyio_replylen < 5) { printf("dyio-info: incorrect gchv[%u] reply\n", ch); exit(-1); } value = (dyio_reply[1] << 24) | (dyio_reply[2] << 16) | (dyio_reply[3] << 8) | dyio_reply[4]; return value; }
/* * Establish a connection to the DyIO device. */ void dyio_connect(const char *devname) { /* Open serial port */ if (serial_open(devname, 115200) < 0) { /* failed to open serial port */ exit(-1); } /* Ping the device. */ dyio_call(PKT_GET, ID_BCS_CORE, "_png", 0, 0); if (dyio_debug) printf("dyio-connect: OK\n"); if (verbose) printf("DyIO device address: %02x-%02x-%02x-%02x-%02x-%02x\n", dyio_reply_mac[0], dyio_reply_mac[1], dyio_reply_mac[2], dyio_reply_mac[3], dyio_reply_mac[4], dyio_reply_mac[5]); }
/* * Set channel value. */ void dyio_set_value(int ch, int value, int msec) { uint8_t query[9]; query[0] = ch; query[1] = value >> 24; query[2] = value >> 16; query[3] = value >> 8; query[4] = value; query[5] = msec >> 24; query[6] = msec >> 16; query[7] = msec >> 8; query[8] = msec; dyio_call(PKT_POST, ID_BCS_IO, "schv", query, 9); if (dyio_replylen < 2) { printf("dyio-info: incorrect schv[%u] reply\n", ch); exit(-1); } }
/* * Query and display information about the namespaces. */ void dyio_print_namespaces(dyio_t *d) { int query_type, resp_type, num_args, num_resp; int num_spaces, ns, num_methods, m; uint8_t query[2], *args, *resp; char rpc[5]; /* Query the number of namespaces. */ dyio_call(d, PKT_GET, ID_BCS_CORE, "_nms", 0, 0); if (d->reply_len < 1) { printf("dyio-info: incorrect _nms reply: length %u bytes\n", d->reply_len); exit(-1); } num_spaces = d->reply[0]; /* Print info about every namespace. */ for (ns=0; ns<num_spaces; ns++) { query[0] = ns; dyio_call(d, PKT_GET, ID_BCS_CORE, "_nms", query, 1); if (d->reply_len < 1) { printf("dyio-info: incorrect _nms[%u] reply\n", ns); exit(-1); } printf("Namespace %u: %s\n", ns, d->reply); /* Print available methods. */ num_methods = 1; for (m=0; m<num_methods; m++) { /* Get method name (RPC). */ query[0] = ns; query[1] = m; dyio_call(d, PKT_GET, ID_BCS_RPC, "_rpc", query, 2); if (d->reply_len < 7) { printf("dyio-info: incorrect _rpc[%u] reply\n", ns); exit(-1); } num_methods = d->reply[2]; rpc[0] = d->reply[3]; rpc[1] = d->reply[4]; rpc[2] = d->reply[5]; rpc[3] = d->reply[6]; rpc[4] = 0; /* Get method args. */ query[0] = ns; query[1] = m; dyio_call(d, PKT_GET, ID_BCS_RPC, "args", query, 2); if (d->reply_len < 6) { printf("dyio-info: incorrect args[%u] reply\n", ns); exit(-1); } query_type = d->reply[2]; num_args = d->reply[3]; args = &d->reply[4]; resp_type = d->reply[4 + num_args]; num_resp = d->reply[5 + num_args]; resp = &d->reply[6 + num_args]; printf(" %s %s(", rpc, pkt_name(query_type)); print_args(num_args, args); printf(") -> %s(", pkt_name(resp_type)); print_args(num_resp, resp); printf(")\n"); } } }