/*
   Copyright (C) 1998 T. Scott Dattalo

This file is part of gpsim.

gpsim 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, or (at your option)
any later version.

gpsim 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 gpasm; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */


//
// p16x7x
//
//  This file supports:
//    P16C71
//    P16C712
//    P16C716
//    P16C72
//    P16C73
//    P16C74


#include <stdio.h>
#include <iostream>
#include <string>

#include "../config.h"
#include "symbol.h"

#include "p16x7x.h"
#include "pic-ioports.h"
#include "stimuli.h"
#include "pm_rd.h"


//#define DEBUG_AD


//------------------------------------------------------
class P16C71::PIR_16C71 : public PIR_SET
{
public:
  PIR_16C71(ADCON0 *adcon0)
    : m_adcon0(adcon0)
  {
  }

  virtual bool interrupt_status()
  {
    return m_adcon0->getADIF();
  }
private:
  ADCON0 *m_adcon0;
};

//------------------------------------------------------------------------
//
P16C71::P16C71(const char *_name, const char *desc)
  : P16C61(_name, desc)
{
  if(verbose)
    cout << "c71 constructor, type = " << isa() << '\n';

  m_pir = new PIR_16C71(&adcon0);
}


void P16C71::create_sfr_map()
{

  if(verbose)
    cout << "creating c71 registers \n";

  add_sfr_register(&adcon0, 0x08, RegisterValue(0,0));
  add_sfr_register(&adcon1, 0x88, RegisterValue(0,0));

  add_sfr_register(&adres,  0x89, RegisterValue(0,0));
  add_sfr_register(&adres,  0x09, RegisterValue(0,0));


  adres.new_name("adres");

  adcon1.setValidCfgBits(ADCON1::PCFG0 | ADCON1::PCFG1,0);
  adcon1.setNumberOfChannels(4);
  adcon1.setIOPin(0, &(*m_porta)[0]);
  adcon1.setIOPin(1, &(*m_porta)[1]);
  adcon1.setIOPin(2, &(*m_porta)[2]);
  adcon1.setIOPin(3, &(*m_porta)[3]);
  adcon1.setChannelConfiguration(0, 0x0f);
  adcon1.setChannelConfiguration(1, 0x0f);
  adcon1.setChannelConfiguration(2, 0x03);
  adcon1.setChannelConfiguration(3, 0x00);
  adcon1.setVrefHiConfiguration(1, 3);

  adcon0.setAdres(&adres);
  adcon0.setAdresLow(0);
  adcon0.setAdcon1(&adcon1);
  adcon0.setIntcon(&intcon_reg);
  adcon0.setA2DBits(8);

  intcon = &intcon_reg;

  intcon_reg.set_pir_set(m_pir);

}


void P16C71::create_symbols()
{
  pic_processor::create_symbols();
}

void P16C71::create()
{

  P16C61::create();

  create_sfr_map();

}

Processor * P16C71::construct(const char *name)
{

  P16C71 *p = new P16C71(name);

  if(verbose)
    cout << " c71 construct\n";

  p->create();
  p->create_invalid_registers ();
  p->create_symbols();

  symbol_table.add_module(p,p->name().c_str());

  return p;

}



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

void P16C712::create_sfr_map()
{

  if(verbose)
    cout << "creating c712/6 registers \n";

  /* Extra timers and Capture/Compare are like in 16x63 => 16X6X code */
  P16X6X_processor::create_sfr_map();

  /* The A/D section is similar to 16x71, but not equal */
  add_sfr_register(&adcon0, 0x1F, RegisterValue(0,0));
  add_sfr_register(&adcon1, 0x9F, RegisterValue(0,0));

  add_sfr_register(&adres,  0x1E, RegisterValue(0,0));

  //1adcon0.analog_port = porta;
  adcon0.setAdres(&adres);
  adcon0.setAdresLow(0);
  adcon0.setAdcon1(&adcon1);
  adcon0.setIntcon(&intcon_reg);
  adcon0.setChannel_Mask(3);
  adcon0.setA2DBits(8);
  intcon = &intcon_reg;

  adcon1.setValidCfgBits(ADCON1::PCFG0 | ADCON1::PCFG1| ADCON1::PCFG2,0);
  adcon1.setNumberOfChannels(4);
  adcon1.setIOPin(0, &(*m_porta)[0]);
  adcon1.setIOPin(1, &(*m_porta)[1]);
  adcon1.setIOPin(2, &(*m_porta)[2]);
  adcon1.setIOPin(3, &(*m_porta)[3]);
  adcon1.setChannelConfiguration(0, 0x0f);
  adcon1.setChannelConfiguration(1, 0x0f);
  adcon1.setChannelConfiguration(2, 0x0f);
  adcon1.setChannelConfiguration(3, 0x0f);
  adcon1.setChannelConfiguration(4, 0x0b);
  adcon1.setChannelConfiguration(5, 0x0b);
  adcon1.setChannelConfiguration(6, 0x00);
  adcon1.setChannelConfiguration(7, 0x00);
  adcon1.setVrefHiConfiguration(1, 3);
  adcon1.setVrefHiConfiguration(3, 3);
  adcon1.setVrefHiConfiguration(5, 3);

  adcon0.new_name("adcon0");
  adcon1.new_name("adcon1");
  adres.new_name("adres");
}



