\documentclass[11pt]{article}
\usepackage{pdflscape}
\newif\ifpdf
\ifx\pdfoutput\undefined
    \pdffalse           % we are not running PDFLaTeX
\else
    \pdfoutput=1        % we are running PDFLaTeX
    \pdftrue
\fi
%----------------------------------------------------------------------
\ifpdf
    \usepackage[pdftex,
        letterpaper=true,
        colorlinks=true,
        urlcolor=rltblue,               % \href{...}{...}
        anchorcolor=rltbrightblue,
        filecolor=rltgreen,             % \href*{...}
        linkcolor=rltred,               % \ref{...} and \pageref{...}
        menucolor=webdarkblue,
        citecolor=webbrightgreen,
        pdftitle={EE 308 Spring 2009},
        pdfauthor={Bill Rison, New Mexico Tech},
        pagebackref,
        pdfpagemode=None,
        bookmarksopen=true]{hyperref}
    \pdfcompresslevel=9
    \usepackage[pdftex]{graphicx}
    \usepackage{thumbpdf}
\else
    \usepackage[dvips,
        letterpaper=true,
        colorlinks=true,
        urlcolor=rltblue,               % \href{...}{...}
        anchorcolor=rltbrightblue,
        filecolor=rltgreen,             % \href*{...}
        linkcolor=rltred,               % \ref{...} and \pageref{...}
        menucolor=webdarkblue,
        citecolor=webbrightgreen]{hyperref}
    \usepackage{graphicx}
\fi

\usepackage{color}
\definecolor{rltbrightred}{rgb}{1,0,0}
\definecolor{Red}{rgb}{1,0,0}
\definecolor{rltred}{rgb}{0.75,0,0}
\definecolor{rltdarkred}{rgb}{0.5,0,0}
%
\definecolor{rltbrightgreen}{rgb}{0,0.75,0}
\definecolor{rltgreen}{rgb}{0,0.5,0}
\definecolor{rltdarkgreen}{rgb}{0,0,0.25}
%
\definecolor{rltbrightblue}{rgb}{0,0,1}
\definecolor{rltblue}{rgb}{0,0,0.75}
\definecolor{rltdarkblue}{rgb}{0,0,0.5}

\definecolor{webred}{rgb}{0.5,.25,0}
\definecolor{webblue}{rgb}{0,0,0.75}
\definecolor{webgreen}{rgb}{0,0.5,0}


\usepackage{fancyheadings}
%\setlength{\parskip}{2ex}
%\setlength{\parindent}{2em}
\hoffset=-55pt
\voffset=-60pt
\textheight=9in
\textwidth=6.5in
\parindent=2em
\parskip=10pt
\pagestyle{fancy}
\lhead{\bfseries EE 308}
\chead{\bfseries }
\rhead{\bfseries Spring 2009}
\lfoot{\bfseries }
\cfoot{\thepage}
\rfoot{\bfseries }
\setlength{\headrulewidth}{0.5pt}

\begin{document}\label{start}


\begin{large}

\begin{center}
{\bf The MC9S12 Input Capture Function}
\end{center}

\begin{itemize}
\item The MC9S12 allows you to capture the time an external event occurs on any
of the eight Port T {\tt PTT} pins
\item An external event is either a rising edge or a falling edge
\item To use the Input Capture Function:
\begin{itemize}
\item Enable the timer subsystem (set {\tt TEN} bit of {\tt TSCR1})
\item Set the prescaler
\item Tell the MC9S12 that you want to use a particular pin of {\tt
PTT} for input capture
\item Tell the MC9S12 which edge (rising, falling, or either) you
want to capture
\item Tell the MC9S12 if you want an interrupt to be generated when
the cature occurs
\end{itemize}
\end{itemize}

\newpage

\landscape

\begin{center}
{\bf A Simplified Block Diagram of the MC9S12 Input Capture Subsystem}
\end{center}
\begin{itemize}
\item There are eight timer channels.  Any channel can be used for Input
Capture
\end{itemize}

