/*
 * SmartHome server: Plug-in x10
 *
 * Copyright (C) 2010 Daniel Pisi <dan.pisi@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License
 * as published by the Free Software Foundation.
 *
 */

/**
 * @file x10packet.cpp
 * @brief Stores one X10 packet
 * @author Daniel Pisi
 */

#include "x10packet.h"

const quint8 x10enc[16] = {0x06, 0x0E, 0x02, 0x0A, 0x01, 0x09, 0x05, 0x0D, 0x07, 0x0F, 0x03, 0x0B, 0x00, 0x08, 0x04, 0x0C};

// -----------------------------------------------------------------------------

/**
 * \brief Constructor of X10Packet, an initialization of the object
 */
X10Packet::X10Packet()
{
    mDimAmount = 0;
    mFa = mEs = false;

    mHousecode = 0;
    mData = 0;

    mChecksum = 0;
    mModified = false;
}
// -----------------------------------------------------------------------------

/**
 * \brief Sets the housecode
 * \param housecode Housecode
 * \return true if the housecode has been set successfully
 */
bool X10Packet::setHousecode(quint8 housecode)
{
    if ((housecode >= 'A') && (housecode <= 'P'))
    {
        mHousecode = x10enc[housecode - 'A'];
        mModified  = true;
        return true;
    }
    else
        return false;
}
// -----------------------------------------------------------------------------

/**
 * \brief Sets the devicecode
 * \param devicecode Devicecode
 * \return true if the devicecode has been set successfully
 */
bool X10Packet::setDevicecode(quint8 devicecode)
{
    if ((devicecode  >= 1) && (devicecode <= 16))
    {
        mData      = x10enc[devicecode - 1];
        mFa        = false;
        mEs        = false;
        mModified  = true;
        return true;
    }
    else
        return false;
}
// -----------------------------------------------------------------------------

/**
 * \brief Sets the command
 * \param function Command
 * \return true if the command has been set successfully
 */
bool X10Packet::setFunction(X10Function function)
{
    if ((function == X10Packet::fcAllUnitsOff) ||
        (function == X10Packet::fcAllLightsOn) || (function == X10Packet::fcAllLightsOff) ||
        (function == X10Packet::fcOn) || (function == X10Packet::fcOff) ||
        (function == X10Packet::fcDim) || (function == X10Packet::fcBright))
    {
        mData      = (quint8)function;
        mFa        = true;
        mEs        = false;
        mModified  = true;
        return true;
    }
    else
        return false;
}
// -----------------------------------------------------------------------------

/**
 * \brief Sets the number of dim steps
 * \param dim Number of dim steps
 * \return true if the number of dim steps has been set successfully
 */
bool X10Packet::setDimAmount(quint8 dim)
{
    mDimAmount = qMin(dim, (quint8)22);
    mModified  = true;
    return true;
}
// -----------------------------------------------------------------------------

/**
 * \brief Generates the raw packet data
 * \return Generated packet data
 */
QByteArray X10Packet::frameData()
{
    char data[2];

    data[0]  = (mDimAmount & 0x1F) << 3;
    data[0] |= 0x04;
    data[0] |= (mFa ? 0x02 : 0x00);
    data[0] |= (mEs ? 0x01 : 0x00);

    data[1]  = (mHousecode & 0x0F) << 4;
    data[1] |= (mData & 0x0F);

    return QByteArray(data, 2);
}
// -----------------------------------------------------------------------------

/**
 * \brief Calculates a checksum of the packet
 * \return Checksum of the packet
 */
quint8 X10Packet::checksum()
{
    if (mModified)
    {
        QByteArray frame = frameData();

        mChecksum = (frame[0] + frame[1]) & 0xFF;
        mModified = false;
    }

    return mChecksum;
}
// -----------------------------------------------------------------------------