void P16C712::create()
{

  if(verbose)
    cout << " c712/6 create \n";
  create_iopin_map(); /* 14 bits 18 pins connections */
  _14bit_processor::create();
  create_sfr_map();
  //1ccp1con.iopin = portb->pins[2];

}

Processor * P16C712::construct(const char *name)
{

  P16C712 *p = new P16C712(name);

  if(verbose)
    cout << " c712 construct\n";

  p->create();
  p->create_invalid_registers ();
  p->create_symbols();

  symbol_table.add_module(p,p->name().c_str());

  return p;

}


P16C712::P16C712(const char *_name, const char *desc)
  : P16C62(_name, desc)
{
  if(verbose)
    cout << "c712 constructor, type = " << isa() << '\n';

}


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

Processor * P16C716::construct(const char *name)
{

  P16C716 *p = new P16C716(name);

  if(verbose)
    cout << " c716 construct\n";

  p->create();
  p->create_invalid_registers ();
  p->create_symbols();

  symbol_table.add_module(p,p->name().c_str());

  return p;

}


P16C716::P16C716(const char *_name, const char *desc)
  : P16C712(_name, desc)
{
  if(verbose)
    cout << "c716 constructor, type = " << isa() << '\n';

}


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

void P16C72::create_sfr_map()
{

  if(verbose)
    cout << "creating c72 registers \n";

  // Parent classes just set PIR version 1
  pir_set_2_def.set_pir1(&pir1_2_reg);
  pir_set_2_def.set_pir2(&pir2_2_reg);

  add_sfr_register(&adcon0, 0x1f, RegisterValue(0,0));
  add_sfr_register(&adcon1, 0x9f, RegisterValue(0,0));

  add_sfr_register(&adres,  0x1e, RegisterValue(0,0));

  adcon0.setAdres(&adres);
  adcon0.setAdresLow(0);
  adcon0.setAdcon1(&adcon1);
  adcon0.setIntcon(&intcon_reg);
  // adcon0.pir_set = get_pir_set();
  adcon0.pir_set = &pir_set_2_def;
  adcon0.setChannel_Mask(7); // even though there are only 5 inputs...
  adcon0.setA2DBits(8);

  intcon = &intcon_reg;

  adcon1.setValidCfgBits(ADCON1::PCFG0 | ADCON1::PCFG1| ADCON1::PCFG2, 0);
  adcon1.setNumberOfChannels(5);
  adcon1.setIOPin(0, &(*m_porta)[0]);
  adcon1.setIOPin(1, &(*m_porta)[1]);
  adcon1.setIOPin(2, &(*m_porta)[2]);
  adcon1.setIOPin(3, &(*m_porta)[3]);
  adcon1.setIOPin(4, &(*m_porta)[5]);
  adcon1.setChannelConfiguration(0, 0x1f);
  adcon1.setChannelConfiguration(1, 0x1f);
  adcon1.setChannelConfiguration(2, 0x1f);
  adcon1.setChannelConfiguration(3, 0x1f);
  adcon1.setChannelConfiguration(4, 0x0b);
  adcon1.setChannelConfiguration(5, 0x0b);
  adcon1.setChannelConfiguration(6, 0x00);
  adcon1.setChannelConfiguration(7, 0x00);
  adcon1.setVrefHiConfiguration(1, 3);
  adcon1.setVrefHiConfiguration(3, 3);
  adcon1.setVrefHiConfiguration(5, 3);

  adcon0.new_name("adcon0");
  adcon1.new_name("adcon1");
  adres.new_name("adres");

  // Link the A/D converter to the Capture Compare Module
  ccp2con.setADCON(&adcon0);
}


