OpenCores
URL https://opencores.org/ocsvn/gecko3/gecko3/trunk

Subversion Repositories gecko3

[/] [gecko3/] [trunk/] [GECKO3COM/] [gecko3com-fw/] [firmware/] [src/] [scpi_parser.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 nussgipfel
/* GECKO3COM
2
 *
3
 * Copyright (C) 2009 by
4
 *   ___    ____  _   _
5
 *  (  _`\ (  __)( ) ( )
6
 *  | (_) )| (_  | |_| |   Berne University of Applied Sciences
7
 *  |  _ <'|  _) |  _  |   School of Engineering and
8
 *  | (_) )| |   | | | |   Information Technology
9
 *  (____/'(_)   (_) (_)
10
 *
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation, either version 3 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
 
25
/*********************************************************************/
26
/** \file     scpi_parser.c
27
 *********************************************************************
28
 * \brief     Parser for the SCPI commands.
29
 *
30
 *            The supported commands are defined here in the parser.
31
 *            So if you would like to extend the known set of commands,
32
 *            you have to add them here. \n
33
 *            The parser excecutes the necessary Function(s) for the
34
 *            detected command or it sets the "action" enum
35
 *            variable to signal wich command was parsed.
36
 *            In these way this parser handles most IEEE488.2 and SCPI 1999.0
37
 *            mandatory commands and SCPI 1999.0 itself.
38
 *
39
 * \note      when used with USB 1.1 systems, the maximum command length
40
 *            you can define is limited to 52 characters because we only
41
 *            parse commands in the first packet.
42
 *
43
 *
44
 * \author    Christoph Zimmermann bfh.ch * \date      2009-02-04
45
 *
46
*/
47
 
48
#include <stdint.h>
49
#include <ctype.h>
50
#include <string.h>
51
 
52
#include "scpi_parser.h"
53
#include "usb_tmc.h"
54
#include "usb_descriptors.h"
55
#include "firmware_version.h"
56
#include "debugprint.h"
57
 
58
 
59
#define SCPI_VERSION "1999.0\n" /**< Version of the SCPI standard this device complies to */
60
 
61
#define MAXFILL       12 /**< Maximum length of the longest command, defines the buffer size of the parser */
62
 
63
 
64
/** helper function to convert a unsigned byte to an ascii string
65
 *
66
 *  \param[in]  byte unsigned byte to convert
67
 *  \param[out] ascii string with "\n" at the end
68
 *  \return     length of string
69
 */
70
static uint8_t byte2ascii(uint8_t byte, xdata unsigned char *ascii) {
71
  idata unsigned char first_digit, second_digit, third_digit;
72
 
73
  first_digit = byte % 10;
74
  byte -= first_digit;
75
  byte /= 10;
76
  second_digit = byte % 10;
77
  if(second_digit == 0) {
78
    ascii[0] = first_digit + '0';
79
    ascii[1] = '\n';
80
    return 2;
81
  }
82
  byte -= second_digit;
83
  byte /= 10;
84
  third_digit = byte % 10;
85
  if(third_digit == 0) {
86
    ascii[0] = second_digit + '0';
87
    ascii[1] = first_digit + '0';
88
    ascii[2] = '\n';
89
    return 3;
90
  }
91
  ascii[0] = third_digit + '0';
92
  ascii[1] = second_digit + '0';
93
  ascii[2] = first_digit + '0';
94
  ascii[3] = '\n';
95
  return 4;
96
}
97
 
98
/** helper function to convert an ascii string to a unsigned byte
99
 *
100
 *  \param[in]  ascii string with '\n' or '\0' at the end
101
 *  \return byte result unsigned byte, 0 if case of error
102
 */
103
static uint8_t ascii2byte(const xdata unsigned char *ascii) {
104
  idata uint8_t byte = 0, i = 0;
105
  idata unsigned char local_char;
106
 
107
  for(i; i<4;i++) {
108
    local_char = ascii[i];
109
    if(local_char >= '0' && local_char <= '9') {
110
      byte = byte*10 + (local_char - '0');
111
    }
112
    else if(local_char == '\n' || local_char == '\0') {
113
      return byte;
114
    }
115
    else {
116
      ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
117
      return 0;
118
    }
119
  }
120
 
121
  ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
122
  return 0;
123
}
124
 
125
 
126
/** helper function to copy unicode 16 chars from the usb descriptor to an
127
 * ascii string to form the *idn? response
128
 *
129
 * \param[in] pointer to string to fill
130
 * \param[in] pointer to usb string descriptor to read from
131
 * \return pointer that points to the last character in the string (one before \0)
132
 */
133
static char* descr2string(char *target, const xdata char *descriptor) {
134
  uint8_t i, j, descriptor_length;
135
 
136
  /* the first byte in the descriptor is the length, second byte is the type */
137
  descriptor_length = (uint8_t)descriptor[0] - 2;
138
  descriptor_length >>= 1;
139
 
140
  for (i = 0; i < descriptor_length; i++){
141
    j = i << 1;
142
    j += 2;
143
    target[i] = descriptor[j];
144
  }
145
  target[i+1] = '\0';
146
 
147
  return &target[i];
148
}
149
 
150
 
151
/* -------------------------------------------------------------------- */
152
/** \brief SCPI command parser */
153
int8_t scpi_scan(idata uint16_t *offset, xdata Scanner *s, xdata TMC_Response_Queue *queue){
154
 
155
  xdata unsigned char buffer[MAXFILL];
156
  unsigned char *string_index;
157
  uint8_t i;
158
  char * xdata srcPtr = s->source;
159
  xdata unsigned char * xdata bufferPtr = buffer;
160
 
161
  xdata uint16_t * xdata localqueuelength = &queue->length;
162
  xdata uint8_t * xdata localqueue = queue->buf;
163
 
164
  srcPtr += *offset;
165
 
166
  for(i=0;i<MAXFILL;i++) {
167
    buffer[i] = tolower(*srcPtr);
168
    srcPtr++;
169
  }
170
 
171
  /* this set of commands the mandatory IEEE488 commands */
172
 
173
  if(*bufferPtr == '*') {
174
    bufferPtr++;
175
 
176
    if(!strncmp("cls", bufferPtr, 3)) {
177
      /** \li *cls, clear status command */
178
      ieee488_status.EventStatusRegister = 0;
179
      ieee488_status.StatusByteRegister = 0;
180
      usb_tmc_state = TMC_STATE_IDLE;
181
      return 1;
182
    }
183
 
184
    if(!strncmp("ese", bufferPtr, 3)) {
185
      bufferPtr += 3;
186
      if(*bufferPtr == ' ') {
187
        /** \li *ese, standard event status enable command */
188
        ieee488_status.EventStatusEnable = ascii2byte(bufferPtr+1);
189
        usb_tmc_state = TMC_STATE_IDLE;
190
        return 1;
191
      }
192
      else if(*bufferPtr == '?') {
193
        /** \li *ese?, standard event status enable query */
194
        *localqueuelength = byte2ascii(ieee488_status.EventStatusEnable,localqueue);
195
        IEEE488_set_mav();
196
        usb_tmc_state = TMC_STATE_IDLE;
197
        return 1;
198
      }
199
      else {
200
        return 0;
201
      }
202
    }
203
 
204
    if(!strncmp("esr?", bufferPtr, 4)) {
205
      /** \li *esr?, standard event status register query */
206
      queue->length = byte2ascii(ieee488_status.EventStatusRegister,queue->buf);
207
      IEEE488_set_mav();
208
      ieee488_status.EventStatusRegister = 0;
209
      usb_tmc_state = TMC_STATE_IDLE;
210
      return 1;
211
    }
212
 
213
    if(!strncmp("idn?", bufferPtr, 4)) {
214
      /** \li *idn?, identification query */
215
      string_index = descr2string((char*)queue->buf, \
216
                                  string_descriptors[(uint8_t)full_speed_device_descr[14]] \
217
                                  );
218
      *string_index = ',';
219
      string_index++;
220
      string_index = descr2string(string_index, \
221
                                  string_descriptors[(uint8_t)full_speed_device_descr[15]] \
222
                                  );
223
      *string_index = ',';
224
      string_index++;
225
      string_index = descr2string(string_index, \
226
                                  string_descriptors[(uint8_t)full_speed_device_descr[16]]\
227
                                  );
228
 
229
      strcat((char*)queue->buf, ",");
230
      strcat((char*)queue->buf, FIRMWARE_VERSION);
231
 
232
      queue->length = strlen((char*)queue->buf);
233
 
234
      usb_tmc_state = TMC_STATE_IDLE;
235
      IEEE488_set_mav();
236
      return 1;
237
    }
238
 
239
    if(!strncmp("opc", bufferPtr, 3)) {
240
      bufferPtr += 3;
241
      if(*bufferPtr == '?') {
242
        /** \li *opc?, operation complete query */
243
        queue->buf[0] = '1';
244
        queue->buf[1] = '\n';
245
        queue->length = 2;
246
        usb_tmc_state = TMC_STATE_IDLE;
247
        IEEE488_set_mav();
248
        return 1;
249
      }
250
      else {
251
        /** \li *opc, operation complete command */
252
        ieee488_status.OPC_Received = 1;
253
        usb_tmc_state = TMC_STATE_IDLE;
254
        return 1;
255
      }
256
    }
257
 
258
    if(!strncmp("rst", bufferPtr, 3)) {
259
      /** \li *rst, reset command. resets the FPGA and connected modules */
260
      s->action = SYSTEM_RESET;
261
      return 1;
262
    }
263
 
264
    if(!strncmp("sre", bufferPtr, 3)) {
265
      bufferPtr += 3;
266
      if(*bufferPtr == ' ') {
267
        /** \li *sre, service request enable command */
268
        ieee488_status.ServiceRequestEnable = ascii2byte(bufferPtr+1);
269
        usb_tmc_state = TMC_STATE_IDLE;
270
        return 1;
271
      }
272
      else if(*bufferPtr == '?') {
273
        /** \li *sre?, service request enable query */
274
        queue->length = byte2ascii(ieee488_status.ServiceRequestEnable,queue->buf);
275
        usb_tmc_state = TMC_STATE_IDLE;
276
        return 1;
277
      }
278
      else {
279
        return 0;
280
      }
281
    }
282
 
283
    if(!strncmp("stb?", bufferPtr, 4)) {
284
      /** \li *stb?, read status byte query */
285
      queue->length = byte2ascii(IEEE488_status_query(&ieee488_status),queue->buf);
286
      usb_tmc_state = TMC_STATE_IDLE;
287
      IEEE488_set_mav();
288
      return 1;
289
    }
290
 
291
    if(!strncmp("wai", bufferPtr, 3)) {
292
      /** \li *wai, wait-to-continue command */
293
      /* we excecute only sequential commands, so we are always finished */
294
      return 1;
295
    }
296
 
297
    else {
298
      return 0;
299
    }
300
  }
301
 
302
  /* -------------------------------------------------------------------- */
303
  /* this set of regular expressions are for the mandatory SCPI 99 commands.
304
   * many are missing because we have not enought memory
305
   */
306
  if(!strncmp("syst:", bufferPtr, 5)) {
307
    bufferPtr += 5;
308
 
309
    if(!strncmp("err?", bufferPtr, 4)) {
310
      /** \li syst:err?, gets an error message if there is one */
311
      if(ieee488_status.EventStatusRegister & bmCOMMAND_ERROR){
312
        strcpy((char*)queue->buf, "-100, \"Command error\"\n");
313
        queue->length = 22;
314
        ieee488_status.EventStatusRegister &= ~bmCOMMAND_ERROR;
315
      }
316
      else if(ieee488_status.EventStatusRegister & bmEXECUTION_ERROR){
317
        strcpy((char*)queue->buf, "-200, \"Execution error\"\n");
318
        queue->length = 24;
319
        ieee488_status.EventStatusRegister &= ~bmEXECUTION_ERROR;
320
      }
321
      else {
322
        strcpy((char*)queue->buf, "0, \"No error\"\n");
323
        queue->length = 14;
324
      }
325
      usb_tmc_state = TMC_STATE_IDLE;
326
      IEEE488_set_mav();
327
      return 1;
328
    }
329
 
330
    if(!strncmp("vers?", bufferPtr, 5)) {
331
      /** \li syst:vers?, returns the SCPI standard version number */
332
      strcpy((char*)queue->buf, SCPI_VERSION);
333
      queue->length = 7;
334
      usb_tmc_state = TMC_STATE_IDLE;
335
      IEEE488_set_mav();
336
      return 1;
337
    }
338
 
339
    else {
340
      return 0;
341
    }
342
  }
343
 
344
  /* -------------------------------------------------------------------- */
345
  /* this set of regular expressions are for the device functions */
346
  if(!strncmp("fpga:", bufferPtr, 5)) {
347
    bufferPtr += 5;
348
 
349
    if(!strncmp("conf ", bufferPtr, 5)) {
350
      /** \li fpga:conf, configures the fpga with the following bitfile */
351
      s->action = FPGA_CONFIGURE;
352
      *offset += 10;
353
      return 1;
354
    }
355
 
356
    if(!strncmp("type?", bufferPtr, 5)) {
357
      /** \li fpga:type?, returns the fpga type as string */
358
      s->action = rqFPGA_TYPE;
359
      *offset += 10;
360
      return 1;
361
    }
362
 
363
    if(!strncmp("id?", bufferPtr, 3)) {
364
      /** \li fpga:id?, returns the jtag id code of the fpga as 32bit int */
365
      s->action = rqFPGA_IDCODE;
366
      *offset += 8;
367
      return 1;
368
    }
369
 
370
    if(!strncmp("done?", bufferPtr, 5)) {
371
      /** \li fpga:done?, is true when the fpga is configured */
372
      s->action = rqFPGA_DONE;
373
      *offset += 10;
374
      return 1;
375
    }
376
 
377
    if(!strncmp("data", bufferPtr, 4)) {
378
      /** \li fpga:data, context switch to fpga. After this command you
379
       *      communicate directly with the fpga. The GECKO3COM firmware does
380
       *      not interprete the SCPI commands anymore. */
381
      s->action = FPGA_COMMUNICATION;
382
      *offset += 9;
383
      return 1;
384
    }
385
 
386
    else {
387
      return 0;
388
    }
389
  }
390
 
391
  if(!strncmp("mem:", bufferPtr, 4)) {
392
    bufferPtr += 4;
393
 
394
    if(!strncmp("data ", bufferPtr, 5)) {
395
      /** \li mem:data, receives a bitfile to store in SPI flash.
396
       * available memory slots are 0 and 1 */
397
      s->action = SPI_WRITE;
398
      *offset += 9;
399
 
400
      return 1;
401
    }
402
 
403
    if(!strncmp("del ", bufferPtr, 4)) {
404
      /** \li mem:del, DEPRICATED deletes the desired fpga configuration,
405
       * available memory slots are 0 and 1 */
406
      s->action = SPI_DELETE;
407
      *offset += 8;
408
 
409
      return 1;
410
    }
411
 
412
    else {
413
      return 0;
414
    }
415
  }
416
 
417
  /* matches all. when no command is parsed return an error */
418
 
419
  return 0;
420
}
421
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.