Skip to content

File SwitchWithCover2Pos.cpp

File List > Firmware > Libraries > PanelGroup > Inputs > SwitchWithCover2Pos > SwitchWithCover2Pos.cpp

Go to the documentation of this file

#ifdef ARDUINO_ARCH_STM32

#include "SwitchWithCover2Pos.h"
#include <CANProtocol.h>  // sendBatched, canIdEvt, ControlPacket
#include <STM32Board.h>

namespace OpenSkyhawk {

SwitchWithCover2Pos::SwitchWithCover2Pos(uint16_t switchId, uint16_t coverId, PinRef pin,
                                         bool reverse)
    : Switch2Pos(switchId, pin, reverse),
      _coverId(coverId),
      _state(Cover::OFF_CLOSED),
      _target(Cover::OFF_CLOSED),
      _lastStepMs(0) {}

void SwitchWithCover2Pos::emit(bool active, bool init) {
    _target = active ? Cover::ON_OPEN : Cover::OFF_CLOSED;

    // Boot / SYNC_REQ: re-assert BOTH frames, not just the one that would have changed. Seeding
    // the machine at the far end makes the sequencer walk the whole travel in the right order —
    // cover first when opening, switch first when closing (FirmwarePlan D5).
    if (init) _state = active ? Cover::OFF_CLOSED : Cover::ON_OPEN;

    // Back-date the step clock so the first frame goes on the next poll(): COVER_DELAY_MS is the
    // gap *between* the pair, not latency added before the first one.
    _lastStepMs = millis() - COVER_DELAY_MS;
}

void SwitchWithCover2Pos::poll() {
    Switch2Pos::poll();   // debounce; a confirmed change calls emit() above
    step();
}

void SwitchWithCover2Pos::step() {
    if (_state == _target) return;
    if ((uint32_t)(millis() - _lastStepMs) < COVER_DELAY_MS) return;

    // One position per step, and the frame is whatever that transition means.
    if (_target > _state) {
        _state = (Cover)((uint8_t)_state + 1);
        if (_state == Cover::OFF_OPEN) sendCover(true);     // OFF_CLOSED → OFF_OPEN
        else                           sendSwitch(true);    // OFF_OPEN   → ON_OPEN
    } else {
        _state = (Cover)((uint8_t)_state - 1);
        if (_state == Cover::OFF_OPEN) sendSwitch(false);   // ON_OPEN    → OFF_OPEN
        else                           sendCover(false);    // OFF_OPEN   → OFF_CLOSED
    }
    _lastStepMs = millis();
}

void SwitchWithCover2Pos::sendCover(bool open) {
    CANProtocol::sendBatched(canIdEvt(NODE_ID),
                             ControlPacket{_coverId, static_cast<uint16_t>(open ? 1u : 0u)});
    if (STM32Board::isDebug()) {
        auto& d = STM32Board::diagSerial();
        d.print(F("[SWC] cover 0x")); d.print(_coverId, HEX);
        d.print(F(": ")); d.println(open ? 1 : 0);
    }
}

void SwitchWithCover2Pos::sendSwitch(bool on) {
    CANProtocol::sendBatched(canIdEvt(NODE_ID),
                             ControlPacket{_controlId, static_cast<uint16_t>(on ? 1u : 0u)});
    if (STM32Board::isDebug()) {
        auto& d = STM32Board::diagSerial();
        d.print(F("[SWC] switch 0x")); d.print(_controlId, HEX);
        d.print(F(": ")); d.println(on ? 1 : 0);
    }
}

}  // namespace OpenSkyhawk

#endif  // ARDUINO_ARCH_STM32