void P16C72::create_symbols()
{

  if(verbose)
    cout << "c72 create symbols\n";
  pic_processor::create_symbols();
}


void P16C72::create()
{

  P16C62::create();

  P16C72::create_sfr_map();

}

Processor * P16C72::construct(const char *name)
{

  P16C72 *p = new P16C72(name);

  if(verbose)
    cout << " c72 construct\n";

  p->create();
  p->create_invalid_registers ();
  p->create_symbols();


  symbol_table.add_module(p,p->name().c_str());

  return p;

}


P16C72::P16C72(const char *_name, const char *desc)
  : P16C62(_name, desc),
    pir1_2_reg(&intcon_reg,&pie1), pir2_2_reg(&intcon_reg,&pie2)
{
  if(verbose)
    cout << "c72 constructor, type = " << isa() << '\n';

  pir1 = &pir1_2_reg;
  pir2 = &pir2_2_reg;

}


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

void P16C73::create_sfr_map()
{

  if(verbose)
    cout << "creating c73 registers \n";

  // Parent classes just set PIR version 1
  pir_set_2_def.set_pir1(&pir1_2_reg);
  pir_set_2_def.set_pir2(&pir2_2_reg);

  add_sfr_register(&adcon0, 0x1f, RegisterValue(0,0));
  add_sfr_register(&adcon1, 0x9f, RegisterValue(0,0));

  add_sfr_register(&adres,  0x1e, RegisterValue(0,0));

  //1adcon0.analog_port = porta;
  //2adcon0.analog_port2 = 0;
  adcon0.setAdres(&adres);
  adcon0.setAdresLow(0);
  adcon0.setAdcon1(&adcon1);
  adcon0.setIntcon(&intcon_reg);
  // adcon0.pir_set = get_pir_set();
  adcon0.pir_set = &pir_set_2_def;
  adcon0.setChannel_Mask(7); // even though there are only 5 inputs...
  adcon0.setA2DBits(8);

  intcon = &intcon_reg;

  //1adcon1.analog_port = porta;
  adcon1.setValidCfgBits(ADCON1::PCFG0 | ADCON1::PCFG1| ADCON1::PCFG2, 0);

  adcon1.setNumberOfChannels(5);
  adcon1.setIOPin(0, &(*m_porta)[0]);
  adcon1.setIOPin(1, &(*m_porta)[1]);
  adcon1.setIOPin(2, &(*m_porta)[2]);
  adcon1.setIOPin(3, &(*m_porta)[3]);
  adcon1.setIOPin(4, &(*m_porta)[5]);
  adcon1.setChannelConfiguration(0, 0x1f);
  adcon1.setChannelConfiguration(1, 0x1f);
  adcon1.setChannelConfiguration(2, 0x1f);
  adcon1.setChannelConfiguration(3, 0x1f);
  adcon1.setChannelConfiguration(4, 0x0b);
  adcon1.setChannelConfiguration(5, 0x0b);
  adcon1.setChannelConfiguration(6, 0x00);
  adcon1.setChannelConfiguration(7, 0x00);
  adcon1.setVrefHiConfiguration(1, 3);
  adcon1.setVrefHiConfiguration(3, 3);
  adcon1.setVrefHiConfiguration(5, 3);


  adcon0.new_name("adcon0");
  adcon1.new_name("adcon1");
  adres.new_name("adres");

  // Link the A/D converter to the Capture Compare Module
  ccp2con.setADCON(&adcon0);
}


void P16C73::create_symbols()
{

  if(verbose)
    cout << "c73 create symbols\n";
  pic_processor::create_symbols();
}


void P16C73::create()
{

  P16C63::create();

  P16C73::create_sfr_map();

}

Processor * P16C73::construct(const char *name)
{

  P16C73 *p = new P16C73(name);

  if(verbose)
    cout << " c73 construct\n";

  p->create();
  p->create_invalid_registers ();
  p->create_symbols();

  symbol_table.add_module(p,p->name().c_str());

  return p;

}


