https://github.com/j123b567/scpi-parser

Dependents:   scpi_sx127x scpi_sx127x_firstTest MLX90418_I2C_master

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ieee488.c Source File

ieee488.c

00001 /*-
00002  * Copyright (c) 2012-2013 Jan Breuer,
00003  *
00004  * All Rights Reserved
00005  * 
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are
00008  * met:
00009  * 1. Redistributions of source code must retain the above copyright notice,
00010  *    this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 
00015  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00016  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00018  * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
00019  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
00022  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00023  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00024  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00025  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 
00028 /**
00029  * @file   scpi_ieee488.c
00030  * @date   Thu Nov 15 10:58:45 UTC 2012
00031  * 
00032  * @brief  Implementation of IEEE488.2 commands and state model
00033  * 
00034  * 
00035  */
00036 
00037 #include "scpi/parser.h"
00038 #include "scpi/ieee488.h"
00039 #include "scpi/error.h"
00040 #include "scpi/constants.h"
00041 
00042 #include <stdio.h>
00043 
00044 /**
00045  * Update register value
00046  * @param context
00047  * @param name - register name
00048  */
00049 static void regUpdate(scpi_t * context, scpi_reg_name_t name) {
00050     SCPI_RegSet(context, name, SCPI_RegGet(context, name));
00051 }
00052 
00053 /**
00054  * Update STB register according to value and its mask register
00055  * @param context
00056  * @param val value of register
00057  * @param mask name of mask register (enable register)
00058  * @param stbBits bits to clear or set in STB
00059  */
00060 static void regUpdateSTB(scpi_t * context, scpi_reg_val_t val, scpi_reg_name_t mask, scpi_reg_val_t stbBits) {
00061     if (val & SCPI_RegGet(context, mask)) {
00062         SCPI_RegSetBits(context, SCPI_REG_STB, stbBits);
00063     } else {
00064         SCPI_RegClearBits(context, SCPI_REG_STB, stbBits);
00065     }
00066 }
00067 
00068 /**
00069  * Get register value
00070  * @param name - register name
00071  * @return register value
00072  */
00073 scpi_reg_val_t SCPI_RegGet(scpi_t * context, scpi_reg_name_t name) {
00074     if ((name < SCPI_REG_COUNT) && (context->registers != NULL)) {
00075         return context->registers[name];
00076     } else {
00077         return 0;
00078     }
00079 }
00080 
00081 /**
00082  * Wrapper function to control interface from context
00083  * @param context
00084  * @param ctrl number of controll message
00085  * @param value value of related register
00086  */
00087 static size_t writeControl(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val) {
00088     if (context && context->interface && context->interface->control) {
00089         return context->interface->control(context, ctrl, val);
00090     } else {
00091         return 0;
00092     }
00093 }
00094 
00095 /**
00096  * Set register value
00097  * @param name - register name
00098  * @param val - new value
00099  */
00100 void SCPI_RegSet(scpi_t * context, scpi_reg_name_t name, scpi_reg_val_t val) {
00101     scpi_bool_t srq = FALSE;
00102     scpi_reg_val_t mask;
00103     scpi_reg_val_t old_val;
00104 
00105     if ((name >= SCPI_REG_COUNT) || (context->registers == NULL)) {
00106         return;
00107     }
00108     
00109     /* store old register value */
00110     old_val = context->registers[name];
00111 
00112     /* set register value */
00113     context->registers[name] = val;
00114 
00115     /** @TODO: remove recutsion */
00116     switch (name) {
00117         case SCPI_REG_STB:
00118             mask = SCPI_RegGet(context, SCPI_REG_SRE);
00119             mask &= ~STB_SRQ;
00120             if (val & mask) {
00121                 val |= STB_SRQ;
00122                 /* avoid sending SRQ if nothing has changed */
00123                 if (old_val != val) {
00124                     srq = TRUE;
00125                 }
00126             } else {
00127                 val &= ~STB_SRQ;
00128             }
00129             break;
00130         case SCPI_REG_SRE:
00131             regUpdate(context, SCPI_REG_STB);
00132             break;
00133         case SCPI_REG_ESR:
00134             regUpdateSTB(context, val, SCPI_REG_ESE, STB_ESR);
00135             break;
00136         case SCPI_REG_ESE:
00137             regUpdate(context, SCPI_REG_ESR);
00138             break;
00139         case SCPI_REG_QUES:
00140             regUpdateSTB(context, val, SCPI_REG_QUESE, STB_QES);
00141             break;
00142         case SCPI_REG_QUESE:
00143             regUpdate(context, SCPI_REG_QUES);
00144             break;
00145         case SCPI_REG_OPER:
00146             regUpdateSTB(context, val, SCPI_REG_OPERE, STB_OPS);
00147             break;
00148         case SCPI_REG_OPERE:
00149             regUpdate(context, SCPI_REG_OPER);
00150             break;
00151             
00152             
00153         case SCPI_REG_COUNT:
00154             /* nothing to do */
00155             break;
00156     }
00157 
00158     /* set updated register value */
00159     context->registers[name] = val;
00160 
00161     if (srq) {
00162         writeControl(context, SCPI_CTRL_SRQ, SCPI_RegGet(context, SCPI_REG_STB));
00163     }
00164 }
00165 
00166 /**
00167  * Set register bits
00168  * @param name - register name
00169  * @param bits bit mask
00170  */
00171 void SCPI_RegSetBits(scpi_t * context, scpi_reg_name_t name, scpi_reg_val_t bits) {
00172     SCPI_RegSet(context, name, SCPI_RegGet(context, name) | bits);
00173 }
00174 
00175 /**
00176  * Clear register bits
00177  * @param name - register name
00178  * @param bits bit mask
00179  */
00180 void SCPI_RegClearBits(scpi_t * context, scpi_reg_name_t name, scpi_reg_val_t bits) {
00181     SCPI_RegSet(context, name, SCPI_RegGet(context, name) & ~bits);
00182 }
00183 
00184 /**
00185  * Clear event register
00186  * @param context
00187  */
00188 void SCPI_EventClear(scpi_t * context) {
00189     /* TODO */
00190     SCPI_RegSet(context, SCPI_REG_ESR, 0);
00191 }
00192 
00193 /**
00194  * *CLS - This command clears all status data structures in a device. 
00195  *        For a device which minimally complies with SCPI. (SCPI std 4.1.3.2)
00196  * @param context
00197  * @return 
00198  */
00199 scpi_result_t SCPI_CoreCls(scpi_t * context) {
00200     SCPI_EventClear(context);
00201     SCPI_ErrorClear(context);
00202     SCPI_RegSet(context, SCPI_REG_OPER, 0);
00203     SCPI_RegSet(context, SCPI_REG_QUES, 0);
00204     return SCPI_RES_OK;
00205 }
00206 
00207 /**
00208  * *ESE
00209  * @param context
00210  * @return 
00211  */
00212 scpi_result_t SCPI_CoreEse(scpi_t * context) {
00213     int32_t new_ESE;
00214     if (SCPI_ParamInt(context, &new_ESE, TRUE)) {
00215         SCPI_RegSet(context, SCPI_REG_ESE, (scpi_reg_val_t)new_ESE);
00216     }
00217     return SCPI_RES_OK;
00218 }
00219 
00220 /**
00221  * *ESE?
00222  * @param context
00223  * @return 
00224  */
00225 scpi_result_t SCPI_CoreEseQ(scpi_t * context) {
00226     SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_ESE));
00227     return SCPI_RES_OK;
00228 }
00229 
00230 /**
00231  * *ESR?
00232  * @param context
00233  * @return 
00234  */
00235 scpi_result_t SCPI_CoreEsrQ(scpi_t * context) {
00236     SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_ESR));
00237     SCPI_RegSet(context, SCPI_REG_ESR, 0);
00238     return SCPI_RES_OK;
00239 }
00240 
00241 /**
00242  * *IDN?
00243  * 
00244  * field1: MANUFACTURE
00245  * field2: MODEL
00246  * field4: SUBSYSTEMS REVISIONS
00247  * 
00248  * example: MANUFACTURE,MODEL,0,01-02-01
00249  * @param context
00250  * @return 
00251  */
00252 scpi_result_t SCPI_CoreIdnQ(scpi_t * context) {
00253     int i;
00254     for (i = 0; i<4; i++) {
00255         if (context->idn[i]) {
00256             SCPI_ResultMnemonic(context, context->idn[i]);
00257         } else {
00258             SCPI_ResultMnemonic(context, "0");
00259         }
00260     }
00261     return SCPI_RES_OK;
00262 }
00263 
00264 /**
00265  * *OPC
00266  * @param context
00267  * @return 
00268  */
00269 scpi_result_t SCPI_CoreOpc(scpi_t * context) {
00270     SCPI_RegSetBits(context, SCPI_REG_ESR, ESR_OPC);
00271     return SCPI_RES_OK;
00272 }
00273 
00274 /**
00275  * *OPC?
00276  * @param context
00277  * @return 
00278  */
00279 scpi_result_t SCPI_CoreOpcQ(scpi_t * context) {
00280     /* Operation is always completed */
00281     SCPI_ResultInt(context, 1);
00282     return SCPI_RES_OK;
00283 }
00284 
00285 /**
00286  * *RST
00287  * @param context
00288  * @return 
00289  */
00290 scpi_result_t SCPI_CoreRst(scpi_t * context) {
00291     if (context && context->interface && context->interface->reset) {
00292         return context->interface->reset(context);
00293     }
00294     return SCPI_RES_OK;
00295 }
00296 
00297 /**
00298  * *SRE
00299  * @param context
00300  * @return 
00301  */
00302 scpi_result_t SCPI_CoreSre(scpi_t * context) {
00303     int32_t new_SRE;
00304     if (SCPI_ParamInt(context, &new_SRE, TRUE)) {
00305         SCPI_RegSet(context, SCPI_REG_SRE, (scpi_reg_val_t)new_SRE);
00306     }
00307     return SCPI_RES_OK;
00308 }
00309 
00310 /**
00311  * *SRE?
00312  * @param context
00313  * @return 
00314  */
00315 scpi_result_t SCPI_CoreSreQ(scpi_t * context) {
00316     SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_SRE));
00317     return SCPI_RES_OK;
00318 }
00319 
00320 /**
00321  * *STB?
00322  * @param context
00323  * @return 
00324  */
00325 scpi_result_t SCPI_CoreStbQ(scpi_t * context) {
00326     SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_STB));
00327     return SCPI_RES_OK;
00328 }
00329 
00330 /**
00331  * *TST?
00332  * @param context
00333  * @return 
00334  */
00335 scpi_result_t SCPI_CoreTstQ(scpi_t * context) {
00336     (void) context;
00337     SCPI_ResultInt(context, 0);
00338     return SCPI_RES_OK;
00339 }
00340 
00341 /**
00342  * *WAI
00343  * @param context
00344  * @return 
00345  */
00346 scpi_result_t SCPI_CoreWai(scpi_t * context) {
00347     (void) context;
00348     /* NOP */
00349     return SCPI_RES_OK;
00350 }