\includegraphics[width=9in]{input_capture}

\endlandscape

\newpage
\begin{center}
{\bf Registers used to enable Input Capture Function}
\end{center}

\includegraphics[width=6in]{ic_regs_0}

\includegraphics[width=6in]{ic_regs_1}

\includegraphics[width=6in]{ic_regs_2}

\newpage

\begin{center}
{\bf USING INPUT CAPTURE ON THE MC9S12}\\
\end{center}

Input Capture:  Connect a digital signal to a pin of Port T.  Can capture the
time of an edge (rising, falling or either) -- the edge will latch the value
of TCNT into TCx register.  This is used to measure the difference between two
times.

To use Port T Pin x as an input capture pin:
\begin{enumerate}
\item Turn on timer subsystem (1 \verb+->+ Bit 7 of TSCR1 reg)
\item Set prescaler (TSCR2 reg). To get most accuracy set overflow rate as
small as possible, but larger than the maximum time difference you need to
measure.
\item Set up PTx as IC (0 \verb+->+ bit x of TIOS reg)
\item Set edge to capture (EDGxB EDGxA of TCTL 3-4 regs)

\begin{tabular}{||c|c|l||}\hline \hline
EDGxB & EDGxA & \\ \hline \hline
0 & 0 & Disabled \\ \hline
0 & 1 & Rising Edge \\ \hline
1 & 0 & Falling Edge \\ \hline
1 & 1 & Either Edge \\ \hline
\end{tabular}

\item Clear flag (1 \verb+->+ bit x of TFLG1 reg, 0 \verb+->+ all other bits of TFLG1)
\item If using interrupts
\begin{enumerate}
\item Enable interrupt on channel x (1 \verb+->+ bit x of TIE reg)
\item Clear I bit of CCR ({\tt cli} or {\tt enable()})
\item In interrupt service routine, 
\begin{enumerate}
\item Read time of edge from TCx 
\item Clear flag (1 \verb+->+ bit x of TFLG1 reg, 0 \verb+->+ all other bits of TFLG1)
\end{enumerate}
\end{enumerate}
\item If polling in main program
\begin{enumerate}
\item Wait for Bit x of TFLG1 to become set
\item Read time of edge from TCx
\item Clear flag (1 \verb+->+ bit x of TFLG1 reg, 0 \verb+->+ all other bits of TFLG1)
\end{enumerate}
\end{enumerate}

\newpage

\begin{verbatim}
 
/* Program to determine the time between two rising edges using the *
 * MC9S12 Input Capture subsystem
 */

#include "hcs12.h"
#include "DBug12.h"

unsigned int first, second, time;

main()
{
    TSCR1 = BIT7;                /* Turn on timer subsystem */
    TSCR2 = 0x05;                /* Set prescaler for divide by 32 */
                                 /* 87.38 ms overflow time */

    /* Setup for IC1 */
    TIOS = TIOS & ~BIT1;             /* IOC1 set for Input Capture */
    TCTL4 = (TCTL4 | BIT2) & ~BIT3;  /* Capture Rising Edge */
    TFLG1 = BIT1;                    /* Clear IC1 Flag */

    /* Setup for IC2 */
    TIOS = TIOS & ~BIT2;             /* IOC2 set for Input Capture */
    TCTL4 = (TCTL4 | BIT4) & ~BIT5;  /* Capture Rising Edge */
    TFLG1 = BIT2;                    /* Clear IC2 Flag */

    while ((TFLG1 & BIT1) == 0) ;  /* Wait for 1st rising edge; */
    first = TC1;                   /* Read time of 1st edge;    */

    while ((TFLG1 & BIT2) == 0) ;  /* Wait for 2nd rising edge; */
    second = TC2;                  /* Read time of 2nd edge;    */

    time = second - first;         /* Calculate total time */
    DB12FNP->printf("time = %d cycles\n",time);
    asm(" swi");
}
\end{verbatim}