P16C73::P16C73(const char *_name, const char *desc)
  : P16C63(_name, desc),
    pir1_2_reg(&intcon_reg,&pie1), pir2_2_reg(&intcon_reg,&pie2)
{
  if(verbose)
    cout << "c73 constructor, type = " << isa() << '\n';

  pir1 = &pir1_2_reg;
  pir2 = &pir2_2_reg;


}

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

void P16F73::create_sfr_map()
{

  if(verbose)
    cout << "creating f73 registers \n";

  add_sfr_register(pm_rd.get_reg_pmadr(),  0x10d);
  add_sfr_register(pm_rd.get_reg_pmadrh(), 0x10f);
  add_sfr_register(pm_rd.get_reg_pmdata(), 0x10c);
  add_sfr_register(pm_rd.get_reg_pmdath(), 0x10e);
  add_sfr_register(pm_rd.get_reg_pmcon1(), 0x18c);

  alias_file_registers(0x80,0x80,0x80);
  alias_file_registers(0x01,0x01,0x100);
  alias_file_registers(0x82,0x84,0x80);
  alias_file_registers(0x06,0x06,0x100);
  alias_file_registers(0x8a,0x8b,0x80);
  alias_file_registers(0x100,0x100,0x80);
  alias_file_registers(0x81,0x81,0x100);
  alias_file_registers(0x102,0x104,0x80);
  alias_file_registers(0x86,0x86,0x100);
  alias_file_registers(0x10a,0x10b,0x80);


  alias_file_registers(0x20,0x7f,0x100);
  alias_file_registers(0xa0,0xff,0x100);

}


void P16F73::create_symbols()
{

  if(verbose)
    cout << "f73 create symbols\n";
  pic_processor::create_symbols();
}


void P16F73::create()
{

  P16C73::create();

  pm_rd.set_cpu(this);

  status->rp_mask = 0x60;  // rp0 and rp1 are valid.
  indf->base_address_mask1 = 0x80; // used for indirect accesses above 0x100
  indf->base_address_mask2 = 0x1ff; // used for indirect accesses above 0x100

  P16F73::create_sfr_map();

}

Processor * P16F73::construct(const char *name)
{

  P16F73 *p = new P16F73(name);

  if(verbose)
    cout << " f73 construct\n";

  p->create();
  p->create_invalid_registers ();
  p->create_symbols();

  symbol_table.add_module(p,p->name().c_str());

  return p;

}


P16F73::P16F73(const char *_name, const char *desc)
  : P16C73(_name, desc)
{
  if(verbose)
    cout << "f73 constructor, type = " << isa() << '\n';

}

//------------------------------------------------------------
//
//           16C74
//

void P16C74::create_sfr_map()
{

  if(verbose)
    cout << "creating c74 registers \n";

  // Parent classes just set PIR version 1
  pir_set_2_def.set_pir1(&pir1_2_reg);
  pir_set_2_def.set_pir2(&pir2_2_reg);

  add_sfr_register(&adcon0, 0x1f, RegisterValue(0,0));
  add_sfr_register(&adcon1, 0x9f, RegisterValue(0,0));

  add_sfr_register(&adres,  0x1e, RegisterValue(0,0));

  //1adcon0.analog_port = porta;
  //1adcon0.analog_port2 = porte;

  adcon0.setAdres(&adres);
  adcon0.setAdresLow(0);
  adcon0.setAdcon1(&adcon1);
  adcon0.setIntcon(&intcon_reg);
  adcon0.pir_set = &pir_set_2_def;
  adcon0.setChannel_Mask(7);
  adcon0.setA2DBits(8);

  intcon = &intcon_reg;


  adcon1.setValidCfgBits(ADCON1::PCFG0 | ADCON1::PCFG1 | ADCON1::PCFG2, 0);
  adcon1.setNumberOfChannels(8);
  adcon1.setIOPin(0, &(*m_porta)[0]);
  adcon1.setIOPin(1, &(*m_porta)[1]);
  adcon1.setIOPin(2, &(*m_porta)[2]);
  adcon1.setIOPin(3, &(*m_porta)[3]);
  adcon1.setIOPin(4, &(*m_porta)[5]);
  adcon1.setIOPin(5, &(*m_porte)[0]);
  adcon1.setIOPin(6, &(*m_porte)[1]);
  adcon1.setIOPin(7, &(*m_porte)[2]);

  adcon1.setChannelConfiguration(0, 0xff);
  adcon1.setChannelConfiguration(1, 0xff);
  adcon1.setChannelConfiguration(2, 0x1f);
  adcon1.setChannelConfiguration(3, 0x1f);
  adcon1.setChannelConfiguration(4, 0x0b);
  adcon1.setChannelConfiguration(5, 0x0b);
  adcon1.setChannelConfiguration(6, 0x00);
  adcon1.setChannelConfiguration(7, 0x00);

  adcon1.setVrefHiConfiguration(1, 3);
  adcon1.setVrefHiConfiguration(3, 3);
  adcon1.setVrefHiConfiguration(5, 3);


  adcon0.new_name("adcon0");
  adcon1.new_name("adcon1");
  adres.new_name("adres");

  // Link the A/D converter to the Capture Compare Module
  ccp2con.setADCON(&adcon0);
}


