root / arduino-1.0 / libraries / Ethernet / utility / w5100.h @ 58d82c77
History | View | Annotate | Download (13.6 KB)
1 | 58d82c77 | Tom Mullins | /*
|
---|---|---|---|
2 | * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
||
3 | *
|
||
4 | * This file is free software; you can redistribute it and/or modify
|
||
5 | * it under the terms of either the GNU General Public License version 2
|
||
6 | * or the GNU Lesser General Public License version 2.1, both as
|
||
7 | * published by the Free Software Foundation.
|
||
8 | */
|
||
9 | |||
10 | #ifndef W5100_H_INCLUDED
|
||
11 | #define W5100_H_INCLUDED
|
||
12 | |||
13 | #include <avr/pgmspace.h> |
||
14 | #include <SPI.h> |
||
15 | |||
16 | #define MAX_SOCK_NUM 4 |
||
17 | |||
18 | typedef uint8_t SOCKET;
|
||
19 | |||
20 | #define IDM_OR 0x8000 |
||
21 | #define IDM_AR0 0x8001 |
||
22 | #define IDM_AR1 0x8002 |
||
23 | #define IDM_DR 0x8003 |
||
24 | /*
|
||
25 | class MR {
|
||
26 | public:
|
||
27 | static const uint8_t RST = 0x80;
|
||
28 | static const uint8_t PB = 0x10;
|
||
29 | static const uint8_t PPPOE = 0x08;
|
||
30 | static const uint8_t LB = 0x04;
|
||
31 | static const uint8_t AI = 0x02;
|
||
32 | static const uint8_t IND = 0x01;
|
||
33 | };
|
||
34 | */
|
||
35 | /*
|
||
36 | class IR {
|
||
37 | public:
|
||
38 | static const uint8_t CONFLICT = 0x80;
|
||
39 | static const uint8_t UNREACH = 0x40;
|
||
40 | static const uint8_t PPPoE = 0x20;
|
||
41 | static const uint8_t SOCK0 = 0x01;
|
||
42 | static const uint8_t SOCK1 = 0x02;
|
||
43 | static const uint8_t SOCK2 = 0x04;
|
||
44 | static const uint8_t SOCK3 = 0x08;
|
||
45 | static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); };
|
||
46 | };
|
||
47 | */
|
||
48 | |||
49 | class SnMR { |
||
50 | public:
|
||
51 | static const uint8_t CLOSE = 0x00; |
||
52 | static const uint8_t TCP = 0x01; |
||
53 | static const uint8_t UDP = 0x02; |
||
54 | static const uint8_t IPRAW = 0x03; |
||
55 | static const uint8_t MACRAW = 0x04; |
||
56 | static const uint8_t PPPOE = 0x05; |
||
57 | static const uint8_t ND = 0x20; |
||
58 | static const uint8_t MULTI = 0x80; |
||
59 | }; |
||
60 | |||
61 | enum SockCMD {
|
||
62 | Sock_OPEN = 0x01,
|
||
63 | Sock_LISTEN = 0x02,
|
||
64 | Sock_CONNECT = 0x04,
|
||
65 | Sock_DISCON = 0x08,
|
||
66 | Sock_CLOSE = 0x10,
|
||
67 | Sock_SEND = 0x20,
|
||
68 | Sock_SEND_MAC = 0x21,
|
||
69 | Sock_SEND_KEEP = 0x22,
|
||
70 | Sock_RECV = 0x40
|
||
71 | }; |
||
72 | |||
73 | /*class SnCmd {
|
||
74 | public:
|
||
75 | static const uint8_t OPEN = 0x01;
|
||
76 | static const uint8_t LISTEN = 0x02;
|
||
77 | static const uint8_t CONNECT = 0x04;
|
||
78 | static const uint8_t DISCON = 0x08;
|
||
79 | static const uint8_t CLOSE = 0x10;
|
||
80 | static const uint8_t SEND = 0x20;
|
||
81 | static const uint8_t SEND_MAC = 0x21;
|
||
82 | static const uint8_t SEND_KEEP = 0x22;
|
||
83 | static const uint8_t RECV = 0x40;
|
||
84 | };
|
||
85 | */
|
||
86 | |||
87 | class SnIR { |
||
88 | public:
|
||
89 | static const uint8_t SEND_OK = 0x10; |
||
90 | static const uint8_t TIMEOUT = 0x08; |
||
91 | static const uint8_t RECV = 0x04; |
||
92 | static const uint8_t DISCON = 0x02; |
||
93 | static const uint8_t CON = 0x01; |
||
94 | }; |
||
95 | |||
96 | class SnSR { |
||
97 | public:
|
||
98 | static const uint8_t CLOSED = 0x00; |
||
99 | static const uint8_t INIT = 0x13; |
||
100 | static const uint8_t LISTEN = 0x14; |
||
101 | static const uint8_t SYNSENT = 0x15; |
||
102 | static const uint8_t SYNRECV = 0x16; |
||
103 | static const uint8_t ESTABLISHED = 0x17; |
||
104 | static const uint8_t FIN_WAIT = 0x18; |
||
105 | static const uint8_t CLOSING = 0x1A; |
||
106 | static const uint8_t TIME_WAIT = 0x1B; |
||
107 | static const uint8_t CLOSE_WAIT = 0x1C; |
||
108 | static const uint8_t LAST_ACK = 0x1D; |
||
109 | static const uint8_t UDP = 0x22; |
||
110 | static const uint8_t IPRAW = 0x32; |
||
111 | static const uint8_t MACRAW = 0x42; |
||
112 | static const uint8_t PPPOE = 0x5F; |
||
113 | }; |
||
114 | |||
115 | class IPPROTO { |
||
116 | public:
|
||
117 | static const uint8_t IP = 0; |
||
118 | static const uint8_t ICMP = 1; |
||
119 | static const uint8_t IGMP = 2; |
||
120 | static const uint8_t GGP = 3; |
||
121 | static const uint8_t TCP = 6; |
||
122 | static const uint8_t PUP = 12; |
||
123 | static const uint8_t UDP = 17; |
||
124 | static const uint8_t IDP = 22; |
||
125 | static const uint8_t ND = 77; |
||
126 | static const uint8_t RAW = 255; |
||
127 | }; |
||
128 | |||
129 | class W5100Class { |
||
130 | |||
131 | public:
|
||
132 | void init();
|
||
133 | |||
134 | /**
|
||
135 | * @brief This function is being used for copy the data form Receive buffer of the chip to application buffer.
|
||
136 | *
|
||
137 | * It calculate the actual physical address where one has to read
|
||
138 | * the data from Receive buffer. Here also take care of the condition while it exceed
|
||
139 | * the Rx memory uper-bound of socket.
|
||
140 | */
|
||
141 | void read_data(SOCKET s, volatile uint8_t * src, volatile uint8_t * dst, uint16_t len); |
||
142 | |||
143 | /**
|
||
144 | * @brief This function is being called by send() and sendto() function also.
|
||
145 | *
|
||
146 | * This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
|
||
147 | * register. User should read upper byte first and lower byte later to get proper value.
|
||
148 | */
|
||
149 | void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len); |
||
150 | /**
|
||
151 | * @brief A copy of send_data_processing that uses the provided ptr for the
|
||
152 | * write offset. Only needed for the "streaming" UDP API, where
|
||
153 | * a single UDP packet is built up over a number of calls to
|
||
154 | * send_data_processing_ptr, because TX_WR doesn't seem to get updated
|
||
155 | * correctly in those scenarios
|
||
156 | * @param ptr value to use in place of TX_WR. If 0, then the value is read
|
||
157 | * in from TX_WR
|
||
158 | * @return New value for ptr, to be used in the next call
|
||
159 | */
|
||
160 | // FIXME Update documentation
|
||
161 | void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len); |
||
162 | |||
163 | /**
|
||
164 | * @brief This function is being called by recv() also.
|
||
165 | *
|
||
166 | * This function read the Rx read pointer register
|
||
167 | * and after copy the data from receive buffer update the Rx write pointer register.
|
||
168 | * User should read upper byte first and lower byte later to get proper value.
|
||
169 | */
|
||
170 | void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek = 0); |
||
171 | |||
172 | inline void setGatewayIp(uint8_t *_addr); |
||
173 | inline void getGatewayIp(uint8_t *_addr); |
||
174 | |||
175 | inline void setSubnetMask(uint8_t *_addr); |
||
176 | inline void getSubnetMask(uint8_t *_addr); |
||
177 | |||
178 | inline void setMACAddress(uint8_t * addr); |
||
179 | inline void getMACAddress(uint8_t * addr); |
||
180 | |||
181 | inline void setIPAddress(uint8_t * addr); |
||
182 | inline void getIPAddress(uint8_t * addr); |
||
183 | |||
184 | inline void setRetransmissionTime(uint16_t timeout); |
||
185 | inline void setRetransmissionCount(uint8_t _retry); |
||
186 | |||
187 | void execCmdSn(SOCKET s, SockCMD _cmd);
|
||
188 | |||
189 | uint16_t getTXFreeSize(SOCKET s); |
||
190 | uint16_t getRXReceivedSize(SOCKET s); |
||
191 | |||
192 | |||
193 | // W5100 Registers
|
||
194 | // ---------------
|
||
195 | private:
|
||
196 | static uint8_t write(uint16_t _addr, uint8_t _data);
|
||
197 | static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); |
||
198 | static uint8_t read(uint16_t addr);
|
||
199 | static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len);
|
||
200 | |||
201 | #define __GP_REGISTER8(name, address) \
|
||
202 | static inline void write##name(uint8_t _data) { \ |
||
203 | write(address, _data); \ |
||
204 | } \ |
||
205 | static inline uint8_t read##name() { \ |
||
206 | return read(address); \
|
||
207 | } |
||
208 | #define __GP_REGISTER16(name, address) \
|
||
209 | static void write##name(uint16_t _data) { \ |
||
210 | write(address, _data >> 8); \
|
||
211 | write(address+1, _data & 0xFF); \ |
||
212 | } \ |
||
213 | static uint16_t read##name() { \ |
||
214 | uint16_t res = read(address); \ |
||
215 | res = (res << 8) + read(address + 1); \ |
||
216 | return res; \
|
||
217 | } |
||
218 | #define __GP_REGISTER_N(name, address, size) \
|
||
219 | static uint16_t write##name(uint8_t *_buff) { \ |
||
220 | return write(address, _buff, size); \
|
||
221 | } \ |
||
222 | static uint16_t read##name(uint8_t *_buff) { \ |
||
223 | return read(address, _buff, size); \
|
||
224 | } |
||
225 | |||
226 | public: |
||
227 | __GP_REGISTER8 (MR, 0x0000); // Mode |
||
228 | __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address |
||
229 | __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address |
||
230 | __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address |
||
231 | __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address |
||
232 | __GP_REGISTER8 (IR, 0x0015); // Interrupt |
||
233 | __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask |
||
234 | __GP_REGISTER16(RTR, 0x0017); // Timeout address |
||
235 | __GP_REGISTER8 (RCR, 0x0019); // Retry count |
||
236 | __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size |
||
237 | __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size |
||
238 | __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode |
||
239 | __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer |
||
240 | __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number |
||
241 | __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode |
||
242 | __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode |
||
243 | |||
244 | #undef __GP_REGISTER8
|
||
245 | #undef __GP_REGISTER16
|
||
246 | #undef __GP_REGISTER_N
|
||
247 | |||
248 | // W5100 Socket registers
|
||
249 | // ----------------------
|
||
250 | private:
|
||
251 | static inline uint8_t readSn(SOCKET _s, uint16_t _addr); |
||
252 | static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data); |
||
253 | static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); |
||
254 | static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); |
||
255 | |||
256 | static const uint16_t CH_BASE = 0x0400; |
||
257 | static const uint16_t CH_SIZE = 0x0100; |
||
258 | |||
259 | #define __SOCKET_REGISTER8(name, address) \
|
||
260 | static inline void write##name(SOCKET _s, uint8_t _data) { \ |
||
261 | writeSn(_s, address, _data); \ |
||
262 | } \ |
||
263 | static inline uint8_t read##name(SOCKET _s) { \ |
||
264 | return readSn(_s, address); \
|
||
265 | } |
||
266 | #define __SOCKET_REGISTER16(name, address) \
|
||
267 | static void write##name(SOCKET _s, uint16_t _data) { \ |
||
268 | writeSn(_s, address, _data >> 8); \
|
||
269 | writeSn(_s, address+1, _data & 0xFF); \ |
||
270 | } \ |
||
271 | static uint16_t read##name(SOCKET _s) { \ |
||
272 | uint16_t res = readSn(_s, address); \ |
||
273 | res = (res << 8) + readSn(_s, address + 1); \ |
||
274 | return res; \
|
||
275 | } |
||
276 | #define __SOCKET_REGISTER_N(name, address, size) \
|
||
277 | static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \ |
||
278 | return writeSn(_s, address, _buff, size); \
|
||
279 | } \ |
||
280 | static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \ |
||
281 | return readSn(_s, address, _buff, size); \
|
||
282 | } |
||
283 | |||
284 | public: |
||
285 | __SOCKET_REGISTER8(SnMR, 0x0000) // Mode |
||
286 | __SOCKET_REGISTER8(SnCR, 0x0001) // Command |
||
287 | __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt |
||
288 | __SOCKET_REGISTER8(SnSR, 0x0003) // Status |
||
289 | __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port |
||
290 | __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr |
||
291 | __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr |
||
292 | __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port |
||
293 | __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size |
||
294 | __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode |
||
295 | __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS |
||
296 | __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL |
||
297 | __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size |
||
298 | __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer |
||
299 | __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer |
||
300 | __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size |
||
301 | __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer |
||
302 | __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) |
||
303 | |||
304 | #undef __SOCKET_REGISTER8
|
||
305 | #undef __SOCKET_REGISTER16
|
||
306 | #undef __SOCKET_REGISTER_N
|
||
307 | |||
308 | |||
309 | private: |
||
310 | static const uint8_t RST = 7; // Reset BIT |
||
311 | |||
312 | static const int SOCKETS = 4; |
||
313 | static const uint16_t SMASK = 0x07FF; // Tx buffer MASK |
||
314 | static const uint16_t RMASK = 0x07FF; // Rx buffer MASK |
||
315 | public:
|
||
316 | static const uint16_t SSIZE = 2048; // Max Tx buffer size |
||
317 | private:
|
||
318 | static const uint16_t RSIZE = 2048; // Max Rx buffer size |
||
319 | uint16_t SBASE[SOCKETS]; // Tx buffer base address
|
||
320 | uint16_t RBASE[SOCKETS]; // Rx buffer base address
|
||
321 | |||
322 | private:
|
||
323 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||
324 | inline static void initSS() { DDRB |= _BV(4); }; |
||
325 | inline static void setSS() { PORTB &= ~_BV(4); }; |
||
326 | inline static void resetSS() { PORTB |= _BV(4); }; |
||
327 | #elif defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
|
||
328 | inline static void initSS() { DDRB |= _BV(0); }; |
||
329 | inline static void setSS() { PORTB &= ~_BV(0); }; |
||
330 | inline static void resetSS() { PORTB |= _BV(0); }; |
||
331 | #else
|
||
332 | inline static void initSS() { DDRB |= _BV(2); }; |
||
333 | inline static void setSS() { PORTB &= ~_BV(2); }; |
||
334 | inline static void resetSS() { PORTB |= _BV(2); }; |
||
335 | #endif
|
||
336 | |||
337 | }; |
||
338 | |||
339 | extern W5100Class W5100;
|
||
340 | |||
341 | uint8_t W5100Class::readSn(SOCKET _s, uint16_t _addr) { |
||
342 | return read(CH_BASE + _s * CH_SIZE + _addr);
|
||
343 | } |
||
344 | |||
345 | uint8_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) { |
||
346 | return write(CH_BASE + _s * CH_SIZE + _addr, _data);
|
||
347 | } |
||
348 | |||
349 | uint16_t W5100Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { |
||
350 | return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
|
||
351 | } |
||
352 | |||
353 | uint16_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { |
||
354 | return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
|
||
355 | } |
||
356 | |||
357 | void W5100Class::getGatewayIp(uint8_t *_addr) {
|
||
358 | readGAR(_addr); |
||
359 | } |
||
360 | |||
361 | void W5100Class::setGatewayIp(uint8_t *_addr) {
|
||
362 | writeGAR(_addr); |
||
363 | } |
||
364 | |||
365 | void W5100Class::getSubnetMask(uint8_t *_addr) {
|
||
366 | readSUBR(_addr); |
||
367 | } |
||
368 | |||
369 | void W5100Class::setSubnetMask(uint8_t *_addr) {
|
||
370 | writeSUBR(_addr); |
||
371 | } |
||
372 | |||
373 | void W5100Class::getMACAddress(uint8_t *_addr) {
|
||
374 | readSHAR(_addr); |
||
375 | } |
||
376 | |||
377 | void W5100Class::setMACAddress(uint8_t *_addr) {
|
||
378 | writeSHAR(_addr); |
||
379 | } |
||
380 | |||
381 | void W5100Class::getIPAddress(uint8_t *_addr) {
|
||
382 | readSIPR(_addr); |
||
383 | } |
||
384 | |||
385 | void W5100Class::setIPAddress(uint8_t *_addr) {
|
||
386 | writeSIPR(_addr); |
||
387 | } |
||
388 | |||
389 | void W5100Class::setRetransmissionTime(uint16_t _timeout) {
|
||
390 | writeRTR(_timeout); |
||
391 | } |
||
392 | |||
393 | void W5100Class::setRetransmissionCount(uint8_t _retry) {
|
||
394 | writeRCR(_retry); |
||
395 | } |
||
396 | |||
397 | #endif |