<commit_before>#include "alfe/main.h"

class Symbol
{
public:
    Symbol() : _cookie(_nextCookie) { ++_nextCookie; }
    bool operator==(Symbol other) { return _cookie == other._cookie; }
    bool operator!=(Symbol other) { return _cookie != other._cookie; }
    UInt32 hash(int t) { return Hash(typeid(Symbol)).mixin(_cookie); }
private:
    static int _nextCookie;
    int _cookie;
};

int Symbol::_nextCookie = 0;

Symbol zero;
Symbol unknown;

class Register
{
public:
    Register(String name, int binaryEncoding, int width)
      : _name(name), _binaryEncoding(binaryEncoding), _width(width) { }
    Word value() { return _value; }
    bool isConstant() { return _symbol == zero; }
    virtual void assign(T value, Symbol symbol)
    {
        _value = value;
        _symbol = symbol;
        for (auto& i : _partOf)
            i->partAssigned(value, symbol, this);
    }
    bool hasValue(Word v) { return isConstant() && value() == v; }
    void clear() { assign(0, unknown); }
    void makePartOf(Register* larger)
    {
        _partOf.append(larger);
    }
    virtual void partAssigned(Word value, Symbol symbol, Register* part) { }
protected:
    String _name;
    int _width;
    int _binaryEncoding;
    Word _value;
    Symbol _symbol;
    AppendableArray<Register*> _partOf;
};

class CompoundRegister : public Register
{
public:
    CompoundRegister(String name, int binaryEncoding, Register* lowPart,
        Register* highPart)
      : Register(name, binaryEncoding, lowPart->_width + highPart->_width),
        _lowPart(lowPart), _highPart(highPart)
    {
        lowPart->makePartOf(this);
        highPart->makePartOf(this);
    }
    void assign(Word value, Symbol symbol)
    {
        Register::assign(value, symbol);
        int shift = 8 * lowPart->_width;
        // Assign direcly instead of going through assign to avoid sprious
        // partAssigned() calls.
        _lowPart->_value = value & ((1 << shift) - 1);
        _lowPart->_symbol = symbol;
        _highPart->_value = value >> shift;
        _highPart->_symbol = (symbol == zero ? zero : unknown);
    }
    void partAssigned(Word value, Symbol symbol, Register* part)
    {
        int shift = 8 * lowPart->_width;
        if (part == _lowPart) {
            _value = (_highPart->_value << shift) | value;
            if (symbol != _symbol) {
                if (_highPart->_symbol == zero && symbol == zero)
                    _symbol = zero;
                else
                    _symbol = unknown;
            }
        }
        else {
            _value = _lowPart->_value | (value << shift);
            if (_lowPart->_symbol == zero && symbol == zero)
                _symbol = zero;
            else
                _symbol = unknown;
        }
    }
private:
    Register<T2>* _lowPart;
    Register<T2>* _highPart;
    int _binaryEncoding;
};

RegisterFile registerFile;
Register al("al", 0, 1);
Register cl("cl", 1, 1);
Register dl("dl", 2, 1);
Register bl("bl", 3, 1);
Register ah("ah", 4, 1);
Register ch("ch", 5, 1);
Register dh("dh", 6, 1);
Register bh("bh", 7, 1);
CompoundRegister ax("ax", 0, &al, &ah);
CompoundRegister cx("cx", 1, &cl, &dh);
CompoundRegister dx("dx", 2, &dl, &dh);
CompoundRegister bx("bx", 3, &bl, &bh);
Register sp("sp", 4, 2);
Register bp("bp", 5, 2);
Register si("si", 6, 2);
Register di("di", 7, 2);
Register es("es", 0, 2);
Register cs("cs", 1, 2);
Register ss("ss", 2, 2);
Register ds("ds", 3, 2);
Register ip("ip", 0, 2);
Register flags("flags", 0, 2);

class Instruction : public LinkedListMember<Instruction>
{
};

class MovInstruction : public Instruction
{
public:
    MovInstruction(Operand destination, Operand source)
      : _destination(destination), _source(source)
    { }
private:
    Operand _destination;
    Operand _source;

};

class LabelInstruction : public Instruction
{
};

class InstructionChain
{
public:
    void add(Instruction* instruction) { _instructions.add(instruction); }
private:
    OwningLinkedList<Instruction> _instructions;
};

class Operand
{
};

void emit_mov(InstructionChain chain, Operand destination, Operand source)
{
    chain.add(MovInstruction(destination, source));
}

