simulavr-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Simulavr-devel] ADC Patch


From: Keith Gudger
Subject: [Simulavr-devel] ADC Patch
Date: Thu, 13 Nov 2003 12:08:33 -0800 (PST)

Ted:

Attached are the files needed to patch in the ADC.  The adc.diff file
covers the changes to the devsupp.c file.  Note that the atmega103 is the
only non-USB part in the list with an ADC.  Also note that since the USB
parts have slightly different I/O addresses, the fact that a part supports
USB needs to get passed to the adc device creations.  That is why the
usb.h file is attached.

Keith
? simulavr/devsupp.diff
? simulavr/src_old
? simulavr/src/config.h
? simulavr/src/sa_kg3.zip
Index: simulavr/src/devsupp.c
===================================================================
RCS file: /cvsroot/simulavr/simulavr/src/devsupp.c,v
retrieving revision 1.17
diff -u -r1.17 devsupp.c
--- simulavr/src/devsupp.c      13 Nov 2003 07:34:24 -0000      1.17
+++ simulavr/src/devsupp.c      13 Nov 2003 19:48:07 -0000
@@ -57,6 +57,8 @@
 #include "eeprom.h"
 #include "timers.h"
 #include "ports.h"
+#include "adc.h"
+#include "usb.h"
 
 #include "avrcore.h"
 
@@ -113,6 +115,8 @@
         uint8_t  acsr;
         uint8_t  wdtcr;
         uint8_t  timsk;
+        uint8_t  adcsr;
+        uint8_t  uier;
     } mask;
 };
 
@@ -142,7 +146,9 @@
   /* mask.mcucr   */  (mask_SE | mask_SM | mask_ISC01 | mask_ISC00),
   /* mask.acsr    */  (mask_ACD | mask_ACO | mask_ACI | mask_ACIE | mask_ACIS1 
| mask_ACIS0),
   /* mask.wdtcr   */  (mask_WDE | mask_WDP2 | mask_WDP1 | mask_WDP0),
-  /* mask.timsk   */  (mask_TOIE0)
+  /* mask.timsk   */  (mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  0
   }
 };
 
@@ -169,7 +175,9 @@
   /* mask.acsr    */  (mask_ACD | mask_ACO | mask_ACI | mask_ACIE | 
                        mask_ACIC | mask_ACIS1 | mask_ACIS0),
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1 | 
mask_WDP0),
-  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_TICIE1 | mask_TOIE0)
+  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_TICIE1 | mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  0
   }
 };
 
@@ -196,7 +204,9 @@
   /* mask.acsr    */  (mask_ACD | mask_ACO | mask_ACI | mask_ACIE | 
                        mask_ACIC | mask_ACIS1 | mask_ACIS0),
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1 | 
mask_WDP0),
-  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0)
+  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  0
   }
 };
 
@@ -223,7 +233,9 @@
   /* mask.acsr    */  (mask_ACD | mask_ACO | mask_ACI | mask_ACIE | 
                        mask_ACIC | mask_ACIS1 | mask_ACIS0),
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1 | 
mask_WDP0),
-  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0)
+  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  0
   }
 };
 
@@ -249,7 +261,9 @@
   /* mask.acsr    */  (mask_ACD | mask_ACO | mask_ACI | mask_ACIE |
                        mask_ACIC | mask_ACIS1 | mask_ACIS0),
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1 | 
mask_WDP0),
-  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0)
+  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  0
   }
 };
 
@@ -276,7 +290,9 @@
   /* mask.acsr    */  (mask_ACD | mask_ACO | mask_ACI | mask_ACIE |
                        mask_ACIC | mask_ACIS1 | mask_ACIS0),
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1 | 
mask_WDP0),
-  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0)
+  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  0
   }
 };
 
@@ -303,7 +319,9 @@
   /* mask.acsr    */  (mask_ACD | mask_ACO | mask_ACI | mask_ACIE | 
                        mask_ACIC | mask_ACIS1 | mask_ACIS0),
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1 | 
mask_WDP0),
-  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0)
+  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0),
+  /* mask.adcsr   */  (mask_ADEN),
+  /* mask.uier    */  0
   }
 };
 
@@ -330,7 +348,9 @@
   /* mask.acsr    */  (mask_ACD | mask_ACO | mask_ACI | mask_ACIE | 
                        mask_ACIC | mask_ACIS1 | mask_ACIS0),
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1 | 
mask_WDP0),
-  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0)
+  /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1 | 
mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  0
   }
 };
 
@@ -357,7 +377,9 @@
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1
                        | mask_WDP0),
   /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1
-                       | mask_TOIE0)
+                       | mask_TOIE0),
+  /* mask.adcsr   */  (mask_ADEN),
+  /* mask.uier    */  (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_FEP3)
   }
 };
 
