| class SPCR1emulation | class SPCR1emulation | ||||
| { | { | ||||
| public: | public: | ||||
| inline SPCR1emulation & operator = (int val) __attribute__((always_inline)) { | |||||
| uint32_t ctar, mcr, sim6; | |||||
| //serial_print("SPCR="); | |||||
| //serial_phex(val); | |||||
| //serial_print("\n"); | |||||
| sim6 = SIM_SCGC6; | |||||
| if (!(sim6 & SIM_SCGC6_SPI1)) { | |||||
| //serial_print("init1\n"); | |||||
| SIM_SCGC6 = sim6 | SIM_SCGC6_SPI1; | |||||
| SPI1_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1); | |||||
| } | |||||
| if (!(val & (1<<SPE))) { | |||||
| SPI1_MCR |= SPI_MCR_MDIS; // TODO: use bitband for atomic access | |||||
| } | |||||
| ctar = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1); | |||||
| if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE; | |||||
| if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL; | |||||
| if (val & (1<<CPHA)) { | |||||
| ctar |= SPI_CTAR_CPHA; | |||||
| if ((val & 3) == 0) { | |||||
| ctar |= SPI_CTAR_BR(1) | SPI_CTAR_ASC(1); | |||||
| } else if ((val & 3) == 1) { | |||||
| ctar |= SPI_CTAR_BR(4) | SPI_CTAR_ASC(4); | |||||
| } else if ((val & 3) == 2) { | |||||
| ctar |= SPI_CTAR_BR(6) | SPI_CTAR_ASC(6); | |||||
| } else { | |||||
| ctar |= SPI_CTAR_BR(7) | SPI_CTAR_ASC(7); | |||||
| } | |||||
| } else { | |||||
| if ((val & 3) == 0) { | |||||
| ctar |= SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1); | |||||
| } else if ((val & 3) == 1) { | |||||
| ctar |= SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(4); | |||||
| } else if ((val & 3) == 2) { | |||||
| ctar |= SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(6); | |||||
| } else { | |||||
| ctar |= SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(7); | |||||
| } | |||||
| } | |||||
| ctar |= (SPI1_CTAR0 & SPI_CTAR_DBR); | |||||
| update_ctar(ctar); | |||||
| mcr = SPI_MCR_DCONF(0) | SPI_MCR_PCSIS(0x1F); | |||||
| if (val & (1<<MSTR)) mcr |= SPI_MCR_MSTR; | |||||
| if (val & (1<<SPE)) { | |||||
| mcr &= ~(SPI_MCR_MDIS | SPI_MCR_HALT); | |||||
| SPI1_MCR = mcr; | |||||
| enable_pins(); | |||||
| } else { | |||||
| mcr |= (SPI_MCR_MDIS | SPI_MCR_HALT); | |||||
| SPI1_MCR = mcr; | |||||
| disable_pins(); | |||||
| } | |||||
| //serial_print("MCR:"); | |||||
| //serial_phex32(SPI1_MCR); | |||||
| //serial_print(", CTAR0:"); | |||||
| //serial_phex32(SPI1_CTAR0); | |||||
| //serial_print("\n"); | |||||
| return *this; | |||||
| } | |||||
| inline SPCR1emulation & operator |= (int val) __attribute__((always_inline)) { | |||||
| uint32_t sim6; | |||||
| //serial_print("SPCR |= "); | |||||
| //serial_phex(val); | |||||
| //serial_print("\n"); | |||||
| sim6 = SIM_SCGC6; | |||||
| if (!(sim6 & SIM_SCGC6_SPI1)) { | |||||
| //serial_print("init2\n"); | |||||
| SIM_SCGC6 = sim6 | SIM_SCGC6_SPI1; | |||||
| SPI1_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1); | |||||
| } | |||||
| if (val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) { | |||||
| uint32_t ctar = SPI1_CTAR0; | |||||
| if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE; // TODO: use bitband | |||||
| if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL; | |||||
| if ((val & 3) == 1) { | |||||
| // TODO: implement - is this ever really needed | |||||
| } else if ((val & 3) == 2) { | |||||
| // TODO: implement - is this ever really needed | |||||
| } else if ((val & 3) == 3) { | |||||
| // TODO: implement - is this ever really needed | |||||
| } | |||||
| if (val & (1<<CPHA) && !(ctar & SPI_CTAR_CPHA)) { | |||||
| ctar |= SPI_CTAR_CPHA; | |||||
| // TODO: clear SPI_CTAR_CSSCK, set SPI_CTAR_ASC | |||||
| } | |||||
| update_ctar(ctar); | |||||
| } | |||||
| if (val & (1<<MSTR)) SPI1_MCR |= SPI_MCR_MSTR; | |||||
| if (val & (1<<SPE)) { | |||||
| SPI1_MCR &= ~(SPI_MCR_MDIS | SPI_MCR_HALT); | |||||
| enable_pins(); | |||||
| } | |||||
| //serial_print("MCR:"); | |||||
| //serial_phex32(SPI1_MCR); | |||||
| //serial_print(", CTAR0:"); | |||||
| //serial_phex32(SPI1_CTAR0); | |||||
| //serial_print("\n"); | |||||
| return *this; | |||||
| } | |||||
| inline SPCR1emulation & operator &= (int val) __attribute__((always_inline)) { | |||||
| //serial_print("SPCR &= "); | |||||
| //serial_phex(val); | |||||
| //serial_print("\n"); | |||||
| SIM_SCGC6 |= SIM_SCGC6_SPI1; | |||||
| if (!(val & (1<<SPE))) { | |||||
| SPI1_MCR |= (SPI_MCR_MDIS | SPI_MCR_HALT); | |||||
| disable_pins(); | |||||
| } | |||||
| if ((val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) != ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) { | |||||
| uint32_t ctar = SPI1_CTAR0; | |||||
| if (!(val & (1<<DORD))) ctar &= ~SPI_CTAR_LSBFE; // TODO: use bitband | |||||
| if (!(val & (1<<CPOL))) ctar &= ~SPI_CTAR_CPOL; | |||||
| if ((val & 3) == 0) { | |||||
| // TODO: implement - is this ever really needed | |||||
| } else if ((val & 3) == 1) { | |||||
| // TODO: implement - is this ever really needed | |||||
| } else if ((val & 3) == 2) { | |||||
| // TODO: implement - is this ever really needed | |||||
| } | |||||
| if (!(val & (1<<CPHA)) && (ctar & SPI_CTAR_CPHA)) { | |||||
| ctar &= ~SPI_CTAR_CPHA; | |||||
| // TODO: set SPI_CTAR_ASC, clear SPI_CTAR_CSSCK | |||||
| } | |||||
| update_ctar(ctar); | |||||
| } | |||||
| if (!(val & (1<<MSTR))) SPI1_MCR &= ~SPI_MCR_MSTR; | |||||
| return *this; | |||||
| } | |||||
| inline int operator & (int val) const __attribute__((always_inline)) { | |||||
| int ret = 0; | |||||
| //serial_print("SPCR & "); | |||||
| //serial_phex(val); | |||||
| //serial_print(" MCR:"); | |||||
| //serial_phex32(SPI1_MCR); | |||||
| //serial_print(", CTAR0:"); | |||||
| //serial_phex32(SPI1_CTAR0); | |||||
| //serial_print("\n"); | |||||
| //serial_print("\n"); | |||||
| SIM_SCGC6 |= SIM_SCGC6_SPI1; | |||||
| if ((val & (1<<DORD)) && (SPI1_CTAR0 & SPI_CTAR_LSBFE)) ret |= (1<<DORD); | |||||
| if ((val & (1<<CPOL)) && (SPI1_CTAR0 & SPI_CTAR_CPOL)) ret |= (1<<CPOL); | |||||
| if ((val & (1<<CPHA)) && (SPI1_CTAR0 & SPI_CTAR_CPHA)) ret |= (1<<CPHA); | |||||
| if ((val & 3) == 3) { | |||||
| uint32_t dbr = SPI1_CTAR0 & 15; | |||||
| if (dbr <= 1) { | |||||
| } else if (dbr <= 4) { | |||||
| ret |= (1<<SPR0); | |||||
| } else if (dbr <= 6) { | |||||
| ret |= (1<<SPR1); | |||||
| } else { | |||||
| ret |= (1<<SPR1)|(1<<SPR0); | |||||
| } | |||||
| } else if ((val & 3) == 1) { | |||||
| // TODO: implement - is this ever really needed | |||||
| } else if ((val & 3) == 2) { | |||||
| // TODO: implement - is this ever really needed | |||||
| } | |||||
| if (val & (1<<SPE) && (!(SPI1_MCR & SPI_MCR_MDIS))) ret |= (1<<SPE); | |||||
| if (val & (1<<MSTR) && (SPI1_MCR & SPI_MCR_MSTR)) ret |= (1<<MSTR); | |||||
| //serial_print("ret = "); | |||||
| //serial_phex(ret); | |||||
| //serial_print("\n"); | |||||
| return ret; | |||||
| } | |||||
| inline void setMOSI(uint8_t pin) __attribute__((always_inline)) { | inline void setMOSI(uint8_t pin) __attribute__((always_inline)) { | ||||
| if (pin == 0) pinout &= ~1; // MOSI1 = 0 (PTB16) | if (pin == 0) pinout &= ~1; // MOSI1 = 0 (PTB16) | ||||
| if (pin == 21) pinout |= 1; // MOSI1 = 21 (PTD6) | if (pin == 21) pinout |= 1; // MOSI1 = 21 (PTD6) | ||||
| friend class SPIFIFO1class; | friend class SPIFIFO1class; | ||||
| private: | private: | ||||
| static uint8_t pinout; | static uint8_t pinout; | ||||
| static inline void update_ctar(uint32_t ctar) __attribute__((always_inline)) { | |||||
| if (SPI1_CTAR0 == ctar) return; | |||||
| uint32_t mcr = SPI1_MCR; | |||||
| if (mcr & SPI_MCR_MDIS) { | |||||
| SPI1_CTAR0 = ctar; | |||||
| } else { | |||||
| SPI1_MCR = mcr | SPI_MCR_MDIS | SPI_MCR_HALT; | |||||
| SPI1_CTAR0 = ctar; | |||||
| SPI1_MCR = mcr; | |||||
| } | |||||
| } | |||||
| }; | }; | ||||
| extern SPCR1emulation SPCR1; | extern SPCR1emulation SPCR1; | ||||