void out(Operand port, Operand value)
{
    if (port >= 0x100)
        mov(dx, port);
    if (value.size() == 1) {
        mov(al, value);
        if (dx.value() == port
    }
    else
        mov(ax, value);

}

class SetInstruction
{
public:
    SetInstruction(Register* destination, Word value, Symbol symbol = zero)
      : _destination(destination), _value(value), _symbol(symbol) { }
    Instruction* expand()
    {
        if (dynamic_cast<CPURegister*>(destination) != 0)
            return this;

        if (symbol == zero) {
            if (destination->symbol() == zero) {
                auto pr = dynamic_cast<IndexedPortRegister*>(destination);
                if (pr != 0) {
                    insertBefore(new SetInstruction(pr->indexRegister(),
                        pr->indexValue());
                }
                insertBefore(new PortWriteByteInstruction(pr->registerPort(),
                    value);

            }
            else {

            }
        }
        else {

        }

    }
private:
    Register* _destination;
    Word _value;
    Symbol _symbol;
};

static const Word port_CGA_status = 0x3da;
static const Byte mask_CGA_notDisplayEnable = 1;
static const Byte mask_CGA_verticalSync = 8;

class CGAWaitForDisplayEnableInstruction : public Instruction
{
public:
    Instruction* expand()
    {
        insertBefore(new SetInstruction(&dx, port_CGA_status));
        LabelInstruction wait = new LabelInstruction();
        insertBefore(wait);
        insertBefore(new INInstruction(&al, &dx));
        insertBefore(new TESTInstruction(&al, mask_CGA_notDisplayEnable));
        insertBefore(new JNZInstruction(wait));
        Instruction* r = previous();
        remove();
        return r;
    }
};

class CGAWaitForDisplayDisableInstruction : public Instruction
{
public:
    Instruction* expand()
    {
        insertBefore(new SetInstruction(&dx, port_CGA_status));
        LabelInstruction wait = new LabelInstruction();
        insertBefore(wait);
        insertBefore(new INInstruction(&al, &dx));
        insertBefore(new TESTInstruction(&al, mask_CGA_notDisplayEnable));
        insertBefore(new JZInstruction(wait));
        Instruction* r = previous();
        remove();
        return r;
    }
};

class CGAWaitForVerticalSyncInstruction : public Instruction
{
public:
    Instruction* expand()
    {
        insertBefore(new SetInstruction(&dx, port_CGA_status));
        LabelInstruction wait = new LabelInstruction();
        insertBefore(wait);
        insertBefore(new INInstruction(&al, &dx));
        insertBefore(new TESTInstruction(&al, mask_CGA_verticalSync));
        insertBefore(new JZInstruction(wait));
        Instruction* r = previous();
        remove();
        return r;
    }
};

class CGAWaitForNoVerticalSyncInstruction : public Instruction
{
public:
    Instruction* expand()
    {
        insertBefore(new SetInstruction(&dx, port_CGA_status));
        LabelInstruction wait = new LabelInstruction();
        insertBefore(wait);
        insertBefore(new INInstruction(&al, &dx));
        insertBefore(new TESTInstruction(&al, mask_CGA_verticalSync));
        insertBefore(new JNZInstruction(wait));
        Instruction* r = previous();
        remove();
        return r;
    }
};

class Program : public ProgramBase
{
public:
    void run()
    {

    }
};
<commit_msg>More assembler work<commit_after>#include "alfe/main.h"

class Symbol
{
public:
    Symbol() : _cookie(_nextCookie) { ++_nextCookie; }
    bool operator==(Symbol other) { return _cookie == other._cookie; }
    bool operator!=(Symbol other) { return _cookie != other._cookie; }
    UInt32 hash(int t) { return Hash(typeid(Symbol)).mixin(_cookie); }
private:
    static int _nextCookie;
    int _cookie;
};

int Symbol::_nextCookie = 0;

Symbol zero;
Symbol unknown;

class Register
{
public:
    Register(String name, int binaryEncoding, int width)
      : _name(name), _binaryEncoding(binaryEncoding), _width(width) { }
    Word value() { return _value; }
    bool isConstant() { return _symbol == zero; }
    virtual void assign(T value, Symbol symbol)
    {
        _value = value;
        _symbol = symbol;
        for (auto& i : _partOf)
            i->partAssigned(value, symbol, this);
    }
    bool hasValue(Word v) { return isConstant() && value() == v; }
    void clear() { assign(0, unknown); }
    void makePartOf(Register* larger)
    {
        _partOf.append(larger);
    }
    virtual void partAssigned(Word value, Symbol symbol, Register* part) { }
protected:
    String _name;
    int _width;
    int _binaryEncoding;
    Word _value;
    Symbol _symbol;
    AppendableArray<Register*> _partOf;
};

class CompoundRegister : public Register
{
public:
    CompoundRegister(String name, int binaryEncoding, Register* lowPart,
        Register* highPart)
      : Register(name, binaryEncoding, lowPart->_width + highPart->_width),
        _lowPart(lowPart), _highPart(highPart)
    {
        lowPart->makePartOf(this);
        highPart->makePartOf(this);
    }
    void assign(Word value, Symbol symbol)
    {
        Register::assign(value, symbol);
        int shift = 8 * lowPart->_width;
        // Assign direcly instead of going through assign to avoid sprious
        // partAssigned() calls.
        _lowPart->_value = value & ((1 << shift) - 1);
        _lowPart->_symbol = symbol;
        _highPart->_value = value >> shift;
        _highPart->_symbol = (symbol == zero ? zero : unknown);
    }
    void partAssigned(Word value, Symbol symbol, Register* part)
    {
        int shift = 8 * lowPart->_width;
        if (part == _lowPart) {
            _value = (_highPart->_value << shift) | value;
            if (symbol != _symbol) {
                if (_highPart->_symbol == zero && symbol == zero)
                    _symbol = zero;
                else
                    _symbol = unknown;
            }
        }
        else {
            _value = _lowPart->_value | (value << shift);
            if (_lowPart->_symbol == zero && symbol == zero)
                _symbol = zero;
            else
                _symbol = unknown;
        }
    }
private:
    Register<T2>* _lowPart;
    Register<T2>* _highPart;
    int _binaryEncoding;
};

RegisterFile registerFile;
Register al("al", 0, 1);
Register cl("cl", 1, 1);
Register dl("dl", 2, 1);
Register bl("bl", 3, 1);
Register ah("ah", 4, 1);
Register ch("ch", 5, 1);
Register dh("dh", 6, 1);
Register bh("bh", 7, 1);
CompoundRegister ax("ax", 0, &al, &ah);
CompoundRegister cx("cx", 1, &cl, &dh);
CompoundRegister dx("dx", 2, &dl, &dh);
CompoundRegister bx("bx", 3, &bl, &bh);
Register sp("sp", 4, 2);
Register bp("bp", 5, 2);
Register si("si", 6, 2);
Register di("di", 7, 2);
Register es("es", 0, 2);
Register cs("cs", 1, 2);
Register ss("ss", 2, 2);
Register ds("ds", 3, 2);
Register ip("ip", 0, 2);
Register flags("flags", 0, 2);

class Instruction : public LinkedListMember<Instruction>
{
};

class MovInstruction : public Instruction
{
public:
    MovInstruction(Operand destination, Operand source)
      : _destination(destination), _source(source)
    { }
private:
    Operand _destination;
    Operand _source;

};

class LabelInstruction : public Instruction
{
};

class InstructionChain
{
public:
    void add(Instruction* instruction) { _instructions.add(instruction); }
private:
    OwningLinkedList<Instruction> _instructions;
};

class Operand
{
};

void emit_mov(InstructionChain chain, Operand destination, Operand source)
{
    chain.add(MovInstruction(destination, source));
}

void out(Operand port, Operand value)
{
    if (port >= 0x100)
        mov(dx, port);
    if (value.size() == 1) {
        mov(al, value);
        if (dx.value() == port
    }
    else
        mov(ax, value);

}

class SetInstruction
{
public:
    SetInstruction(Register* destination, Word value, Symbol symbol = zero)
      : _destination(destination), _value(value), _symbol(symbol) { }
    Instruction* expand()
    {
        if (dynamic_cast<CPURegister*>(_destination) != 0)
            return this;

        if (_symbol == zero) {
            if (_destination->symbol() == zero) {
                auto pr = dynamic_cast<PortRegister*>(_destionation);
                if (pr != 0) {
                    auto ipr = dynamic_cast<IndexedPortRegister*>(pr);
                    if (ipr != 0) {
                        insertBefore(new SetInstruction(ipr->indexRegister(),
                            ipr->indexValue());
                    }
                    insertBefore(new PortWriteByteInstruction(
                        pr->registerPort(), value);
                    insertBefore(new SetNote(_destination, _value, _symbol));
                    Instruction* r = previous();
                    remove();
                    return r;
                }
                else {
                    if (!_destination->hasValue(_value)) {

                    }
                }
            }
            else {

            }
        }
        else {

        }

    }
private:
    Register* _destination;
    Word _value;
    Symbol _symbol;
};

static const Word port_CGA_status = 0x3da;
static const Byte mask_CGA_notDisplayEnable = 1;
static const Byte mask_CGA_verticalSync = 8;

class CGAWaitForDisplayEnableInstruction : public Instruction
{
public:
    Instruction* expand()
    {
        insertBefore(new SetInstruction(&dx, port_CGA_status));
        LabelInstruction wait = new LabelInstruction();
        insertBefore(wait);
        insertBefore(new INInstruction(&al, &dx));
        insertBefore(new TESTInstruction(&al, mask_CGA_notDisplayEnable));
        insertBefore(new JNZInstruction(wait));
        Instruction* r = previous();
        remove();
        return r;
    }
};

class CGAWaitForDisplayDisableInstruction : public Instruction
{
public:
    Instruction* expand()
    {
        insertBefore(new SetInstruction(&dx, port_CGA_status));
        LabelInstruction wait = new LabelInstruction();
        insertBefore(wait);
        insertBefore(new INInstruction(&al, &dx));
        insertBefore(new TESTInstruction(&al, mask_CGA_notDisplayEnable));
        insertBefore(new JZInstruction(wait));
        Instruction* r = previous();
        remove();
        return r;
    }
};

class CGAWaitForVerticalSyncInstruction : public Instruction
{
public:
    Instruction* expand()
    {
        insertBefore(new SetInstruction(&dx, port_CGA_status));
        LabelInstruction wait = new LabelInstruction();
        insertBefore(wait);
        insertBefore(new INInstruction(&al, &dx));
        insertBefore(new TESTInstruction(&al, mask_CGA_verticalSync));
        insertBefore(new JZInstruction(wait));
        Instruction* r = previous();
        remove();
        return r;
    }
};

class CGAWaitForNoVerticalSyncInstruction : public Instruction
{
public:
    Instruction* expand()
    {
        insertBefore(new SetInstruction(&dx, port_CGA_status));
        LabelInstruction wait = new LabelInstruction();
        insertBefore(wait);
        insertBefore(new INInstruction(&al, &dx));
        insertBefore(new TESTInstruction(&al, mask_CGA_verticalSync));
        insertBefore(new JNZInstruction(wait));
        Instruction* r = previous();
        remove();
        return r;
    }
};

class Program : public ProgramBase
{
public:
    void run()
    {

    }
};
<|endoftext|>


<commit_before>/*-------------------------------
PASA LA CALCULADORA
Autores:
Jaime Sevilla Molina
Victor Gonzalez
Fecha
2014/11
Version: 1.0
---------------------------------*/

//BIBLIOTECAS
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
#include <cmath>
#include <fstream>
#include <iomanip>

using namespace std;

//TIPOS PROPIOS
typedef enum tJugador
{
	Nadie,
	Jugador,
	Automata
};

//FUNCIONES
//FUNCIONES DE JUEGO

void saludar ();

//Dependiendo de quien gane, la despedida sera distinta
void despedirse (tJugador ganador);

//Muestra un menu que permite al jugador jugar, salir, o ver las reglas del juego
int menu();

//Muestra las instrucciones del juego, siempre que su archivo no contenga errores
bool acerca();

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora();

//Decide aleatoriamente quien empieza.
tJugador quienEmpieza();
//Devuelve true si nuevo esta en la misma fila que ultimo
bool mismaFila(int ultimo, int nuevo);

//Devuelve true si nuevo esta en la misma columna que ultimo
bool mismaColumna(int ultimo, int nuevo);

//Devuelve true si nuevo cumple las reglas del juego con respecto a ultimo
//Si ultimo == 0, este es el primer digito de la partida, y devuelve true
bool digitoValido(int ultimo, int nuevo);

//FUNCIONES DE IA NIVEL 1
//Devuelve un digito del 1 al 9
int digitoAleatorio();

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo);

//FUNCIONES DE JUGADOR
//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona();

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo);

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n);

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo);

/* Las funciones a continuacion se implementaran en un futuro
//FUNCIONES DE INFORME
//Actualiza el archivo informePC.txt con los tres argumentos. En caso de no encontrar
//el archivo, lo crea y devuelve false; en otro caso devuelve true.
bool actInforme(int jugadas, int ganadas, int abandonos);

//FUNCIONES DE DIFICULTAD AVANZADA
int botDificil(int ultimo);

-----------------------------------------------------------------------------------*/

int main(){
	tJugador ganador;
	int opcion;

	saludar();

	//Bucle Menu
	do{
		opcion = menu();
		if(opcion == 1){
			ganador = pasaCalculadora();
			despedirse(ganador);
		}
		else if(opcion == 2) acerca();

	}while(opcion != 0);

	cout << "Hasta la proxima (pulsa enter)";
	cin;

	return 0;
}

//Saluda al jugador y le pregunta su nombre
void saludar(){
	string nombre;
	cout << "Bienvenido a Pasa la calculadora!" << endl;
	cout << "Como te llamas? ";
	cin >> nombre;
	cout << "Hola " << nombre << endl << endl;
}

//Se despide del jugador, la despedida varia segun gane el jugador, el automata o ninguno de ellos (el jugador abandone)
void despedirse(tJugador ganador){
	string nombre;
	if (ganador == Nadie){
		cout << "¿Abandonas? Ohhh..." << endl;
	}
	else if (ganador == Jugador){
		cout << "Enhorabuena, has ganado" << endl;
	}
	else /*if (ganador == Automata)*/{
		cout << "Lo siento, he ganado" << endl;
	}
}

//Proporciona al jugador la posibilidad de jugar, ver las instrucciones del juego o salir.
int menu(){
	int seleccionar;
	cout << "1 - Jugar" << endl;
	cout << "2 - Acerca de" << endl;
	cout << "0 - Salir" << endl;

	do{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> seleccionar;

		if (seleccionar < 0 || seleccionar > 2)
		{
			cout << "Error! Introduce un digito entre 0 y 2" << endl;
			seleccionar = -1;
		}
		else if(cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}
	}while (seleccionar == -1);

	return seleccionar;
}

//Muestra el archivo "acerca.txt" siempre que este no contenga errores
bool acerca(){

	bool ok;
	ifstream acerca;
	char c;

	acerca.open("acerca.txt");

	if(acerca.is_open())
	{
		acerca.get(c); //Lee el primer caracter

		while(!acerca.fail()) //Mientras la lectura no falle
		{
			cout << c;
			acerca.get(c); //Lee el siguiente caracter
		}

		ok = true;
		acerca.close();

	}
	else
	{
		ok = false;
		cout << "Error, el archivo 'acerca.txt' no existe" << endl;
	}

	return ok;
}

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora(){
	//Variables
	tJugador turno;
	int total = 0, ultimoDigito = 0;
	const int META=31;
		//Inicializar partida
	srand(time(NULL));//Semilla
	turno = quienEmpieza();

	//Bucle de juego
	do
	{
		//Turno jugador
		if (turno == Jugador)
		{
			ultimoDigito = digitoPersona(ultimoDigito);
			turno = Automata;
		}
		//Turno bot
		else /*if (turno == Automata)*/
		{
			ultimoDigito = digitoAutomata(ultimoDigito);
			turno = Jugador;
		}
		total += ultimoDigito;
		cout << "Total = " << total << endl;
	}
	while ((total < META) && (ultimoDigito != 0));

	if (ultimoDigito == 0) turno = Nadie;
	//Si el jugador abandona, no gana nadie

	return turno;
}

//Decide aleatoriamente quien empieza la partida, si el automata o el jugador
tJugador quienEmpieza(){
	if (rand() % 2)
	{
		cout << "Tu empiezas" << endl;
		return Jugador;
	}
	else
	{
		cout << "Empiezo yo" << endl;
		return Automata;
	}
}

//Define que numeros se encuentran en la misma fila que el ultimo pulsado
bool mismaFila(int ultimo, int nuevo)
{
	double filaUltimo, filaNuevo;
	filaUltimo = (ultimo/3);
	filaNuevo = (nuevo/3);
	return ceil(filaUltimo) == ceil(filaNuevo);
}

//Define que numeros se encuentran en la misma columna que el ultimo
bool mismaColumna(int ultimo, int nuevo)
{
	int columnaUltimo, columnaNuevo;
	columnaUltimo = (ultimo % 3);
	columnaNuevo = (nuevo % 3);
	return columnaUltimo == columnaNuevo;
}

//Determina que digitos se pueden pulsar en funcion de las reglas del juego
bool digitoValido(int ultimo, int nuevo)  //hay un bug
{
	if (ultimo == 0) return true;//Si es el primer turno, todos los numeros valen

	return ((mismaFila(ultimo, nuevo))||(mismaColumna(ultimo, nuevo)))&&(ultimo!=nuevo);
}

//Genera un digito aleatorio
int digitoAleatorio()
{
	return (rand() % 9) + 1;
}

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo)
{
	int digito;

	do
	{
	digito = digitoAleatorio();
	}
	while (!digitoValido(ultimo, digito));

	cout << "Elijo el numero " << digito << endl;

	return digito;
}

//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona()
{
	int digito = -1;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> digito;

		if (digito < 0 || digito > 9)
		{
		cout << "Error! Introduce un digito entre 0 y 9" << endl;
		digito = -1;
		}

		else if (cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}
	}
	while (digito == -1);

	return digito;
}

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo)
{
	int digito; //-1 es mi error flag

	mostrarCalculadora(ultimo);

	do
	{
		digito = digitoPersona();
		if (!digitoValido(ultimo, digito))
		{
			cout << "Error! El digito debe estar en la misma fila y columna que el ultimo" << endl;
			digito = -1;
		}
	}
	while (digito == -1);

	cout << "Has elegido el " << digito << endl;

	return digito;
}

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n)
{
	if(digitoValido(ultimo, n)) return char (n+int('0'));
	else return ' ';
}

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo)
{
	for (int i = 7; i<10; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 4; i<7; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 1; i<4; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
}
<commit_msg>Matando duendes<commit_after>/*-------------------------------
PASA LA CALCULADORA
Autores:
Jaime Sevilla Molina
Victor Gonzalez
Fecha
2014/11
Version: 2.0
---------------------------------*/

//BIBLIOTECAS
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
#include <cmath>
#include <fstream>
#include <iomanip>

using namespace std;

//TIPOS PROPIOS
typedef enum tJugador
{
	Nadie,
	Jugador,
	Automata
};

//FUNCIONES
//FUNCIONES DE JUEGO

void saludar ();

//Dependiendo de quien gane, la despedida sera distinta
void despedirse (tJugador ganador);

//Muestra un menu que permite al jugador jugar, salir, o ver las reglas del juego
int menu();

//Muestra las instrucciones del juego, siempre que su archivo no contenga errores
bool acerca();

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora();

//Decide aleatoriamente quien empieza.
tJugador quienEmpieza();
//Devuelve true si nuevo esta en la misma fila que ultimo
bool mismaFila(int ultimo, int nuevo);

//Devuelve true si nuevo esta en la misma columna que ultimo
bool mismaColumna(int ultimo, int nuevo);

//Devuelve true si nuevo cumple las reglas del juego con respecto a ultimo
//Si ultimo == 0, este es el primer digito de la partida, y devuelve true
bool digitoValido(int ultimo, int nuevo);

//FUNCIONES DE IA NIVEL 1
//Devuelve un digito del 1 al 9
int digitoAleatorio();

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo);

