public TimerService(IConfigProvider configProvider, IDateTimeWrapper dateTimeWrapper, ILogger <TimerService> logger, ITariffService tariffService) { _config = configProvider.Get <TimerConfig>(); _dateTimeWrapper = dateTimeWrapper; _logger = logger; _tariffService = tariffService; }
protected override void OnCreate() { TimerConfig config = TimerConfig.Default(); config.Top = 685; config.Left = 772; config.Color = "red"; config.Font_Size = 20; SetTimerConfig(config); if (ConfigFile.ReadConfigAndCreate("AppData", "AutoRun", "1").Trim() == "1") { if (SetAutoRunCtrlRegInfo(true)) { Log.Info("设置开机自启动成功"); } } //初装机注册文件 if (GlobalAppData.GetInstance().AppFirst&& RegsvrStarTrans()) { Log.Info("注册成功"); GlobalAppData.GetInstance().AppFirst = false; } ReceiptPrinter.AddedToManager(); }
public Timer(IOptions <TimerConfig> config, IBackgroundTaskQueue <MotorCloudEvent <IJobExecutionContext> > queue, IApplicationNameService applicationNameService) { _queue = queue; _applicationNameService = applicationNameService; _config = config?.Value ?? throw new ArgumentNullException(nameof(config.Value)); }
private void OnTimerFired(object timerConfig) { lock (_inTimerCallbackLock) { T callbackParam; if (_queue.TryDequeue(out callbackParam)) { TimerConfig <T> config = (TimerConfig <T>)timerConfig; try { _callbacksInFlight++; bool runComplete = false; Exception loggedException = null; try { config.Callback(callbackParam); runComplete = true; } catch (Exception ex) { LogManager.Log.Error("Error in Throttled Processor Action", ex); loggedException = ex; } try { if (runComplete) { if (config.SuccessCallback != null) { config.SuccessCallback(callbackParam); } } else { if (config.FailedCallback != null) { config.FailedCallback(callbackParam, loggedException); } } } catch (Exception ex) { LogManager.Log.Error("Error in Throttled Processor Reporting Callback", ex); } } finally { _callbacksInFlight--; } } } }
public ThrottledProcessor(int msBetween, Action <T> callback, Action <T> successCallback, ThrottledProcessorFailedCallback <T> failedCallback) { _queue = new ConcurrentQueue <T>(); TimerConfig <T> config = new TimerConfig <T> { Callback = callback, SuccessCallback = successCallback, FailedCallback = failedCallback, }; _timer = new Timer(OnTimerFired, config, 0, msBetween); }
protected override void OnCreate() { var config = TimerConfig.Default(); config.Left = 868; config.Top = 64; config.Font_Size = 22; SetTimerConfig(config); //if (ConfigFile.ReadConfigAndCreate("AppData", "AutoRun", "1").Trim() == "1") //{ // if (SetAutoRunCtrlRegInfo(true)) // Log.Info("设置开机自启动成功"); //} #region 此功能在配置参数时已实现 //if (ConfigFile.ReadConfigAndCreate("AppData", "AutoRun", "1").Trim() == "1") //{ // if (SetAutoRunCtrlRegInfo(true)) // Log.Info("设置开机自启动成功"); //} //else //{ // if (SetAutoRunCtrlRegInfo(false)) // Log.Info("取消开机自启动成功"); //} #endregion //初装机注册文件 if (GlobalAppData.GetInstance().AppFirst&& RegsvrStarTrans()) { Log.Info("注册成功"); GlobalAppData.GetInstance().AppFirst = false; } //GPRS.AddedToManager(); CardReader.AddedToManager(); Esam.AddedToManager(); ReceiptPrinter.AddedToManager(); //R80.AddedToManager(); GasCardReader.AddedToManager(); }
/// <summary> /// Draws the background pie /// </summary> /// <param name="e"></param> protected virtual void OnDrawBackCircle(PaintEventArgs e, TimerConfig timer, Func <Color, Brush>[] createBrush, bool createLastCountdownEffects) { /* * Creates a filled pie */ /* local */ void fillPie(Brush color, float startAngle, float angle, float scale, float centerOffset) { Rectangle area = new Rectangle( x: squareArea.X + (int)(squareArea.Width * (1 - scale) / 2f), y: squareArea.Y + (int)(squareArea.Height * (1 - scale) / 2f), width: Math.Max(1, (int)(squareArea.Width * scale)), height: Math.Max(1, (int)(squareArea.Height * scale)) ); Region region = new Region(); GraphicsPath path = new GraphicsPath(); path.AddPie(area, -90 + startAngle, angle); region.MakeEmpty(); region.Union(path); if (centerOffset > 0) { GraphicsPath exclPath = new GraphicsPath(); Rectangle exclArea = new Rectangle( x: squareArea.X + (int)(squareArea.Width * (1 - centerOffset) / 2f), y: squareArea.Y + (int)(squareArea.Height * (1 - centerOffset) / 2f), width: Math.Max(1, (int)(squareArea.Width * centerOffset)), height: Math.Max(1, (int)(squareArea.Height * centerOffset)) ); exclPath.AddEllipse(exclArea); region.Exclude(exclPath); exclPath.Dispose(); } e.Graphics.FillRegion(color, region); region.Dispose(); path.Dispose(); } /* * Creates an unfilled pie */ /* local */ void drawPie(Pen color, float startAngle, float angle, float scale) { Rectangle area = new Rectangle( x: squareArea.X + (int)(squareArea.Width * (1 - scale) / 2f), y: squareArea.Y + (int)(squareArea.Height * (1 - scale) / 2f), width: Math.Max(1, (int)(squareArea.Width * scale)), height: Math.Max(1, (int)(squareArea.Height * scale)) ); e.Graphics.DrawPie(color, area, -90 + startAngle, angle); } //Color scheme to use Color[] colors = timer.AnalogColors; //Create the final-minute color shift if (createLastCountdownEffects && timer.TimeLeft.TotalMinutes < 1f && !timer.Overtime) { fillPie( color: BG_BRUSH, startAngle: (DateTime.Now.Second + DateTime.Now.Millisecond / 1000f) / 60f * 360f, angle: (float)timer.RealTimeLeft.TotalSeconds / 60f * 360f, scale: 1 - BG_FRAME_SCALE, centerOffset: 0f ); } /* * Draw pies */ //Draw for days (more than 1 day) if (timer.TimeLeft.TotalDays >= 1) { float dividend = 1f; for (int i = 0; i < Math.Ceiling(timer.TimeLeft.TotalDays / 12); i++) { //Create a colored pen based on what days we are drawing using (Brush b = createBrush[i % createBrush.Length](colors[(i + 6) % colors.Length])) { if (i == Math.Floor(timer.TimeLeft.TotalDays / 12)) { fillPie( color: b, startAngle: 0f, angle: (float)timer.TimeLeft.TotalDays % 12f * 360f / 12f, scale: DISC_INITAL_SCALE / dividend, centerOffset: DISC_INITAL_SCALE_HOURS ); } else { fillPie( color: b, startAngle: 0f, angle: 360f, scale: DISC_INITAL_SCALE / dividend, centerOffset: DISC_INITAL_SCALE_HOURS ); } } dividend += DISC_INITAL_SCALE_HOURS; } //Draw lines segmenting the bar using (Pen p = new Pen(Color.FromArgb(0x7F, Color.Silver), 1.5f) { DashStyle = DashStyle.Dash }) { for (int a = 0; a < Math.Min(12, timer.TimeLeft.TotalDays); a++) { Point center = new Point(squareArea.X + squareArea.Width / 2, squareArea.Y + squareArea.Height / 2); PointF startPoint = GetPointAtAngle(center, (int)(DISC_INITAL_SCALE_HOURS * squareArea.Width / 2), CalculateAngle(a * (timer.Overtime ? -1 : 1), 12)); PointF endPoint = GetPointAtAngle(center, (int)(DISC_INITAL_SCALE * squareArea.Width / 2), CalculateAngle(a * (timer.Overtime ? -1 : 1), 12)); e.Graphics.DrawLine(p, startPoint, endPoint); } } //Draw week indicators fillPie(Brushes.Gray, 7 / 12f * 360f, 1f, DISC_INITAL_SCALE, DISC_INITAL_SCALE_HOURS); if (timer.TimeLeft.TotalDays >= 7f) { fillPie(Brushes.Gray, 2 / 12f * 360f, 1f, DISC_INITAL_SCALE, DISC_INITAL_SCALE_HOURS); } if (timer.TimeLeft.TotalDays >= 14f) { fillPie(Brushes.Gray, 9 / 12f * 360f, 1f, DISC_INITAL_SCALE, DISC_INITAL_SCALE_HOURS); } //fillPie(BG_BRUSH, 0f, 360f, DISC_INITAL_SCALE_HOURS); } //Draw for hours (more than 3 hours) else if (timer.TimeLeft.TotalHours >= 3) { float dividend = 1f; for (int i = 0; i < Math.Ceiling(timer.TimeLeft.TotalDays * 2); i++) { //Create a colored pen based on what hours we are drawing using (Brush b = createBrush[i % createBrush.Length](colors[(i + 4) % colors.Length])) { if (i == Math.Floor(timer.TimeLeft.TotalDays * 2)) { fillPie( color: b, startAngle: ((DateTime.Now.Hour % 12) + DateTime.Now.Minute / 60f) / 12f * 360f, angle: (float)(timer.RealTimeLeft.TotalHours % 12) / 12f * 360f, scale: DISC_INITAL_SCALE_HOURS / dividend, centerOffset: 0f ); } else { fillPie( color: b, startAngle: 0f, angle: 360f, scale: DISC_INITAL_SCALE_HOURS / dividend, centerOffset: 0f ); } } dividend += DISC_INITAL_SCALE_HOURS; } } //Draw for minutes (less than 3 hours) else { float dividend = 1f; for (int i = 0; i < Math.Ceiling(timer.TimeLeft.TotalHours); i++) { //Create a colored pen based on what hour we are drawing using (Brush b = createBrush[i % createBrush.Length](colors[i % colors.Length])) { if (i == Math.Floor(timer.TimeLeft.TotalHours)) { fillPie( color: b, startAngle: (DateTime.Now.Minute + DateTime.Now.Second / 60f) / 60f * 360f, angle: (float)(timer.RealTimeLeft.TotalMinutes % 60) / 60f * 360f, scale: DISC_INITAL_SCALE / dividend, centerOffset: 0f ); } else { fillPie( color: b, startAngle: 0f, angle: 360f, scale: DISC_INITAL_SCALE / dividend, centerOffset: 0f ); } } dividend += DISC_DIVIDEND_INCREMENT; } } //Draw for seconds (less than 12 minutes) if (createLastCountdownEffects && timer.TimeLeft.TotalMinutes < 12 && !(timer.Overtime && timer.StopAtZero)) { using (Pen p = new Pen(colors[10 % colors.Length], 2f) { DashStyle = DashStyle.Dash }) { drawPie( color: p, startAngle: 0f, angle: (float)timer.RealTimeLeft.TotalMinutes / 12f * 360f, scale: DISC_INITAL_SCALE ); } } }
public STM32F4_RTC(Machine machine) { mainTimer = new TimerConfig(this); alarmA = new AlarmConfig(this, mainTimer); alarmB = new AlarmConfig(this, mainTimer); AlarmIRQ = new GPIO(); ticker = new LimitTimer(machine.ClockSource, 1, this, nameof(ticker), 1, direction: Direction.Ascending, eventEnabled: true); ticker.LimitReached += UpdateState; ResetInnerTimers(); IFlagRegisterField syncFlag = null; var registerMap = new Dictionary <long, DoubleWordRegister> { { (long)Registers.TimeRegister, new DoubleWordRegister(this) .WithValueField(0, 4, name: "SU", writeCallback: (_, value) => UpdateMainTimer(Registers.TimeRegister, DateTimeSelect.Second, Rank.Units, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Second, Rank.Units)) .WithValueField(4, 3, name: "ST", writeCallback: (_, value) => UpdateMainTimer(Registers.TimeRegister, DateTimeSelect.Second, Rank.Tens, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Second, Rank.Tens)) .WithReservedBits(7, 1) .WithValueField(8, 4, name: "MU", writeCallback: (_, value) => UpdateMainTimer(Registers.TimeRegister, DateTimeSelect.Minute, Rank.Units, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Minute, Rank.Units)) .WithValueField(12, 3, name: "MT", writeCallback: (_, value) => UpdateMainTimer(Registers.TimeRegister, DateTimeSelect.Minute, Rank.Tens, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Minute, Rank.Tens)) .WithReservedBits(15, 1) .WithValueField(16, 4, name: "HU", writeCallback: (_, value) => UpdateMainTimer(Registers.TimeRegister, DateTimeSelect.Hour, Rank.Units, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Hour, Rank.Units)) .WithValueField(20, 2, name: "HT", writeCallback: (_, value) => UpdateMainTimer(Registers.TimeRegister, DateTimeSelect.Hour, Rank.Tens, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Hour, Rank.Tens)) .WithFlag(22, name: "PM", writeCallback: (_, value) => { if (CheckIfInInitMode(Registers.TimeRegister) && CheckIfUnlocked(Registers.TimeRegister)) { mainTimer.PM = value; } }, valueProviderCallback: _ => mainTimer.PM) .WithReservedBits(23, 9) }, { (long)Registers.DateRegister, new DoubleWordRegister(this, 0x2101) .WithValueField(0, 4, name: "DU", writeCallback: (_, value) => UpdateMainTimer(Registers.DateRegister, DateTimeSelect.Day, Rank.Units, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Day, Rank.Units)) .WithValueField(4, 2, name: "DT", writeCallback: (_, value) => UpdateMainTimer(Registers.DateRegister, DateTimeSelect.Day, Rank.Tens, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Day, Rank.Tens)) .WithReservedBits(6, 2) .WithValueField(8, 4, name: "MU", writeCallback: (_, value) => UpdateMainTimer(Registers.DateRegister, DateTimeSelect.Month, Rank.Units, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Month, Rank.Units)) .WithValueField(12, 1, name: "MT", writeCallback: (_, value) => UpdateMainTimer(Registers.DateRegister, DateTimeSelect.Month, Rank.Tens, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Month, Rank.Tens)) .WithValueField(13, 3, name: "WDU", writeCallback: (_, value) => { if (CheckIfInInitMode(Registers.DateRegister) && CheckIfUnlocked(Registers.DateRegister)) { if (value == 0) { this.Log(LogLevel.Warning, "Writting value 0 to WeekDay register is forbidden"); return; } mainTimer.WeekDay = (DayOfTheWeek)value; } }, valueProviderCallback: _ => (uint)mainTimer.WeekDay) .WithValueField(16, 4, name: "YU", writeCallback: (_, value) => UpdateMainTimer(Registers.DateRegister, DateTimeSelect.Year, Rank.Units, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Year, Rank.Units)) .WithValueField(20, 4, name: "YT", writeCallback: (_, value) => UpdateMainTimer(Registers.DateRegister, DateTimeSelect.Year, Rank.Tens, value), valueProviderCallback: _ => mainTimer.Read(DateTimeSelect.Year, Rank.Tens)) .WithReservedBits(24, 8) }, { (long)Registers.ControlRegister, new DoubleWordRegister(this) .WithTag("WUCKSEL", 0, 3) .WithTag("TSEDGE", 3, 1) .WithTag("REFCKON", 4, 1) .WithTag("BYPSHAD", 5, 1) .WithFlag(6, name: "FMT", writeCallback: (_, value) => { if (CheckIfUnlocked(Registers.ControlRegister)) { AMPMFormat = value; mainTimer.ConfigureAMPM(); alarmA.ConfigureAMPM(); alarmB.ConfigureAMPM(); } }, valueProviderCallback: _ => AMPMFormat) .WithTag("DCE", 7, 1) .WithFlag(8, name: "ALRAE", writeCallback: (_, value) => { if (CheckIfUnlocked(Registers.ControlRegister)) { alarmA.Enable = value; } }, valueProviderCallback: _ => alarmA.Enable) .WithFlag(9, name: "ALRBE", writeCallback: (_, value) => { if (CheckIfUnlocked(Registers.ControlRegister)) { alarmB.Enable = value; } }, valueProviderCallback: _ => alarmB.Enable) .WithTag("WUTE", 10, 1) // Wakeup Timer not supported .WithTag("TSE", 11, 1) // Timestamp not supported .WithFlag(12, name: "ALRAIE", writeCallback: (_, value) => { if (CheckIfUnlocked(Registers.ControlRegister)) { alarmA.InterruptEnable = value; } }, valueProviderCallback: _ => alarmA.InterruptEnable) .WithFlag(13, name: "ALRBIE", writeCallback: (_, value) => { if (CheckIfUnlocked(Registers.ControlRegister) && value) { alarmB.InterruptEnable = value; } }, valueProviderCallback: _ => alarmB.InterruptEnable) .WithTag("WUTIE", 14, 1) // Wakeup Timer not supported .WithTag("TSIE", 15, 1) // Timestamp not supported .WithTag("ADD1H", 16, 1) .WithTag("SUB1H", 17, 1) .WithTag("BKP", 18, 1) .WithTag("COSEL", 19, 1) .WithTag("POL", 20, 1) .WithTag("OSEL", 21, 2) .WithTag("COE", 23, 1) .WithReservedBits(24, 8) }, { (long)Registers.ISR, new DoubleWordRegister(this, 0x7) .WithFlag(0, FieldMode.Read, valueProviderCallback: _ => !alarmA.Enable, name: "ALRAWF") .WithFlag(1, FieldMode.Read, valueProviderCallback: _ => !alarmB.Enable, name: "ALRBWF") .WithTag("WUTWF", 2, 1) .WithTag("SHPF", 3, 1) .WithFlag(4, FieldMode.Read, valueProviderCallback: _ => mainTimer.TimeState.Year != 2000, name: "INITS") .WithFlag(5, out syncFlag, FieldMode.Read | FieldMode.WriteZeroToClear, name: "RSF", readCallback: (_, curr) => { // this strange logic is required by the Zephyr driver; // it wants to read 0 before reading 1, otherwise it times-out if (!curr) { syncFlag.Value = true; } }) .WithFlag(6, FieldMode.Read, valueProviderCallback: _ => initMode, name: "INITF") .WithFlag(7, FieldMode.Write, name: "INIT", writeCallback: (_, value) => { if (CheckIfUnlocked(Registers.ISR)) { ticker.Enabled = !value; initMode = value; } }) .WithFlag(8, FieldMode.WriteZeroToClear | FieldMode.Read, name: "ALRAF", changeCallback: (_, __) => { alarmA.Flag = false; }, valueProviderCallback: _ => alarmA.Flag) .WithFlag(9, FieldMode.WriteZeroToClear | FieldMode.Read, name: "ALRBF", changeCallback: (_, __) => { alarmB.Flag = false; }, valueProviderCallback: _ => alarmB.Flag) .WithTag("WUTF", 10, 1) .WithTag("TSF", 11, 1) .WithTag("TSOVF", 12, 1) .WithTag("TAMP1F", 13, 1) .WithTag("TAMP2F", 14, 1) .WithReservedBits(15, 1) .WithTag("RECALPF", 16, 1) .WithReservedBits(17, 15) }, { (long)Registers.PrescalerRegister, new DoubleWordRegister(this) .WithTag("PREDIV_S", 0, 15) .WithReservedBits(15, 1) .WithTag("PREDIV_A", 16, 7) .WithReservedBits(23, 9) }, { (long)Registers.WakeupTimerRegister, new DoubleWordRegister(this, 0x7F00FF) .WithTag("WUT", 0, 16) .WithReservedBits(16, 16) }, { (long)Registers.CalibrationRegister, new DoubleWordRegister(this) .WithTag("DC", 0, 5) .WithReservedBits(5, 2) .WithTag("DCS", 7, 1) .WithReservedBits(8, 24) }, { (long)Registers.AlarmARegister, new DoubleWordRegister(this) .WithValueField(0, 4, name: "SU", writeCallback: (_, value) => UpdateTimerA(DateTimeSelect.Second, Rank.Units, value), valueProviderCallback: _ => alarmA.Read(DateTimeSelect.Second, Rank.Units)) .WithValueField(4, 3, name: "ST", writeCallback: (_, value) => UpdateTimerA(DateTimeSelect.Second, Rank.Tens, value), valueProviderCallback: _ => alarmA.Read(DateTimeSelect.Second, Rank.Tens)) .WithFlag(7, name: "MSK1", writeCallback: (_, value) => { if (CheckIfDisabled(alarmA) && CheckIfUnlocked(Registers.AlarmARegister)) { alarmA.SecondsMask = value; } }, valueProviderCallback: _ => alarmA.SecondsMask) .WithValueField(8, 4, name: "MU", writeCallback: (_, value) => UpdateTimerA(DateTimeSelect.Minute, Rank.Units, value), valueProviderCallback: _ => alarmA.Read(DateTimeSelect.Minute, Rank.Units)) .WithValueField(12, 3, name: "MT", writeCallback: (_, value) => UpdateTimerA(DateTimeSelect.Minute, Rank.Tens, value), valueProviderCallback: _ => alarmA.Read(DateTimeSelect.Minute, Rank.Tens)) .WithFlag(15, name: "MSK2", writeCallback: (_, value) => { if (CheckIfDisabled(alarmA) && CheckIfUnlocked(Registers.AlarmARegister)) { alarmA.MinutesMask = value; } }, valueProviderCallback: _ => alarmA.MinutesMask) .WithValueField(16, 4, name: "HU", writeCallback: (_, value) => UpdateTimerA(DateTimeSelect.Hour, Rank.Units, value), valueProviderCallback: _ => alarmA.Read(DateTimeSelect.Hour, Rank.Units)) .WithValueField(20, 2, name: "HT", writeCallback: (_, value) => UpdateTimerA(DateTimeSelect.Hour, Rank.Tens, value), valueProviderCallback: _ => alarmA.Read(DateTimeSelect.Hour, Rank.Tens)) .WithFlag(22, name: "PM", writeCallback: (_, value) => { if (CheckIfDisabled(alarmA) && CheckIfUnlocked(Registers.AlarmARegister)) { alarmA.PM = value; } }, valueProviderCallback: _ => alarmA.PM) .WithFlag(23, name: "MSK3", writeCallback: (_, value) => { if (CheckIfDisabled(alarmA) && CheckIfUnlocked(Registers.AlarmARegister)) { alarmA.HoursMask = value; } }, valueProviderCallback: _ => alarmA.HoursMask) .WithValueField(24, 4, name: "DU", writeCallback: (_, value) => UpdateTimerA(DateTimeSelect.Day, Rank.Units, value), valueProviderCallback: _ => alarmA.Read(DateTimeSelect.Day, Rank.Units)) .WithValueField(28, 2, name: "DT", writeCallback: (_, value) => UpdateTimerA(DateTimeSelect.Day, Rank.Tens, value), valueProviderCallback: _ => alarmA.Read(DateTimeSelect.Day, Rank.Tens)) .WithTag("WDSEL", 30, 1) // Weekday instead of date units usupported .WithFlag(31, name: "MSK4", writeCallback: (_, value) => { if (CheckIfDisabled(alarmA) && CheckIfUnlocked(Registers.AlarmARegister)) { alarmA.DaysMask = value; } }, valueProviderCallback: _ => alarmA.DaysMask) }, { (long)Registers.AlarmBRegister, new DoubleWordRegister(this) .WithValueField(0, 4, name: "SU", writeCallback: (_, value) => UpdateTimerB(DateTimeSelect.Second, Rank.Units, value), valueProviderCallback: _ => alarmB.Read(DateTimeSelect.Second, Rank.Units)) .WithValueField(4, 3, name: "ST", writeCallback: (_, value) => UpdateTimerB(DateTimeSelect.Second, Rank.Tens, value), valueProviderCallback: _ => alarmB.Read(DateTimeSelect.Second, Rank.Tens)) .WithFlag(7, name: "MSK1", writeCallback: (_, value) => { if (CheckIfDisabled(alarmB) && CheckIfUnlocked(Registers.AlarmBRegister)) { alarmB.SecondsMask = value; } }, valueProviderCallback: _ => alarmB.SecondsMask) .WithValueField(8, 4, name: "MU", writeCallback: (_, value) => UpdateTimerB(DateTimeSelect.Minute, Rank.Units, value), valueProviderCallback: _ => alarmB.Read(DateTimeSelect.Minute, Rank.Units)) .WithValueField(12, 3, name: "MT", writeCallback: (_, value) => UpdateTimerB(DateTimeSelect.Minute, Rank.Tens, value), valueProviderCallback: _ => alarmB.Read(DateTimeSelect.Minute, Rank.Tens)) .WithFlag(15, name: "MSK2", writeCallback: (_, value) => { if (CheckIfDisabled(alarmB) && CheckIfUnlocked(Registers.AlarmBRegister)) { alarmB.MinutesMask = value; } }, valueProviderCallback: _ => alarmB.MinutesMask) .WithValueField(16, 4, name: "HU", writeCallback: (_, value) => UpdateTimerB(DateTimeSelect.Hour, Rank.Units, value), valueProviderCallback: _ => alarmB.Read(DateTimeSelect.Hour, Rank.Units)) .WithValueField(20, 2, name: "HT", writeCallback: (_, value) => UpdateTimerB(DateTimeSelect.Hour, Rank.Tens, value), valueProviderCallback: _ => alarmB.Read(DateTimeSelect.Hour, Rank.Tens)) .WithFlag(22, name: "PM", writeCallback: (_, value) => { if (CheckIfDisabled(alarmB) && CheckIfUnlocked(Registers.AlarmBRegister)) { alarmB.PM = value; } }, valueProviderCallback: _ => alarmB.PM) .WithFlag(23, name: "MSK3", writeCallback: (_, value) => { if (CheckIfDisabled(alarmB) && CheckIfUnlocked(Registers.AlarmBRegister)) { alarmB.HoursMask = value; } }, valueProviderCallback: _ => alarmB.HoursMask) .WithValueField(24, 4, name: "DU", writeCallback: (_, value) => UpdateTimerB(DateTimeSelect.Day, Rank.Units, value), valueProviderCallback: _ => alarmB.Read(DateTimeSelect.Day, Rank.Units)) .WithValueField(28, 2, name: "DT", writeCallback: (_, value) => UpdateTimerB(DateTimeSelect.Day, Rank.Tens, value), valueProviderCallback: _ => alarmB.Read(DateTimeSelect.Day, Rank.Tens)) .WithTag("WDSEL", 30, 1) // Weekday instead of date units usupported .WithFlag(31, name: "MSK4", writeCallback: (_, value) => { if (CheckIfDisabled(alarmB) && CheckIfUnlocked(Registers.AlarmBRegister)) { alarmB.DaysMask = value; } }, valueProviderCallback: _ => alarmB.DaysMask) }, { (long)Registers.WriteProtectionRegister, new DoubleWordRegister(this) .WithValueField(0, 8, name: "KEY", writeCallback: (_, value) => { if (value == UnlockKey1 && !firstStageUnlocked) { firstStageUnlocked = true; } else if (value == UnlockKey2 && firstStageUnlocked) { registersUnlocked = true; } else { firstStageUnlocked = false; registersUnlocked = false; } }, valueProviderCallback: _ => 0) .WithReservedBits(8, 24) }, { (long)Registers.SubSecondRegister, new DoubleWordRegister(this) .WithTag("SS", 0, 16) .WithReservedBits(16, 16) }, { (long)Registers.ShiftControlRegister, new DoubleWordRegister(this) .WithTag("SUBFS", 0, 15) .WithReservedBits(15, 16) .WithTag("ADD1S", 31, 1) }, { (long)Registers.TimestampTimeRegister, new DoubleWordRegister(this) .WithTag("Second", 0, 7) .WithReservedBits(7, 1) .WithTag("Minute", 8, 7) .WithReservedBits(15, 1) .WithTag("Hour", 16, 6) .WithTag("PM", 22, 1) .WithReservedBits(23, 9) }, { (long)Registers.TimestampDateRegister, new DoubleWordRegister(this) .WithTag("Day", 0, 6) .WithReservedBits(6, 2) .WithTag("Month", 8, 5) .WithTag("WDU", 13, 3) .WithReservedBits(16, 16) }, { (long)Registers.TimestampSubSecondRegister, new DoubleWordRegister(this) .WithTag("SS", 0, 16) .WithReservedBits(16, 16) }, { (long)Registers.ClockCalibrationRegister, new DoubleWordRegister(this) .WithTag("CALM", 0, 9) .WithReservedBits(9, 4) .WithTag("CALW16", 13, 1) .WithTag("CALW8", 14, 1) .WithTag("CALP", 15, 1) .WithReservedBits(16, 16) }, { (long)Registers.TamperAndAlternateFunctionConfigurationRegister, new DoubleWordRegister(this) .WithTag("TAMP1E", 0, 1) .WithTag("TAMP1TRG", 1, 1) .WithTag("TAMPIE", 2, 1) .WithTag("TAMP2E", 3, 1) .WithTag("TAMP2TRG", 4, 1) .WithReservedBits(5, 2) .WithTag("TAMPTS", 7, 1) .WithTag("TAMPFREQ", 8, 3) .WithTag("TAMPFLT", 11, 2) .WithTag("TAMPPRCH", 13, 2) .WithTag("TAMPPUDIS", 15, 1) .WithTag("TAMP1INSEL", 16, 1) .WithTag("TSINSEL", 17, 1) .WithTag("ALARMOUTTYPE", 18, 1) .WithReservedBits(19, 13) }, { (long)Registers.AlarmASubSecondRegister, new DoubleWordRegister(this) .WithTag("SS", 0, 15) .WithReservedBits(15, 9) .WithTag("MASKSS", 24, 4) .WithReservedBits(28, 4) }, { (long)Registers.AlarmBSubSecondRegister, new DoubleWordRegister(this) .WithTag("SS", 0, 15) .WithReservedBits(15, 9) .WithTag("MASKSS", 24, 4) .WithReservedBits(28, 4) }, }; registers = new DoubleWordRegisterCollection(this, registerMap); }