Oak Ridge (Ordella) High Voltage Power Supply environment controller
r2273 | dcl | 2008-01-15 12:28:38 +1100 (Tue, 15 Jan 2008) | 2 lines
This commit is contained in:
964
site_ansto/orhvps.c
Normal file
964
site_ansto/orhvps.c
Normal file
@@ -0,0 +1,964 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
O R H V P S
|
||||||
|
|
||||||
|
Support for Oak Ridge High Voltage Power Supply for SICS.
|
||||||
|
|
||||||
|
The meaning and working of the functions defined is as desribed for a
|
||||||
|
general environment controller.
|
||||||
|
|
||||||
|
Douglas Clowes, December 2007
|
||||||
|
|
||||||
|
Copyright:
|
||||||
|
|
||||||
|
Labor fuer Neutronenstreuung
|
||||||
|
Paul Scherrer Institut
|
||||||
|
CH-5423 Villigen-PSI
|
||||||
|
|
||||||
|
|
||||||
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
|
and license this software and its documentation for any purpose, provided
|
||||||
|
that existing copyright notices are retained in all copies and that this
|
||||||
|
notice is included verbatim in any distributions. No written agreement,
|
||||||
|
license, or royalty fee is required for any of the authorized uses.
|
||||||
|
Modifications to this software may be copyrighted by their authors
|
||||||
|
and need not follow the licensing terms described here, provided that
|
||||||
|
the new terms are clearly indicated on the first page of each file where
|
||||||
|
they apply.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||||
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||||
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||||||
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||||||
|
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
||||||
|
MODIFICATIONS.
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "orhvps.h"
|
||||||
|
#include "sics.h"
|
||||||
|
#include "asyncqueue.h"
|
||||||
|
#include "nwatch.h"
|
||||||
|
#include "fsm.h"
|
||||||
|
#include "anstoutil.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define CMDLEN 132
|
||||||
|
|
||||||
|
typedef struct orhvps_s {
|
||||||
|
pEVControl controller;
|
||||||
|
int iValue; /* integer value from controller (0..63) */
|
||||||
|
int iPeriod; /* integer step-rate period in milliseconds */
|
||||||
|
float fValue; /* current voltage in volts */
|
||||||
|
float fMax; /* maximum voltage in volts at iValue=63 */
|
||||||
|
float fRate; /* voltage slew rate in volts per second */
|
||||||
|
float fTarget; /* requested target voltage */
|
||||||
|
char* name;
|
||||||
|
pAsyncUnit asyncUnit;
|
||||||
|
StateMachine fsm;
|
||||||
|
pNWTimer state_timer; /**< state timer */
|
||||||
|
} ORHVPSDriv, *pORHVPSDriv;
|
||||||
|
|
||||||
|
static int ORHVPSGetValue( pEVDriver self, float* fPos);
|
||||||
|
static int ORHVPSSetValue( pEVDriver self, float fPos);
|
||||||
|
static int ORHVPSSend(pEVDriver self, char *pCommand, char *pReply, int iLen);
|
||||||
|
static int ORHVPSError(pEVDriver self, int *iCode, char *error, int iErrLen);
|
||||||
|
static int ORHVPSFix(pEVDriver self, int iError);
|
||||||
|
static int ORHVPSInit(pEVDriver self);
|
||||||
|
static int ORHVPSClose(pEVDriver self);
|
||||||
|
static void ORHVPSKillPrivate(void *pData);
|
||||||
|
static void ORHVPSNotify(void* context, int event);
|
||||||
|
|
||||||
|
static int ORHV_SendCmd(pORHVPSDriv self,
|
||||||
|
char* command,
|
||||||
|
int cmd_len,
|
||||||
|
AsyncTxnHandler callback)
|
||||||
|
{
|
||||||
|
pStateMachine sm = &self->fsm;
|
||||||
|
return AsyncUnitSendTxn(self->asyncUnit,
|
||||||
|
command, cmd_len,
|
||||||
|
callback, sm, CMDLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/**
|
||||||
|
* \brief SendCallback is the callback for the general command.
|
||||||
|
*/
|
||||||
|
static int ORHV_SendCallback(pAsyncTxn pCmd)
|
||||||
|
{
|
||||||
|
char* cmnd = pCmd->out_buf;
|
||||||
|
char* resp = pCmd->inp_buf;
|
||||||
|
pORHVPSDriv self = (pORHVPSDriv) pCmd->cntx;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (pCmd->txn_status == ATX_TIMEOUT) {
|
||||||
|
if (self->debug) {
|
||||||
|
SICSLogWrite(pCmd->out_buf, eStatus);
|
||||||
|
SICSLogWrite("<TIMEOUT>", eStatus);
|
||||||
|
}
|
||||||
|
strncpy(self->lastCmd, pCmd->out_buf, CMDLEN);
|
||||||
|
self->errorCode = MOTCMDTMO;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (resp[0]) {
|
||||||
|
case ':':
|
||||||
|
case ' ':
|
||||||
|
if (self->debug) {
|
||||||
|
SICSLogWrite(cmnd, eStatus);
|
||||||
|
SICSLogWrite(resp, eStatus);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
strncpy(self->lastCmd, pCmd->out_buf, CMDLEN);
|
||||||
|
strncpy(self->dmc2280Error, &resp[1], CMDLEN);
|
||||||
|
SICSLogWrite(cmnd, eError);
|
||||||
|
SICSLogWrite(resp, eError);
|
||||||
|
self->errorCode = BADCMD;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SICSLogWrite(cmnd, eError);
|
||||||
|
SICSLogWrite(resp, eError);
|
||||||
|
self->errorCode = BADUNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ORHV_QueueCmd(pORHVPSDriv self,
|
||||||
|
char *cmd,
|
||||||
|
int cmd_len,
|
||||||
|
AsyncTxnHandler cb) {
|
||||||
|
if (cb == NULL)
|
||||||
|
cb = ORHV_SendCallback;
|
||||||
|
return ORHV_SendCmd(self, cmd, cmd_len, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Sends a DMC2280 command to the motor controller.
|
||||||
|
*
|
||||||
|
* If the command fails it displays the DMC2280 error message to the client
|
||||||
|
* and writes it to the log file, also sets errorCode field in motor's
|
||||||
|
* data structure.
|
||||||
|
*
|
||||||
|
* \param self (rw) provides access to the motor's data structure
|
||||||
|
* \param *command (r) DMC2280 command
|
||||||
|
* \return
|
||||||
|
* - SUCCESS
|
||||||
|
* - FAILURE
|
||||||
|
* \see SUCCESS FAILURE
|
||||||
|
*/
|
||||||
|
/* First character returned by controller is
|
||||||
|
'?' for an invalid command or
|
||||||
|
':' for a valid command with no response
|
||||||
|
' ' for a valid command with a response (':' follows)
|
||||||
|
*/
|
||||||
|
static int ORHV_Send(pORHVPSDriv self, char *command, int cmd_len) {
|
||||||
|
return ORHV_QueueCmd(self, command, cmd_len, ORHV_SendCallback);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Sends a command and waits for a response
|
||||||
|
*
|
||||||
|
* \param self motor data
|
||||||
|
* \param cmd command to send
|
||||||
|
* \param reply space to return response
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
static int ORHV_SendReceive(pORHVPSDriv self,
|
||||||
|
char *cmd,
|
||||||
|
int cmd_len,
|
||||||
|
char* reply,
|
||||||
|
int *rep_len) {
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = AsyncUnitTransact(self->asyncUnit, cmd, cmd_len, reply, rep_len);
|
||||||
|
|
||||||
|
if (status != 1) {
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ORHVState_Unknown(pStateMachine sm, pEvtEvent event);
|
||||||
|
static void ORHVState_Idle(pStateMachine sm, pEvtEvent event);
|
||||||
|
static void ORHVState_Raising(pStateMachine sm, pEvtEvent event);
|
||||||
|
static void ORHVState_Lowering(pStateMachine sm, pEvtEvent event);
|
||||||
|
|
||||||
|
static void str_n_cat(char* s1, int len, const char* s2) {
|
||||||
|
int i = strlen(s1);
|
||||||
|
const char* p = s2;
|
||||||
|
while (i < len - 3 && *p) {
|
||||||
|
if (*p == '\r') {
|
||||||
|
s1[i++] = '\\';
|
||||||
|
s1[i++] = 'r';
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
else if (*p == '\n') {
|
||||||
|
s1[i++] = '\\';
|
||||||
|
s1[i++] = 'n';
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s1[i++] = *p++;
|
||||||
|
}
|
||||||
|
s1[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* state_name(StateFunc func)
|
||||||
|
{
|
||||||
|
if (func == NULL) return "<null_state>";
|
||||||
|
if (func == ORHVState_Unknown) return "ORHVState_Unknown";
|
||||||
|
if (func == ORHVState_Idle) return "ORHVState_Idle";
|
||||||
|
if (func == ORHVState_Raising) return "ORHVState_Raising";
|
||||||
|
if (func == ORHVState_Lowering) return "ORHVState_Lowering";
|
||||||
|
return "<unknown_state>";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* event_name(pEvtEvent event, char* text, int length)
|
||||||
|
{
|
||||||
|
if (event == NULL)
|
||||||
|
return "<null_event>";
|
||||||
|
switch (event->event_type) {
|
||||||
|
case eStateEvent:
|
||||||
|
snprintf(text, length, "eStateEvent");
|
||||||
|
return text;
|
||||||
|
case eTimerEvent:
|
||||||
|
snprintf(text, length, "eTimerEvent");
|
||||||
|
return text;
|
||||||
|
case eMessageEvent:
|
||||||
|
snprintf(text, length, "eMessageEvent:");
|
||||||
|
str_n_cat(text, length, event->event.msg.cmd->out_buf);
|
||||||
|
str_n_cat(text, length, "|");
|
||||||
|
str_n_cat(text, length, event->event.msg.cmd->inp_buf);
|
||||||
|
return text;
|
||||||
|
case eCommandEvent:
|
||||||
|
/* TODO Command Events */
|
||||||
|
snprintf(text, length, "eCommandEvent:unknown");
|
||||||
|
return text;
|
||||||
|
case eTimeoutEvent:
|
||||||
|
snprintf(text, length, "eTimeoutEvent");
|
||||||
|
return text;
|
||||||
|
default:
|
||||||
|
snprintf(text, length, "<unknown_event>");
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ORHVState_Unknown(pStateMachine sm, pEvtEvent event) {
|
||||||
|
pEVDriver driv = (pEVDriver) sm->context;
|
||||||
|
pORHVPSDriv priv = (pORHVPSDriv) driv->pPrivate;
|
||||||
|
switch (event->event_type) {
|
||||||
|
case eStateEvent:
|
||||||
|
if (priv->state_timer)
|
||||||
|
NetWatchRemoveTimer(priv->state_timer);
|
||||||
|
priv->state_timer = NULL;
|
||||||
|
ORHV_SendCmd(priv, "vz", 2, fsm_msg_callback);
|
||||||
|
sm->mySubState = 1;
|
||||||
|
return;
|
||||||
|
case eTimerEvent:
|
||||||
|
priv->state_timer = NULL;
|
||||||
|
return;
|
||||||
|
case eMessageEvent:
|
||||||
|
do {
|
||||||
|
pAsyncTxn pCmd = event->event.msg.cmd;
|
||||||
|
pCmd->inp_buf[pCmd->inp_idx] = '\0';
|
||||||
|
if (sm->mySubState == 1) { /* Version Request */
|
||||||
|
char* p = strchr(pCmd->inp_buf, 'z');
|
||||||
|
if (p) {
|
||||||
|
char line[132];
|
||||||
|
*p = '\0';
|
||||||
|
sprintf(line, "Version: %s", pCmd->inp_buf);
|
||||||
|
SICSLogWrite(line, eStatus);
|
||||||
|
}
|
||||||
|
ORHV_SendCmd(priv, "Hz", 2, fsm_msg_callback);
|
||||||
|
sm->mySubState = 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sm->mySubState == 2) { /* HV Get Request */
|
||||||
|
char* p = strchr(pCmd->inp_buf, 'z');
|
||||||
|
if (p) {
|
||||||
|
priv->iValue = (pCmd->inp_buf[1] & 0x3F);
|
||||||
|
priv->fValue = priv->iValue * (priv->fMax / 63.0);
|
||||||
|
priv->fTarget = priv->fValue;
|
||||||
|
}
|
||||||
|
fsm_change_state(sm, ORHVState_Idle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
return;
|
||||||
|
case eCommandEvent:
|
||||||
|
return;
|
||||||
|
case eTimeoutEvent:
|
||||||
|
ORHV_SendCmd(priv, "vz", 2, fsm_msg_callback);
|
||||||
|
sm->mySubState = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ORHVState_Idle(pStateMachine sm, pEvtEvent event){
|
||||||
|
pEVDriver driv = (pEVDriver) sm->context;
|
||||||
|
pORHVPSDriv priv = (pORHVPSDriv) driv->pPrivate;
|
||||||
|
int newVal;
|
||||||
|
switch (event->event_type) {
|
||||||
|
case eStateEvent:
|
||||||
|
if (priv->state_timer)
|
||||||
|
NetWatchRemoveTimer(priv->state_timer);
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
200,
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
case eTimerEvent:
|
||||||
|
priv->state_timer = NULL;
|
||||||
|
newVal = roundf(priv->fTarget / (priv->fMax / 63.0));
|
||||||
|
if (newVal > priv->iValue) {
|
||||||
|
fsm_change_state(sm, ORHVState_Raising);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newVal < priv->iValue) {
|
||||||
|
fsm_change_state(sm, ORHVState_Lowering);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
200,
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
case eMessageEvent:
|
||||||
|
do {
|
||||||
|
} while (0);
|
||||||
|
case eCommandEvent:
|
||||||
|
return;
|
||||||
|
case eTimeoutEvent:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ORHVState_Raising(pStateMachine sm, pEvtEvent event){
|
||||||
|
pEVDriver driv = (pEVDriver) sm->context;
|
||||||
|
pORHVPSDriv priv = (pORHVPSDriv) driv->pPrivate;
|
||||||
|
int newVal;
|
||||||
|
switch (event->event_type) {
|
||||||
|
case eStateEvent:
|
||||||
|
if (priv->state_timer)
|
||||||
|
NetWatchRemoveTimer(priv->state_timer);
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
200,
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
sm->mySubState = 1;
|
||||||
|
return;
|
||||||
|
case eTimerEvent:
|
||||||
|
priv->state_timer = NULL;
|
||||||
|
if (sm->mySubState == 1) {
|
||||||
|
ORHV_SendCmd(priv, "Hz", 2, fsm_msg_callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sm->mySubState == 2) {
|
||||||
|
char cmd[3];
|
||||||
|
cmd[0] = 'h';
|
||||||
|
cmd[1] = priv->iValue < 63 ? priv->iValue + 1 : priv->iValue;
|
||||||
|
cmd[2] = 'z';
|
||||||
|
ORHV_SendCmd(priv, cmd, 3, fsm_msg_callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sm->mySubState = 1;
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
100, /* TODO*/
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
case eMessageEvent:
|
||||||
|
do {
|
||||||
|
pAsyncTxn pCmd = event->event.msg.cmd;
|
||||||
|
pCmd->inp_buf[pCmd->inp_idx] = '\0';
|
||||||
|
if (sm->mySubState == 1) { /* HV Get Request */
|
||||||
|
if (pCmd->inp_buf[0] == 'H' && pCmd->inp_buf[2] == 'z') {
|
||||||
|
priv->iValue = (pCmd->inp_buf[1] & 0x3F);
|
||||||
|
priv->fValue = priv->iValue * (priv->fMax / 63.0);
|
||||||
|
newVal = roundf(priv->fTarget / (priv->fMax / 63.0));
|
||||||
|
if (newVal == priv->iValue) {
|
||||||
|
fsm_change_state(sm, ORHVState_Idle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newVal < priv->iValue) {
|
||||||
|
fsm_change_state(sm, ORHVState_Lowering);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sm->mySubState = 2;
|
||||||
|
}
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
100, /* TODO*/
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sm->mySubState == 2) { /* HV Set Request */
|
||||||
|
if (*pCmd->inp_buf == 0x06) {
|
||||||
|
/* TODO: ACK */
|
||||||
|
}
|
||||||
|
else if (*pCmd->inp_buf == 0x15) {
|
||||||
|
/* TODO: NAK */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* TODO: ??? */
|
||||||
|
}
|
||||||
|
sm->mySubState = 1;
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
priv->iPeriod, /* TODO*/
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
sm->mySubState = 1;
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
100, /* TODO*/
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
case eCommandEvent:
|
||||||
|
return;
|
||||||
|
case eTimeoutEvent:
|
||||||
|
sm->mySubState = 1;
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
100, /* TODO*/
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ORHVState_Lowering(pStateMachine sm, pEvtEvent event){
|
||||||
|
pEVDriver driv = (pEVDriver) sm->context;
|
||||||
|
pORHVPSDriv priv = (pORHVPSDriv) driv->pPrivate;
|
||||||
|
char cmd[3];
|
||||||
|
int newVal;
|
||||||
|
switch (event->event_type) {
|
||||||
|
case eStateEvent:
|
||||||
|
if (priv->state_timer)
|
||||||
|
NetWatchRemoveTimer(priv->state_timer);
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
200,
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
sm->mySubState = 1;
|
||||||
|
return;
|
||||||
|
case eTimerEvent:
|
||||||
|
priv->state_timer = NULL;
|
||||||
|
if (sm->mySubState == 1) {
|
||||||
|
ORHV_SendCmd(priv, "Hz", 2, fsm_msg_callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sm->mySubState == 2) {
|
||||||
|
cmd[0] = 'h';
|
||||||
|
cmd[1] = priv->iValue > 0 ? priv->iValue - 1 : priv->iValue;
|
||||||
|
cmd[2] = 'z';
|
||||||
|
ORHV_SendCmd(priv, cmd, 3, fsm_msg_callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sm->mySubState = 1;
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
100, /* TODO*/
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
case eMessageEvent:
|
||||||
|
do {
|
||||||
|
pAsyncTxn pCmd = event->event.msg.cmd;
|
||||||
|
pCmd->inp_buf[pCmd->inp_idx] = '\0';
|
||||||
|
if (sm->mySubState == 1) { /* HV Get Request */
|
||||||
|
if (pCmd->inp_buf[0] == 'H' && pCmd->inp_buf[2] == 'z') {
|
||||||
|
priv->iValue = (pCmd->inp_buf[1] & 0x3F);
|
||||||
|
priv->fValue = priv->iValue * (priv->fMax / 63.0);
|
||||||
|
newVal = roundf(priv->fTarget / (priv->fMax / 63.0));
|
||||||
|
if (newVal == priv->iValue) {
|
||||||
|
fsm_change_state(sm, ORHVState_Idle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newVal > priv->iValue) {
|
||||||
|
fsm_change_state(sm, ORHVState_Raising);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sm->mySubState = 2;
|
||||||
|
}
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
100, /* TODO*/
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sm->mySubState == 2) { /* HV Set Request */
|
||||||
|
if (*pCmd->inp_buf == 0x06) {
|
||||||
|
/* TODO: ACK */
|
||||||
|
}
|
||||||
|
else if (*pCmd->inp_buf == 0x15) {
|
||||||
|
/* TODO: NAK */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* TODO: ??? */
|
||||||
|
}
|
||||||
|
sm->mySubState = 1;
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
priv->iPeriod, /* TODO*/
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
sm->mySubState = 1;
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
100, /* TODO*/
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
case eCommandEvent:
|
||||||
|
return;
|
||||||
|
case eTimeoutEvent:
|
||||||
|
sm->mySubState = 1;
|
||||||
|
NetWatchRegisterTimer(&priv->state_timer,
|
||||||
|
100, /* TODO*/
|
||||||
|
fsm_tmr_callback, sm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ORHVPSGetValue( pEVDriver self, float* fPos) {
|
||||||
|
pORHVPSDriv me = NULL;
|
||||||
|
int newVal;
|
||||||
|
assert(self);
|
||||||
|
assert(self->pPrivate);
|
||||||
|
me = (pORHVPSDriv) self->pPrivate;
|
||||||
|
newVal = roundf(me->fTarget / (me->fMax / 63.0));
|
||||||
|
if (newVal == me->iValue)
|
||||||
|
*fPos = me->fTarget;
|
||||||
|
else
|
||||||
|
*fPos = me->fValue;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int ORHVPSSetValue( pEVDriver self, float fPos) {
|
||||||
|
pORHVPSDriv me = NULL;
|
||||||
|
assert(self);
|
||||||
|
assert(self->pPrivate);
|
||||||
|
me = (pORHVPSDriv) self->pPrivate;
|
||||||
|
if (fPos < 0.0 || fPos > me->fMax)
|
||||||
|
return 0;
|
||||||
|
me->fTarget = fPos;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int ORHVPSSend(pEVDriver self, char *pCommand, char *pReply, int iLen) {
|
||||||
|
char cmd[CMDLEN];
|
||||||
|
int cmd_len;
|
||||||
|
char rsp[CMDLEN];
|
||||||
|
int rsp_len;
|
||||||
|
int idx = 0;
|
||||||
|
int i;
|
||||||
|
cmd[0] = '\0';
|
||||||
|
if (pCommand && *pCommand && pReply && iLen > 0) {
|
||||||
|
for (i = 0; pCommand[i]; ++i) {
|
||||||
|
int k;
|
||||||
|
if (pCommand[i] == '\\') {
|
||||||
|
k = 0;
|
||||||
|
if (isxdigit(pCommand[i+1]) && isxdigit(pCommand[i+2])) {
|
||||||
|
if (pCommand[i+1] >= '0' && pCommand[i+1] <= '9')
|
||||||
|
k = (pCommand[i+1] - '0') << 4;
|
||||||
|
else if (pCommand[i+1] >= 'a' && pCommand[i+1] <= 'f')
|
||||||
|
k = (pCommand[i+1] - 'a' + 10) << 4;
|
||||||
|
else if (pCommand[i+1] >= 'A' && pCommand[i+1] <= 'F')
|
||||||
|
k = (pCommand[i+1] - 'A' + 10) << 4;
|
||||||
|
if (pCommand[i+2] >= '0' && pCommand[i+2] <= '9')
|
||||||
|
k += (pCommand[i+2] - '0');
|
||||||
|
else if (pCommand[i+2] >= 'a' && pCommand[i+2] <= 'f')
|
||||||
|
k += (pCommand[i+2] - 'a' + 10);
|
||||||
|
else if (pCommand[i+2] >= 'A' && pCommand[i+2] <= 'F')
|
||||||
|
k += (pCommand[i+2] - 'A' + 10);
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
k = pCommand[i];
|
||||||
|
if (idx < CMDLEN)
|
||||||
|
cmd[idx++] = k;
|
||||||
|
}
|
||||||
|
if (idx < CMDLEN)
|
||||||
|
cmd[idx] = '\0';
|
||||||
|
cmd_len = idx;
|
||||||
|
rsp_len = CMDLEN;
|
||||||
|
ORHV_SendReceive(self->pPrivate, cmd, cmd_len, rsp, &rsp_len);
|
||||||
|
idx = 0;
|
||||||
|
for (i = 0; i < rsp_len; ++i) {
|
||||||
|
if ((rsp[i] < 32 || rsp[i] > 126) && idx < iLen - 3) {
|
||||||
|
snprintf(&pReply[idx], 3, "\\%02x", rsp[i]);
|
||||||
|
idx += 3;
|
||||||
|
}
|
||||||
|
else if (idx < iLen)
|
||||||
|
pReply[idx++] = rsp[i];
|
||||||
|
}
|
||||||
|
pReply[idx] = '\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static int ORHVPSError(pEVDriver self, int *iCode, char *error, int iErrLen) {
|
||||||
|
/* TODO */
|
||||||
|
*iCode = -1;
|
||||||
|
strncpy(error,"TODO Error Messages",iErrLen);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int ORHVPSFix(pEVDriver self, int iError) {
|
||||||
|
/* TODO */
|
||||||
|
return DEVFAULT;
|
||||||
|
}
|
||||||
|
static int ORHVPSInit(pEVDriver self) {
|
||||||
|
/* TODO */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int ORHVPSClose(pEVDriver self) {
|
||||||
|
/* TODO */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static void ORHVPSKillPrivate(void *pData) {
|
||||||
|
pORHVPSDriv pMe = (pORHVPSDriv) pData;
|
||||||
|
if (pMe) {
|
||||||
|
if (pMe->asyncUnit) {
|
||||||
|
AsyncUnitDestroy(pMe->asyncUnit);
|
||||||
|
pMe->asyncUnit = NULL;
|
||||||
|
}
|
||||||
|
if (pMe ->name) {
|
||||||
|
free(pMe ->name);
|
||||||
|
pMe ->name = NULL;
|
||||||
|
}
|
||||||
|
/* Not required as performed in caller
|
||||||
|
* free(pMe);
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ORHVPSNotify(void* context, int event)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
pEVDriver self = (pEVDriver) context;
|
||||||
|
char line[132];
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case AQU_DISCONNECT:
|
||||||
|
snprintf(line, 132, "Disconnect on Device '%s'", self->name);
|
||||||
|
SICSLogWrite(line, eStatus);
|
||||||
|
/* TODO: disconnect */
|
||||||
|
break;
|
||||||
|
case AQU_RECONNECT:
|
||||||
|
snprintf(line, 132, "Reconnect on Device '%s'", self->name);
|
||||||
|
SICSLogWrite(line, eStatus);
|
||||||
|
/* TODO: reconnect */
|
||||||
|
if (self->has_fsm) {
|
||||||
|
/* Reset the state machine */
|
||||||
|
if (self->state_timer)
|
||||||
|
NetWatchRemoveTimer(self->state_timer);
|
||||||
|
self->state_timer = 0;
|
||||||
|
change_state(self, DMCState_Unknown);
|
||||||
|
/* Schedule a timer event as soon as possible */
|
||||||
|
NetWatchRegisterTimer(&self->state_timer,
|
||||||
|
0,
|
||||||
|
state_tmr_callback, self);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static pAsyncProtocol ORHVPS_Protocol = NULL;
|
||||||
|
|
||||||
|
static int ORHVPS_Tx(pAsyncProtocol p, pAsyncTxn ctx)
|
||||||
|
{
|
||||||
|
int iRet = 1;
|
||||||
|
pAsyncTxn myCmd = (pAsyncTxn) ctx;
|
||||||
|
|
||||||
|
if (myCmd) {
|
||||||
|
myCmd->txn_status = ATX_ACTIVE;
|
||||||
|
iRet = AsyncUnitWrite(myCmd->unit, myCmd->out_buf, myCmd->out_len);
|
||||||
|
/* TODO handle errors */
|
||||||
|
if (iRet < 0) { /* TODO: EOF */
|
||||||
|
/*
|
||||||
|
iRet = AsyncUnitReconnect(myCmd->unit);
|
||||||
|
if (iRet == 0)
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ORHVPS_Rx(pAsyncProtocol p, pAsyncTxn ctx, int rxchar) {
|
||||||
|
int iRet = 1;
|
||||||
|
pAsyncTxn myCmd = (pAsyncTxn) ctx;
|
||||||
|
|
||||||
|
switch (myCmd->txn_state) {
|
||||||
|
case 0: /* first character */
|
||||||
|
if (rxchar == 0x06) { /* ACK */
|
||||||
|
/* normal prompt */
|
||||||
|
myCmd->txn_state = 99;
|
||||||
|
myCmd->txn_status = ATX_COMPLETE;
|
||||||
|
}
|
||||||
|
else if (rxchar == 0x15) { /* NAK */
|
||||||
|
myCmd->txn_state = 99;
|
||||||
|
myCmd->txn_status = ATX_COMPLETE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* normal data */
|
||||||
|
myCmd->txn_state = 1;
|
||||||
|
}
|
||||||
|
/* note fallthrough */
|
||||||
|
case 1: /* receiving reply */
|
||||||
|
if (myCmd->inp_idx < myCmd->inp_len)
|
||||||
|
myCmd->inp_buf[myCmd->inp_idx++] = rxchar;
|
||||||
|
if (rxchar == 'z')
|
||||||
|
myCmd->txn_state = 99;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (myCmd->txn_state == 99) {
|
||||||
|
iRet = 0;
|
||||||
|
}
|
||||||
|
if (iRet == 0) { /* end of command */
|
||||||
|
return AQU_POP_CMD;
|
||||||
|
}
|
||||||
|
return iRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ORHVPS_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) {
|
||||||
|
if (event == AQU_TIMEOUT) {
|
||||||
|
/* handle command timeout */
|
||||||
|
pTxn->txn_status = ATX_TIMEOUT;
|
||||||
|
return AQU_POP_CMD;
|
||||||
|
}
|
||||||
|
return AQU_POP_CMD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ORHVPS_PrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_len, int rsp_len) {
|
||||||
|
txn->out_buf = (char*) malloc(cmd_len);
|
||||||
|
if (txn->out_buf == NULL) {
|
||||||
|
SICSLogWrite("ERROR: Out of memory in ORHVPS_PrepareTxn", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(txn->out_buf, cmd, cmd_len);
|
||||||
|
txn->out_len = cmd_len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ORHVPSInitProtocol(SicsInterp *pSics) {
|
||||||
|
if (ORHVPS_Protocol == NULL) {
|
||||||
|
ORHVPS_Protocol = AsyncProtocolCreate(pSics, "ORHVPS", NULL, NULL);
|
||||||
|
ORHVPS_Protocol->sendCommand = ORHVPS_Tx;
|
||||||
|
ORHVPS_Protocol->handleInput = ORHVPS_Rx;
|
||||||
|
ORHVPS_Protocol->handleEvent = ORHVPS_Ev;
|
||||||
|
ORHVPS_Protocol->prepareTxn = ORHVPS_PrepareTxn;
|
||||||
|
ORHVPS_Protocol->killPrivate = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_period(float max, float rate) {
|
||||||
|
//return (int) roundf(1000 * (priv->fMax / 63.0) / priv->fRate);
|
||||||
|
return (int) roundf((rate * 60 * 1000) / 63.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pEVDriver CreateORHVPSDriver(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
pEVDriver self = NULL;
|
||||||
|
pORHVPSDriv priv = NULL;
|
||||||
|
|
||||||
|
if (argc < 1)
|
||||||
|
return NULL;
|
||||||
|
self = CreateEVDriver(argc, argv);
|
||||||
|
if (!self)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
priv = (pORHVPSDriv)malloc(sizeof(ORHVPSDriv));
|
||||||
|
if(!priv) {
|
||||||
|
DeleteEVDriver(self);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(priv,0,sizeof(ORHVPSDriv));
|
||||||
|
priv->fValue = 0.0;
|
||||||
|
|
||||||
|
if (!AsyncUnitCreate(argv[0], &priv->asyncUnit)) {
|
||||||
|
char line[132];
|
||||||
|
snprintf(line, 132, "Error: did not find AsyncQueue %s for Device %s", argv[1], argv[0]);
|
||||||
|
DeleteEVDriver(self);
|
||||||
|
free(priv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
AsyncUnitSetNotify(priv->asyncUnit, self, ORHVPSNotify);
|
||||||
|
|
||||||
|
/* initialise function pointers */
|
||||||
|
self->SetValue = ORHVPSSetValue;
|
||||||
|
self->GetValue = ORHVPSGetValue;
|
||||||
|
self->Send = ORHVPSSend;
|
||||||
|
self->GetError = ORHVPSError;
|
||||||
|
self->TryFixIt = ORHVPSFix;
|
||||||
|
self->Init = ORHVPSInit;
|
||||||
|
self->Close = ORHVPSClose;
|
||||||
|
|
||||||
|
self->pPrivate = priv;
|
||||||
|
self->KillPrivate = ORHVPSKillPrivate;
|
||||||
|
|
||||||
|
priv->fsm.context = self;
|
||||||
|
priv->fsm.state_name = state_name;
|
||||||
|
priv->fsm.event_name = event_name;
|
||||||
|
priv->name = strdup(argv[0]);
|
||||||
|
priv->fMax = 2400.0;
|
||||||
|
priv->fRate = 10.0;
|
||||||
|
priv->iPeriod = get_period(priv->fMax, priv->fRate);
|
||||||
|
|
||||||
|
fsm_change_state(&priv->fsm, ORHVState_Unknown);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ORHVPSRegister(pEVControl self, pEVDriver driv)
|
||||||
|
{
|
||||||
|
pORHVPSDriv priv = (pORHVPSDriv) driv->pPrivate;
|
||||||
|
priv->controller = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ORHVPSWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[])
|
||||||
|
{
|
||||||
|
pEVControl self = (pEVControl)pData;
|
||||||
|
pEVDriver driv = self->pDriv;
|
||||||
|
pORHVPSDriv priv = (pORHVPSDriv) driv->pPrivate;
|
||||||
|
assert(self);
|
||||||
|
assert(pCon);
|
||||||
|
assert(pSics);
|
||||||
|
|
||||||
|
if(argc < 2)
|
||||||
|
{
|
||||||
|
return EVControlWrapper(pCon,pSics,pData,argc,argv);
|
||||||
|
}
|
||||||
|
if (strcasecmp("send", argv[1]) == 0) {
|
||||||
|
char cmd[CMDLEN];
|
||||||
|
int cmd_len;
|
||||||
|
char rsp[CMDLEN];
|
||||||
|
int rsp_len;
|
||||||
|
int idx = 0;
|
||||||
|
int i;
|
||||||
|
cmd[idx] = '\0';
|
||||||
|
for (i = 2; i < argc; ++i) {
|
||||||
|
int j, k;
|
||||||
|
if (i > 2 && idx < CMDLEN)
|
||||||
|
cmd[idx++] = ' ';
|
||||||
|
for (j = 0; argv[i][j]; ++j) {
|
||||||
|
if (argv[i][j] == '\\') {
|
||||||
|
k = 0;
|
||||||
|
if (isxdigit(argv[i][j+1]) && isxdigit(argv[i][j+2])) {
|
||||||
|
if (argv[i][j+1] >= '0' && argv[i][j+1] <= '9')
|
||||||
|
k = (argv[i][j+1] - '0') << 4;
|
||||||
|
else if (argv[i][j+1] >= 'a' && argv[i][j+1] <= 'f')
|
||||||
|
k = (argv[i][j+1] - 'a' + 10) << 4;
|
||||||
|
else if (argv[i][j+1] >= 'A' && argv[i][j+1] <= 'F')
|
||||||
|
k = (argv[i][j+1] - 'A' + 10) << 4;
|
||||||
|
if (argv[i][j+2] >= '0' && argv[i][j+2] <= '9')
|
||||||
|
k += (argv[i][j+2] - '0');
|
||||||
|
else if (argv[i][j+2] >= 'a' && argv[i][j+2] <= 'f')
|
||||||
|
k += (argv[i][j+2] - 'a' + 10);
|
||||||
|
else if (argv[i][j+2] >= 'A' && argv[i][j+2] <= 'F')
|
||||||
|
k += (argv[i][j+2] - 'A' + 10);
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
k = argv[i][j];
|
||||||
|
if (idx < CMDLEN)
|
||||||
|
cmd[idx++] = k;
|
||||||
|
}
|
||||||
|
if (idx < CMDLEN)
|
||||||
|
cmd[idx] = '\0';
|
||||||
|
cmd_len = idx;
|
||||||
|
}
|
||||||
|
rsp_len = CMDLEN;
|
||||||
|
ORHV_SendReceive(priv, cmd, cmd_len, rsp, &rsp_len);
|
||||||
|
idx = 0;
|
||||||
|
for (i = 0; i < rsp_len; ++i) {
|
||||||
|
if (rsp[i] < 32 || rsp[i] > 126) {
|
||||||
|
snprintf(&cmd[idx], 3, "\\%02x", rsp[i]);
|
||||||
|
idx += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cmd[idx++] = rsp[i];
|
||||||
|
}
|
||||||
|
cmd[idx] = '\0';
|
||||||
|
SCWrite(pCon, cmd, eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcasecmp("max", argv[1]) == 0) {
|
||||||
|
char rsp[CMDLEN];
|
||||||
|
if (argc > 2) {
|
||||||
|
float max = atof(argv[2]);
|
||||||
|
if (max >= 0.0 && max <= 2600.0) {
|
||||||
|
priv->fMax = max;
|
||||||
|
priv->iPeriod = get_period(priv->fMax, priv->fRate);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SCWrite(pCon, "max must be between 0.0 and 2600.0", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf(rsp, CMDLEN, "%s.max = %8.2f", priv->name, priv->fMax);
|
||||||
|
SCWrite(pCon, rsp, eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcasecmp("debug", argv[1]) == 0) {
|
||||||
|
char rsp[CMDLEN];
|
||||||
|
if (argc > 2) {
|
||||||
|
int debug = atoi(argv[2]);
|
||||||
|
if (debug != 0)
|
||||||
|
priv->fsm.debug = true;
|
||||||
|
else
|
||||||
|
priv->fsm.debug = false;
|
||||||
|
}
|
||||||
|
snprintf(rsp, CMDLEN, "%s.debug = %d", priv->name, priv->fsm.debug ? 1 : 0);
|
||||||
|
SCWrite(pCon, rsp, eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcasecmp("rate", argv[1]) == 0) {
|
||||||
|
char rsp[CMDLEN];
|
||||||
|
if (argc > 2) {
|
||||||
|
float rate = atof(argv[2]);
|
||||||
|
if (rate >= 1.0 && rate <= 10.0) {
|
||||||
|
priv->fRate = rate;
|
||||||
|
priv->iPeriod = get_period(priv->fMax, priv->fRate);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SCWrite(pCon, "rate must be between 1.0 and 10.0", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf(rsp, CMDLEN, "%s.rate = %8.2f", priv->name, priv->fRate);
|
||||||
|
SCWrite(pCon, rsp, eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcasecmp("period", argv[1]) == 0) {
|
||||||
|
char rsp[CMDLEN];
|
||||||
|
if (argc > 2) {
|
||||||
|
SCWrite(pCon, "cannot set period, set max and rate instead", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
snprintf(rsp, CMDLEN, "%s.period = %6d", priv->name, priv->iPeriod);
|
||||||
|
SCWrite(pCon, rsp, eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcasecmp("reset", argv[1]) == 0) {
|
||||||
|
char rsp[CMDLEN];
|
||||||
|
fsm_change_state(&priv->fsm, ORHVState_Unknown);
|
||||||
|
snprintf(rsp, CMDLEN, "%s.reset = 1", priv->name);
|
||||||
|
SCWrite(pCon, rsp, eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return EVControlWrapper(pCon,pSics,pData,argc,argv);
|
||||||
|
}
|
||||||
|
|
||||||
34
site_ansto/orhvps.h
Normal file
34
site_ansto/orhvps.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
O R H V P S
|
||||||
|
|
||||||
|
Support for Oak Ridge High Voltage Power Supply for SICS.
|
||||||
|
|
||||||
|
The meaning and working of the functions defined is as desribed for a
|
||||||
|
general environment controller.
|
||||||
|
|
||||||
|
Douglas Clowes, December 2007
|
||||||
|
|
||||||
|
copyright: see implementation file.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
#ifndef SICSORHVPS
|
||||||
|
#define SICSORHVPS
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "sics.h"
|
||||||
|
#include <obpar.h>
|
||||||
|
#include <evcontroller.h>
|
||||||
|
#include <evcontroller.i>
|
||||||
|
#include "evdriver.h"
|
||||||
|
|
||||||
|
void ORHVPSInitProtocol(SicsInterp *pSics);
|
||||||
|
|
||||||
|
pEVDriver CreateORHVPSDriver(int argc, char *argv[]);
|
||||||
|
|
||||||
|
void ORHVPSRegister(pEVControl self, pEVDriver driv);
|
||||||
|
|
||||||
|
int ORHVPSWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
|
#endif
|
||||||
|
|
||||||
Reference in New Issue
Block a user