//FUNCIONES DE JUGADOR
//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona();

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo);

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n);

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo);

/* Las funciones a continuacion se implementaran en un futuro
//FUNCIONES DE INFORME
//Actualiza el archivo informePC.txt con los tres argumentos. En caso de no encontrar
//el archivo, lo crea y devuelve false; en otro caso devuelve true.
bool actInforme(int jugadas, int ganadas, int abandonos);

//FUNCIONES DE DIFICULTAD AVANZADA
int botDificil(int ultimo);

-----------------------------------------------------------------------------------*/

int main(){
	tJugador ganador;
	int opcion;

	saludar();

	//Bucle Menu
	do{
		opcion = menu();
		if(opcion == 1){
			ganador = pasaCalculadora();
			despedirse(ganador);
		}
		else if(opcion == 2) acerca();

	}while(opcion != 0);

	cout << "Hasta la proxima (pulsa enter)";
	cin;

	return 0;
}

//Saluda al jugador y le pregunta su nombre
void saludar(){
	string nombre;
	cout << "Bienvenido a Pasa la calculadora!" << endl;
	cout << "Como te llamas? ";
	cin >> nombre;
	cout << "Hola " << nombre << endl << endl;
}

//Se despide del jugador, la despedida varia segun gane el jugador, el automata o ninguno de ellos (el jugador abandone)
void despedirse(tJugador ganador){
	string nombre;
	if (ganador == Nadie){
		cout << "Abandonas? Ohhh..." << endl;
	}
	else if (ganador == Jugador){
		cout << "Enhorabuena, has ganado" << endl;
	}
	else /*if (ganador == Automata)*/{
		cout << "Lo siento, he ganado" << endl;
	}
}

//Proporciona al jugador la posibilidad de jugar, ver las instrucciones del juego o salir.
int menu(){
	int seleccionar = -1; //Error flag
	cout << "1 - Jugar" << endl;
	cout << "2 - Acerca de" << endl;
	cout << "0 - Salir" << endl;

	do{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> seleccionar;

		if(cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (seleccionar < 0 || seleccionar > 2)
		{
			cout << "Error! Introduce un digito entre 0 y 2" << endl;
			seleccionar = -1;
		}

	}while (seleccionar == -1);

	return seleccionar;
}

//Muestra el archivo "acerca.txt" siempre que este no contenga errores
bool acerca(){

	bool ok;
	ifstream acerca;
	char c;

	acerca.open("acerca.txt");

	if(acerca.is_open())
	{
		acerca.get(c); //Lee el primer caracter

		while(!acerca.fail()) //Mientras la lectura no falle
		{
			cout << c;
			acerca.get(c); //Lee el siguiente caracter
		}

		ok = true;
		acerca.close();

	}
	else
	{
		ok = false;
		cout << "Error, el archivo 'acerca.txt' no existe" << endl;
	}

	return ok;
}

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora(){
	//Variables
	tJugador turno;
	int total = 0, ultimoDigito = 0;
	const int META=31;
		//Inicializar partida
	srand(time(NULL));//Semilla
	turno = quienEmpieza();

	//Bucle de juego
	do
	{
		//Turno jugador
		if (turno == Jugador)
		{
			ultimoDigito = digitoPersona(ultimoDigito);
			turno = Automata;
		}
		//Turno bot
		else /*if (turno == Automata)*/
		{
			ultimoDigito = digitoAutomata(ultimoDigito);
			turno = Jugador;
		}
		total += ultimoDigito;
		cout << "Total = " << total << endl;
	}
	while ((total < META) && (ultimoDigito != 0));

	if (ultimoDigito == 0) turno = Nadie;
	//Si el jugador abandona, no gana nadie

	return turno;
}

//Decide aleatoriamente quien empieza la partida, si el automata o el jugador
tJugador quienEmpieza(){
	if (rand() % 2)
	{
		cout << "Tu empiezas" << endl;
		return Jugador;
	}
	else
	{
		cout << "Empiezo yo" << endl;
		return Automata;
	}
}

//Define que numeros se encuentran en la misma fila que el ultimo pulsado
bool mismaFila(int ultimo, int nuevo)
{
	double filaUltimo, filaNuevo;
	filaUltimo = (ultimo/3);
	filaNuevo = (nuevo/3);
	return ceil(filaUltimo) == ceil(filaNuevo);
}

//Define que numeros se encuentran en la misma columna que el ultimo
bool mismaColumna(int ultimo, int nuevo)
{
	int columnaUltimo, columnaNuevo;
	columnaUltimo = (ultimo % 3);
	columnaNuevo = (nuevo % 3);
	return columnaUltimo == columnaNuevo;
}

//Determina que digitos se pueden pulsar en funcion de las reglas del juego
bool digitoValido(int ultimo, int nuevo)  //hay un bug
{
	if (ultimo == 0) return true;//Si es el primer turno, todos los numeros valen

	return ((mismaFila(ultimo, nuevo))||(mismaColumna(ultimo, nuevo)))&&(ultimo!=nuevo);
}

//Genera un digito aleatorio
int digitoAleatorio()
{
	return (rand() % 9) + 1;
}

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo)
{
	int digito;

	do
	{
	digito = digitoAleatorio();
	}
	while (!digitoValido(ultimo, digito));

	cout << "Elijo el numero " << digito << endl;

	return digito;
}

