LCOV - code coverage report
Current view: top level - drivers/device - mscbhv4.cxx (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 221 0
Test Date: 2025-11-11 10:26:08 Functions: 0.0 % 6 0

            Line data    Source code
       1              : /********************************************************************\
       2              : 
       3              :   Name:         mscbhv4.c
       4              :   Created by:   Stefan Ritt
       5              : 
       6              :   Contents:     MSCB Mu3e 4-channel High Voltage Device Driver
       7              : 
       8              :   $Id: mscbhvr.c 2753 2005-10-07 14:55:31Z ritt $
       9              : 
      10              : \********************************************************************/
      11              : 
      12              : #include <stdio.h>
      13              : #include <math.h>
      14              : #include <stdarg.h>
      15              : #include <string.h>
      16              : #include <assert.h>
      17              : #include <stdlib.h>
      18              : #include "midas.h"
      19              : #include "mscb.h"
      20              : #include "mfe.h"
      21              : 
      22              : /*---- globals -----------------------------------------------------*/
      23              : 
      24              : typedef struct {
      25              :    char mscb_device[NAME_LENGTH];
      26              :    char pwd[NAME_LENGTH];
      27              :    BOOL debug;
      28              :    int  *address;
      29              :    int  channels;
      30              : } MSCBHV4_SETTINGS;
      31              : 
      32              : typedef struct {
      33              :    unsigned char control;
      34              :    float u_demand;
      35              :    float u_meas;
      36              :    unsigned char enabled;
      37              :    unsigned char on[4];
      38              :    float i_meas[4];
      39              :    bool cached;
      40              : } MSCB_NODE_VARS;
      41              : 
      42              : typedef struct {
      43              :    MSCBHV4_SETTINGS settings;
      44              :    int fd;
      45              :    MSCB_NODE_VARS *node_vars;
      46              : } MSCBHV4_INFO;
      47              : 
      48              : INT mscbhv4_read_all(MSCBHV4_INFO * info, int i);
      49              : 
      50              : /*---- device driver routines --------------------------------------*/
      51              : 
      52            0 : INT mscbhv4_init(HNDLE hkey, void **pinfo, INT channels, INT(*bd) (INT cmd, ...))
      53              : {
      54              :    int  status, size;
      55              :    HNDLE hDB;
      56              :    MSCBHV4_INFO *info;
      57              :    MSCB_INFO node_info;
      58              :    KEY key;
      59              : 
      60              :    /* allocate info structure */
      61            0 :    info = (MSCBHV4_INFO *) calloc(1, sizeof(MSCBHV4_INFO));
      62            0 :    info->node_vars = (MSCB_NODE_VARS *) calloc(channels, sizeof(MSCB_NODE_VARS));
      63            0 :    *pinfo = info;
      64              : 
      65            0 :    cm_get_experiment_database(&hDB, NULL);
      66              : 
      67              :    // retrieve device name
      68            0 :    db_get_key(hDB, hkey, &key);
      69              : 
      70              :    // create MSCBHV4 settings record
      71            0 :    size = sizeof(info->settings.mscb_device);
      72            0 :    info->settings.mscb_device[0] = 0;
      73            0 :    status = db_get_value(hDB, hkey, "MSCB Device", &info->settings.mscb_device, &size, TID_STRING, TRUE);
      74            0 :    if (status != DB_SUCCESS)
      75            0 :       return FE_ERR_ODB;
      76              : 
      77            0 :    size = sizeof(info->settings.pwd);
      78            0 :    info->settings.pwd[0] = 0;
      79            0 :    status = db_get_value(hDB, hkey, "MSCB Pwd", &info->settings.pwd, &size, TID_STRING, TRUE);
      80            0 :    if (status != DB_SUCCESS)
      81            0 :       return FE_ERR_ODB;
      82              : 
      83            0 :    info->settings.address = (int*)calloc(sizeof(INT), channels/4);
      84            0 :    assert(info->settings.address);
      85              : 
      86            0 :    int n_nodes = ((channels-1) / 4 + 1);
      87            0 :    size = n_nodes * sizeof(INT);
      88            0 :    status = db_get_value(hDB, hkey, "MSCB Address", info->settings.address, &size, TID_INT, FALSE);
      89            0 :    if (status != DB_SUCCESS)
      90            0 :       return FE_ERR_ODB;
      91              : 
      92              :    // open device on MSCB
      93            0 :    info->fd = mscb_init(info->settings.mscb_device, NAME_LENGTH, info->settings.pwd, info->settings.debug);
      94            0 :    if (info->fd < 0) {
      95            0 :       cm_msg(MERROR, "mscbhv4_init",
      96              :              "Cannot access MSCB submaster at \"%s\". Check power and connection.",
      97            0 :              info->settings.mscb_device);
      98            0 :       return FE_ERR_HW;
      99              :    }
     100              : 
     101              :    // check nodes
     102            0 :    for (int i=0 ; i<n_nodes ; i++) {
     103            0 :       status = mscb_info(info->fd, info->settings.address[i], &node_info);
     104            0 :       if (status != MSCB_SUCCESS) {
     105            0 :          cm_msg(MERROR, "mscbhv4_init",
     106              :                 "Cannot access HV4 node at address \"%d\". Please check cabling and power.",
     107            0 :                 info->settings.address[0]);
     108            0 :          return FE_ERR_HW;
     109              :       }
     110              : 
     111            0 :       if (strcmp(node_info.node_name, "HV+") != 0 &&
     112            0 :           strcmp(node_info.node_name, "HV-") != 0) {
     113            0 :          cm_msg(MERROR, "mscbhvr_init",
     114              :                 "Found unexpected node \"%s\" at address \"%d\".",
     115            0 :                 node_info.node_name, info->settings.address[i]);
     116            0 :          return FE_ERR_HW;
     117              :       }
     118              :    }
     119              : 
     120              :    // read all values from HV4 devices
     121            0 :    for (int i=0 ; i<channels ; i++) {
     122              : 
     123            0 :       if (i % 10 == 0)
     124            0 :          printf("%s: %d\r", key.name, i);
     125              : 
     126            0 :       status = mscbhv4_read_all(info, i);
     127            0 :       if (status != FE_SUCCESS)
     128            0 :          return status;
     129              :    }
     130            0 :    printf("%s: %d\n", key.name, channels);
     131              : 
     132            0 :    return FE_SUCCESS;
     133              : }
     134              : 
     135              : /*----------------------------------------------------------------------------*/
     136              : 
     137            0 : INT mscbhv4_read_all(MSCBHV4_INFO * info, int i)
     138              : {
     139              :    int size, status;
     140              :    unsigned char buffer[256], *pbuf;
     141              :    char str[256];
     142              : 
     143            0 :    if (i % 4 != 0)
     144            0 :       return FE_SUCCESS;
     145              : 
     146            0 :    size = sizeof(buffer);
     147            0 :    status = mscb_read_range(info->fd, info->settings.address[i/4], 0, 10, buffer, &size);
     148            0 :    if (status != MSCB_SUCCESS) {
     149            0 :       sprintf(str, "Error reading MSCB HV4 at \"%s:%d\".",
     150            0 :               info->settings.mscb_device, info->settings.address[i/4]);
     151            0 :       mfe_error(str);
     152            0 :       return FE_ERR_HW;
     153              :    }
     154              : 
     155              :    // decode variables from buffer
     156            0 :    pbuf = buffer;
     157            0 :    DWORD_SWAP(pbuf);
     158            0 :    info->node_vars[i].u_demand = *((float *)pbuf);
     159            0 :    pbuf += sizeof(float);
     160            0 :    DWORD_SWAP(pbuf);
     161            0 :    info->node_vars[i].u_meas = *((float *)pbuf);
     162            0 :    pbuf += sizeof(float);
     163            0 :    info->node_vars[i].enabled = *((unsigned char *)pbuf);
     164            0 :    pbuf += sizeof(char);
     165            0 :    info->node_vars[i].on[0] = *((unsigned char *)pbuf);
     166            0 :    pbuf += sizeof(char);
     167            0 :    info->node_vars[i].on[1] = *((unsigned char *)pbuf);
     168            0 :    pbuf += sizeof(char);
     169            0 :    info->node_vars[i].on[2] = *((unsigned char *)pbuf);
     170            0 :    pbuf += sizeof(char);
     171            0 :    info->node_vars[i].on[3] = *((unsigned char *)pbuf);
     172            0 :    pbuf += sizeof(char);
     173            0 :    DWORD_SWAP(pbuf);
     174            0 :    info->node_vars[i].i_meas[0] = *((float *)pbuf);
     175            0 :    pbuf += sizeof(float);
     176            0 :    DWORD_SWAP(pbuf);
     177            0 :    info->node_vars[i].i_meas[1] = *((float *)pbuf);
     178            0 :    pbuf += sizeof(float);
     179            0 :    DWORD_SWAP(pbuf);
     180            0 :    info->node_vars[i].i_meas[2] = *((float *)pbuf);
     181            0 :    pbuf += sizeof(float);
     182            0 :    DWORD_SWAP(pbuf);
     183            0 :    info->node_vars[i].i_meas[3] = *((float *)pbuf);
     184            0 :    pbuf += sizeof(float);
     185              : 
     186              :    // mark voltage/current as valid in cache
     187            0 :    for (int j=i ; j<i+4 ; j++)
     188            0 :       info->node_vars[j].cached = 1;
     189              : 
     190            0 :    return FE_SUCCESS;
     191              : }
     192              : 
     193              : /*----------------------------------------------------------------------------*/
     194              : 
     195            0 : INT mscbhv4_exit(MSCBHV4_INFO * info)
     196              : {
     197            0 :    mscb_exit(info->fd);
     198              : 
     199            0 :    free(info);
     200              : 
     201            0 :    return FE_SUCCESS;
     202              : }
     203              : 
     204              : /*----------------------------------------------------------------------------*/
     205              : 
     206            0 : INT mscbhv4_set(MSCBHV4_INFO * info, INT channel, float value)
     207              : {
     208            0 :    int fc = channel / 4 * 4; // first channel of module
     209            0 :    int mc = channel % 4;     // channel in module
     210              : 
     211            0 :    if (value == 0) {
     212              :       // turn channel off
     213            0 :       unsigned char flag = 0;
     214            0 :       mscb_write(info->fd, info->settings.address[channel/4], 3+mc, &flag, 1);
     215            0 :       info->node_vars[channel].u_demand = 0;
     216            0 :       info->node_vars[fc].on[mc] = 0;
     217              :    } else {
     218              : 
     219            0 :       mscb_write(info->fd, info->settings.address[channel / 4], 0, &value, 4);
     220              : 
     221              :       // set demand value of all four channels, since unit only has one demand
     222            0 :       for (int i = fc; i < fc + 4; i++)
     223            0 :          if (info->node_vars[i].u_demand != 0)
     224            0 :             info->node_vars[i].u_demand = value;
     225              : 
     226            0 :       if (info->node_vars[fc].on[mc] == 0) {
     227              :          // turn channel on
     228            0 :          unsigned char flag = 1;
     229            0 :          mscb_write(info->fd, info->settings.address[channel/4], 3+mc, &flag, 1);
     230            0 :          info->node_vars[fc].on[mc] = 1;
     231              :       }
     232              :    }
     233              : 
     234            0 :    return FE_SUCCESS;
     235              : }
     236              : 
     237              : /*----------------------------------------------------------------------------*/
     238              : 
     239            0 : INT mscbhv4_get(MSCBHV4_INFO * info, INT channel, float *pvalue)
     240              : {
     241            0 :    int fc = channel / 4 * 4; // first channel of module
     242              : 
     243              :    // check if value was previously read by mscbhvr_read_all()
     244            0 :    if (info->node_vars[channel].cached) {
     245            0 :       if (info->node_vars[fc].on[channel % 4] == 0)
     246            0 :          *pvalue = 0;
     247              :       else
     248            0 :          *pvalue = info->node_vars[fc].u_meas;
     249            0 :       info->node_vars[channel].cached = 0;
     250            0 :       return FE_SUCCESS;
     251              :    }
     252              : 
     253            0 :    int status = mscbhv4_read_all(info, channel);
     254              : 
     255            0 :    if (info->node_vars[fc].on[channel % 4] == 0)
     256            0 :       *pvalue = 0;
     257              :    else
     258            0 :       *pvalue = info->node_vars[fc].u_meas;
     259            0 :    return status;
     260              : }
     261              : 
     262              : /*---- device driver entry point -----------------------------------*/
     263              : 
     264            0 : INT mscbhv4(INT cmd, ...)
     265              : {
     266              :    va_list argptr;
     267              :    HNDLE hKey;
     268              :    INT channel, status;
     269              :    float value, *pvalue;
     270              :    int *pivalue, i;
     271              :    INT(*bd)(INT,...);
     272              :    MSCBHV4_INFO *info;
     273              : 
     274            0 :    va_start(argptr, cmd);
     275            0 :    status = FE_SUCCESS;
     276              : 
     277            0 :    switch (cmd) {
     278            0 :       case CMD_INIT:
     279            0 :          hKey = va_arg(argptr, HNDLE);
     280            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     281            0 :          channel = va_arg(argptr, INT);
     282            0 :          bd = va_arg(argptr, INT(*)(INT,...));
     283            0 :          status = mscbhv4_init(hKey, (void**)info, channel, bd);
     284            0 :          break;
     285              : 
     286            0 :       case CMD_EXIT:
     287            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     288            0 :          status = mscbhv4_exit(info);
     289            0 :          break;
     290              : 
     291            0 :       case CMD_SET:
     292            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     293            0 :          channel = va_arg(argptr, INT);
     294            0 :          value = (float) va_arg(argptr, double);
     295            0 :          status = mscbhv4_set(info, channel, value);
     296            0 :          break;
     297              : 
     298            0 :       case CMD_GET:
     299            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     300            0 :          channel = va_arg(argptr, INT);
     301            0 :          pvalue = va_arg(argptr, float *);
     302            0 :          status = mscbhv4_get(info, channel, pvalue);
     303            0 :          break;
     304              : 
     305            0 :       case CMD_GET_DEMAND:
     306            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     307            0 :          channel = va_arg(argptr, INT);
     308            0 :          pvalue = va_arg(argptr, float *);
     309            0 :          i = channel / 4 * 4;
     310              : 
     311            0 :          if (info->node_vars[i].on[channel % 4] == 0)
     312            0 :             *pvalue = 0;
     313              :          else
     314            0 :             *pvalue = info->node_vars[i].u_demand;
     315            0 :          break;
     316              : 
     317            0 :       case CMD_GET_CURRENT:
     318            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     319            0 :          channel = va_arg(argptr, INT);
     320            0 :          pvalue = va_arg(argptr, float *);
     321            0 :          i = channel / 4 * 4;
     322            0 :          *pvalue = info->node_vars[i].i_meas[channel % 4];
     323            0 :          break;
     324              : 
     325            0 :       case CMD_GET_LABEL:
     326              :       case CMD_SET_LABEL:
     327            0 :          status = FE_SUCCESS;
     328            0 :          break;
     329              : 
     330            0 :       case CMD_GET_THRESHOLD:
     331            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     332            0 :          channel = va_arg(argptr, INT);
     333            0 :          pvalue = va_arg(argptr, float *);
     334            0 :          *pvalue = 0.01f;
     335            0 :          break;
     336              : 
     337            0 :       case CMD_GET_THRESHOLD_CURRENT:
     338            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     339            0 :          channel = va_arg(argptr, INT);
     340            0 :          pvalue = va_arg(argptr, float *);
     341            0 :          *pvalue = 0.05f;
     342            0 :          break;
     343              : 
     344            0 :       case CMD_GET_THRESHOLD_ZERO:
     345            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     346            0 :          channel = va_arg(argptr, INT);
     347            0 :          pvalue = va_arg(argptr, float *);
     348            0 :          *pvalue = 15;
     349            0 :          break;
     350              : 
     351            0 :       case CMD_GET_STATUS:
     352            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     353            0 :          channel = va_arg(argptr, INT);
     354            0 :          pivalue = va_arg(argptr, INT *);
     355            0 :          i = channel / 4 * 4;
     356            0 :          *pivalue = info->node_vars[i].enabled;
     357            0 :          break;
     358              : 
     359            0 :       case CMD_GET_VOLTAGE_LIMIT:
     360            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     361            0 :          channel = va_arg(argptr, INT);
     362            0 :          pvalue = va_arg(argptr, float *);
     363            0 :          *pvalue = 120;
     364            0 :          break;
     365              : 
     366            0 :       case CMD_GET_CURRENT_LIMIT:
     367            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     368            0 :          channel = va_arg(argptr, INT);
     369            0 :          pvalue = va_arg(argptr, float *);
     370            0 :          *pvalue = 1.25;
     371            0 :          break;
     372              : 
     373            0 :       case CMD_GET_RAMPDOWN:
     374              :       case CMD_GET_RAMPUP:
     375              :       case CMD_GET_TRIP_TIME:
     376              :       case CMD_GET_TRIP:
     377              :       case CMD_GET_TEMPERATURE:
     378            0 :          info = va_arg(argptr, MSCBHV4_INFO *);
     379            0 :          channel = va_arg(argptr, INT);
     380            0 :          pivalue = va_arg(argptr, INT *);
     381            0 :          *pivalue = 0; // not implemented for the moment...
     382            0 :          status = FE_SUCCESS;
     383            0 :          break;
     384              : 
     385            0 :       case CMD_SET_TRIP_TIME:
     386              :       case CMD_SET_VOLTAGE_LIMIT:
     387              :       case CMD_SET_CURRENT_LIMIT:
     388              :       case CMD_START:
     389              :       case CMD_STOP:
     390              :       case CMD_SET_RAMPUP:
     391              :       case CMD_SET_RAMPDOWN:
     392            0 :          break;
     393              : 
     394            0 :       default:
     395            0 :          cm_msg(MERROR, "mscbhv4 device driver", "Received unknown command %d", cmd);
     396            0 :          status = FE_ERR_DRIVER;
     397            0 :          break;
     398              :    }
     399              : 
     400            0 :    va_end(argptr);
     401              : 
     402            0 :    return status;
     403              : }
     404              : 
     405              : /*------------------------------------------------------------------*/
        

Generated by: LCOV version 2.0-1