@ -60,184 +60,217 @@
// ------------------------
# if ENABLED(LPC_SOFTWARE_SPI)
# include <SoftwareSPI.h>
# include <SoftwareSPI.h>
// Software SPI
// Software SPI
static uint8_t SPI_speed = 0 ;
static uint8_t SPI_speed = 0 ;
static uint8_t spiTransfer ( uint8_t b ) {
return swSpiTransfer ( b , SPI_speed , SCK_PIN , MISO_PIN , MOSI_PIN ) ;
}
static uint8_t spiTransfer ( uint8_t b )
{
return swSpiTransfer ( b , SPI_speed , SCK_PIN , MISO_PIN , MOSI_PIN ) ;
}
void spiBegin ( ) {
swSpiBegin ( SCK_PIN , MISO_PIN , MOSI_PIN ) ;
}
void spiBegin ( )
{
swSpiBegin ( SCK_PIN , MISO_PIN , MOSI_PIN ) ;
}
void spiInit ( uint8_t spiRate ) {
SPI_speed = swSpiInit ( spiRate , SCK_PIN , MOSI_PIN ) ;
}
void spiInit ( uint8_t spiRate )
{
SPI_speed = swSpiInit ( spiRate , SCK_PIN , MOSI_PIN ) ;
}
uint8_t spiRec ( ) { return spiTransfer ( 0xFF ) ; }
uint8_t spiRec ( ) { return spiTransfer ( 0xFF ) ; }
void spiRead ( uint8_t * buf , uint16_t nbyte ) {
for ( int i = 0 ; i < nbyte ; i + + )
buf [ i ] = spiTransfer ( 0xFF ) ;
}
void spiRead ( uint8_t * buf , uint16_t nbyte )
{
for ( int i = 0 ; i < nbyte ; i + + )
buf [ i ] = spiTransfer ( 0xFF ) ;
}
void spiSend ( uint8_t b ) { ( void ) spiTransfer ( b ) ; }
void spiSend ( uint8_t b ) { ( void ) spiTransfer ( b ) ; }
void spiSend ( const uint8_t * buf , size_t nbyte ) {
for ( uint16_t i = 0 ; i < nbyte ; i + + )
( void ) spiTransfer ( buf [ i ] ) ;
}
void spiSend ( const uint8_t * buf , size_t nbyte )
{
for ( uint16_t i = 0 ; i < nbyte ; i + + )
( void ) spiTransfer ( buf [ i ] ) ;
}
void spiSendBlock ( uint8_t token , const uint8_t * buf ) {
( void ) spiTransfer ( token ) ;
for ( uint16_t i = 0 ; i < 512 ; i + + )
( void ) spiTransfer ( buf [ i ] ) ;
}
void spiSendBlock ( uint8_t token , const uint8_t * buf )
{
( void ) spiTransfer ( token ) ;
for ( uint16_t i = 0 ; i < 512 ; i + + )
( void ) spiTransfer ( buf [ i ] ) ;
}
# else
void spiBegin ( ) { // setup SCK, MOSI & MISO pins for SSP0
spiInit ( SPI_SPEED ) ;
}
void spiBegin ( )
{ // setup SCK, MOSI & MISO pins for SSP0
spiInit ( SPI_SPEED ) ;
}
void spiInit ( uint8_t spiRate ) {
# if MISO_PIN == BOARD_SPI1_MISO_PIN
SPI . setModule ( 1 ) ;
# elif MISO_PIN == BOARD_SPI2_MISO_PIN
SPI . setModule ( 2 ) ;
# endif
SPI . setDataSize ( DATA_SIZE_8BIT ) ;
SPI . setDataMode ( SPI_MODE0 ) ;
SPI . setClock ( SPISettings : : spiRate2Clock ( spiRate ) ) ;
SPI . begin ( ) ;
}
void spiInit ( uint8_t spiRate )
{
# if MISO_PIN == BOARD_SPI1_MISO_PIN
SPI . setModule ( 1 ) ;
# elif MISO_PIN == BOARD_SPI2_MISO_PIN
SPI . setModule ( 2 ) ;
# endif
SPI . setDataSize ( DATA_SIZE_8BIT ) ;
SPI . setDataMode ( SPI_MODE0 ) ;
static uint8_t doio ( uint8_t b ) {
return SPI . transfer ( b & 0x00FF ) & 0x00FF ;
}
SPI . setClock ( SPISettings : : spiRate2Clock ( spiRate ) ) ;
SPI . begin ( ) ;
}
void spiSend ( uint8_t b ) { doio ( b ) ; }
static uint8_t doio ( uint8_t b )
{
return SPI . transfer ( b & 0x00FF ) & 0x00FF ;
}
void spiSend ( const uint8_t * buf , size_t nbyte ) {
for ( uint16_t i = 0 ; i < nbyte ; i + + ) doio ( buf [ i ] ) ;
}
void spiSend ( uint8_t b ) { doio ( b ) ; }
void spiSend ( uint32_t chan , byte b ) {
}
void spiSend ( const uint8_t * buf , size_t nbyte )
{
for ( uint16_t i = 0 ; i < nbyte ; i + + )
doio ( buf [ i ] ) ;
}
void spiSend ( uint32_t chan , const uint8_t * buf , size_t nbyte ) {
}
void spiSend ( uint32_t chan , byte b )
{
}
// Read single byte from SPI
uint8_t spiRec ( ) { return doio ( 0xFF ) ; }
void spiSend ( uint32_t chan , const uint8_t * buf , size_t nbyte )
{
}
uint8_t spiRec ( uint32_t chan ) { return 0 ; }
// Read single byte from SPI
uint8_t spiRec ( ) { return doio ( 0xFF ) ; }
// Read from SPI into buffer
void spiRead ( uint8_t * buf , uint16_t nbyte ) {
for ( uint16_t i = 0 ; i < nbyte ; i + + ) buf [ i ] = doio ( 0xFF ) ;
}
uint8_t spiRec ( uint32_t chan ) { return 0 ; }
uint8_t spiTransfer ( uint8_t b ) {
return doio ( b ) ;
}
// Read from SPI into buffer
void spiRead ( uint8_t * buf , uint16_t nbyte )
{
for ( uint16_t i = 0 ; i < nbyte ; i + + )
buf [ i ] = doio ( 0xFF ) ;
}
// Write from buffer to SPI
void spiSendBlock ( uint8_t token , const uint8_t * buf ) {
( void ) spiTransfer ( token ) ;
for ( uint16_t i = 0 ; i < 512 ; i + + )
( void ) spiTransfer ( buf [ i ] ) ;
}
uint8_t spiTransfer ( uint8_t b )
{
return doio ( b ) ;
}
/** Begin SPI transaction, set clock, bit order, data mode */
void spiBeginTransaction ( uint32_t spiClock , uint8_t bitOrder , uint8_t dataMode ) {
// TODO: to be implemented
// Write from buffer to SPI
void spiSendBlock ( uint8_t token , const uint8_t * buf )
{
( void ) spiTransfer ( token ) ;
for ( uint16_t i = 0 ; i < 512 ; i + + )
( void ) spiTransfer ( buf [ i ] ) ;
}
}
/** Begin SPI transaction, set clock, bit order, data mode */
void spiBeginTransaction ( uint32_t spiClock , uint8_t bitOrder , uint8_t dataMode )
{
// TODO: to be implemented
}
# endif // LPC_SOFTWARE_SPI
/**
* @ brief Wait until TXE ( tx empty ) flag is set and BSY ( busy ) flag unset .
*/
static inline void waitSpiTxEnd ( LPC_SSP_TypeDef * spi_d ) {
while ( SSP_GetStatus ( spi_d , SSP_STAT_TXFIFO_EMPTY ) = = RESET ) { /* nada */ } // wait until TXE=1
while ( SSP_GetStatus ( spi_d , SSP_STAT_BUSY ) = = SET ) { /* nada */ } // wait until BSY=0
static inline void waitSpiTxEnd ( LPC_SSP_TypeDef * spi_d )
{
while ( SSP_GetStatus ( spi_d , SSP_STAT_TXFIFO_EMPTY ) = = RESET )
{ /* nada */
} // wait until TXE=1
while ( SSP_GetStatus ( spi_d , SSP_STAT_BUSY ) = = SET )
{ /* nada */
} // wait until BSY=0
}
SPIClass : : SPIClass ( uint8_t device ) {
// Hold the pin init state of the SPI, to avoid init more than once,
//even if more instances of SPIClass exist
static bool spiInitialised [ BOARD_NR_SPI ] = { false } ;
SPIClass : : SPIClass ( uint8_t device )
{
// Init things specific to each SPI device
// clock divider setup is a bit of hack, and needs to be improved at a later date.
PINSEL_CFG_Type PinCfg ; // data structure to hold init values
# if BOARD_NR_SPI >= 1
_settings [ 0 ] . spi_d = LPC_SSP0 ;
_settings [ 0 ] . dataMode = SPI_MODE0 ;
_settings [ 0 ] . dataSize = DATA_SIZE_8BIT ;
_settings [ 0 ] . clock = SPI_CLOCK_MAX ;
// _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
PinCfg . Funcnum = 2 ;
PinCfg . OpenDrain = 0 ;
PinCfg . Pinmode = 0 ;
PinCfg . Pinnum = LPC176x : : pin_bit ( BOARD_SPI1_SCK_PIN ) ;
PinCfg . Portnum = LPC176x : : pin_port ( BOARD_SPI1_SCK_PIN ) ;
PINSEL_ConfigPin ( & PinCfg ) ;
SET_OUTPUT ( BOARD_SPI1_SCK_PIN ) ;
# if BOARD_NR_SPI >= 1
_settings [ 0 ] . spi_d = LPC_SSP0 ;
_settings [ 0 ] . dataMode = SPI_MODE0 ;
_settings [ 0 ] . dataSize = DATA_SIZE_8BIT ;
_settings [ 0 ] . clock = SPI_CLOCK_MAX ;
// _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
# endif
PinCfg . Pinnum = LPC176x : : pin_bit ( BOARD_SPI1_MISO_PIN ) ;
PinCfg . Portnum = LPC176x : : pin_port ( BOARD_SPI1_MISO_PIN ) ;
PINSEL_ConfigPin ( & PinCfg ) ;
SET_INPUT ( BOARD_SPI1_MISO_PIN ) ;
# if BOARD_NR_SPI >= 2
_settings [ 1 ] . spi_d = LPC_SSP1 ;
_settings [ 1 ] . dataMode = SPI_MODE0 ;
_settings [ 1 ] . dataSize = DATA_SIZE_8BIT ;
_settings [ 1 ] . clock = SPI_CLOCK_MAX ;
// _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
# endif
PinCfg . Pinnum = LPC176x : : pin_bit ( BOARD_SPI1_MOSI_PIN ) ;
PinCfg . Portnum = LPC176x : : pin_port ( BOARD_SPI1_MOSI_PIN ) ;
PINSEL_ConfigPin ( & PinCfg ) ;
SET_OUTPUT ( BOARD_SPI1_MOSI_PIN ) ;
# endif
# if BOARD_NR_SPI >= 2
_settings [ 1 ] . spi_d = LPC_SSP1 ;
_settings [ 1 ] . dataMode = SPI_MODE0 ;
_settings [ 1 ] . dataSize = DATA_SIZE_8BIT ;
_settings [ 1 ] . clock = SPI_CLOCK_MAX ;
// _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
setModule ( device ) ;
/* Initialize GPDMA controller */
//TODO: call once in the constructor? or each time?
GPDMA_Init ( ) ;
}
void SPIClass : : begin ( )
{
// Init the SPI pins in the firt begin call
if ( ( _currentSetting - > spi_d = = LPC_SSP0 & & spiInitialised [ 0 ] = = false ) | |
( _currentSetting - > spi_d = = LPC_SSP1 & & spiInitialised [ 1 ] = = false ) )
{
pin_t sck , miso , mosi ;
if ( _currentSetting - > spi_d = = LPC_SSP0 )
{
sck = BOARD_SPI1_SCK_PIN ;
miso = BOARD_SPI1_MISO_PIN ;
mosi = BOARD_SPI1_MOSI_PIN ;
spiInitialised [ 0 ] = true ;
}
else if ( _currentSetting - > spi_d = = LPC_SSP0 )
{
sck = BOARD_SPI2_SCK_PIN ;
miso = BOARD_SPI2_MISO_PIN ;
mosi = BOARD_SPI2_MOSI_PIN ;
spiInitialised [ 1 ] = true ;
}
PINSEL_CFG_Type PinCfg ; // data structure to hold init values
PinCfg . Funcnum = 2 ;
PinCfg . OpenDrain = 0 ;
PinCfg . Pinmode = 0 ;
PinCfg . Pinnum = LPC176x : : pin_bit ( BOARD_SPI2_SCK_PIN ) ;
PinCfg . Portnum = LPC176x : : pin_port ( BOARD_SPI2_SCK_PIN ) ;
PinCfg . Pinnum = LPC176x : : pin_bit ( sck ) ;
PinCfg . Portnum = LPC176x : : pin_port ( sck ) ;
PINSEL_ConfigPin ( & PinCfg ) ;
SET_OUTPUT ( BOARD_SPI2_SCK_PIN ) ;
SET_OUTPUT ( sck ) ;
PinCfg . Pinnum = LPC176x : : pin_bit ( BOARD_SPI2_MISO_PIN ) ;
PinCfg . Portnum = LPC176x : : pin_port ( BOARD_SPI2_MISO_PIN ) ;
PinCfg . Pinnum = LPC176x : : pin_bit ( miso ) ;
PinCfg . Portnum = LPC176x : : pin_port ( miso ) ;
PINSEL_ConfigPin ( & PinCfg ) ;
SET_INPUT ( BOARD_SPI2_MISO_PIN ) ;
SET_INPUT ( miso ) ;
PinCfg . Pinnum = LPC176x : : pin_bit ( BOARD_SPI2_MOSI_PIN ) ;
PinCfg . Portnum = LPC176x : : pin_port ( BOARD_SPI2_MOSI_PIN ) ;
PinCfg . Pinnum = LPC176x : : pin_bit ( mosi ) ;
PinCfg . Portnum = LPC176x : : pin_port ( mosi ) ;
PINSEL_ConfigPin ( & PinCfg ) ;
SET_OUTPUT ( BOARD_SPI2_MOSI_PIN ) ;
# endif
setModule ( device ) ;
/* Initialize GPDMA controller */
//TODO: call once in the constructor? or each time?
GPDMA_Init ( ) ;
}
SET_OUTPUT ( mosi ) ;
}
void SPIClass : : begin ( ) {
updateSettings ( ) ;
SSP_Cmd ( _currentSetting - > spi_d , ENABLE ) ; // start SSP running
SSP_Cmd ( _currentSetting - > spi_d , ENABLE ) ; // start SSP running
}
void SPIClass : : beginTransaction ( const SPISettings & cfg ) {
void SPIClass : : beginTransaction ( const SPISettings & cfg )
{
setBitOrder ( cfg . bitOrder ) ;
setDataMode ( cfg . dataMode ) ;
setDataSize ( cfg . dataSize ) ;
@ -245,29 +278,33 @@ void SPIClass::beginTransaction(const SPISettings &cfg) {
begin ( ) ;
}
uint8_t SPIClass : : transfer ( const uint16_t b ) {
uint8_t SPIClass : : transfer ( const uint16_t b )
{
/* send and receive a single byte */
SSP_ReceiveData ( _currentSetting - > spi_d ) ; // read any previous data
SSP_SendData ( _currentSetting - > spi_d , b ) ;
waitSpiTxEnd ( _currentSetting - > spi_d ) ; // wait for it to finish
waitSpiTxEnd ( _currentSetting - > spi_d ) ; // wait for it to finish
return SSP_ReceiveData ( _currentSetting - > spi_d ) ;
}
uint16_t SPIClass : : transfer16 ( const uint16_t data ) {
return ( transfer ( ( data > > 8 ) & 0xFF ) < < 8 )
| ( transfer ( data & 0xFF ) & 0xFF ) ;
uint16_t SPIClass : : transfer16 ( const uint16_t data )
{
return ( transfer ( ( data > > 8 ) & 0xFF ) < < 8 ) | ( transfer ( data & 0xFF ) & 0xFF ) ;
}
void SPIClass : : end ( ) {
void SPIClass : : end ( )
{
// SSP_Cmd(_currentSetting->spi_d, DISABLE); // stop device or SSP_DeInit?
SSP_DeInit ( _currentSetting - > spi_d ) ;
}
void SPIClass : : send ( uint8_t data ) {
void SPIClass : : send ( uint8_t data )
{
SSP_SendData ( _currentSetting - > spi_d , data ) ;
}
void SPIClass : : dmaSend ( void * buf , uint16_t length , bool minc ) {
void SPIClass : : dmaSend ( void * buf , uint16_t length , bool minc )
{
//TODO: LPC dma can only write 0xFFF bytes at once.
GPDMA_Channel_CFG_Type GPDMACfg ;
@ -304,11 +341,13 @@ void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
GPDMA_ChannelCmd ( 0 , ENABLE ) ;
// wait data transfer
while ( ! GPDMA_IntGetStatus ( GPDMA_STAT_RAWINTTC , 0 ) & & ! GPDMA_IntGetStatus ( GPDMA_STAT_RAWINTERR , 0 ) ) { }
while ( ! GPDMA_IntGetStatus ( GPDMA_STAT_RAWINTTC , 0 ) & & ! GPDMA_IntGetStatus ( GPDMA_STAT_RAWINTERR , 0 ) )
{
}
// clear err and int
GPDMA_ClearIntPending ( GPDMA_STATCLR_INTTC , 0 ) ;
GPDMA_ClearIntPending ( GPDMA_STATCLR_INTERR , 0 ) ;
GPDMA_ClearIntPending ( GPDMA_STATCLR_INTTC , 0 ) ;
GPDMA_ClearIntPending ( GPDMA_STATCLR_INTERR , 0 ) ;
// dma disable
GPDMA_ChannelCmd ( 0 , DISABLE ) ;
@ -318,45 +357,54 @@ void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
SSP_DMACmd ( _currentSetting - > spi_d , SSP_DMA_TX , DISABLE ) ;
}
uint16_t SPIClass : : read ( ) {
uint16_t SPIClass : : read ( )
{
return SSP_ReceiveData ( _currentSetting - > spi_d ) ;
}
void SPIClass : : read ( uint8_t * buf , uint32_t len ) {
for ( uint16_t i = 0 ; i < len ; i + + ) buf [ i ] = transfer ( 0xFF ) ;
void SPIClass : : read ( uint8_t * buf , uint32_t len )
{
for ( uint16_t i = 0 ; i < len ; i + + )
buf [ i ] = transfer ( 0xFF ) ;
}
void SPIClass : : setClock ( uint32_t clock ) {
void SPIClass : : setClock ( uint32_t clock )
{
_currentSetting - > clock = clock ;
}
void SPIClass : : setModule ( uint8_t device ) {
_currentSetting = & _settings [ device - 1 ] ; // SPI channels are called 1 2 and 3 but the array is zero indexed
void SPIClass : : setModule ( uint8_t device )
{
_currentSetting = & _settings [ device - 1 ] ; // SPI channels are called 1 2 and 3 but the array is zero indexed
}
void SPIClass : : setBitOrder ( uint8_t bitOrder ) {
void SPIClass : : setBitOrder ( uint8_t bitOrder )
{
_currentSetting - > bitOrder = bitOrder ;
}
void SPIClass : : setDataMode ( uint8_t dataMode ) {
void SPIClass : : setDataMode ( uint8_t dataMode )
{
_currentSetting - > dataMode = dataMode ;
}
void SPIClass : : setDataSize ( uint32_t ds ) {
void SPIClass : : setDataSize ( uint32_t ds )
{
_currentSetting - > dataSize = ds ;
}
/**
* Set up / tear down
*/
void SPIClass : : updateSettings ( ) {
void SPIClass : : updateSettings ( )
{
//SSP_DeInit(_currentSetting->spi_d); //todo: need force de init?!
// divide PCLK by 2 for SSP0
CLKPWR_SetPCLKDiv ( _currentSetting - > spi_d = = LPC_SSP0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1 , CLKPWR_PCLKSEL_CCLK_DIV_2 ) ;
SSP_CFG_Type HW_SPI_init ; // data structure to hold init values
SSP_ConfigStructInit ( & HW_SPI_init ) ; // set values for SPI mode
SSP_CFG_Type HW_SPI_init ; // data structure to hold init values
SSP_ConfigStructInit ( & HW_SPI_init ) ; // set values for SPI mode
HW_SPI_init . ClockRate = _currentSetting - > clock ;
HW_SPI_init . Databit = _currentSetting - > dataSize ;
@ -367,35 +415,36 @@ void SPIClass::updateSettings() {
* 2 1 0 Rising Falling
* 3 1 1 Falling Rising
*/
switch ( _currentSetting - > dataMode ) {
case SPI_MODE0 :
HW_SPI_init . CPHA = SSP_CPHA_FIRST ;
HW_SPI_init . CPOL = SSP_CPOL_HI ;
break ;
case SPI_MODE1 :
HW_SPI_init . CPHA = SSP_CPHA_SECOND ;
HW_SPI_init . CPOL = SSP_CPOL_HI ;
break ;
case SPI_MODE2 :
HW_SPI_init . CPHA = SSP_CPHA_FIRST ;
HW_SPI_init . CPOL = SSP_CPOL_LO ;
break ;
case SPI_MODE3 :
HW_SPI_init . CPHA = SSP_CPHA_SECOND ;
HW_SPI_init . CPOL = SSP_CPOL_LO ;
break ;
default :
break ;
switch ( _currentSetting - > dataMode )
{
case SPI_MODE0 :
HW_SPI_init . CPHA = SSP_CPHA_FIRST ;
HW_SPI_init . CPOL = SSP_CPOL_HI ;
break ;
case SPI_MODE1 :
HW_SPI_init . CPHA = SSP_CPHA_SECOND ;
HW_SPI_init . CPOL = SSP_CPOL_HI ;
break ;
case SPI_MODE2 :
HW_SPI_init . CPHA = SSP_CPHA_FIRST ;
HW_SPI_init . CPOL = SSP_CPOL_LO ;
break ;
case SPI_MODE3 :
HW_SPI_init . CPHA = SSP_CPHA_SECOND ;
HW_SPI_init . CPOL = SSP_CPOL_LO ;
break ;
default :
break ;
}
// TODO: handle bitOrder
SSP_Init ( _currentSetting - > spi_d , & HW_SPI_init ) ; // puts the values into the proper bits in the SSP0 registers
SSP_Init ( _currentSetting - > spi_d , & HW_SPI_init ) ; // puts the values into the proper bits in the SSP0 registers
}
# if MISO_PIN == BOARD_SPI1_MISO_PIN
SPIClass SPI ( 1 ) ;
SPIClass SPI ( 1 ) ;
# elif MISO_PIN == BOARD_SPI2_MISO_PIN
SPIClass SPI ( 2 ) ;
SPIClass SPI ( 2 ) ;
# endif
# endif // TARGET_LPC1768