use crate::soc::{Access, FieldSpec, find_field, same_name};
use super::family::{Family, Part, Slot};
use super::{CHANNELS, INPUTS, Tim};
pub(super) const BYTE: u64 = 0xFF;
const ABSENT: FieldSpec = FieldSpec::new("", 0, 0, Access::ReadWrite);
const fn lookup(part: &Part, register: &str, field: &str) -> Option<&'static FieldSpec> {
let mut name = field;
let mut spelling = 0;
while spelling < part.spellings.len() {
let respelled = &part.spellings[spelling];
if same_name(respelled.register, register) && same_name(respelled.manual, field) {
name = respelled.file;
}
spelling += 1;
}
let mut table = 0;
while table < part.tables.len() {
if let Some(found) = find_field(part.tables[table], register, name) {
return Some(found);
}
table += 1;
}
None
}
const fn both(part: &Part, register: &str, field: &str) -> &'static FieldSpec {
match lookup(part, register, field) {
Some(found) => found,
None => panic!("both manuals give the timers this field"),
}
}
const fn either(part: &Part, register: &str, field: &str) -> &'static FieldSpec {
match lookup(part, register, field) {
Some(found) => found,
None => &ABSENT,
}
}
#[derive(Debug, Clone, Copy)]
pub(super) struct Split {
low: &'static FieldSpec,
high: &'static FieldSpec,
}
impl Split {
pub(super) const fn new(low: &'static FieldSpec, high: &'static FieldSpec) -> Self {
Self { low, high }
}
pub(super) const fn get(&self, register_value: u64) -> u64 {
self.low.get(register_value) | (self.high.get(register_value) << self.low.width)
}
pub(super) const fn set(&self, register_value: u64, value: u64) -> u64 {
let low_mask = (1u64 << self.low.width) - 1;
self.high.set(
self.low.set(register_value, value & low_mask),
value >> self.low.width,
)
}
pub(super) const fn mask(&self) -> u64 {
self.low.mask() | self.high.mask()
}
}
pub(super) const SMS_DISABLED: u64 = 0b0000;
pub(super) const SMS_ENCODER_1: u64 = 0b0001;
pub(super) const SMS_ENCODER_2: u64 = 0b0010;
pub(super) const SMS_ENCODER_3: u64 = 0b0011;
pub(super) const SMS_RESET: u64 = 0b0100;
pub(super) const SMS_GATED: u64 = 0b0101;
pub(super) const SMS_TRIGGER: u64 = 0b0110;
pub(super) const SMS_EXTERNAL_CLOCK_1: u64 = 0b0111;
pub(super) const SMS_COMBINED: u64 = 0b1000;
pub(super) const TS_LAST_LOW_INTERNAL: u64 = 0b00011;
pub(super) const TS_TI1_EDGES: u64 = 0b00100;
pub(super) const TS_TI1FP1: u64 = 0b00101;
pub(super) const TS_TI2FP2: u64 = 0b00110;
pub(super) const TS_ETRF: u64 = 0b00111;
pub(super) const TS_FIRST_HIGH_INTERNAL: u64 = 0b01000;
pub(super) const TS_LAST_INTERNAL: u64 = 0b01100;
pub(super) const TS_RESERVED: u64 = 0b01101;
pub(super) const CMS_EDGE_ALIGNED: u64 = 0b00;
pub(super) const CMS_FLAGS_DOWN: u64 = 0b01;
pub(super) const CMS_FLAGS_UP: u64 = 0b10;
pub(super) const MMS_RESET: u64 = 0b000;
pub(super) const MMS_ENABLE: u64 = 0b001;
pub(super) const MMS_UPDATE: u64 = 0b010;
pub(super) const MMS_COMPARE_PULSE: u64 = 0b011;
pub(super) const MMS_FIRST_REFERENCE: u64 = 0b100;
pub(super) const MMS2_FIRST_REFERENCE: u64 = 0b0100;
pub(super) const MMS2_LAST_REFERENCE: u64 = 0b1001;
pub(super) const MMS2_OC4_EDGES: u64 = 0b1010;
pub(super) const MMS2_OC6_EDGES: u64 = 0b1011;
pub(super) const MMS2_OC4_OR_OC6_RISING: u64 = 0b1100;
pub(super) const MMS2_OC4_RISING_OC6_FALLING: u64 = 0b1101;
pub(super) const MMS2_OC5_OR_OC6_RISING: u64 = 0b1110;
pub(super) const MMS2_OC5_RISING_OC6_FALLING: u64 = 0b1111;
pub(super) const CCS_OUTPUT: u64 = 0b00;
pub(super) const CCS_OWN_INPUT: u64 = 0b01;
pub(super) const CCS_OTHER_INPUT: u64 = 0b10;
pub(super) const CCS_TRC: u64 = 0b11;
pub(super) const OCM_FROZEN: u64 = 0b0000;
pub(super) const OCM_ACTIVE_ON_MATCH: u64 = 0b0001;
pub(super) const OCM_INACTIVE_ON_MATCH: u64 = 0b0010;
pub(super) const OCM_TOGGLE: u64 = 0b0011;
pub(super) const OCM_FORCE_INACTIVE: u64 = 0b0100;
pub(super) const OCM_FORCE_ACTIVE: u64 = 0b0101;
pub(super) const OCM_PWM_1: u64 = 0b0110;
pub(super) const OCM_PWM_2: u64 = 0b0111;
pub(super) const OCM_RETRIGGERABLE_1: u64 = 0b1000;
pub(super) const OCM_RETRIGGERABLE_2: u64 = 0b1001;
pub(super) const OCM_COMBINED_1: u64 = 0b1100;
pub(super) const OCM_COMBINED_2: u64 = 0b1101;
pub(super) const OCM_ASYMMETRIC_1: u64 = 0b1110;
pub(super) const OCM_ASYMMETRIC_2: u64 = 0b1111;
pub(super) const LOCK_LEVEL_1: u64 = 1;
pub(super) const LOCK_LEVEL_2: u64 = 2;
pub(super) const LOCK_LEVEL_3: u64 = 3;
impl<F: Family> Tim<F> {
const fn both(register: &str, field: &str) -> &'static FieldSpec {
both(F::PART, register, field)
}
const fn either(register: &str, field: &str) -> &'static FieldSpec {
either(F::PART, register, field)
}
pub(super) const CEN: &'static FieldSpec = Self::both("CR1", "CEN");
pub(super) const UDIS: &'static FieldSpec = Self::both("CR1", "UDIS");
pub(super) const URS: &'static FieldSpec = Self::both("CR1", "URS");
pub(super) const OPM: &'static FieldSpec = Self::both("CR1", "OPM");
pub(super) const DIR: &'static FieldSpec = Self::both("CR1", "DIR");
pub(super) const CMS: &'static FieldSpec = Self::both("CR1", "CMS");
pub(super) const ARPE: &'static FieldSpec = Self::both("CR1", "ARPE");
pub(super) const CKD: &'static FieldSpec = Self::both("CR1", "CKD");
pub(super) const UIFREMAP: &'static FieldSpec = Self::either("CR1", "UIFREMAP");
pub(super) const CCPC: &'static FieldSpec = Self::both("CR2", "CCPC");
pub(super) const CCUS: &'static FieldSpec = Self::both("CR2", "CCUS");
pub(super) const CCDS: &'static FieldSpec = Self::both("CR2", "CCDS");
pub(super) const MMS: &'static FieldSpec = Self::both("CR2", "MMS");
pub(super) const TI1S: &'static FieldSpec = Self::both("CR2", "TI1S");
pub(super) const MMS2: &'static FieldSpec = Self::either("CR2", "MMS2");
pub(super) const SMS: Split =
Split::new(Self::both("SMCR", "SMS"), Self::either("SMCR", "SMS_3"));
pub(super) const TS: Split =
Split::new(Self::both("SMCR", "TS"), Self::either("SMCR", "TS_4_3"));
pub(super) const MSM: &'static FieldSpec = Self::both("SMCR", "MSM");
pub(super) const ETF: &'static FieldSpec = Self::both("SMCR", "ETF");
pub(super) const ETPS: &'static FieldSpec = Self::both("SMCR", "ETPS");
pub(super) const ECE: &'static FieldSpec = Self::both("SMCR", "ECE");
pub(super) const ETP: &'static FieldSpec = Self::both("SMCR", "ETP");
pub(super) const UIE: &'static FieldSpec = Self::both("DIER", "UIE");
pub(super) const COMIE: &'static FieldSpec = Self::both("DIER", "COMIE");
pub(super) const TIE: &'static FieldSpec = Self::both("DIER", "TIE");
pub(super) const BIE: &'static FieldSpec = Self::both("DIER", "BIE");
pub(super) const UDE: &'static FieldSpec = Self::both("DIER", "UDE");
pub(super) const COMDE: &'static FieldSpec = Self::both("DIER", "COMDE");
pub(super) const TDE: &'static FieldSpec = Self::both("DIER", "TDE");
pub(super) const UIF: &'static FieldSpec = Self::both("SR", "UIF");
pub(super) const COMIF: &'static FieldSpec = Self::both("SR", "COMIF");
pub(super) const TIF: &'static FieldSpec = Self::both("SR", "TIF");
pub(super) const BIF: &'static FieldSpec = Self::both("SR", "BIF");
pub(super) const B2IF: &'static FieldSpec = Self::either("SR", "B2IF");
pub(super) const SBIF: &'static FieldSpec = Self::either("SR", "SBIF");
pub(super) const UG: &'static FieldSpec = Self::both("EGR", "UG");
pub(super) const COMG: &'static FieldSpec = Self::both("EGR", "COMG");
pub(super) const TG: &'static FieldSpec = Self::both("EGR", "TG");
pub(super) const BG: &'static FieldSpec = Self::both("EGR", "BG");
pub(super) const B2G: &'static FieldSpec = Self::either("EGR", "B2G");
pub(super) const UIFCPY: &'static FieldSpec = Self::either("CNT", "UIFCPY");
pub(super) const DTG: &'static FieldSpec = Self::both("BDTR", "DTG");
pub(super) const LOCK: &'static FieldSpec = Self::both("BDTR", "LOCK");
pub(super) const OSSI: &'static FieldSpec = Self::both("BDTR", "OSSI");
pub(super) const OSSR: &'static FieldSpec = Self::both("BDTR", "OSSR");
pub(super) const BKE: &'static FieldSpec = Self::both("BDTR", "BKE");
pub(super) const BKP: &'static FieldSpec = Self::both("BDTR", "BKP");
pub(super) const AOE: &'static FieldSpec = Self::both("BDTR", "AOE");
pub(super) const MOE: &'static FieldSpec = Self::both("BDTR", "MOE");
pub(super) const BKF: &'static FieldSpec = Self::either("BDTR", "BKF");
pub(super) const BK2F: &'static FieldSpec = Self::either("BDTR", "BK2F");
pub(super) const BK2E: &'static FieldSpec = Self::either("BDTR", "BK2E");
pub(super) const BK2P: &'static FieldSpec = Self::either("BDTR", "BK2P");
pub(super) const DBA: &'static FieldSpec = Self::both("DCR", "DBA");
pub(super) const DBL: &'static FieldSpec = Self::both("DCR", "DBL");
pub(super) const ETRSEL: &'static FieldSpec = Self::either("AF1", "ETRSEL");
pub(super) const BKINE: &'static FieldSpec = Self::either("AF1", "BKINE");
pub(super) const BK2INE: &'static FieldSpec = Self::either("AF2", "BK2INE");
pub(super) const CC_S: [&'static FieldSpec; INPUTS] = [
Self::both("CCMR1_Output", "CC1S"),
Self::both("CCMR1_Output", "CC2S"),
Self::both("CCMR2_Output", "CC3S"),
Self::both("CCMR2_Output", "CC4S"),
];
pub(super) const IC_PSC: [&'static FieldSpec; INPUTS] = [
Self::both("CCMR1_Input", "IC1PSC"),
Self::both("CCMR1_Input", "IC2PSC"),
Self::both("CCMR2_Input", "IC3PSC"),
Self::both("CCMR2_Input", "IC4PSC"),
];
pub(super) const IC_F: [&'static FieldSpec; INPUTS] = [
Self::both("CCMR1_Input", "IC1F"),
Self::both("CCMR1_Input", "IC2F"),
Self::both("CCMR2_Input", "IC3F"),
Self::both("CCMR2_Input", "IC4F"),
];
pub(super) const OC_FE: [&'static FieldSpec; CHANNELS] = [
Self::both("CCMR1_Output", "OC1FE"),
Self::both("CCMR1_Output", "OC2FE"),
Self::both("CCMR2_Output", "OC3FE"),
Self::both("CCMR2_Output", "OC4FE"),
Self::either("CCMR3_Output", "OC5FE"),
Self::either("CCMR3_Output", "OC6FE"),
];
pub(super) const OC_PE: [&'static FieldSpec; CHANNELS] = [
Self::both("CCMR1_Output", "OC1PE"),
Self::both("CCMR1_Output", "OC2PE"),
Self::both("CCMR2_Output", "OC3PE"),
Self::both("CCMR2_Output", "OC4PE"),
Self::either("CCMR3_Output", "OC5PE"),
Self::either("CCMR3_Output", "OC6PE"),
];
pub(super) const OC_CE: [&'static FieldSpec; CHANNELS] = [
Self::both("CCMR1_Output", "OC1CE"),
Self::both("CCMR1_Output", "OC2CE"),
Self::both("CCMR2_Output", "OC3CE"),
Self::both("CCMR2_Output", "OC4CE"),
Self::either("CCMR3_Output", "OC5CE"),
Self::either("CCMR3_Output", "OC6CE"),
];
pub(super) const OC_M: [Split; CHANNELS] = [
Split::new(
Self::both("CCMR1_Output", "OC1M"),
Self::either("CCMR1_Output", "OC1M_3"),
),
Split::new(
Self::both("CCMR1_Output", "OC2M"),
Self::either("CCMR1_Output", "OC2M_3"),
),
Split::new(
Self::both("CCMR2_Output", "OC3M"),
Self::either("CCMR2_Output", "OC3M_3"),
),
Split::new(
Self::both("CCMR2_Output", "OC4M"),
Self::either("CCMR2_Output", "OC4M_3"),
),
Split::new(
Self::either("CCMR3_Output", "OC5M"),
Self::either("CCMR3_Output", "OC5M3"),
),
Split::new(
Self::either("CCMR3_Output", "OC6M"),
Self::either("CCMR3_Output", "OC6M3"),
),
];
pub(super) const CC_E: [&'static FieldSpec; CHANNELS] = [
Self::both("CCER", "CC1E"),
Self::both("CCER", "CC2E"),
Self::both("CCER", "CC3E"),
Self::both("CCER", "CC4E"),
Self::either("CCER", "CC5E"),
Self::either("CCER", "CC6E"),
];
pub(super) const CC_P: [&'static FieldSpec; CHANNELS] = [
Self::both("CCER", "CC1P"),
Self::both("CCER", "CC2P"),
Self::both("CCER", "CC3P"),
Self::both("CCER", "CC4P"),
Self::either("CCER", "CC5P"),
Self::either("CCER", "CC6P"),
];
pub(super) const CC_NP: [&'static FieldSpec; INPUTS] = [
Self::both("CCER", "CC1NP"),
Self::both("CCER", "CC2NP"),
Self::both("CCER", "CC3NP"),
Self::both("CCER", "CC4NP"),
];
pub(super) const CC_NE: [&'static FieldSpec; 3] = [
Self::both("CCER", "CC1NE"),
Self::both("CCER", "CC2NE"),
Self::both("CCER", "CC3NE"),
];
pub(super) const CC_IF: [&'static FieldSpec; CHANNELS] = [
Self::both("SR", "CC1IF"),
Self::both("SR", "CC2IF"),
Self::both("SR", "CC3IF"),
Self::both("SR", "CC4IF"),
Self::either("SR", "CC5IF"),
Self::either("SR", "CC6IF"),
];
pub(super) const CC_IE: [&'static FieldSpec; INPUTS] = [
Self::both("DIER", "CC1IE"),
Self::both("DIER", "CC2IE"),
Self::both("DIER", "CC3IE"),
Self::both("DIER", "CC4IE"),
];
pub(super) const CC_OF: [&'static FieldSpec; INPUTS] = [
Self::both("SR", "CC1OF"),
Self::both("SR", "CC2OF"),
Self::both("SR", "CC3OF"),
Self::both("SR", "CC4OF"),
];
pub(super) const CC_DE: [&'static FieldSpec; INPUTS] = [
Self::both("DIER", "CC1DE"),
Self::both("DIER", "CC2DE"),
Self::both("DIER", "CC3DE"),
Self::both("DIER", "CC4DE"),
];
pub(super) const CC_G: [&'static FieldSpec; INPUTS] = [
Self::both("EGR", "CC1G"),
Self::both("EGR", "CC2G"),
Self::both("EGR", "CC3G"),
Self::both("EGR", "CC4G"),
];
pub(super) const OIS: [&'static FieldSpec; CHANNELS] = [
Self::both("CR2", "OIS1"),
Self::both("CR2", "OIS2"),
Self::both("CR2", "OIS3"),
Self::both("CR2", "OIS4"),
Self::either("CR2", "OIS5"),
Self::either("CR2", "OIS6"),
];
pub(super) const OIS_N: [&'static FieldSpec; 3] = [
Self::both("CR2", "OIS1N"),
Self::both("CR2", "OIS2N"),
Self::both("CR2", "OIS3N"),
];
pub(super) const TI_SELECT: [&'static FieldSpec; INPUTS] = [
Self::either("TISEL", "TI1SEL"),
Self::either("TISEL", "TI2SEL"),
Self::either("TISEL", "TI3SEL"),
Self::either("TISEL", "TI4SEL"),
];
pub(super) const GROUP: [&'static FieldSpec; 3] = [
Self::either("CCR5", "GC5C1"),
Self::either("CCR5", "GC5C2"),
Self::either("CCR5", "GC5C3"),
];
pub(super) const BREAK_ENABLES: [[&'static FieldSpec; super::BREAK_SOURCES]; 2] = [
[
Self::BKINE,
Self::either("AF1", "BKCMP1E"),
Self::either("AF1", "BKCMP2E"),
Self::either("AF1", "BKDF1BK0E"),
],
[
Self::BK2INE,
Self::either("AF2", "BK2CMP1E"),
Self::either("AF2", "BK2CMP2E"),
Self::either("AF2", "BK2DF1BK1E"),
],
];
pub(super) const BREAK_POLARITIES: [[Option<&'static FieldSpec>; super::BREAK_SOURCES]; 2] = [
[
Some(Self::either("AF1", "BKINP")),
Some(Self::either("AF1", "BKCMP1P")),
Some(Self::either("AF1", "BKCMP2P")),
None,
],
[
Some(Self::either("AF2", "BK2INP")),
Some(Self::either("AF2", "BK2CMP1P")),
Some(Self::either("AF2", "BK2CMP2P")),
None,
],
];
pub(super) const BREAK_CONTROLS: [(
&'static FieldSpec,
&'static FieldSpec,
&'static FieldSpec,
Slot,
); 2] = [
(Self::BKE, Self::BKP, Self::BKF, Slot::Af1),
(Self::BK2E, Self::BK2P, Self::BK2F, Slot::Af2),
];
pub(super) const REQUEST_ENABLES: [&'static FieldSpec; super::REQUESTS] = [
Self::UDE,
Self::CC_DE[0],
Self::CC_DE[1],
Self::CC_DE[2],
Self::CC_DE[3],
Self::TDE,
Self::COMDE,
];
}