Teensy 4.1 core updated for C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.8KB

  1. #include "avr_emulation.h"
  2. #if F_BUS == 48000000
  3. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(48 / 2) * ((1+1)/2)
  4. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(48 / 3) * ((1+1)/2) 33% duty cycle
  5. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(48 / 2) * ((1+0)/2)
  6. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0)) //(48 / 3) * ((1+0)/2)
  7. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1)) //(48 / 2) * ((1+0)/4)
  8. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(1)) //(48 / 3) * ((1+0)/4)
  9. #elif F_BUS == 24000000
  10. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2) 12 MHz
  11. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2) 12 MHz
  12. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2)
  13. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 3) * ((1+1)/2) 33% duty cycle
  14. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(24 / 2) * ((1+0)/2)
  15. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0)) //(24 / 3) * ((1+0)/2)
  16. #endif
  17. // sck = F_BUS / PBR * ((1+DBR)/BR)
  18. // PBR = 2, 3, 5, 7
  19. // DBR = 0, 1 -- zero preferred
  20. // BR = 2, 4, 6, 8, 16, 32, 64, 128, 256, 512
  21. #ifndef SPI_MODE0
  22. #define SPI_MODE0 0x00 // CPOL = 0, CPHA = 0
  23. #define SPI_MODE1 0x04 // CPOL = 0, CPHA = 1
  24. #define SPI_MODE2 0x08 // CPOL = 1, CPHA = 0
  25. #define SPI_MODE3 0x0C // CPOL = 1, CPHA = 1
  26. #endif
  27. #define SPI_CONTINUE 1
  28. static uint8_t pcs=0;
  29. class SPIFIFOclass
  30. {
  31. public:
  32. inline bool begin(uint8_t pin, uint32_t speed, uint32_t mode=SPI_MODE0) __attribute__((always_inline)) {
  33. uint32_t p, ctar = speed;
  34. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  35. SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  36. if (mode & 0x08) ctar |= SPI_CTAR_CPOL;
  37. if (mode & 0x04) {
  38. ctar |= SPI_CTAR_CPHA;
  39. ctar |= (ctar & 0x0F) << 8;
  40. } else {
  41. ctar |= (ctar & 0x0F) << 12;
  42. }
  43. SPI0_CTAR0 = ctar | SPI_CTAR_FMSZ(7);
  44. SPI0_CTAR1 = ctar | SPI_CTAR_FMSZ(15);
  45. if (pin == 10) { // PTC4
  46. CORE_PIN10_CONFIG = PORT_PCR_MUX(2);
  47. p = 0x01;
  48. } else if (pin == 2) { // PTD0
  49. CORE_PIN2_CONFIG = PORT_PCR_MUX(2);
  50. p = 0x01;
  51. } else if (pin == 9) { // PTC3
  52. CORE_PIN9_CONFIG = PORT_PCR_MUX(2);
  53. p = 0x02;
  54. } else if (pin == 6) { // PTD4
  55. CORE_PIN6_CONFIG = PORT_PCR_MUX(2);
  56. p = 0x02;
  57. } else if (pin == 20) { // PTD5
  58. CORE_PIN20_CONFIG = PORT_PCR_MUX(2);
  59. p = 0x04;
  60. } else if (pin == 23) { // PTC2
  61. CORE_PIN23_CONFIG = PORT_PCR_MUX(2);
  62. p = 0x04;
  63. } else if (pin == 21) { // PTD6
  64. CORE_PIN21_CONFIG = PORT_PCR_MUX(2);
  65. p = 0x08;
  66. } else if (pin == 22) { // PTC1
  67. CORE_PIN22_CONFIG = PORT_PCR_MUX(2);
  68. p = 0x08;
  69. } else if (pin == 15) { // PTC0
  70. CORE_PIN15_CONFIG = PORT_PCR_MUX(2);
  71. p = 0x10;
  72. } else {
  73. return false;
  74. }
  75. pcs = p;
  76. clear();
  77. SPCR.enable_pins();
  78. return true;
  79. }
  80. inline void write(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) {
  81. while (((SPI0_SR) & (15 << 12)) > (3 << 12)) ; // wait for space in the TX fifo
  82. SPI0_PUSHR = (b & 0xFF) | (pcs << 16) | (cont ? SPI_PUSHR_CONT : 0);
  83. }
  84. inline void write16(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) {
  85. while (((SPI0_SR) & (15 << 12)) > (3 << 12)) ; // wait for space in the TX fifo
  86. SPI0_PUSHR = (b & 0xFFFF) | (pcs << 16) | (cont ? SPI_PUSHR_CONT : 0) | SPI_PUSHR_CTAS(1);
  87. }
  88. inline uint32_t read(void) __attribute__((always_inline)) {
  89. while ((SPI0_SR & (15 << 4)) == 0) ; // TODO, could wait forever
  90. return SPI0_POPR;
  91. }
  92. inline void clear(void) __attribute__((always_inline)) {
  93. SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F) | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
  94. }
  95. };
  96. extern SPIFIFOclass SPIFIFO;