//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona()
{
	int digito = -1;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> digito;

		if (cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (digito < 0 || digito > 9)
		{
		cout << "Error! Introduce un digito entre 0 y 9" << endl;
		digito = -1;
		}

	}
	while (digito == -1);

	return digito;
}

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo)
{
	int digito = -1; //-1 es mi error flag

	mostrarCalculadora(ultimo);

	do
	{
		digito = digitoPersona();
		if (!digitoValido(ultimo, digito))
		{
			cout << "Error! El digito debe estar en la misma fila y columna que el ultimo" << endl;
			digito = -1;
		}
	}
	while (digito == -1);

	cout << "Has elegido el " << digito << endl;

	return digito;
}

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n)
{
	if(digitoValido(ultimo, n)) return char (n+int('0'));
	else return ' ';
}

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo)
{
	for (int i = 7; i<10; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 4; i<7; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 1; i<4; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
}
<|endoftext|>


<commit_before>/************************************************************************//**
 * @file PeerIOSerialControl.cpp
 * @brief Arduino Peer IO-Control through Serial Port Communications.
 * @authors
 *    tgit23        1/2017       Original
 ******************************************************************************/
#include "PeerIOSerialControl.h"
#define ID_MASK 0x0F    // Bytes[0] [0000 1111] ArduinoID ( 0-15 )
#define REPLY_BIT 4     // Bytes[0] [0001 0000] Reply-1, Send-0
#define RW_BIT 5        // Bytes[0] [0010 0000] Read-1, Write-0
#define DA_BIT 6        // Bytes[0] [0100 0000] Digital-1, Analog-0
#define DPIN_MASK 0x3F  // Bytes[1] [0011 1111] Digital Pins ( 0 - 63 )
#define APIN_MASK 0x7F  // Bytes[1] [0111 1111] Analog Pins ( 0 - 127 )
#define HL_BIT 6        // Bytes[1] [0100 0000] High-1, Low-0
#define END_BIT 7       // Bytes[?} [1000 0000] Any set 8th bit flags END-OF-PACKET

//-----------------------------------------------------------------------------------------------------
// Initializer
//-----------------------------------------------------------------------------------------------------
PeerIOSerialControl::PeerIOSerialControl(int ThisArduinoID, Stream &CommunicationPort, Stream &DebugPort) {
  ArduinoID = ThisArduinoID;
  COMPort = &CommunicationPort;
  DBPort = &DebugPort;
}

void PeerIOSerialControl::digitalWriteB(uint8_t Pin, uint8_t Value) {
  int packetID = SendPacket(DIGITAL,WRITE,Pin,Value);
  unsigned long Start = millis();
  do {
    if ( Available() ) break;
  } while ( (millis() - Start) < BlockingTimeoutMS );
}
int PeerIOSerialControl::digitalReadB(uint8_t Pin) {
  int packetID = SendPacket(DIGITAL,READ,Pin);
  unsigned long Start = millis();
  do {
    if ( Available() ) return GetReply(packetID);
  } while ( (millis() - Start) < BlockingTimeoutMS );
  return -1;
}
int PeerIOSerialControl::analogReadB(uint8_t Pin) {
  int packetID = SendPacket(ANALOG,READ,Pin);
  unsigned long Start = millis();
  do {
    if ( Available() ) return GetReply(packetID);
  } while ( (millis() - Start) < BlockingTimeoutMS );
  return -1;
}
void PeerIOSerialControl::analogWriteB(uint8_t Pin, int Value) {
  int packetID = SendPacket(ANALOG,WRITE,Pin,Value);
  unsigned long Start = millis();
  do {
    if ( Available() ) break;
  } while ( (millis() - Start) < BlockingTimeoutMS );
}

int PeerIOSerialControl::digitalWriteNB(uint8_t Pin, uint8_t Value) {
  return SendPacket(DIGITAL,WRITE,Pin,Value);
}
int PeerIOSerialControl::digitalReadNB(uint8_t Pin) {
  return SendPacket(DIGITAL,READ,Pin);
}
int PeerIOSerialControl::analogReadNB(uint8_t Pin) {
  return SendPacket(ANALOG,READ,Pin);
}
int PeerIOSerialControl::analogWriteNB(uint8_t Pin, int Value) {
  return SendPacket(ANALOG,WRITE,Pin,Value);
}

void PeerIOSerialControl::TargetArduinoID(int ID) {
  iTargetArduinoID = ID;
}
int PeerIOSerialControl::TargetArduinoID() {
  return iTargetArduinoID;
}

void PeerIOSerialControl::Timeout(int milliseconds) {
  BlockingTimeoutMS = milliseconds;
}
int PeerIOSerialControl::Timeout() {
  return BlockingTimeoutMS;
}
void PeerIOSerialControl::VirtualPin(int Pin, int Value) {
  if ( Pin > 63 && Pin < 128 ) iVirtualPin[Pin-64] = Value;
}
int PeerIOSerialControl::VirtualPin(int Pin) {
  if ( Pin > 63 && Pin < 128 ) return iVirtualPin[Pin-64];
}

//-----------------------------------------------------------------------------------------------------
// SendPacket()
//-----------------------------------------------------------------------------------------------------
int PeerIOSerialControl::SendPacket(bool DA, bool RW, byte Pin, int Value = -1) {
  DBL(("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"));
  DBL(("SendPacket()"));
  byte SBytes[4] = { 0,0,0,0 };
  if ( DA ) bitSet(SBytes[0],DA_BIT);
  if ( RW ) bitSet(SBytes[0],RW_BIT);
  SBytes[0] = SBytes[0] | (iTargetArduinoID & ID_MASK);

  if ( DA == DIGITAL ) {
    SBytes[1] = (Pin & DPIN_MASK);                             // 6-bit Pin for Digital
    if ( RW != READ ) bitWrite(SBytes[1],HL_BIT,(Value>0));    // Digital Write - Set H/L Bit
    bitSet(SBytes[1],END_BIT);                                 // Digital only uses 2-Bytes

  } else {
    SBytes[1] = (Pin & APIN_MASK);                             // 7-bit Pin for Analog
    if ( Value > -1 ) {
      Value = ValueTo7bits(Value);                            // Conversion marks the END_BIT
      SBytes[2] = lowByte(Value);
      SBytes[3] = highByte(Value);
    } else {
      bitSet(SBytes[1],END_BIT);                               // Set END_BIT if not sending Value
    }
  }

  DB(("SendBytes( "));
  COMPort->write(SBytes[0]);
  COMPort->write(SBytes[1]);
  if ( SBytes[2] != 0 ) COMPort->write(SBytes[2]);
  if ( SBytes[3] != 0 ) COMPort->write(SBytes[3]);
  DB((SBytes[0],HEX));DBC;DB((SBytes[1],HEX));DBC;DB((SBytes[2],HEX));DBC;DB((SBytes[3],HEX));DBL((" )"));

  return ( SBytes[1] << 8 ) | SBytes[0];                        // Return Bytes 0, 1 for tracking
}

//-----------------------------------------------------------------------------------------------------
// GetReply()
//-----------------------------------------------------------------------------------------------------
int PeerIOSerialControl::GetReply(int packetID = -1) {
  DB(("GetReply("));DB((packetID,HEX));DBL((")"));
  int UseRBI = RBI - 1;
  if ( UseRBI < 1 ) UseRBI = 0;

  // Find the Reply for this Command
  if ( packetID != -1 ) {
    byte Byte0 = lowByte(packetID);
    byte Byte1 = highByte(packetID);
    int i = UseRBI; UseRBI = -1;
    do {
      DB(("\tRBytes["));DB((i));DB(("][0] = "));DBL((RBytes[i][0],HEX));
      DB(("\tRBytes["));DB((i));DB(("][1] = "));DBL((RBytes[i][1],HEX));
      if ( (Byte0 & 0xEF) == (RBytes[i][0] & 0xEF) &&
           (Byte1 & 0x3F) == (RBytes[i][1] & 0x3F) ) {
                UseRBI = i;
                break;
      }
      i--; if ( i < 0 ) i = 9;
    } while ( i != RBI );
  }

  if ( UseRBI < 0 ) return -1;
  if ( bitRead(RBytes[UseRBI][0],RW_BIT) == WRITE ) {
    return 0;                                         // Okay Status for a WRITE COMMAND
  } else {
    if ( bitRead(RBytes[UseRBI][0],DA_BIT) == DIGITAL ) {              // Value of the Reply
      return bitRead(RBytes[UseRBI][1],HL_BIT);
    } else {
      return ValueTo8bits(RBytes[UseRBI][2],RBytes[UseRBI][3]);
    }
  }
}

//-----------------------------------------------------------------------------------------------------
// ValueTo8bits()   ValueTo7bits()
//  - Encodes / Decodes numeric values into (2)7-bit bytes for the 14-bit 'AV' (Analog Value) Bytes
//  - This function automatically attaches the END_BIT at the appropriate location.
//-----------------------------------------------------------------------------------------------------
int PeerIOSerialControl::ValueTo8bits(byte lByte, byte hByte) {
  bitClear(hByte,7);                        // Clear any End-Of-Packet flag
  bitWrite(lByte,7,bitRead(hByte,0));       // Transfer hByte<0> onto lByte<7>
  return (hByte<<7) | lByte;                // Left shift 7 overwrites lByte<7>
}
int PeerIOSerialControl::ValueTo7bits(int From8BitValue) {
  byte lByte = lowByte(From8BitValue);
  byte hByte = highByte(From8BitValue);
  if ( From8BitValue > 0x3FFF ) return -1;  //  Value is too big for a 14-bit Value
  hByte = hByte << 1;                       // Make Room on hByte for bit-7 of lByte
  bitWrite(hByte,0,bitRead(lByte,7));       // Transfer lByte<7> onto hByte<0>
  if ( From8BitValue > 0x7F ) {
    bitSet(hByte,7);        // Value > 7-bits so Set 'END_BIT' @ hByte
    bitClear(lByte,7);
  } else {
    bitSet(lByte,7);        // Value <= 7-bits so Set 'END_BIT' @ lByte
    bitClear(hByte,7);
  }
  return (hByte<<8) | lByte;
}

//-----------------------------------------------------------------------------------------------------
// DecodePacket()
//-----------------------------------------------------------------------------------------------------
void PeerIOSerialControl::DecodePacket(long lPacket = -1) {
  byte Byte0; byte Byte1; byte Byte2; byte Byte3;
  if ( lPacket = -1 ) {
    Byte0=Bytes[0];Byte1=Bytes[1];Byte2=Bytes[2];Byte3=Bytes[3];
  } else {
    Byte0 = ( lPacket >> 24 ) & 0xFF;
    Byte1 = ( lPacket >> 16 ) & 0xFF;
    Byte2 = ( lPacket >> 8 ) & 0xFF;
    Byte3 = lPacket & 0xFF;
  }
  DB(("D/A Flag = "));if ( bitRead(Byte0,DA_BIT) ) { DBL(("DIGITAL")); } else { DBL(("ANALOG")); }
  DB(("R/W Flag = "));if ( bitRead(Byte0,RW_BIT) ) { DBL(("READ")); } else { DBL(("WRITE")); }
  DB(("S/R Flag = "));if ( bitRead(Byte0,REPLY_BIT) ) { DBL(("REPLY")); } else { DBL(("SEND")); }
  DB(("Arduino ID = "));DBL(( (Byte0 & ID_MASK) ));
  if ( bitRead(Byte0,DA_BIT) ) {
    DB(("H/L Flag = "));
    if ( bitRead(Byte0,HL_BIT) ) { DBL(("HIGH")); } else { DBL(("LOW")); }
    DB(("PIN = "));DBL(( (Byte1 & DPIN_MASK) ));
  } else {
    DB(("Value = "));DBL(( ValueTo8bits(Byte2, Byte3) ));
    DB(("PIN = "));DBL(( (Byte1 & APIN_MASK) ));
  }
}

//-----------------------------------------------------------------------------------------------------
// ProcessPacket()
//-----------------------------------------------------------------------------------------------------
void PeerIOSerialControl::ProcessPacket() {
  DB(("ProcessPacket( "));
  DB((Bytes[0],HEX));DBC;DB((Bytes[1],HEX));DBC;DB((Bytes[2],HEX));DBC;DB((Bytes[3],HEX));
  DB((" ) - "));

  // REPLY PACKET RECEIVED
  if ( bitRead(Bytes[0],REPLY_BIT) ) {
    DBL(("Packet Type REPLY"));
    for ( int i=0;i<4;i++ ) RBytes[RBI][i] = Bytes[i];   // Put Replies in RBytes Buffer
#if defined(DEBUG)
  #if DEBUG>0
      DecodePacket();
  #endif
#endif

  // COMMAND PACKET RECEIVED
  } else if ( (Bytes[0] & ID_MASK) == ArduinoID ) {

    DBL(("Packet Type SEND"));
    // DIGITAL
    if ( bitRead(Bytes[0],DA_BIT) == DIGITAL ) {
      int pin = Bytes[1] & DPIN_MASK;
      if ( bitRead(Bytes[0],RW_BIT) == READ ) {
        DB(("digitalRead("));DB((pin));DBL((")"));
        bitWrite(Bytes[1],HL_BIT,digitalRead(pin));
      } else {
        DB(("digitalWrite("));DB((pin));DB((","));DB((bitRead(Bytes[1],HL_BIT)));DBL((")"));
        digitalWrite(pin,bitRead(Bytes[1],HL_BIT));
      }
      bitSet(Bytes[1],END_BIT);

    // ANALOG
    } else {
      int pin = Bytes[1] & APIN_MASK;
      int val = 0;
      if ( bitRead(Bytes[0],RW_BIT) == READ ) {
        DB(("analogRead("));DB((pin));DBL((")"));
        if ( pin > 63 && pin < 128 ) {
          val = ValueTo7bits(iVirtualPin[pin-64]);
        } else {
          val = ValueTo7bits(analogRead(pin));
        }
        Bytes[2] = lowByte(val);
        Bytes[3] = highByte(val);
      } else {
        DB(("analogWrite("));DB((pin));DB((","));DB((ValueTo8bits(Bytes[2],Bytes[3])));DBL((")"));
        if ( pin > 63 && pin < 128 ) {
          iVirtualPin[pin-64] = ValueTo8bits(Bytes[2],Bytes[3]);
        } else {
          analogWrite(pin,ValueTo8bits(Bytes[2],Bytes[3]));
        }
      }
    }

    // Send out the Reply Packet
    bitSet(Bytes[0],REPLY_BIT); // Set the Reply Bit
    DB(("SendBytes( "));
    COMPort->write(Bytes[0]);
    COMPort->write(Bytes[1]);
    if ( Bytes[2] != 0 ) COMPort->write(Bytes[2]);
    if ( Bytes[3] != 0 ) COMPort->write(Bytes[3]);
    DB((Bytes[0],HEX));DBC;DB((Bytes[1],HEX));DBC;DB((Bytes[2],HEX));DBC;DB((Bytes[3],HEX));DBL((" )"));
  }

}

//-----------------------------------------------------------------------------------------------------
// Available()
//-----------------------------------------------------------------------------------------------------
bool PeerIOSerialControl::Available() {
  // Receive Bytes
  while(COMPort->available() > 0) {
    Bytes[idx] = COMPort->read();
    if ( Bytes[idx] != -1 ) {
      //DBL((Bytes[idx],HEX));
      if ( bitRead(Bytes[idx],END_BIT) ) {
        DBL(("-----------------------------------------------------------"));
        DB(("Packet Received @ Size: "));DBL((idx+1));
        bitClear(Bytes[idx],END_BIT);           // Clear the END_BIT
        for(int i=(idx+1);i<4;i++) Bytes[i]=0;  // Clear unused bytes
        idx = 0;
        ProcessPacket();
        return true;
      } else {
        idx++;
      }
    }
  }
}

<commit_msg>Fixed new compiler warnings<commit_after>/************************************************************************//**
 * @file PeerIOSerialControl.cpp
 * @brief Arduino Peer IO-Control through Serial Port Communications.
 * @authors
 *    tgit23        1/2017       Original
 ******************************************************************************/
#include "PeerIOSerialControl.h"
#define ID_MASK 0x0F    // Bytes[0] [0000 1111] ArduinoID ( 0-15 )
#define REPLY_BIT 4     // Bytes[0] [0001 0000] Reply-1, Send-0
#define RW_BIT 5        // Bytes[0] [0010 0000] Read-1, Write-0
#define DA_BIT 6        // Bytes[0] [0100 0000] Digital-1, Analog-0
#define DPIN_MASK 0x3F  // Bytes[1] [0011 1111] Digital Pins ( 0 - 63 )
#define APIN_MASK 0x7F  // Bytes[1] [0111 1111] Analog Pins ( 0 - 127 )
#define HL_BIT 6        // Bytes[1] [0100 0000] High-1, Low-0
#define END_BIT 7       // Bytes[?} [1000 0000] Any set 8th bit flags END-OF-PACKET

//-----------------------------------------------------------------------------------------------------
// Initializer
//-----------------------------------------------------------------------------------------------------
PeerIOSerialControl::PeerIOSerialControl(int ThisArduinoID, Stream &CommunicationPort, Stream &DebugPort) {
  ArduinoID = ThisArduinoID;
  COMPort = &CommunicationPort;
  DBPort = &DebugPort;
}

void PeerIOSerialControl::digitalWriteB(uint8_t Pin, uint8_t Value) {
  int packetID = SendPacket(DIGITAL,WRITE,Pin,Value);
  unsigned long Start = millis();
  do {
    if ( Available() ) break;
  } while ( (millis() - Start) < BlockingTimeoutMS );
}
int PeerIOSerialControl::digitalReadB(uint8_t Pin) {
  int packetID = SendPacket(DIGITAL,READ,Pin);
  unsigned long Start = millis();
  do {
    if ( Available() ) return GetReply(packetID);
  } while ( (millis() - Start) < BlockingTimeoutMS );
  return -1;
}
int PeerIOSerialControl::analogReadB(uint8_t Pin) {
  int packetID = SendPacket(ANALOG,READ,Pin);
  unsigned long Start = millis();
  do {
    if ( Available() ) return GetReply(packetID);
  } while ( (millis() - Start) < BlockingTimeoutMS );
  return -1;
}
void PeerIOSerialControl::analogWriteB(uint8_t Pin, int Value) {
  int packetID = SendPacket(ANALOG,WRITE,Pin,Value);
  unsigned long Start = millis();
  do {
    if ( Available() ) break;
  } while ( (millis() - Start) < BlockingTimeoutMS );
}

int PeerIOSerialControl::digitalWriteNB(uint8_t Pin, uint8_t Value) {
  return SendPacket(DIGITAL,WRITE,Pin,Value);
}
int PeerIOSerialControl::digitalReadNB(uint8_t Pin) {
  return SendPacket(DIGITAL,READ,Pin);
}
int PeerIOSerialControl::analogReadNB(uint8_t Pin) {
  return SendPacket(ANALOG,READ,Pin);
}
int PeerIOSerialControl::analogWriteNB(uint8_t Pin, int Value) {
  return SendPacket(ANALOG,WRITE,Pin,Value);
}

void PeerIOSerialControl::TargetArduinoID(int ID) {
  iTargetArduinoID = ID;
}
int PeerIOSerialControl::TargetArduinoID() {
  return iTargetArduinoID;
}

void PeerIOSerialControl::Timeout(int milliseconds) {
  BlockingTimeoutMS = milliseconds;
}
int PeerIOSerialControl::Timeout() {
  return BlockingTimeoutMS;
}
void PeerIOSerialControl::VirtualPin(int Pin, int Value) {
  if ( Pin > 63 && Pin < 128 ) iVirtualPin[Pin-64] = Value;
}
int PeerIOSerialControl::VirtualPin(int Pin) {
  if ( Pin > 63 && Pin < 128 ) return iVirtualPin[Pin-64];
}

//-----------------------------------------------------------------------------------------------------
// SendPacket()
//-----------------------------------------------------------------------------------------------------
int PeerIOSerialControl::SendPacket(bool DA, bool RW, byte Pin, int Value) {
  DBL(("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"));
  DBL(("SendPacket()"));
  byte SBytes[4] = { 0,0,0,0 };
  if ( DA ) bitSet(SBytes[0],DA_BIT);
  if ( RW ) bitSet(SBytes[0],RW_BIT);
  SBytes[0] = SBytes[0] | (iTargetArduinoID & ID_MASK);

  if ( DA == DIGITAL ) {
    SBytes[1] = (Pin & DPIN_MASK);                             // 6-bit Pin for Digital
    if ( RW != READ ) bitWrite(SBytes[1],HL_BIT,(Value>0));    // Digital Write - Set H/L Bit
    bitSet(SBytes[1],END_BIT);                                 // Digital only uses 2-Bytes

  } else {
    SBytes[1] = (Pin & APIN_MASK);                             // 7-bit Pin for Analog
    if ( Value > -1 ) {
      Value = ValueTo7bits(Value);                            // Conversion marks the END_BIT
      SBytes[2] = lowByte(Value);
      SBytes[3] = highByte(Value);
    } else {
      bitSet(SBytes[1],END_BIT);                               // Set END_BIT if not sending Value
    }
  }

  DB(("SendBytes( "));
  COMPort->write(SBytes[0]);
  COMPort->write(SBytes[1]);
  if ( SBytes[2] != 0 ) COMPort->write(SBytes[2]);
  if ( SBytes[3] != 0 ) COMPort->write(SBytes[3]);
  DB((SBytes[0],HEX));DBC;DB((SBytes[1],HEX));DBC;DB((SBytes[2],HEX));DBC;DB((SBytes[3],HEX));DBL((" )"));

  return ( SBytes[1] << 8 ) | SBytes[0];                        // Return Bytes 0, 1 for tracking
}

//-----------------------------------------------------------------------------------------------------
// GetReply()
//-----------------------------------------------------------------------------------------------------
int PeerIOSerialControl::GetReply(int packetID) {
  DB(("GetReply("));DB((packetID,HEX));DBL((")"));
  int UseRBI = RBI - 1;
  if ( UseRBI < 1 ) UseRBI = 0;

  // Find the Reply for this Command
  if ( packetID != -1 ) {
    byte Byte0 = lowByte(packetID);
    byte Byte1 = highByte(packetID);
    int i = UseRBI; UseRBI = -1;
    do {
      DB(("\tRBytes["));DB((i));DB(("][0] = "));DBL((RBytes[i][0],HEX));
      DB(("\tRBytes["));DB((i));DB(("][1] = "));DBL((RBytes[i][1],HEX));
      if ( (Byte0 & 0xEF) == (RBytes[i][0] & 0xEF) &&
           (Byte1 & 0x3F) == (RBytes[i][1] & 0x3F) ) {
                UseRBI = i;
                break;
      }
      i--; if ( i < 0 ) i = 9;
    } while ( i != RBI );
  }

  if ( UseRBI < 0 ) return -1;
  if ( bitRead(RBytes[UseRBI][0],RW_BIT) == WRITE ) {
    return 0;                                         // Okay Status for a WRITE COMMAND
  } else {
    if ( bitRead(RBytes[UseRBI][0],DA_BIT) == DIGITAL ) {              // Value of the Reply
      return bitRead(RBytes[UseRBI][1],HL_BIT);
    } else {
      return ValueTo8bits(RBytes[UseRBI][2],RBytes[UseRBI][3]);
    }
  }
}

//-----------------------------------------------------------------------------------------------------
// ValueTo8bits()   ValueTo7bits()
//  - Encodes / Decodes numeric values into (2)7-bit bytes for the 14-bit 'AV' (Analog Value) Bytes
//  - This function automatically attaches the END_BIT at the appropriate location.
//-----------------------------------------------------------------------------------------------------
int PeerIOSerialControl::ValueTo8bits(byte lByte, byte hByte) {
  bitClear(hByte,7);                        // Clear any End-Of-Packet flag
  bitWrite(lByte,7,bitRead(hByte,0));       // Transfer hByte<0> onto lByte<7>
  return (hByte<<7) | lByte;                // Left shift 7 overwrites lByte<7>
}
int PeerIOSerialControl::ValueTo7bits(int From8BitValue) {
  byte lByte = lowByte(From8BitValue);
  byte hByte = highByte(From8BitValue);
  if ( From8BitValue > 0x3FFF ) return -1;  //  Value is too big for a 14-bit Value
  hByte = hByte << 1;                       // Make Room on hByte for bit-7 of lByte
  bitWrite(hByte,0,bitRead(lByte,7));       // Transfer lByte<7> onto hByte<0>
  if ( From8BitValue > 0x7F ) {
    bitSet(hByte,7);        // Value > 7-bits so Set 'END_BIT' @ hByte
    bitClear(lByte,7);
  } else {
    bitSet(lByte,7);        // Value <= 7-bits so Set 'END_BIT' @ lByte
    bitClear(hByte,7);
  }
  return (hByte<<8) | lByte;
}

//-----------------------------------------------------------------------------------------------------
// DecodePacket()
//-----------------------------------------------------------------------------------------------------
void PeerIOSerialControl::DecodePacket(long lPacket) {
  byte Byte0; byte Byte1; byte Byte2; byte Byte3;
  if ( lPacket = -1 ) {
    Byte0=Bytes[0];Byte1=Bytes[1];Byte2=Bytes[2];Byte3=Bytes[3];
  } else {
    Byte0 = ( lPacket >> 24 ) & 0xFF;
    Byte1 = ( lPacket >> 16 ) & 0xFF;
    Byte2 = ( lPacket >> 8 ) & 0xFF;
    Byte3 = lPacket & 0xFF;
  }
  DB(("D/A Flag = "));if ( bitRead(Byte0,DA_BIT) ) { DBL(("DIGITAL")); } else { DBL(("ANALOG")); }
  DB(("R/W Flag = "));if ( bitRead(Byte0,RW_BIT) ) { DBL(("READ")); } else { DBL(("WRITE")); }
  DB(("S/R Flag = "));if ( bitRead(Byte0,REPLY_BIT) ) { DBL(("REPLY")); } else { DBL(("SEND")); }
  DB(("Arduino ID = "));DBL(( (Byte0 & ID_MASK) ));
  if ( bitRead(Byte0,DA_BIT) ) {
    DB(("H/L Flag = "));
    if ( bitRead(Byte0,HL_BIT) ) { DBL(("HIGH")); } else { DBL(("LOW")); }
    DB(("PIN = "));DBL(( (Byte1 & DPIN_MASK) ));
  } else {
    DB(("Value = "));DBL(( ValueTo8bits(Byte2, Byte3) ));
    DB(("PIN = "));DBL(( (Byte1 & APIN_MASK) ));
  }
}

//-----------------------------------------------------------------------------------------------------
// ProcessPacket()
//-----------------------------------------------------------------------------------------------------
void PeerIOSerialControl::ProcessPacket() {
  DB(("ProcessPacket( "));
  DB((Bytes[0],HEX));DBC;DB((Bytes[1],HEX));DBC;DB((Bytes[2],HEX));DBC;DB((Bytes[3],HEX));
  DB((" ) - "));

  // REPLY PACKET RECEIVED
  if ( bitRead(Bytes[0],REPLY_BIT) ) {
    DBL(("Packet Type REPLY"));
    for ( int i=0;i<4;i++ ) RBytes[RBI][i] = Bytes[i];   // Put Replies in RBytes Buffer
#if defined(DEBUG)
  #if DEBUG>0
      DecodePacket();
  #endif
#endif

  // COMMAND PACKET RECEIVED
  } else if ( (Bytes[0] & ID_MASK) == ArduinoID ) {

    DBL(("Packet Type SEND"));
    // DIGITAL
    if ( bitRead(Bytes[0],DA_BIT) == DIGITAL ) {
      int pin = Bytes[1] & DPIN_MASK;
      if ( bitRead(Bytes[0],RW_BIT) == READ ) {
        DB(("digitalRead("));DB((pin));DBL((")"));
        bitWrite(Bytes[1],HL_BIT,digitalRead(pin));
      } else {
        DB(("digitalWrite("));DB((pin));DB((","));DB((bitRead(Bytes[1],HL_BIT)));DBL((")"));
        digitalWrite(pin,bitRead(Bytes[1],HL_BIT));
      }
      bitSet(Bytes[1],END_BIT);

    // ANALOG
    } else {
      int pin = Bytes[1] & APIN_MASK;
      int val = 0;
      if ( bitRead(Bytes[0],RW_BIT) == READ ) {
        DB(("analogRead("));DB((pin));DBL((")"));
        if ( pin > 63 && pin < 128 ) {
          val = ValueTo7bits(iVirtualPin[pin-64]);
        } else {
          val = ValueTo7bits(analogRead(pin));
        }
        Bytes[2] = lowByte(val);
        Bytes[3] = highByte(val);
      } else {
        DB(("analogWrite("));DB((pin));DB((","));DB((ValueTo8bits(Bytes[2],Bytes[3])));DBL((")"));
        if ( pin > 63 && pin < 128 ) {
          iVirtualPin[pin-64] = ValueTo8bits(Bytes[2],Bytes[3]);
        } else {
          analogWrite(pin,ValueTo8bits(Bytes[2],Bytes[3]));
        }
      }
    }

    // Send out the Reply Packet
    bitSet(Bytes[0],REPLY_BIT); // Set the Reply Bit
    DB(("SendBytes( "));
    COMPort->write(Bytes[0]);
    COMPort->write(Bytes[1]);
    if ( Bytes[2] != 0 ) COMPort->write(Bytes[2]);
    if ( Bytes[3] != 0 ) COMPort->write(Bytes[3]);
    DB((Bytes[0],HEX));DBC;DB((Bytes[1],HEX));DBC;DB((Bytes[2],HEX));DBC;DB((Bytes[3],HEX));DBL((" )"));
  }

}

//-----------------------------------------------------------------------------------------------------
// Available()
//-----------------------------------------------------------------------------------------------------
bool PeerIOSerialControl::Available() {
  // Receive Bytes
  while(COMPort->available() > 0) {
    Bytes[idx] = COMPort->read();
    if ( Bytes[idx] != -1 ) {
      //DBL((Bytes[idx],HEX));
      if ( bitRead(Bytes[idx],END_BIT) ) {
        DBL(("-----------------------------------------------------------"));
        DB(("Packet Received @ Size: "));DBL((idx+1));
        bitClear(Bytes[idx],END_BIT);           // Clear the END_BIT
        for(int i=(idx+1);i<4;i++) Bytes[i]=0;  // Clear unused bytes
        idx = 0;
        ProcessPacket();
        return true;
      } else {
        idx++;
      }
    }
  }
}

<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H $    */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file dp16.H
/// @brief Subroutines to control the DP16 logic blocks
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#ifndef _MSS_DP16_H_
#define _MSS_DP16_H_

#include <fapi2.H>
#include <vector>

namespace mss
{
namespace dp16
{

///
/// @brief Configure the DP16 sysclk
/// @tparam T the fapi2 target type
/// @param[in] i_target a target
/// @return FAPI2_RC_SUCCESs iff ok
///
template< fapi2::TargetType T >
fapi2::ReturnCode setup_sysclk( const fapi2::Target<T>& i_target );

///
/// @brief Configure the DP16 sysclk
/// @param[in] i_target a MCBIST target
/// @return FAPI2_RC_SUCCESs iff ok
///
template<>
fapi2::ReturnCode setup_sysclk( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target );

///
/// @brief Reset the training delay configureation
/// @tparam T the type of the port
/// @param[in] i_target the port target
/// @param[in] l_rank_pairs vector of rank pairs
/// @return FAPI2_RC_SUCCES iff ok
///
template< fapi2::TargetType T>
fapi2::ReturnCode reset_delay_values( const fapi2::Target<T>& i_target,
                                      const std::vector< uint64_t >& l_rank_pairs );

///
/// @brief Reset the training delay configureation
/// @param[in] i_target the port target
/// @param[in]  l_rank_pairs vector of rank pairs
/// @return FAPI2_RC_SUCCES iff ok
///
template<>
fapi2::ReturnCode reset_delay_values( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
                                      const std::vector< uint64_t >& l_rank_pairs );

///
/// @brief Write the read clock enable registers
/// @tparam T the type of the port
/// @param[in] i_target a port target
/// @param[in] l_rank_pairs vector of rank pairs
/// @return FAPI2_RC_SUCCES iff ok
///
template< fapi2::TargetType T>
fapi2::ReturnCode read_clock_enable( const fapi2::Target<T>& i_target,
                                     const std::vector< uint64_t >& l_rank_pairs );

///
/// @brief Write the clock enable registers
/// @param[in] i_target a port target
/// @param[in] l_rank_pairs vector of rank pairs
/// @return FAPI2_RC_SUCCES iff ok
///
template<>
fapi2::ReturnCode read_clock_enable( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
                                     const std::vector< uint64_t >& l_rank_pairs );

///
/// @brief Write the clock enable registers
/// @tparam T the type of the port
/// @param[in] i_target  a port target
/// @param[in] l_rank_pairs vector of rank pairs
/// @return FAPI2_RC_SUCCES iff ok
///
template< fapi2::TargetType T>
fapi2::ReturnCode write_clock_enable( const fapi2::Target<T>& i_target,
                                      const std::vector< uint64_t >& l_rank_pairs );

///
/// @brief Write the clock enable registers
/// @param[in] i_target a port target
/// @param[in] l_rank_pairs vector of rank pairs
/// @return FAPI2_RC_SUCCES iff ok
///
template<>
fapi2::ReturnCode write_clock_enable( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
                                      const std::vector< uint64_t >& l_rank_pairs );

///
/// @brief Write the data bit enable registers
/// @tparam T the type of the port
/// @param[in] i_target a port target
/// @return FAPI2_RC_SUCCESs iff ok
///
template< fapi2::TargetType T>
fapi2::ReturnCode write_data_bit_enable( const fapi2::Target<T>& i_target );

///
/// @brief Write the data bit enable registers
/// @param[in] i_target a port target
/// @return FAPI2_RC_SUCCESs iff ok
///
template<>
fapi2::ReturnCode write_data_bit_enable( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target );

///
/// @brief Setup the bad-bits masks for a port
/// @tparam T the fapi2::TargetType
/// @param[in] i_target the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template< fapi2::TargetType T>
inline fapi2::ReturnCode set_bad_bits(const fapi2::Target<T>& i_target);

///
/// @brief Setup the bad-bits masks for a port
/// @tparam T the fapi2::TargetType
/// @param[in] i_target the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template<>
inline fapi2::ReturnCode set_bad_bits(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    // Note: We need to do this ... BRS
    return fapi2::FAPI2_RC_SUCCESS;
}

}
}

#endif
<commit_msg>Add phy control error checking, clean up dp16, apb<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H $    */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file dp16.H
/// @brief Subroutines to control the DP16 logic blocks
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#ifndef _MSS_DP16_H_
#define _MSS_DP16_H_

#include <vector>
#include <fapi2.H>
#include <p9_mc_scom_addresses.H>
#include <p9_mc_scom_addresses_fld.H>

namespace mss
{

// I have a dream that the PHY code can be shared among controllers. So, I drive the
// engine from a set of traits. This might be folly. Allow me to dream. BRS

///
/// @class dp16Traits
/// @brief a collection of traits associated with the PHY DP16 block
/// @tparam T fapi2::TargetType representing the PHY
///
template< fapi2::TargetType T >
class dp16Traits;

///
/// @class dp16Traits
/// @brief a collection of traits associated with the Centaur PHY
///
template<>
class dp16Traits<fapi2::TARGET_TYPE_MBA>
{
};

///
/// @class dp16Traits
/// @brief a collection of traits associated with the Nimbus PHY DP16 block
///
template<>
class dp16Traits<fapi2::TARGET_TYPE_MCA>
{
};

///
/// @class mss::dp16
/// @brief PHY DP16 Block class
/// @tparam T fapi2 Target Type
/// @tparam TT traits type defaults to dp16Traits<T>
///
template< fapi2::TargetType T, typename TT = dp16Traits<T> >
class dp16
{
    public:

        ///
        /// @brief Configure the DP16 sysclk
        /// @tparam K the fapi2 target type
        /// @param[in] i_target a target
        /// @return FAPI2_RC_SUCCESs iff ok
        ///
        template< fapi2::TargetType K >
        fapi2::ReturnCode setup_sysclk( const fapi2::Target<K>& i_target );

        ///
        /// @brief Reset the training delay configureation
        /// @tparam T the type of the port
        /// @param[in] i_target the port target
        /// @param[in] l_rank_pairs vector of rank pairs
        /// @return FAPI2_RC_SUCCES iff ok
        ///
        fapi2::ReturnCode reset_delay_values( const fapi2::Target<T>& i_target,
                                              const std::vector< uint64_t >& l_rank_pairs );

        ///
        /// @brief Write the read clock enable registers
        /// @tparam T the type of the port
        /// @param[in] i_target a port target
        /// @param[in] l_rank_pairs vector of rank pairs
        /// @return FAPI2_RC_SUCCES iff ok
        ///
        fapi2::ReturnCode read_clock_enable( const fapi2::Target<T>& i_target,
                                             const std::vector< uint64_t >& l_rank_pairs );

        ///
        /// @brief Write the clock enable registers
        /// @tparam T the type of the port
        /// @param[in] i_target  a port target
        /// @param[in] l_rank_pairs vector of rank pairs
        /// @return FAPI2_RC_SUCCES iff ok
        ///
        fapi2::ReturnCode write_clock_enable( const fapi2::Target<T>& i_target,
                                              const std::vector< uint64_t >& l_rank_pairs );

        ///
        /// @brief Write the data bit enable registers
        /// @tparam T the type of the port
        /// @param[in] i_target a port target
        /// @return FAPI2_RC_SUCCESs iff ok
        ///
        fapi2::ReturnCode write_data_bit_enable( const fapi2::Target<T>& i_target );

        ///
        /// @brief Setup the bad-bits masks for a port
        /// @tparam T the fapi2::TargetType
        /// @param[in] i_target the target (MCA or MBA?)
        /// @return FAPI2_RC_SUCCESS if and only if ok
        ///
        inline fapi2::ReturnCode set_bad_bits(const fapi2::Target<T>& i_target);

};

///
/// @brief Configure the DP16 sysclk
/// @param[in] i_target a MCBIST target
/// @return FAPI2_RC_SUCCESs iff ok
///
template<>
template<>
fapi2::ReturnCode dp16<fapi2::TARGET_TYPE_MCA>::setup_sysclk(
    const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target );

///
/// @brief Reset the training delay configureation
/// @param[in] i_target the port target
/// @param[in]  l_rank_pairs vector of rank pairs
/// @return FAPI2_RC_SUCCES iff ok
///
template<>
fapi2::ReturnCode dp16<fapi2::TARGET_TYPE_MCA>::reset_delay_values(
    const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
    const std::vector< uint64_t >& l_rank_pairs );

///
/// @brief Write the clock enable registers
/// @param[in] i_target a port target
/// @param[in] l_rank_pairs vector of rank pairs
/// @return FAPI2_RC_SUCCES iff ok
///
template<>
fapi2::ReturnCode dp16<fapi2::TARGET_TYPE_MCA>::read_clock_enable(
    const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
    const std::vector< uint64_t >& l_rank_pairs );

///
/// @brief Write the clock enable registers
/// @param[in] i_target a port target
/// @param[in] l_rank_pairs vector of rank pairs
/// @return FAPI2_RC_SUCCES iff ok
///
template<>
fapi2::ReturnCode dp16<fapi2::TARGET_TYPE_MCA>::write_clock_enable(
    const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
    const std::vector< uint64_t >& l_rank_pairs );

///
/// @brief Write the data bit enable registers
/// @param[in] i_target a port target
/// @return FAPI2_RC_SUCCESs iff ok
///
template<>
fapi2::ReturnCode dp16<fapi2::TARGET_TYPE_MCA>::write_data_bit_enable(
    const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target );

///
/// @brief Setup the bad-bits masks for a port
/// @tparam T the fapi2::TargetType
/// @param[in] i_target the target (MCA or MBA?)
/// @return FAPI2_RC_SUCCESS if and only if ok
///
template<>
inline fapi2::ReturnCode dp16<fapi2::TARGET_TYPE_MCA>::set_bad_bits(
    const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    // Note: We need to do this ... BRS
    return fapi2::FAPI2_RC_SUCCESS;
}

}

#endif
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
//

#include "PlacemarkManager.h"

#include <QtCore/QBuffer>
#include <QtCore/QByteArray>
#include <QtCore/QDataStream>
#include <QtCore/QDateTime>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtXml/QXmlInputSource>
#include <QtXml/QXmlSimpleReader>

#include "KmlFileViewItem.h"
#include "FileViewModel.h"
#include "MarbleDirs.h"
#include "MarblePlacemarkModel.h"
#include "MarbleGeometryModel.h"
#include "PlacemarkContainer.h"
#include "PlacemarkLoader.h"

#include "GeoDataDocument.h"
#include "GeoDataParser.h"
#include "GeoDataPlacemark.h"

using namespace Marble;

namespace Marble {
class PlacemarkManagerPrivate
{
    public:
        PlacemarkManagerPrivate( QObject* parent )
        : m_model( 0 )
        , m_geomodel( new MarbleGeometryModel() )
        , m_fileViewModel( new FileViewModel(parent ) )
        , m_finalized( true )
        , m_target( QString() )
        {
        };

        MarblePlacemarkModel* m_model;
        MarbleGeometryModel* m_geomodel;
        QList<PlacemarkLoader*> m_loaderList;
        FileViewModel* m_fileViewModel;
        QStringList m_pathList;

        bool m_finalized;
        QString m_target;
};
}

PlacemarkManager::PlacemarkManager( QObject *parent )
    : QObject( parent )
    , d( new PlacemarkManagerPrivate( parent ) )
{

}

PlacemarkManager::~PlacemarkManager()
{
    foreach( PlacemarkLoader *loader, d->m_loaderList ) {
        if ( loader ) {
            loader->wait();
        }
    }

    delete d->m_model;
    delete d->m_fileViewModel;
    delete d;
    /* do not delete the d->m_geomodel here
     * it is not this models property
     */
}

MarblePlacemarkModel* PlacemarkManager::model() const
{
    return d->m_model;
}

FileViewModel* PlacemarkManager::fileViewModel() const
{
    return d->m_fileViewModel;
}

MarbleGeometryModel* PlacemarkManager::geomodel() const
{
    return d->m_geomodel;
}

void PlacemarkManager::setGeoModel( MarbleGeometryModel * model )
{
    d->m_geomodel = model;
}

void PlacemarkManager::setPlacemarkModel( MarblePlacemarkModel *model )
{
    d->m_model = model;
}

void PlacemarkManager::clearPlacemarks()
{
    d->m_model->clearPlacemarks();
}

QStringList PlacemarkManager::containers() const
{
    return fileViewModel()->containers() + d->m_pathList;
}

QString PlacemarkManager::toRegularName( QString name )
{
    return name.remove(".kml").remove(".cache");
}

void PlacemarkManager::addPlacemarkFile( const QString& filepath, bool finalized )
{
    if( ! containers().contains( toRegularName( filepath ) ) ) {
        qDebug() << "adding container:" << toRegularName( filepath ) << finalized;
        PlacemarkLoader* loader = new PlacemarkLoader( this, filepath, finalized );
        connect (   loader, SIGNAL( placemarksLoaded( PlacemarkLoader*, PlacemarkContainer * ) ),
                    this, SLOT( loadPlacemarkContainer( PlacemarkLoader*, PlacemarkContainer * ) ) );
        connect (   loader, SIGNAL( placemarkLoaderFailed( PlacemarkLoader* ) ),
                    this, SLOT( cleanupLoader( PlacemarkLoader* ) ) );
        connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                    this, SLOT( addGeoDataDocument( GeoDataDocument* ) ) );
        d->m_loaderList.append( loader );
        d->m_pathList.append( toRegularName( filepath ) );
        loader->start();
    }
}

