/netcon Module/Pollin AVR-NET-IO/obsolet/UART_Ethernet Bridge/UART_Ethernet Bridge/enc28j60.c

https://github.com/sli92/netcon · C · 309 lines · 182 code · 86 blank · 41 comment · 26 complexity · 94aa4f47012d546b5d9a1f44bbfd70a7 MD5 · raw file

  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3. #include "enc28j60.h"
  4. uint8_t enc28j60CurrentBank = 0;
  5. uint16_t enc28j60NextPacketAdress = RECEIVE_BUFFER_START;
  6. void enc28j60Init(const uint8_t *MACAddr)
  7. {
  8. // Ausgänge: SS MOSI SCK
  9. DDRB |= (1 << DDB4) | (1 << DDB5) | (1 << DDB7);
  10. // Eingange: MISO
  11. DDRB &= ~(1 << DDB6);
  12. // SCK = F_CPU/16 Master SPI-Enable
  13. // SPCR |= (1 << SPR0) | (1 << MSTR) | (1 << SPE);
  14. // SCK = F_CPU/2 Master SPI-Enable
  15. SPCR |= (1 << SPI2X) | (1 << MSTR) | (1 << SPE);
  16. enc28j60SystemResetCommand();
  17. // ENC28J60 errata, page 3, issue 2
  18. _delay_ms(1);
  19. // while(!(enc28j60ReadControlRegister(ESTAT) & (1 << ESTAT_CLKRDY)));
  20. // Setup Receive buffer
  21. enc28j60WriteControlRegister(ERXSTL, RECEIVE_BUFFER_START);
  22. enc28j60WriteControlRegister(ERXSTH, RECEIVE_BUFFER_START >> 8);
  23. enc28j60WriteControlRegister(ERXNDL, RECEIVE_BUFFER_END);
  24. enc28j60WriteControlRegister(ERXNDH, RECEIVE_BUFFER_END >> 8);
  25. // MAC Setup
  26. enc28j60BitFieldSet(MACON1, (1 << MACON1_MARXEN) | (1 << MACON1_TXPAUS) | (1 << MACON1_RXPAUS));
  27. enc28j60BitFieldClear(MACON2, 1 << MACON2_MARST);
  28. enc28j60BitFieldSet(MACON3, (1 << MACON3_FULDPX) | (1 << MACON3_FRMLNEN) | (1 << MACON3_TXCRCEN) | (1 << MACON3_PADCFG0));
  29. enc28j60WriteControlRegister(MAMXFLL, MAX_FRAME_LENGTH + 4);
  30. enc28j60WriteControlRegister(MAMXFLH, (MAX_FRAME_LENGTH + 4) >> 8);
  31. // See ENC28J60 data sheet, page 34
  32. enc28j60WriteControlRegister(MABBIPG, 0x15);
  33. enc28j60WriteControlRegister(MAIPGL, 0x12);
  34. enc28j60WriteControlRegister(MAADR1, MACAddr[0]);
  35. enc28j60WriteControlRegister(MAADR2, MACAddr[1]);
  36. enc28j60WriteControlRegister(MAADR3, MACAddr[2]);
  37. enc28j60WriteControlRegister(MAADR4, MACAddr[3]);
  38. enc28j60WriteControlRegister(MAADR5, MACAddr[4]);
  39. enc28j60WriteControlRegister(MAADR6, MACAddr[5]);
  40. // Set PHY in full duplex mode
  41. enc28j60WritePHYRegister(PHCON1, 1 << PHCON1_PDPXMD);
  42. enc28j60BitFieldSet(ECON1, 1 << ECON1_RXEN);
  43. }
  44. uint8_t enc28j60ReadControlRegister(uint8_t regAddr)
  45. {
  46. uint8_t data;
  47. // Switch bank if necessary
  48. enc28j60SetBank(regAddr);
  49. // Set chip select
  50. PORTB &= ~(1 << PB4);
  51. // Write
  52. SPDR = OPCODE_RCR | (regAddr & ADDR_MASK);
  53. while(!(SPSR & (1 << SPIF)));
  54. // Read
  55. SPDR = 0x00;
  56. while(!(SPSR & (1 << SPIF)));
  57. // Reread if chip sends dummy byte first
  58. if(regAddr & DUMMY_TRANSFER)
  59. {
  60. SPDR = 0x00;
  61. while(!(SPSR & (1 << SPIF)));
  62. }
  63. data = SPDR;
  64. // Remove chip select
  65. PORTB |= (1 << PB4);
  66. return data;
  67. }
  68. void enc28j60ReadBufferMemory(uint8_t *data, uint16_t len)
  69. {
  70. // Set chip select
  71. PORTB &= ~(1 << PB4);
  72. SPDR = OPCODE_RBM | 0x1A;
  73. while(!(SPSR & (1 << SPIF)));
  74. while(len--)
  75. {
  76. SPDR = 0x00;
  77. while(!(SPSR & (1 << SPIF)));
  78. *data++ = SPDR;
  79. }
  80. // Remove chip select
  81. PORTB |= (1 << PB4);
  82. }
  83. void enc28j60WriteControlRegister(uint8_t regAddr, uint8_t data)
  84. {
  85. // Switch bank if necessary
  86. enc28j60SetBank(regAddr);
  87. // Set chip select
  88. PORTB &= ~(1 << PB4);
  89. SPDR = OPCODE_WCR | (regAddr & ADDR_MASK);
  90. while(!(SPSR & (1 << SPIF)));
  91. SPDR = data;
  92. while(!(SPSR & (1 << SPIF)));
  93. // Remove chip select
  94. PORTB |= (1 << PB4);
  95. }
  96. void enc28j60WriteBufferMemory(uint8_t *data, uint16_t len)
  97. {
  98. // Set chip select
  99. PORTB &= ~(1 << PB4);
  100. SPDR = OPCODE_WBM | 0x1A;
  101. while(!(SPSR & (1 << SPIF)));
  102. while(len--)
  103. {
  104. SPDR = *data++;
  105. while(!(SPSR & (1 << SPIF)));
  106. }
  107. // Remove chip select
  108. PORTB |= (1 << PB4);
  109. }
  110. void enc28j60BitFieldSet(uint8_t regAddr, uint8_t data)
  111. {
  112. // Switch bank if necessary
  113. enc28j60SetBank(regAddr);
  114. // Set chip select
  115. PORTB &= ~(1 << PB4);
  116. SPDR = OPCODE_BFS | (regAddr & ADDR_MASK);
  117. while(!(SPSR & (1 << SPIF)));
  118. SPDR = data;
  119. while(!(SPSR & (1 << SPIF)));
  120. // Remove chip select
  121. PORTB |= (1 << PB4);
  122. }
  123. void enc28j60BitFieldClear(uint8_t regAddr, uint8_t data)
  124. {
  125. // Switch bank if necessary
  126. enc28j60SetBank(regAddr);
  127. // Set chip select
  128. PORTB &= ~(1 << PB4);
  129. SPDR = OPCODE_BFC | (regAddr & ADDR_MASK);
  130. while(!(SPSR & (1 << SPIF)));
  131. SPDR = data;
  132. while(!(SPSR & (1 << SPIF)));
  133. // Remove chip select
  134. PORTB |= (1 << PB4);
  135. }
  136. void enc28j60SystemResetCommand(void)
  137. {
  138. // Set chip select
  139. PORTB &= ~(1 << PB4);
  140. SPDR = OPCODE_SRC | 0x1F;
  141. while(!(SPSR & (1 << SPIF)));
  142. // Remove chip select
  143. PORTB |= (1 << PB4);
  144. }
  145. void enc28j60SetBank(uint8_t regAddr)
  146. {
  147. if(((regAddr & ADDR_MASK) < KEY_REGISTERS_START) && enc28j60CurrentBank != (regAddr & BANK_MASK))
  148. {
  149. enc28j60CurrentBank = (regAddr & BANK_MASK);
  150. enc28j60BitFieldClear(ECON1, (1 << ECON1_BSEL1) | (1 << ECON1_BSEL0));
  151. enc28j60BitFieldSet(ECON1, (enc28j60CurrentBank >> 5));
  152. }
  153. }
  154. uint16_t enc28j60ReadPHYRegister(uint8_t regAddr)
  155. {
  156. enc28j60WriteControlRegister(MIREGADR, regAddr);
  157. enc28j60WriteControlRegister(MICMD, (1 << MICMD_MIIRD));
  158. while(enc28j60ReadControlRegister(MISTAT) & (1 << MISTAT_BUSY));
  159. enc28j60WriteControlRegister(MICMD, (0 << MICMD_MIIRD));
  160. return enc28j60ReadControlRegister(MIRDL) | (enc28j60ReadControlRegister(MIRDH) << 8);
  161. }
  162. void enc28j60WritePHYRegister(uint8_t regAddr, uint16_t data)
  163. {
  164. enc28j60WriteControlRegister(MIREGADR, regAddr);
  165. enc28j60WriteControlRegister(MIWRL, data);
  166. enc28j60WriteControlRegister(MIWRH, data >> 8);
  167. while(enc28j60ReadControlRegister(MISTAT) & (1 << MISTAT_BUSY));
  168. }
  169. void enc28j60TransmitPacket(uint8_t *data, uint16_t length, uint8_t perPacketControlByte)
  170. {
  171. if(enc28j60ReadControlRegister(ECON1) & (1 << ECON1_TXRTS))
  172. return;
  173. uint16_t adress = TRANSMIT_BUFFER_START;
  174. enc28j60WriteControlRegister(ETXSTL, adress);
  175. enc28j60WriteControlRegister(ETXSTH, adress >> 8);
  176. enc28j60WriteControlRegister(EWRPTL, adress);
  177. enc28j60WriteControlRegister(EWRPTH, adress >> 8);
  178. enc28j60WriteBufferMemory(&perPacketControlByte, 1);
  179. enc28j60WriteBufferMemory(data, length);
  180. adress += length;
  181. enc28j60WriteControlRegister(ETXNDL, adress);
  182. enc28j60WriteControlRegister(ETXNDH, adress >> 8);
  183. enc28j60BitFieldClear(EIR, 1 << EIR_TXIF);
  184. enc28j60BitFieldSet(EIE, 1 << EIE_TXIE);
  185. enc28j60BitFieldSet(ECON1, 1 << ECON1_TXRTS);
  186. }
  187. uint16_t enc28j60ReceivePacket(uint8_t *data, uint16_t maxlength)
  188. {
  189. uint16_t length, temp;
  190. uint8_t header[6];
  191. if(!enc28j60ReadControlRegister(EPKTCNT))
  192. return 0;
  193. enc28j60WriteControlRegister(ERDPTL, enc28j60NextPacketAdress);
  194. enc28j60WriteControlRegister(ERDPTH, enc28j60NextPacketAdress >> 8);
  195. enc28j60ReadBufferMemory(header, 6);
  196. enc28j60NextPacketAdress = header[0] | (header[1] << 8);
  197. length = (header[2] | (header[3] << 8)) - 4;
  198. // status = header[4] | (header[5] << 8);
  199. length = length > maxlength ? maxlength : length;
  200. enc28j60ReadBufferMemory(data, length);
  201. // ENC28J60 errata, page 6, issue 14
  202. // The receive hardware may corrupt the circular receive buffer
  203. // when an even value is programmed into the ERXRDPTH:ERXRDPTL registers.
  204. temp = enc28j60ReadControlRegister(ERXSTL) | (enc28j60ReadControlRegister(ERXSTH) << 8);
  205. if(enc28j60NextPacketAdress == temp)
  206. {
  207. // ERXND = RECEIVE_BUFFER_END
  208. enc28j60WriteControlRegister(ERXRDPTL, RECEIVE_BUFFER_END);
  209. enc28j60WriteControlRegister(ERXRDPTH, RECEIVE_BUFFER_END >> 8);
  210. }
  211. else
  212. {
  213. temp = enc28j60NextPacketAdress - 1;
  214. enc28j60WriteControlRegister(ERXRDPTL, temp);
  215. enc28j60WriteControlRegister(ERXRDPTH, temp >> 8);
  216. }
  217. /*
  218. enc28j60WriteControlRegister(ERXRDPTL, enc28j60NextPacketAdress & 0xFF);
  219. enc28j60WriteControlRegister(ERXRDPTH, (enc28j60NextPacketAdress >> 8) & 0xFF);
  220. */
  221. enc28j60BitFieldSet(ECON2, 1 << ECON2_PKTDEC);
  222. return length;
  223. }