Norimasa Okamoto / WIZ820ioNetIf
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers w5200.cpp Source File

w5200.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 "w5200.h"
00014 
00015 SPI* pSPI;
00016 DigitalOut* pCS;
00017 void initSS(){ pCS->write(1); }
00018 void setSS() { pCS->write(0); }
00019 void resetSS() { pCS->write(1); }
00020 
00021 // W5200 controller instance
00022 W5200Class W5200;
00023 
00024 #define TX_RX_MAX_BUF_SIZE 2048
00025 #define TX_BUF 0x1100
00026 #define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
00027 
00028 #define TXBUF_BASE 0x8000
00029 #define RXBUF_BASE 0xC000
00030 
00031 #if defined(TARGET_KL25Z)
00032 #define RESET_PIN PTD5
00033 #define CS_PIN    PTD0
00034 #define MOSI_PIN  PTD2
00035 #define MISO_PIN  PTD3
00036 #define SCLK_PIN  PTD1
00037 #endif
00038 
00039 void W5200Class::init(void)
00040 {
00041   if (!pSPI) {
00042     pSPI = new SPI(MOSI_PIN, MISO_PIN, SCLK_PIN); // mosi, miso, sclk
00043   }
00044   if (!pCS) {
00045     pCS = new DigitalOut(CS_PIN);
00046   }
00047   initSS();
00048   writeMR(1<<RST);
00049   
00050   for (int i=0; i<MAX_SOCK_NUM; i++) {
00051     write((0x4000 + i * 0x100 + 0x001F), 2);
00052     write((0x4000 + i * 0x100 + 0x001E), 2);
00053   }
00054 
00055   for (int i=0; i<MAX_SOCK_NUM; i++) {
00056     SBASE[i] = TXBUF_BASE + SSIZE * i;
00057     RBASE[i] = RXBUF_BASE + RSIZE * i;
00058   }
00059 }
00060 
00061 uint16_t W5200Class::getTXFreeSize(SOCKET s)
00062 {
00063   uint16_t val=0, val1=0;
00064   do {
00065     val1 = readSnTX_FSR(s);
00066     if (val1 != 0)
00067       val = readSnTX_FSR(s);
00068   } 
00069   while (val != val1);
00070   return val;
00071 }
00072 
00073 uint16_t W5200Class::getRXReceivedSize(SOCKET s)
00074 {
00075   uint16_t val=0,val1=0;
00076   do {
00077     val1 = readSnRX_RSR(s);
00078     if (val1 != 0)
00079       val = readSnRX_RSR(s);
00080   } 
00081   while (val != val1);
00082   return val;
00083 }
00084 
00085 
00086 void W5200Class::send_data_processing(SOCKET s, const uint8_t *data, uint16_t len)
00087 {
00088   // This is same as having no offset in a call to send_data_processing_offset
00089   send_data_processing_offset(s, 0, data, len);
00090 }
00091 
00092 void W5200Class::send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len)
00093 {
00094   uint16_t ptr = readSnTX_WR(s);
00095   ptr += data_offset;
00096   uint16_t offset = ptr & SMASK;
00097   uint16_t dstAddr = offset + SBASE[s];
00098 
00099   if (offset + len > SSIZE) 
00100   {
00101     // Wrap around circular buffer
00102     uint16_t size = SSIZE - offset;
00103     write(dstAddr, data, size);
00104     write(SBASE[s], data + size, len - size);
00105   } 
00106   else {
00107     write(dstAddr, data, len);
00108   }
00109 
00110   ptr += len;
00111   writeSnTX_WR(s, ptr);
00112 }
00113 
00114 
00115 void W5200Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
00116 {
00117   uint16_t ptr;
00118   ptr = readSnRX_RD(s);
00119   read_data(s, (uint8_t *)ptr, data, len);
00120   if (!peek)
00121   {
00122     ptr += len;
00123     writeSnRX_RD(s, ptr);
00124   }
00125 }
00126 
00127 void W5200Class::read_data(SOCKET s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len)
00128 {
00129   uint16_t size;
00130   uint16_t src_mask;
00131   uint16_t src_ptr;
00132 
00133   //src_mask = (uint16_t)src & RMASK;
00134   src_mask = (int)src & RMASK;
00135   src_ptr = RBASE[s] + src_mask;
00136 
00137   if( (src_mask + len) > RSIZE ) 
00138   {
00139     size = RSIZE - src_mask;
00140     read(src_ptr, (uint8_t *)dst, size);
00141     dst += size;
00142     read(RBASE[s], (uint8_t *) dst, len - size);
00143   } 
00144   else
00145     read(src_ptr, (uint8_t *) dst, len);
00146 }
00147 
00148 
00149 uint8_t W5200Class::write(uint16_t _addr, uint8_t _data)
00150 {
00151   setSS();  
00152   
00153   pSPI->write(_addr >> 8);
00154   pSPI->write(_addr & 0xFF);
00155   pSPI->write(0x80);
00156   pSPI->write(0x01);
00157   pSPI->write(_data);
00158   resetSS();
00159   return 1;
00160 }
00161 
00162 uint16_t W5200Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len)
00163 {
00164     setSS();
00165     pSPI->write(_addr >> 8);
00166     pSPI->write(_addr & 0xFF);
00167     pSPI->write((0x80 | ((_len & 0x7F00) >> 8)));
00168     pSPI->write(_len & 0x00FF);
00169 
00170   for (uint16_t i=0; i<_len; i++)
00171   {
00172     pSPI->write(_buf[i]);
00173   }
00174   resetSS();
00175  
00176   return _len;
00177 }
00178 
00179 uint8_t W5200Class::read(uint16_t _addr)
00180 {
00181   setSS();  
00182   pSPI->write(_addr >> 8);
00183   pSPI->write(_addr & 0xFF);
00184   pSPI->write(0x00);
00185   pSPI->write(0x01);
00186   uint8_t _data = pSPI->write(0);
00187   resetSS();
00188   return _data;
00189 }
00190 
00191 uint16_t W5200Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
00192 {
00193     setSS();
00194     pSPI->write(_addr >> 8);
00195     pSPI->write(_addr & 0xFF);
00196     pSPI->write((0x00 | ((_len & 0x7F00) >> 8)));
00197     pSPI->write(_len & 0x00FF);
00198 
00199     for (uint16_t i=0; i<_len; i++)
00200     {
00201         _buf[i] = pSPI->write(0);
00202     }
00203     resetSS();
00204     return _len;
00205 }
00206 
00207 void W5200Class::execCmdSn(SOCKET s, SockCMD _cmd) {
00208   // Send command to socket
00209   writeSnCR(s, _cmd);
00210   // Wait for command to complete
00211   while (readSnCR(s))
00212     ;
00213 }