void PlacemarkManager::addGeoDataDocument( GeoDataDocument* document )
{
    AbstractFileViewItem* item = new KmlFileViewItem( *this, *document );

    d->m_fileViewModel->append( item );

    // now get the document that will be preserved throughout the life time
    GeoDataDocument* doc = dynamic_cast<KmlFileViewItem*>(item)->document();
    // remove the hashes in front of the styles.
    QVector<GeoDataFeature>::Iterator end = doc->end();
    QVector<GeoDataFeature>::Iterator itr = doc->begin();
    for ( ; itr != end; ++itr ) {
        // use *itr (or itr.value()) here
        QString styleUrl = itr->styleUrl().remove('#');
        itr->setStyle( &doc->style( styleUrl ) );
    }

    // do not set this file if it only contains points
    if( doc->isVisible() )
        d->m_geomodel->setGeoDataRoot( doc );
    emit geoDataDocumentAdded( *doc );
}

void PlacemarkManager::addPlacemarkData( const QString& data, const QString& key )
{
    loadKmlFromData( data, key, false );
}

void PlacemarkManager::removePlacemarkKey( const QString& key )
{
    QString nkey = key;
    qDebug() << "trying to remove file:" << key;
    for( int i = 0; i < d->m_fileViewModel->rowCount(); ++i )
    {
        if( toRegularName( nkey ) == toRegularName( d->m_fileViewModel->data(d->m_fileViewModel->index(i, 0)).toString() ) ) {
            d->m_fileViewModel->remove(d->m_fileViewModel->index(i, 0));
            break;
        }
    };
}

