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

            Line data    Source code
       1              : /********************************************************************\
       2              : 
       3              :   Name:         hv.c
       4              :   Created by:   Stefan Ritt
       5              : 
       6              :   Contents:     High Voltage Class Driver
       7              : 
       8              :   $Id: hv.c 5126 2011-07-07 12:32:53Z ritt $
       9              : 
      10              : \********************************************************************/
      11              : 
      12              : #include <stdio.h>
      13              : #include <math.h>
      14              : #include <assert.h>
      15              : #include <stdlib.h>
      16              : #include <string.h>
      17              : #include "midas.h"
      18              : #include "mstrlcpy.h"
      19              : 
      20              : // minimal ramping increment to reduce calls to (potential slow) SET function
      21              : #define HV_MIN_RAMP_STEP 0.05
      22              : 
      23              : typedef struct {
      24              : 
      25              :    /* ODB keys */
      26              :    HNDLE hKeyRoot, hKeyDemand, hKeyMeasured, hKeyCurrent, hKeyChStatus, hKeyTemperature;
      27              : 
      28              :    /* globals */
      29              :    INT num_channels;
      30              :    INT format;
      31              :    DWORD last_update;
      32              :    INT last_channel;
      33              :    INT last_channel_updated;
      34              : 
      35              :    /* items in /Variables record */
      36              :    char *names;
      37              :    float *demand;
      38              :    float *measured;
      39              :    float *current;
      40              :    DWORD *chStatus;
      41              :    float *temperature;
      42              : 
      43              :    /* items in /Settings */
      44              :    float *update_threshold;
      45              :    float *update_threshold_current;
      46              :    float *zero_threshold;
      47              :    float *voltage_limit;
      48              :    float *current_limit;
      49              :    float *rampup_speed;
      50              :    float *rampdown_speed;
      51              :    float *trip_time;
      52              :    DWORD *chState;
      53              :    INT   *crateMap;
      54              : 
      55              :    /* mirror arrays */
      56              :    float *demand_mirror;
      57              :    float *measured_mirror;
      58              :    float *current_mirror;
      59              :    DWORD *chStatus_mirror;
      60              :    float *temperature_mirror;
      61              :    DWORD *last_change;
      62              : 
      63              :    DEVICE_DRIVER **driver;
      64              :    INT *channel_offset;
      65              :    void **dd_info;
      66              : 
      67              : } HV_INFO;
      68              : 
      69              : #ifndef ABS
      70              : #define ABS(a) (((a) < 0)   ? -(a) : (a))
      71              : #endif
      72              : 
      73              : /*------------------------------------------------------------------*/
      74              : 
      75            0 : static void free_mem(HV_INFO * hv_info)
      76              : {
      77            0 :    free(hv_info->names);
      78            0 :    free(hv_info->demand);
      79            0 :    free(hv_info->measured);
      80            0 :    free(hv_info->current);
      81            0 :    free(hv_info->chStatus);
      82            0 :    free(hv_info->temperature);
      83              : 
      84            0 :    free(hv_info->update_threshold);
      85            0 :    free(hv_info->update_threshold_current);
      86            0 :    free(hv_info->zero_threshold);
      87            0 :    free(hv_info->voltage_limit);
      88            0 :    free(hv_info->current_limit);
      89            0 :    free(hv_info->rampup_speed);
      90            0 :    free(hv_info->rampdown_speed);
      91            0 :    free(hv_info->trip_time);
      92            0 :    free(hv_info->chState);
      93            0 :    free(hv_info->crateMap);
      94              : 
      95            0 :    free(hv_info->demand_mirror);
      96            0 :    free(hv_info->measured_mirror);
      97            0 :    free(hv_info->current_mirror);
      98            0 :    free(hv_info->chStatus_mirror);
      99            0 :    free(hv_info->temperature_mirror);
     100            0 :    free(hv_info->last_change);
     101              : 
     102            0 :    free(hv_info->dd_info);
     103            0 :    free(hv_info->channel_offset);
     104            0 :    free(hv_info->driver);
     105              : 
     106            0 :    free(hv_info);
     107            0 : }
     108              : 
     109              : /*----------------------------------------------------------------------------*/
     110              : 
     111            0 : INT hv_start(EQUIPMENT * pequipment)
     112              : {
     113              :    INT i;
     114              : 
     115              :    /* call start method of device drivers */
     116            0 :    for (i = 0; pequipment->driver[i].dd != NULL ; i++)
     117            0 :       if (pequipment->driver[i].flags & DF_MULTITHREAD) {
     118            0 :          pequipment->driver[i].pequipment = &pequipment->info;
     119            0 :          device_driver(&pequipment->driver[i], CMD_START);
     120              :       }
     121              : 
     122            0 :    return FE_SUCCESS;
     123              : }
     124              : 
     125              : /*----------------------------------------------------------------------------*/
     126              : 
     127            0 : INT hv_stop(EQUIPMENT * pequipment)
     128              : {
     129              :    INT i;
     130              : 
     131              :    /* call close method of device drivers */
     132            0 :    for (i = 0; pequipment->driver[i].dd != NULL ; i++)
     133            0 :       if (pequipment->driver[i].flags & DF_MULTITHREAD)
     134            0 :          device_driver(&pequipment->driver[i], CMD_CLOSE);
     135              : 
     136              :    /* call stop method of device drivers */
     137            0 :    for (i = 0; pequipment->driver[i].dd != NULL ; i++)
     138            0 :       if (pequipment->driver[i].flags & DF_MULTITHREAD)
     139            0 :          device_driver(&pequipment->driver[i], CMD_STOP);
     140              : 
     141            0 :    return FE_SUCCESS;
     142              : }
     143              : 
     144              : /*------------------------------------------------------------------*/
     145              : 
     146            0 : INT hv_read(EQUIPMENT * pequipment, int channel)
     147              : {
     148            0 :    int i, status = 0;
     149              :    float max_diff;
     150              :    DWORD act_time, min_time;
     151              :    BOOL changed;
     152              :    HV_INFO *hv_info;
     153              :    HNDLE hDB;
     154              : 
     155            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     156            0 :    cm_get_experiment_database(&hDB, NULL);
     157              : 
     158              :    /* if driver is multi-threaded, read all channels at once */
     159            0 :    for (i=0 ; i < hv_info->num_channels ; i++) {
     160            0 :       if (hv_info->driver[i]->flags & DF_MULTITHREAD) {
     161            0 :          status = device_driver(hv_info->driver[i], CMD_GET,
     162            0 :                                 i - hv_info->channel_offset[i],
     163            0 :                                 &hv_info->measured[i]);
     164            0 :          status = device_driver(hv_info->driver[i], CMD_GET_CURRENT,
     165            0 :                                 i - hv_info->channel_offset[i],
     166            0 :                                 &hv_info->current[i]);
     167            0 :          if (hv_info->driver[i]->flags & DF_REPORT_STATUS)
     168            0 :             status = device_driver(hv_info->driver[i], CMD_GET_STATUS,
     169            0 :                                    i - hv_info->channel_offset[i],
     170            0 :                                    &hv_info->chStatus[i]);
     171            0 :          if (hv_info->driver[i]->flags & DF_REPORT_TEMP)
     172            0 :             status = device_driver(hv_info->driver[i], CMD_GET_TEMPERATURE,
     173            0 :                                    i - hv_info->channel_offset[i],
     174            0 :                                    &hv_info->temperature[i]);
     175            0 :          if (hv_info->driver[i]->flags & DF_POLL_DEMAND)
     176            0 :             status = device_driver(hv_info->driver[i], CMD_GET_DEMAND,
     177            0 :                                    i - hv_info->channel_offset[i],
     178            0 :                                    &hv_info->demand[i]);
     179              :       }
     180              :    }
     181              : 
     182              :    /* else read only single channel */
     183            0 :    if (!(hv_info->driver[channel]->flags & DF_MULTITHREAD)) {
     184            0 :       status = device_driver(hv_info->driver[channel], CMD_GET,
     185            0 :                                  channel - hv_info->channel_offset[channel],
     186            0 :                                  &hv_info->measured[channel]);
     187            0 :       status = device_driver(hv_info->driver[channel], CMD_GET_CURRENT,
     188            0 :                                  channel - hv_info->channel_offset[channel],
     189            0 :                                  &hv_info->current[channel]);
     190            0 :       if (hv_info->driver[channel]->flags & DF_REPORT_STATUS)
     191            0 :          status = device_driver(hv_info->driver[channel], CMD_GET_STATUS,
     192            0 :                                     channel - hv_info->channel_offset[channel],
     193            0 :                                     &hv_info->chStatus[channel]);
     194            0 :       if (hv_info->driver[channel]->flags & DF_REPORT_TEMP)
     195            0 :          status = device_driver(hv_info->driver[channel], CMD_GET_TEMPERATURE,
     196            0 :                                     channel - hv_info->channel_offset[channel],
     197            0 :                                     &hv_info->temperature[channel]);
     198            0 :       if (hv_info->driver[channel]->flags & DF_POLL_DEMAND)
     199            0 :          status = device_driver(hv_info->driver[channel], CMD_GET_DEMAND,
     200            0 :                                 channel - hv_info->channel_offset[channel],
     201            0 :                                 &hv_info->demand[channel]);
     202              :    }
     203              : 
     204              :    // check how much channels have changed since last ODB update
     205            0 :    act_time = ss_millitime();
     206              : 
     207              :    // check for update measured
     208            0 :    max_diff = 0.f;
     209            0 :    min_time = 60000;
     210            0 :    changed = FALSE;
     211            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     212            0 :       if (ABS(hv_info->measured[i] - hv_info->measured_mirror[i]) > max_diff)
     213            0 :          max_diff = ABS(hv_info->measured[i] - hv_info->measured_mirror[i]);
     214              : 
     215              :       /* indicate change if variation more than the threshold */
     216            0 :       if (ABS(hv_info->measured[i] - hv_info->measured_mirror[i]) >
     217            0 :           hv_info->update_threshold[i] && (ABS(hv_info->measured[i]) > hv_info->zero_threshold[i]))
     218            0 :          changed = TRUE;
     219              : 
     220            0 :       if (!ss_isnan(hv_info->measured[i]) && ss_isnan(hv_info->measured_mirror[i]))
     221            0 :          changed = TRUE;
     222              : 
     223            0 :       if (act_time - hv_info->last_change[i] < min_time)
     224            0 :          min_time = act_time - hv_info->last_change[i];
     225              :    }
     226              : 
     227              :    /* update if change is more than update_sensitivity or less than 20 seconds ago
     228              :       or last update is older than a minute */
     229            0 :    if (changed || (min_time < 20000 && max_diff > 0) ||
     230            0 :        act_time - hv_info->last_update > 60000) {
     231            0 :       hv_info->last_update = act_time;
     232              : 
     233            0 :       for (i = 0; i < hv_info->num_channels; i++)
     234            0 :          hv_info->measured_mirror[i] = hv_info->measured[i];
     235              : 
     236            0 :       db_set_data(hDB, hv_info->hKeyMeasured, hv_info->measured,
     237            0 :                   sizeof(float) * hv_info->num_channels, hv_info->num_channels,
     238              :                   TID_FLOAT);
     239              : 
     240            0 :       pequipment->odb_out++;
     241              :    }
     242              : 
     243              :    // check for update current
     244            0 :    max_diff = 0.f;
     245            0 :    min_time = 10000;
     246            0 :    changed = FALSE;
     247            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     248            0 :       if (ABS(hv_info->current[i] - hv_info->current_mirror[i]) > max_diff)
     249            0 :          max_diff = ABS(hv_info->current[i] - hv_info->current_mirror[i]);
     250              : 
     251            0 :       if (ABS(hv_info->current[i] - hv_info->current_mirror[i]) >
     252            0 :           hv_info->update_threshold_current[i])
     253            0 :          changed = TRUE;
     254              : 
     255            0 :       if (act_time - hv_info->last_change[i] < min_time)
     256            0 :          min_time = act_time - hv_info->last_change[i];
     257              :    }
     258              : 
     259              :    // update if change is more than update_sensitivity or less than 5sec ago
     260            0 :    if (changed || (min_time < 5000 && max_diff > 0)) {
     261            0 :       for (i = 0; i < hv_info->num_channels; i++)
     262            0 :          hv_info->current_mirror[i] = hv_info->current[i];
     263              : 
     264            0 :       db_set_data(hDB, hv_info->hKeyCurrent, hv_info->current,
     265            0 :                   sizeof(float) * hv_info->num_channels, hv_info->num_channels,
     266              :                   TID_FLOAT);
     267              : 
     268            0 :       pequipment->odb_out++;
     269              :    }
     270              : 
     271              :    // check for update demand
     272            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     273            0 :       if (hv_info->driver[i]->flags & DF_POLL_DEMAND) {
     274            0 :          if (hv_info->demand[i] != hv_info->demand_mirror[i]) {
     275            0 :             db_set_data_index(hDB, hv_info->hKeyDemand, &hv_info->demand[i],
     276              :                               sizeof(float), i, TID_FLOAT);
     277            0 :             hv_info->demand_mirror[i] = hv_info->demand[i];
     278              :          }
     279              : 
     280            0 :          pequipment->odb_out++;
     281              :       }
     282              :    }
     283              : 
     284              :    // check for updated chStatus
     285            0 :    max_diff = 0.f;
     286            0 :    min_time = 60000;
     287            0 :    changed = FALSE;
     288            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     289            0 :       if (hv_info->driver[i]->flags & DF_REPORT_STATUS){
     290            0 :           if(hv_info->chStatus[i] != hv_info->chStatus_mirror[i])
     291            0 :             changed = TRUE;
     292              :                                  
     293            0 :          if (act_time - hv_info->last_change[i] < min_time)
     294            0 :             min_time = act_time - hv_info->last_change[i];
     295              :       }
     296              :    }
     297              :       
     298              :    // update if change is more than update_sensitivity or less than 20 seconds ago or last update is older than a minute
     299            0 :    if (changed || (min_time < 20000 && max_diff > 0) ||
     300            0 :        act_time - hv_info->last_update > 60000) {
     301            0 :       hv_info->last_update = act_time;
     302              :    
     303            0 :       for (i = 0; i < hv_info->num_channels; i++)
     304            0 :          hv_info->chStatus_mirror[i] = hv_info->chStatus[i];
     305              :    
     306            0 :       db_set_data(hDB, hv_info->hKeyChStatus, hv_info->chStatus,
     307            0 :                   sizeof(DWORD) * hv_info->num_channels, hv_info->num_channels,
     308              :                   TID_DWORD);
     309              :       
     310            0 :       pequipment->odb_out++;
     311              :    }
     312              : 
     313              :    // check for temperature update
     314            0 :    max_diff = 0.f;
     315            0 :    min_time = 60000;
     316            0 :    changed = FALSE;
     317            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     318            0 :       if (hv_info->driver[i]->flags & DF_REPORT_TEMP){
     319            0 :          if (ABS(hv_info->temperature[i] - hv_info->temperature_mirror[i]) > max_diff)
     320            0 :             max_diff = ABS(hv_info->temperature[i] - hv_info->temperature_mirror[i]);
     321              :    
     322              :          // indicate change if variation more than the threshold
     323            0 :          if(hv_info->temperature[i] != hv_info->temperature_mirror[i])
     324            0 :             changed = TRUE;
     325              :    
     326            0 :          if (act_time - hv_info->last_change[i] < min_time)
     327            0 :             min_time = act_time - hv_info->last_change[i];
     328              :       }
     329              :    }
     330              :                                  
     331              :    // update if change is more than update_sensitivity or less than 20 seconds ago or last update is older than a minute
     332            0 :    if (changed || (min_time < 20000 && max_diff > 0) ||
     333            0 :        act_time - hv_info->last_update > 60000) {
     334            0 :       hv_info->last_update = act_time;
     335              :       
     336            0 :       for (i = 0; i < hv_info->num_channels; i++)
     337            0 :          hv_info->temperature_mirror[i] = hv_info->temperature[i];
     338              :    
     339            0 :       db_set_data(hDB, hv_info->hKeyTemperature, hv_info->temperature,
     340            0 :                   sizeof(float) * hv_info->num_channels, hv_info->num_channels,
     341              :                   TID_FLOAT);
     342              :    
     343            0 :       pequipment->odb_out++;
     344              :    }
     345              : 
     346            0 :    return status;
     347              : }
     348              : 
     349              : /*------------------------------------------------------------------*/
     350              : 
     351            0 : INT hv_ramp(HV_INFO * hv_info)
     352              : {
     353            0 :    INT i, status = 0, switch_tag = FALSE;
     354            0 :    float delta, ramp_speed = 0;
     355              : 
     356            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     357              : 
     358            0 :       if (!ss_isnan(hv_info->demand[i]) &&
     359            0 :           (hv_info->demand[i] != hv_info->demand_mirror[i])) {
     360              : 
     361              :          /* check if to ramp up or down */
     362            0 :          if ((hv_info->demand[i] >= 0.f) && (hv_info->demand_mirror[i] > 0.f)) {
     363            0 :             switch_tag = FALSE;
     364            0 :             if (hv_info->demand[i] > hv_info->demand_mirror[i])
     365            0 :                ramp_speed = hv_info->rampup_speed[i];
     366              :             else
     367            0 :                ramp_speed = hv_info->rampdown_speed[i];
     368              :          }
     369            0 :          if ((hv_info->demand[i] >= 0.f) && (hv_info->demand_mirror[i] < 0.f)) {
     370            0 :             switch_tag = TRUE;
     371            0 :             ramp_speed = hv_info->rampdown_speed[i];
     372              :          }
     373            0 :          if ((hv_info->demand[i] < 0.f) && (hv_info->demand_mirror[i] > 0.f)) {
     374            0 :             switch_tag = TRUE;
     375            0 :             ramp_speed = hv_info->rampdown_speed[i];
     376              :          }
     377            0 :          if ((hv_info->demand[i] < 0.f) && (hv_info->demand_mirror[i] < 0.f)) {
     378            0 :             switch_tag = FALSE;
     379            0 :             if (hv_info->demand[i] > hv_info->demand_mirror[i])
     380            0 :                ramp_speed = hv_info->rampdown_speed[i];
     381              :             else
     382            0 :                ramp_speed = hv_info->rampup_speed[i];
     383              :          }
     384            0 :          if (hv_info->demand_mirror[i] == 0.f) {
     385            0 :             switch_tag = FALSE;
     386            0 :             ramp_speed = hv_info->rampup_speed[i];
     387              :          }
     388              : 
     389            0 :          if (ramp_speed == 0.f)
     390            0 :             if (switch_tag)
     391            0 :                hv_info->demand_mirror[i] = 0.f; /* go to zero */
     392              :             else
     393            0 :                hv_info->demand_mirror[i] = hv_info->demand[i];  /* step directly to the new high voltage */
     394              :          else {
     395            0 :             delta = (float) ((ss_millitime() -
     396            0 :                               hv_info->last_change[i]) / 1000.0 * ramp_speed);
     397            0 :             if (delta < HV_MIN_RAMP_STEP)
     398            0 :                return FE_SUCCESS;
     399              : 
     400            0 :             if (hv_info->demand[i] > hv_info->demand_mirror[i])
     401            0 :                hv_info->demand_mirror[i] =
     402            0 :                    MIN(hv_info->demand[i], hv_info->demand_mirror[i] + delta);
     403              :             else
     404            0 :                hv_info->demand_mirror[i] =
     405            0 :                    MAX(hv_info->demand[i], hv_info->demand_mirror[i] - delta);
     406              :          }
     407            0 :          status = device_driver(hv_info->driver[i], CMD_SET,
     408            0 :                                 i - hv_info->channel_offset[i], hv_info->demand_mirror[i]);
     409            0 :          hv_info->last_change[i] = ss_millitime();
     410              :       }
     411              :    }
     412              : 
     413            0 :    return status;
     414              : }
     415              : 
     416              : 
     417              : /*------------------------------------------------------------------*/
     418              : 
     419            0 : void hv_demand(INT hDB, INT hKey, void *info)
     420              : {
     421              :    INT i;
     422              :    HV_INFO *hv_info;
     423              :    EQUIPMENT *pequipment;
     424              : 
     425            0 :    pequipment = (EQUIPMENT *) info;
     426            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     427              : 
     428              :    /* check for voltage limit */
     429            0 :    for (i = 0; i < hv_info->num_channels; i++)
     430            0 :       if (fabs(hv_info->demand[i]) > fabs(hv_info->voltage_limit[i])) {
     431            0 :          hv_info->demand[i] = hv_info->voltage_limit[i];
     432              : 
     433              :          /* correct value in ODB */
     434            0 :          db_set_data_index(hDB, hv_info->hKeyDemand, &hv_info->demand[i],
     435              :                            sizeof(float), i, TID_FLOAT);
     436              :       }
     437              : 
     438              :    /* set individual channels only if demand value differs */
     439            0 :    for (i = 0; i < hv_info->num_channels; i++)
     440            0 :       if (hv_info->demand[i] != hv_info->demand_mirror[i])
     441            0 :          hv_info->last_change[i] = ss_millitime();
     442              : 
     443            0 :    pequipment->odb_in++;
     444              : 
     445            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     446              :       /* if device can do hardware ramping, just set value */   
     447            0 :       if (hv_info->driver[i]->flags & DF_HW_RAMP) {
     448            0 :          if (!ss_isnan(hv_info->demand[i]) &&
     449            0 :              (hv_info->demand[i] != hv_info->demand_mirror[i])) {
     450            0 :             device_driver(hv_info->driver[i], CMD_SET,
     451            0 :                           i - hv_info->channel_offset[i], hv_info->demand[i]);
     452            0 :             hv_info->last_change[i] = ss_millitime();
     453            0 :             hv_info->demand_mirror[i] = hv_info->demand[i];
     454              :          }
     455              :       }
     456              :    }
     457              : 
     458              :    /* execute one ramping for devices which have not hardware ramping */
     459            0 :    hv_ramp(hv_info);
     460            0 : }
     461              : 
     462              : /*------------------------------------------------------------------*/
     463              : 
     464            0 : void hv_set_trip_time(INT hDB, INT hKey, void *info)
     465              : {
     466              :    INT i;
     467              :    HV_INFO *hv_info;
     468              :    EQUIPMENT *pequipment;
     469              : 
     470            0 :    pequipment = (EQUIPMENT *) info;
     471            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     472              : 
     473              :    /* check for voltage limit */
     474            0 :    for (i = 0; i < hv_info->num_channels; i++)
     475            0 :       device_driver(hv_info->driver[i], CMD_SET_TRIP_TIME,
     476            0 :                     i - hv_info->channel_offset[i], hv_info->trip_time[i]);
     477              : 
     478            0 :    pequipment->odb_in++;
     479            0 : }
     480              : 
     481              : /*------------------------------------------------------------------*/
     482              : 
     483            0 : void hv_set_current_limit(INT hDB, INT hKey, void *info)
     484              : {
     485              :    INT i;
     486              :    HV_INFO *hv_info;
     487              :    EQUIPMENT *pequipment;
     488              : 
     489            0 :    pequipment = (EQUIPMENT *) info;
     490            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     491              : 
     492              :    /* check for voltage limit */
     493            0 :    for (i = 0; i < hv_info->num_channels; i++)
     494            0 :       device_driver(hv_info->driver[i], CMD_SET_CURRENT_LIMIT,
     495            0 :                     i - hv_info->channel_offset[i], hv_info->current_limit[i]);
     496              : 
     497            0 :    pequipment->odb_in++;
     498            0 : }
     499              : 
     500              : /*------------------------------------------------------------------*/
     501              : 
     502            0 : void hv_set_rampup(INT hDB, INT hKey, void *info)
     503              : {
     504              :    INT i;
     505              :    HV_INFO *hv_info;
     506              :    EQUIPMENT *pequipment;
     507              : 
     508            0 :    pequipment = (EQUIPMENT *) info;
     509            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     510              : 
     511              :    /* check for voltage limit */
     512            0 :    for (i = 0; i < hv_info->num_channels; i++)
     513            0 :       device_driver(hv_info->driver[i], CMD_SET_RAMPUP,
     514            0 :                     i - hv_info->channel_offset[i], hv_info->rampup_speed[i]);
     515              : 
     516            0 :    pequipment->odb_in++;
     517            0 : }
     518              : 
     519              : /*------------------------------------------------------------------*/
     520              : 
     521            0 : void hv_set_rampdown(INT hDB, INT hKey, void *info)
     522              : {
     523              :    INT i;
     524              :    HV_INFO *hv_info;
     525              :    EQUIPMENT *pequipment;
     526              : 
     527            0 :    pequipment = (EQUIPMENT *) info;
     528            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     529              : 
     530              :    /* check for voltage limit */
     531            0 :    for (i = 0; i < hv_info->num_channels; i++)
     532            0 :       device_driver(hv_info->driver[i], CMD_SET_RAMPDOWN,
     533            0 :                     i - hv_info->channel_offset[i], hv_info->rampdown_speed[i]);
     534              : 
     535            0 :    pequipment->odb_in++;
     536            0 : }
     537              : 
     538              : /*------------------------------------------------------------------*/
     539              : 
     540            0 : void hv_set_voltage_limit(INT hDB, INT hKey, void *info)
     541              : {
     542              :    INT i;
     543              :    HV_INFO *hv_info;
     544              :    EQUIPMENT *pequipment;
     545              : 
     546            0 :    pequipment = (EQUIPMENT *) info;
     547            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     548              : 
     549              :    /* check for voltage limit */
     550            0 :    for (i = 0; i < hv_info->num_channels; i++)
     551            0 :       device_driver(hv_info->driver[i], CMD_SET_VOLTAGE_LIMIT,
     552            0 :                     i - hv_info->channel_offset[i], hv_info->voltage_limit[i]);
     553              : 
     554            0 :    pequipment->odb_in++;
     555            0 : }
     556              : 
     557              : /*------------------------------------------------------------------*/
     558              : 
     559            0 : void hv_update_label(INT hDB, INT hKey, void *info)
     560              : {
     561              :    
     562              :    INT i;
     563              :    HV_INFO *hv_info;
     564              :    EQUIPMENT *pequipment;
     565              : 
     566            0 :    pequipment = (EQUIPMENT *) info;
     567            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     568              : 
     569              :    //update channel labels based on the midas channel names
     570            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     571            0 :      device_driver(hv_info->driver[i], CMD_SET_LABEL, i - hv_info->channel_offset[i], hv_info->names + NAME_LENGTH * i);
     572              :    }
     573            0 : }
     574              : 
     575              : /*------------------------------------------------------------------*/
     576              : 
     577            0 : void hv_set_chState(INT hDB, INT hKey, void *info)
     578              : {
     579              :    INT i;
     580              :    HV_INFO *hv_info;
     581              :    EQUIPMENT *pequipment;
     582              :    
     583            0 :    pequipment = (EQUIPMENT *) info;
     584            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     585              :    
     586            0 :    for (i = 0; i < hv_info->num_channels; i++){
     587            0 :      device_driver(hv_info->driver[i], CMD_SET_CHSTATE, i - hv_info->channel_offset[i], (double)hv_info->chState[i] );
     588              :    }
     589              :    
     590            0 :    pequipment->odb_in++;
     591            0 : }
     592              : 
     593              : /*------------------------------------------------------------------*/
     594              :    
     595            0 : void validate_odb_array(HNDLE hDB, HV_INFO *hv_info, const char *path, double default_value, int cmd, 
     596              :                         float *array, void (*callback)(INT,INT,void *) ,EQUIPMENT *pequipment)
     597              : {
     598              :    int i;
     599              :    HNDLE hKey;
     600              : 
     601            0 :    for (i = 0; i < hv_info->num_channels; i++)
     602            0 :       array[i] = (float)default_value;
     603            0 :    if (db_find_key(hDB, hv_info->hKeyRoot, path, &hKey) != DB_SUCCESS)
     604            0 :       for (i = 0; i < hv_info->num_channels; i++)
     605            0 :          device_driver(hv_info->driver[i], cmd,
     606            0 :                        i - hv_info->channel_offset[i], array + i);
     607            0 :    db_merge_data(hDB, hv_info->hKeyRoot, path, array, sizeof(float) * hv_info->num_channels,
     608              :                  hv_info->num_channels, TID_FLOAT);
     609            0 :    db_find_key(hDB, hv_info->hKeyRoot, path, &hKey);
     610            0 :    assert(hKey);
     611            0 :    db_open_record(hDB, hKey, array, sizeof(float) * hv_info->num_channels, MODE_READ, 
     612              :                   callback, pequipment);
     613            0 : }
     614              : 
     615            0 : void validate_odb_array_bool(HNDLE hDB, HV_INFO *hv_info, const char *path, double default_value, int cmd,
     616              :                         DWORD *array, void (*callback)(INT,INT,void *) ,EQUIPMENT *pequipment)
     617              : {
     618              :    int i;
     619              :    HNDLE hKey;
     620              :    
     621            0 :    for (i = 0; i < hv_info->num_channels; i++)
     622            0 :       array[i] = (DWORD)default_value;
     623            0 :    if (db_find_key(hDB, hv_info->hKeyRoot, path, &hKey) != DB_SUCCESS)
     624            0 :       for (i = 0; i < hv_info->num_channels; i++){
     625            0 :          device_driver(hv_info->driver[i], cmd, i - hv_info->channel_offset[i], array + i);
     626            0 :          array[i] = 0;
     627              :       }
     628            0 :    db_merge_data(hDB, hv_info->hKeyRoot, path, array, sizeof(DWORD) * hv_info->num_channels, hv_info->num_channels, TID_DWORD);
     629            0 :    db_find_key(hDB, hv_info->hKeyRoot, path, &hKey);
     630            0 :    assert(hKey);
     631            0 :    db_open_record(hDB, hKey, array, sizeof(DWORD) * hv_info->num_channels, MODE_READ,
     632              :                   callback, pequipment);
     633            0 : }
     634              : 
     635            0 : void validate_odb_int(HNDLE hDB, HV_INFO *hv_info, const char *path, double default_value, int cmd,
     636              :                         int *target, void (*callback)(INT,INT,void *) ,EQUIPMENT *pequipment)
     637              : {
     638              :    int i;
     639              :    HNDLE hKey;
     640              : 
     641            0 :    for (i = 0; i < 1; i++)
     642            0 :       target[i] = (INT)default_value;
     643            0 :    if (db_find_key(hDB, hv_info->hKeyRoot, path, &hKey) != DB_SUCCESS)
     644            0 :       for (i = 0; i < 1; i++){
     645            0 :          device_driver(hv_info->driver[i], cmd, i - hv_info->channel_offset[i], target + i);
     646              :       }
     647            0 :    db_merge_data(hDB, hv_info->hKeyRoot, path, target, sizeof(INT), 1, TID_INT);
     648            0 :    db_find_key(hDB, hv_info->hKeyRoot, path, &hKey);
     649            0 :    assert(hKey);
     650            0 :    db_open_record(hDB, hKey, target, sizeof(INT), MODE_READ,callback, pequipment);
     651            0 : }
     652              : 
     653              : /*------------------------------------------------------------------*/
     654              : 
     655            0 : INT hv_init(EQUIPMENT * pequipment)
     656              : {
     657              :    int status, size, i, j, index, offset;
     658              :    char str[256];
     659              :    HNDLE hDB, hKey;
     660              :    HV_INFO *hv_info;
     661              :    BOOL partially_disabled;
     662              : 
     663              :    /* allocate private data */
     664            0 :    pequipment->cd_info = calloc(1, sizeof(HV_INFO));
     665            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
     666              : 
     667              :    /* get class driver root key */
     668            0 :    cm_get_experiment_database(&hDB, NULL);
     669            0 :    sprintf(str, "/Equipment/%s", pequipment->name);
     670            0 :    db_create_key(hDB, 0, str, TID_KEY);
     671            0 :    db_find_key(hDB, 0, str, &hv_info->hKeyRoot);
     672              : 
     673              :    /* save event format */
     674            0 :    size = sizeof(str);
     675            0 :    db_get_value(hDB, hv_info->hKeyRoot, "Common/Format", str, &size, TID_STRING, TRUE);
     676              : 
     677            0 :    if (equal_ustring(str, "Fixed"))
     678            0 :       hv_info->format = FORMAT_FIXED;
     679            0 :    else if (equal_ustring(str, "MIDAS"))
     680            0 :       hv_info->format = FORMAT_MIDAS;
     681              :    else {
     682            0 :       hv_info->format = 0;
     683            0 :       cm_msg(MERROR, "hv_init", "Unknown Common/Format \"%s\", should be FIXED or MIDAS", str);
     684            0 :       return FE_ERR_ODB;
     685              :    }
     686              : 
     687              :    /* count total number of channels */
     688            0 :    for (i = 0, hv_info->num_channels = 0; pequipment->driver[i].name[0]; i++) {
     689            0 :       if (pequipment->driver[i].channels == 0) {
     690            0 :          cm_msg(MERROR, "hv_init", "Driver with zero channels not allowed");
     691            0 :          return FE_ERR_ODB;
     692              :       }
     693              : 
     694            0 :       hv_info->num_channels += pequipment->driver[i].channels;
     695              :    }
     696              : 
     697            0 :    if (hv_info->num_channels == 0) {
     698            0 :       cm_msg(MERROR, "hv_init", "No channels found in device driver list");
     699            0 :       return FE_ERR_ODB;
     700              :    }
     701              : 
     702              :    /* Allocate memory for buffers */
     703            0 :    hv_info->names = (char *) calloc(hv_info->num_channels, NAME_LENGTH);
     704              : 
     705            0 :    hv_info->demand = (float *) calloc(hv_info->num_channels, sizeof(float));
     706            0 :    hv_info->measured = (float *) calloc(hv_info->num_channels, sizeof(float));
     707            0 :    hv_info->current = (float *) calloc(hv_info->num_channels, sizeof(float));
     708            0 :    hv_info->chStatus = (DWORD *) calloc(hv_info->num_channels, sizeof(DWORD));
     709            0 :    hv_info->temperature = (float *) calloc(hv_info->num_channels, sizeof(float));
     710              : 
     711            0 :    hv_info->update_threshold = (float *) calloc(hv_info->num_channels, sizeof(float));
     712            0 :    hv_info->update_threshold_current = (float *) calloc(hv_info->num_channels, sizeof(float));
     713            0 :    hv_info->zero_threshold = (float *) calloc(hv_info->num_channels, sizeof(float));
     714            0 :    hv_info->voltage_limit = (float *) calloc(hv_info->num_channels, sizeof(float));
     715            0 :    hv_info->current_limit = (float *) calloc(hv_info->num_channels, sizeof(float));
     716            0 :    hv_info->rampup_speed = (float *) calloc(hv_info->num_channels, sizeof(float));
     717            0 :    hv_info->rampdown_speed = (float *) calloc(hv_info->num_channels, sizeof(float));
     718            0 :    hv_info->trip_time = (float *) calloc(hv_info->num_channels, sizeof(float));
     719            0 :    hv_info->chState = (DWORD *) calloc(hv_info->num_channels, sizeof(DWORD));
     720            0 :    hv_info->crateMap = (INT *) calloc(hv_info->num_channels, sizeof(INT));
     721              : 
     722            0 :    hv_info->demand_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
     723            0 :    hv_info->measured_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
     724            0 :    hv_info->current_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
     725            0 :    hv_info->chStatus_mirror = (DWORD *) calloc(hv_info->num_channels, sizeof(DWORD));
     726            0 :    hv_info->temperature_mirror = (float *) calloc(hv_info->num_channels, sizeof(float));
     727            0 :    hv_info->last_change = (DWORD *) calloc(hv_info->num_channels, sizeof(DWORD));
     728              : 
     729            0 :    hv_info->dd_info = (void **) calloc(hv_info->num_channels, sizeof(void *));
     730            0 :    hv_info->channel_offset = (INT *) calloc(hv_info->num_channels, sizeof(INT));
     731            0 :    hv_info->driver = (DEVICE_DRIVER **) calloc(hv_info->num_channels, sizeof(void *));
     732              : 
     733            0 :    if (!hv_info->driver) {
     734            0 :       cm_msg(MERROR, "hv_init", "Not enough memory");
     735            0 :       return FE_ERR_ODB;
     736              :    }
     737              : 
     738              :    /*---- Initialize device drivers ----*/
     739              : 
     740              :    /* call init method */
     741            0 :    partially_disabled = FALSE;
     742            0 :    for (i = 0; pequipment->driver[i].name[0]; i++) {
     743            0 :       sprintf(str, "Settings/Devices/%s", pequipment->driver[i].name);
     744            0 :       status = db_find_key(hDB, hv_info->hKeyRoot, str, &hKey);
     745            0 :       if (status != DB_SUCCESS) {
     746            0 :          db_create_key(hDB, hv_info->hKeyRoot, str, TID_KEY);
     747            0 :          status = db_find_key(hDB, hv_info->hKeyRoot, str, &hKey);
     748            0 :          if (status != DB_SUCCESS) {
     749            0 :             cm_msg(MERROR, "hv_init", "Cannot create %s entry in online database", str);
     750            0 :             free_mem(hv_info);
     751            0 :             return FE_ERR_ODB;
     752              :          }
     753              :       }
     754              : 
     755              :       /* check enabled flag */
     756            0 :       size = sizeof(pequipment->driver[i].enabled);
     757            0 :       pequipment->driver[i].enabled = 1;
     758            0 :       sprintf(str, "Settings/Devices/%s/Enabled", pequipment->driver[i].name);
     759            0 :       status = db_get_value(hDB, hv_info->hKeyRoot, str, &pequipment->driver[i].enabled, &size, TID_BOOL, TRUE);
     760            0 :       if (status != DB_SUCCESS)
     761            0 :          return FE_ERR_ODB;
     762              :       
     763            0 :       if (pequipment->driver[i].enabled) {
     764            0 :          printf("Connecting %s...", pequipment->driver[i].name);
     765            0 :          fflush(stdout);
     766            0 :          status = device_driver(&pequipment->driver[i], CMD_INIT, hKey);
     767            0 :          if (status != FE_SUCCESS) {
     768            0 :             free_mem(hv_info);
     769            0 :             return status;
     770              :          }
     771            0 :          printf("OK\n");
     772              :       } else
     773            0 :          partially_disabled = TRUE;
     774              :    }
     775              : 
     776              :    /* compose device driver channel assignment */
     777            0 :    for (i = 0, j = 0, index = 0, offset = 0; i < hv_info->num_channels; i++, j++) {
     778            0 :       while (j >= pequipment->driver[index].channels && pequipment->driver[index].name[0]) {
     779            0 :          offset += j;
     780            0 :          index++;
     781            0 :          j = 0;
     782              :       }
     783              : 
     784            0 :       hv_info->driver[i] = &pequipment->driver[index];
     785            0 :       hv_info->channel_offset[i] = offset;
     786              :    }
     787              : 
     788              :    /*---- Create/Read settings ----*/
     789              :    
     790            0 :    db_create_key(hDB, hv_info->hKeyRoot, "Settings/Editable", TID_STRING);
     791            0 :    status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Editable", &hKey);
     792            0 :    if (status == DB_SUCCESS) {
     793            0 :       const int kSize = 10;
     794              :       char editable[kSize][NAME_LENGTH];
     795              :       int count;
     796            0 :       for (i = 0; i < kSize; i++)
     797            0 :          editable[i][0] = 0;
     798            0 :       count = 0;
     799            0 :       strcpy(editable[count++], "Demand");
     800            0 :       if (hv_info->driver[0]->flags & DF_REPORT_CHSTATE)
     801            0 :          strcpy(editable[count++], "ChState");
     802            0 :       db_set_data(hDB, hKey, editable, count * NAME_LENGTH, count, TID_STRING);
     803              :    }
     804              : 
     805              :    // Names
     806            0 :    for (i = 0; i < hv_info->num_channels; i++){
     807            0 :       if((hv_info->driver[i]->flags & DF_LABELS_FROM_DEVICE) == 0)
     808            0 :          sprintf(hv_info->names + NAME_LENGTH * i, "Default%%CH %d", i);
     809              :    }
     810              : 
     811            0 :    if (db_find_key(hDB, hv_info->hKeyRoot, "Settings/Names", &hKey) != DB_SUCCESS)
     812            0 :       for (i = 0; i < hv_info->num_channels; i++)
     813            0 :             device_driver(hv_info->driver[i], CMD_GET_LABEL, i - hv_info->channel_offset[i], hv_info->names + NAME_LENGTH * i);
     814              : 
     815            0 :    db_merge_data(hDB, hv_info->hKeyRoot, "Settings/Names", hv_info->names, NAME_LENGTH * hv_info->num_channels, hv_info->num_channels, TID_STRING);
     816            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Settings/Names", &hKey);
     817            0 :    assert(hKey);
     818            0 :    db_open_record(hDB, hKey, hv_info->names, NAME_LENGTH * hv_info->num_channels, MODE_READ, NULL, pequipment);
     819              : 
     820              :    /* Unit */
     821            0 :    status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Demand", &hKey);
     822            0 :    if (status == DB_NO_KEY) {
     823            0 :       int n = hv_info->num_channels;
     824            0 :       char *unit = (char *)calloc(n, 32);
     825            0 :       for (int ii=0 ; ii<n ; ii++)
     826            0 :          mstrlcpy(unit + ii*32, "V", 32);
     827            0 :       db_create_key(hDB, hv_info->hKeyRoot, "Settings/Unit Demand", TID_STRING);
     828            0 :       db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Demand", &hKey);
     829            0 :       db_set_data(hDB, hKey, unit, n*32, n, TID_STRING);
     830            0 :       free(unit);
     831              :    }
     832            0 :    status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Measured", &hKey);
     833            0 :    if (status == DB_NO_KEY) {
     834            0 :       int n = hv_info->num_channels;
     835            0 :       char *unit = (char *)calloc(n, 32);
     836            0 :       for (int ii=0 ; ii<n ; ii++)
     837            0 :          mstrlcpy(unit + ii*32, "V", 32);
     838            0 :       db_create_key(hDB, hv_info->hKeyRoot, "Settings/Unit Measured", TID_STRING);
     839            0 :       db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Measured", &hKey);
     840            0 :       db_set_data(hDB, hKey, unit, n*32, n, TID_STRING);
     841            0 :       free(unit);
     842              :    }
     843            0 :    status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Current", &hKey);
     844            0 :    if (status == DB_NO_KEY) {
     845            0 :       int n = hv_info->num_channels;
     846            0 :       char *unit = (char *)calloc(n, 32);
     847            0 :       for (int ii=0 ; ii<n ; ii++)
     848            0 :          mstrlcpy(unit + ii*32, "uA", 32);
     849            0 :       db_create_key(hDB, hv_info->hKeyRoot, "Settings/Unit Current", TID_STRING);
     850            0 :       db_find_key(hDB, hv_info->hKeyRoot, "Settings/Unit Current", &hKey);
     851            0 :       db_set_data(hDB, hKey, unit, n*32, n, TID_STRING);
     852            0 :       free(unit);
     853              :    }
     854              : 
     855              :    /* Format */
     856            0 :    status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Demand", &hKey);
     857            0 :    if (status == DB_NO_KEY) {
     858            0 :       int n = hv_info->num_channels;
     859            0 :       char *format = (char *)calloc(n, 32);
     860            0 :       for (int ii=0 ; ii<n ; ii++)
     861            0 :          mstrlcpy(format + ii*32, "%f2", 32);
     862            0 :       db_create_key(hDB, hv_info->hKeyRoot, "Settings/Format Demand", TID_STRING);
     863            0 :       db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Demand", &hKey);
     864            0 :       db_set_data(hDB, hKey, format, n*32, n, TID_STRING);
     865            0 :       free(format);
     866              :    }
     867            0 :    status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Measured", &hKey);
     868            0 :    if (status == DB_NO_KEY) {
     869            0 :       int n = hv_info->num_channels;
     870            0 :       char *format = (char *)calloc(n, 32);
     871            0 :       for (int ii=0 ; ii<n ; ii++)
     872            0 :          mstrlcpy(format + ii*32, "%f2", 32);
     873            0 :       db_create_key(hDB, hv_info->hKeyRoot, "Settings/Format Measured", TID_STRING);
     874            0 :       db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Measured", &hKey);
     875            0 :       db_set_data(hDB, hKey, format, n*32, n, TID_STRING);
     876            0 :       free(format);
     877              :    }
     878            0 :    status = db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Current", &hKey);
     879            0 :    if (status == DB_NO_KEY) {
     880            0 :       int n = hv_info->num_channels;
     881            0 :       char *format = (char *)calloc(n, 32);
     882            0 :       for (int ii=0 ; ii<n ; ii++)
     883            0 :          mstrlcpy(format + ii*32, "%f2", 32);
     884            0 :       db_create_key(hDB, hv_info->hKeyRoot, "Settings/Format Current", TID_STRING);
     885            0 :       db_find_key(hDB, hv_info->hKeyRoot, "Settings/Format Current", &hKey);
     886            0 :       db_set_data(hDB, hKey, format, n*32, n, TID_STRING);
     887            0 :       free(format);
     888              :    }
     889              : 
     890              :    /* Update threshold */
     891            0 :    validate_odb_array(hDB, hv_info, "Settings/Update Threshold Measured", 0.5, CMD_GET_THRESHOLD, 
     892              :                       hv_info->update_threshold, NULL, NULL);
     893              : 
     894              :    /* Update threshold current */
     895            0 :    validate_odb_array(hDB, hv_info, "Settings/Update Threshold Current", 1, CMD_GET_THRESHOLD_CURRENT, 
     896              :                       hv_info->update_threshold_current, NULL, NULL);
     897              : 
     898              :    /* Zero threshold */
     899            0 :    validate_odb_array(hDB, hv_info, "Settings/Zero Threshold", 20, CMD_GET_THRESHOLD_ZERO, 
     900              :                       hv_info->zero_threshold, NULL, NULL);
     901              : 
     902              :    /* Voltage limit */
     903            0 :    validate_odb_array(hDB, hv_info, "Settings/Voltage Limit", 3000, CMD_GET_VOLTAGE_LIMIT, 
     904              :                       hv_info->voltage_limit, hv_set_voltage_limit, pequipment);
     905              : 
     906              :    /* Current limit */
     907            0 :    validate_odb_array(hDB, hv_info, "Settings/Current Limit", 3000, CMD_GET_CURRENT_LIMIT, 
     908              :                       hv_info->current_limit, hv_set_current_limit, pequipment);
     909              : 
     910              :    /* Trip Time */
     911            0 :    validate_odb_array(hDB, hv_info, "Settings/Trip Time", 10, CMD_GET_TRIP_TIME, 
     912              :                       hv_info->trip_time, hv_set_trip_time, pequipment);
     913              : 
     914              :    /* Ramp up */
     915            0 :    validate_odb_array(hDB, hv_info, "Settings/Ramp Up Speed", 0, CMD_GET_RAMPUP, 
     916              :                       hv_info->rampup_speed, hv_set_rampup, pequipment);
     917              : 
     918              :    /* Ramp down */
     919            0 :    validate_odb_array(hDB, hv_info, "Settings/Ramp Down Speed", 0, CMD_GET_RAMPDOWN, 
     920              :                       hv_info->rampdown_speed, hv_set_rampdown, pequipment);
     921              : 
     922              :    /* Crate Map */
     923            0 :    if (hv_info->driver[0]->flags & DF_REPORT_CRATEMAP) {
     924            0 :       sprintf(str, "Settings/Devices/%s/DD/crateMap", pequipment->driver[0].name);
     925            0 :       validate_odb_int(hDB, hv_info, str, 'n', CMD_GET_CRATEMAP,
     926              :                       hv_info->crateMap, NULL, pequipment);
     927              :    }
     928              : 
     929              :    /*---- Create/Read variables ----*/
     930              : 
     931              :    /* Demand */
     932            0 :    db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Demand",
     933            0 :                  hv_info->demand, sizeof(float) * hv_info->num_channels,
     934              :                  hv_info->num_channels, TID_FLOAT);
     935            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Variables/Demand", &hv_info->hKeyDemand);
     936              : 
     937              :    /* Measured */
     938            0 :    db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Measured",
     939            0 :                  hv_info->measured, sizeof(float) * hv_info->num_channels,
     940              :                  hv_info->num_channels, TID_FLOAT);
     941            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Variables/Measured", &hv_info->hKeyMeasured);
     942            0 :    memcpy(hv_info->measured_mirror, hv_info->measured,
     943            0 :           hv_info->num_channels * sizeof(float));
     944              : 
     945              :    /* Current */
     946            0 :    db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Current",
     947            0 :                  hv_info->current, sizeof(float) * hv_info->num_channels,
     948              :                  hv_info->num_channels, TID_FLOAT);
     949            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Variables/Current", &hv_info->hKeyCurrent);
     950            0 :    memcpy(hv_info->current_mirror, hv_info->current,
     951            0 :           hv_info->num_channels * sizeof(float));
     952              : 
     953              :    /* Channel State */
     954            0 :    if (hv_info->driver[0]->flags & DF_REPORT_CHSTATE)
     955            0 :       validate_odb_array_bool(hDB, hv_info, "Variables/ChState", 'n', CMD_GET_CHSTATE,
     956              :                          hv_info->chState, hv_set_chState, pequipment);
     957              : 
     958              :    /* Status */
     959            0 :    if (hv_info->driver[0]->flags & DF_REPORT_STATUS){
     960            0 :       db_merge_data(hDB, hv_info->hKeyRoot, "Variables/ChStatus",
     961            0 :                     hv_info->chStatus, sizeof(DWORD) * hv_info->num_channels,
     962              :                     hv_info->num_channels, TID_DWORD);
     963            0 :       db_find_key(hDB, hv_info->hKeyRoot, "Variables/ChStatus", &hv_info->hKeyChStatus);
     964            0 :       memcpy(hv_info->chStatus_mirror, hv_info->chStatus,
     965            0 :              hv_info->num_channels * sizeof(DWORD));
     966              :    }
     967              : 
     968              :    /* Temperature */
     969            0 :    if (hv_info->driver[0]->flags & DF_REPORT_TEMP){
     970            0 :       db_merge_data(hDB, hv_info->hKeyRoot, "Variables/Temperature",
     971            0 :                     hv_info->temperature, sizeof(float) * hv_info->num_channels,
     972              :                     hv_info->num_channels, TID_FLOAT);
     973            0 :       db_find_key(hDB, hv_info->hKeyRoot, "Variables/Temperature", &hv_info->hKeyTemperature);
     974            0 :       memcpy(hv_info->temperature_mirror, hv_info->temperature,
     975            0 :              hv_info->num_channels * sizeof(float));
     976              :    }
     977              : 
     978              :    /*---- set labels from midas SC names ----*/
     979            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     980            0 :       if ((hv_info->driver[i]->flags & DF_LABELS_FROM_DEVICE) == 0)
     981            0 :       status = device_driver(hv_info->driver[i], CMD_SET_LABEL, 
     982            0 :                              i - hv_info->channel_offset[i], hv_info->names + NAME_LENGTH * i);
     983              :    }
     984              : 
     985              :    /*---- set/get values ----*/
     986            0 :    for (i = 0; i < hv_info->num_channels; i++) {
     987            0 :       if ((hv_info->driver[i]->flags & DF_PRIO_DEVICE) == 0) {
     988            0 :          hv_info->demand_mirror[i] = MIN(hv_info->demand[i], hv_info->voltage_limit[i]);
     989            0 :          status = device_driver(hv_info->driver[i], CMD_SET, 
     990            0 :                                 i - hv_info->channel_offset[i], hv_info->demand_mirror[i]);
     991            0 :          status = device_driver(hv_info->driver[i], CMD_SET_TRIP_TIME,
     992            0 :                                 i - hv_info->channel_offset[i], hv_info->trip_time[i]);
     993            0 :          status = device_driver(hv_info->driver[i], CMD_SET_CURRENT_LIMIT,
     994            0 :                                 i - hv_info->channel_offset[i], hv_info->current_limit[i]);
     995            0 :          status = device_driver(hv_info->driver[i], CMD_SET_VOLTAGE_LIMIT,
     996            0 :                                 i - hv_info->channel_offset[i], hv_info->voltage_limit[i]);
     997            0 :          if(hv_info->driver[i]->flags & DF_HW_RAMP){
     998            0 :             status = device_driver(hv_info->driver[i], CMD_SET_RAMPUP,
     999            0 :                                    i - hv_info->channel_offset[i], hv_info->rampup_speed[i]);
    1000            0 :             status = device_driver(hv_info->driver[i], CMD_SET_RAMPDOWN,
    1001            0 :                                    i - hv_info->channel_offset[i], hv_info->rampdown_speed[i]);
    1002              :          }
    1003            0 :          if (hv_info->driver[i]->flags & DF_REPORT_CHSTATE)
    1004            0 :             status = device_driver(hv_info->driver[i], CMD_SET_CHSTATE,
    1005            0 :                                    i - hv_info->channel_offset[i], (double)hv_info->chState[i]);
    1006              :       } else {
    1007            0 :          if (hv_info->driver[i]->flags & DF_POLL_DEMAND) {
    1008            0 :             hv_info->demand[i] = ss_nan();
    1009            0 :             hv_info->demand_mirror[i] = ss_nan();
    1010              :          } else {
    1011              :             // use CMD_GET_DEMAND_DIRECT, since demand value coming from thread has not yet
    1012              :             // been placed in buffer
    1013            0 :             status = device_driver(hv_info->driver[i], CMD_GET_DEMAND_DIRECT,
    1014            0 :                                    i - hv_info->channel_offset[i], hv_info->demand + i);
    1015            0 :             hv_info->demand_mirror[i] = hv_info->demand[i];
    1016              :          }
    1017              : 
    1018            0 :          status = device_driver(hv_info->driver[i], CMD_GET_TRIP_TIME,
    1019            0 :                                 i - hv_info->channel_offset[i], &hv_info->trip_time[i]);
    1020            0 :          status = device_driver(hv_info->driver[i], CMD_GET_CURRENT_LIMIT,
    1021            0 :                                 i - hv_info->channel_offset[i], &hv_info->current_limit[i]);
    1022            0 :          status = device_driver(hv_info->driver[i], CMD_GET_VOLTAGE_LIMIT,
    1023            0 :                                 i - hv_info->channel_offset[i], &hv_info->voltage_limit[i]);
    1024            0 :          if (hv_info->driver[i]->flags & DF_HW_RAMP) {
    1025            0 :             status = device_driver(hv_info->driver[i], CMD_GET_RAMPUP,
    1026            0 :                                    i - hv_info->channel_offset[i], &hv_info->rampup_speed[i]);
    1027            0 :             status = device_driver(hv_info->driver[i], CMD_GET_RAMPDOWN,
    1028            0 :                                    i - hv_info->channel_offset[i], &hv_info->rampdown_speed[i]);
    1029              :          }
    1030            0 :          if (hv_info->driver[i]->flags & DF_REPORT_CHSTATE)
    1031            0 :             status = device_driver(hv_info->driver[i], CMD_GET_CHSTATE,
    1032            0 :                                    i - hv_info->channel_offset[i], &hv_info->chState[i]);
    1033            0 :          if (hv_info->driver[i]->flags & DF_REPORT_CRATEMAP)
    1034            0 :             status = device_driver(hv_info->driver[i], CMD_GET_CRATEMAP,
    1035            0 :                                    i - hv_info->channel_offset[i], &hv_info->crateMap[i]);
    1036              :       }
    1037              :    }
    1038              : 
    1039            0 :    db_set_record(hDB, hv_info->hKeyDemand, hv_info->demand,
    1040            0 :                  hv_info->num_channels * sizeof(float), 0);
    1041              : 
    1042            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Settings/Trip Time", &hKey);
    1043            0 :    db_set_record(hDB, hKey, hv_info->trip_time, hv_info->num_channels * sizeof(float), 0);
    1044            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Settings/Current Limit", &hKey);
    1045            0 :    db_set_record(hDB, hKey, hv_info->current_limit, hv_info->num_channels * sizeof(float), 0);
    1046            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Settings/Voltage Limit", &hKey);
    1047            0 :    db_set_record(hDB, hKey, hv_info->voltage_limit, hv_info->num_channels * sizeof(float), 0);
    1048            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Settings/Ramp Up Speed", &hKey);
    1049            0 :    db_set_record(hDB, hKey, hv_info->rampup_speed, hv_info->num_channels * sizeof(float), 0);
    1050            0 :    db_find_key(hDB, hv_info->hKeyRoot, "Settings/Ramp Down Speed", &hKey);
    1051            0 :    db_set_record(hDB, hKey, hv_info->rampdown_speed, hv_info->num_channels * sizeof(float), 0);
    1052            0 :    if (hv_info->driver[0]->flags & DF_REPORT_CHSTATE){
    1053            0 :       db_find_key(hDB, hv_info->hKeyRoot, "Variables/ChState", &hKey);
    1054            0 :       db_set_record(hDB, hKey, hv_info->chState, hv_info->num_channels * sizeof(DWORD), 'n');
    1055              :    }
    1056            0 :    if (hv_info->driver[0]->flags & DF_REPORT_CRATEMAP){
    1057            0 :       sprintf(str, "Settings/Devices/%s/DD/crateMap", pequipment->driver[0].name);
    1058            0 :       db_find_key(hDB, hv_info->hKeyRoot, str, &hKey);
    1059            0 :       db_set_record(hDB, hKey, hv_info->crateMap, sizeof(INT), 'n');
    1060              :    }
    1061              : 
    1062              :    /*--- open hotlink to HV demand values ----*/
    1063            0 :    db_open_record(hDB, hv_info->hKeyDemand, hv_info->demand,
    1064            0 :                   hv_info->num_channels * sizeof(float), MODE_READ, hv_demand,
    1065              :                   pequipment);
    1066              : 
    1067              :    /* initially read all channels */
    1068            0 :    for (i=0 ; i<hv_info->num_channels ; i++) {
    1069            0 :       if ((hv_info->driver[i]->flags & DF_QUICKSTART) == 0) {
    1070            0 :          if (hv_info->driver[i]->enabled) {
    1071            0 :             hv_info->driver[i]->dd(CMD_GET, hv_info->driver[i]->dd_info,
    1072            0 :                                    i - hv_info->channel_offset[i], &hv_info->measured[i]);
    1073            0 :             hv_info->driver[i]->dd(CMD_GET_CURRENT, hv_info->driver[i]->dd_info,
    1074            0 :                                    i - hv_info->channel_offset[i], &hv_info->current[i]);
    1075            0 :             if (hv_info->driver[i]->flags & DF_REPORT_STATUS)
    1076            0 :                hv_info->driver[i]->dd(CMD_GET_STATUS, hv_info->driver[i]->dd_info,
    1077            0 :                                       i - hv_info->channel_offset[i], &hv_info->chStatus[i]);
    1078            0 :             if (hv_info->driver[i]->flags & DF_REPORT_TEMP)
    1079            0 :                hv_info->driver[i]->dd(CMD_GET_TEMPERATURE, hv_info->driver[i]->dd_info,
    1080            0 :                                       i - hv_info->channel_offset[i], &hv_info->temperature[i]);
    1081              : 
    1082            0 :             hv_info->measured_mirror[i]    = hv_info->measured[i];
    1083            0 :             hv_info->current_mirror[i]     = hv_info->current[i];
    1084            0 :             hv_info->chStatus_mirror[i]    = hv_info->chStatus[i];
    1085            0 :             hv_info->temperature_mirror[i] = hv_info->temperature[i];
    1086              : 
    1087            0 :             db_set_data_index(hDB, hv_info->hKeyCurrent, &hv_info->current[i], sizeof(float), i, TID_FLOAT);
    1088              : 
    1089            0 :             if (hv_info->driver[0]->flags & DF_REPORT_STATUS)
    1090            0 :                db_set_data_index(hDB, hv_info->hKeyChStatus, &hv_info->chStatus[i],
    1091              :                            sizeof(DWORD), i, TID_DWORD);
    1092              : 
    1093            0 :             if (hv_info->driver[0]->flags & DF_REPORT_TEMP)
    1094            0 :                db_set_data_index(hDB, hv_info->hKeyTemperature, &hv_info->temperature[i],
    1095            0 :                            sizeof(float) * hv_info->num_channels, hv_info->num_channels,
    1096              :                            TID_FLOAT);
    1097              : 
    1098              :          }
    1099              :       }
    1100              :    }
    1101              : 
    1102            0 :    pequipment->odb_out++;
    1103              :    
    1104            0 :    if (partially_disabled)
    1105            0 :       return FE_PARTIALLY_DISABLED;
    1106              :    
    1107            0 :    return FE_SUCCESS;
    1108              : }
    1109              : 
    1110              : /*------------------------------------------------------------------*/
    1111              : 
    1112            0 : INT hv_exit(EQUIPMENT * pequipment)
    1113              : {
    1114              :    INT i;
    1115              : 
    1116            0 :    free_mem((HV_INFO *) pequipment->cd_info);
    1117              : 
    1118              :    /* call exit method of device drivers */
    1119            0 :    for (i = 0; pequipment->driver[i].dd != NULL; i++)
    1120            0 :       device_driver(&pequipment->driver[i], CMD_EXIT);
    1121              : 
    1122            0 :    return FE_SUCCESS;
    1123              : }
    1124              : 
    1125              : /*------------------------------------------------------------------*/
    1126              : 
    1127            0 : INT hv_idle(EQUIPMENT * pequipment)
    1128              : {
    1129            0 :    INT act, status = 0;
    1130              :    DWORD act_time;
    1131              :    HV_INFO *hv_info;
    1132              : 
    1133            0 :    hv_info = (HV_INFO *) pequipment->cd_info;
    1134              : 
    1135              :    /* do ramping */
    1136            0 :    hv_ramp(hv_info);
    1137              : 
    1138            0 :    if (hv_info->driver[0]->flags & DF_MULTITHREAD) {
    1139              :       // hv_read reads all channels
    1140            0 :       status = hv_read(pequipment, 0);
    1141              :    } else {
    1142              :       /* select next measurement channel */
    1143            0 :       hv_info->last_channel = (hv_info->last_channel + 1) % hv_info->num_channels;
    1144              :       
    1145              :       /* measure channel */
    1146            0 :       status = hv_read(pequipment, hv_info->last_channel);
    1147              :    }
    1148              :    
    1149              :    /* additionally read channel recently updated if not multithreaded */
    1150            0 :    if (!(hv_info->driver[hv_info->last_channel]->flags & DF_MULTITHREAD)) {
    1151              : 
    1152            0 :       act_time = ss_millitime();
    1153              : 
    1154            0 :       act = (hv_info->last_channel_updated + 1) % hv_info->num_channels;
    1155            0 :       while (!(act_time - hv_info->last_change[act] < 10000)) {
    1156            0 :          act = (act + 1) % hv_info->num_channels;
    1157            0 :          if (act == hv_info->last_channel_updated) {
    1158              :             /* non found, so return */
    1159            0 :             return status;
    1160              :          }
    1161              :       }
    1162              : 
    1163              :       /* updated channel found, so read it additionally */
    1164            0 :       status = hv_read(pequipment, act);
    1165            0 :       hv_info->last_channel_updated = act;
    1166              :    }
    1167              : 
    1168            0 :    return status;
    1169              : }
    1170              : 
    1171              : /*------------------------------------------------------------------*/
    1172              : 
    1173            0 : INT cd_hv_read(char *pevent, int offset)
    1174              : {
    1175              :    float *pdata;
    1176              : 
    1177            0 :    EQUIPMENT* pequipment = *((EQUIPMENT **) pevent);
    1178            0 :    HV_INFO* hv_info = (HV_INFO *) pequipment->cd_info;
    1179              : 
    1180            0 :    if (hv_info->format == FORMAT_FIXED) {
    1181            0 :       memcpy(pevent, hv_info->demand, sizeof(float) * hv_info->num_channels);
    1182            0 :       pevent += sizeof(float) * hv_info->num_channels;
    1183              : 
    1184            0 :       memcpy(pevent, hv_info->measured, sizeof(float) * hv_info->num_channels);
    1185            0 :       pevent += sizeof(float) * hv_info->num_channels;
    1186              : 
    1187            0 :       memcpy(pevent, hv_info->current, sizeof(float) * hv_info->num_channels);
    1188            0 :       pevent += sizeof(float) * hv_info->num_channels;
    1189              : 
    1190            0 :       memcpy(pevent, hv_info->chStatus, sizeof(DWORD) * hv_info->num_channels);
    1191            0 :       pevent += sizeof(DWORD) * hv_info->num_channels;
    1192              : 
    1193            0 :       memcpy(pevent, hv_info->temperature, sizeof(float) * hv_info->num_channels);
    1194            0 :       pevent += sizeof(float) * hv_info->num_channels;
    1195              : 
    1196            0 :       return ( 4 * sizeof(float) + sizeof(DWORD) )* hv_info->num_channels;
    1197            0 :    } else if (hv_info->format == FORMAT_MIDAS) {
    1198            0 :       bk_init32(pevent);
    1199              : 
    1200              :       /* create DMND bank */
    1201            0 :       bk_create(pevent, "DMND", TID_FLOAT, (void **)&pdata);
    1202            0 :       memcpy(pdata, hv_info->demand, sizeof(float) * hv_info->num_channels);
    1203            0 :       pdata += hv_info->num_channels;
    1204            0 :       bk_close(pevent, pdata);
    1205              : 
    1206              :       /* create MSRD bank */
    1207            0 :       bk_create(pevent, "MSRD", TID_FLOAT, (void **)&pdata);
    1208            0 :       memcpy(pdata, hv_info->measured, sizeof(float) * hv_info->num_channels);
    1209            0 :       pdata += hv_info->num_channels;
    1210            0 :       bk_close(pevent, pdata);
    1211              : 
    1212              :       /* create CRNT bank */
    1213            0 :       bk_create(pevent, "CRNT", TID_FLOAT, (void **)&pdata);
    1214            0 :       memcpy(pdata, hv_info->current, sizeof(float) * hv_info->num_channels);
    1215            0 :       pdata += hv_info->num_channels;
    1216            0 :       bk_close(pevent, pdata);
    1217              : 
    1218              :       /* create STAT bank */
    1219            0 :       bk_create(pevent, "STAT", TID_DWORD, (void **)&pdata);
    1220            0 :       memcpy(pdata, hv_info->chStatus, sizeof(DWORD) * hv_info->num_channels); 
    1221            0 :       pdata += hv_info->num_channels;
    1222            0 :       bk_close(pevent, pdata);
    1223              : 
    1224              :       /* create TPTR bank */
    1225            0 :       bk_create(pevent, "TPTR", TID_FLOAT, (void **)&pdata);
    1226            0 :       memcpy(pdata, hv_info->temperature, sizeof(float) * hv_info->num_channels); 
    1227            0 :       pdata += hv_info->num_channels;
    1228            0 :       bk_close(pevent, pdata);
    1229              : 
    1230            0 :       return bk_size(pevent);
    1231              :    } else {
    1232            0 :       assert(!"unsupported hv_info->format");
    1233              :    }
    1234              : 
    1235              :    return 0;
    1236              : }
    1237              : 
    1238              : /*------------------------------------------------------------------*/
    1239              : 
    1240            0 : INT cd_hv(INT cmd, PEQUIPMENT pequipment)
    1241              : {
    1242              :    INT status;
    1243              : 
    1244            0 :    switch (cmd) {
    1245            0 :    case CMD_INIT:
    1246            0 :       status = hv_init(pequipment);
    1247            0 :       break;
    1248              : 
    1249            0 :    case CMD_EXIT:
    1250            0 :       status = hv_exit(pequipment);
    1251            0 :       break;
    1252              : 
    1253            0 :    case CMD_START:
    1254            0 :       status = hv_start(pequipment);
    1255            0 :       break;
    1256              : 
    1257            0 :    case CMD_STOP:
    1258            0 :       status = hv_stop(pequipment);
    1259            0 :       break;
    1260              : 
    1261            0 :    case CMD_IDLE:
    1262            0 :       status = hv_idle(pequipment);
    1263            0 :       break;
    1264              : 
    1265            0 :    default:
    1266            0 :       cm_msg(MERROR, "HV class driver", "Received unknown command %d", cmd);
    1267            0 :       status = FE_ERR_DRIVER;
    1268            0 :       break;
    1269              :    }
    1270              : 
    1271            0 :    return status;
    1272              : }
        

Generated by: LCOV version 2.0-1