1 | #include "../main.h"
|
2 | #include "lanDriver.h"
|
3 |
|
4 | typedef struct enc{
|
5 |
|
6 | volatile unsigned char current_bank;
|
7 | volatile unsigned int next_packet_ptr;
|
8 | unsigned char revision;
|
9 |
|
10 | }enc28j60_t;
|
11 |
|
12 | char initSequence[] = {
|
13 | // Address, Value
|
14 | //setup bank0 (config stored in progmem, see above)
|
15 | //tx buffer:
|
16 | ENC28J60_REG_ETXSTL, lo8(ENC28J60_TX_BUFFER_START), //start lo
|
17 | ENC28J60_REG_ETXSTH, hi8(ENC28J60_TX_BUFFER_START), //start hi
|
18 | ENC28J60_REG_ETXNDL, lo8(ENC28J60_TX_BUFFER_END ), //end lo
|
19 | ENC28J60_REG_ETXNDH, hi8(ENC28J60_TX_BUFFER_END ), //end hi
|
20 | //rx buffer
|
21 | ENC28J60_REG_ERXSTL, lo8(ENC28J60_RX_BUFFER_START), //start lo
|
22 | ENC28J60_REG_ERXSTH, hi8(ENC28J60_RX_BUFFER_START), //start hi
|
23 | ENC28J60_REG_ERXNDL, lo8(ENC28J60_RX_BUFFER_END ), //end lo
|
24 | ENC28J60_REG_ERXNDH, hi8(ENC28J60_RX_BUFFER_END ), //end hi
|
25 | //rx ptr:
|
26 | //ENC28J60_REG_ERDPTL, lo8(ENC28J60_RX_BUFFER_START+1),
|
27 | //ENC28J60_REG_ERDPTH, hi8(ENC28J60_RX_BUFFER_START+1),
|
28 |
|
29 | //setup bank2: (see microchip datasheet p.36)
|
30 | //1.) clear the MARST bit in MACON2.
|
31 | ENC28J60_REG_MACON2, 0x00,
|
32 | //2.) mac rx enable, activate pause control frame support
|
33 | ENC28J60_REG_MACON1, ((1<<ENC28J60_BIT_MARXEN)|(1<<ENC28J60_BIT_RXPAUS)|(1<<ENC28J60_BIT_TXPAUS)),
|
34 | //3.) setup MACON3: auto padding of small packets, add crc, enable frame length check:
|
35 | ENC28J60_REG_MACON3, ((1<<ENC28J60_BIT_PADCFG0)|(1<<ENC28J60_BIT_TXCRCEN)|(1<<ENC28J60_BIT_FRMLNEN)),
|
36 | //4.) dont set up MACON4 (use default)
|
37 | //5.) setup maximum framelenght to 1518:
|
38 | ENC28J60_REG_MAMXFLL, lo8(1518),
|
39 | ENC28J60_REG_MAMXFLH, hi8(1518),
|
40 | //6.) set up back-to-back gap: 0x15 for full duplex / 0x12 for half duplex
|
41 | ENC28J60_REG_MABBIPG, 0x12, //half duplex
|
42 | //7.) setup non-back-to-back gap: use 0x12
|
43 | ENC28J60_REG_MAIPGL, 0x12,
|
44 | //8.) setup non-back-to-back gap high byte: 0x0C for half duplex:
|
45 | ENC28J60_REG_MAIPGH, 0x0C, //half duplex
|
46 | //9.) dont change MACLCON1+2 / MACLCON2 might be changed for networks with long wires !
|
47 |
|
48 | //setup bank3:
|
49 | //10.) programm mac address: BYTE BACKWARD !
|
50 | ENC28J60_REG_MAADR5, NIC_MAC0,
|
51 | ENC28J60_REG_MAADR4, NIC_MAC1,
|
52 | ENC28J60_REG_MAADR3, NIC_MAC2,
|
53 | ENC28J60_REG_MAADR2, NIC_MAC3,
|
54 | ENC28J60_REG_MAADR1, NIC_MAC4,
|
55 | ENC28J60_REG_MAADR0, NIC_MAC5
|
56 | };
|
57 |
|
58 |
|
59 | static char read_LAN(char adr);
|
60 | static char write_LAN(char adr, char data);
|
61 | static void select_bank(char bank);
|
62 | static char cmd_LAN(char cmd, char data);
|
63 | static void write_phy_LAN(char adr, unsigned int data);
|
64 | void cmd_write_LAN(char hi, char lo);
|
65 |
|
66 | enc28j60_t enc;
|
67 |
|
68 | /**
|
69 | * This function initiates the lan chip
|
70 | * @return Errorcode LANINIT_
|
71 | */
|
72 | char init_LAN(){
|
73 |
|
74 | char str[12];
|
75 | // to force bank update
|
76 | enc.current_bank=0xff;
|
77 |
|
78 | // Reset ENC 28 J 60
|
79 | PORTC &=~(1<<LAN_RST);
|
80 | _delay_ms(10);
|
81 | // Release
|
82 | PORTC |=(1<<LAN_RST);
|
83 |
|
84 |
|
85 | // Wait for Startup (at least 50 us)
|
86 | _delay_us(60);
|
87 | // To prevent bad requests wait again at least 5 ms
|
88 | _delay_ms(10);
|
89 |
|
90 | sendStringRS232("vor while\r\n");
|
91 |
|
92 | itoa((int)read_LAN(ENC28J60_REG_ESTAT),str,2);
|
93 | sendStringRS232("Statusregister: 0b");
|
94 | sendStringRS232(str);
|
95 | sendStringRS232("\r\n");
|
96 |
|
97 | // Waiting until chip is ready
|
98 | while(!(read_LAN(ENC28J60_REG_ESTAT) & 0x01)){};
|
99 |
|
100 | sendStringRS232("nach while\r\n");
|
101 |
|
102 | itoa((int)read_LAN(ENC28J60_REG_ESTAT),str,2);
|
103 | sendStringRS232("Statusregister: 0b");
|
104 | sendStringRS232(str);
|
105 | sendStringRS232("\r\n");
|
106 |
|
107 | sendStringRS232("vor for\r\n");
|
108 |
|
109 | /*
|
110 | for(int i=0; i<(2*22);i += 2){
|
111 | write_LAN(initSequence[i], initSequence[1+1]);
|
112 | }
|
113 | */
|
114 |
|
115 |
|
116 |
|
117 | write_LAN(ENC28J60_REG_ETXSTL,lo8(ENC28J60_TX_BUFFER_START));
|
118 |
|
119 | itoa((int)read_LAN(ENC28J60_REG_ETXSTL),str,16);
|
120 | sendStringRS232("\r\nb0 ETXSTL: 0x");
|
121 | sendStringRS232(str);
|
122 | sendStringRS232(" sollte 0x00 heisen !!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n");
|
123 |
|
124 | write_LAN(ENC28J60_REG_ETXSTH,hi8(ENC28J60_TX_BUFFER_START));
|
125 |
|
126 | itoa((int)read_LAN(ENC28J60_REG_ETXSTH),str,16);
|
127 | sendStringRS232("\r\nb0 ETXSTH: 0x");
|
128 | sendStringRS232(str);
|
129 | sendStringRS232(" sollte 0x1a heisen !!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n");
|
130 |
|
131 |
|
132 |
|
133 | write_LAN(ENC28J60_REG_MAIPGL, 0x12);
|
134 |
|
135 | itoa((int)read_LAN(ENC28J60_REG_MAIPGL),str,16);
|
136 | sendStringRS232("\r\nb2 MAIPGL: 0x");
|
137 | sendStringRS232(str);
|
138 | sendStringRS232(" sollte 0x12 heisen !!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n");
|
139 |
|
140 | write_LAN(ENC28J60_REG_MAADR5, NIC_MAC0);
|
141 |
|
142 | itoa((int)read_LAN(ENC28J60_REG_MAADR5),str,16);
|
143 | sendStringRS232("\r\nb3 MAADR5: 0x");
|
144 | sendStringRS232(str);
|
145 | sendStringRS232(" sollte 0xac heisen !!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n");
|
146 |
|
147 | sendStringRS232("nach for\r\n");
|
148 |
|
149 | //no loop back of transmitted frames
|
150 | //write_phy_LAN(ENC28J60_PHY_PHCON2, (1<<ENC28J60_BIT_HDLDIS));
|
151 |
|
152 | sendStringRS232("nach loop while\r\n");
|
153 |
|
154 | //enable interrups
|
155 | //enc28j60_write_address(ENC28J60_REG_EIE, (1<<6)|(1<<7));
|
156 |
|
157 | //enable rx
|
158 | //enc28j60_write_address(ENC28J60_REG_ECON1, (1<<ENC28J60_BIT_RXEN));
|
159 | //enc28j60_spi_write_word(ENC28J60_OP_BFS|ENC28J60_REG_ECON1, (1<<ENC28J60_BIT_RXEN));
|
160 |
|
161 | // Set 16 Bit LED Register to configure LEDs
|
162 | // LEDA: link status, LEDB: RX&TX activity
|
163 | //write_phy_LAN(ENC28J60_PHY_PHLCON,0x0472);
|
164 | sendStringRS232("nach led enable\r\n");
|
165 |
|
166 |
|
167 |
|
168 |
|
169 | return LANINIT_FAILD;
|
170 | }
|
171 |
|
172 |
|
173 | /**
|
174 | * This function prints out the Errorcodes from Laninit
|
175 | * @param err Errorcode
|
176 | */
|
177 | void printLanInitErrors(char err){
|
178 | switch (err){
|
179 | case LANINIT_FAILD:{
|
180 | sendStringRS232("fail (unknown reason)");
|
181 | break;
|
182 | }
|
183 | case LANINIT_SUCCESSFULL:{
|
184 | sendStringRS232("successfully");
|
185 | break;
|
186 | }
|
187 |
|
188 | }
|
189 |
|
190 | }
|
191 |
|
192 |
|
193 | /** PROTECTED
|
194 | *
|
195 | * Reads from the config register
|
196 | */
|
197 | static char read_LAN(char adr){
|
198 |
|
199 | // Select bank
|
200 | select_bank(adr);
|
201 | // Add Command
|
202 | adr = adr | LAN_RCR;
|
203 | // read
|
204 | return cmd_LAN(adr,0);
|
205 | }
|
206 |
|
207 |
|
208 | /**
|
209 | * This function writes to the PHY Registers
|
210 | *
|
211 | * @param ard address of the Register
|
212 | * @param data data to be write to tha PHY register
|
213 | *
|
214 | */
|
215 | static void write_phy_LAN(char adr, unsigned int data){
|
216 |
|
217 | //see microchip datasheet p.21
|
218 | //set address to MIREGADR:
|
219 | write_LAN(ENC28J60_REG_MIREGADR,adr);
|
220 |
|
221 | // Send data
|
222 | write_LAN(ENC28J60_REG_MIWRL, data&0xff);
|
223 | write_LAN(ENC28J60_REG_MIWRH, data>>8);
|
224 |
|
225 | // wait until phy reg is written
|
226 |
|
227 | char str[12];
|
228 | sendStringRS232("read phy REG_MISTAT\r\n");
|
229 | itoa((int)enc.current_bank,str,10);
|
230 | sendStringRS232("bank: ");
|
231 | sendStringRS232(str);
|
232 | sendStringRS232("\r\n");
|
233 |
|
234 | while(read_LAN(ENC28J60_REG_MISTAT) & (1<<ENC28J60_BIT_MISTAT_BUSY))
|
235 | {
|
236 |
|
237 |
|
238 |
|
239 |
|
240 | _delay_ms(10000);
|
241 |
|
242 | /*
|
243 | itoa((int)read_LAN(ENC28J60_REG_MISTAT),str,2);
|
244 | sendStringRS232("Statusregister1: 0b");
|
245 | sendStringRS232(str);
|
246 | sendStringRS232("\r\n");
|
247 |
|
248 | itoa((int)read_LAN(ENC28J60_REG_ESTAT),str,2);
|
249 | sendStringRS232("Statusregister2: 0b");
|
250 | sendStringRS232(str);
|
251 | sendStringRS232("\r\n");
|
252 | _delay_ms(10000);
|
253 | */
|
254 | }
|
255 | }
|
256 |
|
257 |
|
258 | /**
|
259 | * Writes to the config registers
|
260 | */
|
261 | static char write_LAN(char adr, char data){
|
262 |
|
263 | // Select bank
|
264 | select_bank(adr);
|
265 | // Add Command
|
266 | adr = adr | LAN_WCR;
|
267 | // Write
|
268 | return cmd_LAN(adr,data);
|
269 | }
|
270 |
|
271 |
|
272 | /**
|
273 | * Select a bank of config registers
|
274 | */
|
275 | static void select_bank(char bank){
|
276 |
|
277 | if((bank & 0x60) != enc.current_bank){
|
278 | sendStringRS232("switch from bank ");
|
279 |
|
280 | char str[12];
|
281 |
|
282 | itoa((int)enc.current_bank>>5,str,10);
|
283 |
|
284 | sendStringRS232(str);
|
285 |
|
286 |
|
287 | enc.current_bank = (bank & 0x60);
|
288 |
|
289 | sendStringRS232(" to bank ");
|
290 |
|
291 | itoa((int)enc.current_bank>>5,str,10);
|
292 |
|
293 | sendStringRS232(str);
|
294 |
|
295 | sendStringRS232(" \r\n");
|
296 |
|
297 |
|
298 |
|
299 | // release old bank select
|
300 | cmd_write_LAN((LAN_BFC|ENC28J60_REG_ECON1),((1<<ENC28J60_BIT_ECON1_BSEL0) | (1<<ENC28J60_BIT_ECON1_BSEL1)));
|
301 | // Set new one
|
302 | cmd_write_LAN((LAN_BFC|ENC28J60_REG_ECON1),enc.current_bank>>5);
|
303 |
|
304 | char bk = (cmd_LAN((LAN_RCR | ENC28J60_REG_ECON1),0)) & ((1<<ENC28J60_BIT_ECON1_BSEL0) | (1<<ENC28J60_BIT_ECON1_BSEL1));
|
305 | //(read_LAN(ENC28J60_REG_ECON1)&((1<<ENC28J60_BIT_ECON1_BSEL0) | (1<<ENC28J60_BIT_ECON1_BSEL1)));
|
306 | if(bk == enc.current_bank>>5){
|
307 | sendStringRS232("bankset ok ");
|
308 |
|
309 | sendStringRS232("bank ");
|
310 | itoa((int)enc.current_bank>>5,str,10);
|
311 |
|
312 | sendStringRS232(str);
|
313 |
|
314 | sendStringRS232("\r\n");
|
315 | }else{
|
316 |
|
317 | sendStringRS232("Error while bankset ");
|
318 | sendStringRS232(" to bank ");
|
319 |
|
320 | itoa((int)enc.current_bank>>5,str,10);
|
321 |
|
322 | sendStringRS232(str);
|
323 |
|
324 | sendStringRS232(" anstatt ");
|
325 |
|
326 | itoa((int)bk,str,10);
|
327 |
|
328 | sendStringRS232(str);
|
329 |
|
330 | sendStringRS232("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n");
|
331 | }
|
332 |
|
333 | }
|
334 | }
|
335 |
|
336 |
|
337 | /**
|
338 | * This function sends a command with data or without data if data = 0
|
339 | *
|
340 | */
|
341 | static char cmd_LAN(char cmd, char data){
|
342 |
|
343 | char ret=0;
|
344 | char str[12];
|
345 |
|
346 | // Release CS SD Card (low active)
|
347 | PORTB &=~(1<<LAN_CS);
|
348 |
|
349 | SPI_SEND(cmd);
|
350 |
|
351 | // Write
|
352 | if(data)
|
353 | SPI_SEND(data);
|
354 |
|
355 |
|
356 | //if MAC* or MI* is read a second dummy read is neccesary
|
357 | if(cmd & 0x80){
|
358 | ret = SPI_RECEIVE_0x00();
|
359 | /*
|
360 | itoa((int)ret,str,2);
|
361 | sendStringRS232("Statusregister-: 0b");
|
362 | sendStringRS232(str);
|
363 | sendStringRS232("\r\n");
|
364 | sendStringRS232("data & 0x80\r\n");*/
|
365 | }
|
366 |
|
367 | ret = SPI_RECEIVE_0x00();
|
368 |
|
369 | // set CS LAN (low active)
|
370 | PORTB |=(1<<LAN_CS);
|
371 |
|
372 | return ret;
|
373 | }
|
374 |
|
375 | void cmd_write_LAN(char hi, char lo){
|
376 | // Release CS SD Card (low active)
|
377 | PORTB &=~(1<<LAN_CS);
|
378 |
|
379 | SPI_SEND(hi);
|
380 | SPI_SEND(lo);
|
381 |
|
382 | // set CS LAN (low active)
|
383 | PORTB |=(1<<LAN_CS);
|
384 | }
|