/*
   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.  */


//
// p16x6x
//
//  This file supports:
//    P16C61

#define PORT_EXPERIMENT true


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


#include "packages.h"
#include "stimuli.h"
#include "symbol.h"

#include "p16x6x.h"
#include "pic-ioports.h"
#include "intcon.h"

void P16C61::create(void)
{

  create_iopin_map();

  _14bit_processor::create();

  add_file_registers(0x0c, 0x2f, 0x80);
  Pic14Bit::create_sfr_map();

}

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

  P16C61 *p = new P16C61(name);

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

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

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

  return p;

}

P16C61::P16C61(const char *_name, const char *desc)
  
{
}


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

void P16C62::create_iopin_map(void)
{
  package = new Package(28);
  if(!package)
    return;

  package->assign_pin(1, 0);

  package->assign_pin( 2, m_porta->addPin(new IO_bi_directional("porta0"),0));
  package->assign_pin( 3, m_porta->addPin(new IO_bi_directional("porta1"),1));
  package->assign_pin( 4, m_porta->addPin(new IO_bi_directional("porta2"),2));
  package->assign_pin( 5, m_porta->addPin(new IO_bi_directional("porta3"),3));
  package->assign_pin( 6, m_porta->addPin(new IO_open_collector("porta4"),4));
  package->assign_pin( 7, m_porta->addPin(new IO_bi_directional("porta5"),5));


  package->assign_pin(8, 0); //VSS
  package->assign_pin(9, 0);  // OSC
  package->assign_pin(10, 0); // OSC

  package->assign_pin(11, m_portc->addPin(new IO_bi_directional("portc0"),0));
  package->assign_pin(12, m_portc->addPin(new IO_bi_directional("portc1"),1));
  package->assign_pin(13, m_portc->addPin(new IO_bi_directional("portc2"),2));
  package->assign_pin(14, m_portc->addPin(new IO_bi_directional("portc3"),3));
  package->assign_pin(15, m_portc->addPin(new IO_bi_directional("portc4"),4));
  package->assign_pin(16, m_portc->addPin(new IO_bi_directional("portc5"),5));
  package->assign_pin(17, m_portc->addPin(new IO_bi_directional("portc6"),6));
  package->assign_pin(18, m_portc->addPin(new IO_bi_directional("portc7"),7));

  package->assign_pin(19, 0); //VSS
  package->assign_pin(20, 0); //VDD
  package->assign_pin(21, m_portb->addPin(new IO_bi_directional_pu("portb0"),0));
  package->assign_pin(22, m_portb->addPin(new IO_bi_directional_pu("portb1"),1));
  package->assign_pin(23, m_portb->addPin(new IO_bi_directional_pu("portb2"),2));
  package->assign_pin(24, m_portb->addPin(new IO_bi_directional_pu("portb3"),3));
  package->assign_pin(25, m_portb->addPin(new IO_bi_directional_pu("portb4"),4));
  package->assign_pin(26, m_portb->addPin(new IO_bi_directional_pu("portb5"),5));
  package->assign_pin(27, m_portb->addPin(new IO_bi_directional_pu("portb6"),6));
  package->assign_pin(28, m_portb->addPin(new IO_bi_directional_pu("portb7"),7));

  if (hasSSP()) {
    ssp.initialize(
		get_pir_set(),    // PIR
	 	&(*m_portc)[3],   // SCK
		&(*m_porta)[5],   // SS
		&(*m_portc)[5],   // SDO
		&(*m_portc)[4],   // SDI
		m_trisc,         // I2C port
		SSP_TYPE_BSSP
  	);  
  }

  tmr1l.setIOpin(&(*m_portc)[0]);

}

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

