use crate::alpha16::{Adc16ChannelId, Adc32ChannelId, ChannelId};
use std::num::ParseIntError;
use thiserror::Error;
pub const ADC16_SUPPRESSION_THRESHOLD_JSON_PTR: &str =
"/Equipment/CTRL/Settings/ADC/adc16_sthreshold";
pub const ADC32_SUPPRESSION_ENABLE_JSON_PTR: &str =
"/Equipment/CTRL/Settings/ADC/adc32_ch_suppress";
pub const ADC32_SUPPRESSION_THRESHOLD_JSON_PTR: &str =
"/Equipment/CTRL/Settings/ADC/adc32_sthreshold";
pub const BSC_PULSER_ENABLE_JSON_PTR: &str = "/Equipment/CTRL/Settings/BscPulserEnable";
pub const FIELD_WIRE_PULSER_ENABLE_JSON_PTR: &str = "/Equipment/CTRL/Settings/FwPulserEnable";
pub const PULSER_ENABLE_JSON_PTR: &str = "/Equipment/CTRL/Settings/Pulser/Enable";
pub const PWB_FORCE_CHANNELS_JSON_PTR: &str = "/Equipment/CTRL/Settings/PWB/ch_force";
pub const PWB_SUPPRESSION_THRESHOLD_JSON_PTR: &str = "/Equipment/CTRL/Settings/PWB/ch_threshold";
pub const TRIGGER_PULSER_JSON_PTR: &str = "/Equipment/CTRL/Settings/TrigSrc/TrigPulser";
pub const TRIGGER_SOURCES_JSON_PTR: &str = "/Equipment/CTRL/Settings/TrigSrc";
#[derive(Error, Debug)]
#[error("unknown conversion from unsigned `{input}` to EventId")]
pub struct TryEventIdFromUnsignedError {
input: u16,
}
#[derive(Clone, Copy, Debug)]
pub enum EventId {
Main,
Chronobox,
Sequencer2,
}
impl TryFrom<u16> for EventId {
type Error = TryEventIdFromUnsignedError;
fn try_from(num: u16) -> Result<Self, Self::Error> {
match num {
1 => Ok(EventId::Main),
4 => Ok(EventId::Chronobox),
8 => Ok(EventId::Sequencer2),
_ => Err(TryEventIdFromUnsignedError { input: num }),
}
}
}
#[derive(Error, Debug)]
pub enum ParseAlpha16BankNameError {
#[error("input string `{input}` doesn't match Alpha16BankName pattern")]
PatternMismatch { input: String },
#[error("unknown board id")]
UnknownBoardId(#[from] crate::alpha16::ParseBoardIdError),
#[error("unknown channel id")]
UnknownChannelId(#[from] ParseIntError),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Adc16BankName {
board_id: crate::alpha16::BoardId,
channel_id: Adc16ChannelId,
}
impl Adc16BankName {
pub fn board_id(&self) -> crate::alpha16::BoardId {
self.board_id
}
pub fn channel_id(&self) -> Adc16ChannelId {
self.channel_id
}
}
impl TryFrom<&str> for Adc16BankName {
type Error = ParseAlpha16BankNameError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
if !name.starts_with('B')
|| name.len() != 4
|| !name.chars().all(|c| c.is_ascii_alphanumeric())
|| name.chars().any(|c| c.is_ascii_lowercase())
{
return Err(Self::Error::PatternMismatch {
input: name.to_string(),
});
}
let board_id = crate::alpha16::BoardId::try_from(&name[1..][..2])?;
let channel_id = Adc16ChannelId::try_from(u8::from_str_radix(&name[3..], 16)?).unwrap();
Ok(Adc16BankName {
board_id,
channel_id,
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Adc32BankName {
board_id: crate::alpha16::BoardId,
channel_id: Adc32ChannelId,
}
impl Adc32BankName {
pub fn board_id(&self) -> crate::alpha16::BoardId {
self.board_id
}
pub fn channel_id(&self) -> Adc32ChannelId {
self.channel_id
}
}
impl TryFrom<&str> for Adc32BankName {
type Error = ParseAlpha16BankNameError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
if !name.starts_with('C')
|| name.len() != 4
|| !name.chars().all(|c| c.is_ascii_alphanumeric())
|| name.chars().any(|c| c.is_ascii_lowercase())
{
return Err(Self::Error::PatternMismatch {
input: name.to_string(),
});
}
let board_id = crate::alpha16::BoardId::try_from(&name[1..][..2])?;
let channel_id = Adc32ChannelId::try_from(u8::from_str_radix(&name[3..], 32)?).unwrap();
Ok(Adc32BankName {
board_id,
channel_id,
})
}
}
#[derive(Clone, Copy, Debug)]
pub enum Alpha16BankName {
A16(Adc16BankName),
A32(Adc32BankName),
}
impl TryFrom<&str> for Alpha16BankName {
type Error = ParseAlpha16BankNameError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
match name.chars().next() {
Some('C') => Ok(Self::A32(Adc32BankName::try_from(name)?)),
Some('B') => Ok(Self::A16(Adc16BankName::try_from(name)?)),
_ => Err(Self::Error::PatternMismatch {
input: name.to_string(),
}),
}
}
}
impl Alpha16BankName {
pub fn board_id(&self) -> crate::alpha16::BoardId {
match self {
Self::A16(name) => name.board_id,
Self::A32(name) => name.board_id,
}
}
pub fn channel_id(&self) -> ChannelId {
match self {
Self::A16(name) => ChannelId::A16(name.channel_id),
Self::A32(name) => ChannelId::A32(name.channel_id),
}
}
}
#[derive(Error, Debug)]
pub enum ParsePadwingBankNameError {
#[error("input string `{input}` doesn't match PadwingBankName pattern")]
PatternMismatch { input: String },
#[error("unknown board id")]
UnknownBoardId(#[from] crate::padwing::ParseBoardIdError),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct PadwingBankName {
board_id: crate::padwing::BoardId,
}
impl PadwingBankName {
pub fn board_id(&self) -> crate::padwing::BoardId {
self.board_id
}
}
impl TryFrom<&str> for PadwingBankName {
type Error = ParsePadwingBankNameError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
if !name.starts_with("PC")
|| name.len() != 4
|| !name[2..].chars().all(|c| c.is_ascii_digit())
{
return Err(Self::Error::PatternMismatch {
input: name.to_string(),
});
}
let board_id = crate::padwing::BoardId::try_from(&name[2..])?;
Ok(PadwingBankName { board_id })
}
}
#[derive(Error, Debug)]
pub enum ParseTriggerBankNameError {
#[error("input string `{input}` doesn't match TriggerBankName pattern")]
PatternMismatch { input: String },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TriggerBankName;
impl TryFrom<&str> for TriggerBankName {
type Error = ParseTriggerBankNameError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
if name != "ATAT" {
return Err(Self::Error::PatternMismatch {
input: name.to_string(),
});
}
Ok(TriggerBankName)
}
}
#[derive(Error, Debug)]
pub enum ParseTrb3BankNameError {
#[error("input string `{input}` doesn't match Trb3BankName pattern")]
PatternMismatch { input: String },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Trb3BankName;
impl TryFrom<&str> for Trb3BankName {
type Error = ParseTrb3BankNameError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
if name != "TRBA" {
return Err(Self::Error::PatternMismatch {
input: name.to_string(),
});
}
Ok(Trb3BankName)
}
}
#[derive(Error, Debug)]
pub enum ParseSeq2BankNameError {
#[error("input string `{input}` doesn't match Seq2BankName pattern")]
PatternMismatch { input: String },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Seq2BankName;
impl TryFrom<&str> for Seq2BankName {
type Error = ParseSeq2BankNameError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
if name != "SEQ2" {
return Err(Self::Error::PatternMismatch {
input: name.to_string(),
});
}
Ok(Seq2BankName)
}
}
#[derive(Error, Debug)]
pub enum ParseMcVertexBankNameError {
#[error("input string `{input}` doesn't match McVertexBankName pattern")]
PatternMismatch { input: String },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct McVertexBankName;
impl TryFrom<&str> for McVertexBankName {
type Error = ParseMcVertexBankNameError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
if name != "MCVX" {
return Err(Self::Error::PatternMismatch {
input: name.to_string(),
});
}
Ok(McVertexBankName)
}
}
#[derive(Error, Debug)]
pub enum ParseMainEventBankNameError {
#[error("input string `{input}` doesn't match any main event bank name pattern")]
PatternMismatch { input: String },
#[error("bad alpha16 bank name")]
BadAlpha16(#[from] ParseAlpha16BankNameError),
#[error("bad padwing bank name")]
BadPadwing(#[from] ParsePadwingBankNameError),
#[error("bad trigger bank name")]
BadTrigger(#[from] ParseTriggerBankNameError),
#[error("bad trb3 bank name")]
BadTrb3(#[from] ParseTrb3BankNameError),
#[error("bad mc vertex bank name")]
BadMcVertex(#[from] ParseMcVertexBankNameError),
}
#[derive(Clone, Copy, Debug)]
pub enum MainEventBankName {
Alpha16(Alpha16BankName),
Padwing(PadwingBankName),
Trg(TriggerBankName),
Trb3(Trb3BankName),
McVertex(McVertexBankName),
}
impl TryFrom<&str> for MainEventBankName {
type Error = ParseMainEventBankNameError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
match name.chars().next() {
Some('A') => Ok(Self::Trg(TriggerBankName::try_from(name)?)),
Some('B' | 'C') => Ok(Self::Alpha16(Alpha16BankName::try_from(name)?)),
Some('P') => Ok(Self::Padwing(PadwingBankName::try_from(name)?)),
Some('T') => Ok(Self::Trb3(Trb3BankName::try_from(name)?)),
Some('M') => Ok(Self::McVertex(McVertexBankName::try_from(name)?)),
_ => Err(Self::Error::PatternMismatch {
input: name.to_string(),
}),
}
}
}
#[derive(Error, Debug)]
pub enum ParseChronoboxBankNameError {
#[error("input string `{input}` doesn't match ChronoboxBankName pattern")]
PatternMismatch { input: String },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ChronoboxBankName {
pub board_id: crate::chronobox::BoardId,
}
impl TryFrom<&str> for ChronoboxBankName {
type Error = ParseChronoboxBankNameError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
match name {
"CBF1" => Ok(Self {
board_id: crate::chronobox::BoardId::try_from("cb01").unwrap(),
}),
"CBF2" => Ok(Self {
board_id: crate::chronobox::BoardId::try_from("cb02").unwrap(),
}),
"CBF3" => Ok(Self {
board_id: crate::chronobox::BoardId::try_from("cb03").unwrap(),
}),
"CBF4" => Ok(Self {
board_id: crate::chronobox::BoardId::try_from("cb04").unwrap(),
}),
_ => Err(Self::Error::PatternMismatch {
input: name.to_string(),
}),
}
}
}
#[cfg(test)]
mod tests;