\newpage

\begin{center}
{\bf Using D-Bug12 Routines to Print Information to the Terminal}\\
\end{center}

D-Bug12 has several built-in C routines.  Descriptions of these can be found
in \href{http://www.ee.nmt.edu/~rison/datasheets/ee308/DB12RG4.pdf}{D-BUG12
V4.x.x Reference Guide}.  To use these routines you need to include the header
file {\tt DBug12.h}.  These work like oridnary C functions, but you call them
with pointers to the routines in D-Bug12.  For example, you would call the
{\tt putchar()} function with the following line of C code:

\begin{verbatim}
    DB12FNP->putchar(c);
\end{verbatim}

Here is a C program to print {\tt Hello, world!} to the terminal:

\begin{verbatim}
#include "DBug12.h"

void main(void)
{
    DB12FNP->printf("Hello, world!\n\r");
}
\end{verbatim}

%\newpage

Here is a program to print a number to the terminal in three different
forms:

\begin{verbatim}
#include "DBug12.h"

void main(void)
{
    unsigned int i;

    i = 0xf000;
    
    DB12FNP->printf("Hex:  0x%04x, Unsigned:  %u, Signed:  %d\n\r",i,i,i);
}
\end{verbatim}

The output of the above program will be:

\begin{verbatim}
  Hex:  0xf000,  Unsigned:  61440, Signed:  -4096       
\end{verbatim}

\begin{itemize}
\item {\bf DO NOT USE \verb+DB12FNP->printf+ INSIDE AN INTERRUPT SERVICE
ROUTINE}
\item \verb+DB12FNP->printf+ takes a long time to complete, so you may miss
other interrupts while the function executes
\item Set a flag in the interrupt service routine to tell the main program
that an interrupt has been received, and print the data out in the main
program
\end{itemize}

\newpage

\begin{center}
{\bf Program to measure the time between two rising edges, and print out the
result}
\end{center}


\begin{verbatim}

/* Program to determine the time between two rising edges using
 * the MC9S12 Input Capture subsystem.  
 *
 * The first edge occurs on Bit 1 of PTT
 * The second edge occurs on Bit 2 of PTT
 *
 * This program uses interrupts to determine when the two edges
 * have occurred.
 */

#include "hcs12.h"
#include "DBug12.h"
#include "vectors12.h"

#define enable() asm(" cli")
#define disable() asm(" sei")

#define TRUE  1
#define FALSE 0

/* Function Prototypes */
void INTERRUPT tic1_isr(void);
void INTERRUPT tic2_isr(void);

/* Declare things changed inside ISRs as volatile */
volatile unsigned int first, second, time, done;

main()
{
    disable();
    done = FALSE;

    /* Turn on timer subsystem */
    TSCR1 = BIT7;
    /* Set prescaler to 32 (87.38 ms), no TOF interrupt */
    TSCR2 = 0x05;
\end{verbatim}

\newpage

\begin{verbatim}
    /* Setup for IC1 */
    TIOS = TIOS & ~BIT1;             /* Configure PT1 as IC */
    TCTL4 = (TCTL4 | BIT2) & ~BIT3;  /* Capture Rising Edge */
    TFLG1 = BIT1;                    /* Clear IC1 Flag */
    /* Set interrupt vector for Timer Channel 1 */
    UserTimerCh1 = (short) &tic1_isr;
    TIE = TIE | BIT1;            /* Enable IC1 Interrupt */

    /* Setup for IC2 */
    TIOS = TIOS & ~BIT2;             /* Configure PT2 as IC */
    TCTL4 = (TCTL4 | BIT4) & ~BIT5;  /* Capture Rising Edge */
    TFLG1 = BIT2;                    /* Clear IC2 Flag */
    /* Set interrupt vector for Timer Channel 2 */
    UserTimerCh2 = (short) &tic2_isr;
    TIE = TIE | BIT2;            /* Enable IC2 Interrupt */
 
    /* Enable interrupts by clearing I bit of CCR */
    enable();

    while (!done) 
    {
       asm(" wai");  /* Low power mode while waiting */
    }

    time = second - first;         /* Calculate total time */

    DB12FNP->printf("time = %d cycles\r\n",time)  /* print */;
}

