// ======================================================================
// Common definitions for the USB driver
//
// Copyright 2006-2010 Dick Streefland
//
// This is free software, licensed under the terms of the GNU General
// Public License as published by the Free Software Foundation.
// ======================================================================

#ifdef __ASSEMBLER__
#define __SFR_OFFSET            0
#endif
#include <avr/io.h>
#include "usbtiny.h"

// Preprocessor magic
#define CAT2(a,b)               CAT2EXP(a, b)
#define CAT2EXP(a,b)            a ## b
#define CAT3(a,b,c)             CAT3EXP(a, b, c)
#define CAT3EXP(a,b,c)          a ## b ## c

// I/O Ports for USB
#define USB_IN                  CAT2(PIN, USBTINY_PORT)
#define USB_OUT                 CAT2(PORT, USBTINY_PORT)
#define USB_DDR                 CAT2(DDR, USBTINY_PORT)

// I/O bit masks for USB
#define USB_MASK_DMINUS         (1 << (USBTINY_DMINUS))
#define USB_MASK_DPLUS          (1 << (USBTINY_DPLUS))
#define USB_MASK                (USB_MASK_DMINUS | USB_MASK_DPLUS)

// Interrupt configuration
#if     defined EICRA
#  define USB_INT_CONFIG        EICRA
#else
#  define USB_INT_CONFIG        MCUCR
#endif
#define USB_INT_CONFIG_SET      ((1 << CAT3(ISC,USBTINY_INT,1)) | (1 << CAT3(ISC,USBTINY_INT,0)))
#define USB_INT_VECTOR    CAT3(INT, USBTINY_INT, _vect)

// Interrupt enable
#if     defined GIMSK
#  define USB_INT_ENABLE        GIMSK
#elif   defined EIMSK
#  define USB_INT_ENABLE        EIMSK
#else
#  define USB_INT_ENABLE        GICR
#endif
#define USB_INT_ENABLE_BIT      CAT2(INT,USBTINY_INT)

// Interrupt pending bit
#if     defined EIFR
#  define USB_INT_PENDING       EIFR
#else
#  define USB_INT_PENDING       GIFR
#endif
#define USB_INT_PENDING_BIT     CAT2(INTF,USBTINY_INT)
#if     defined INF0 && ! defined INTF0
#  define       INTF0           INF0    // fix for incorrect definition in iotn13.h
#endif

// USB PID values
#define USB_PID_SETUP           0x2d
#define USB_PID_OUT             0xe1
#define USB_PID_IN              0x69
#define USB_PID_DATA0           0xc3
#define USB_PID_DATA1           0x4b
#define USB_PID_ACK             0xd2
#define USB_PID_NAK             0x5a
#define USB_PID_STALL           0x1e

// Various constants
#define USB_BUFSIZE             11      // PID + data + CRC

// Bit manipulation macros
#define BIT_CLR(reg,bit)        { (reg) &= ~ _BV(bit); }
#define BIT_SET(reg,bit)        { (reg) |=   _BV(bit); }
#define BIT_TST(reg,bit)        (((reg) & _BV(bit)) != 0)

// I/O port manipulation macros
#define DDR_CLR(p,b)            BIT_CLR(DDR  ## p, b)
#define DDR_SET(p,b)            BIT_SET(DDR  ## p, b)
#define PORT_CLR(p,b)           BIT_CLR(PORT ## p, b)
#define PORT_SET(p,b)           BIT_SET(PORT ## p, b)
#define PORT_TST(p,b)           BIT_TST(PORT ## p, b)
#define PIN_TST(p,b)            BIT_TST(PIN  ## p, b)
#define PIN_SET(p,b)            BIT_SET(PIN  ## p, b)

// Macros that can be used with an argument of the form (port,bit)
#define INPUT(bit)              DDR_CLR bit
#define OUTPUT(bit)             DDR_SET bit
#define CLR(bit)                PORT_CLR bit
#define SET(bit)                PORT_SET bit
#define ISSET(bit)              PORT_TST bit
#define TST(bit)                PIN_TST bit
#define TOGGLE(bit)             PIN_SET bit