void P16C74::create_symbols()
{

  if(verbose)
    cout << "c74 create symbols\n";
  Pic14Bit::create_symbols();
}


void P16C74::create()
{

  P16C65::create();

  P16C74::create_sfr_map();

}

Processor * P16C74::construct(const char *name)
{

  P16C74 *p = new P16C74(name);;

  if(verbose)
    cout << " c74 construct\n";

  p->create();
  p->create_invalid_registers ();
  p->create_symbols();

  symbol_table.add_module(p,p->name().c_str());

  return p;

}


P16C74::P16C74(const char *_name, const char *desc)
  : P16C65(_name, desc) ,
    pir1_2_reg(&intcon_reg,&pie1), pir2_2_reg(&intcon_reg,&pie2)
{
  if(verbose)
    cout << "c74 constructor, type = " << isa() << '\n';

  pir1 = &pir1_2_reg;
  pir2 = &pir2_2_reg;

}

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

void P16F74::create_sfr_map()
{

  if(verbose)
    cout << "creating f74 registers \n";

  add_sfr_register(pm_rd.get_reg_pmadr(),  0x10d);
  add_sfr_register(pm_rd.get_reg_pmadrh(), 0x10f);
  add_sfr_register(pm_rd.get_reg_pmdata(), 0x10c);
  add_sfr_register(pm_rd.get_reg_pmdath(), 0x10e);
  add_sfr_register(pm_rd.get_reg_pmcon1(), 0x18c);

  alias_file_registers(0x80,0x80,0x80);
  alias_file_registers(0x01,0x01,0x100);
  alias_file_registers(0x82,0x84,0x80);
  alias_file_registers(0x06,0x06,0x100);
  alias_file_registers(0x8a,0x8b,0x80);
  alias_file_registers(0x100,0x100,0x80);
  alias_file_registers(0x81,0x81,0x100);
  alias_file_registers(0x102,0x104,0x80);
  alias_file_registers(0x86,0x86,0x100);
  alias_file_registers(0x10a,0x10b,0x80);


  alias_file_registers(0x20,0x7f,0x100);
  alias_file_registers(0xa0,0xff,0x100);

}


void P16F74::create_symbols()
{

  if(verbose)
    cout << "f74 create symbols\n";
  pic_processor::create_symbols();
}


void P16F74::create()
{

  P16C74::create();

  pm_rd.set_cpu(this);

  status->rp_mask = 0x60;  // rp0 and rp1 are valid.
  indf->base_address_mask1 = 0x80; // used for indirect accesses above 0x100
  indf->base_address_mask2 = 0x1ff; // used for indirect accesses above 0x100

  P16F74::create_sfr_map();

}

Processor * P16F74::construct(const char *name)
{

  P16F74 *p = new P16F74(name);

  if(verbose)
    cout << " f74 construct\n";

  p->create();
  p->create_invalid_registers ();
  p->create_symbols();

  symbol_table.add_module(p,p->name().c_str());

  return p;

}


P16F74::P16F74(const char *_name, const char *desc)
  : P16C74(_name, desc)
{
  if(verbose)
    cout << "f74 constructor, type = " << isa() << '\n';

}




syntax highlighted by Code2HTML, v. 0.9.1