void INTERRUPT tic1_isr(void)
{
    first = TC1;
    TFLG1 = BIT1;
}

void INTERRUPT tic2_isr(void)
{
    second = TC2;
    done = TRUE;
    TFLG1 = BIT2;
}
\end{verbatim}

\newpage

\landscape

\includegraphics[width=9in]{tof_ic}

\endlandscape

\newpage


\begin{center}
{\bf The MC9S12 Output Compare Function}\\[0.5in];
\end{center}

\includegraphics[width=6in]{oc1}

\newpage

\includegraphics[width=6in]{oc2}

\newpage

\landscape

\includegraphics[width=9in]{oc3}

\newpage

\includegraphics[width=9in]{output_compare}

\endlandscape

\newpage

\begin{center}
{\bf The MC9S12 Output Compare Function}
\end{center}

\begin{itemize}
\item The MC9S12 allows you to force an event to happen on any 
of the eight {\tt PTT} pins
\item An external event is a rising edge, a falling edge, or a toggle
\item To use the Output Compare Function:
\begin{itemize}
\item Enable the timer subsystem (set {\tt TEN} bit of {\tt TSCR1})
\item Set the prescaler
\item Tell the MC9S12 that you want to use Bit~x of {\tt PTT} for output
compare
\item Tell the MC9S12 what you want to do on Bit~x of {\tt PTT} (generate
rising edge, falling edge, or toggle)
\item Tell the MC9S12 what time you want the event to occur
\item Tell the MC9S12 if you want an interrupt to be generated when
the event is forced to occur
\end{itemize}

\item There are some more complicated features of the output compare subsystem
which are activated using registers {\tt CFORC}, {\tt OC7M}, {\tt OC7D} and
\item Writing a 1 to the corresponding bit of {\tt CFORC} forces an output
compare event to occur, the same as if a successful comparison has taken
place (Section~8.6.5 of Huang).
\item Using {\tt OC7M} and {\tt OC7D} allow Timer Channel 7 to control
multiple output compare functions (Section~8.6.4 of Huang).
\item Using {\tt TTOV} allows you to toggle an output compare pin when {\tt
TCNT} overflows.  This allows you to use the output compare system to generate
pulse width modulated signals.
\item We will not discuss these advanced features in this class.
\end{itemize}

\newpage

\includegraphics[width=6in]{oc_regs_0}

\includegraphics[width=6in]{oc_regs_1}

\includegraphics[width=6in]{oc_regs_2}

\newpage

\begin{center}
{\bf USING OUTPUT COMPARE ON THE MC9S12}\\
\end{center}

\begin{enumerate}
\item In the main program:
\begin{enumerate}
\item Turn on timer subsystem (TSCR1 reg)
\item Set prescaler (TSCR2 reg)
\item Set up PTx as OC (TIOS reg)
\item Set action on compare (TCTL 1-2 regs, OMx OLx bits)
\item Clear Flag (TFLG1 reg)
\item Enable int (TIE reg)
\end{enumerate}
\item In interrupt service routine
\begin{enumerate}
\item Set time for next action to occur (write TCx reg)
\begin{itemize}
\item For periodic events add time to TCx register
\end{itemize}
\item Clear flag (TFLG1 reg)
\end{enumerate}
\end{enumerate}

\newpage

\begin{center}
{\bf Setting and Clearing Bits in the Timer Subsystem} \\[.05in]
\end{center}