void PlacemarkManager::cleanupLoader( PlacemarkLoader* loader )
{
    d->m_loaderList.removeAll( loader );
    if ( loader->isFinished() ) {
         d->m_pathList.removeAll( loader->path() );
         delete loader;
    }
}

void PlacemarkManager::loadPlacemarkContainer( PlacemarkLoader* loader, PlacemarkContainer * container )
{
    qDebug() << "Containername:" << container->name() << "to be finalized:" << (d->m_loaderList.size() == 1) << d->m_loaderList.size();
    d->m_loaderList.removeAll( loader );
    if ( container )
    {
        d->m_model->addPlacemarks( *container, false, d->m_finalized && d->m_loaderList.isEmpty() );
    }

    if( d->m_loaderList.isEmpty() ) {
        emit finalize();
    }

    if ( loader->isFinished() ) {
         d->m_pathList.removeAll( loader->path() );
         delete loader;
    }
}

void PlacemarkManager::loadKml( const QString& filename, bool clearPrevious )
{
    Q_UNUSED( clearPrevious )

    addPlacemarkFile( filename, true );
}

void PlacemarkManager::loadKmlFromData( const QString& data, const QString& key, bool finalize )
{
    Q_UNUSED( finalize )

    Q_ASSERT( d->m_model != 0 && "You have called loadKmlFromData before creating a model!" );

    PlacemarkContainer container;

    d->m_finalized = true;
    qDebug() << "adding container:" << key;
    PlacemarkLoader* loader = new PlacemarkLoader( this, data, key );
    connect (   loader, SIGNAL( placemarksLoaded( PlacemarkLoader*, PlacemarkContainer * ) ),
                this, SLOT( loadPlacemarkContainer( PlacemarkLoader*, PlacemarkContainer * ) ) );
    connect (   loader, SIGNAL( placemarkLoaderFailed( PlacemarkLoader* ) ),
                this, SLOT( cleanupLoader( PlacemarkLoader* ) ) );
    connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                this, SLOT( addGeoDataDocument( GeoDataDocument* ) ) );
    d->m_loaderList.append( loader );
    loader->start();
}

