use crate::error::{CaError, CaResult};
use crate::server::record::{FieldDesc, ProcessOutcome, Record};
use crate::types::{DbFieldType, EpicsValue};
pub struct AiRecord {
pub val: f64,
pub egu: String,
pub hopr: f64,
pub lopr: f64,
pub prec: i16,
pub rval: i32,
pub oraw: i32, pub linr: i16, pub eguf: f64,
pub egul: f64,
pub eslo: f64, pub eoff: f64, pub roff: i32,
pub aslo: f64, pub aoff: f64,
pub smoo: f64, pub adel: f64,
pub mdel: f64,
pub lalm: f64,
pub alst: f64,
pub mlst: f64,
pub init: bool,
skip_convert: bool,
pub simm: i16,
pub siml: String,
pub siol: String,
pub sims: i16,
}
impl Default for AiRecord {
fn default() -> Self {
Self {
val: 0.0,
egu: String::new(),
hopr: 0.0,
lopr: 0.0,
prec: 0,
rval: 0,
oraw: 0,
linr: 0,
eguf: 0.0,
egul: 0.0,
eslo: 1.0,
eoff: 0.0,
roff: 0,
aslo: 1.0,
aoff: 0.0,
smoo: 0.0,
adel: 0.0,
mdel: 0.0,
lalm: 0.0,
alst: 0.0,
mlst: 0.0,
init: false,
skip_convert: false,
simm: 0,
siml: String::new(),
siol: String::new(),
sims: 0,
}
}
}
impl AiRecord {
pub fn new(val: f64) -> Self {
Self {
val,
..Default::default()
}
}
}
static FIELDS: &[FieldDesc] = &[
FieldDesc {
name: "VAL",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "EGU",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "HOPR",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "LOPR",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "PREC",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "RVAL",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "ORAW",
dbf_type: DbFieldType::Long,
read_only: true,
},
FieldDesc {
name: "LINR",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "EGUF",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "EGUL",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "ESLO",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "EOFF",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "ROFF",
dbf_type: DbFieldType::Long,
read_only: false,
},
FieldDesc {
name: "ASLO",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "AOFF",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "SMOO",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "ADEL",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "MDEL",
dbf_type: DbFieldType::Double,
read_only: false,
},
FieldDesc {
name: "LALM",
dbf_type: DbFieldType::Double,
read_only: true,
},
FieldDesc {
name: "ALST",
dbf_type: DbFieldType::Double,
read_only: true,
},
FieldDesc {
name: "MLST",
dbf_type: DbFieldType::Double,
read_only: true,
},
FieldDesc {
name: "INIT",
dbf_type: DbFieldType::Char,
read_only: true,
},
FieldDesc {
name: "SIMM",
dbf_type: DbFieldType::Short,
read_only: false,
},
FieldDesc {
name: "SIML",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "SIOL",
dbf_type: DbFieldType::String,
read_only: false,
},
FieldDesc {
name: "SIMS",
dbf_type: DbFieldType::Short,
read_only: false,
},
];
impl Record for AiRecord {
fn record_type(&self) -> &'static str {
"ai"
}
fn init_record(&mut self, pass: u8) -> CaResult<()> {
if pass == 0 {
let saved_eoff = self.eoff;
let saved_eslo = self.eslo;
if self.eslo == 1.0 && self.eoff == 0.0 {
self.eoff = self.egul;
}
if self.linr == 1 {
self.eoff = saved_eoff;
self.eslo = saved_eslo;
}
self.mlst = self.val;
self.alst = self.val;
self.lalm = self.val;
self.oraw = self.rval;
}
Ok(())
}
fn process(&mut self) -> CaResult<ProcessOutcome> {
if !self.skip_convert {
let mut v = (self.rval as f64) + (self.roff as f64);
if self.aslo != 0.0 {
v *= self.aslo;
}
v += self.aoff;
match self.linr {
0 => {} 1 | 2 => {
v = v * self.eslo + self.eoff;
}
_ => {} }
if self.smoo != 0.0 && self.init && self.val.is_finite() {
self.val = v * (1.0 - self.smoo) + self.val * self.smoo;
} else {
self.val = v;
}
} self.skip_convert = false;
self.oraw = self.rval;
self.init = true;
Ok(ProcessOutcome::complete())
}
fn get_field(&self, name: &str) -> Option<EpicsValue> {
match name {
"VAL" => Some(EpicsValue::Double(self.val)),
"EGU" => Some(EpicsValue::String(self.egu.clone())),
"HOPR" => Some(EpicsValue::Double(self.hopr)),
"LOPR" => Some(EpicsValue::Double(self.lopr)),
"PREC" => Some(EpicsValue::Short(self.prec)),
"RVAL" => Some(EpicsValue::Long(self.rval)),
"ORAW" => Some(EpicsValue::Long(self.oraw)),
"LINR" => Some(EpicsValue::Short(self.linr)),
"EGUF" => Some(EpicsValue::Double(self.eguf)),
"EGUL" => Some(EpicsValue::Double(self.egul)),
"ESLO" => Some(EpicsValue::Double(self.eslo)),
"EOFF" => Some(EpicsValue::Double(self.eoff)),
"ROFF" => Some(EpicsValue::Long(self.roff)),
"ASLO" => Some(EpicsValue::Double(self.aslo)),
"AOFF" => Some(EpicsValue::Double(self.aoff)),
"SMOO" => Some(EpicsValue::Double(self.smoo)),
"ADEL" => Some(EpicsValue::Double(self.adel)),
"MDEL" => Some(EpicsValue::Double(self.mdel)),
"LALM" => Some(EpicsValue::Double(self.lalm)),
"ALST" => Some(EpicsValue::Double(self.alst)),
"MLST" => Some(EpicsValue::Double(self.mlst)),
"INIT" => Some(EpicsValue::Char(if self.init { 1 } else { 0 })),
"SIMM" => Some(EpicsValue::Short(self.simm)),
"SIML" => Some(EpicsValue::String(self.siml.clone())),
"SIOL" => Some(EpicsValue::String(self.siol.clone())),
"SIMS" => Some(EpicsValue::Short(self.sims)),
_ => None,
}
}
fn put_field(&mut self, name: &str, value: EpicsValue) -> CaResult<()> {
match name {
"VAL" => match value {
EpicsValue::Double(v) => {
self.val = v;
Ok(())
}
EpicsValue::Long(v) => {
self.val = v as f64;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"EGU" => match value {
EpicsValue::String(v) => {
self.egu = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"HOPR" => match value {
EpicsValue::Double(v) => {
self.hopr = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"LOPR" => match value {
EpicsValue::Double(v) => {
self.lopr = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"PREC" => match value {
EpicsValue::Short(v) => {
self.prec = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"RVAL" => match value {
EpicsValue::Long(v) => {
self.rval = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"LINR" => match value {
EpicsValue::Short(v) => {
self.linr = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"EGUF" => match value {
EpicsValue::Double(v) => {
self.eguf = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"EGUL" => match value {
EpicsValue::Double(v) => {
self.egul = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"ESLO" => match value {
EpicsValue::Double(v) => {
self.eslo = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"EOFF" => match value {
EpicsValue::Double(v) => {
self.eoff = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"ROFF" => match value {
EpicsValue::Long(v) => {
self.roff = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"ASLO" => match value {
EpicsValue::Double(v) => {
self.aslo = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"AOFF" => match value {
EpicsValue::Double(v) => {
self.aoff = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"SMOO" => match value {
EpicsValue::Double(v) => {
self.smoo = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"ADEL" => match value {
EpicsValue::Double(v) => {
self.adel = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"MDEL" => match value {
EpicsValue::Double(v) => {
self.mdel = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"LALM" => match value {
EpicsValue::Double(v) => {
self.lalm = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"ALST" => match value {
EpicsValue::Double(v) => {
self.alst = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"MLST" => match value {
EpicsValue::Double(v) => {
self.mlst = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"SIMM" => match value {
EpicsValue::Short(v) => {
self.simm = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"SIML" => match value {
EpicsValue::String(v) => {
self.siml = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"SIOL" => match value {
EpicsValue::String(v) => {
self.siol = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
"SIMS" => match value {
EpicsValue::Short(v) => {
self.sims = v;
Ok(())
}
_ => Err(CaError::TypeMismatch(name.into())),
},
_ => Err(CaError::FieldNotFound(name.into())),
}
}
fn field_list(&self) -> &'static [FieldDesc] {
FIELDS
}
fn set_device_did_compute(&mut self, did_compute: bool) {
self.skip_convert = did_compute;
}
}