@@ -384,7 +406,9 @@
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1
                        | mask_WDP0),
   /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1
-                       | mask_TOIE0)
+                       | mask_TOIE0),
+  /* mask.adcsr   */  (mask_ADEN),
+  /* mask.uier    */  (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_FEP3 | 
mask_HEP0)
   }
 };
 
@@ -411,7 +435,9 @@
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1
                        | mask_WDP0),
   /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1
-                       | mask_TOIE0)
+                       | mask_TOIE0),
+  /* mask.adcsr   */  (mask_ADEN),
+  /* mask.uier    */  (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_FEP3 | 
mask_HEP0)
   }
 };
 
@@ -438,7 +464,9 @@
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1
                        | mask_WDP0),
   /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1
-                       | mask_TOIE0)
+                       | mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_FEP3 | 
mask_HEP0)
   }
 };
 
@@ -465,7 +493,9 @@
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1
                        | mask_WDP0),
   /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1
-                       | mask_TOIE0)
+                       | mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_HEP0)
   }
 };
 
@@ -492,7 +522,9 @@
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1
                        | mask_WDP0),
   /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1
-                       | mask_TOIE0)
+                       | mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_FEP3 | 
mask_HEP0)
   }
 };
 
@@ -519,7 +551,9 @@
   /* mask.wdtcr   */  (mask_WDTOE | mask_WDE | mask_WDP2 | mask_WDP1
                        | mask_WDP0),
   /* mask.timsk   */  (mask_TOIE1 | mask_OCIE1A | mask_OCIE1B | mask_TICIE1
-                       | mask_TOIE0)
+                       | mask_TOIE0),
+  /* mask.adcsr   */  0,
+  /* mask.uier    */  (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_HEP0)
   }
 };
 
@@ -666,7 +700,15 @@
             }
         }
 
-        /* Attach device port vdevs */
+        if (dev->mask.adcsr)
+        {   
+            vdev = (VDevice *)adc_intr_new(dev->mask.uier);
+            avr_core_attach_vdev( core, vdev );
+            vdev = (VDevice *)adc_new(dev->mask.uier);
+            avr_core_attach_vdev( core, vdev );
+        }
+
+       /* Attach device port vdevs */
 
         pp = dev->ports;
         while (*pp)
/*
 * $Id: adc.c,v 1.9 2003/11/07 22:22:34 kgudger Exp $
 *
 ****************************************************************************
 *
 * simulavr - A simulator for the Atmel AVR family of microcontrollers.
 * Copyright (C) 2001, 2002  Theodore A. Roth
 *
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 ****************************************************************************
 */

/**
 * \file adc.c
 * \brief Module to simulate the AVR's ADC module.
 *
 */

#include <config.h>

#include <stdio.h>
#include <stdlib.h>

#include "avrerror.h"
#include "avrmalloc.h"
#include "avrclass.h"
#include "utils.h"
#include "callback.h"
#include "op_names.h"

#include "storage.h"
#include "flash.h"

#include "vdevs.h"
#include "memory.h"
#include "stack.h"
#include "register.h"
#include "sram.h"
#include "eeprom.h"
#include "timers.h"
#include "ports.h"
#include "adc.h"

#include "avrcore.h"

#include "intvects.h"

/******************************************************************************\
 *
 * ADC Interrupts 
 *
\******************************************************************************/
static uint8_t adc_intr_read   ( VDevice *dev, int addr );
static void  adc_intr_write    ( VDevice *dev, int addr, uint8_t val );
static void  adc_intr_reset    ( VDevice *dev );
static char *adc_intr_reg_name ( VDevice *dev , int addr );
static int adc_intr_cb( uint64_t time, AvrClass *data ) ;
static int     adc_clk_incr_cb( uint64_t ck, AvrClass *data );

/** \brief Allocate a new ADC interrupt */

ADCIntr_T *adc_intr_new( uint8_t uier )
{
    ADCIntr_T *adc;

    adc = avr_new( ADCIntr_T, 1 );
    adc_intr_construct( adc, uier );
    class_overload_destroy( (AvrClass *)adc, adc_intr_destroy );

    return adc;
}

/** \brief Constructor for adc interrupt object. */

void adc_intr_construct( ADCIntr_T *adc, uint8_t uier )
{
    char *name = "ADCIntr";

    if (adc == NULL)
        avr_error( "passed null ptr" );

    if ( uier )
        vdev_construct( (VDevice *)adc, name, ADC_INTR_BASE_U, ADC_INTR_SIZE,
                    adc_intr_read, adc_intr_write, adc_intr_reset, 
adc_intr_reg_name );
    else
        vdev_construct( (VDevice *)adc, name, ADC_INTR_BASE_A, ADC_INTR_SIZE,
                    adc_intr_read, adc_intr_write, adc_intr_reset, 
adc_intr_reg_name );

    adc_intr_reset( (VDevice*)adc );
}

