Handle flag for NEGATIVE time; unify time incrementing

This commit is contained in:
Allen Hill
2026-08-13 17:47:31 -07:00
parent 0bef565564
commit 5d6b5f4ce0
2 changed files with 43 additions and 36 deletions
+40 -34
View File
@@ -167,7 +167,7 @@ void CDChanger::handle(const Frame &in, Frame &out) {
track = 1; track = 1;
mins = 0xff; mins = 0xff;
secs = 0x7f; secs = 0x7f;
flags2 = 0xc0; flags2 &= ~NEGATIVE;
generateStatus(out, true, Device::CMD_SW); generateStatus(out, true, Device::CMD_SW);
media_action(MediaAction::Track_Next); media_action(MediaAction::Track_Next);
out.reaction = r_TrackChange; out.reaction = r_TrackChange;
@@ -175,7 +175,7 @@ void CDChanger::handle(const Frame &in, Frame &out) {
case Track_Seek_Down: case Track_Seek_Down:
state = SEEKING_TRACK; state = SEEKING_TRACK;
// Track down returns to track beginning if in ~middle of song // Track down returns to track beginning if in ~middle of song
if (mins == 0 && secs < 5) { if ((flags2 & NEGATIVE) != 0 || (mins == 0 && secs < 5)) {
if (track > 1) if (track > 1)
--track; --track;
else else
@@ -185,17 +185,13 @@ void CDChanger::handle(const Frame &in, Frame &out) {
} }
mins = 0xff; mins = 0xff;
secs = 0x7f; secs = 0x7f;
flags2 = 0xc0; flags2 &= ~NEGATIVE;
generateStatus(out, true, Device::CMD_SW); generateStatus(out, true, Device::CMD_SW);
out.reaction = r_TrackChange; out.reaction = r_TrackChange;
break; break;
case Track_Fast_Forward: { case Track_Fast_Forward: {
state |= SEEKING; state |= SEEKING;
secs += TIME_SKIP; incrementTime(TIME_SKIP);
if (secs > 59) {
secs -= 60;
++mins;
}
generateStatus(out, true, Device::CMD_SW); generateStatus(out, true, Device::CMD_SW);
media_action(MediaAction::Skip_Forward); media_action(MediaAction::Skip_Forward);
cdtimer_reset(); // Skipped to a whole/round sec; ensure next tick cdtimer_reset(); // Skipped to a whole/round sec; ensure next tick
@@ -205,17 +201,7 @@ void CDChanger::handle(const Frame &in, Frame &out) {
} }
case Track_Rewind: { case Track_Rewind: {
state |= SEEKING; state |= SEEKING;
if (secs < TIME_SKIP) { incrementTime(-TIME_SKIP);
if (mins > 0) {
const uint8_t dif = TIME_SKIP - secs;
secs = 60 - dif;
--mins;
} else {
mins = 0;
secs = 0;
}
} else
secs -= TIME_SKIP;
generateStatus(out, true, Device::CMD_SW); generateStatus(out, true, Device::CMD_SW);
media_action(MediaAction::Skip_Backward); media_action(MediaAction::Skip_Backward);
cdtimer_reset(); // Skipped to a whole/round sec; ensure next tick cdtimer_reset(); // Skipped to a whole/round sec; ensure next tick
@@ -268,8 +254,8 @@ void CDChanger::handle(const Frame &in, Frame &out) {
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
} }
std::unique_ptr<Frame> CDChanger::react( std::unique_ptr<Frame>
expected<std::unique_ptr<Frame>, detail::SendError> exp) { CDChanger::react(expected<std::unique_ptr<Frame>, detail::SendError> exp) {
if (!exp) { if (!exp) {
if (exp.error().reaction == to_underlying(r_StateReport) && if (exp.error().reaction == to_underlying(r_StateReport) &&
@@ -277,7 +263,7 @@ std::unique_ptr<Frame> CDChanger::react(
++failedStatusReports > 1) { ++failedStatusReports > 1) {
failedStatusReports = 0; failedStatusReports = 0;
stopPlaying(); // Disable periodic updates if e.g. no-one's stopPlaying(); // Disable periodic updates if e.g. no-one's
// listening (car was turned off?) // listening (car was turned off?)
} }
} else { } else {
auto out = std::move(exp.value()); auto out = std::move(exp.value());
@@ -348,7 +334,7 @@ void CDChanger::enable(Frame &out) {
if (secs > TWODIGIT_MAX) if (secs > TWODIGIT_MAX)
secs = 0; secs = 0;
state = SEEKING | SEEKING_TRACK; state = SEEKING | SEEKING_TRACK;
flags2 = 0xc0; flags2 = 0x80;
generateStatus(out, false, Device::STATUS); generateStatus(out, false, Device::STATUS);
out.reaction = r_StartPlaying; out.reaction = r_StartPlaying;
} }
@@ -399,19 +385,40 @@ void CDChanger::setTime(uint8_t min, uint8_t sec) {
secs = sec; secs = sec;
} }
void CDChanger::incrementTime() { // Increment the time by inc_sec (REQUIRES |inc_sec| <= 59).
void CDChanger::incrementTime(int8_t inc_sec) {
// Sentinel values (>TWODIGIT_MAX) mean "no time"; leave them alone until // Sentinel values (>TWODIGIT_MAX) mean "no time"; leave them alone until
// setTime() replaces them with a real count. // setTime() replaces them with a real count.
if (secs > TWODIGIT_MAX) if (mins > TWODIGIT_MAX)
return; return;
if (secs == 59) {
secs = 0; if ((flags2 & NEGATIVE) != 0)
if (mins == TWODIGIT_MAX) inc_sec = -inc_sec; // time forward shrinks a negative magnitude
mins = 0; int8_t sum = secs + inc_sec;
else
mins++; if (sum < 0 && mins == 0) {
} else // Stepped through zero: the display flips sign and counts away from it.
secs++; secs = (uint8_t)-sum;
flags2 ^= NEGATIVE;
return;
}
if (sum > 59) {
if (mins == TWODIGIT_MAX) { // saturate at 99:59 rather than wrap the hour
secs = 59;
return;
}
sum -= 60;
++mins;
} else if (sum < 0) {
sum += 60;
--mins; // mins > 0: the mins == 0 borrow was handled above
}
secs = (uint8_t)sum;
// Zero is neither sign, so it must never display as -00:00.
if ((mins | secs) == 0)
flags2 &= ~NEGATIVE;
} }
// Used for changed status messages // Used for changed status messages
@@ -439,7 +446,6 @@ void CDChanger::normalizeState() {
secs = 0; secs = 0;
state = PLAYBACK; state = PLAYBACK;
flags &= (uint8_t)~(DISK_SCAN | SCAN); flags &= (uint8_t)~(DISK_SCAN | SCAN);
flags2 = 0x80;
} }
#ifndef NDEBUG #ifndef NDEBUG
+3 -2
View File
@@ -39,6 +39,7 @@ public:
REPEAT = 1 << 4, REPEAT = 1 << 4,
DISK_SCAN = 1 << 5, DISK_SCAN = 1 << 5,
SCAN = 1 << 6, SCAN = 1 << 6,
NEGATIVE = 1 << 6,
}; };
/// Message state machine /// Message state machine
@@ -68,7 +69,7 @@ public:
void disable(Frame &out); void disable(Frame &out);
static bool pending(); static bool pending();
void emit(Frame &out); void emit(Frame &out);
void incrementTime(); void incrementTime(int8_t inc_sec = 1);
bool isPlaying() const; bool isPlaying() const;
#ifndef NDEBUG #ifndef NDEBUG
void media_action(MediaAction action); void media_action(MediaAction action);
@@ -93,7 +94,7 @@ private:
uint8_t mins = 0xFF; // Decimal storage; serialize to BCD uint8_t mins = 0xFF; // Decimal storage; serialize to BCD
uint8_t secs = 0x7F; // Decimal storage; serialize to BCD uint8_t secs = 0x7F; // Decimal storage; serialize to BCD
uint8_t flags = 0; uint8_t flags = 0;
uint8_t flags2 = 0xC0; uint8_t flags2 = 0x80;
}; };
} // namespace avclan } // namespace avclan