/***************************************************************************
 *   Copyright (C) 2003-2005 by David Saxton                               *
 *   david@bluehaze.org                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#ifndef PICPACKAGES_H
#define PICPACKAGES_H

#include <QString>
#include <QStringList>

#include <QMap>

/**
@author David Saxton
*/
class PicPin
{
public:
    enum pin_type {
        type_input = 0x1, // Input only pin
        type_bidir = 0x2, // Bi-directional (input/output)
        type_open = 0x4,  // Open collector
        type_vss = 0x8,   // Voltage source
        type_vdd = 0x10,  // Voltage drain
        type_mclr = 0x20, // Memory clear
        type_osc = 0x40   // Oscillator
    };

    PicPin();
    PicPin(const QString &_pinID, PicPin::pin_type _type, const QString &_portName = "", int _portPosition = -1);

    PicPin::pin_type type;

    QString pinID; // Id of pin, eg 'MCLR'

    // For bidir (io) pins
    QString portName; // Name of port, eg 'PORTA'
    int portPosition; // Position in port
};

typedef QMap<int, PicPin> PicPinMap;

/**
@short Describes the PIC package (i.e. pins)
@author David Saxton
*/
class MicroPackage
{
public:
    MicroPackage(const int pinCount);
    virtual ~MicroPackage();

    /**
     * Assigns a pin to a position in the package.
     */
    void assignPin(int pinPosition, PicPin::pin_type type, const QString &pinID, const QString &portName = "", int portPosition = -1);
    void assignPin(int pinPosition, PicPin::pin_type type, const char *pinID, const char *portName = "", int portPosition = -1)
    {
        assignPin(pinPosition, type, QString::fromLatin1(pinID), QString::fromLatin1(portName), portPosition);
    }

    /**
     * Returns the pins of the given type(s). If portName is not specified, all pins will be returned;
     * not just those belonging to a given port. pin_type's can be OR'ed together
     * e.g. pins( PicPin::type_input | PicPin::type_bidir, "PORTA" ) will return all bidirectional or
     * input pins belonging to PORTA. If pinType is 0, then this will return all pins
     */
    PicPinMap pins(uint pinType = 0, const QString &portName = "");
    /**
     * Returns just a QStringList of the pin ids.
     * @see pins( uint pinType, const QString& portName )
     */
    QStringList pinIDs(uint pinType = 0, const QString &portName = "");
    /**
     * Returns the number of pins of the given type(s) (which can be OR'ed together), with the given
     * port name if specified, while avoiding the construction of a new PicPinMap. if pinType is 0,
     * then all pin types are considered
     * @see pins
     */
    int pinCount(uint pinType = 0, const QString &portName = "");
    /**
     * Returns a list of port names, eg 'PORTA', 'PORTB' for the package
     */
    QStringList portNames() const
    {
        return m_portNames;
    }
    /**
     * Returns the number of ports
     */
    uint portCount() const
    {
        return m_portNames.size();
    }

private:
    PicPinMap m_picPinMap;
    QStringList m_portNames;
    int m_numPins;
};

#endif