void P16C64::create_iopin_map(void)
{

  package = new Package(40);
  if(!package)
    return;

  // Now Create the package and place the I/O pins

  package->assign_pin(1, 0);

  package->assign_pin( 2, m_porta->addPin(new IO_bi_directional("porta0"),0));
  package->assign_pin( 3, m_porta->addPin(new IO_bi_directional("porta1"),1));
  package->assign_pin( 4, m_porta->addPin(new IO_bi_directional("porta2"),2));
  package->assign_pin( 5, m_porta->addPin(new IO_bi_directional("porta3"),3));
  package->assign_pin( 6, m_porta->addPin(new IO_open_collector("porta4"),4));
  package->assign_pin( 7, m_porta->addPin(new IO_bi_directional("porta5"),5));

  package->assign_pin( 8, m_porte->addPin(new IO_bi_directional("porte0"),0));
  package->assign_pin( 9, m_porte->addPin(new IO_bi_directional("porte1"),1));
  package->assign_pin(10, m_porte->addPin(new IO_bi_directional("porte2"),2));

  package->assign_pin(11, 0);
  package->assign_pin(12, 0);
  package->assign_pin(13, 0);
  package->assign_pin(14, 0);

  package->assign_pin(15, m_portc->addPin(new IO_bi_directional("portc0"),0));
  package->assign_pin(16, m_portc->addPin(new IO_bi_directional("portc1"),1));
  package->assign_pin(17, m_portc->addPin(new IO_bi_directional("portc2"),2));
  package->assign_pin(18, m_portc->addPin(new IO_bi_directional("portc3"),3));
  package->assign_pin(23, m_portc->addPin(new IO_bi_directional("portc4"),4));
  package->assign_pin(24, m_portc->addPin(new IO_bi_directional("portc5"),5));
  package->assign_pin(25, m_portc->addPin(new IO_bi_directional("portc6"),6));
  package->assign_pin(26, m_portc->addPin(new IO_bi_directional("portc7"),7));


  package->assign_pin(19, m_portd->addPin(new IO_bi_directional("portd0"),0));
  package->assign_pin(20, m_portd->addPin(new IO_bi_directional("portd1"),1));
  package->assign_pin(21, m_portd->addPin(new IO_bi_directional("portd2"),2));
  package->assign_pin(22, m_portd->addPin(new IO_bi_directional("portd3"),3));
  package->assign_pin(27, m_portd->addPin(new IO_bi_directional("portd4"),4));
  package->assign_pin(28, m_portd->addPin(new IO_bi_directional("portd5"),5));
  package->assign_pin(29, m_portd->addPin(new IO_bi_directional("portd6"),6));
  package->assign_pin(30, m_portd->addPin(new IO_bi_directional("portd7"),7));

  package->assign_pin(31, 0);
  package->assign_pin(32, 0);

  package->assign_pin(33, m_portb->addPin(new IO_bi_directional_pu("portb0"),0));
  package->assign_pin(34, m_portb->addPin(new IO_bi_directional_pu("portb1"),1));
  package->assign_pin(35, m_portb->addPin(new IO_bi_directional_pu("portb2"),2));
  package->assign_pin(36, m_portb->addPin(new IO_bi_directional_pu("portb3"),3));
  package->assign_pin(37, m_portb->addPin(new IO_bi_directional_pu("portb4"),4));
  package->assign_pin(38, m_portb->addPin(new IO_bi_directional_pu("portb5"),5));
  package->assign_pin(39, m_portb->addPin(new IO_bi_directional_pu("portb6"),6));
  package->assign_pin(40, m_portb->addPin(new IO_bi_directional_pu("portb7"),7));

  if (hasSSP()) {
    ssp.initialize(
		get_pir_set(),    // PIR
		&(*m_portc)[3],   // SCK
		&(*m_porta)[5],   // SS
		&(*m_portc)[5],   // SDO
		&(*m_portc)[4],   // SDI
		m_trisc,         // I2C port
		SSP_TYPE_BSSP
		   ); 
  }
  psp.initialize(get_pir_set(),    // PIR
		m_portd,	   // Parallel port
		m_trisd,	   // Parallel tris
		m_trise,	   // Control tris
		&(*m_porte)[0],	   // NOT RD
		&(*m_porte)[1],	   // NOT WR
		&(*m_porte)[2]);   // NOT CS

  tmr1l.setIOpin(&(*m_portc)[0]);
}


//---------------------------------------------------------
//
//  P16x6x::create_sfr_map(void) - Here's where all of the 
//  registers are defined for a p16c63 and greater...

