simulavr-devel
[Top][All Lists]
Advanced

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

[Simulavr-devel] UART and USB updates


From: Keith Gudger
Subject: [Simulavr-devel] UART and USB updates
Date: Thu, 4 Dec 2003 15:05:45 -0800 (PST)

Ted:

To make it easier on myself, I included both of these updates in this
email.  (Hopefully the attachments are really there this time.)

My cvs tree should have been from Tuesday or Wednesday, and the only
affected file is devsupp.c, so I don't think you will have any problem.
If you do, please let me know and I'll redo this when Savannah is back up.

Keith
--- /asic/keith/simulavr/devsupp.c      2003-12-02 10:14:21.000000000 -0800
+++ src/devsupp.c       2003-12-04 14:24:55.000000000 -0800
@@ -61,6 +61,7 @@
 #include "spi.h"
 #include "adc.h"
 #include "usb.h"
+#include "uart.h"
 
 #include "avrcore.h"
 
@@ -125,6 +126,7 @@
         uint8_t timsk;
         uint8_t spcr;
         uint8_t adcsr;
+        uint8_t uart;
         uint8_t uier;
     } mask;
 };
@@ -162,6 +164,7 @@
         .timsk      = (mask_TOIE0),
         .spcr       = 0,
         .adcsr      = 0,
+        .uart       = 0,
         .uier       = 0
     }
 };
@@ -194,6 +197,7 @@
                        | mask_TOIE0),
         .spcr       = 0,
         .adcsr      = 0,
+        .uart       = 0,
         .uier       = 0
     }
 };
@@ -226,6 +230,7 @@
                        | mask_TOIE0),
         .spcr       = (mask_SPIE),
         .adcsr      = 0,
+        .uart       = ONE_UART,
         .uier       = 0
     }
 };
@@ -258,6 +263,7 @@
                        | mask_TOIE0),
         .spcr       = (mask_SPIE),
         .adcsr      = 0,
+        .uart       = ONE_UART,
         .uier       = 0
     }
 };
@@ -290,6 +296,7 @@
                        | mask_TOIE0),
         .spcr       = (mask_SPIE),
         .adcsr      = 0,
+        .uart       = ONE_UART,
         .uier       = 0
     }
 };
@@ -322,6 +329,7 @@
                        | mask_TOIE0),
         .spcr       = (mask_SPIE),
         .adcsr      = 0,
+        .uart       = ONE_UART,
         .uier       = 0
     }
 };
@@ -354,6 +362,7 @@
                        | mask_TOIE0),
         .spcr       = (mask_SPIE),
         .adcsr      = (mask_ADEN),
+        .uart       = ONE_UART,
         .uier       = 0
     }
 };
@@ -386,6 +395,7 @@
                        | mask_TOIE0),
         .spcr       = (mask_SPIE),
         .adcsr      = 0,
+        .uart       = TWO_UART_HI,
         .uier       = 0
     }
 };
@@ -417,6 +427,7 @@
                        | mask_TOIE0),
         .spcr       = (mask_SPIE),
         .adcsr      = (mask_ADEN),
+        .uart       = 0,
         .uier       = (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_FEP3)
     }
 };
@@ -448,6 +459,7 @@
                        | mask_TOIE0),
         .spcr       = 0,
         .adcsr      = (mask_ADEN),
+        .uart       = 0,
         .uier       = (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_FEP3
                        | mask_HEP0)}
 };
@@ -479,6 +491,7 @@
                        | mask_TOIE0),
         .spcr       = (mask_SPIE),
         .adcsr      = (mask_ADEN),
+        .uart       = 0,
         .uier       = (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_FEP3
                        | mask_HEP0)
     }
@@ -511,6 +524,7 @@
                        | mask_TOIE0),
         .spcr       = (mask_SPIE),
         .adcsr      = 0,
+        .uart       = ONE_UART,
         .uier       = (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_FEP3
                        | mask_HEP0)
     }
@@ -543,6 +557,7 @@
                        | mask_TOIE0),
         .spcr       = 0,
         .adcsr      = 0,
+        .uart       = 0,
         .uier       = (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_HEP0)
     }
 };
@@ -574,6 +589,7 @@
                        | mask_TOIE0),
         .spcr       = (mask_SPIE),
         .adcsr      = 0,
+        .uart       = 0,
         .uier       = (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_FEP3
                        | mask_HEP0)
     }
@@ -606,6 +622,7 @@
                        | mask_TOIE0),
         .spcr       = 0,
         .adcsr      = 0,
+        .uart       = 0,
         .uier       = (mask_FEP0 | mask_FEP1 | mask_FEP2 | mask_HEP0)
     }
 };
@@ -771,7 +788,31 @@
             avr_core_attach_vdev (core, vdev);
         }
 
-        /* Attach device port vdevs */
+        if (dev->mask.uart)
+        {
+            vdev = (VDevice *)uart0_intr_new(dev->mask.uart);
+            avr_core_attach_vdev( core, vdev ); /* uart0_intterupt */
+
+            if ( dev->mask.uart & TWO_UART )
+                       {
+                vdev = (VDevice *)uart_new(ONE_UART); 
+                avr_core_attach_vdev( core, vdev ); /* this is for uart0 */
+                vdev = (VDevice *)uart1_intr_new(dev->mask.uart);
+                avr_core_attach_vdev( core, vdev ); /* uart1_intterupt */
+            }
+            vdev = (VDevice *)uart_new(dev->mask.uart); 
+            avr_core_attach_vdev( core, vdev ); /* this is for uart0/uart1*/
+        }
+               
+        if (dev->mask.uier)
+        {
+            vdev = (VDevice *)usb_intr_new( dev->mask.uier );
+            avr_core_attach_vdev( core, vdev );
+            vdev = (VDevice *)usb_new();
+            avr_core_attach_vdev( core, vdev );
+        }
+
+       /* Attach device port vdevs */
 
         pp = dev->ports;
         while (*pp)