#include "PlacemarkManager.moc"
<commit_msg>Marble PlacemarkManager didn't delete it's default MarbleGeometryModel, because it doesn't take ownership of it. Now the MarbleGeometryModel is initialized with 0 to prevent this memory leak. Thanks to mjansen.<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
//

#include "PlacemarkManager.h"

#include <QtCore/QBuffer>
#include <QtCore/QByteArray>
#include <QtCore/QDataStream>
#include <QtCore/QDateTime>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtXml/QXmlInputSource>
#include <QtXml/QXmlSimpleReader>

#include "KmlFileViewItem.h"
#include "FileViewModel.h"
#include "MarbleDirs.h"
#include "MarblePlacemarkModel.h"
#include "MarbleGeometryModel.h"
#include "PlacemarkContainer.h"
#include "PlacemarkLoader.h"

#include "GeoDataDocument.h"
#include "GeoDataParser.h"
#include "GeoDataPlacemark.h"

using namespace Marble;

namespace Marble {
class PlacemarkManagerPrivate
{
    public:
        PlacemarkManagerPrivate( QObject* parent )
        : m_model( 0 )
        , m_geomodel( 0 )
        , m_fileViewModel( new FileViewModel(parent ) )
        , m_finalized( true )
        , m_target( QString() )
        {
        };