void P16X6X_processor::create_sfr_map()
{

  if(verbose)
    cout << "P16X6X_processor::create_sfr_map\n";

  Pic14Bit::create_sfr_map();

  // P16x63 and higher have porta5
  m_porta->setEnableMask(0x3f);
  m_porta->setTris(m_trisa);

  // The 16c62,c64 have general purpose registers
  // at addresses 20-7f and a0-bf
  add_file_registers(0x20, 0x7f, 0);
  add_file_registers(0xa0, 0xbf, 0);


  add_sfr_register(pir1,   0x0c, RegisterValue(0,0),"pir1");
  add_sfr_register(&pie1,   0x8c, RegisterValue(0,0));

  add_sfr_register(&tmr1l,  0x0e, RegisterValue(0,0),"tmr1l");
  add_sfr_register(&tmr1h,  0x0f, RegisterValue(0,0),"tmr1h");

  add_sfr_register(&pcon,   0x8e, RegisterValue(0,0),"pcon");

  add_sfr_register(&t1con,  0x10, RegisterValue(0,0));
  add_sfr_register(&tmr2,   0x11, RegisterValue(0,0));
  add_sfr_register(&t2con,  0x12, RegisterValue(0,0));
  add_sfr_register(&pr2,    0x92, RegisterValue(0xff,0));

  if( hasSSP() ) {
    add_sfr_register(&ssp.sspbuf,  0x13, RegisterValue(0,0),"sspbuf");
    add_sfr_register(&ssp.sspcon,  0x14, RegisterValue(0,0),"sspcon");
    add_sfr_register(&ssp.sspadd,  0x93, RegisterValue(0,0),"sspadd");
    add_sfr_register(&ssp.sspstat, 0x94, RegisterValue(0,0),"sspstat");
    tmr2.ssp_module = &ssp;
  }

  add_sfr_register(&ccpr1l,  0x15, RegisterValue(0,0));
  add_sfr_register(&ccpr1h,  0x16, RegisterValue(0,0));
  add_sfr_register(&ccp1con, 0x17, RegisterValue(0,0));

  // get_pir_set()->set_pir1(get_pir1());
  pir_set_def.set_pir1(pir1);

  intcon = &intcon_reg;
  intcon_reg.set_pir_set(get_pir_set());

  // Maybe there's a better place for this, but let's go ahead and link all
  // of the registers together (there's probably a better way too) :

  tmr1l.tmrh = &tmr1h;
  tmr1l.t1con = &t1con;
  tmr1l.setInterruptSource(new InterruptSource(pir1, PIR1v1::TMR1IF));
  tmr1l.ccpcon = &ccp1con;

  tmr1h.tmrl  = &tmr1l;

  t1con.tmrl  = &tmr1l;

  t2con.tmr2  = &tmr2;
  tmr2.pir_set   = get_pir_set();
  tmr2.pr2    = &pr2;
  tmr2.t2con  = &t2con;
  tmr2.ccp1con = &ccp1con;
  tmr2.ccp2con = &ccp2con;
  pr2.tmr2    = &tmr2;


  ccp1con.setCrosslinks(&ccpr1l, get_pir_set(), &tmr2);
  ccp1con.setIOpin(&((*m_portc)[2]));
  ccpr1l.ccprh  = &ccpr1h;
  ccpr1l.tmrl   = &tmr1l;
  ccpr1h.ccprl  = &ccpr1l;

  //  portc->ccp1con = &ccp1con;

  ccpr1l.new_name("ccpr1l");
  ccpr1h.new_name("ccpr1h");
  ccp1con.new_name("ccp1con");

  if (pir1) {
    pir1->set_intcon(&intcon_reg);
    pir1->set_pie(&pie1);
  }
  pie1.pir    = pir1;
  pie1.new_name("pie1");


}
//--------------------------------------------------

void P16X6X_processor::create_symbols()
{
  Pic14Bit::create_symbols();
}


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

P16X6X_processor::P16X6X_processor(const char *_name, const char *_desc)
  : Pic14Bit(_name,_desc)
{
  

  if(verbose)
    cout << "generic 16X6X constructor, type = " << isa() << '\n';


  m_portc = new PicPortRegister("portc",8,0xff);
  m_trisc = new PicTrisRegister("trisc",m_portc);

  pir1 = new PIR1v1(&intcon_reg, &pie1);
  pir2 = new PIR2v1(&intcon_reg, &pie2);

}

P16X6X_processor::~P16X6X_processor()
{
  
}
/*******************************************************************
 *
 *        Definitions for the various P16x6x processors
 *
 */


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



void P16C62::create_sfr_map()
{
  if(verbose)
    cout << "creating c62 registers\n";

  P16X6X_processor::create_sfr_map();

  add_sfr_register(m_portc, 0x07);
  add_sfr_register(m_trisc, 0x87, RegisterValue(0xff,0));

  //1((PORTC*)portc)->ccp1con = &ccp1con;

}