\begin{itemize}
\item Registers in the timer subsystem control multiple timer channels.
\begin{itemize}
\item Usually, you want to use ANDS and ORS to change only that channel you
are working on.
\item For example, to make Channel 2 an output compare, and set it to toggle
on compare, do this:

\begin{large}
\begin{verbatim}
    TIOS = TIOS | BIT2;              /* Configure PT2 as Output Compare */
    TCTL2 = (TCTL2 | BIT4) & ~BIT5;  /* Set up PT2 to toggle on compare */
\end{verbatim}
\end{large}

\item Do not do this:

\begin{large}
\begin{verbatim}
    TIOS = BIT2;              /* Configure PT2 as Output Compare */
    TCTL2 = BIT4);            /* Set up PT2 to toggle on compare */
\end{verbatim}
\end{large}

This would set up Channel 2 as an output compare, toggle on successful
compare.  However, it will force all the other channels to input capture --
this may not be what you want to do.
\end{itemize}
\item {\bf \color{Red}{To clear a flag bit, do not use ORs!}}
\begin{itemize}
\item To clear Timer Channel 2 flag, do the following:
\begin{large}
\begin{verbatim}
    TFLG1 = BIT2;
\end{verbatim}
\end{large}

This will clear Timer Channel 2 flag, and leave all other flags unaffected.
\item Do not do this:
\begin{large}
\begin{verbatim}
    TFLG1 = TFLG1 | BIT2;   /* DO NOT DO THIS */
\end{verbatim}
\end{large}

This will clear Timer Channel 2 flag, but will also clear any other flag which
is set.

Suppose, for example, Timer Channel 2 and Timer Channel 3 flags are both set
at the same time, so {\tt TFLG1} register is {\tt 0x0C}.  You want to deal the
Timer Channel 2 first and Timer Channel 3 afterwards.

The command:

\begin{large}
\begin{verbatim}
    TFLG1 = TFLG1 | BIT2;   /* DO NOT DO THIS */
\end{verbatim}
\end{large}

will read TFLG1, which will return an {\tt 0x0C}.  ORing that with a {\tt
0x04} ({\tt{BIT2}}) will result in an {\tt 0x0C}.  Writing that back to {\tt TFLG1} will
clear Timer Channel 2 flag and Timer Channel 3 flag.    Now Timer Channel 3
flag is cleared, so you will never deal with the event which set Timer Channel
3 flag.


\end{itemize}

\end{itemize}

\newpage

\begin{verbatim}
/*
 * Program to generate square wave on PT2
 * Frequency of square wave is 500 Hz
 * Period of square wave is 2 ms
 * Set prescale to give 0.667 us cycle
 * 2 ms is 3,000 cycles of 1.5 MHz clock
 * 
 */
#include "hcs12.h"
#include "vectors12.h"

#define PERIOD      3000
#define HALF_PERIOD (PERIOD/2)

#define disable()  asm(" sei")
#define enable()  asm(" cli")

void INTERRUPT toc2_isr(void);

main()
{
    disable();

    TSCR1 = BIT7;                     /* Turn on timer subsystem */
    TSCR2 = 0x04;                     /* Set prescaler to 16 (0.666 us) */

    TIOS = TIOS | BIT2;              /* Configure PT2 as Output Compare */
    TCTL2 = (TCTL2 | BIT4) & ~BIT5;  /* Set up PT2 to toggle on compare */
    TFLG1 = BIT2;                    /* Clear Channel 2 flag */
    /* Set interrupt vector for Timer Channel 2 */
    UserTimerCh2 = (unsigned short) &toc2_isr;
    TIE = TIE | BIT2;                /* Enable interrupt on Channel 2 */

    enable();

    while (1) 
    {
        asm("wai");
    }
}

void INTERRUPT toc2_isr(void)
{
    TC2 = TC2 + HALF_PERIOD;
    TFLG1 = BIT2;
}
\end{verbatim}


\end{large}

\label{end}
\end{document}