/** \brief Destructor for adc interrupt object. */

void adc_intr_destroy( void *adc )
{
    if (adc == NULL)
        return;

    vdev_destroy( adc );
}


static uint8_t  adc_intr_read( VDevice *dev, int addr )
{
    ADCIntr_T *adc = (ADCIntr_T *)dev;

    switch ( addr - vdev_get_base(dev) ) {
        case ADC_INTR_ADCSR_ADDR   : return (adc->adcsr );
        case ADC_INTR_ADMUX_ADDR   : return (adc->admux );
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return 0;                   /* will never get here */
}


static void  adc_intr_write( VDevice *dev, int addr, uint8_t val )
{
    ADCIntr_T *adc     = (ADCIntr_T *)dev;
    CallBack  *cb;
    ADC_T     *adc_d;

    adc_d = (ADC_T *)avr_core_get_vdev_by_name( (AvrCore 
*)vdev_get_core((VDevice *)adc),
                                                   "ADC" );

    switch ( addr - vdev_get_base(dev) ) {
        case ADC_INTR_ADCSR_ADDR   : 
            if ( val & mask_ADIF )  /* clears interrupt flag */
                adc->adcsr = val & ~mask_ADIF ;
            else
                adc->adcsr = val ;

            if ( ( val & mask_ADSC ) && ( val & mask_ADEN ) )
            {
                if ( ( adc->intr_cb == NULL ) )
                {
                    /* we need to install the intr_cb function */
                    cb = callback_new( adc_intr_cb, (AvrClass *)adc );
                    adc->intr_cb = cb;
                    avr_core_async_cb_add( (AvrCore *)vdev_get_core(dev), cb );
                }
                if ( ( adc_d->clk_cb == NULL ) )
                {
                    /* we need to install the clk_cb function */
                    cb = callback_new( adc_clk_incr_cb, (AvrClass *)adc_d );
                    adc_d->clk_cb = cb;
                    avr_core_clk_cb_add( (AvrCore *)vdev_get_core(dev), cb );
                }
                adc_d->adc_count = 13 ;
                switch ( (adc->adcsr) & (mask_ADPS0 | mask_ADPS1 | mask_ADPS2) 
) {
                    case ADC_CK_0:
                    case ADC_CK_2:
                        adc_d->divisor = 2;
                        break;
                    case ADC_CK_4:
                        adc_d->divisor = 4;
                        break;
                    case ADC_CK_8:
                        adc_d->divisor = 8;
                        break;
                    case ADC_CK_16:
                        adc_d->divisor = 16;
                        break;
                    case ADC_CK_32:
                        adc_d->divisor = 32;
                        break;
                    case ADC_CK_64:
                        adc_d->divisor = 64;
                        break;
                    case ADC_CK_128:
                        adc_d->divisor = 128;
                        break;
                    default:
                        avr_error( "The impossible happened!" );
                }
            }
            else
            {
                adc->intr_cb = NULL; /* no interrupt are enabled, remove the 
callback */
            }
            break;
        case ADC_INTR_ADMUX_ADDR   : adc->admux = val ; break ;
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
}

static void  adc_intr_reset( VDevice *dev )
{
    ADCIntr_T *adc = (ADCIntr_T *)dev;

    adc->intr_cb = NULL;

    adc->adcsr = 0;
        adc->admux = 0 ;
}

static char *adc_intr_reg_name( VDevice *dev , int addr )
{
    switch ( addr - vdev_get_base(dev) ) {
        case ADC_INTR_ADCSR_ADDR   : return ("ADSCR" );
        case ADC_INTR_ADMUX_ADDR   : return ("ADMUX" );
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return NULL;                /* will never get here */
}

static int adc_intr_cb( uint64_t time, AvrClass *data )
{
    ADCIntr_T *adc = (ADCIntr_T *)data;

    if ( adc->intr_cb == NULL )
        return CB_RET_REMOVE;

    if ( ( adc->adcsr & mask_ADEN ) && ( adc->adcsr & mask_ADIE ) && 
              ( adc->adcsr & mask_ADIF ))  /* an enabled interrupt occured */
    {
        AvrCore *core = (AvrCore *)vdev_get_core((VDevice *)adc);
        avr_core_irq_raise( core, irq_vect_table_index(ADC) );
        adc->adcsr &= ~mask_ADIF;
    }

    return CB_RET_RETAIN;
}

/******************************************************************************\
 *
 * ADC  
 *
\******************************************************************************/

static uint8_t  adc_read     ( VDevice *dev, int addr );
static void    adc_write    ( VDevice *dev, int addr, uint8_t val );
static void    adc_reset    ( VDevice *dev );
static char   *adc_reg_name ( VDevice *dev , int addr );

/** \brief Allocate a new ADC structure. */

ADC_T *adc_new( uint8_t uier )
{
    ADC_T *adc;

    adc = avr_new( ADC_T, 1 );
    adc_construct( adc, uier );
    class_overload_destroy( (AvrClass *)adc, adc_destroy );

    return adc;
}

/** \brief Constructor for ADC object. */

void adc_construct( ADC_T *adc, uint8_t uier )
{
    char *name = "ADC";

    if (adc == NULL)
        avr_error( "passed null ptr" );

    if ( uier )
        vdev_construct( (VDevice *)adc, name, ADC_BASE_U, ADC_SIZE,
                        adc_read, adc_write, adc_reset, adc_reg_name );
    else
        vdev_construct( (VDevice *)adc, name, ADC_BASE_A, ADC_SIZE,
                        adc_read, adc_write, adc_reset, adc_reg_name );

    adc_reset( (VDevice*)adc );
        adc->u_divisor = uier ? 12 : 1 ;
}

/** \brief Destructor for ADC object. */

void adc_destroy( void *adc )
{
    if (adc == NULL)
        return;

    vdev_destroy( adc );
}

static uint8_t adc_read( VDevice *dev, int addr )
{
    ADC_T *adc = (ADC_T *)dev;

    switch ( addr - vdev_get_base(dev) ) {
        case ADC_ADCL_ADDR: return adc->adcl;
        case ADC_ADCH_ADDR: return adc->adch;
         default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return 0;                   /* will never get here */
}

static void adc_write( VDevice *dev, int addr, uint8_t val )
{
    avr_error( "Bad ADC write address: 0x%04x", addr );
}

static void adc_reset( VDevice *dev )
{
    ADC_T *adc = (ADC_T *)dev;

    adc->clk_cb = NULL;

    adc->adcl = 0;
    adc->adch = 0;
    adc->adc_count = 0 ;
        adc->adc_in = 0 ;
    adc->divisor = 0;
}

static char *adc_reg_name( VDevice *dev , int addr )
{
    switch ( addr - vdev_get_base(dev) ) {
        case ADC_ADCL_ADDR: return "ADCL" ;
        case ADC_ADCH_ADDR: return "ADCH" ;
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return NULL;
}


static int adc_clk_incr_cb( uint64_t ck, AvrClass *data )
{
    ADC_T    *adc = (ADC_T *)data;
    uint8_t   last  = adc->adc_count;
    ADCIntr_T *adc_ti;
    
    adc_ti = (ADCIntr_T *)avr_core_get_vdev_by_name( (AvrCore 
*)vdev_get_core((VDevice *)adc),
                                                   "ADCIntr" );

    if (adc->clk_cb == NULL)
        return CB_RET_REMOVE;

    if (adc->divisor <= 0)
        avr_error( "Bad divisor value: %d", adc->divisor );

    /* decrement clock if ck is a multiple of divisor */
    adc->adc_count -= ((ck % (adc->divisor * adc->u_divisor)) == 0);
    
    /* */
    if (adc->adc_count != last)  /* we've changed the counter */
    {
        if ( adc->adc_count == 0 )
        {
            adc_ti->adcsr |= mask_ADIF;    
            adc_ti->adcsr &= ~mask_ADSC;
            adc->adc_in = adc_port_rd( adc_ti->admux ) ;
            adc->adcl = (adc->adc_in)      & 0xff ;    /* update adcl to what 
we read */
            adc->adch = ((adc->adc_in)>>8) & 0x03 ;    /* update adch */
            if ( adc_ti->adcsr & mask_ADFR )      /* free running mode */
                adc->adc_count = 13 ;
            else
            {
                adc->clk_cb = NULL; 
                return CB_RET_REMOVE;
            }
        }
    }
    return CB_RET_RETAIN;
}

uint16_t adc_port_rd( uint8_t mux )
{
    int   data;
    char  line[80];

    while (1)
    {
        fprintf( stderr, "\nEnter data to read into the ADC for channel %d: ",
                 mux);

        /* try to read in a line of input */
        if ( fgets(line, sizeof(line), stdin) == NULL)
            continue;
        
        /* try to parse the line for a byte of data */
        if ( sscanf(line, "%d\n", &data) != 1 )
            continue;

        break;
    }
    return (uint16_t)(data & 0x3ff);
}

void adc_port_wr( uint8_t val )
{
    fprintf( stderr, "wrote 0x%02x to ADC\n", val );
}

/*
 * $Id: adc.h,v 1.3 2003/11/07 20:58:28 kgudger Exp $
 *
 ****************************************************************************
 *
 * simulavr - A simulator for the Atmel AVR family of microcontrollers.
 * Copyright (C) 2001, 2002  Theodore A. Roth
 *
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 ****************************************************************************
 */

#ifndef ADC_H
#define ADC_H

/****************************************************************************\
 *
 * ADCInter_T(VDevice) : ADC Interrupt and Control Register
 *
 \****************************************************************************/

enum _adc_intr_constants {
    ADC_INTR_BASE_A = 0x26,     /* base address for vdev */
    ADC_INTR_BASE_U = 0x27,     /* base address for vdev */
    ADC_INTR_SIZE = 2,        /* SPCR, SPSR */

    ADC_INTR_ADCSR_ADDR = 0,
    ADC_INTR_ADMUX_ADDR = 1,
};

typedef enum {
    bit_ADPS0  = 0,             /* Clock Rate Select 0   */
    bit_ADPS1  = 1,             /* Clock Rate Select 1   */
    bit_ADPS2  = 2,             /* Clock Rate Select 1   */
    bit_ADIE   = 3,             /* ADC Interrupt Enable  */
    bit_ADIF   = 4,             /* ADC Interrupt Flag    */
    bit_ADFR   = 5,             /* Free Run Select       */
    bit_ADSC   = 6,             /* ADC Start Conversion  */
    bit_ADEN   = 7,             /* ADC Enable            */
} ADCSR_BITS;

typedef enum {
    mask_ADPS0   = 1 << bit_ADPS0,
        mask_ADPS1   = 1 << bit_ADPS1,
    mask_ADPS2   = 1 << bit_ADPS2,
    mask_ADIE    = 1 << bit_ADIE,
    mask_ADIF    = 1 << bit_ADIF,
    mask_ADFR    = 1 << bit_ADFR,
    mask_ADSC    = 1 << bit_ADSC,
    mask_ADEN    = 1 << bit_ADEN,
} ADCSR_MASKS;

typedef enum {
    bit_MUX0   = 0,             /* MUX Channel Select Bit */
    bit_MUX1   = 1,             /* MUX Channel Select Bit */
    bit_MUX2   = 2,             /* MUX Channel Select Bit */
    bit_MUX3   = 3,             /* MUX Channel Select Bit */
} ADMUX_BITS;

typedef enum {
    mask_MUX0   = 1 << bit_MUX0,
    mask_MUX1   = 1 << bit_MUX1,
    mask_MUX2   = 1 << bit_MUX2,
    mask_MUX3   = 1 << bit_MUX3,
} ADMUX_MASKS;

typedef struct _ADCIntr_T ADCIntr_T;

struct _ADCIntr_T {
    VDevice   parent;
    uint8_t   adcsr;             /* ADC Interrupt control and status register */
    uint8_t   admux;             /* ADC Multiplexer Select register */
    CallBack *intr_cb;          /* callback for checking and raising interrupts 
*/
};

extern ADCIntr_T *adc_intr_new       ( uint8_t uier );
extern void      adc_intr_construct ( ADCIntr_T *ti, uint8_t uier );
extern void      adc_intr_destroy   ( void *ti );

/****************************************************************************\
 *
 * General ADC bits and masks.
 *
\****************************************************************************/

enum _adc_cs_constants {
    ADC_CK_0       = 0x00,      /* CK/2                               */
    ADC_CK_2       = 0x01,      /* CK/2                               */
    ADC_CK_4       = 0x02,      /* CK/4                               */
    ADC_CK_8       = 0x03,      /* CK/8                               */
    ADC_CK_16      = 0x04,      /* CK/16                              */
    ADC_CK_32      = 0x05,      /* CK/32                              */
    ADC_CK_64      = 0x06,      /* CK/64                              */
    ADC_CK_128     = 0x07,      /* CK/128                             */
};

/****************************************************************************\
 *
 * ADC(VDevice) : ADC
 *
\****************************************************************************/

enum _adc_constants {
    ADC_BASE_A  = 0x24,         /* base memory address */
    ADC_BASE_U  = 0x22,         /* base memory address */
    ADC_SIZE    = 2,            /* ADC Data Register Size = 2 bytes */

    ADC_ADCL_ADDR = 0,          /* offset from base to ADCL Register */
    ADC_ADCH_ADDR = 1,          /* offset from base to ADCH Register */
};

typedef struct _ADC ADC_T;

struct _ADC {
    VDevice   parent;
    uint8_t   adcl;             /* data  register */
    uint8_t   adch;             /* data  register */
    uint16_t  adc_count;        /* 16 bit count register */
    uint16_t  adc_in;          /* new data  register */
    uint16_t  divisor;          /* clock divisor */
    uint8_t   u_divisor;        /* extra usb clock divisor */
    CallBack *clk_cb;           /* incr timer tied to clock */
};

extern ADC_T *adc_new       ( uint8_t uier );
extern void   adc_construct ( ADC_T *adc, uint8_t uier );
extern void   adc_destroy   ( void *adc );
extern void   adc_intr_set_flag   ( ADCIntr_T *ti );
extern void   adc_intr_clear_flag ( ADCIntr_T *ti );
extern uint16_t adc_port_rd( uint8_t mux ) ;
extern void   adc_port_wr( uint8_t val );

#endif
/*
 * $Id: usb.h,v 1.3 2003/10/28 20:58:28 kgudger Exp $
 *
 ****************************************************************************
 *
 * simulavr - A simulator for the Atmel AVR family of microcontrollers.
 * Copyright (C) 2001, 2002  Theodore A. Roth
 *
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 ****************************************************************************
 */

#ifndef USB_H
#define USB_H

/****************************************************************************\
 *
 * USBInter_T(VDevice) : USB Interrupt Mask/Flag/Enable Registers
 *
 \****************************************************************************/

enum _usb_intr_constants {
    USB_INTR_BASE = 0x1ff3,   /* base address for vdev */
    USB_INTR_SIZE = 11,       /* UIER, unused, UIAR, UIMSK*/

    USB_INTR_ENABLE_ADDR  = 0,
    USB_INTR_UNUSED_ADDR  = 1,
    USB_INTR_ACK_ADDR     = 2,
    USB_INTR_MASK_ADDR    = 3,
    USB_INTR_STATUS_ADDR  = 4,
    USB_INTR_SPRSMSK_ADDR = 5,
    USB_INTR_SPRSIE_ADDR  = 6,
    USB_INTR_SPRSR_ADDR   = 7,
    USB_GLB_STATE_ADDR    = 8,
    USB_FRM_NUM_L_ADDR    = 9,
    USB_FRM_NUM_H_ADDR    = 10,
};

typedef enum {
    bit_FEP0  = 0,             /* Function Endpoint 0 interrupt enable */
    bit_FEP1  = 1,             /* Function Endpoint 1 interrupt enable */
    bit_FEP2  = 2,             /* Function Endpoint 2 interrupt enable */
    bit_HEP0  = 3,             /* Hub      Endpoint 0 interrupt enable */
    bit_FEP3  = 4,             /* Function Endpoint 3 interrupt enable */
} USBMSK_BITS;

typedef enum {
    mask_FEP0  = 1 << bit_FEP0,
    mask_FEP1 = 1 << bit_FEP1,
    mask_FEP2 = 1 << bit_FEP2,
    mask_HEP0 = 1 << bit_HEP0,
    mask_FEP3  = 1 << bit_FEP3,
} USB_MASKS;

typedef enum {
    bit_TX_COMPLETE      = 0,       
    bit_RX_OUT_PACKET    = 1,
    bit_RX_SETUP         = 2,
    bit_STALL_SENT       = 3,
    bit_TX_PACKET_READY  = 4, 
    bit_FORCE_STALL      = 5, 
    bit_DATA_END         = 6, 
    bit_DATA_DIR         = 7, 
} USBCSR_BITS;

typedef enum {
    bit_TX_COMPLETE_ACK      = 0,       
    bit_RX_OUT_PACKET_ACK    = 1,
    bit_RX_SETUP_ACK         = 2,
    bit_STALL_SENT_ACK       = 3,
} USBCAR_BITS;

typedef enum {
    TX_COMPLETE      = 1 << bit_TX_COMPLETE,
    RX_OUT_PACKET    = 1 << bit_RX_OUT_PACKET,
    RX_SETUP         = 1 << bit_RX_SETUP,
    STALL_SENT       = 1 << bit_STALL_SENT,
    TX_PACKET_READY  = 1 << bit_TX_PACKET_READY,
    FORCE_STALL      = 1 << bit_FORCE_STALL,
    DATA_END         = 1 << bit_DATA_END,
    DATA_DIR         = 1 << bit_DATA_DIR,
} USBCSR_MASKS;

typedef struct _USBInter_T USBInter_T;

struct _USBInter_T {
    VDevice   parent;
    uint8_t   uier;             /* USB interrupt enable (mask) register */
    uint8_t   uiar;             /* USB interrupt ack  register */
    uint8_t   uimsk;            /* USB interrupt mask register */
    uint8_t   uisr;             /* USB interrupt flag register */
    uint8_t   func_mask;        /* mask of available register functions */
    uint8_t   sprsmsk;
    uint8_t   sprsie;
    uint8_t   sprsr;
    uint8_t   glb_state;
    uint8_t   frm_num_l;
    uint8_t   frm_num_h;
    CallBack *intr_cb;          /* callback for checking and raising interrupts 
*/
};

extern USBInter_T *usb_intr_new       ( uint8_t func_mask );
extern void        usb_intr_construct ( USBInter_T *usb, uint8_t func_mask );
extern void        usb_intr_destroy   ( void *usb );

/****************************************************************************\
 *
 * USB(VDevice) : USB Structure
 *
\****************************************************************************/

enum _usb_constants {
    USB_BASE = 0x1fa0,         /* base memory address */
    USB_SIZE = 83,            /* TCCR0 and TCNT0 */

    USB_FCAR5_ADDR = 0,       /* offset from base to FCAR Register */
    USB_FCAR4_ADDR = 1,
    USB_FCAR3_ADDR = 2,       
    USB_FCAR2_ADDR = 3,
    USB_FCAR1_ADDR = 4,
    USB_FCAR0_ADDR = 5,
    USB_HCAR0_ADDR = 7,
        USB_PSTATE1_ADDR = 8,
        USB_PSTATE2_ADDR = 9,
        USB_PSTATE3_ADDR = 0x0a,
        USB_PSTATE4_ADDR = 0x0b,
        USB_PSTATE5_ADDR = 0x0c,
        USB_PSTATE6_ADDR = 0x0d,
        USB_PSTATE7_ADDR = 0x0e,
        USB_PSTATE8_ADDR = 0x0f,
        USB_HPSCR1_ADDR  = 0x10,     /* 0x1fb0 */
        USB_HPSCR2_ADDR  = 0x11,
        USB_HPSCR3_ADDR  = 0x12,
        USB_HPSCR4_ADDR  = 0x13,
        USB_HPSCR5_ADDR  = 0x14,
        USB_HPSCR6_ADDR  = 0x15,
        USB_HPSCR7_ADDR  = 0x16,
        USB_HPSCR8_ADDR  = 0x17,
        USB_HPSTAT1_ADDR = 0x18,
        USB_HPSTAT2_ADDR = 0x19,
        USB_HPSTAT3_ADDR = 0x1a,
        USB_HPSTAT4_ADDR = 0x1b,
        USB_HPSTAT5_ADDR = 0x1c,
        USB_HPSTAT6_ADDR = 0x1d,
        USB_HPSTAT7_ADDR = 0x1e,
        USB_HPSTAT8_ADDR = 0x1f,
    USB_HPCON_ADDR   = 0x25,
        USB_HSTR_ADDR    = 0x27,     /* 0X1FC7 */
        USB_FBYTE_CNT5_ADDR = 0x28,
        USB_FBYTE_CNT4_ADDR = 0x29,
        USB_FBYTE_CNT3_ADDR = 0x2a,
        USB_FBYTE_CNT2_ADDR = 0x2b,
        USB_FBYTE_CNT1_ADDR = 0x2c,
        USB_FBYTE_CNT0_ADDR = 0x2d,
        USB_HBYTE_CNT0_ADDR = 0x2f,
        USB_FDR5_ADDR       = 0x30,  /* 0x1fd0 */
        USB_FDR4_ADDR       = 0x31,
        USB_FDR3_ADDR       = 0x32,
        USB_FDR2_ADDR       = 0x33,
        USB_FDR1_ADDR       = 0x34,
        USB_FDR0_ADDR       = 0x35,
        USB_HDR0_ADDR       = 0x37,
        USB_FCSR5_ADDR      = 0x38,
        USB_FCSR4_ADDR      = 0x39,
        USB_FCSR3_ADDR      = 0x3a,
        USB_FCSR2_ADDR      = 0x3b,
        USB_FCSR1_ADDR      = 0x3c,
        USB_FCSR0_ADDR      = 0x3d,
        USB_HCSR0_ADDR      = 0x3f,
        USB_FENDP5_CNTR_ADDR = 0x40, /* 0x1fe0 */
        USB_FENDP4_CNTR_ADDR = 0x41,
        USB_FENDP3_CNTR_ADDR = 0x42,
        USB_FENDP2_CNTR_ADDR = 0x43,
        USB_FENDP1_CNTR_ADDR = 0x44,
        USB_FENDP0_CNTR_ADDR = 0x45,
        USB_HENDP1_CNTR_ADDR = 0x46,
        USB_HENDP0_CNTR_ADDR = 0x47,
        USB_FADDR_ADDR       = 0x4e, /* 0x1fee */
        USB_HADDR_ADDR       = 0x4f,
        USB_ICSR_ADDR        = 0x51, /* 0x1ff1 */
        USB_UOVCER_ADDR      = 0x52, /* 0x1ff2 */
};

typedef struct _USB USB_T;

struct _USB {
    VDevice   parent;
    uint8_t   uovcer;            /* overcurrent register */
    uint8_t   haddr;             /* Hub Address register */
    uint8_t   faddr;             /* Function Address register */
    uint8_t   hstr ;             /* Hub Status register */
    uint8_t   hpcon;             /* Hub Port Control register */
    uint8_t   icsr;              /* interrupt control sense register */
    uint8_t   fendp5_cntr;       /* endpoint 5 control register */
    uint8_t   fendp4_cntr;       /* endpoint 4 control register */
    uint8_t   fendp3_cntr;       /* endpoint 3 control register */
    uint8_t   fendp2_cntr;       /* endpoint 2 control register */
    uint8_t   fendp1_cntr;       /* endpoint 1 control register */
    uint8_t   fendp0_cntr;       /* endpoint 0 control register */
    uint8_t   hendp1_cntr;       /* hub endpoint control register */
    uint8_t   hendp0_cntr;       /* hub endpoint control register */
    uint8_t   fcsr5;             /* endpoint 5 control & status register */
    uint8_t   fcsr4;             /* endpoint 4 control & status register */
    uint8_t   fcsr3;             /* endpoint 3 control & status register */
    uint8_t   fcsr2;             /* endpoint 2 control & status register */
    uint8_t   fcsr1;             /* endpoint 1 control & status register */
    uint8_t   fcsr0;             /* endpoint 0 control & status register */
    uint8_t   hcsr0;             /* hub endpoint control & status register */
    uint8_t   fcar5;             /* endpoint 5 control & ack register */
    uint8_t   fcar4;             /* endpoint 4 control & ack register */
    uint8_t   fcar3;             /* endpoint 3 control & ack register */
    uint8_t   fcar2;             /* endpoint 2 control & ack register */
    uint8_t   fcar1;             /* endpoint 1 control & ack register */
    uint8_t   fcar0;             /* endpoint 0 control & ack register */
    uint8_t   hcar0;             /* hub endpoint control & ack register */
    uint8_t   hpstat1;           /* hub port 1 status register */
    uint8_t   hpstat2;           /* hub port 2 status register */
    uint8_t   hpstat3;           /* hub port 3 status register */
    uint8_t   hpstat4;           /* hub port 4 status register */
    uint8_t   hpstat5;           /* hub port 5 status register */
    uint8_t   hpstat6;           /* hub port 6 status register */
    uint8_t   hpstat7;           /* hub port 7 status register */
    uint8_t   hpstat8;           /* hub port 8 status register */
    uint8_t   pstate1;           /* hub port 1 port state register */
    uint8_t   pstate2;           /* hub port 2 port state register */
    uint8_t   pstate3;           /* hub port 3 port state register */
    uint8_t   pstate4;           /* hub port 4 port state register */
    uint8_t   pstate5;           /* hub port 5 port state register */
    uint8_t   pstate6;           /* hub port 6 port state register */
    uint8_t   pstate7;           /* hub port 7 port state register */
    uint8_t   pstate8;           /* hub port 8 port state register */
    uint8_t   hpscr1;            /* hub port 1 status change register */
    uint8_t   hpscr2;            /* hub port 2 status change register */
    uint8_t   hpscr3;            /* hub port 3 status change register */
    uint8_t   hpscr4;            /* hub port 4 status change register */
    uint8_t   hpscr5;            /* hub port 5 status change register */
    uint8_t   hpscr6;            /* hub port 6 status change register */
    uint8_t   hpscr7;            /* hub port 7 status change register */
    uint8_t   hpscr8;            /* hub port 8 status change register */
    uint8_t   fdr5;              /* endpoint 5 data register */
    uint8_t   fdr4;              /* endpoint 4 data register */
    uint8_t   fdr3;              /* endpoint 3 data register */
    uint8_t   fdr2;              /* endpoint 2 data register */
    uint8_t   fdr1;              /* endpoint 1 data register */
    uint8_t   fdr0;              /* endpoint 0 data register */
    uint8_t   hdr0;              /* hub endpoint data register */
    uint8_t   fbyte_cnt5;        /* byte count register */
    uint8_t   fbyte_cnt4;        /* byte count register */
    uint8_t   fbyte_cnt3;        /* byte count register */
    uint8_t   fbyte_cnt2;        /* byte count register */
    uint8_t   fbyte_cnt1;        /* byte count register */
    uint8_t   fbyte_cnt0;        /* byte count register */
    uint8_t   hbyte_cnt0;        /* byte count register */
};

extern USB_T *usb_new       ( void );
extern void  usb_construct ( USB_T *usb );
extern void  usb_destroy   ( void *usb );
extern void  usb_intr_set_flag ( USB_T *usb, uint8_t bitnr );
extern void  usb_intr_clear_flag ( USB_T *usb, uint8_t bitnr );

#endif /* USB_H */

reply via email to

[Prev in Thread] Current Thread [Next in Thread]