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 10KB

11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
11 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #ifndef _SPIFIFO_h_
  2. #define _SPIFIFO_h_
  3. #include "avr_emulation.h"
  4. #ifdef KINETISK
  5. #if F_BUS == 60000000
  6. #define HAS_SPIFIFO
  7. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(60 / 3) * ((1+1)/2) = 20 MHz
  8. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(60 / 2) * ((1+0)/2) = 15 MHz
  9. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(60 / 5) * ((1+1)/2)
  10. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1)) //(60 / 2) * ((1+0)/4) = 7.5 MHz
  11. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0)) //(60 / 5) * ((1+0)/2)
  12. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(60 / 5) * ((1+1)/6)
  13. #elif F_BUS == 56000000
  14. #define HAS_SPIFIFO
  15. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(56 / 3) * ((1+1)/2) = 18.67
  16. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(56 / 2) * ((1+0)/2) = 14
  17. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(56 / 5) * ((1+1)/2) = 11.2
  18. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(56 / 7) * ((1+1)/2)
  19. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0)) //(56 / 5) * ((1+0)/2)
  20. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0)) //(56 / 7) * ((1+0)/2)
  21. #elif F_BUS == 48000000
  22. #define HAS_SPIFIFO
  23. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(48 / 2) * ((1+1)/2)
  24. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(48 / 3) * ((1+1)/2)
  25. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(48 / 2) * ((1+0)/2)
  26. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(48 / 2) * ((1+1)/6)
  27. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1)) //(48 / 2) * ((1+0)/4)
  28. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(48 / 2) * ((1+0)/6)
  29. #elif F_BUS == 40000000
  30. #define HAS_SPIFIFO
  31. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(40 / 2) * ((1+1)/2) = 20
  32. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(40 / 3) * ((1+1)/2) = 13.33
  33. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(40 / 2) * ((1+0)/2) = 10
  34. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(40 / 5) * ((1+1)/2)
  35. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(40 / 7) * ((1+1)/2) = 5.71
  36. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(1)) //(40 / 5) * ((1+0)/2)
  37. #elif F_BUS == 36000000
  38. #define HAS_SPIFIFO
  39. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 2) * ((1+1)/2) = 18
  40. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 3) * ((1+1)/2) = 12
  41. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 3) * ((1+1)/2) = 12
  42. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 5) * ((1+1)/2) = 7.2
  43. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(36 / 2) * ((1+1)/6)
  44. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(36 / 3) * ((1+1)/6)
  45. #elif F_BUS == 24000000
  46. #define HAS_SPIFIFO
  47. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2) 12 MHz
  48. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2) 12 MHz
  49. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2)
  50. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 3) * ((1+1)/2)
  51. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(24 / 2) * ((1+0)/2)
  52. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/6)
  53. #elif F_BUS == 16000000
  54. #define HAS_SPIFIFO
  55. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz
  56. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz
  57. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz
  58. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz
  59. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz
  60. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz
  61. #elif F_BUS == 8000000
  62. #define HAS_SPIFIFO
  63. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz
  64. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz
  65. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz
  66. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz
  67. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz
  68. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz
  69. #elif F_BUS == 4000000
  70. #define HAS_SPIFIFO
  71. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz
  72. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz
  73. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz
  74. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz
  75. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz
  76. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz
  77. #elif F_BUS == 2000000
  78. #define HAS_SPIFIFO
  79. #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz
  80. #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz
  81. #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz
  82. #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz
  83. #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz
  84. #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz
  85. #endif // F_BUS
  86. #endif // KINETISK
  87. /*
  88. #! /usr/bin/perl
  89. $clock = 60;
  90. for $i (2, 3, 5, 7) {
  91. for $j (0, 1) {
  92. for $k (2, 4, 6, 8, 16, 32) {
  93. $out = $clock / $i * (1 + $j) / $k;
  94. printf "%0.2f : ", $out;
  95. print "$clock / $i * (1 + $j) / $k = $out\n";
  96. }
  97. }
  98. }
  99. */
  100. // sck = F_BUS / PBR * ((1+DBR)/BR)
  101. // PBR = 2, 3, 5, 7
  102. // DBR = 0, 1 -- zero preferred
  103. // BR = 2, 4, 6, 8, 16, 32, 64, 128, 256, 512
  104. #ifdef HAS_SPIFIFO
  105. #ifndef SPI_MODE0
  106. #define SPI_MODE0 0x00 // CPOL = 0, CPHA = 0
  107. #define SPI_MODE1 0x04 // CPOL = 0, CPHA = 1
  108. #define SPI_MODE2 0x08 // CPOL = 1, CPHA = 0
  109. #define SPI_MODE3 0x0C // CPOL = 1, CPHA = 1
  110. #endif
  111. #define SPI_CONTINUE 1
  112. class SPIFIFOclass
  113. {
  114. public:
  115. inline void begin(uint8_t pin, uint32_t speed, uint32_t mode=SPI_MODE0) __attribute__((always_inline)) {
  116. uint32_t p, ctar = speed;
  117. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  118. SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  119. if (mode & 0x08) ctar |= SPI_CTAR_CPOL;
  120. if (mode & 0x04) {
  121. ctar |= SPI_CTAR_CPHA;
  122. ctar |= (ctar & 0x0F) << 8;
  123. } else {
  124. ctar |= (ctar & 0x0F) << 12;
  125. }
  126. SPI0.CTAR0 = ctar | SPI_CTAR_FMSZ(7);
  127. SPI0.CTAR1 = ctar | SPI_CTAR_FMSZ(15);
  128. if (pin == 10) { // PTC4
  129. CORE_PIN10_CONFIG = PORT_PCR_MUX(2);
  130. p = 0x01;
  131. } else if (pin == 2) { // PTD0
  132. CORE_PIN2_CONFIG = PORT_PCR_MUX(2);
  133. p = 0x01;
  134. } else if (pin == 9) { // PTC3
  135. CORE_PIN9_CONFIG = PORT_PCR_MUX(2);
  136. p = 0x02;
  137. } else if (pin == 6) { // PTD4
  138. CORE_PIN6_CONFIG = PORT_PCR_MUX(2);
  139. p = 0x02;
  140. } else if (pin == 20) { // PTD5
  141. CORE_PIN20_CONFIG = PORT_PCR_MUX(2);
  142. p = 0x04;
  143. } else if (pin == 23) { // PTC2
  144. CORE_PIN23_CONFIG = PORT_PCR_MUX(2);
  145. p = 0x04;
  146. } else if (pin == 21) { // PTD6
  147. CORE_PIN21_CONFIG = PORT_PCR_MUX(2);
  148. p = 0x08;
  149. } else if (pin == 22) { // PTC1
  150. CORE_PIN22_CONFIG = PORT_PCR_MUX(2);
  151. p = 0x08;
  152. } else if (pin == 15) { // PTC0
  153. CORE_PIN15_CONFIG = PORT_PCR_MUX(2);
  154. p = 0x10;
  155. } else {
  156. reg = portOutputRegister(pin);
  157. *reg = 1;
  158. pinMode(pin, OUTPUT);
  159. p = 0;
  160. }
  161. pcs = p;
  162. clear();
  163. SPCR.enable_pins();
  164. }
  165. inline void write(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) {
  166. uint32_t pcsbits = pcs << 16;
  167. if (pcsbits) {
  168. SPI0.PUSHR = (b & 0xFF) | pcsbits | (cont ? SPI_PUSHR_CONT : 0);
  169. while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
  170. } else {
  171. *reg = 0;
  172. SPI0.SR = SPI_SR_EOQF;
  173. SPI0.PUSHR = (b & 0xFF) | (cont ? 0 : SPI_PUSHR_EOQ);
  174. if (cont) {
  175. while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ;
  176. } else {
  177. while (!(SPI0.SR & SPI_SR_EOQF)) ;
  178. *reg = 1;
  179. }
  180. }
  181. }
  182. inline void write16(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) {
  183. uint32_t pcsbits = pcs << 16;
  184. if (pcsbits) {
  185. SPI0.PUSHR = (b & 0xFFFF) | (pcs << 16) |
  186. (cont ? SPI_PUSHR_CONT : 0) | SPI_PUSHR_CTAS(1);
  187. while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ;
  188. } else {
  189. *reg = 0;
  190. SPI0.SR = SPI_SR_EOQF;
  191. SPI0.PUSHR = (b & 0xFFFF) | (cont ? 0 : SPI_PUSHR_EOQ) | SPI_PUSHR_CTAS(1);
  192. if (cont) {
  193. while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ;
  194. } else {
  195. while (!(SPI0.SR & SPI_SR_EOQF)) ;
  196. *reg = 1;
  197. }
  198. }
  199. }
  200. inline uint32_t read(void) __attribute__((always_inline)) {
  201. while ((SPI0.SR & (15 << 4)) == 0) ; // TODO, could wait forever
  202. return SPI0.POPR;
  203. }
  204. inline void clear(void) __attribute__((always_inline)) {
  205. SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F) | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
  206. }
  207. private:
  208. static uint8_t pcs;
  209. static volatile uint8_t *reg;
  210. };
  211. extern SPIFIFOclass SPIFIFO;
  212. #endif // HAS_SPIFIFO
  213. #endif