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.

SPIFIFO.h 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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. static volatile uint8_t *reg = 0;
  30. class SPIFIFOclass
  31. {
  32. public:
  33. inline void begin(uint8_t pin, uint32_t speed, uint32_t mode=SPI_MODE0) __attribute__((always_inline)) {
  34. uint32_t p, ctar = speed;
  35. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  36. SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  37. if (mode & 0x08) ctar |= SPI_CTAR_CPOL;
  38. if (mode & 0x04) {
  39. ctar |= SPI_CTAR_CPHA;
  40. ctar |= (ctar & 0x0F) << 8;
  41. } else {
  42. ctar |= (ctar & 0x0F) << 12;
  43. }
  44. SPI0.CTAR0 = ctar | SPI_CTAR_FMSZ(7);
  45. SPI0.CTAR1 = ctar | SPI_CTAR_FMSZ(15);
  46. if (pin == 10) { // PTC4
  47. CORE_PIN10_CONFIG = PORT_PCR_MUX(2);
  48. p = 0x01;
  49. } else if (pin == 2) { // PTD0
  50. CORE_PIN2_CONFIG = PORT_PCR_MUX(2);
  51. p = 0x01;
  52. } else if (pin == 9) { // PTC3
  53. CORE_PIN9_CONFIG = PORT_PCR_MUX(2);
  54. p = 0x02;
  55. } else if (pin == 6) { // PTD4
  56. CORE_PIN6_CONFIG = PORT_PCR_MUX(2);
  57. p = 0x02;
  58. } else if (pin == 20) { // PTD5
  59. CORE_PIN20_CONFIG = PORT_PCR_MUX(2);
  60. p = 0x04;
  61. } else if (pin == 23) { // PTC2
  62. CORE_PIN23_CONFIG = PORT_PCR_MUX(2);
  63. p = 0x04;
  64. } else if (pin == 21) { // PTD6
  65. CORE_PIN21_CONFIG = PORT_PCR_MUX(2);
  66. p = 0x08;
  67. } else if (pin == 22) { // PTC1
  68. CORE_PIN22_CONFIG = PORT_PCR_MUX(2);
  69. p = 0x08;
  70. } else if (pin == 15) { // PTC0
  71. CORE_PIN15_CONFIG = PORT_PCR_MUX(2);
  72. p = 0x10;
  73. } else {
  74. reg = portOutputRegister(pin);
  75. *reg = 1;
  76. pinMode(pin, OUTPUT);
  77. p = 0;
  78. }
  79. pcs = p;
  80. clear();
  81. SPCR.enable_pins();
  82. }
  83. inline void write(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) {
  84. uint32_t pcsbits = pcs << 16;
  85. if (pcsbits) {
  86. SPI0.PUSHR = (b & 0xFF) | pcsbits | (cont ? SPI_PUSHR_CONT : 0);
  87. while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
  88. } else {
  89. *reg = 0;
  90. SPI0.SR = SPI_SR_EOQF;
  91. SPI0.PUSHR = (b & 0xFF) | (cont ? 0 : SPI_PUSHR_EOQ);
  92. if (cont) {
  93. while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ;
  94. } else {
  95. while (!(SPI0.SR & SPI_SR_EOQF)) ;
  96. *reg = 1;
  97. }
  98. }
  99. }
  100. inline void write16(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) {
  101. uint32_t pcsbits = pcs << 16;
  102. if (pcsbits) {
  103. SPI0.PUSHR = (b & 0xFFFF) | (pcs << 16) |
  104. (cont ? SPI_PUSHR_CONT : 0) | SPI_PUSHR_CTAS(1);
  105. while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ;
  106. } else {
  107. *reg = 0;
  108. SPI0.SR = SPI_SR_EOQF;
  109. SPI0.PUSHR = (b & 0xFFFF) | (cont ? 0 : SPI_PUSHR_EOQ) | SPI_PUSHR_CTAS(1);
  110. if (cont) {
  111. while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ;
  112. } else {
  113. while (!(SPI0.SR & SPI_SR_EOQF)) ;
  114. *reg = 1;
  115. }
  116. }
  117. }
  118. inline uint32_t read(void) __attribute__((always_inline)) {
  119. while ((SPI0.SR & (15 << 4)) == 0) ; // TODO, could wait forever
  120. return SPI0.POPR;
  121. }
  122. inline void clear(void) __attribute__((always_inline)) {
  123. SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F) | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
  124. }
  125. };
  126. extern SPIFIFOclass SPIFIFO;