|
|
|
|
|
|
|
|
}; |
|
|
}; |
|
|
extern SPCR1emulation SPCR1; |
|
|
extern SPCR1emulation SPCR1; |
|
|
|
|
|
|
|
|
|
|
|
//////////////////// |
|
|
|
|
|
// SPI2 |
|
|
|
|
|
class SPCR2emulation |
|
|
|
|
|
{ |
|
|
|
|
|
public: |
|
|
|
|
|
inline SPCR2emulation & operator = (int val) __attribute__((always_inline)) { |
|
|
|
|
|
uint32_t ctar, mcr, sim3; |
|
|
|
|
|
//serial_print("SPCR="); |
|
|
|
|
|
//serial_phex(val); |
|
|
|
|
|
//serial_print("\n"); |
|
|
|
|
|
sim3 = SIM_SCGC3; |
|
|
|
|
|
if (!(sim3 & SIM_SCGC3_SPI2)) { |
|
|
|
|
|
//serial_print("init1\n"); |
|
|
|
|
|
SIM_SCGC3 = sim3 | SIM_SCGC3_SPI2; |
|
|
|
|
|
SPI2_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1); |
|
|
|
|
|
} |
|
|
|
|
|
if (!(val & (1<<SPE))) { |
|
|
|
|
|
SPI2_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 |= (SPI2_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); |
|
|
|
|
|
SPI2_MCR = mcr; |
|
|
|
|
|
enable_pins(); |
|
|
|
|
|
} else { |
|
|
|
|
|
mcr |= (SPI_MCR_MDIS | SPI_MCR_HALT); |
|
|
|
|
|
SPI2_MCR = mcr; |
|
|
|
|
|
disable_pins(); |
|
|
|
|
|
} |
|
|
|
|
|
//serial_print("MCR:"); |
|
|
|
|
|
//serial_phex32(SPI2_MCR); |
|
|
|
|
|
//serial_print(", CTAR0:"); |
|
|
|
|
|
//serial_phex32(SPI2_CTAR0); |
|
|
|
|
|
//serial_print("\n"); |
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
inline SPCR2emulation & operator |= (int val) __attribute__((always_inline)) { |
|
|
|
|
|
uint32_t sim3; |
|
|
|
|
|
//serial_print("SPCR |= "); |
|
|
|
|
|
//serial_phex(val); |
|
|
|
|
|
//serial_print("\n"); |
|
|
|
|
|
sim3 = SIM_SCGC3; |
|
|
|
|
|
if (!(sim3 & SIM_SCGC3_SPI2)) { |
|
|
|
|
|
//serial_print("init2\n"); |
|
|
|
|
|
SIM_SCGC6 = sim3 | SIM_SCGC3_SPI2; |
|
|
|
|
|
SPI2_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 = SPI2_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)) SPI2_MCR |= SPI_MCR_MSTR; |
|
|
|
|
|
if (val & (1<<SPE)) { |
|
|
|
|
|
SPI2_MCR &= ~(SPI_MCR_MDIS | SPI_MCR_HALT); |
|
|
|
|
|
enable_pins(); |
|
|
|
|
|
} |
|
|
|
|
|
//serial_print("MCR:"); |
|
|
|
|
|
//serial_phex32(SPI2_MCR); |
|
|
|
|
|
//serial_print(", CTAR0:"); |
|
|
|
|
|
//serial_phex32(SPI2_CTAR0); |
|
|
|
|
|
//serial_print("\n"); |
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
inline SPCR2emulation & operator &= (int val) __attribute__((always_inline)) { |
|
|
|
|
|
//serial_print("SPCR &= "); |
|
|
|
|
|
//serial_phex(val); |
|
|
|
|
|
//serial_print("\n"); |
|
|
|
|
|
SIM_SCGC3 |= SIM_SCGC3_SPI2; |
|
|
|
|
|
if (!(val & (1<<SPE))) { |
|
|
|
|
|
SPI2_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 = SPI2_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))) SPI2_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(SPI2_MCR); |
|
|
|
|
|
//serial_print(", CTAR0:"); |
|
|
|
|
|
//serial_phex32(SPI2_CTAR0); |
|
|
|
|
|
//serial_print("\n"); |
|
|
|
|
|
|
|
|
|
|
|
//serial_print("\n"); |
|
|
|
|
|
SIM_SCGC3 |= SIM_SCGC3_SPI2; |
|
|
|
|
|
if ((val & (1<<DORD)) && (SPI2_CTAR0 & SPI_CTAR_LSBFE)) ret |= (1<<DORD); |
|
|
|
|
|
if ((val & (1<<CPOL)) && (SPI2_CTAR0 & SPI_CTAR_CPOL)) ret |= (1<<CPOL); |
|
|
|
|
|
if ((val & (1<<CPHA)) && (SPI2_CTAR0 & SPI_CTAR_CPHA)) ret |= (1<<CPHA); |
|
|
|
|
|
if ((val & 3) == 3) { |
|
|
|
|
|
uint32_t dbr = SPI2_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) && (!(SPI2_MCR & SPI_MCR_MDIS))) ret |= (1<<SPE); |
|
|
|
|
|
if (val & (1<<MSTR) && (SPI2_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)) { |
|
|
|
|
|
if (pin == 44) pinout &= ~1; |
|
|
|
|
|
if (pin == 52) pinout |= 1; |
|
|
|
|
|
} |
|
|
|
|
|
inline void setMISO(uint8_t pin) __attribute__((always_inline)) { |
|
|
|
|
|
if (pin == 45) pinout &= ~2; |
|
|
|
|
|
if (pin == 51) pinout |= 2; |
|
|
|
|
|
} |
|
|
|
|
|
inline void setSCK(uint8_t pin) __attribute__((always_inline)) { |
|
|
|
|
|
if (pin == 46) pinout &= ~4; |
|
|
|
|
|
if (pin == 53) pinout |= 4; |
|
|
|
|
|
} |
|
|
|
|
|
inline void enable_pins(void) __attribute__((always_inline)) { |
|
|
|
|
|
//serial_print("enable_pins\n"); |
|
|
|
|
|
if ((pinout & 1) == 0) { |
|
|
|
|
|
CORE_PIN44_CONFIG = PORT_PCR_MUX(2); |
|
|
|
|
|
} else { |
|
|
|
|
|
CORE_PIN52_CONFIG = PORT_PCR_MUX(2); |
|
|
|
|
|
} |
|
|
|
|
|
if ((pinout & 2) == 0) { |
|
|
|
|
|
CORE_PIN45_CONFIG = PORT_PCR_MUX(2); |
|
|
|
|
|
} else { |
|
|
|
|
|
CORE_PIN51_CONFIG = PORT_PCR_MUX(2); |
|
|
|
|
|
} |
|
|
|
|
|
if ((pinout & 4) == 0) { |
|
|
|
|
|
CORE_PIN46_CONFIG = PORT_PCR_MUX(2); |
|
|
|
|
|
} else { |
|
|
|
|
|
CORE_PIN53_CONFIG = PORT_PCR_MUX(2); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
inline void disable_pins(void) __attribute__((always_inline)) { |
|
|
|
|
|
//serial_print("disable_pins\n"); |
|
|
|
|
|
if ((pinout & 1) == 0) { |
|
|
|
|
|
CORE_PIN44_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); |
|
|
|
|
|
} else { |
|
|
|
|
|
CORE_PIN52_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); |
|
|
|
|
|
} |
|
|
|
|
|
if ((pinout & 2) == 0) { |
|
|
|
|
|
CORE_PIN45_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); |
|
|
|
|
|
} else { |
|
|
|
|
|
CORE_PIN51_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); |
|
|
|
|
|
} |
|
|
|
|
|
if ((pinout & 4) == 0) { |
|
|
|
|
|
CORE_PIN46_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); |
|
|
|
|
|
} else { |
|
|
|
|
|
CORE_PIN53_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
friend class SPIFIFO1class; |
|
|
|
|
|
private: |
|
|
|
|
|
static uint8_t pinout; |
|
|
|
|
|
static inline void update_ctar(uint32_t ctar) __attribute__((always_inline)) { |
|
|
|
|
|
if (SPI2_CTAR0 == ctar) return; |
|
|
|
|
|
uint32_t mcr = SPI2_MCR; |
|
|
|
|
|
if (mcr & SPI_MCR_MDIS) { |
|
|
|
|
|
SPI2_CTAR0 = ctar; |
|
|
|
|
|
} else { |
|
|
|
|
|
SPI2_MCR = mcr | SPI_MCR_MDIS | SPI_MCR_HALT; |
|
|
|
|
|
SPI2_CTAR0 = ctar; |
|
|
|
|
|
SPI2_MCR = mcr; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
extern SPCR2emulation SPCR2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
class SPSRemulation |
|
|
class SPSRemulation |