| 31 | |
| 32 | template <u8 _DATA_PIN, u8 _CLOCK_PIN, u32 _SPI_CLOCK_DIVIDER> |
| 33 | class AVRUSART1SPIOutput { |
| 34 | Selectable *mPSelect; |
| 35 | |
| 36 | public: |
| 37 | AVRUSART1SPIOutput() { mPSelect = nullptr; } |
| 38 | AVRUSART1SPIOutput(Selectable *pSelect) { mPSelect = pSelect; } |
| 39 | void setSelect(Selectable *pSelect) { mPSelect = pSelect; } |
| 40 | |
| 41 | void init() FL_NOEXCEPT { |
| 42 | UBRR1 = 0; |
| 43 | |
| 44 | /* Set MSPI mode of operation and SPI data mode 0. */ |
| 45 | UCSR1C = (1<<UMSEL11)|(1<<UMSEL10)|(0<<UCPHA1)|(0<<UCPOL1); |
| 46 | /* Enable receiver and transmitter. */ |
| 47 | UCSR1B = (1<<RXEN1)|(1<<TXEN1); |
| 48 | |
| 49 | FastPin<_CLOCK_PIN>::setOutput(); |
| 50 | FastPin<_DATA_PIN>::setOutput(); |
| 51 | |
| 52 | // must be done last, see page 206 |
| 53 | setSPIRate(); |
| 54 | } |
| 55 | |
| 56 | void setSPIRate() FL_NOEXCEPT { |
| 57 | if(_SPI_CLOCK_DIVIDER > 2) { |
| 58 | UBRR1 = (_SPI_CLOCK_DIVIDER/2)-1; |
| 59 | } else { |
| 60 | UBRR1 = 0; |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | |
| 65 | static void stop() FL_NOEXCEPT { |
| 66 | // TODO: stop the uart spi output |
| 67 | } |
| 68 | |
| 69 | static bool shouldWait(bool wait = false) FL_NOEXCEPT __attribute__((always_inline)) { |
| 70 | static bool sWait=false; |
| 71 | if(sWait) { |
| 72 | sWait = wait; return true; |
| 73 | } else { |
| 74 | sWait = wait; return false; |
| 75 | } |
| 76 | // return true; |
| 77 | } |
| 78 | static void wait() FL_NOEXCEPT __attribute__((always_inline)) { |
| 79 | if(shouldWait()) { |
| 80 | while(!(UCSR1A & (1<<UDRE1))); |
| 81 | } |
| 82 | } |
| 83 | static void waitFully() __attribute__((always_inline)) { wait(); } |
| 84 | |
| 85 | static void writeWord(u16 w) __attribute__((always_inline)) { writeByte(w>>8); writeByte(w&0xFF); } |
| 86 | |
| 87 | static void writeByte(u8 b) __attribute__((always_inline)) { wait(); UDR1=b; shouldWait(true); } |
| 88 | static void writeBytePostWait(u8 b) __attribute__((always_inline)) { UDR1=b; shouldWait(true); wait(); } |
| 89 | static void writeByteNoWait(u8 b) __attribute__((always_inline)) { UDR1=b; shouldWait(true); } |
| 90 | |