/*
 * hc08gpioport.h
 *
 * Copyright (C) 2016 - salvi
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef HC08GPIOPORT_H
#define HC08GPIOPORT_H

#ifndef HC08IOPORT_H
#include "hc08ioport.h"
#endif
#include "log.h"

#define DDROFFSET   4
#define PUEOFFSET   0xB
#define PTA			0
#define PTB			1
#define DDRA		(PTA + DDROFFSET)
#define DDRB		(PTB + DDROFFSET)
#define PTAPUE		(PTA + PUEOFFSET)
#define PTBPUE		(PTB + PUEOFFSET)

// AGGIUNGERE OPENCOLLECTOR
class InputConnector {
  private:
	InputConnector *next;
  protected:
	unsigned char totempoles;
	unsigned char opencollectors;
	unsigned char value;
  public:
	InputConnector (unsigned char ttp, unsigned char oc) { totempoles = ttp; opencollectors = oc; next = NULL; value = 0; };
	void setNext(InputConnector *nx) { next = nx; };
	InputConnector *getNext() { return next; };
	virtual unsigned char add(unsigned char input) {
		/* Log::printf("InputConnector::add(%02x) - ttp %02x/oc %02x/Valore %02x - Ritorno %02x", 
		  input, totempoles, opencollectors, value, 
		  ((input & ~totempoles) | (value & totempoles)) & (value | ~opencollectors)); */
		return (((input & ~totempoles) | (value & totempoles)) & (value | ~opencollectors)); };
	void setValue(unsigned char v) { value = v; };
	unsigned char getValue() { return value; };
};

class OutputConnector {
  private:
	OutputConnector *next;
  protected:
	unsigned char mask;
	unsigned char value;
  public:
	OutputConnector (unsigned char msk) { mask = msk; next = NULL; value = 0; };
	void setNext(OutputConnector *nx) { next = nx; };
	OutputConnector *getNext() { return next; };
	virtual void out(unsigned char v) { /* Log::printf("OutputConnector - out %x", v); */ value = v; };
};

class GpIoPort: public IoPort {
  private:
	unsigned char evalOutput();
	void sentToOutput();
  protected:
	InputConnector *inputs;
	OutputConnector *outputs;
	unsigned char ddr;
	unsigned char pue;
  public:
	GpIoPort (unsigned int addr):IoPort(addr) { ddr = 0; inputs = NULL; outputs = NULL; };
	void addInput(InputConnector *input) { input->setNext(inputs); inputs = input; }
	void addOutput (OutputConnector *output) { output->setNext(outputs); outputs = output; }
	virtual bool isPort(unsigned int rAddress) { return rAddress==address || rAddress==address + DDROFFSET || rAddress==address + PUEOFFSET; };
	virtual unsigned char getValue(unsigned int rAddress);
	virtual unsigned char getRowValue(unsigned int rAddress);
	unsigned char getVal() { return value; };
	unsigned char getDDR() { return ddr; };
	unsigned char getPUE() { return pue; };
	virtual void setValue(unsigned int rAddress, unsigned char dato);
};

#endif