|
| 1 | +/* |
| 2 | + * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st> |
| 3 | + * SPI Master library for arduino. |
| 4 | + * |
| 5 | + * This file is free software; you can redistribute it and/or modify |
| 6 | + * it under the terms of either the GNU General Public License version 2 |
| 7 | + * or the GNU Lesser General Public License version 2.1, both as |
| 8 | + * published by the Free Software Foundation. |
| 9 | + */ |
| 10 | + |
| 11 | +#include "SPI_Class.h" |
| 12 | + |
| 13 | +SPIClass::SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void)) : |
| 14 | + spi(_spi), id(_id), initCb(_initCb) |
| 15 | +{ |
| 16 | + // Empty |
| 17 | +} |
| 18 | + |
| 19 | +void SPIClass::begin() { |
| 20 | + initCb(); |
| 21 | + SPI_Configure(spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS); |
| 22 | + SPI_Enable(spi); |
| 23 | + |
| 24 | + // NPCS control is left to the user |
| 25 | + |
| 26 | + // Default speed set to 4Mhz |
| 27 | + setClockDivider(BOARD_SPI_DEFAULT_SS, 21); |
| 28 | + setDataMode(BOARD_SPI_DEFAULT_SS, SPI_MODE0); |
| 29 | + setBitOrder(BOARD_SPI_DEFAULT_SS, MSBFIRST); |
| 30 | +} |
| 31 | + |
| 32 | +void SPIClass::begin(uint8_t _pin) { |
| 33 | + uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin); |
| 34 | + PIO_Configure( |
| 35 | + g_APinDescription[spiPin].pPort, |
| 36 | + g_APinDescription[spiPin].ulPinType, |
| 37 | + g_APinDescription[spiPin].ulPin, |
| 38 | + g_APinDescription[spiPin].ulPinConfiguration); |
| 39 | + |
| 40 | + // Default speed set to 4Mhz |
| 41 | + setClockDivider(_pin, 21); |
| 42 | + setDataMode(_pin, SPI_MODE0); |
| 43 | + setBitOrder(_pin, MSBFIRST); |
| 44 | +} |
| 45 | + |
| 46 | +void SPIClass::end(uint8_t _pin) { |
| 47 | + uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin); |
| 48 | + // Setting the pin as INPUT will disconnect it from SPI peripheral |
| 49 | + pinMode(spiPin, INPUT); |
| 50 | +} |
| 51 | + |
| 52 | +void SPIClass::end() { |
| 53 | + SPI_Disable(spi); |
| 54 | +} |
| 55 | + |
| 56 | +void SPIClass::setBitOrder(uint8_t _pin, BitOrder _bitOrder) { |
| 57 | + uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); |
| 58 | + bitOrder[ch] = _bitOrder; |
| 59 | +} |
| 60 | + |
| 61 | +void SPIClass::setDataMode(uint8_t _pin, uint8_t _mode) { |
| 62 | + uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); |
| 63 | + mode[ch] = _mode | SPI_CSR_CSAAT; |
| 64 | + // SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed |
| 65 | + // transfer. Some device needs that for working properly. |
| 66 | + SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1)); |
| 67 | +} |
| 68 | + |
| 69 | +void SPIClass::setClockDivider(uint8_t _pin, uint8_t _divider) { |
| 70 | + uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); |
| 71 | + divider[ch] = _divider; |
| 72 | + // SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed |
| 73 | + // transfer. Some device needs that for working properly. |
| 74 | + SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1)); |
| 75 | +} |
| 76 | + |
| 77 | +byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) { |
| 78 | + uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); |
| 79 | + // Reverse bit order |
| 80 | + if (bitOrder[ch] == LSBFIRST) |
| 81 | + _data = __REV(__RBIT(_data)); |
| 82 | + uint32_t d = _data | SPI_PCS(ch); |
| 83 | + if (_mode == SPI_LAST) |
| 84 | + d |= SPI_TDR_LASTXFER; |
| 85 | + |
| 86 | + // SPI_Write(spi, _channel, _data); |
| 87 | + while ((spi->SPI_SR & SPI_SR_TDRE) == 0) |
| 88 | + ; |
| 89 | + spi->SPI_TDR = d; |
| 90 | + |
| 91 | + // return SPI_Read(spi); |
| 92 | + while ((spi->SPI_SR & SPI_SR_RDRF) == 0) |
| 93 | + ; |
| 94 | + d = spi->SPI_RDR; |
| 95 | + // Reverse bit order |
| 96 | + if (bitOrder[ch] == LSBFIRST) |
| 97 | + d = __REV(__RBIT(d)); |
| 98 | + return d & 0xFF; |
| 99 | +} |
| 100 | + |
| 101 | +void SPIClass::attachInterrupt(void) { |
| 102 | + // Should be enableInterrupt() |
| 103 | +} |
| 104 | + |
| 105 | +void SPIClass::detachInterrupt(void) { |
| 106 | + // Should be disableInterrupt() |
| 107 | +} |
| 108 | + |
| 109 | +#if SPI_INTERFACES_COUNT > 0 |
| 110 | +static void SPI_0_Init(void) { |
| 111 | + PIO_Configure( |
| 112 | + g_APinDescription[PIN_SPI_MOSI].pPort, |
| 113 | + g_APinDescription[PIN_SPI_MOSI].ulPinType, |
| 114 | + g_APinDescription[PIN_SPI_MOSI].ulPin, |
| 115 | + g_APinDescription[PIN_SPI_MOSI].ulPinConfiguration); |
| 116 | + PIO_Configure( |
| 117 | + g_APinDescription[PIN_SPI_MISO].pPort, |
| 118 | + g_APinDescription[PIN_SPI_MISO].ulPinType, |
| 119 | + g_APinDescription[PIN_SPI_MISO].ulPin, |
| 120 | + g_APinDescription[PIN_SPI_MISO].ulPinConfiguration); |
| 121 | + PIO_Configure( |
| 122 | + g_APinDescription[PIN_SPI_SCK].pPort, |
| 123 | + g_APinDescription[PIN_SPI_SCK].ulPinType, |
| 124 | + g_APinDescription[PIN_SPI_SCK].ulPin, |
| 125 | + g_APinDescription[PIN_SPI_SCK].ulPinConfiguration); |
| 126 | +} |
| 127 | + |
| 128 | +SPIClass SPI(SPI_INTERFACE, SPI_INTERFACE_ID, SPI_0_Init); |
| 129 | +#endif |
0 commit comments