]> rtime.felk.cvut.cz Git - pes-rpp/rpp-test-sw.git/blob - rpp-test-sw/commands/cmd_port.c
Change license to MIT
[pes-rpp/rpp-test-sw.git] / rpp-test-sw / commands / cmd_port.c
1 /*
2  * Copyright (C) 2012-2015 Czech Technical University in Prague
3  *
4  * Created on: 28.2.2013
5  *
6  * Authors:
7  *     - Michal Horn
8  *
9  * Permission is hereby granted, free of charge, to any person
10  * obtaining a copy of this software and associated documentation
11  * files (the "Software"), to deal in the Software without
12  * restriction, including without limitation the rights to use,
13  * copy, modify, merge, publish, distribute, sublicense, and/or sell
14  * copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following
16  * conditions:
17  *
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  *
30  * File : cmd_port.c
31  *
32  * Abstract:
33  *           Commands for port controlling
34  *          - Printing list of available ports (not yet available)
35  *          - Setting/getting port value*
36  */
37
38 #include "cmd_port.h"
39 #include "stdio.h"
40 #include "string.h"
41
42 #ifndef DOCGEN
43
44 #include "rpp/rpp.h"
45 #include "drv/port.h"
46 #ifdef TARGET_HAS_SPI
47 #include "drv/spi.h"
48 #endif
49 #include <drv/endian.h>
50 #include "cmdproc_utils.h"
51
52 #define MIN(a, b) ((a) < (b) ? (a) : (b))
53
54 int cmd_do_port_list(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
55 {
56         uint32_t i;
57
58         rpp_sci_printf("List of all defined ports with its type. Those names can be used by portval command.\r\n");
59
60         for (i = 0; i < ARRAY_SIZE(port_desc); i++) {
61                 const struct port_desc *port = &port_desc[i];
62                 const char *rw[4] = { "N/A", "WO", "RO", "RW" };
63                 char note[30] = "";
64 #ifdef TARGET_HAS_SPI
65                 if (port->set == port_spi_set)
66                         snprintf(note, sizeof(note), "SPI, %s", port->cfg.spi.chip);
67 #endif
68                 rpp_sci_printf("%-10s %s %dx%db%s%s%s\r\n",
69                                            port->name,
70                                            rw[(port->set ? 1 : 0) | (port->get ? 2 : 0)],
71                                            port->numchn, port->bpch,
72                                            *note ? " (": "",
73                                            note,
74                                            *note ? ")" : "");
75         }
76         return 1;
77 }
78
79 static const struct port_desc *port_from_name(const char *port_name)
80 {
81         uint32_t i;
82
83         for (i = 0; i < ARRAY_SIZE(port_desc); i++)
84                 if (strcmp(port_name, port_desc[i].name) == 0)
85                         return &port_desc[i];
86         return NULL;
87 }
88
89 /**
90  * @brief       Read values from specified port
91  *
92  * @param[in]   cmd_io  Pointer to IO stack
93  * @param[in]   des             Pointer to command descriptor
94  * @param[in]   param   Parameters of command
95  * @return      0 when OK or error code
96  */
97 int cmd_do_port_val(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
98 {
99         int32_t ret;
100         int i;
101         char portName[32];
102
103         if (sscanf(param[1], "%31s ", portName) != 1)
104                 return -CMDERR_BADPAR;
105
106         const struct port_desc *port = port_from_name(portName);
107         if (!port)
108                 return -CMDERR_BADPAR;
109
110         if (param[2] != NULL) { // More parameters = set values
111                 if (!port->set)
112                         return -CMDERR_WRPERM;
113
114                 switch (port->bpch) {
115                 case 1: {
116                         uint32_t value;
117                         ret = sscanf(param[2], "%i", &value);
118                         if (ret == EOF || ret == 0)
119                                 return -CMDERR_BADPAR;
120
121                         ret = port->set(port, &value, sizeof(value));
122                         if (ret == FAILURE)
123                                 return -CMDERR_WRPERM;
124                         return cmd_opchar_replong(cmd_io, param, value, 0, 16);
125                 }
126                 case 16: {
127                         uint16_t value[8];
128                         int i, n;
129                         char *p = param[2];
130                         assert(port->numchn <= ARRAY_SIZE(value));
131
132                         for (i = 0; i < port->numchn; i++) {
133                                 ret = sscanf(param[2], "%hi%n", &value[i], &n);
134                                 if (ret == EOF || ret == 0)
135                                         break;
136                                 value[i] = cpu_to_be16(value[i]);
137                                 p += n;
138                         }
139
140                         ret = port->set(port, &value, port->numchn * 2);
141                         if (ret == FAILURE)
142                                 return -CMDERR_WRPERM;
143                         if (port->numchn == 1)
144                                 return cmd_opchar_replong(cmd_io, param, be16_to_cpu(value[0]), 0, 16);
145                         else {
146                                 for (i = 0; i < port->numchn; i++)
147                                         rpp_sci_printf("%#x ", be16_to_cpu(value[i]));
148                                 rpp_sci_printf("\n");
149                                 return 0;
150                         }
151                 }
152                 case 24: {
153                         uint32_t value;
154                         ret = sscanf(param[2], "%i", &value);
155                         if (ret == EOF || ret == 0 || (value & 0xff000000))
156                                 return -CMDERR_BADPAR;
157
158                         char v[3] = { (value >> 16) & 0xff, (value >> 8) & 0xff, (value >> 0) & 0xff };
159
160                         ret = port->set(port, &v, sizeof(v));
161                         if (ret == FAILURE)
162                                 return -CMDERR_WRPERM;
163                         value = v[0] << 16 | v[1] << 8 | v[2];
164                         return cmd_opchar_replong(cmd_io, param, value, 0, 16);
165                 }
166                 case 32: {
167                         uint32_t value;
168                         ret = sscanf(param[2], "%i", &value);
169                         if (ret == EOF || ret == 0)
170                                 return -CMDERR_BADPAR;
171
172                         char v[4] = { (value >> 24) & 0xff, (value >> 16) & 0xff, (value >> 8) & 0xff, (value >> 0) & 0xff };
173
174                         ret = port->set(port, &v, sizeof(v));
175                         if (ret == FAILURE)
176                                 return -CMDERR_WRPERM;
177                         value = v[0] << 24 | v[1] << 16 | v[2] << 8 | v[3];
178                         return cmd_opchar_replong(cmd_io, param, value, 0, 16);
179                 }
180                 default:
181                         rpp_sci_printf("Unsupported bits-per-channel value: %d\n", port->bpch);
182                         return -CMDERR_NODEV;
183                 }
184         } else { /* Get values from port */
185                 if (!port->get)
186                         return -CMDERR_RDPERM;
187
188                 /* Workaround for cmd_opchar_replong() to work */
189                 param[2] = param[0] + strlen(param[0]);
190
191                 switch (port->bpch) {
192                 case 1: {
193                         uint32_t value = 0;
194                         ret = port->get(port, &value, sizeof(value));
195                         if (ret == FAILURE)
196                                 return -CMDERR_RDPERM;
197                         return cmd_opchar_replong(cmd_io, param, value, 0, 16);
198                 }
199                 case 16: {
200                         uint16_t values[16] = {0};
201                         if (port->numchn > ARRAY_SIZE(values))
202                                 return -CMDERR_BADCFG;
203                         ret = port->get(port, &values, sizeof(values));
204                         if (ret == FAILURE)
205                                 return -CMDERR_RDPERM;
206
207                         if (port->numchn == 1)
208                                 return cmd_opchar_replong(cmd_io, param, values[0], 0, 16);
209                         else {
210                                 rpp_sci_printf("%*s=", param[2] - param[0], param[0]);
211                                 for (i = 0; i < port->numchn; i++)
212                                         rpp_sci_printf(" %hx", values[i]);
213                                 rpp_sci_printf("\n");
214                                 return 0;
215                         }
216                 }
217                 default:
218                         rpp_sci_printf("Unsupported bits-per-channel value: %d\n", port->bpch);
219                         return -CMDERR_NODEV;
220                 }
221         }
222 #pragma diag_remark 112
223         return 0; //warning #112-D: statement is unreachable
224 #pragma diag_warning 112
225 }
226
227 #endif  /* DOCGEN */
228
229 /** Command descriptor for read values from port command */
230 cmd_des_t const cmd_des_port_val = {
231         0, 0,
232         "portval*","Read or write values from or to the port",
233         "### Command syntax ###\n"
234         "\n"
235         "     portval<NAME> <VAL> [<VAL> ...]\n"
236         "     portval<NAME>\n"
237         "where\n"
238         "\n"
239         "- `<NAME>` is a string specifying the name of the port\n"
240         "- `<VAL>` is decimal, hexdecimal (0x) or octal (0) number\n"
241         "\n"
242         "### Description ###\n"
243         "\n"
244         "This command sets (when VAL is present) or gets (without VAL) values\n"
245         "of all channels of the specified port. For digital IO ports (1 bit per\n"
246         "channel), the least significant bit of the VAL corresponds to the\n"
247         "first pin, the second bit to the second pin, etc.\n"
248         "\n"
249         "The set variant of the command returns a value that depends on the\n"
250         "port type. For digital IO, this is the value set, for SPI ports this\n"
251         "is the SPI response.\n"
252         "\n"
253         "The get variant returns the value read from the port.\n"
254         "\n"
255         "If the port represents an SPI device, then it is write only and the\n"
256         "argument is interpreted as a message sent to the device.\n"
257         "\n"
258         "If the port is represents the ADC interface of the MCU, it is read\n"
259         "only and returns values for each ADC pin.\n"
260         "\n"
261         "Port names and interface type can be obtained with the portlist\n"
262         "command.\n"
263         "\n"
264         "### Example ###\n"
265         "\n"
266         "     --> portvalGIOB 0x3A\n"
267         "     portvalGIOB=0x3a\n"
268         "     --> portvalGIOB\n"
269         "     portvalGIOB=0x3a\n"
270         "     --> portvalADCCND 0x4100 0x4100 0x4100 0x4100 0x4100 0x4100\n"
271         "     0xffff 0xffff 0xffff 0xffff 0xffff 0xffff\n",
272         CMD_HANDLER(cmd_do_port_val), (void *)&cmd_list_port
273 };
274
275 /** Command descriptor for port list printout */
276 cmd_des_t const cmd_des_port_list = {
277         0, 0,
278         "portlist","Print a list of all port names",
279         "### Command syntax ###\n"
280         "\n"
281         "     portlist\n"
282         "\n"
283         "### Description ###\n"
284         "\n"
285         "This command prints the list of all defined ports accessible via the\n"
286         "portval command. Each line contains port name, read/write type, number\n"
287         "of channels and width of the channel in bits.\n"
288         "\n"
289         "### Example ###\n"
290         "\n"
291         "     --> portlist\n"
292         "     List of all defined ports with its type. Those names can be used by portval command.\n"
293         "     GIOA       RW 8x1b\n"
294         "     GIOB       RW 8x1b\n"
295         "     NHET1      RW 30x1b\n"
296         "     ADC        RO 24x16b\n"
297         "     THERM1     WO 1x16b (SPI, MCP6S93)\n"
298         "     THERM2     WO 1x16b (SPI, MCP6S93)\n"
299         "     ADCCND     WO 6x16b (SPI, MCP6S93)\n"
300         "     PWR        WO 1x16b (SPI, TPS65381)\n"
301         "     SENSUP     WO 1x16b (SPI, MCP6S93)\n"
302         "     DACLBK     WO 1x16b (SPI, MCP6S93)\n",
303         CMD_HANDLER(cmd_do_port_list), (void *)&cmd_list_port
304 };
305
306 /** List of commands for port, defined as external */
307 cmd_des_t const *cmd_list_port[] = {
308         &cmd_des_port_val,
309         &cmd_des_port_list,
310         NULL
311 };