/*
 * $Id: uart.c,v 1.9 2003/11/04 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 uart.c
 * \brief Module to simulate the AVR's uart 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 "uart.h"

#include "avrcore.h"

#include "intvects.h"

/****************************************************************************\
 *
 * uart Interrupts 
 *
\****************************************************************************/
static uint8_t uart_intr_read   ( VDevice *dev, int addr );
static void  uart_intr_write    ( VDevice *dev, int addr, uint8_t val );
static void  uart_intr_reset    ( VDevice *dev );
static char *uart_intr_reg_name ( VDevice *dev , int addr );
static int uart_intr_cb( uint64_t time, AvrClass *data ) ;

int UART_Int_Table[] = {
    irq_vect_table_index(UART_RX),       /* uart Rx complete */
    irq_vect_table_index(UART_UDRE),     /* uart data register empty */
    irq_vect_table_index(UART_TX)        /* uart Tx complete */
};

int UART0_Int_Table[] = {
    irq_vect_table_index(USART0_RX),           /* uart Rx complete */
    irq_vect_table_index(USART0_UDRE),         /* uart data register empty */
    irq_vect_table_index(USART0_TX)            /* uart Tx complete */
};

int UART1_Int_Table[] = {
    irq_vect_table_index(USART1_RX),           /* uart Rx complete */
    irq_vect_table_index(USART1_UDRE),         /* uart data register empty */
    irq_vect_table_index(USART1_TX)            /* uart Tx complete */
};


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

UARTIntr_T *uart0_intr_new( uint8_t uart_num )
{
    UARTIntr_T *uart;

    uart = avr_new( UARTIntr_T, 1 );
    uart0_intr_construct( uart );
    class_overload_destroy( (AvrClass *)uart, uart_intr_destroy );

    if ( uart_num > ONE_UART )
        uart->Int_Table = &UART0_Int_Table[0] ;
    else
        uart->Int_Table = &UART_Int_Table[0] ;
                
    return uart;
}

UARTIntr_T *uart1_intr_new( uint8_t uart_num )
{
    UARTIntr_T *uart;

    uart = avr_new( UARTIntr_T, 1 );
    uart1_intr_construct( uart, uart_num );
    class_overload_destroy( (AvrClass *)uart, uart_intr_destroy );

    uart->Int_Table = &UART1_Int_Table[0] ;
                
    return uart;
}

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

void uart0_intr_construct( UARTIntr_T *uart )
{
    char *name = "uartIntr0";

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

    vdev_construct( (VDevice *)uart, name, UART_INTR_BASE_0, UART_INTR_SIZE,
                    uart_intr_read, uart_intr_write, uart_intr_reset, 
                    uart_intr_reg_name );

    uart_intr_reset( (VDevice*)uart );
}

void uart1_intr_construct( UARTIntr_T *uart, uint8_t uart_num )
{
    char *name = "uartIntr1";

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

    if ( uart_num > TWO_UART )
        vdev_construct( (VDevice *)uart, name, UART_INTR_BASE_128, 
                        UART_INTR_SIZE, uart_intr_read, uart_intr_write, 
                        uart_intr_reset, uart_intr_reg_name );
    else
        vdev_construct( (VDevice *)uart, name, UART_INTR_BASE_1,
                        UART_INTR_SIZE, uart_intr_read, uart_intr_write, 
                        uart_intr_reset, uart_intr_reg_name );

    uart_intr_reset( (VDevice*)uart );
}

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

void uart_intr_destroy( void *uart )
{
    if (uart == NULL)
        return;

    vdev_destroy( uart );
}


