#if !defined(_usb_h_) || defined(_USBHOST_H_)
#error "Never include usbhost.h directly; include Usb.h instead"
#else
#define _USBHOST_H_
#if USING_SPI4TEENSY3
#include <spi4teensy3.h>
#include <sys/types.h>
#endif
template< typename SPI_CLK, typename SPI_MOSI, typename SPI_MISO, typename SPI_SS > class SPi {
public:
#if USING_SPI4TEENSY3
static void init() {
spi4teensy3::init(); SPI_SS::SetDirWrite();
SPI_SS::Set();
}
#elif SPI_HAS_TRANSACTION
static void init() {
SPI.begin(); }
#elif !defined(SPDR)
static void init() {
SPI_SS::SetDirWrite();
SPI_SS::Set();
SPI.begin();
#if defined(__MIPSEL__)
SPI.setClockDivider(1);
#elif defined(__ARDUINO_X86__)
#ifdef SPI_CLOCK_1M
SPI.setClockSpeed(12000000); #else
SPI.setClockDivider(SPI_CLOCK_DIV2); #endif
#else
SPI.setClockDivider(4); #endif
}
#elif defined(RBL_NRF51822)
static void init() {
SPI_SS::SetDirWrite();
SPI_SS::Set();
SPI.begin();
}
#else
static void init() {
SPI_CLK::SetDirWrite();
SPI_MOSI::SetDirWrite();
SPI_MISO::SetDirRead();
SPI_SS::SetDirWrite();
SPCR = 0x50;
SPSR = 0x01;
}
#endif
};
#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi;
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi;
#elif (defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))) || defined(__ARDUINO_X86__) || defined(__MIPSEL__)
typedef SPi< P13, P11, P12, P10 > spi;
#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)
typedef SPi< P76, P75, P74, P10 > spi;
#elif defined(RBL_NRF51822)
typedef SPi< P16, P18, P17, P10 > spi;
#else
#error "No SPI entry in usbhost.h"
#endif
typedef enum {
vbus_on = 0,
vbus_off = GPX_VBDET
} VBUS_t;
template< typename SPI_SS, typename INTR > class MAX3421e {
static uint8_t vbusState;
public:
MAX3421e();
void regWr(uint8_t reg, uint8_t data);
uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p);
void gpioWr(uint8_t data);
uint8_t regRd(uint8_t reg);
uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p);
uint8_t gpioRd();
uint16_t reset();
int8_t Init();
int8_t Init(int mseconds);
void vbusPower(VBUS_t state) {
regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | state));
}
uint8_t getVbusState(void) {
return vbusState;
};
void busprobe();
uint8_t GpxHandler();
uint8_t IntHandler();
uint8_t Task();
};
template< typename SPI_SS, typename INTR >
uint8_t MAX3421e< SPI_SS, INTR >::vbusState = 0;
template< typename SPI_SS, typename INTR >
MAX3421e< SPI_SS, INTR >::MAX3421e() {
#ifdef BOARD_MEGA_ADK
P55::SetDirWrite();
P55::Set();
#endif
};
template< typename SPI_SS, typename INTR >
void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) {
XMEM_ACQUIRE_SPI();
#if SPI_HAS_TRANSACTION
SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); #endif
SPI_SS::Clear();
#if USING_SPI4TEENSY3
uint8_t c[2];
c[0] = reg | 0x02;
c[1] = data;
spi4teensy3::send(c, 2);
#elif SPI_HAS_TRANSACTION
uint8_t c[2];
c[0] = reg | 0x02;
c[1] = data;
SPI.transfer(c, 2);
#elif !defined(SPDR)
SPI.transfer(reg | 0x02);
SPI.transfer(data);
#else
SPDR = (reg | 0x02);
while(!(SPSR & (1 << SPIF)));
SPDR = data;
while(!(SPSR & (1 << SPIF)));
#endif
SPI_SS::Set();
#if SPI_HAS_TRANSACTION
SPI.endTransaction();
#endif
XMEM_RELEASE_SPI();
return;
};
template< typename SPI_SS, typename INTR >
uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
XMEM_ACQUIRE_SPI();
#if SPI_HAS_TRANSACTION
SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); #endif
SPI_SS::Clear();
#if USING_SPI4TEENSY3
spi4teensy3::send(reg | 0x02);
spi4teensy3::send(data_p, nbytes);
data_p += nbytes;
#elif SPI_HAS_TRANSACTION
SPI.transfer(reg | 0x02);
SPI.transfer(data_p, nbytes);
data_p += nbytes;
#elif defined(__ARDUINO_X86__)
SPI.transfer(reg | 0x02);
SPI.transferBuffer(data_p, NULL, nbytes);
data_p += nbytes;
#elif !defined(SPDR)
SPI.transfer(reg | 0x02);
while(nbytes) {
SPI.transfer(*data_p);
nbytes--;
data_p++; }
#else
SPDR = (reg | 0x02); while(nbytes) {
while(!(SPSR & (1 << SPIF))); SPDR = (*data_p); nbytes--;
data_p++; }
while(!(SPSR & (1 << SPIF)));
#endif
SPI_SS::Set();
#if SPI_HAS_TRANSACTION
SPI.endTransaction();
#endif
XMEM_RELEASE_SPI();
return ( data_p);
}
template< typename SPI_SS, typename INTR >
void MAX3421e< SPI_SS, INTR >::gpioWr(uint8_t data) {
regWr(rIOPINS1, data);
data >>= 4;
regWr(rIOPINS2, data);
return;
}
template< typename SPI_SS, typename INTR >
uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) {
XMEM_ACQUIRE_SPI();
#if SPI_HAS_TRANSACTION
SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); #endif
SPI_SS::Clear();
#if USING_SPI4TEENSY3
spi4teensy3::send(reg);
uint8_t rv = spi4teensy3::receive();
SPI_SS::Set();
#elif !defined(SPDR) || SPI_HAS_TRANSACTION
SPI.transfer(reg);
uint8_t rv = SPI.transfer(0); SPI_SS::Set();
#else
SPDR = reg;
while(!(SPSR & (1 << SPIF)));
SPDR = 0; while(!(SPSR & (1 << SPIF)));
SPI_SS::Set();
uint8_t rv = SPDR;
#endif
#if SPI_HAS_TRANSACTION
SPI.endTransaction();
#endif
XMEM_RELEASE_SPI();
return (rv);
}
template< typename SPI_SS, typename INTR >
uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
XMEM_ACQUIRE_SPI();
#if SPI_HAS_TRANSACTION
SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); #endif
SPI_SS::Clear();
#if USING_SPI4TEENSY3
spi4teensy3::send(reg);
spi4teensy3::receive(data_p, nbytes);
data_p += nbytes;
#elif SPI_HAS_TRANSACTION
SPI.transfer(reg);
memset(data_p, 0, nbytes); SPI.transfer(data_p, nbytes);
data_p += nbytes;
#elif defined(__ARDUINO_X86__)
SPI.transfer(reg);
SPI.transferBuffer(NULL, data_p, nbytes);
data_p += nbytes;
#elif !defined(SPDR)
SPI.transfer(reg);
while(nbytes) {
*data_p++ = SPI.transfer(0);
nbytes--;
}
#else
SPDR = reg;
while(!(SPSR & (1 << SPIF))); while(nbytes) {
SPDR = 0; nbytes--;
while(!(SPSR & (1 << SPIF)));
#if 0#else
*data_p++ = SPDR;
}
#endif
#endif
SPI_SS::Set();
#if SPI_HAS_TRANSACTION
SPI.endTransaction();
#endif
XMEM_RELEASE_SPI();
return ( data_p);
}
template< typename SPI_SS, typename INTR >
uint8_t MAX3421e< SPI_SS, INTR >::gpioRd() {
uint8_t gpin = 0;
gpin = regRd(rIOPINS2); gpin &= 0xf0; gpin |= (regRd(rIOPINS1) >> 4); return ( gpin);
}
template< typename SPI_SS, typename INTR >
uint16_t MAX3421e< SPI_SS, INTR >::reset() {
uint16_t i = 0;
regWr(rUSBCTL, bmCHIPRES);
regWr(rUSBCTL, 0x00);
while(++i) {
if((regRd(rUSBIRQ) & bmOSCOKIRQ)) {
break;
}
}
return ( i);
}
template< typename SPI_SS, typename INTR >
int8_t MAX3421e< SPI_SS, INTR >::Init() {
XMEM_ACQUIRE_SPI();
SPI_SS::SetDirWrite();
SPI_SS::Set();
spi::init();
INTR::SetDirRead();
XMEM_RELEASE_SPI();
regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));
if(reset() == 0) { return ( -1);
}
regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST);
regWr(rHIEN, bmCONDETIE | bmFRAMEIE);
regWr(rHCTL, bmSAMPLEBUS); while(!(regRd(rHCTL) & bmSAMPLEBUS));
busprobe();
regWr(rHIRQ, bmCONDETIRQ); regWr(rCPUCTL, 0x01);
return ( 0);
}
template< typename SPI_SS, typename INTR >
int8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) {
XMEM_ACQUIRE_SPI();
SPI_SS::SetDirWrite();
SPI_SS::Set();
spi::init();
INTR::SetDirRead();
XMEM_RELEASE_SPI();
regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET));
if(reset() == 0) { return ( -1);
}
if(mseconds < 1000) mseconds = 1000;
delay(mseconds);
regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST);
regWr(rHIEN, bmCONDETIE | bmFRAMEIE);
regWr(rHCTL, bmSAMPLEBUS); while(!(regRd(rHCTL) & bmSAMPLEBUS));
busprobe();
regWr(rHIRQ, bmCONDETIRQ); regWr(rCPUCTL, 0x01);
regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));
return ( 0);
}
template< typename SPI_SS, typename INTR >
void MAX3421e< SPI_SS, INTR >::busprobe() {
uint8_t bus_sample;
bus_sample = regRd(rHRSL); bus_sample &= (bmJSTATUS | bmKSTATUS); switch(bus_sample) { case( bmJSTATUS):
if((regRd(rMODE) & bmLOWSPEED) == 0) {
regWr(rMODE, MODE_FS_HOST); vbusState = FSHOST;
} else {
regWr(rMODE, MODE_LS_HOST); vbusState = LSHOST;
}
break;
case( bmKSTATUS):
if((regRd(rMODE) & bmLOWSPEED) == 0) {
regWr(rMODE, MODE_LS_HOST); vbusState = LSHOST;
} else {
regWr(rMODE, MODE_FS_HOST); vbusState = FSHOST;
}
break;
case( bmSE1): vbusState = SE1;
break;
case( bmSE0): regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ);
vbusState = SE0;
break;
}}
template< typename SPI_SS, typename INTR >
uint8_t MAX3421e< SPI_SS, INTR >::Task(void) {
uint8_t rcode = 0;
uint8_t pinvalue;
pinvalue = INTR::IsSet(); if(pinvalue == 0) {
rcode = IntHandler();
}
return ( rcode);
}
template< typename SPI_SS, typename INTR >
uint8_t MAX3421e< SPI_SS, INTR >::IntHandler() {
uint8_t HIRQ;
uint8_t HIRQ_sendback = 0x00;
HIRQ = regRd(rHIRQ); if(HIRQ & bmCONDETIRQ) {
busprobe();
HIRQ_sendback |= bmCONDETIRQ;
}
regWr(rHIRQ, HIRQ_sendback);
return ( HIRQ_sendback);
}
#endif