/*
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 gpsim; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef __14_BIT_TMRS_H__
#define __14_BIT_TMRS_H__
#include "gpsim_classes.h"
#include "registers.h"
#include "breakpoints.h"
#include "ioports.h"
#include "ssp.h"
class TMRL;
class TMRH;
class TMR2;
class CCPRL;
class ADCON0;
class PIR_SET;
class InterruptSource;
class _14bit_processor;
//---------------------------------------------------------
// Todo
//
// The timer base classes need to be abstracted one more
// layer. The 18fxxx parts have a new timer, TMR3, that's
// almost but not quite, identical to the 16fxx's TMR1.
//---------------------------------------------------------
// CCPCON - Capture and Compare registers
//---------------------------------------------------------
class CCPRH : public sfr_register
{
public:
CCPRL *ccprl;
bool pwm_mode;
unsigned int pwm_value;
CCPRH();
void put(unsigned int new_value);
void put_value(unsigned int new_value);
unsigned int get();
};
class CCPRL : public sfr_register
{
public:
CCPRH *ccprh;
TMRL *tmrl;
void put(unsigned int new_value);
void capture_tmr();
void start_compare_mode();
void stop_compare_mode();
void start_pwm_mode();
void stop_pwm_mode();
void assign_tmr(TMRL *ptmr);
CCPRL();
};
//---------------------------------------------------------
// CCPCON - Capture and Compare Control register
//---------------------------------------------------------
class CCPSignalSource; // I/O pin interface
class CCPSignalSink; // I/O pin interface
class PinModule;
class CCPCON : public sfr_register
{
public:
/* Bit definitions for the register */
enum {
CCPM0 = 1 << 0,
CCPM1 = 1 << 1,
CCPM2 = 1 << 2,
CCPM3 = 1 << 3,
CCPY = 1 << 4,
CCPX = 1 << 5
};
/* Define the Modes (based on the CCPM bits) */
enum {
ALL_OFF0 = 0,
ALL_OFF1 = 1,
ALL_OFF2 = 2,
ALL_OFF3 = 3,
CAP_FALLING_EDGE = 4,
CAP_RISING_EDGE = 5,
CAP_RISING_EDGE4 = 6,
CAP_RISING_EDGE16 = 7,
COM_SET_OUT = 8,
COM_CLEAR_OUT = 9,
COM_INTERRUPT = 10,
COM_TRIGGER = 11,
PWM0 = 12,
PWM1 = 13,
PWM2 = 14,
PWM3 = 15
};
void new_edge(unsigned int level);
void compare_match();
void pwm_match(int new_state);
void put(unsigned int new_value);
char getState();
void setCrosslinks(CCPRL *, PIR_SET *, TMR2 *);
void setADCON(ADCON0 *);
CCPCON();
void setIOpin(PinModule *);
private:
PinModule *m_PinModule;
CCPSignalSource *m_source;
CCPSignalSink *m_sink;
bool m_bInputEnabled; // Input mode for capture/compare
bool m_bOutputEnabled; // Output mode for PWM
char m_cOutputState;
int edges;
CCPRL *ccprl;
PIR_SET *pir_set;
TMR2 *tmr2;
ADCON0 *adcon0;
};
//---------------------------------------------------------
// T1CON - Timer 1 control register
class T1CON : public sfr_register
{
public:
enum
{
TMR1ON = 1<<0,
TMR1CS = 1<<1,
T1SYNC = 1<<2,
T1OSCEN = 1<<3,
T1CKPS0 = 1<<4,
T1CKPS1 = 1<<5,
T1RD16 = 1<<6
};
TMRL *tmrl;
T1CON();
unsigned int get();
// For (at least) the 18f family, there's a 4X PLL that effects the
// the relative timing between gpsim's cycle counter (which is equivalent
// to the cumulative instruction count) and the external oscillator. In
// all parts, the clock source for the timer is fosc, the external oscillator.
// However, for the 18f parts, the instructions execute 4 times faster when
// the PLL is selected.
virtual unsigned int get_prescale();
unsigned int get_tmr1cs()
{
return(value.get() & TMR1CS);
}
unsigned int get_tmr1on()
{
return(value.get() & TMR1ON);
}
virtual void put(unsigned int new_value);
};
//---------------------------------------------------------
// TMRL & TMRH - Timer 1
class TMRH : public sfr_register
{
public:
TMRL *tmrl;
void put(unsigned int new_value);
unsigned int get();
virtual unsigned int get_value();
TMRH();
};
class TMRL : public sfr_register, public TriggerObject, public SignalSink
{
public:
TMRH *tmrh;
T1CON *t1con;
CCPCON *ccpcon;
unsigned int
prescale,
prescale_counter,
break_value,
compare_value,
value_16bit; /* Low and high concatenated */
guint64
synchronized_cycle,
last_cycle,
future_cycle;
bool compare_mode;
virtual void callback();
virtual void callback_print();
TMRL();
virtual void put(unsigned int new_value);
virtual unsigned int get();
virtual unsigned int get_value();
virtual unsigned int get_low_and_high();
virtual void on_or_off(int new_state);
virtual void current_value();
virtual void new_clock_source();
virtual void update();
virtual void clear_timer();
virtual void setSinkState(char);
virtual void setIOpin(PinModule *);
virtual void setInterruptSource(InterruptSource *);
protected:
virtual void increment(); // Used when TMR1 is attached to an external clock
private:
char m_cState;
bool m_bExtClkEnabled;
InterruptSource *m_Interrupt;
};
class PR2 : public sfr_register
{
public:
TMR2 *tmr2;
PR2();
void put(unsigned int new_value);
};
//---------------------------------------------------------
// T2CON - Timer 2 control register
class T2CON : public sfr_register
{
public:
enum
{
T2CKPS0 = 1<<0,
T2CKPS1 = 1<<1,
TMR2ON = 1<<2,
TOUTPS0 = 1<<3,
TOUTPS1 = 1<<4,
TOUTPS2 = 1<<5,
TOUTPS3 = 1<<6
};
TMR2 *tmr2;
T2CON();
inline unsigned int get_t2ckps0()
{
return(value.get() & T2CKPS0);
}
inline unsigned int get_t2ckps1()
{
return(value.get() & T2CKPS1);
}
inline unsigned int get_tmr2on()
{
return(value.get() & TMR2ON);
}
inline unsigned int get_post_scale()
{
return( (value.get() & (TOUTPS0 | TOUTPS1 | TOUTPS2 | TOUTPS3)) >> 3 );
}
inline unsigned int get_pre_scale()
{
// ps1:ps0 prescale
// 0 0 1
// 0 1 4
// 1 x 16
if(value.get() & T2CKPS1)
return 16;
else
if(value.get() & T2CKPS0)
return 4;
else
return 1;
}
void put(unsigned int new_value);
};
//---------------------------------------------------------
// TMR2 - Timer
class TMR2 : public sfr_register, public TriggerObject
{
public:
/* Define the way in which the tmr2 callback function may be updated. */
enum TMR2_UPDATE_TYPES
{
TMR2_PWM1_UPDATE = 1<<0, // wrt ccp1
TMR2_PWM2_UPDATE = 1<<1, // wrt ccp2
TMR2_PR2_UPDATE = 1<<2, // update pr2 match
TMR2_WRAP = 1<<3, // wrap TMR2
TMR2_DONTCARE_UPDATE = 0xf // whatever comes next
};
int pwm_mode;
int update_state;
int last_update;
unsigned int
prescale,
prescale_counter,
break_value,
duty_cycle1, /* for ccp1 */
duty_cycle2; /* for ccp2 */
int
post_scale;
guint64
last_cycle,
future_cycle;
PR2 *pr2;
PIR_SET *pir_set;
T2CON *t2con;
CCPCON *ccp1con;
CCPCON *ccp2con;
SSP_MODULE *ssp_module;
virtual void callback();
virtual void callback_print();
TMR2();
void put(unsigned int new_value);
unsigned int get();
void on_or_off(int new_state);
void start();
void new_pre_post_scale();
void new_pr2(unsigned int new_value);
void current_value();
void update(int ut = TMR2_DONTCARE_UPDATE);
void pwm_dc(unsigned int dc, unsigned int ccp_address);
void stop_pwm(unsigned int ccp_address);
virtual unsigned int get_value();
};
//---------------------------------------------------------
//
// TMR2_MODULE
//
//
class TMR2_MODULE
{
public:
_14bit_processor *cpu;
char * name_str;
T2CON *t2con;
PR2 *pr2;
TMR2 *tmr2;
TMR2_MODULE();
void initialize(T2CON *t2con, PR2 *pr2, TMR2 *tmr2);
};
//---------------------------------------------------------
//
// TMR1_MODULE
//
//
class TMR1_MODULE
{
public:
_14bit_processor *cpu;
char * name_str;
T1CON *t1con;
PIR_SET *pir_set;
TMR1_MODULE();
void initialize(T1CON *t1con, PIR_SET *pir_set);
};
#endif
syntax highlighted by Code2HTML, v. 0.9.1