void P16C62::create_symbols(void)
{

  if(verbose)
    cout << "creating c62 symbols\n";

  P16X6X_processor::create_symbols();
}


void  P16C62::create(void)
{

  if(verbose)
    cout << " c62 create \n";

  create_iopin_map();
  
  _14bit_processor::create();

  P16C62::create_sfr_map();

  // Build the links between the I/O Pins and the internal peripherals
  //1ccp1con.iopin = portc->pins[2];

}

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

  P16C62 *p = new P16C62(name);

  cout << " c62 construct\n";

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

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

  return p;

}

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

void P16C63::create_sfr_map(void)
{

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

  P16C62::create_sfr_map();

  add_file_registers(0xc0, 0xff, 0);

  add_sfr_register(pir2,    0x0d, RegisterValue(0,0),"pir2");
  add_sfr_register(&pie2,   0x8d, RegisterValue(0,0));

  add_sfr_register(&ccpr2l, 0x1b, RegisterValue(0,0));
  add_sfr_register(&ccpr2h, 0x1c, RegisterValue(0,0));
  add_sfr_register(&ccp2con, 0x1d, RegisterValue(0,0));

  // get_pir_set()->set_pir2(get_pir2());
  pir_set_def.set_pir2(pir2);

  ccp2con.setCrosslinks(&ccpr2l, get_pir_set(), &tmr2);
  ccp2con.setIOpin(&((*m_portc)[1]));
  ccpr2l.ccprh  = &ccpr2h;
  ccpr2l.tmrl   = &tmr1l;
  ccpr2h.ccprl  = &ccpr2l;

  usart.initialize(get_pir_set(),&(*m_portc)[6], &(*m_portc)[7],
		   new _TXREG(&usart), new _RCREG(&usart));

  add_sfr_register(&usart.rcsta, 0x18, RegisterValue(0,0),"rcsta");
  add_sfr_register(&usart.txsta, 0x98, RegisterValue(2,0),"txsta");
  add_sfr_register(&usart.spbrg, 0x99, RegisterValue(0,0),"spbrg");
  add_sfr_register(usart.txreg,  0x19, RegisterValue(0,0),"txreg");
  add_sfr_register(usart.rcreg,  0x1a, RegisterValue(0,0),"rcreg");

  ccpr2l.new_name("ccpr2l");
  ccpr2h.new_name("ccpr2h");
  ccp2con.new_name("ccp2con");

  if (pir2) {
    pir2->set_intcon(&intcon_reg);
    pir2->set_pie(&pie2);
  }

  pie2.pir    = get_pir2();
  pie2.new_name("pie2");


}

void P16C63::create_symbols(void)
{

  if(verbose)
    cout << "creating c63 symbols\n";

  // There's nothing to create...

}


//------------------------------------------------------------------------
//
// P16C63 constructor
// 
// Note: Since the 'C63 is derived from the 'C62. So before this constructor
// is called, the C62 constructor will be called. Most of the initialization
// is done within the 'C62 constructor.

P16C63::P16C63(const char *_name, const char *desc)
  : P16C62(_name,desc)
{

  if(verbose)
    cout << "c63 constructor, type = " << isa() << '\n';

}

void P16C63::create(void)
{
  if(verbose)
    cout << " c63 create \n";

  P16C62::create();

  P16C63::create_sfr_map();

  // Build the links between the I/O Pins and the internal peripherals
  //1ccp2con.iopin = portc->pins[1];

}

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

  P16C63 *p = new P16C63(name);

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

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

  p->create_symbols();

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

  return p;

}


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

void P16C64::create_sfr_map(void)
{
   if(verbose)
    cout << "creating c64 registers\n";

  pir_set_2_def.set_pir1(&pir1_2_reg);


  P16X6X_processor::create_sfr_map();

  add_sfr_register(m_portc, 0x07);
  add_sfr_register(m_trisc, 0x87, RegisterValue(0xff,0));

  add_sfr_register(m_portd, 0x08);
  add_sfr_register(m_trisd, 0x88, RegisterValue(0xff,0));

  add_sfr_register(m_porte, 0x09);
  add_sfr_register(m_trise, 0x89, RegisterValue(0x07,0));

  //1((PORTC*)portc)->ccp1con = &ccp1con;

}

