2011-06-21 00:03:22 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
|
|
|
* SPI Master library for arduino.
|
|
|
|
*
|
|
|
|
* This file is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of either the GNU General Public License version 2
|
|
|
|
* or the GNU Lesser General Public License version 2.1, both as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "SPI.h"
|
|
|
|
|
2012-05-18 01:30:54 +02:00
|
|
|
SPIClass::SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void)) :
|
2012-04-24 09:31:50 +02:00
|
|
|
spi(_spi), id(_id), initCb(_initCb)
|
|
|
|
{
|
2011-12-05 19:21:19 +01:00
|
|
|
initCb();
|
|
|
|
|
2012-06-08 22:34:38 +02:00
|
|
|
SPI_Configure(spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
|
2012-04-24 09:31:50 +02:00
|
|
|
SPI_Enable(spi);
|
|
|
|
}
|
|
|
|
|
2012-06-09 15:02:51 +02:00
|
|
|
void SPIClass::begin() {
|
|
|
|
// NPCS control is left to the user
|
|
|
|
|
2012-08-13 16:58:19 +02:00
|
|
|
// Default speed set to 4Mhz
|
|
|
|
setClockDivider(BOARD_SPI_DEFAULT_SS, 21);
|
2012-06-09 15:02:51 +02:00
|
|
|
setDataMode(BOARD_SPI_DEFAULT_SS, SPI_MODE0);
|
2012-08-24 15:23:50 +02:00
|
|
|
setBitOrder(BOARD_SPI_DEFAULT_SS, MSBFIRST);
|
2012-06-09 15:02:51 +02:00
|
|
|
}
|
|
|
|
|
2012-05-18 01:30:54 +02:00
|
|
|
void SPIClass::begin(uint8_t _pin) {
|
2012-06-08 22:34:38 +02:00
|
|
|
uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
|
2012-06-03 23:35:08 +02:00
|
|
|
PIO_Configure(
|
2012-06-08 22:34:38 +02:00
|
|
|
g_APinDescription[spiPin].pPort,
|
|
|
|
g_APinDescription[spiPin].ulPinType,
|
|
|
|
g_APinDescription[spiPin].ulPin,
|
|
|
|
g_APinDescription[spiPin].ulPinConfiguration);
|
2012-08-24 15:23:50 +02:00
|
|
|
|
|
|
|
// Default speed set to 500Khz
|
|
|
|
setClockDivider(_pin, 168);
|
2012-06-03 23:35:08 +02:00
|
|
|
setDataMode(_pin, SPI_MODE0);
|
2012-08-24 15:23:50 +02:00
|
|
|
setBitOrder(_pin, MSBFIRST);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SPIClass::end(uint8_t _pin) {
|
|
|
|
uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
|
|
|
|
// Setting the pin as INPUT will disconnect it from SPI peripheral
|
|
|
|
pinMode(spiPin, INPUT);
|
2011-06-21 00:03:22 +02:00
|
|
|
}
|
|
|
|
|
2011-12-02 16:29:50 +01:00
|
|
|
void SPIClass::end() {
|
2012-04-24 09:31:50 +02:00
|
|
|
SPI_Disable(spi);
|
2011-06-21 00:03:22 +02:00
|
|
|
}
|
|
|
|
|
2012-08-24 15:23:50 +02:00
|
|
|
void SPIClass::setBitOrder(uint8_t _pin, BitOrder _bitOrder) {
|
|
|
|
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
|
|
|
|
bitOrder[ch] = _bitOrder;
|
|
|
|
}
|
2011-06-21 00:03:22 +02:00
|
|
|
|
2012-05-18 01:30:54 +02:00
|
|
|
void SPIClass::setDataMode(uint8_t _pin, uint8_t _mode) {
|
2012-08-24 15:23:50 +02:00
|
|
|
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
|
|
|
|
mode[ch] = _mode | SPI_CSR_CSAAT;
|
2012-06-08 22:51:03 +02:00
|
|
|
// SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed
|
|
|
|
// transfer. Some device needs that for working properly.
|
2012-08-24 15:23:50 +02:00
|
|
|
SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1));
|
2011-06-21 00:03:22 +02:00
|
|
|
}
|
|
|
|
|
2012-05-18 01:30:54 +02:00
|
|
|
void SPIClass::setClockDivider(uint8_t _pin, uint8_t _divider) {
|
2012-08-24 15:23:50 +02:00
|
|
|
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
|
|
|
|
divider[ch] = _divider;
|
2012-06-08 22:51:03 +02:00
|
|
|
// SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed
|
|
|
|
// transfer. Some device needs that for working properly.
|
2012-08-24 15:23:50 +02:00
|
|
|
SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1));
|
2012-04-24 09:31:50 +02:00
|
|
|
}
|
|
|
|
|
2012-05-18 01:30:54 +02:00
|
|
|
byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {
|
2012-08-24 15:23:50 +02:00
|
|
|
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
|
|
|
|
// Reverse bit order
|
|
|
|
if (bitOrder[ch] == LSBFIRST)
|
|
|
|
_data = __REV(__RBIT(_data));
|
|
|
|
uint32_t d = _data | SPI_PCS(ch);
|
2012-05-18 01:30:54 +02:00
|
|
|
if (_mode == SPI_LAST)
|
2012-04-24 09:31:50 +02:00
|
|
|
d |= SPI_TDR_LASTXFER;
|
|
|
|
|
|
|
|
// SPI_Write(spi, _channel, _data);
|
|
|
|
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
|
|
|
|
;
|
|
|
|
spi->SPI_TDR = d;
|
|
|
|
|
|
|
|
// return SPI_Read(spi);
|
|
|
|
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
|
|
|
|
;
|
|
|
|
d = spi->SPI_RDR;
|
2012-08-24 15:23:50 +02:00
|
|
|
// Reverse bit order
|
|
|
|
if (bitOrder[ch] == LSBFIRST)
|
|
|
|
d = __REV(__RBIT(d));
|
2012-04-24 09:31:50 +02:00
|
|
|
return d & 0xFF;
|
2011-10-11 20:46:18 +02:00
|
|
|
}
|
|
|
|
|
2011-12-02 16:29:50 +01:00
|
|
|
void SPIClass::attachInterrupt(void) {
|
|
|
|
// Should be enableInterrupt()
|
2011-10-11 20:46:18 +02:00
|
|
|
}
|
|
|
|
|
2011-12-02 16:29:50 +01:00
|
|
|
void SPIClass::detachInterrupt(void) {
|
|
|
|
// Should be disableInterrupt()
|
2011-10-11 20:46:18 +02:00
|
|
|
}
|
2011-12-02 16:29:50 +01:00
|
|
|
|
|
|
|
#if SPI_INTERFACES_COUNT > 0
|
2012-04-23 15:50:30 +02:00
|
|
|
static void SPI_0_Init(void) {
|
2012-06-03 23:35:08 +02:00
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[PIN_SPI_MOSI].pPort,
|
2011-12-05 19:21:19 +01:00
|
|
|
g_APinDescription[PIN_SPI_MOSI].ulPinType,
|
|
|
|
g_APinDescription[PIN_SPI_MOSI].ulPin,
|
|
|
|
g_APinDescription[PIN_SPI_MOSI].ulPinConfiguration);
|
2012-06-03 23:35:08 +02:00
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[PIN_SPI_MISO].pPort,
|
2011-12-05 19:21:19 +01:00
|
|
|
g_APinDescription[PIN_SPI_MISO].ulPinType,
|
|
|
|
g_APinDescription[PIN_SPI_MISO].ulPin,
|
|
|
|
g_APinDescription[PIN_SPI_MISO].ulPinConfiguration);
|
2012-06-03 23:35:08 +02:00
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[PIN_SPI_SCK].pPort,
|
2011-12-05 19:21:19 +01:00
|
|
|
g_APinDescription[PIN_SPI_SCK].ulPinType,
|
|
|
|
g_APinDescription[PIN_SPI_SCK].ulPin,
|
|
|
|
g_APinDescription[PIN_SPI_SCK].ulPinConfiguration);
|
|
|
|
}
|
|
|
|
|
2012-05-18 01:30:54 +02:00
|
|
|
SPIClass SPI(SPI_INTERFACE, SPI_INTERFACE_ID, SPI_0_Init);
|
2011-12-02 16:29:50 +01:00
|
|
|
#endif
|