static uint8_t  uart_intr_read( VDevice *dev, int addr )
{
    UARTIntr_T *uart = (UARTIntr_T *)dev;

    switch ( addr - vdev_get_base(dev) ) {
        case UART_INTR_UBRR_ADDR   : return (uart->ubrr );
        case UART_INTR_UCR_ADDR    : return (uart->ucr  );
        case UART_INTR_USR_ADDR    : return (uart->usr  );
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return 0;                   /* will never get here */
}


static void  uart_intr_write( VDevice *dev, int addr, uint8_t val )
{
    UARTIntr_T *uart     = (UARTIntr_T *)dev;
    CallBack    *cb;

    switch ( addr - vdev_get_base(dev) ) {
        case UART_INTR_UBRR_ADDR  : (uart->ubrr  = val); break;
        case UART_INTR_USR_ADDR   : 
            if ( val & mask_TXC )
              uart->usr &= ~mask_TXC ;
            break;
        case UART_INTR_UCR_ADDR   :
                    (uart->ucr = val); /* look for interrupt enables */
            if ( ( ( uart->ucr &  mask_TXEN ) && 
                    ( uart->ucr &  mask_TXCIE ) ) ||
                  ( ( uart->ucr &  mask_RXEN ) && 
                    ( uart->ucr &  mask_RXCIE ) ) ||
                    ( uart->ucr &  mask_UDRIE )   )
            {
              if ( uart->intr_cb == NULL )
              {
                /* we need to install the intr_cb function */
                cb = callback_new( uart_intr_cb, (AvrClass *)uart );
                uart->intr_cb = cb;
                avr_core_async_cb_add( (AvrCore *)vdev_get_core(dev), cb );
              }
            }
            else
            {
                uart->intr_cb = NULL; 
               /* no interrupt are enabled, remove the callback */
            }
                            
                        break;
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
}

static void  uart_intr_reset( VDevice *dev )
{
    UARTIntr_T *uart = (UARTIntr_T *)dev;

    uart->intr_cb = NULL;

    uart->ubrr = 0;
    uart->usr  = 0;
    uart->ucr  = 0;
    uart->usr_shadow  = 0;
}

static char *uart_intr_reg_name( VDevice *dev , int addr )
{
    switch ( addr - vdev_get_base(dev) ) {
        case UART_INTR_UBRR_ADDR  : return ("UBRR"    );
        case UART_INTR_UCR_ADDR   : return ("UCR"     );
        case UART_INTR_USR_ADDR   : return ("USR"     );
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return NULL;                /* will never get here */
}

static int uart_intr_cb( uint64_t time, AvrClass *data )
{
    UARTIntr_T *uart = (UARTIntr_T *)data;

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

    if ( ( uart->ucr & mask_RXCIE ) && ( uart->usr & mask_RXC ) ) 
          /* an enabled interrupt occured */
    {
        AvrCore *core = (AvrCore *)vdev_get_core((VDevice *)uart);
        avr_core_irq_raise( core, (uart->Int_Table[URX]) );
    }

    if ( ( uart->ucr & mask_TXCIE ) && ( uart->usr & mask_TXC ) ) 
          /* an enabled interrupt occured */
    {
        AvrCore *core = (AvrCore *)vdev_get_core((VDevice *)uart);
        avr_core_irq_raise( core, (uart->Int_Table[UTX]) );
        uart->usr &= ~mask_TXC;
    }

    if ( ( uart->ucr & mask_UDRIE ) && ( uart->usr & mask_UDRE ) &&
          ( uart->usr_shadow & mask_UDRE ) ) 
          /* an enabled interrupt occured */
    {
        AvrCore *core = (AvrCore *)vdev_get_core((VDevice *)uart);
        avr_core_irq_raise( core, (uart->Int_Table[UUDRE]) );
        uart->usr_shadow &= ~mask_UDRE; /* only issue one interrupt / udre */
    }

    return CB_RET_RETAIN;
}

/****************************************************************************\
 *
 * uart  
 *
\****************************************************************************/

static uint8_t  uart_read     ( VDevice *dev, int addr );
static void    uart_write    ( VDevice *dev, int addr, uint8_t val );
static void    uart_reset    ( VDevice *dev );
static char   *uart_reg_name ( VDevice *dev , int addr );
static int     uart_clk_incr_cb( uint64_t ck, AvrClass *data );

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

UART_T *uart_new( uint8_t uart_num )
{
    UART_T *uart;

    uart = avr_new( UART_T, 1 );
    if ( uart_num > ONE_UART )
        uart1_construct( uart, uart_num );
        else
        uart0_construct( uart );
    class_overload_destroy( (AvrClass *)uart, uart_destroy );

    return uart;
}

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

void uart0_construct( UART_T *uart )
{
    char *name = "uart0";

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

    vdev_construct( (VDevice *)uart, name, UART_BASE_0, UART_SIZE,
                    uart_read, uart_write, uart_reset, uart_reg_name );

    uart_reset( (VDevice*)uart );
        uart->int_name = "uartIntr0";
}

void uart1_construct( UART_T *uart, uint8_t uart_num )
{
    char *name = "uart1";

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

    if ( uart_num > TWO_UART )
        vdev_construct( (VDevice *)uart, name, UART_BASE_128, UART_SIZE,
                        uart_read, uart_write, uart_reset, uart_reg_name );
    else
        vdev_construct( (VDevice *)uart, name, UART_BASE_1, UART_SIZE,
                        uart_read, uart_write, uart_reset, uart_reg_name );

    uart_reset( (VDevice*)uart );
        uart->int_name = "uartIntr1";
}

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

void uart_destroy( void *uart )
{
    if (uart == NULL)
        return;

    vdev_destroy( uart );
}

static uint8_t uart_read( VDevice *dev, int addr )
{
    UART_T *uart = (UART_T *)dev;
    UARTIntr_T *uart_t;
    int  offset  = addr - vdev_get_base(dev);
    uint16_t    udr_temp;

    uart_t = (UARTIntr_T *)avr_core_get_vdev_by_name( 
                             (AvrCore *)vdev_get_core((VDevice *)uart),
                               uart->int_name );

    if ( offset == UART_UDR_ADDR )
    {
        uart_t->usr &= ~mask_RXC ; /* clear RXC bit in USR */
        if ( uart->clk_cb ) /* call back already installed */
        {
          udr_temp = uart_port_rd( addr );
          uart->udr_rx = (uint8_t) udr_temp ; /* lower 8 bits */
          if ( ( uart_t->ucr & mask_CHR9 ) &&  /* 9 bits rec'd */
               ( udr_temp & (1 << 8) ) )      /* hi bit set */
             uart_t->ucr |=  mask_RXB8 ;
          else
             uart_t->ucr &= ~mask_RXB8 ;
        }
        return uart->udr_rx;
    }
    else
        avr_error( "Bad address: 0x%04x", addr );
    return 0;                   /* will never get here */
}

static void uart_write( VDevice *dev, int addr, uint8_t val )
{
    UART_T *uart   = (UART_T *)dev;
    UARTIntr_T *uart_t;
    int  offset  = addr - vdev_get_base(dev);
    CallBack *cb;

    uart_t = (UARTIntr_T *)avr_core_get_vdev_by_name( 
                             (AvrCore *)vdev_get_core((VDevice *)uart),
                              uart->int_name );

    if ( offset == UART_UDR_ADDR )
    {
        if (uart_t->usr & mask_UDRE)
        {
           uart_t->usr        &= ~mask_UDRE ;
           uart_t->usr_shadow &= ~mask_UDRE ;
        }
        else
        {
           uart_t->usr        |= mask_UDRE ;
           uart_t->usr_shadow |= mask_UDRE ;
        }
        uart->udr_tx = val;
        /*
         * When the user writes to UDR, a callback is installed for 
         * clock generated increments. 
         */

        uart->divisor = ( uart_t->ubrr + 1 ) * 16 ;

        /* install the clock incrementor callback (with flair!) */
        if (uart->clk_cb == NULL)
        {
            cb = callback_new( uart_clk_incr_cb, (AvrClass *)uart );
            uart->clk_cb = cb;
            avr_core_clk_cb_add((AvrCore *)vdev_get_core((VDevice *)uart),cb);
        }
        /* set up timer for 8 or 9 clocks based on ucr 
           (includes start and stop bits) */
        uart->tcnt = ( uart_t->ucr & mask_CHR9 ) ? 11 : 10 ; 
    }
    else
    {
        avr_error( "Bad address: 0x%04x", addr );
    }
}

static void uart_reset( VDevice *dev )
{
    UART_T *uart = (UART_T *)dev;

    uart->clk_cb = NULL;

    uart->udr_rx = 0;
    uart->udr_tx = 0;
    uart->tcnt = 0;
    uart->divisor = 0;
}

static char *uart_reg_name( VDevice *dev , int addr )
{
    switch ( addr - vdev_get_base(dev) ) {
        case UART_UDR_ADDR: return "UDR";
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return NULL;
}


static int uart_clk_incr_cb( uint64_t ck, AvrClass *data )
{
    UART_T    *uart = (UART_T *)data;
    UARTIntr_T *uart_t;
    uint8_t   last  = uart->tcnt;

    uart_t = (UARTIntr_T *)avr_core_get_vdev_by_name( 
                             (AvrCore *)vdev_get_core((VDevice *)uart),
                               uart->int_name );

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

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

    /* decrement clock if ck is a mutliple of divisor */
    uart->tcnt -= ((ck % uart->divisor) == 0);

    /* */
    if (uart->tcnt != last)  /* we've changed the counter */
    {
        if ( uart->tcnt == 0 )
        {
            if ( uart_t->usr & mask_UDRE ) /* data register empty */
            {
                uart_t->usr |= mask_TXC; 
                return CB_RET_REMOVE;
            }
            else                         /* there's a byte waiting to go */
            {
                uart_t->usr |= mask_UDRE;
                uart_t->usr_shadow |= mask_UDRE; /* also write shadow */
                /* set up timer for 8 or 9 clocks based on ucr,
                   (includes start and stop bits) */
                uart->tcnt = ( uart_t->ucr & mask_CHR9 ) ? 11 : 10 ; 
            }   
        }
    }
    return CB_RET_RETAIN;
}

uint16_t uart_port_rd( int addr )
{
    int   data;
    char  line[80];

    while (1)
    {
       fprintf( stderr, 
       "\nEnter 9 bits of hex data to read into the uart at address 0x%04x: ",
                 addr);

        /* 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, "%x\n", &data) != 1 )
            continue;

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

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

/*
 * $Id: uart.h,v 1.3 2003/11/04 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 uart_H
#define uart_H

enum _uart_definitions {
    ONE_UART     =  0x01,           /* only one uart */
    TWO_UART     =  0x02,           /* two uarts, 2nd one low */
    TWO_UART_HI  =  0x06,           /* two uarts, 2nd one hi  */
};

/****************************************************************************\
 *
 * uartInter_T(VDevice) : uart Interrupt and Control Register
 *
 \****************************************************************************/

enum _uart_intr_constants {
    UART_INTR_BASE_1   = 0x20,     /* base address for vdev UART1 */
    UART_INTR_BASE_0   = 0x29,     /* base address for vdev UART0*/
    UART_INTR_BASE_128 = 0x99,     /* base address for vdev UART1 mega 128*/
    UART_INTR_SIZE     = 3,        /* UBRR, UCR, USR */

    UART_INTR_UBRR_ADDR  = 0,
    UART_INTR_UCR_ADDR   = 1,
    UART_INTR_USR_ADDR   = 2,
};

enum _uart_int_table_constants {
    URX,            /* uart Rx complete */
    UUDRE,          /* uart data register empty */
    UTX             /* uart Tx complete */
};

typedef enum {
    bit_MPCM  = 0,             /* Multi-processor Communication Mode  */
    bit_U2X   = 1,             /* Double X-mission Speed   */
    bit_OR    = 3,             /* OverRun               */
    bit_FE    = 4,             /* Framing Error         */
    bit_UDRE  = 5,             /* Data Register Empty   */
    bit_TXC   = 6,             /* Transmit Complete     */
    bit_RXC   = 7,             /* Receive Complete      */
} UCR_BITS;

typedef enum {
    mask_MPCM   = 1 << bit_MPCM,
        mask_U2X    = 1 << bit_U2X,
    mask_OR     = 1 << bit_OR,
    mask_FE     = 1 << bit_FE,
    mask_UDRE   = 1 << bit_UDRE,
    mask_TXC    = 1 << bit_TXC,
    mask_RXC    = 1 << bit_RXC,
} UCR_MASKS;

typedef enum {
    bit_TXB8   = 0,             /* Transmit Data Bit 8  */
    bit_RXB8   = 1,             /* Receive  Data Bit 8  */
    bit_CHR9   = 2,             /* 9 bit characters     */
    bit_TXEN   = 3,             /* Transmitter Enable   */
    bit_RXEN   = 4,             /* Receiver    Enable   */
    bit_UDRIE  = 5,             /* Data Register Interrupt Enable */
    bit_TXCIE  = 6,             /* TX Complete   Interrupt Enable */
    bit_RXCIE  = 7,             /* RX Complete   Interrupt Enable */
} USR_BITS;

typedef enum {
    mask_TXB8   = 1 << bit_TXB8,
    mask_RXB8   = 1 << bit_RXB8,
    mask_CHR9   = 1 << bit_CHR9,
    mask_TXEN   = 1 << bit_TXEN,
    mask_RXEN   = 1 << bit_RXEN,
    mask_UDRIE  = 1 << bit_UDRIE,
    mask_TXCIE  = 1 << bit_TXCIE,
    mask_RXCIE  = 1 << bit_RXCIE,
} USR_MASKS;


typedef struct _UARTIntr_T UARTIntr_T;

struct _UARTIntr_T {
    VDevice   parent;
    uint16_t  ubrr;             /* uart BAUD Rate register */
    uint8_t   usr ;             /* uart status register    */
    uint8_t   ucr ;             /* uart control register   */
    uint8_t   usr_shadow ;      /* shadow uart status register   */
    CallBack *intr_cb;          /* callback - check and raise interrupts*/
        int*     Int_Table;        /* pointer to int index for this interrupt*/
};

extern UARTIntr_T *uart0_intr_new     ( uint8_t uart_num );
extern UARTIntr_T *uart1_intr_new     ( uint8_t uart_num );
extern void      uart0_intr_construct ( UARTIntr_T *ti );
extern void      uart1_intr_construct ( UARTIntr_T *ti, uint8_t sram_ext );
extern void      uart_intr_destroy   ( void *ti );

/****************************************************************************\
 *
 * uart(VDevice) : uart
 *
\****************************************************************************/

enum _uart_constants {
    UART_BASE_1    = 0x23,       /* base memory address UART1 */
    UART_BASE_0    = 0x2c,       /* base memory address UART0 */
    UART_BASE_128  = 0x9c,       /* base memory address UART1, mega128 */
    UART_SIZE      = 1,          /* SPDR */

    UART_UDR_ADDR  = 0,          /* offset from base to SPDR Register */
};

typedef struct _UART UART_T;

struct _UART {
    VDevice   parent;
    uint8_t   udr_rx;           /* receive  data  register */
    uint8_t   udr_tx;           /* transmit data  register */
    uint16_t  tcnt;             /* uart timer up-counter register */
    uint16_t  divisor;          /* clock divisor */
    CallBack *clk_cb;           /* incr timer tied to clock */
    char    *int_name;         /* pointer to associated interrupt name */
};

extern UART_T *uart_new       ( uint8_t uart_num );
extern void   uart0_construct ( UART_T *uart );
extern void   uart1_construct ( UART_T *uart, uint8_t sram_ext );
extern void   uart_destroy   ( void *uart );
extern void   uart_intr_set_flag   ( UARTIntr_T *ti );
extern void   uart_intr_clear_flag ( UARTIntr_T *ti );
extern uint16_t uart_port_rd( int addr ) ;
extern void   uart_port_wr( uint8_t val );

#endif
/*
 * $Id: usb.c,v 1.9 2003/10/28 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 usb.c
 * \brief Module to simulate the AVR's USB 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 "usb.h"

#include "intvects.h"

void usb_port_wr(char * name, uint8_t val );
uint8_t usb_port_rd(char * name );
/*****************************************************************************\
 *
 * USB Interrupts 
 *
\*****************************************************************************/

static uint8_t usb_intr_read   ( VDevice *dev, int addr );
static void  usb_intr_write    ( VDevice *dev, int addr, uint8_t val );
static void  usb_intr_reset    ( VDevice *dev );
static char *usb_intr_reg_name ( VDevice *dev , int addr );

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

USBInter_T *usb_intr_new( uint8_t func_mask )
{
    USBInter_T *usb;

    usb = avr_new( USBInter_T, 1 );
    usb_intr_construct( usb, func_mask );
    class_overload_destroy( (AvrClass *)usb, usb_intr_destroy );

    return usb;
}

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

void usb_intr_construct( USBInter_T *usb, uint8_t func_mask )
{
    char *name = "USBIntr";

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

    vdev_construct( (VDevice *)usb, name, USB_INTR_BASE, USB_INTR_SIZE,
                    usb_intr_read, usb_intr_write, usb_intr_reset, 
                    usb_intr_reg_name );

    usb->func_mask = func_mask;

    usb_intr_reset( (VDevice*)usb );
}

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

void usb_intr_destroy( void *usb )
{
    if (usb == NULL)
        return;

    vdev_destroy( usb );
}


static uint8_t  usb_intr_read( VDevice *dev, int addr )
{
    USBInter_T *usb = (USBInter_T *)dev;

    switch ( addr - vdev_get_base(dev) ) {
        case USB_INTR_ENABLE_ADDR : return (usb->uier     );
        case USB_INTR_MASK_ADDR   : return (usb->uimsk    );
        case USB_INTR_STATUS_ADDR : return (usb->uisr    = 
                       usb_port_rd(usb_intr_reg_name((VDevice *)usb, addr)) ) ;
        case USB_INTR_SPRSIE_ADDR : return (usb->sprsie   ) ;

        case USB_INTR_SPRSR_ADDR  : return (usb->sprsr   = 
                       usb_port_rd(usb_intr_reg_name((VDevice *)usb, addr)) ) ;
        case USB_GLB_STATE_ADDR   : return (usb->glb_state) ;
        case USB_FRM_NUM_L_ADDR   : return (usb->frm_num_l) ;
        case USB_FRM_NUM_H_ADDR   : return (usb->frm_num_h) ;
        case USB_INTR_SPRSMSK_ADDR: return (usb->sprsmsk  ) ;
        case USB_INTR_ACK_ADDR    : 
        case USB_INTR_UNUSED_ADDR :
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return 0;                   /* will never get here */
}


static void  usb_intr_write( VDevice *dev, int addr, uint8_t val )
{
    USBInter_T *usb     = (USBInter_T *)dev;

    switch ( addr - vdev_get_base(dev) ) {
        case USB_INTR_ENABLE_ADDR : (usb->uier      = val); break;
        case USB_INTR_MASK_ADDR   : (usb->uimsk     = val); break;
        case USB_INTR_SPRSMSK_ADDR: (usb->sprsmsk   = val); break;
        case USB_INTR_SPRSIE_ADDR : (usb->sprsie    = val); break;
        case USB_INTR_ACK_ADDR    : (usb->uiar      = val); break;
        case USB_GLB_STATE_ADDR   : (usb->glb_state = val); break;
        case USB_FRM_NUM_L_ADDR   : (usb->frm_num_l = val); break;
        case USB_FRM_NUM_H_ADDR   : (usb->frm_num_h = val); break;
        case USB_INTR_STATUS_ADDR :
        case USB_INTR_SPRSR_ADDR  :
        case USB_INTR_UNUSED_ADDR :
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
}


static void  usb_intr_reset( VDevice *dev )
{
    USBInter_T *usb = (USBInter_T *)dev;

    usb->sprsr = 0;
    usb->uisr  = 0;
}

static char *usb_intr_reg_name( VDevice *dev , int addr )
{
    switch ( addr - vdev_get_base(dev) ) {
        case USB_INTR_ENABLE_ADDR : return ("UIER"     );
        case USB_INTR_MASK_ADDR   : return ("UIMSK"    );
        case USB_INTR_STATUS_ADDR : return ("UISR"     ) ;
        case USB_INTR_SPRSIE_ADDR : return ("SPRSIE"   ) ;
        case USB_INTR_SPRSR_ADDR  : return ("SPRSR"    ) ;
        case USB_GLB_STATE_ADDR   : return ("GLB_STATE") ;
        case USB_FRM_NUM_L_ADDR   : return ("FRM_NUM_L") ;
        case USB_FRM_NUM_H_ADDR   : return ("FRM_NUM_H") ;
        case USB_INTR_SPRSMSK_ADDR: return ("SPRSMSK"  ) ;
        case USB_INTR_ACK_ADDR    : return ("UIAR"     ) ;
        case USB_INTR_UNUSED_ADDR : return ("UNUSED"   ) ;
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return NULL;                /* will never get here */
}

/*****************************************************************************\
 *
 * USB  
 *
\*****************************************************************************/

static uint8_t usb_read     ( VDevice *dev, int addr );
static void    usb_write    ( VDevice *dev, int addr, uint8_t val );
static void    usb_reset    ( VDevice *dev );
static char   *usb_reg_name ( VDevice *dev , int addr );

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

USB_T *usb_new( void )
{
    USB_T *usb;

    usb = avr_new( USB_T, 1 );
    usb_construct( usb );
    class_overload_destroy( (AvrClass *)usb, usb_destroy );

    return usb;
}

/** \brief Constructor for new USB object. */

void usb_construct( USB_T *usb )
{
    char *name = "USB";

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

    vdev_construct( (VDevice *)usb, name, USB_BASE, USB_SIZE,
                    usb_read, usb_write, usb_reset, usb_reg_name );

    usb_reset( (VDevice*)usb );
}

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

void usb_destroy( void *usb )
{
    if (usb == NULL)
        return;

    vdev_destroy( usb );
}

static uint8_t usb_read( VDevice *dev, int addr )
{
    USB_T *usb = (USB_T *)dev;

    switch ( addr - vdev_get_base(dev) ) {
        case USB_UOVCER_ADDR: return usb->uovcer;
        case USB_HADDR_ADDR : return usb->haddr;
        case USB_FADDR_ADDR : return usb->faddr;
        case USB_HSTR_ADDR  : return usb->hstr;
        case USB_HPCON_ADDR : return usb->hpcon;
        case USB_ICSR_ADDR  : return usb->icsr;
        case USB_FENDP5_CNTR_ADDR :  return usb->fendp5_cntr ;
        case USB_FENDP4_CNTR_ADDR :  return usb->fendp4_cntr;
        case USB_FENDP3_CNTR_ADDR :  return usb->fendp3_cntr;
        case USB_FENDP2_CNTR_ADDR :  return usb->fendp2_cntr;
        case USB_FENDP1_CNTR_ADDR :  return usb->fendp1_cntr;
        case USB_FENDP0_CNTR_ADDR :  return usb->fendp0_cntr;
        case USB_HENDP1_CNTR_ADDR :  return usb->hendp1_cntr;
        case USB_HENDP0_CNTR_ADDR :  return usb->hendp0_cntr;
        case USB_FCSR5_ADDR       :  return usb->fcsr5 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_FCSR4_ADDR       :  return usb->fcsr4 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_FCSR3_ADDR       :  return usb->fcsr3 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_FCSR2_ADDR       :  return usb->fcsr2 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_FCSR1_ADDR       :  return usb->fcsr1 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_FCSR0_ADDR       :  usb->fcsr0 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
                                     if ( usb->fcsr0 & RX_SETUP )
                                          usb->fbyte_cnt0 = 10;
                                     return usb->fcsr0 ; 
        case USB_HCSR0_ADDR       : usb->hcsr0 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));  
                                     if ( usb->hcsr0 & RX_SETUP )
                                          usb->hbyte_cnt0 = 10;
                                     return usb->hcsr0 ; 
        case USB_FCAR5_ADDR       :  return usb->fcar5;
        case USB_FCAR4_ADDR       :  return usb->fcar4;
        case USB_FCAR3_ADDR       :  return usb->fcar3;
        case USB_FCAR2_ADDR       :  return usb->fcar2;
        case USB_FCAR1_ADDR       :  return usb->fcar1;
        case USB_FCAR0_ADDR       :  return usb->fcar0;
        case USB_HCAR0_ADDR       :  return usb->hcar0;
        case USB_HPSTAT1_ADDR     :  return usb->hpstat1;
        case USB_HPSTAT2_ADDR     :  return usb->hpstat2;
        case USB_HPSTAT3_ADDR     :  return usb->hpstat3;
        case USB_HPSTAT4_ADDR     :  return usb->hpstat4;
        case USB_HPSTAT5_ADDR     :  return usb->hpstat5;
        case USB_HPSTAT6_ADDR     :  return usb->hpstat6;
        case USB_HPSTAT7_ADDR     :  return usb->hpstat7;
        case USB_HPSTAT8_ADDR     :  return usb->hpstat8;
        case USB_PSTATE1_ADDR     :  return usb->pstate1;
        case USB_PSTATE2_ADDR     :  return usb->pstate2;
        case USB_PSTATE3_ADDR     :  return usb->pstate3;
        case USB_PSTATE4_ADDR     :  return usb->pstate4;
        case USB_PSTATE5_ADDR     :  return usb->pstate5;
        case USB_PSTATE6_ADDR     :  return usb->pstate6;
        case USB_PSTATE7_ADDR     :  return usb->pstate7;
        case USB_PSTATE8_ADDR     :  return usb->pstate8;
        case USB_HPSCR1_ADDR      :  return usb->hpscr1;
        case USB_HPSCR2_ADDR      :  return usb->hpscr2;
        case USB_HPSCR3_ADDR      :  return usb->hpscr3;
        case USB_HPSCR4_ADDR      :  return usb->hpscr4;
        case USB_HPSCR5_ADDR      :  return usb->hpscr5; 
        case USB_HPSCR6_ADDR      :  return usb->hpscr6;
        case USB_HPSCR7_ADDR      :  return usb->hpscr7;
        case USB_HPSCR8_ADDR      :  return usb->hpscr8;
        case USB_FBYTE_CNT5_ADDR  :  return usb->fbyte_cnt5 ;
        case USB_FBYTE_CNT4_ADDR  :  return usb->fbyte_cnt4 ;
        case USB_FBYTE_CNT3_ADDR  :  return usb->fbyte_cnt3 ;
        case USB_FBYTE_CNT2_ADDR  :  return usb->fbyte_cnt2 ;
        case USB_FBYTE_CNT1_ADDR  :  return usb->fbyte_cnt1 ;
        case USB_FBYTE_CNT0_ADDR  :  return usb->fbyte_cnt0 ;
        case USB_HBYTE_CNT0_ADDR  :  return usb->hbyte_cnt0 ;
        case USB_FDR5_ADDR        :  return usb->fdr5 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_FDR4_ADDR        :  return usb->fdr4 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_FDR3_ADDR        :  return usb->fdr3 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_FDR2_ADDR        :  return usb->fdr2 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_FDR1_ADDR        :  return usb->fdr1 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_FDR0_ADDR        :  return usb->fdr0 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        case USB_HDR0_ADDR        :  return usb->hdr0 = 
                            usb_port_rd(usb_reg_name((VDevice *)usb, addr));
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return 0;                   /* will never get here */
}

static void usb_write( VDevice *dev, int addr, uint8_t val )
{
    USB_T *usb   = (USB_T *)dev;

    switch ( addr - vdev_get_base(dev) ) {
        case USB_UOVCER_ADDR  : (usb->uovcer    = val); break;
        case USB_HADDR_ADDR   : (usb->haddr     = val); break;
        case USB_FADDR_ADDR   : (usb->faddr     = val); break;
        case USB_HSTR_ADDR    : (usb->hstr      = val); break;
        case USB_HPCON_ADDR   : (usb->hpcon     = val); break;
        case USB_FENDP5_CNTR_ADDR :  usb->fendp5_cntr = val; break;
        case USB_FENDP4_CNTR_ADDR :  usb->fendp4_cntr = val; break;
        case USB_FENDP3_CNTR_ADDR :  usb->fendp3_cntr = val; break;
        case USB_FENDP2_CNTR_ADDR :  usb->fendp2_cntr = val; break;
        case USB_FENDP1_CNTR_ADDR :  usb->fendp1_cntr = val; break;
        case USB_FENDP0_CNTR_ADDR :  usb->fendp0_cntr = val; break;
        case USB_HENDP1_CNTR_ADDR :  usb->hendp1_cntr = val; break;
        case USB_HENDP0_CNTR_ADDR :  usb->hendp0_cntr = val; break;
        case USB_FCAR5_ADDR       :  usb->fcar5 = val; usb->fcsr5 &= ~val;
                                     (usb->fbyte_cnt5) = 0 ; break;
        case USB_FCAR4_ADDR       :  usb->fcar4 = val; usb->fcsr4 &= ~val;
                                      (usb->fbyte_cnt4) = 0 ; break;
        case USB_FCAR3_ADDR       :  usb->fcar3 = val; usb->fcsr3 &= ~val;
                                      (usb->fbyte_cnt3) = 0 ; break;
        case USB_FCAR2_ADDR       :  usb->fcar2 = val; usb->fcsr2 &= ~val;
                                      (usb->fbyte_cnt2) = 0 ; break;
        case USB_FCAR1_ADDR       :  usb->fcar1 = val; usb->fcsr1 &= ~val;
                                      (usb->fbyte_cnt1) = 0 ; break;
        case USB_FCAR0_ADDR       :  usb->fcar0 = val; usb->fcsr0 &= ~val;
                                      (usb->fbyte_cnt0) = 0 ; break;
        case USB_HCAR0_ADDR       :  usb->hcar0 = val; usb->hcsr0 &= ~val;
                                      (usb->hbyte_cnt0) = 0 ; break;
        case USB_FDR5_ADDR        :  usb->fdr5 = val; (usb->fbyte_cnt5)++ ;
                            usb_port_wr(usb_reg_name((VDevice *)usb,addr),val); 
                                     break;
        case USB_FDR4_ADDR             :  usb->fdr4 = val; (usb->fbyte_cnt4)++;
                            usb_port_wr(usb_reg_name((VDevice *)usb,addr),val);
                                     break;
        case USB_FDR3_ADDR        :  usb->fdr3 = val;  (usb->fbyte_cnt3)++ ;
                            usb_port_wr(usb_reg_name((VDevice *)usb,addr),val);
                                     break;
        case USB_FDR2_ADDR        :  usb->fdr2 = val; (usb->fbyte_cnt2)++ ; 
                            usb_port_wr(usb_reg_name((VDevice *)usb,addr),val);
                                     break;
        case USB_FDR1_ADDR        :  usb->fdr1 = val; (usb->fbyte_cnt1)++ ; 
                            usb_port_wr(usb_reg_name((VDevice *)usb,addr),val);
                                     break;
        case USB_FDR0_ADDR        :  usb->fdr0 = val; (usb->fbyte_cnt0)++ ;
                            usb_port_wr(usb_reg_name((VDevice *)usb,addr),val);
                                     break;
        case USB_HDR0_ADDR        :  usb->hdr0 = val; (usb->hbyte_cnt0)++ ;
                            usb_port_wr(usb_reg_name((VDevice *)usb,addr),val);
                                     break;
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
}

static void usb_reset( VDevice *dev )
{
    USB_T *usb = (USB_T *)dev;

    usb->haddr  = 0;
    usb->faddr  = 0;

    usb->hstr   = 0;
    usb->hpcon  = 0;

    usb->uovcer = 0;
}

static char *usb_reg_name( VDevice *dev , int addr )
{
    switch ( addr - vdev_get_base(dev) ) {
        case USB_FCAR5_ADDR :  return "FCAR5";
        case USB_FCAR4_ADDR :  return "FCAR4";
        case USB_FCAR3_ADDR :  return "FCAR3";
        case USB_FCAR2_ADDR :  return "FCAR2";
        case USB_FCAR1_ADDR :  return "FCAR1";
        case USB_FCAR0_ADDR :  return "FCAR0";
        case USB_HCAR0_ADDR :  return "HCAR0";
        case USB_PSTATE1_ADDR :  return "PSTATE1";
        case USB_PSTATE2_ADDR :  return "PSTATE2";
        case USB_PSTATE3_ADDR :  return "PSTATE3";
        case USB_PSTATE4_ADDR :  return "PSTATE4";
        case USB_PSTATE5_ADDR :  return "PSTATE5";
        case USB_PSTATE6_ADDR :  return "PSTATE6";
        case USB_PSTATE7_ADDR :  return "PSTATE7";
        case USB_PSTATE8_ADDR :  return "PSTATE8";
        case USB_HPSCR1_ADDR  :  return "HPSCR1";
        case USB_HPSCR2_ADDR  :  return "HPSCR2";
        case USB_HPSCR3_ADDR  :  return "HPSCR3";
        case USB_HPSCR4_ADDR  :  return "HPSCR4";
        case USB_HPSCR5_ADDR  :  return "HPSCR5"; 
        case USB_HPSCR6_ADDR  :  return "HPSCR6";
        case USB_HPSCR7_ADDR  :  return "HPSCR7";
        case USB_HPSCR8_ADDR  :  return "HPSCR8";
        case USB_HPSTAT1_ADDR :  return "HPSTAT1";
        case USB_HPSTAT2_ADDR :  return "HPSTAT2";
        case USB_HPSTAT3_ADDR :  return "HPSTAT3";
        case USB_HPSTAT4_ADDR :  return "HPSTAT4";
        case USB_HPSTAT5_ADDR :  return "HPSTAT5";
        case USB_HPSTAT6_ADDR :  return "HPSTAT6";
        case USB_HPSTAT7_ADDR :  return "HPSTAT7";
        case USB_HPSTAT8_ADDR :  return "HPSTAT8";
        case USB_HPCON_ADDR   :  return "HPCON";
        case USB_HSTR_ADDR    :  return "HSTR";
        case USB_FBYTE_CNT5_ADDR :  return "FBYTE_CNT5";
        case USB_FBYTE_CNT4_ADDR :  return "FBYTE_CNT4";
        case USB_FBYTE_CNT3_ADDR :  return "FBYTE_CNT3";
        case USB_FBYTE_CNT2_ADDR :  return "FBYTE_CNT2";
        case USB_FBYTE_CNT1_ADDR :  return "FBYTE_CNT1";
        case USB_FBYTE_CNT0_ADDR :  return "FBYTE_CNT0";
        case USB_HBYTE_CNT0_ADDR :  return "HBYTE_CNT0";
        case USB_FDR5_ADDR       :  return "FDR5";
        case USB_FDR4_ADDR       :  return "FDR4";
        case USB_FDR3_ADDR       :  return "FDR3";
        case USB_FDR2_ADDR       :  return "FDR2";
        case USB_FDR1_ADDR       :  return "FDR1";
        case USB_FDR0_ADDR       :  return "FDR0";
        case USB_HDR0_ADDR       :  return "HDR0";
        case USB_FCSR5_ADDR      :  return "FCSR5";
        case USB_FCSR4_ADDR      :  return "FCSR4";
        case USB_FCSR3_ADDR      :  return "FCSR3";
        case USB_FCSR2_ADDR      :  return "FCSR2";
        case USB_FCSR1_ADDR      :  return "FCSR1";
        case USB_FCSR0_ADDR      :  return "FCSR0";
        case USB_HCSR0_ADDR      :  return "HCSR0";
        case USB_FENDP5_CNTR_ADDR :  return "FENDP5_CNTR";
        case USB_FENDP4_CNTR_ADDR :  return "FENDP4_CNTR";
        case USB_FENDP3_CNTR_ADDR :  return "FENDP3_CNTR";
        case USB_FENDP2_CNTR_ADDR :  return "FENDP2_CNTR";
        case USB_FENDP1_CNTR_ADDR :  return "FENDP1_CNTR";
        case USB_FENDP0_CNTR_ADDR :  return "FENDP0_CNTR";
        case USB_HENDP1_CNTR_ADDR :  return "HENDP1_CNTR";
        case USB_HENDP0_CNTR_ADDR :  return "HENDP0_CNTR";
        case USB_FADDR_ADDR       :  return "FADDR";
        case USB_HADDR_ADDR       :  return "HADDR";
        case USB_ICSR_ADDR        :  return "ICSR";
        case USB_UOVCER_ADDR      :  return "UOVCER";
        default:
            avr_error( "Bad address: 0x%04x", addr );
    }
    return NULL;
}

uint8_t usb_port_rd( char * name )
{
    int   data;
    char  line[80];

    while (1)
    {
        fprintf( stderr, "\nEnter a byte of hex data to read into %s: ",
                 name);

        /* 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, "%x\n", &data) != 1 )
            continue;

        break;
    }
    return (uint8_t)(data & 0xff);
}

void usb_port_wr(char * name, uint8_t val )
{
    fprintf( stderr, "wrote 0x%02x to %s\n", val, name );
}



reply via email to

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