Statistics
| Branch: | Revision:

root / arduino-1.0 / libraries / Ethernet / utility / w5100.cpp @ 58d82c77

History | View | Annotate | Download (3.78 KB)

1
/*
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
#include <stdio.h>
11
#include <string.h>
12
#include <avr/interrupt.h>
13

    
14
#include "w5100.h"
15

    
16
// W5100 controller instance
17
W5100Class W5100;
18

    
19
#define TX_RX_MAX_BUF_SIZE 2048
20
#define TX_BUF 0x1100
21
#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
22

    
23
#define TXBUF_BASE 0x4000
24
#define RXBUF_BASE 0x6000
25

    
26
void W5100Class::init(void)
27
{
28
  delay(300);
29

    
30
  SPI.begin();
31
  initSS();
32
  
33
  writeMR(1<<RST);
34
  writeTMSR(0x55);
35
  writeRMSR(0x55);
36

    
37
  for (int i=0; i<MAX_SOCK_NUM; i++) {
38
    SBASE[i] = TXBUF_BASE + SSIZE * i;
39
    RBASE[i] = RXBUF_BASE + RSIZE * i;
40
  }
41
}
42

    
43
uint16_t W5100Class::getTXFreeSize(SOCKET s)
44
{
45
  uint16_t val=0, val1=0;
46
  do {
47
    val1 = readSnTX_FSR(s);
48
    if (val1 != 0)
49
      val = readSnTX_FSR(s);
50
  } 
51
  while (val != val1);
52
  return val;
53
}
54

    
55
uint16_t W5100Class::getRXReceivedSize(SOCKET s)
56
{
57
  uint16_t val=0,val1=0;
58
  do {
59
    val1 = readSnRX_RSR(s);
60
    if (val1 != 0)
61
      val = readSnRX_RSR(s);
62
  } 
63
  while (val != val1);
64
  return val;
65
}
66

    
67

    
68
void W5100Class::send_data_processing(SOCKET s, const uint8_t *data, uint16_t len)
69
{
70
  // This is same as having no offset in a call to send_data_processing_offset
71
  send_data_processing_offset(s, 0, data, len);
72
}
73

    
74
void W5100Class::send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len)
75
{
76
  uint16_t ptr = readSnTX_WR(s);
77
  ptr += data_offset;
78
  uint16_t offset = ptr & SMASK;
79
  uint16_t dstAddr = offset + SBASE[s];
80

    
81
  if (offset + len > SSIZE) 
82
  {
83
    // Wrap around circular buffer
84
    uint16_t size = SSIZE - offset;
85
    write(dstAddr, data, size);
86
    write(SBASE[s], data + size, len - size);
87
  } 
88
  else {
89
    write(dstAddr, data, len);
90
  }
91

    
92
  ptr += len;
93
  writeSnTX_WR(s, ptr);
94
}
95

    
96

    
97
void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
98
{
99
  uint16_t ptr;
100
  ptr = readSnRX_RD(s);
101
  read_data(s, (uint8_t *)ptr, data, len);
102
  if (!peek)
103
  {
104
    ptr += len;
105
    writeSnRX_RD(s, ptr);
106
  }
107
}
108

    
109
void W5100Class::read_data(SOCKET s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len)
110
{
111
  uint16_t size;
112
  uint16_t src_mask;
113
  uint16_t src_ptr;
114

    
115
  src_mask = (uint16_t)src & RMASK;
116
  src_ptr = RBASE[s] + src_mask;
117

    
118
  if( (src_mask + len) > RSIZE ) 
119
  {
120
    size = RSIZE - src_mask;
121
    read(src_ptr, (uint8_t *)dst, size);
122
    dst += size;
123
    read(RBASE[s], (uint8_t *) dst, len - size);
124
  } 
125
  else
126
    read(src_ptr, (uint8_t *) dst, len);
127
}
128

    
129

    
130
uint8_t W5100Class::write(uint16_t _addr, uint8_t _data)
131
{
132
  setSS();  
133
  SPI.transfer(0xF0);
134
  SPI.transfer(_addr >> 8);
135
  SPI.transfer(_addr & 0xFF);
136
  SPI.transfer(_data);
137
  resetSS();
138
  return 1;
139
}
140

    
141
uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len)
142
{
143
  for (uint16_t i=0; i<_len; i++)
144
  {
145
    setSS();    
146
    SPI.transfer(0xF0);
147
    SPI.transfer(_addr >> 8);
148
    SPI.transfer(_addr & 0xFF);
149
    _addr++;
150
    SPI.transfer(_buf[i]);
151
    resetSS();
152
  }
153
  return _len;
154
}
155

    
156
uint8_t W5100Class::read(uint16_t _addr)
157
{
158
  setSS();  
159
  SPI.transfer(0x0F);
160
  SPI.transfer(_addr >> 8);
161
  SPI.transfer(_addr & 0xFF);
162
  uint8_t _data = SPI.transfer(0);
163
  resetSS();
164
  return _data;
165
}
166

    
167
uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
168
{
169
  for (uint16_t i=0; i<_len; i++)
170
  {
171
    setSS();
172
    SPI.transfer(0x0F);
173
    SPI.transfer(_addr >> 8);
174
    SPI.transfer(_addr & 0xFF);
175
    _addr++;
176
    _buf[i] = SPI.transfer(0);
177
    resetSS();
178
  }
179
  return _len;
180
}
181

    
182
void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) {
183
  // Send command to socket
184
  writeSnCR(s, _cmd);
185
  // Wait for command to complete
186
  while (readSnCR(s))
187
    ;
188
}