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.

238 line
10KB

  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. KINETISK_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. KINETISK_SPI0.CTAR0 = ctar | SPI_CTAR_FMSZ(7);
  127. KINETISK_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. pinMode(pin, OUTPUT);
  158. *reg = 1;
  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. KINETISK_SPI0.PUSHR = (b & 0xFF) | pcsbits | (cont ? SPI_PUSHR_CONT : 0);
  169. while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
  170. } else {
  171. *reg = 0;
  172. KINETISK_SPI0.SR = SPI_SR_EOQF;
  173. KINETISK_SPI0.PUSHR = (b & 0xFF) | (cont ? 0 : SPI_PUSHR_EOQ);
  174. if (cont) {
  175. while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ;
  176. } else {
  177. while (!(KINETISK_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. KINETISK_SPI0.PUSHR = (b & 0xFFFF) | (pcs << 16) |
  186. (cont ? SPI_PUSHR_CONT : 0) | SPI_PUSHR_CTAS(1);
  187. while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ;
  188. } else {
  189. *reg = 0;
  190. KINETISK_SPI0.SR = SPI_SR_EOQF;
  191. KINETISK_SPI0.PUSHR = (b & 0xFFFF) | (cont ? 0 : SPI_PUSHR_EOQ) | SPI_PUSHR_CTAS(1);
  192. if (cont) {
  193. while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ;
  194. } else {
  195. while (!(KINETISK_SPI0.SR & SPI_SR_EOQF)) ;
  196. *reg = 1;
  197. }
  198. }
  199. }
  200. inline uint32_t read(void) __attribute__((always_inline)) {
  201. while ((KINETISK_SPI0.SR & (15 << 4)) == 0) ; // TODO, could wait forever
  202. return KINETISK_SPI0.POPR;
  203. }
  204. inline void clear(void) __attribute__((always_inline)) {
  205. KINETISK_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