W5200(WIZ820io) network interface

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers w5100.cpp Source File

w5100.cpp

00001 /*
00002  * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
00003  *
00004  * This file is free software; you can redistribute it and/or modify
00005  * it under the terms of either the GNU General Public License version 2
00006  * or the GNU Lesser General Public License version 2.1, both as
00007  * published by the Free Software Foundation.
00008  */
00009 
00010 #include <stdio.h>
00011 #include <string.h>
00012 #include "mbed.h"
00013 #include "w5100.h"
00014 #ifndef MBED
00015 #include <avr/interrupt.h>
00016 #endif //MBED
00017 
00018 // W5100 controller instance
00019 W5100Class W5100;
00020 
00021 #define TX_RX_MAX_BUF_SIZE 2048
00022 #define TX_BUF 0x1100
00023 #define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
00024 
00025 #ifdef W5200
00026 #define TXBUF_BASE 0x8000
00027 #define RXBUF_BASE 0xC000
00028 #else
00029 #define TXBUF_BASE 0x4000
00030 #define RXBUF_BASE 0x6000
00031 #endif
00032 
00033 #ifdef MBED
00034 
00035 SPI* pSPI = NULL;
00036 DigitalOut* pCS = NULL;
00037 
00038 inline void delay(int n) { wait_ms(n); }
00039 inline static void initSS(){ pCS->write(1); }
00040 inline static void setSS() { pCS->write(0); }
00041 inline static void resetSS() { pCS->write(1); }
00042 
00043 #endif //MBED
00044 
00045 void W5100Class::init(void)
00046 {
00047   if (!pSPI) {
00048     pSPI = new SPI(p11, p12, p13); // mosi, miso, sclk
00049   }
00050   if (!pCS) {
00051     pCS = new DigitalOut(p14);
00052   }
00053   initSS();
00054   writeMR(1<<RST);
00055   
00056 #ifdef W5200
00057   for (int i=0; i<MAX_SOCK_NUM; i++) {
00058     write((0x4000 + i * 0x100 + 0x001F), 2);
00059     write((0x4000 + i * 0x100 + 0x001E), 2);
00060   }
00061 #else  
00062   writeTMSR(0x55);
00063   writeRMSR(0x55);
00064 #endif
00065 
00066   for (int i=0; i<MAX_SOCK_NUM; i++) {
00067     SBASE[i] = TXBUF_BASE + SSIZE * i;
00068     RBASE[i] = RXBUF_BASE + RSIZE * i;
00069   }
00070 }
00071 
00072 uint16_t W5100Class::getTXFreeSize(SOCKET s)
00073 {
00074   uint16_t val=0, val1=0;
00075   do {
00076     val1 = readSnTX_FSR(s);
00077     if (val1 != 0)
00078       val = readSnTX_FSR(s);
00079   } 
00080   while (val != val1);
00081   return val;
00082 }
00083 
00084 uint16_t W5100Class::getRXReceivedSize(SOCKET s)
00085 {
00086   uint16_t val=0,val1=0;
00087   do {
00088     val1 = readSnRX_RSR(s);
00089     if (val1 != 0)
00090       val = readSnRX_RSR(s);
00091   } 
00092   while (val != val1);
00093   return val;
00094 }
00095 
00096 
00097 void W5100Class::send_data_processing(SOCKET s, const uint8_t *data, uint16_t len)
00098 {
00099   // This is same as having no offset in a call to send_data_processing_offset
00100   send_data_processing_offset(s, 0, data, len);
00101 }
00102 
00103 void W5100Class::send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len)
00104 {
00105   uint16_t ptr = readSnTX_WR(s);
00106   ptr += data_offset;
00107   uint16_t offset = ptr & SMASK;
00108   uint16_t dstAddr = offset + SBASE[s];
00109 
00110   if (offset + len > SSIZE) 
00111   {
00112     // Wrap around circular buffer
00113     uint16_t size = SSIZE - offset;
00114     write(dstAddr, data, size);
00115     write(SBASE[s], data + size, len - size);
00116   } 
00117   else {
00118     write(dstAddr, data, len);
00119   }
00120 
00121   ptr += len;
00122   writeSnTX_WR(s, ptr);
00123 }
00124 
00125 
00126 void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
00127 {
00128   uint16_t ptr;
00129   ptr = readSnRX_RD(s);
00130   read_data(s, (uint8_t *)ptr, data, len);
00131   if (!peek)
00132   {
00133     ptr += len;
00134     writeSnRX_RD(s, ptr);
00135   }
00136 }
00137 
00138 void W5100Class::read_data(SOCKET s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len)
00139 {
00140   uint16_t size;
00141   uint16_t src_mask;
00142   uint16_t src_ptr;
00143 
00144 #ifdef MBED
00145   src_mask = (int)src & RMASK;
00146 #else 
00147   src_mask = (uint16_t)src & RMASK;
00148 #endif //MBED
00149   src_ptr = RBASE[s] + src_mask;
00150 
00151   if( (src_mask + len) > RSIZE ) 
00152   {
00153     size = RSIZE - src_mask;
00154     read(src_ptr, (uint8_t *)dst, size);
00155     dst += size;
00156     read(RBASE[s], (uint8_t *) dst, len - size);
00157   } 
00158   else
00159     read(src_ptr, (uint8_t *) dst, len);
00160 }
00161 
00162 
00163 uint8_t W5100Class::write(uint16_t _addr, uint8_t _data)
00164 {
00165   setSS();  
00166   
00167 #ifdef W5200
00168   pSPI->write(_addr >> 8);
00169   pSPI->write(_addr & 0xFF);
00170   pSPI->write(0x80);
00171   pSPI->write(0x01);
00172 #else    
00173   pSPI->write(0xF0);
00174   pSPI->write(_addr >> 8);
00175   pSPI->write(_addr & 0xFF);
00176 #endif  
00177   pSPI->write(_data);
00178   resetSS();
00179   return 1;
00180 }
00181 
00182 uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len)
00183 {
00184     
00185 #ifdef W5200
00186     setSS();
00187     pSPI->write(_addr >> 8);
00188     pSPI->write(_addr & 0xFF);
00189     pSPI->write((0x80 | ((_len & 0x7F00) >> 8)));
00190     pSPI->write(_len & 0x00FF);
00191 
00192   for (uint16_t i=0; i<_len; i++)
00193   {
00194     pSPI->write(_buf[i]);
00195 
00196   }
00197     resetSS();
00198 #else    
00199     
00200   for (uint16_t i=0; i<_len; i++)
00201   {
00202     setSS();    
00203     pSPI->write(0xF0);
00204     pSPI->write(_addr >> 8);
00205     pSPI->write(_addr & 0xFF);
00206     _addr++;
00207     pSPI->write(_buf[i]);
00208     resetSS();
00209   }
00210 #endif
00211   
00212   return _len;
00213 }
00214 
00215 uint8_t W5100Class::read(uint16_t _addr)
00216 {
00217   setSS();  
00218 #ifdef W5200
00219   pSPI->write(_addr >> 8);
00220   pSPI->write(_addr & 0xFF);
00221   pSPI->write(0x00);
00222   pSPI->write(0x01);
00223 #else
00224   pSPI->write(0x0F);
00225   pSPI->write(_addr >> 8);
00226   pSPI->write(_addr & 0xFF);
00227 #endif
00228   
00229   uint8_t _data = pSPI->write(0);
00230   resetSS();
00231   return _data;
00232 }
00233 
00234 uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
00235 {
00236 #ifdef W5200
00237     setSS();
00238     pSPI->write(_addr >> 8);
00239     pSPI->write(_addr & 0xFF);
00240     pSPI->write((0x00 | ((_len & 0x7F00) >> 8)));
00241     pSPI->write(_len & 0x00FF);
00242 
00243   for (uint16_t i=0; i<_len; i++)
00244   {
00245     _buf[i] = pSPI->write(0);
00246 
00247   }
00248     resetSS();
00249 
00250 #else    
00251     
00252   for (uint16_t i=0; i<_len; i++)
00253   {
00254     setSS();
00255     pSPI->write(0x0F);
00256     pSPI->write(_addr >> 8);
00257     pSPI->write(_addr & 0xFF);
00258     _addr++;
00259     _buf[i] = pSPI->write(0);
00260     resetSS();
00261   }
00262 #endif  
00263   return _len;
00264 }
00265 
00266 void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) {
00267   // Send command to socket
00268   writeSnCR(s, _cmd);
00269   // Wait for command to complete
00270   while (readSnCR(s))
00271     ;
00272 }