Skip to content

Commit

Permalink
T T3.4 T3.5 SPI2 support
Browse files Browse the repository at this point in the history
  • Loading branch information
KurtE committed Jul 19, 2016
1 parent 50c8059 commit c79a667
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 0 deletions.
1 change: 1 addition & 0 deletions teensy3/avr_emulation.cpp
Expand Up @@ -38,6 +38,7 @@ uint8_t SPCR1emulation::pinout = 0;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
uint8_t SPCR1emulation::pinout = 0;
uint8_t SPCR2emulation::pinout = 0;
#endif
#ifdef HAS_SPIFIFO

Expand Down
237 changes: 237 additions & 0 deletions teensy3/avr_emulation.h
Expand Up @@ -1325,6 +1325,243 @@ class SPCR1emulation
};
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

class SPSRemulation
Expand Down

0 comments on commit c79a667

Please sign in to comment.