        MarblePlacemarkModel* m_model;
        MarbleGeometryModel* m_geomodel;
        QList<PlacemarkLoader*> m_loaderList;
        FileViewModel* m_fileViewModel;
        QStringList m_pathList;

        bool m_finalized;
        QString m_target;
};
}

PlacemarkManager::PlacemarkManager( QObject *parent )
    : QObject( parent )
    , d( new PlacemarkManagerPrivate( parent ) )
{

}

PlacemarkManager::~PlacemarkManager()
{
    foreach( PlacemarkLoader *loader, d->m_loaderList ) {
        if ( loader ) {
            loader->wait();
        }
    }

    delete d->m_model;
    delete d->m_fileViewModel;
    delete d;
    /* do not delete the d->m_geomodel here
     * it is not this models property
     */
}

MarblePlacemarkModel* PlacemarkManager::model() const
{
    return d->m_model;
}

FileViewModel* PlacemarkManager::fileViewModel() const
{
    return d->m_fileViewModel;
}

MarbleGeometryModel* PlacemarkManager::geomodel() const
{
    return d->m_geomodel;
}

void PlacemarkManager::setGeoModel( MarbleGeometryModel * model )
{
    d->m_geomodel = model;
}

void PlacemarkManager::setPlacemarkModel( MarblePlacemarkModel *model )
{
    d->m_model = model;
}

void PlacemarkManager::clearPlacemarks()
{
    d->m_model->clearPlacemarks();
}

QStringList PlacemarkManager::containers() const
{
    return fileViewModel()->containers() + d->m_pathList;
}

QString PlacemarkManager::toRegularName( QString name )
{
    return name.remove(".kml").remove(".cache");
}

void PlacemarkManager::addPlacemarkFile( const QString& filepath, bool finalized )
{
    if( ! containers().contains( toRegularName( filepath ) ) ) {
        qDebug() << "adding container:" << toRegularName( filepath ) << finalized;
        PlacemarkLoader* loader = new PlacemarkLoader( this, filepath, finalized );
        connect (   loader, SIGNAL( placemarksLoaded( PlacemarkLoader*, PlacemarkContainer * ) ),
                    this, SLOT( loadPlacemarkContainer( PlacemarkLoader*, PlacemarkContainer * ) ) );
        connect (   loader, SIGNAL( placemarkLoaderFailed( PlacemarkLoader* ) ),
                    this, SLOT( cleanupLoader( PlacemarkLoader* ) ) );
        connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                    this, SLOT( addGeoDataDocument( GeoDataDocument* ) ) );
        d->m_loaderList.append( loader );
        d->m_pathList.append( toRegularName( filepath ) );
        loader->start();
    }
}

void PlacemarkManager::addGeoDataDocument( GeoDataDocument* document )
{
    AbstractFileViewItem* item = new KmlFileViewItem( *this, *document );

    d->m_fileViewModel->append( item );

    // now get the document that will be preserved throughout the life time
    GeoDataDocument* doc = dynamic_cast<KmlFileViewItem*>(item)->document();
    // remove the hashes in front of the styles.
    QVector<GeoDataFeature>::Iterator end = doc->end();
    QVector<GeoDataFeature>::Iterator itr = doc->begin();
    for ( ; itr != end; ++itr ) {
        // use *itr (or itr.value()) here
        QString styleUrl = itr->styleUrl().remove('#');
        itr->setStyle( &doc->style( styleUrl ) );
    }

    // do not set this file if it only contains points
    if( doc->isVisible() && d->m_geomodel )
        d->m_geomodel->setGeoDataRoot( doc );
    emit geoDataDocumentAdded( *doc );
}

void PlacemarkManager::addPlacemarkData( const QString& data, const QString& key )
{
    loadKmlFromData( data, key, false );
}

void PlacemarkManager::removePlacemarkKey( const QString& key )
{
    QString nkey = key;
    qDebug() << "trying to remove file:" << key;
    for( int i = 0; i < d->m_fileViewModel->rowCount(); ++i )
    {
        if( toRegularName( nkey ) == toRegularName( d->m_fileViewModel->data(d->m_fileViewModel->index(i, 0)).toString() ) ) {
            d->m_fileViewModel->remove(d->m_fileViewModel->index(i, 0));
            break;
        }
    };
}

void PlacemarkManager::cleanupLoader( PlacemarkLoader* loader )
{
    d->m_loaderList.removeAll( loader );
    if ( loader->isFinished() ) {
         d->m_pathList.removeAll( loader->path() );
         delete loader;
    }
}

void PlacemarkManager::loadPlacemarkContainer( PlacemarkLoader* loader, PlacemarkContainer * container )
{
    qDebug() << "Containername:" << container->name() << "to be finalized:" << (d->m_loaderList.size() == 1) << d->m_loaderList.size();
    d->m_loaderList.removeAll( loader );
    if ( container )
    {
        d->m_model->addPlacemarks( *container, false, d->m_finalized && d->m_loaderList.isEmpty() );
    }

    if( d->m_loaderList.isEmpty() ) {
        emit finalize();
    }

    if ( loader->isFinished() ) {
         d->m_pathList.removeAll( loader->path() );
         delete loader;
    }
}

void PlacemarkManager::loadKml( const QString& filename, bool clearPrevious )
{
    Q_UNUSED( clearPrevious )

    addPlacemarkFile( filename, true );
}

void PlacemarkManager::loadKmlFromData( const QString& data, const QString& key, bool finalize )
{
    Q_UNUSED( finalize )

    Q_ASSERT( d->m_model != 0 && "You have called loadKmlFromData before creating a model!" );

    PlacemarkContainer container;

    d->m_finalized = true;
    qDebug() << "adding container:" << key;
    PlacemarkLoader* loader = new PlacemarkLoader( this, data, key );
    connect (   loader, SIGNAL( placemarksLoaded( PlacemarkLoader*, PlacemarkContainer * ) ),
                this, SLOT( loadPlacemarkContainer( PlacemarkLoader*, PlacemarkContainer * ) ) );
    connect (   loader, SIGNAL( placemarkLoaderFailed( PlacemarkLoader* ) ),
                this, SLOT( cleanupLoader( PlacemarkLoader* ) ) );
    connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                this, SLOT( addGeoDataDocument( GeoDataDocument* ) ) );
    d->m_loaderList.append( loader );
    loader->start();
}

#include "PlacemarkManager.moc"
<|endoftext|>