lamp.cpp 6.96 KB
/*
 * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm)
 *
 * Licensed under GNU General Public License 3.0 or later.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "lamp.hpp"

#include "lamp_helper.hpp"

#define DAPC_TIME_MS 200

namespace dali {
namespace controller {

Lamp::Lamp(ILamp* lamp, Memory* memoryController)
    : mLamp(lamp)
    , mMemoryController(memoryController)
    , mLampState(ILamp::ILampState::OK)
    , mListener(nullptr)
    , mIsPowerSet(false)
    , mLimitError(false)
    , mDapcTime(0)
    , mConstPower(DALI_MASK) {
  mLamp->registerClient(this);
  setLevel(mMemoryController->getPhisicalMinLevel(), 0);
}

Lamp::~Lamp() {
  mLamp->unregisterClient(this);
}

void Lamp::onReset() {
  setLevel(mMemoryController->getMaxLevel(), 0);
  mIsPowerSet = true;
}

bool Lamp::isPowerOn() {
  return (mLamp->getLevel() > 0);
}

bool Lamp::isFailure() {
  switch (mLampState) {
  case ILamp::ILampState::DISCONNECTED:
  case ILamp::ILampState::OVERHEAT:
    return true;
  default:
    return false;
  }
}

bool Lamp::isFading() {
  return mLamp->isFading();
}

bool Lamp::isLimitError() {
  return mLimitError;
}

bool Lamp::isPowerSet() {
  return mIsPowerSet;
}

uint8_t Lamp::getLevel() {
  if (mLampState == ILamp::ILampState::OK) {
    return driver2level(mLamp->getLevel(), mMemoryController->getMinLevel());
  }
  return mMemoryController->getActualLevel();
}

Status Lamp::setLevel(uint8_t level, uint32_t fadeTime) {
  mLimitError = false;

  Status status = Status::OK;
  if (level != DALI_MASK) {
    uint8_t minLevel = mMemoryController->getMinLevel();
    uint8_t maxLevel = mMemoryController->getMaxLevel();

    if ((level != 0) && (level < minLevel)) {
      mLimitError = true;
      level = minLevel;
    }
    if (level > maxLevel) {
      mLimitError = true;
      level = maxLevel;
    }

    mLamp->setLevel(level2driver(level), fadeTime);
    status = mMemoryController->setActualLevel(level);
  }
  return status;
}

uint32_t Lamp::getFadeTime() {
  return kFadeTime[mMemoryController->getFadeTime()];
}

uint32_t Lamp::getFadeRate() {
  return kFadeTime[mMemoryController->getFadeRate()];
}

Status Lamp::abortFading() {
  if (mLamp->isFading()) {
    mLamp->abortFading();
    uint8_t level = driver2level(mLamp->getLevel(), mMemoryController->getMinLevel());
    return mMemoryController->setActualLevel(level);
  }
  return Status::OK;
}

void Lamp::setListener(Listener* listener) {
  mListener = listener;
}

void Lamp::notifyPowerDown() {
  mLamp->setLevel(0, 0);
}

Status Lamp::powerDirect(uint8_t level, uint64_t time) {
  if (level == DALI_MASK) {
    mLamp->abortFading();
    return Status::OK;
  }
  if (time - mDapcTime <= DAPC_TIME_MS) {
    return dapcSequence(level, time);
  }
  onPowerCommand();
  return setLevel(level, getFadeTime());
}

Status Lamp::powerOff() {
  onPowerCommand();
  return setLevel(0, 0);
}

Status Lamp::powerScene(uint8_t scene) {
  uint8_t level = mMemoryController->getLevelForScene(scene);
  if (level == DALI_MASK) {
    level = mMemoryController->getActualLevel();
  }
  onPowerCommand();
  return setLevel(level, getFadeTime());
}

Status Lamp::powerUp() {
  onPowerCommand();
  uint8_t fade = mMemoryController->getFadeRate();
  uint8_t steps = kStepsFor200FadeRate[fade];
  uint8_t level = getLevel();
  uint8_t maxLevel = mMemoryController->getMaxLevel();
  if ((int16_t) level + steps > (int16_t) maxLevel) {
    level = maxLevel;
  } else {
    level += steps;
  }
  return setLevel(level, kFadeTime[fade]);
}

Status Lamp::powerDown() {
  onPowerCommand();
  uint8_t fade = mMemoryController->getFadeRate();
  uint8_t steps = kStepsFor200FadeRate[fade];
  uint8_t level = getLevel();
  uint8_t minLevel = mMemoryController->getMinLevel();
  if ((int16_t) level - steps < (int16_t) minLevel) {
    level = minLevel;
  } else {
    level -= steps;
  }
  return setLevel(level, kFadeTime[fade]);
}

Status Lamp::powerStepUp() {
  onPowerCommand();
  uint8_t level = getLevel();
  uint8_t maxLevel = mMemoryController->getMaxLevel();
  if (level >= maxLevel) {
    level = maxLevel;
  } else {
    level++;
  }
  return setLevel(level, 0);
}

Status Lamp::powerStepDown() {
  onPowerCommand();
  uint8_t level = getLevel();
  uint8_t minLevel = mMemoryController->getMinLevel();
  if (level <= minLevel) {
    level = minLevel;
  } else {
    level--;
  }
  return setLevel(level, 0);
}

Status Lamp::powerOnAndStepUp() {
  onPowerCommand();
  uint8_t level = getLevel();
  if (level == 0) {
    level = mMemoryController->getMinLevel();
  } else {
    uint8_t maxLevel = mMemoryController->getMaxLevel();
    if (level >= maxLevel) {
      level = maxLevel;
    } else {
      level++;
    }
  }
  return setLevel(level, 0);
}

Status Lamp::powerStepDownAndOff() {
  onPowerCommand();
  uint8_t level = getLevel();
  uint8_t minLevel = mMemoryController->getMinLevel();
  if (level <= minLevel) {
    level = 0;
  } else {
    level--;
  }
  return setLevel(level, 0);
}

Status Lamp::powerRecallMinLevel() {
  onPowerCommand();
  return setLevel(mMemoryController->getMinLevel(), 0);
}

Status Lamp::powerRecallMaxLevel() {
  onPowerCommand();
  return setLevel(mMemoryController->getMaxLevel(), 0);
}

Status Lamp::powerRecallOnLevel() {
  if (mIsPowerSet) {
    return Status::INVALID;
  }
  uint8_t level = mMemoryController->getPowerOnLevel();
  if (level == DALI_MASK) {
    level = mMemoryController->getActualLevel();
  }
  return setLevel(level, 0);
}

Status Lamp::powerRecallFaliureLevel() {
  // TODO change mIsPowerSet if called before power on?
  uint8_t level = mMemoryController->getFaliureLevel();
  if (level == DALI_MASK) {
    level = mMemoryController->getActualLevel();
  }
  return setLevel(level, 0);
}

Status Lamp::enableDapcSequence(uint64_t time) {
  mDapcTime = time;
  return Status::OK;
}

Status Lamp::dapcSequence(uint8_t level, uint64_t time) {
  onPowerCommand();
  mDapcTime = time;
  uint8_t actualLevel = getLevel();
  if (actualLevel == 0) {
    // If the actual arc power level is zero, the new level shall be adopted without fading.
    return setLevel(level, 0);
  }
  int16_t deltaLevel = (int32_t) level - actualLevel;
  if (deltaLevel < 0)
    deltaLevel = -deltaLevel;
  if (deltaLevel == 0)
    return Status::OK;
  // deltaLevel should change in 200ms
  int32_t fadeTime = (uint32_t) DALI_LEVEL_MAX * DAPC_TIME_MS / deltaLevel;
  return setLevel(level, (uint32_t) fadeTime);
}

void Lamp::onPowerCommand() {
  mDapcTime = 0;
  mIsPowerSet = true;
}

void Lamp::onLampStateChnaged(ILamp::ILampState state) {
  mLampState = state;
  mListener->onLampStateChnaged(state);
}

} // namespace controller
} // namespace dali