X-Git-Url: http://rtime.felk.cvut.cz/gitweb/pes-rpp/rpp-test-sw.git/blobdiff_plain/35092f9903c112ff36f09066a0c9e2a37faebcee..c13c769f490a1b40ad06c80934d7c628910a6a22:/rpp-test-sw/commands/cmd_port.c diff --git a/rpp-test-sw/commands/cmd_port.c b/rpp-test-sw/commands/cmd_port.c index 12e273c..5f404d7 100644 --- a/rpp-test-sw/commands/cmd_port.c +++ b/rpp-test-sw/commands/cmd_port.c @@ -1,64 +1,74 @@ /* - * Copyright (C) 2012-2013 Czech Technical University in Prague + * Copyright (C) 2012-2015 Czech Technical University in Prague * * Created on: 28.2.2013 * * Authors: * - Michal Horn * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * This document contains proprietary information belonging to Czech + * Technical University in Prague. Passing on and copying of this + * document, and communication of its contents is not permitted + * without prior written authorization. * * File : cmd_port.c * * Abstract: - * Commands for port controlling - * - Printing list of available ports (not yet available) - * - Setting/getting port value* + * Commands for port controlling + * - Printing list of available ports (not yet available) + * - Setting/getting port value* */ #include "cmd_port.h" #include "stdio.h" +#include "string.h" #ifndef DOCGEN #include "rpp/rpp.h" -#include "hal/hal.h" +#include "drv/port.h" +#ifdef TARGET_HAS_SPI +#include "drv/spi.h" +#endif +#include #include "cmdproc_utils.h" +#define MIN(a, b) ((a) < (b) ? (a) : (b)) -int cmd_do_port_list(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) { +int cmd_do_port_list(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ uint32_t i; - char* portInterface; + rpp_sci_printf("List of all defined ports with its type. Those names can be used by portval command.\r\n"); - const port_def_t* ports = hal_port_get_definitions(); - - for (i = 0; i < PORT_CNT; i++) { - if (ports[i].name == PIN_NAME_UNUSED) continue; - if (ports[i].desc->interfaceType == PORT_INTERFACE_SPI) - portInterface = "SPI"; - else if (ports[i].desc->interfaceType == PORT_INTERFACE_GPIO) - portInterface = "GPIO"; - else if (ports[i].desc->interfaceType == PORT_INTERFACE_ADC) - portInterface = "ADC"; - else - portInterface = "UNKNOWN"; - rpp_sci_printf("%s, %s\r\n", ports[i].name, portInterface); + + for (i = 0; i < ARRAY_SIZE(port_desc); i++) { + const struct port_desc *port = &port_desc[i]; + const char *rw[4] = { "N/A", "WO", "RO", "RW" }; + char note[30] = ""; +#ifdef TARGET_HAS_SPI + if (port->set == port_spi_set) + snprintf(note, sizeof(note), "SPI, %s", port->cfg.spi.chip); +#endif + rpp_sci_printf("%-10s %s %dx%db%s%s%s\r\n", + port->name, + rw[(port->set ? 1 : 0) | (port->get ? 2 : 0)], + port->numchn, port->bpch, + *note ? " (": "", + note, + *note ? ")" : ""); } return 1; } +static const struct port_desc *port_from_name(const char *port_name) +{ + uint32_t i; + for (i = 0; i < ARRAY_SIZE(port_desc); i++) + if (strcmp(port_name, port_desc[i].name) == 0) + return &port_desc[i]; + return NULL; +} /** * @brief Read values from specified port @@ -68,174 +78,217 @@ int cmd_do_port_list(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) * @param[in] param Parameters of command * @return 0 when OK or error code */ -int cmd_do_port_val(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) { - char *p; - int i; - port_desc_t* desc; - uint32_t ret; - uint32_t values[MAX_PARAM_VALUES_NUM]; - char portName[32]; - char* token; - uint32_t numParams; - - p = param[1]; - if (sscanf(p, "%31s ", portName) != 1) { - return -CMDERR_BADPAR; - } - - if((desc = hal_port_get_dsc(portName, -1))==NULL) return -CMDERR_BADREG; - - if(param[2] != NULL){ // More parameters = set values - p=param[2]; - if (desc->port_setfnc_ptr == NULL) { - return -CMDERR_WRPERM; - } - else { - if (desc->interfaceType == PORT_INTERFACE_GPIO) { - // Information about pin values are encoded as hexadecimal 8b value - numParams = desc->numValues/8+1; - } - else if (desc->interfaceType == PORT_INTERFACE_SPI) { - // Commands are passed as bytes - numParams = desc->numValues; - } - else if (desc->interfaceType == PORT_INTERFACE_ADC) { - return -CMDERR_BADPAR; // ADC is read only and no other port is supported +int cmd_do_port_val(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + int32_t ret; + int i; + char portName[32]; + + if (sscanf(param[1], "%31s ", portName) != 1) + return -CMDERR_BADPAR; + + const struct port_desc *port = port_from_name(portName); + if (!port) + return -CMDERR_BADPAR; + + if (param[2] != NULL) { // More parameters = set values + if (!port->set) + return -CMDERR_WRPERM; + + switch (port->bpch) { + case 1: { + uint32_t value; + ret = sscanf(param[2], "%i", &value); + if (ret == EOF || ret == 0) + return -CMDERR_BADPAR; + + ret = port->set(port, &value, sizeof(value)); + if (ret == FAILURE) + return -CMDERR_WRPERM; + return cmd_opchar_replong(cmd_io, param, value, 0, 16); } - token = strtok(p, " "); - i = 0; - while (i < numParams && token != NULL) { - if (sscanf(token, "%x", &values[i]) == EOF) { - break; + case 16: { + uint16_t value[8]; + int i, n; + char *p = param[2]; + assert(port->numchn <= ARRAY_SIZE(value)); + + for (i = 0; i < port->numchn; i++) { + ret = sscanf(param[2], "%hi%n", &value[i], &n); + if (ret == EOF || ret == 0) + break; + value[i] = cpu_to_be16(value[i]); + p += n; + } + + ret = port->set(port, &value, port->numchn * 2); + if (ret == FAILURE) + return -CMDERR_WRPERM; + if (port->numchn == 1) + return cmd_opchar_replong(cmd_io, param, be16_to_cpu(value[0]), 0, 16); + else { + for (i = 0; i < port->numchn; i++) + rpp_sci_printf("%#x ", be16_to_cpu(value[i])); + rpp_sci_printf("\n"); + return 0; } - token = strtok(NULL, " "); - i++; } + case 24: { + uint32_t value; + ret = sscanf(param[2], "%i", &value); + if (ret == EOF || ret == 0 || (value & 0xff000000)) + return -CMDERR_BADPAR; - if (i != numParams || token != NULL) { - return -CMDERR_BADPAR; + char v[3] = { (value >> 16) & 0xff, (value >> 8) & 0xff, (value >> 0) & 0xff }; + + ret = port->set(port, &v, sizeof(v)); + if (ret == FAILURE) + return -CMDERR_WRPERM; + value = v[0] << 16 | v[1] << 8 | v[2]; + return cmd_opchar_replong(cmd_io, param, value, 0, 16); } - ret = desc->port_setfnc_ptr(desc->config, desc->numValues, values); - } - return cmd_opchar_replong(cmd_io, param, ret, 0, 16); - } - else { - if (desc->port_getfnc_ptr == NULL) { + case 32: { + uint32_t value; + ret = sscanf(param[2], "%i", &value); + if (ret == EOF || ret == 0) + return -CMDERR_BADPAR; + + char v[4] = { (value >> 24) & 0xff, (value >> 16) & 0xff, (value >> 8) & 0xff, (value >> 0) & 0xff }; + + ret = port->set(port, &v, sizeof(v)); + if (ret == FAILURE) + return -CMDERR_WRPERM; + value = v[0] << 24 | v[1] << 16 | v[2] << 8 | v[3]; + return cmd_opchar_replong(cmd_io, param, value, 0, 16); + } + default: + rpp_sci_printf("Unsupported bits-per-channel value: %d\n", port->bpch); + return -CMDERR_NODEV; + } + } else { /* Get values from port */ + if (!port->get) return -CMDERR_RDPERM; - } - else { - ret = desc->port_getfnc_ptr(desc->config, desc->numValues, values); - for (i = 0; i < desc->numValues; i++) { - rpp_sci_printf("%d\r\n", values[i]); + + /* Workaround for cmd_opchar_replong() to work */ + param[2] = param[0] + strlen(param[0]); + + switch (port->bpch) { + case 1: { + uint32_t value = 0; + ret = port->get(port, &value, sizeof(value)); + if (ret == FAILURE) + return -CMDERR_RDPERM; + return cmd_opchar_replong(cmd_io, param, value, 0, 16); + } + case 16: { + uint16_t values[16] = {0}; + if (port->numchn > ARRAY_SIZE(values)) + return -CMDERR_BADCFG; + ret = port->get(port, &values, sizeof(values)); + if (ret == FAILURE) + return -CMDERR_RDPERM; + + if (port->numchn == 1) + return cmd_opchar_replong(cmd_io, param, values[0], 0, 16); + else { + rpp_sci_printf("%*s=", param[2] - param[0], param[0]); + for (i = 0; i < port->numchn; i++) + rpp_sci_printf(" %hx", values[i]); + rpp_sci_printf("\n"); + return 0; } - } - rpp_sci_printf("portval%s=%x", portName, ret); - return 0; - } + } + default: + rpp_sci_printf("Unsupported bits-per-channel value: %d\n", port->bpch); + return -CMDERR_NODEV; + } + } + return 0; } -#endif /* DOCGEN */ +#endif /* DOCGEN */ /** Command descriptor for read values from port command */ -cmd_des_t const cmd_des_port_val={ - 0, 0, - "portval*","Read or write values from or to the port", - "=== Command syntax ===\n" - "\n" - " portval \n" - " portval\n" - "where\n" - "* is a string specifying the name of the port\n" - "* is a sequence of hexadecimal numbers, separated by spaces, e.g. 12 AA CD\n\n" - "\n" - "=== Description ===\n" - "\n" - "This command sets or gets values of all pins on the specified port.\n" - "If the port is connected to the GPIO interface of the MCU, then\n" - "when writing the value, the lowest significant bit of the argument\n" - "is assigned to the first pin, the second bit is assigned to the\n" - "second pin, etc. The command returns zero.\n" - "When reading from the port, the command returns values for each pin.\n" - "\n" - "If the port is connected to the SPI interface of the MCU, then\n" - "it is write only and the argument is interpreted as a command for\n" - "the port controller. The command returns the response from the\n" - "port controller.\n" - "For command examples please refer to the project wiki\n" - "\n" - "If the port is connected to the ADC interface of the MCU, then\n" - "it is read only and returns values for each ADC pin.\n" - "\n" - "Port names and interface type can be obtained with the portlist\n" - "command.\n" - "\n" - "NOTE: For successful communication with the HBR, HBR_EN pin must\n" - "be set first.\n" - "\n" - "=== Example ===\n" - "\n" - " --> portvalMOUTIN 3A\n" - " portvalMOUTIN=0\n" - " --> portvalMOUTIN\n" - " 0\n" - " 1\n" - " 0\n" - " 1\n" - " 1\n" - " 1\n" - "\n" - "This pair of commands sets:\nMOUT1IN" - "MOUT1IN=0\n" - "MOUT2IN=1\n" - "MOUT3IN=0\n" - "MOUT4IN=1\n" - "MOUT5IN=1\n" - "MOUT6IN=1\n" - "Which is shown in getter output\n", - CMD_HANDLER(cmd_do_port_val), (void *)&cmd_list_port +cmd_des_t const cmd_des_port_val = { + 0, 0, + "portval*","Read or write values from or to the port", + "### Command syntax ###\n" + "\n" + " portval [ ...]\n" + " portval\n" + "where\n" + "\n" + "- `` is a string specifying the name of the port\n" + "- `` is decimal, hexdecimal (0x) or octal (0) number\n" + "\n" + "### Description ###\n" + "\n" + "This command sets (when VAL is present) or gets (without VAL) values\n" + "of all channels of the specified port. For digital IO ports (1 bit per\n" + "channel), the least significant bit of the VAL corresponds to the\n" + "first pin, the second bit to the second pin, etc.\n" + "\n" + "The set variant of the command returns a value that depends on the\n" + "port type. For digital IO, this is the value set, for SPI ports this\n" + "is the SPI response.\n" + "\n" + "The get variant returns the value read from the port.\n" + "\n" + "If the port represents an SPI interface of the MCU, then it is write\n" + "only and the argument is interpreted as a command for the port\n" + "controller.\n" + "\n" + "If the port is represents the ADC interface of the MCU, it is read\n" + "only and returns values for each ADC pin.\n" + "\n" + "Port names and interface type can be obtained with the portlist\n" + "command.\n" + "\n" + "### Example ###\n" + "\n" + " --> portvalGIOB 0x3A\n" + " portvalGIOB=0x3a\n" + " --> portvalGIOB\n" + " portvalGIOB=0x3a\n" + "This pair of commands sets:\nGIOB" + "GIOB=0\n" + "GIOB=1\n" + "GIOB=0\n" + "GIOB=1\n" + "GIOB=1\n" + "GIOB=1\n" + "Which is shown in getter output\n", + CMD_HANDLER(cmd_do_port_val), (void *)&cmd_list_port }; /** Command descriptor for port list printout */ -cmd_des_t const cmd_des_port_list={ - 0, 0, - "portlist","Print a list of all port names", - "=== Command syntax ===\n" - "\n" - " portlist\n" - "\n" - "=== Description ===\n" - "\n" - "This command prints the list of all defined ports accessible via the\n" - "portval command. Each record of the list is a couple of\n" - "PortName-PortInterface, where PortInterface is SPI, ADC or GPIO.\n" - "The type of the MCU<->port interface slightly modifies the meaning\n" - "of the portval command." - "\n" - "=== Example ===\n" - "\n" - " --> portlist\n" - " List of all defined ports with its type. Those names can be used by portval command.\n" - " DINMCU, GPIO\n" - " DINSPI, SPI\n" - " HOUTDIAG, GPIO\n" - " HOUTIN, GPIO\n" - " HOUTIFBK, ADC\n" - " ADC, ADC\n" - " LOUT, SPI\n" - " DAC12, SPI\n" - " DAC34, SPI\n" - " DACDREF, SPI\n" - " HBR, SPI\n" - " FRAY1, SPI\n" - " FRAY2, SPI\n" - " MOUTEN, GPIO\n" - " MOUTIN, GPIO\n", - CMD_HANDLER(cmd_do_port_list), (void *)&cmd_list_port +cmd_des_t const cmd_des_port_list = { + 0, 0, + "portlist","Print a list of all port names", + "### Command syntax ###\n" + "\n" + " portlist\n" + "\n" + "### Description ###\n" + "\n" + "This command prints the list of all defined ports accessible via the\n" + "portval command. Each line contains port name, read/write type, number\n" + "of channels and width of the channel in bits.\n" + "\n" + "### Example ###\n" + "\n" + " --> portlist\n" + " List of all defined ports with its type. Those names can be used by portval command.\n" + " GIOA RW 8x1b\n" + " GIOB RW 8x1b\n" + " NHET RW 30x1b\n" + " ADC RO 16x12b\n", + CMD_HANDLER(cmd_do_port_list), (void *)&cmd_list_port }; /** List of commands for port, defined as external */ -cmd_des_t const *cmd_list_port[]={ - &cmd_des_port_val, - &cmd_des_port_list, - NULL +cmd_des_t const *cmd_list_port[] = { + &cmd_des_port_val, + &cmd_des_port_list, + NULL };