-
Notifications
You must be signed in to change notification settings - Fork 33
AC Indicator #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
AC Indicator #29
Changes from all commits
66aee68
7c922fb
6445c58
8f02eb1
253d924
6fadcbe
71bb064
75a1156
6d13a1e
7866ee0
bc37ea5
45bb7c0
414b9f3
9337c35
fcf83d7
6a8fe20
a360e51
54176cf
6908c13
a329931
053227a
31b0471
deb5439
419383f
d0729ca
b299a07
5ff896e
1215201
b956a7f
168de9f
ea44e8c
47c7caf
152e899
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -71,15 +71,24 @@ void Beeper::update(const AlarmLevel& alarm_level) { | |
| if (snoozeButtonPressed()) { | ||
| toggleSnooze(); | ||
| } | ||
|
|
||
| // check if snooze time is up | ||
| if (snoozed_ && millis() - snooze_time_ > kSnoozeTime) { | ||
| snoozed_ = false; | ||
| } | ||
|
|
||
| if (snoozed_) { | ||
| stop(); | ||
| timeRemaining_ = (kSnoozeTime - (millis() - snooze_time_)) / 1000UL; | ||
| } else { | ||
| play(alarm_level); | ||
| } | ||
|
|
||
| // Reset snooze timer when alarms are gone | ||
| if (alarm_level == NO_ALARM) { | ||
| timeRemaining_ = 0; // Hides timer when snoozed with no alarms | ||
| snoozed_ = false; // Ensures beeping as soon a new alarm emerges | ||
| } | ||
| } | ||
|
|
||
| bool Beeper::snoozeButtonPressed() const { | ||
|
|
@@ -89,9 +98,10 @@ bool Beeper::snoozeButtonPressed() const { | |
| void Beeper::toggleSnooze() { | ||
| if (snoozed_) { | ||
| snoozed_ = false; | ||
| timeRemaining_ = 0; // Hides timer count when beeping | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The getRemainingSnoozeTime function should have the logic of what to return when not snoozed, rather than cluttering up toggleSnooze |
||
| } else { | ||
| snoozed_ = true; | ||
| snooze_time_ = millis(); | ||
| snooze_time_ = millis(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unnecessary whitespace |
||
| } | ||
| } | ||
|
|
||
|
|
@@ -110,12 +120,15 @@ void Beeper::stop() { | |
| } | ||
| } | ||
|
|
||
| unsigned long Beeper::getRemainingSnoozeTime() { | ||
| return timeRemaining_; | ||
| } | ||
|
|
||
| /// Alarm /// | ||
|
|
||
| Alarm::Alarm(const String& default_text, const int& min_bad_to_trigger, | ||
| const int& min_good_to_clear, const AlarmLevel& alarm_level): | ||
| text_(default_text), | ||
| text_(default_text.substring(0, display::kHeaderLength-1)), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The kHeaderLength is already 1 shorter than the display width. Why subtract another? |
||
| min_bad_to_trigger_(min_bad_to_trigger), | ||
| min_good_to_clear_(min_good_to_clear), | ||
| alarm_level_(alarm_level) {} | ||
|
|
@@ -143,15 +156,15 @@ void Alarm::setCondition(const bool& bad, const unsigned long& seq) { | |
| } | ||
|
|
||
| void Alarm::setText(const String& text) { | ||
| if (text.length() == display::kWidth) { | ||
| if (text.length() == display::kFooterLength) { | ||
| text_ = text; | ||
| } | ||
| else if (text.length() > display::kWidth) { | ||
| text_ = text.substring(0, display::kWidth); | ||
| else if (text.length() > display::kFooterLength) { | ||
| text_ = text.substring(0, display::kFooterLength); | ||
| } | ||
| else { | ||
| text_ = text; | ||
| while (text_.length() < display::kWidth) { | ||
| while (text_.length() < display::kFooterLength) { | ||
| text_ += " "; | ||
| } | ||
| } | ||
|
|
@@ -166,7 +179,9 @@ void AlarmManager::begin() { | |
| } | ||
|
|
||
| void AlarmManager::update() { | ||
| displ_->setAlarmText(getText()); | ||
| displ_->setAlarmText(getGeneralAlarmText()); | ||
| displ_->setUnconfirmedKnobAlarmText(getUnconfirmedKnobText()); | ||
| displ_->setSnoozeText(beeper_.getRemainingSnoozeTime()); | ||
| AlarmLevel highest_level = getHighestLevel(); | ||
| beeper_.update(highest_level); | ||
| if (highest_level > NO_ALARM) { | ||
|
|
@@ -191,16 +206,66 @@ int AlarmManager::numON() const { | |
| return num; | ||
| } | ||
|
|
||
| String AlarmManager::getText() const { | ||
| const int num_on = numON(); | ||
| int AlarmManager::numON_Confirm() const { | ||
| int num = 0; | ||
| bool aConfirmAlarm; | ||
| for (int i = 0; i < NUM_ALARMS; i++) { | ||
| aConfirmAlarm = (i==NOT_CONFIRM_TV || i==NOT_CONFIRM_RR || | ||
| i==NOT_CONFIRM_IE || i==NOT_CONFIRM_AC); | ||
| if(aConfirmAlarm) { | ||
| num += (int)alarms_[i].isON(); | ||
| } | ||
| } | ||
| return num; | ||
| } | ||
|
|
||
| int AlarmManager::numON_NonConfirm() const { | ||
| int num = 0; | ||
| bool aConfirmAlarm; | ||
| for (int i = 0; i < NUM_ALARMS; i++) { | ||
| aConfirmAlarm = (i==NOT_CONFIRM_TV || i==NOT_CONFIRM_RR || | ||
| i==NOT_CONFIRM_IE || i==NOT_CONFIRM_AC); | ||
| if(!aConfirmAlarm) { | ||
| num += (int)alarms_[i].isON(); | ||
| } | ||
| } | ||
| return num; | ||
| } | ||
|
|
||
| String AlarmManager::getGeneralAlarmText() const { | ||
| const int num_on = numON_NonConfirm(); | ||
| String text = ""; | ||
| if (num_on > 0) { | ||
| // determine which of the on alarms to display | ||
| const int index = millis() % (num_on * kDisplayTime) / kDisplayTime; | ||
| int count_on = 0; | ||
| int i; | ||
| bool aConfirmAlarm; | ||
| for (i = 0; i < NUM_ALARMS; i++) { | ||
| aConfirmAlarm = (i==NOT_CONFIRM_TV || i==NOT_CONFIRM_RR || | ||
| i==NOT_CONFIRM_IE || i==NOT_CONFIRM_AC); | ||
| if (!aConfirmAlarm && alarms_[i].isON()) { | ||
| if (count_on++ == index) break; | ||
| } | ||
| } | ||
| text = alarms_[i].text(); | ||
| } | ||
| return text; | ||
| } | ||
|
|
||
| String AlarmManager::getUnconfirmedKnobText() const { | ||
| const int num_on = numON_Confirm(); | ||
| String text = ""; | ||
| if (num_on > 0) { | ||
| // determine which of the on alarms to display | ||
| const int index = millis() % (num_on * kDisplayTime) / kDisplayTime; | ||
| int count_on = 0; | ||
| int i; | ||
| bool aConfirmAlarm; | ||
| for (i = 0; i < NUM_ALARMS; i++) { | ||
| if (alarms_[i].isON()) { | ||
| aConfirmAlarm = (i==NOT_CONFIRM_TV || i==NOT_CONFIRM_RR || | ||
| i==NOT_CONFIRM_IE || i==NOT_CONFIRM_AC); | ||
| if (aConfirmAlarm && alarms_[i].isON()) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is confusing and brittle. Now that the confirm knobs and alarms are being written to different places, they should be treated differently. But hardcoding the list of which alarms are confirm alarms, and writing these almost duplicate functions is bad practice. We should abstract the logic of which alarms are in which cycle, so we don't need to hardcode checks and write code multiple times |
||
| if (count_on++ == index) break; | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -140,12 +140,16 @@ class Beeper { | |
| // Update during arduino loop() | ||
| void update(const AlarmLevel& alarm_level); | ||
|
|
||
| // Get snooze time remaining | ||
| unsigned long getRemainingSnoozeTime(); | ||
|
|
||
| private: | ||
| const int beeper_pin_; | ||
| buttons::DebouncedButton snooze_button_; | ||
| Tone tones_[NUM_LEVELS]; | ||
|
|
||
| unsigned long snooze_time_ = 0; | ||
| unsigned long timeRemaining_ = 0; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alarms class still uses milliseconds to represent time (from before the convention was set). However, it's confusing to now set timeRemaining to be seconds. We should either switch everything to floats in seconds (ideal) or leave it in milliseconds consistently until a future update. |
||
| bool snoozed_ = false; | ||
|
|
||
| bool snoozeButtonPressed() const; | ||
|
|
@@ -155,6 +159,7 @@ class Beeper { | |
| void play(const AlarmLevel& alarm_level); | ||
|
|
||
| void stop(); | ||
|
|
||
| }; | ||
|
|
||
|
|
||
|
|
@@ -177,7 +182,7 @@ class Alarm { | |
| // for at least `min_good_to_clear_` consecutive calls with different `seq`. | ||
| void setCondition(const bool& bad, const unsigned long& seq); | ||
|
|
||
| // Set the alarm text (trim or pad to display width) | ||
| // Set the alarm text (trim or pad to footer width) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why to footer width when some alarms are in the header? |
||
| void setText(const String& text); | ||
|
|
||
| // Check if this alarm is on | ||
|
|
@@ -222,11 +227,17 @@ class AlarmManager { | |
| NO_TIDAL_PR, | ||
| OVER_CURREN, | ||
| MECH_FAILUR, | ||
| NOT_CONFIRM, | ||
| NOT_CONFIRM_TV, | ||
| NOT_CONFIRM_RR, | ||
| NOT_CONFIRM_IE, | ||
| NOT_CONFIRM_AC, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need separate alarms for each not_confirm? The old way was better since it's really the same alarm |
||
| TURNING_OFF, | ||
| NUM_ALARMS | ||
| }; | ||
|
|
||
| // Number of NOT_CONFIRM_XX alarms | ||
| static const int numConfirmKnob = 4; | ||
|
|
||
| public: | ||
| AlarmManager(const int& beeper_pin, const int& snooze_pin, const int& led_pin, | ||
| Display* displ, unsigned long const* cycle_count): | ||
|
|
@@ -235,15 +246,18 @@ class AlarmManager { | |
| led_pin_(led_pin), | ||
| led_pulse_(500, 0.5), | ||
| cycle_count_(cycle_count) { | ||
| alarms_[HIGH_PRESSU] = Alarm(" HIGH PRESSURE ", 1, 2, EMERGENCY); | ||
| alarms_[HIGH_PRESSU] = Alarm("HIGH PRESSURE ", 1, 2, EMERGENCY); | ||
| alarms_[LOW_PRESSUR] = Alarm("LOW PRES DISCONNECT?", 1, 1, EMERGENCY); | ||
| alarms_[BAD_PLATEAU] = Alarm(" HIGH RESIST PRES ", 1, 1, NOTIFY); | ||
| alarms_[UNMET_VOLUM] = Alarm(" UNMET TIDAL VOLUME ", 1, 1, EMERGENCY); | ||
| alarms_[NO_TIDAL_PR] = Alarm(" NO TIDAL PRESSURE ", 2, 1, EMERGENCY); | ||
| alarms_[OVER_CURREN] = Alarm(" OVER CURRENT FAULT ", 1, 2, EMERGENCY); | ||
| alarms_[MECH_FAILUR] = Alarm(" MECHANICAL FAILURE ", 1, 1, EMERGENCY); | ||
| alarms_[NOT_CONFIRM] = Alarm(" CONFIRM? ", 1, 1, NOTIFY); | ||
| alarms_[TURNING_OFF] = Alarm(" TURNING OFF ", 1, 1, OFF_LEVEL); | ||
| alarms_[BAD_PLATEAU] = Alarm("HIGH RESIST PRES ", 1, 1, NOTIFY); | ||
| alarms_[UNMET_VOLUM] = Alarm("UNMET TIDAL VOLUME ", 1, 1, EMERGENCY); | ||
| alarms_[NO_TIDAL_PR] = Alarm("NO TIDAL PRESSURE ", 2, 1, EMERGENCY); | ||
| alarms_[OVER_CURREN] = Alarm("OVER CURRENT FAULT ", 1, 2, EMERGENCY); | ||
| alarms_[MECH_FAILUR] = Alarm("MECHANICAL FAILURE ", 1, 1, EMERGENCY); | ||
| alarms_[NOT_CONFIRM_TV] = Alarm("CONFIRM? ", 1, 1, NOTIFY); | ||
| alarms_[NOT_CONFIRM_RR] = Alarm("CONFIRM? ", 1, 1, NOTIFY); | ||
| alarms_[NOT_CONFIRM_IE] = Alarm("CONFIRM? ", 1, 1, NOTIFY); | ||
| alarms_[NOT_CONFIRM_AC] = Alarm("CONFIRM? ", 1, 1, NOTIFY); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is all this duplicating of NOT_CONFIRM really needed? |
||
| alarms_[TURNING_OFF] = Alarm("TURNING OFF ", 1, 1, OFF_LEVEL); | ||
| } | ||
|
|
||
| // Setup during arduino setup() | ||
|
|
@@ -291,8 +305,13 @@ class AlarmManager { | |
| } | ||
|
|
||
| // Setting not confirmed | ||
| inline void unconfirmedChange(const bool& value, const String& message = "") { | ||
| if (value) { | ||
| inline void unconfirmedChange(const bool& value, const String& message = "", const display::DisplayKey& key = 0) { | ||
| Indices NOT_CONFIRM; | ||
| if (key == display::DisplayKey::VOLUME) { NOT_CONFIRM = NOT_CONFIRM_TV;} | ||
| if (key == display::DisplayKey::BPM) { NOT_CONFIRM = NOT_CONFIRM_RR;} | ||
| if (key == display::DisplayKey::IE_RATIO) { NOT_CONFIRM = NOT_CONFIRM_IE;} | ||
| if (key == display::DisplayKey::AC_TRIGGER) { NOT_CONFIRM = NOT_CONFIRM_AC;} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And here again... this will be very hard to maintain |
||
| if (value) { | ||
| alarms_[NOT_CONFIRM].setText(message); | ||
| } | ||
| alarms_[NOT_CONFIRM].setCondition(value, *cycle_count_); | ||
|
|
@@ -310,7 +329,7 @@ class AlarmManager { | |
| inline const bool& getNoTidalPres() { return alarms_[NO_TIDAL_PR].isON(); } | ||
| inline const bool& getOverCurrent() { return alarms_[OVER_CURREN].isON(); } | ||
| inline const bool& getMechanicalFailure() { return alarms_[MECH_FAILUR].isON(); } | ||
| inline const bool& getUnconfirmedChange() { return alarms_[NOT_CONFIRM].isON(); } | ||
| //inline const bool& getUnconfirmedChange() { return alarms_[NOT_CONFIRM].isON(); } | ||
| inline const bool& getTurningOFF() { return alarms_[TURNING_OFF].isON(); } | ||
|
|
||
| private: | ||
|
|
@@ -319,13 +338,24 @@ class AlarmManager { | |
| int led_pin_; | ||
| utils::Pulse led_pulse_; | ||
| Alarm alarms_[NUM_ALARMS]; | ||
| Alarm alarmsHeader_[NUM_ALARMS-numConfirmKnob]; | ||
| Alarm alarmsFooter_[numConfirmKnob]; | ||
| unsigned long const* cycle_count_; | ||
|
|
||
| // Get number of alarms that are ON | ||
| int numON() const; | ||
|
|
||
| // Get text to display | ||
| String getText() const; | ||
| // Get number of knob confirm alarms that are ON | ||
| int numON_Confirm() const; | ||
|
|
||
| // Get number of nonconfirm alarms that are ON | ||
| int numON_NonConfirm() const; | ||
|
|
||
| // Get general alarm text to display | ||
| String getGeneralAlarmText() const; | ||
|
|
||
| // Get unconfirmed knob alarm text to display | ||
| String getUnconfirmedKnobText() const; | ||
|
|
||
| // Get highest priority level of the alarms that are ON | ||
| AlarmLevel getHighestLevel() const; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not the expected behavior. Per expert guidance, the alarms should stay silent for the snooze time even when a new alarm emerges.
See https://emergency-vent.mit.edu/controls/list-of-alarms/