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.

преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
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;