D:/DRISSI/arduino-0022/arduino-0022/libraries/Ethernet/utility/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 <avr/interrupt.h>
00013 
00014 #include "w5100.h"
00015 
00016 // W5100 controller instance
00017 W5100Class W5100;
00018 
00019 #define TX_RX_MAX_BUF_SIZE 2048
00020 #define TX_BUF 0x1100
00021 #define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
00022 
00023 #define TXBUF_BASE 0x4000
00024 #define RXBUF_BASE 0x6000
00025 
00026 void W5100Class::init(void)
00027 {
00028   delay(300);
00029 
00030   SPI.begin();
00031   initSS();
00032   
00033   writeMR(1<<RST);
00034   writeTMSR(0x55);
00035   writeRMSR(0x55);
00036 
00037   for (int i=0; i<MAX_SOCK_NUM; i++) {
00038     SBASE[i] = TXBUF_BASE + SSIZE * i;
00039     RBASE[i] = RXBUF_BASE + RSIZE * i;
00040   }
00041 }
00042 
00043 uint16_t W5100Class::getTXFreeSize(SOCKET s)
00044 {
00045   uint16_t val=0, val1=0;
00046   do {
00047     val1 = readSnTX_FSR(s);
00048     if (val1 != 0)
00049       val = readSnTX_FSR(s);
00050   } 
00051   while (val != val1);
00052   return val;
00053 }
00054 
00055 uint16_t W5100Class::getRXReceivedSize(SOCKET s)
00056 {
00057   uint16_t val=0,val1=0;
00058   do {
00059     val1 = readSnRX_RSR(s);
00060     if (val1 != 0)
00061       val = readSnRX_RSR(s);
00062   } 
00063   while (val != val1);
00064   return val;
00065 }
00066 
00067 
00068 void W5100Class::send_data_processing(SOCKET s, uint8_t *data, uint16_t len)
00069 {
00070   uint16_t ptr = readSnTX_WR(s);
00071 
00072   uint16_t offset = ptr & SMASK;
00073   uint16_t dstAddr = offset + SBASE[s];
00074 
00075   if (offset + len > SSIZE) 
00076   {
00077     // Wrap around circular buffer
00078     uint16_t size = SSIZE - offset;
00079     write(dstAddr, data, size);
00080     write(SBASE[s], data + size, len - size);
00081   } 
00082   else {
00083     write(dstAddr, data, len);
00084   }
00085 
00086   ptr += len;
00087   writeSnTX_WR(s, ptr);
00088 }
00089 
00090 
00091 void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
00092 {
00093   uint16_t ptr;
00094   ptr = readSnRX_RD(s);
00095   read_data(s, (uint8_t *)ptr, data, len);
00096   if (!peek)
00097   {
00098     ptr += len;
00099     writeSnRX_RD(s, ptr);
00100   }
00101 }
00102 
00103 void W5100Class::read_data(SOCKET s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len)
00104 {
00105   uint16_t size;
00106   uint16_t src_mask;
00107   uint16_t src_ptr;
00108 
00109   src_mask = (uint16_t)src & RMASK;
00110   src_ptr = RBASE[s] + src_mask;
00111 
00112   if( (src_mask + len) > RSIZE ) 
00113   {
00114     size = RSIZE - src_mask;
00115     read(src_ptr, (uint8_t *)dst, size);
00116     dst += size;
00117     read(RBASE[s], (uint8_t *) dst, len - size);
00118   } 
00119   else
00120     read(src_ptr, (uint8_t *) dst, len);
00121 }
00122 
00123 
00124 uint8_t W5100Class::write(uint16_t _addr, uint8_t _data)
00125 {
00126   setSS();  
00127   SPI.transfer(0xF0);
00128   SPI.transfer(_addr >> 8);
00129   SPI.transfer(_addr & 0xFF);
00130   SPI.transfer(_data);
00131   resetSS();
00132   return 1;
00133 }
00134 
00135 uint16_t W5100Class::write(uint16_t _addr, uint8_t *_buf, uint16_t _len)
00136 {
00137   for (int i=0; i<_len; i++)
00138   {
00139     setSS();    
00140     SPI.transfer(0xF0);
00141     SPI.transfer(_addr >> 8);
00142     SPI.transfer(_addr & 0xFF);
00143     _addr++;
00144     SPI.transfer(_buf[i]);
00145     resetSS();
00146   }
00147   return _len;
00148 }
00149 
00150 uint8_t W5100Class::read(uint16_t _addr)
00151 {
00152   setSS();  
00153   SPI.transfer(0x0F);
00154   SPI.transfer(_addr >> 8);
00155   SPI.transfer(_addr & 0xFF);
00156   uint8_t _data = SPI.transfer(0);
00157   resetSS();
00158   return _data;
00159 }
00160 
00161 uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
00162 {
00163   for (int i=0; i<_len; i++)
00164   {
00165     setSS();
00166     SPI.transfer(0x0F);
00167     SPI.transfer(_addr >> 8);
00168     SPI.transfer(_addr & 0xFF);
00169     _addr++;
00170     _buf[i] = SPI.transfer(0);
00171     resetSS();
00172   }
00173   return _len;
00174 }
00175 
00176 void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) {
00177   // Send command to socket
00178   writeSnCR(s, _cmd);
00179   // Wait for command to complete
00180   while (readSnCR(s))
00181     ;
00182 }