use crate::dms::multi::{
Color, ColorClassic, ColorScheme, JustificationLine, JustificationPage, Tag,
};
use enumflags2::BitFlags;
#[derive(Debug, thiserror::Error)]
pub enum CfgError {
#[error("Invalid page config")]
InvalidPageCfg,
#[error("Invalid sign dimensions")]
InvalidDimensions,
}
#[enumflags2::bitflags]
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DmsSignAccess {
Other = 1 << 0,
WalkIn = 1 << 1,
Rear = 1 << 2,
Front = 1 << 3,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DmsSignType {
Other = 1,
Bos,
Cms,
VmsChar,
VmsLine,
VmsFull,
PortableOther = 129,
PortableBos,
PortableCms,
PortableVmsChar,
PortableVmsLine,
PortableVmsFull,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DmsLegend {
#[deprecated]
Other = 1,
NoLegend,
LegendExists,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DmsBeaconType {
Other = 1,
None,
OneBeacon,
TwoBeaconSyncFlash,
TwoBeaconsOppFlash,
FourBeaconSyncFlash,
FourBeaconAltRowFlash,
FourBeaconAltColumnFlash,
FourBeaconAltDiagonalFlash,
FourBeaconNoSyncFlash,
OneBeaconStrobe,
TwoBeaconStrobe,
FourBeaconStrobe,
}
#[enumflags2::bitflags]
#[repr(u16)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DmsSignTechnology {
Other = 1 << 0,
Led = 1 << 1,
FlipDisk = 1 << 2,
FiberOptics = 1 << 3,
Shuttered = 1 << 4,
Bulb = 1 << 5,
Drum = 1 << 6,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CharacterSet {
Other = 1,
EightBit,
}
#[derive(Clone)]
pub struct SignCfg {
pub sign_access: BitFlags<DmsSignAccess>,
pub sign_type: DmsSignType,
pub sign_height: u16,
pub sign_width: u16,
pub horizontal_border: u16,
pub vertical_border: u16,
pub legend: DmsLegend,
pub beacon_type: DmsBeaconType,
pub sign_technology: BitFlags<DmsSignTechnology>,
}
#[derive(Clone)]
pub struct VmsCfg {
pub char_height_pixels: u8,
pub char_width_pixels: u8,
pub sign_height_pixels: u16,
pub sign_width_pixels: u16,
pub horizontal_pitch: u8,
pub vertical_pitch: u8,
pub monochrome_color: [u8; 6],
}
#[derive(Clone)]
pub struct MultiCfg {
pub default_background_rgb: Color,
pub default_foreground_rgb: Color,
pub default_flash_on: u8,
pub default_flash_off: u8,
pub default_font: u8,
pub default_justification_line: JustificationLine,
pub default_justification_page: JustificationPage,
pub default_page_on_time: u8,
pub default_page_off_time: u8,
pub default_character_set: CharacterSet,
pub color_scheme: ColorScheme,
pub supported_multi_tags: BitFlags<Tag>,
pub max_number_pages: u8,
pub max_multi_string_length: u16,
}
impl Default for SignCfg {
fn default() -> Self {
SignCfg {
sign_access: BitFlags::empty(),
sign_type: DmsSignType::VmsChar,
sign_height: 1650,
sign_width: 2920,
horizontal_border: 60,
vertical_border: 60,
legend: DmsLegend::NoLegend,
beacon_type: DmsBeaconType::None,
sign_technology: DmsSignTechnology::Led.into(),
}
}
}
impl SignCfg {
pub fn validate(&self, vms_cfg: &VmsCfg) -> Result<(), CfgError> {
if self.is_width_valid(vms_cfg) && self.is_height_valid(vms_cfg) {
Ok(())
} else {
Err(CfgError::InvalidDimensions)
}
}
fn is_width_valid(&self, vms_cfg: &VmsCfg) -> bool {
self.horizontal_border
+ vms_cfg.sign_width_pixels * u16::from(vms_cfg.horizontal_pitch)
<= self.sign_width
}
fn is_height_valid(&self, vms_cfg: &VmsCfg) -> bool {
self.vertical_border
+ vms_cfg.sign_height_pixels * u16::from(vms_cfg.vertical_pitch)
<= self.sign_height
}
}
impl Default for VmsCfg {
fn default() -> Self {
VmsCfg {
char_height_pixels: 7,
char_width_pixels: 5,
sign_height_pixels: 21,
sign_width_pixels: 40,
horizontal_pitch: 70,
vertical_pitch: 70,
monochrome_color: [0xFF, 0x70, 0xE0, 0, 0, 0],
}
}
}
impl Default for MultiCfg {
fn default() -> Self {
let supported_multi_tags = Tag::Cb
| Tag::Cf
| Tag::Fo
| Tag::G
| Tag::Hc
| Tag::Jl
| Tag::Jp
| Tag::Nl
| Tag::Np
| Tag::Pt
| Tag::Sc
| Tag::Tr
| Tag::Cr
| Tag::Pb;
MultiCfg {
default_background_rgb: Color::Legacy(ColorClassic::Black.into()),
default_foreground_rgb: Color::Legacy(ColorClassic::Amber.into()),
default_flash_on: 5,
default_flash_off: 5,
default_font: 1,
default_justification_line: JustificationLine::Center,
default_justification_page: JustificationPage::Middle,
default_page_on_time: 30,
default_page_off_time: 0,
default_character_set: CharacterSet::EightBit,
color_scheme: ColorScheme::Monochrome1Bit,
supported_multi_tags,
max_number_pages: 4,
max_multi_string_length: 65535,
}
}
}
impl MultiCfg {
pub fn validate(&self) -> Result<(), CfgError> {
if self.max_number_pages == 0
|| self.max_number_pages > 1
&& !self.supported_multi_tags.contains(Tag::Np)
{
return Err(CfgError::InvalidPageCfg);
}
Ok(())
}
}