void P16C64::create_symbols(void)
{

  if(verbose)
    cout << "creating c64 symbols\n";

  P16X6X_processor::create_symbols();

  symbol_table.add_register(m_portd);
  symbol_table.add_register(m_porte);

  symbol_table.add_register(m_trisd);
  symbol_table.add_register(m_trise);

}


void  P16C64::create(void)
{

  if(verbose)
    cout << " c64 create \n";

  create_iopin_map();
  
  _14bit_processor::create();

  //P16X6X_processor::create_sfr_map();
  P16C64::create_sfr_map();

  // Build the links between the I/O Pins and the internal peripherals
  //1ccp1con.iopin = portc->pins[2];

}

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

  P16C64 *p = new P16C64(name);

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

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

  return p;

}

P16C64::P16C64(const char *_name, const char *desc)
  : P16X6X_processor(_name,desc), 
  pir1_2_reg(&intcon_reg,&pie1)
{
  if(verbose)
    cout << "c64 constructor, type = " << isa() << '\n';

  pir1 = &pir1_2_reg;


  m_portd = new PicPSP_PortRegister("portd",8,0xff);
  m_trisd = new PicTrisRegister("trisd",(PicPortRegister *)m_portd);

  m_porte = new PicPortRegister("porte",8,0x07);
  m_trise =  new PicPSP_TrisRegister("trise",m_porte);

}
P16C64::~P16C64()
{
}
//------------------------------------------------------------------------
//
//

void P16C65::create_sfr_map(void)
{

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

  //P16C64::create_sfr_map();

  add_file_registers(0xc0, 0xff, 0);

  add_sfr_register(pir2,    0x0d, RegisterValue(0,0),"pir2");
  add_sfr_register(&pie2,   0x8d, RegisterValue(0,0));

  add_sfr_register(&ccpr2l, 0x1b, RegisterValue(0,0));
  add_sfr_register(&ccpr2h, 0x1c, RegisterValue(0,0));
  add_sfr_register(&ccp2con, 0x1d, RegisterValue(0,0));

  // get_pir_set()->set_pir2(&get_pir2());
  pir_set_def.set_pir2(pir2);


  ccp2con.setCrosslinks(&ccpr2l, get_pir_set(), &tmr2);
  ccp2con.setIOpin(&((*m_portc)[1]));

  ccpr2l.ccprh  = &ccpr2h;
  ccpr2l.tmrl   = &tmr1l;
  ccpr2h.ccprl  = &ccpr2l;

  usart.initialize(get_pir_set(),&(*m_portc)[6], &(*m_portc)[7],
		   new _TXREG(&usart), new _RCREG(&usart));

  add_sfr_register(&usart.rcsta, 0x18, RegisterValue(0,0),"rcsta");
  add_sfr_register(&usart.txsta, 0x98, RegisterValue(2,0),"txsta");
  add_sfr_register(&usart.spbrg, 0x99, RegisterValue(0,0),"spbrg");
  add_sfr_register(usart.txreg, 0x19, RegisterValue(0,0),"txreg");
  add_sfr_register(usart.rcreg, 0x1a, RegisterValue(0,0),"rcreg");

  ccpr2l.new_name("ccpr2l");
  ccpr2h.new_name("ccpr2h");
  ccp2con.new_name("ccp2con");

  if (pir2) {
    pir2->set_intcon(&intcon_reg);
    pir2->set_pie(&pie2);
  }

  pie2.pir    = get_pir2();
  pie2.new_name("pie2");

}

void P16C65::create_symbols(void)
{

  if(verbose)
    cout << "creating c65 symbols\n";

  // There's nothing to create...

}


//------------------------------------------------------------------------
//
// P16C65 constructor
// 
// Note: Since the 'C65 is derived from the 'C64. So before this constructor
// is called, the C64 constructor will be called. Most of the initialization
// is done within the 'C64 constructor.

P16C65::P16C65(const char *_name, const char *desc)
  : P16C64(_name,desc)
{

  if(verbose)
    cout << "c65 constructor, type = " << isa() << '\n';
}

void P16C65::create(void)
{
  if(verbose)
    cout << " c65 create \n";

  P16C64::create();

  P16C65::create_sfr_map();

  // Build the links between the I/O Pins and the internal peripherals
  // ccp1con.iopin = portc.pins[2];
  //1ccp2con.iopin = portc->pins[1];

}

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

  P16C65 *p = new P16C65(name);

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

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

  p->create_symbols();

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

  return p;

}



syntax highlighted by Code2HTML, v. 0.9.1