diff --git a/gpio.h b/gpio.h index 877a2df..e064dfe 100755 --- a/gpio.h +++ b/gpio.h @@ -175,8 +175,8 @@ SetupGpio(22, PortC, NoPwmChannel, 6); SetupGpio(23, PortC, NoPwmChannel, 7); const uint8_t kSpiSlaveSelectPin = 4; -const uint8_t kSpiDataOutPin = 5; -const uint8_t kSpiDataInPin = 6; +const uint8_t kSpiMosiPin = 5; +const uint8_t kSpiMisoPin = 6; const uint8_t kSpiClockPin = 7; #else @@ -204,8 +204,8 @@ SetupGpio(18, PortC, NoPwmChannel, 4); SetupGpio(19, PortC, NoPwmChannel, 5); const uint8_t kSpiSlaveSelectPin = 10; -const uint8_t kSpiDataOutPin = 11; -const uint8_t kSpiDataInPin = 12; +const uint8_t kSpiMosiPin = 11; +const uint8_t kSpiMisoPin = 12; const uint8_t kSpiClockPin = 13; #endif // ATMEGA328P diff --git a/spi.h b/spi.h index 327af1b..09a2417 100644 --- a/spi.h +++ b/spi.h @@ -25,7 +25,6 @@ // around 15 cycles (not including the interrupt prelude/postlude), which is // close to the transmission time at the fastest speed. // - the atmega is always configured as a master. -// - no support for reading back from the slave. #ifndef AVRLIB_SPI_H_ #define AVRLIB_SPI_H_ @@ -42,7 +41,7 @@ typedef BitInRegister<SPSRRegister, SPIF> TransferComplete; template<uint8_t slave_select_pin = 10, DataOrder order = MSB_FIRST, uint8_t speed = 4> -class Spi { +class SPIMaster { public: enum { buffer_size = 0, @@ -105,11 +104,54 @@ class Spi { private: typedef Gpio<slave_select_pin> SlaveSelect; typedef Gpio<kSpiSlaveSelectPin> GlobalSlaveSelect; - typedef Gpio<kSpiDataOutPin> DataOut; - typedef Gpio<kSpiDataInPin> DataIn; + typedef Gpio<kSpiMosiPin> DataOut; + typedef Gpio<kSpiMisoPin> DataIn; typedef Gpio<kSpiClockPin> Clock; }; +template<uint8_t slave_select_pin = 10, + DataOrder order = MSB_FIRST, + bool enable_interrupt = false> +class SPISlave { + public: + enum { + buffer_size = 128, + data_size = 8 + }; + + static void Init() { + Clock::set_mode(DIGITAL_INPUT); + DataIn::set_mode(DIGITAL_INPUT); + DataOut::set_mode(DIGITAL_OUTPUT); + GlobalSlaveSelect::set_mode(DIGITAL_INPUT); // Ohhh mistress, ohhhh! + SlaveSelect::set_mode(DIGITAL_INPUT); + + // SPI enabled, configured as master. + uint8_t configuration = _BV(SPE); + if (order == LSB_FIRST) { + configuration |= _BV(DORD); + } + if (enable_interrupt) { + configuration |= _BV(SPIE); + } + SPCR = configuration; + } + + static inline uint8_t Read(uint8_t v) { + while (!TransferComplete::value()); + return SPDR; + } + + private: + typedef Gpio<slave_select_pin> SlaveSelect; + typedef Gpio<kSpiSlaveSelectPin> GlobalSlaveSelect; + typedef Gpio<kSpiMisoPin> DataOut; + typedef Gpio<kSpiMosiPin> DataIn; + typedef Gpio<kSpiClockPin> Clock; +}; + +#define SPI_RECEIVE ISR(SPI_STC_vect) + } // namespace avrlib #endif AVRLIB_SPI_H_