PageRenderTime 45ms CodeModel.GetById 29ms app.highlight 13ms RepoModel.GetById 0ms app.codeStats 0ms

/netcon Module/Ethernet-DK/enc28j60/enc28j60.c

https://github.com/sli92/netcon
C | 315 lines | 209 code | 83 blank | 23 comment | 7 complexity | 09fa4a3658cb97912f632f39f87783e0 MD5 | raw file
  1/*
  2 * Datei:               enc28j60.c
  3 * Author:              dev00
  4 * Beschreibung:        Stellt Funktionen fuer die Benutzung des ENC28J60
  5 *                      Netzwerkcontrollers zur Verfuegung.
  6 *
  7 * Aenderungsdatum:     Do, 27. Okt 2011 20:53:13
  8 *
  9 */
 10#include "compiler_defs.h"
 11#include "C8051F340_defs.h"
 12
 13#include <stdint.h>
 14#include <stdio.h>
 15
 16#include "enc28j60.h"
 17#include "main.h"
 18#include "uart.h"
 19
 20static uint8_t current_bank = 0;
 21static uint16_t next_packet_addr = RECEIVE_BUFFER_START;
 22
 23/*
 24 * Interne Funktionen
 25 *
 26 */
 27void get_cs(void)
 28{
 29        SPI0CN &= ~(1 << _NSSMD0);
 30}
 31
 32void release_cs(void)
 33{
 34        SPI0CN |= (1 << _NSSMD0);
 35}
 36
 37void enc28j60_set_bank(uint8_t reg_addr) __reentrant
 38{
 39        if(((reg_addr & ADDR_MASK) < KEY_REGISTERS_START) &&
 40            current_bank != (reg_addr & BANK_MASK)) {
 41                current_bank = (reg_addr & BANK_MASK);
 42
 43                enc28j60_bit_field_clear(ECON1, (1 << ECON1_BSEL1) |
 44                                                (1 << ECON1_BSEL0));
 45
 46                enc28j60_bit_field_set(ECON1, (current_bank >> 5));
 47        }
 48}
 49
 50void enc28j60_system_reset(void)
 51{
 52        get_cs();
 53
 54        SPI0DAT = OPCODE_SRC | 0x1F;
 55        while(!(SPI0CN & (1 << _SPIF)));
 56        SPI0CN &= ~(1 << _SPIF);
 57
 58        release_cs();
 59}
 60
 61uint8_t enc28j60_read_control_register(uint8_t reg_addr)
 62{
 63        uint8_t _data;
 64
 65        enc28j60_set_bank(reg_addr);
 66
 67        get_cs();
 68
 69        SPI0DAT = OPCODE_RCR | (reg_addr & ADDR_MASK);
 70        while(!(SPI0CN & (1 << _SPIF)));
 71        SPI0CN &= ~(1 << _SPIF);
 72
 73        SPI0DAT = 0x00;
 74        while(!(SPI0CN & (1 << _SPIF)));
 75        _data = SPI0DAT;
 76        SPI0CN &= ~(1 << _SPIF);
 77
 78        if(reg_addr & DUMMY_TRANSFER) {
 79                SPI0DAT = 0x00;
 80                while(!(SPI0CN & (1 << _SPIF)));
 81                _data = SPI0DAT;
 82                SPI0CN &= ~(1 << _SPIF);
 83        }
 84
 85        release_cs();
 86
 87        return _data;
 88}
 89
 90void enc28j60_write_control_register(uint8_t reg_addr, uint8_t _data)
 91{
 92        enc28j60_set_bank(reg_addr);
 93
 94        get_cs();
 95
 96        SPI0DAT = OPCODE_WCR | (reg_addr & ADDR_MASK);
 97        while(!(SPI0CN & (1 << _SPIF)));
 98        SPI0CN &= ~(1 << _SPIF);
 99
100        SPI0DAT = _data;
101
102        while(!(SPI0CN & (1 << _SPIF)));
103        SPI0CN &= ~(1 << _SPIF);
104
105        release_cs();
106}
107
108void enc28j60_read_buffer_memory(uint8_t *_data, uint16_t len)
109{
110        get_cs();
111
112        SPI0DAT = OPCODE_RBM | 0x1A;
113        while(!(SPI0CN & (1 << _SPIF)));
114        SPI0CN &= ~(1 << _SPIF);
115
116        while(len--) {
117                SPI0DAT = 0x00;
118                while(!(SPI0CN & (1 << _SPIF)));
119                *_data++ = SPI0DAT;
120                SPI0CN &= ~(1 << _SPIF);
121        }
122
123        release_cs();
124}
125
126void enc28j60_write_buffer_memory(const uint8_t *_data, uint16_t len)
127{
128        get_cs();
129
130        SPI0DAT = OPCODE_WBM | 0x1A;
131        while(!(SPI0CN & (1 << _SPIF)));
132        SPI0CN &= ~(1 << _SPIF);
133
134        while(len--) {
135                SPI0DAT = *_data++;
136                while(!(SPI0CN & (1 << _SPIF)));
137                SPI0CN &= ~(1 << _SPIF);
138        }
139
140        release_cs();
141}
142
143void enc28j60_bit_field_set(uint8_t reg_addr, uint8_t bitfield) __reentrant
144{
145        enc28j60_set_bank(reg_addr);
146
147        get_cs();
148
149        SPI0DAT = OPCODE_BFS | (reg_addr & ADDR_MASK);
150        while(!(SPI0CN & (1 << _SPIF)));
151        SPI0CN &= ~(1 << _SPIF);
152
153        SPI0DAT = bitfield;
154        while(!(SPI0CN & (1 << _SPIF)));
155        SPI0CN &= ~(1 << _SPIF);
156
157        release_cs();
158}
159
160void enc28j60_bit_field_clear(uint8_t reg_addr, uint8_t bitfield) __reentrant
161{
162        enc28j60_set_bank(reg_addr);
163
164        get_cs();
165
166        SPI0DAT = OPCODE_BFC | (reg_addr & ADDR_MASK);
167        while(!(SPI0CN & (1 << _SPIF)));
168        SPI0CN &= ~(1 << _SPIF);
169
170        SPI0DAT = bitfield;
171        while(!(SPI0CN & (1 << _SPIF)));
172        SPI0CN &= ~(1 << _SPIF);
173
174        release_cs();
175}
176
177uint16_t enc28j60_read_PHY_register(uint8_t reg_addr)
178{
179        enc28j60_write_control_register(MIREGADR, reg_addr);
180        enc28j60_bit_field_set(MICMD, (1 << MICMD_MIIRD));
181
182        while(enc28j60_read_control_register(MISTAT) & (1 << MISTAT_BUSY));
183
184        enc28j60_bit_field_clear(MICMD, (1 << MICMD_MIIRD));
185
186        return enc28j60_read_control_register(MIRDL) | (enc28j60_read_control_register(MIRDH) << 8);
187}
188
189void enc28j60_write_PHY_register(uint8_t reg_addr, uint16_t _data)
190{
191        enc28j60_write_control_register(MIREGADR, reg_addr);
192        enc28j60_write_control_register(MIWRL, _data);
193        enc28j60_write_control_register(MIWRH, _data >> 8);
194
195        while(enc28j60_read_control_register(MISTAT) & (1 << MISTAT_BUSY));
196}
197
198/*
199 * Benutzerfunktionen
200 *
201 */
202void enc28j60_init(const uint8_t *mac_addr)
203{
204        SPI0CKR = 1;
205        SPI0CFG |= (1 << _MSTEN);
206        SPI0CN |= (1 << _NSSMD1) | (1 << _SPIEN);
207
208        enc28j60_system_reset();
209
210        delay_20ms();
211
212        /* Empfangspuffer einstellen */
213        enc28j60_write_control_register(ERXSTL, RECEIVE_BUFFER_START);
214        enc28j60_write_control_register(ERXSTH, (uint16_t)RECEIVE_BUFFER_START >> 8);
215        enc28j60_write_control_register(ERXNDL, RECEIVE_BUFFER_END);
216        enc28j60_write_control_register(ERXNDH, (uint16_t)RECEIVE_BUFFER_END >> 8);
217
218        // enc28j60_write_control_register(MACON1, 0x00);
219        // enc28j60_set_bank(MACON1);
220
221
222        /* MAC initialisieren */
223        enc28j60_bit_field_set(MACON1, (1 << MACON1_MARXEN) |
224                                       (1 << MACON1_TXPAUS) |
225                                       (1 << MACON1_RXPAUS));
226
227        enc28j60_bit_field_clear(MACON2, 1 << MACON2_MARST);
228        enc28j60_bit_field_set(MACON3, (1 << MACON3_FULDPX) |
229                                       (1 << MACON3_FRMLNEN) |
230                                       (1 << MACON3_TXCRCEN) |
231                                       (1 << MACON3_PADCFG0));
232
233        enc28j60_write_control_register(MAMXFLL, MAX_FRAME_LENGTH + 4);
234        enc28j60_write_control_register(MAMXFLH, (MAX_FRAME_LENGTH + 4) >> 8);
235
236        /* Siehe ENC28J60 Datenblatt, Seite 34 */
237        enc28j60_write_control_register(MABBIPG, 0x15);
238        enc28j60_write_control_register(MAIPGL, 0x12);
239
240        enc28j60_write_control_register(MAADR1, mac_addr[0]);
241        enc28j60_write_control_register(MAADR2, mac_addr[1]);
242        enc28j60_write_control_register(MAADR3, mac_addr[2]);
243        enc28j60_write_control_register(MAADR4, mac_addr[3]);
244        enc28j60_write_control_register(MAADR5, mac_addr[4]);
245        enc28j60_write_control_register(MAADR6, mac_addr[5]);
246
247        enc28j60_write_PHY_register(PHCON1, 1 << PHCON1_PDPXMD);
248
249        enc28j60_bit_field_set(ECON1, 1 << ECON1_RXEN);
250}
251
252void enc28j60_transmit(const uint8_t *_data, uint16_t len)
253{
254        uint8_t per_packet_control_byte = 0;
255        uint16_t address = TRANSMIT_BUFFER_START;
256
257        while(enc28j60_read_control_register(ECON1) & (1 << ECON1_TXRTS));
258
259        enc28j60_write_control_register(ETXSTL, address);
260        enc28j60_write_control_register(ETXSTH, address >> 8);
261
262        enc28j60_write_control_register(EWRPTL, address);
263        enc28j60_write_control_register(EWRPTH, address >> 8);
264
265        enc28j60_write_buffer_memory(&per_packet_control_byte, 1);
266        enc28j60_write_buffer_memory(_data, len);
267
268        address += len;
269
270        enc28j60_write_control_register(ETXNDL, address);
271        enc28j60_write_control_register(ETXNDH, address >> 8);
272
273        enc28j60_bit_field_clear(EIR, 1 << EIR_TXIF);
274        enc28j60_bit_field_set(EIE, 1 << EIE_TXIE);
275
276        enc28j60_bit_field_set(ECON1, 1 << ECON1_TXRTS);
277}
278
279uint16_t enc28j60_receive(uint8_t *_data, uint16_t max_len)
280{
281        uint16_t length, temp;
282        uint8_t header[6];
283
284        if(!enc28j60_read_control_register(EPKTCNT))
285                return 0;
286
287        enc28j60_write_control_register(ERDPTL, next_packet_addr);
288        enc28j60_write_control_register(ERDPTH, next_packet_addr >> 8);
289
290        enc28j60_read_buffer_memory(header, 6);
291        next_packet_addr = header[0] | (header[1] << 8);
292
293        length = (header[2] | (((uint16_t)header[3]) << 8)) - 4;
294
295        length = length > max_len ? max_len : length;
296
297        enc28j60_read_buffer_memory(_data, length);
298
299        /* ENC28J60 Errata, Seite 6, Issue 14 */
300        temp = enc28j60_read_control_register(ERXSTL) | (enc28j60_read_control_register(ERXSTH) << 8);
301
302        if(next_packet_addr == temp) {
303                enc28j60_write_control_register(ERXRDPTL, RECEIVE_BUFFER_END);
304                enc28j60_write_control_register(ERXRDPTH, RECEIVE_BUFFER_END >> 8);
305        } else {
306                temp = next_packet_addr - 1;
307                enc28j60_write_control_register(ERXRDPTL, temp);
308                enc28j60_write_control_register(ERXRDPTH, temp >> 8);
309        }
310
311        enc28j60_bit_field_set(ECON2, 1 << ECON2_PKTDEC);
312
313        return length;
314}
315