mirror of
https://github.com/arduino/Arduino.git
synced 2024-12-03 14:24:15 +01:00
eb47701c9f
Because the Mega uses a different pin for SS of the W5100, the SPI library wasn't setting it as an output. It was only setting the hardware SS pin of the ATmega1280, which is elsewhere on the board. Adding initSS() to W5100.init() fixed it.
177 lines
3.4 KiB
C++
177 lines
3.4 KiB
C++
/*
|
|
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
|
*
|
|
* This file is free software; you can redistribute it and/or modify
|
|
* it under the terms of either the GNU General Public License version 2
|
|
* or the GNU Lesser General Public License version 2.1, both as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <avr/interrupt.h>
|
|
|
|
#include "w5100.h"
|
|
|
|
// W5100 controller instance
|
|
W5100Class W5100;
|
|
|
|
#define TX_RX_MAX_BUF_SIZE 2048
|
|
#define TX_BUF 0x1100
|
|
#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
|
|
|
|
#define TXBUF_BASE 0x4000
|
|
#define RXBUF_BASE 0x6000
|
|
|
|
void W5100Class::init(void)
|
|
{
|
|
initSS();
|
|
|
|
writeMR(1<<RST);
|
|
writeTMSR(0x55);
|
|
writeRMSR(0x55);
|
|
|
|
for (int i=0; i<MAX_SOCK_NUM; i++) {
|
|
SBASE[i] = TXBUF_BASE + SSIZE * i;
|
|
RBASE[i] = RXBUF_BASE + RSIZE * i;
|
|
}
|
|
}
|
|
|
|
uint16_t W5100Class::getTXFreeSize(SOCKET s)
|
|
{
|
|
uint16_t val=0, val1=0;
|
|
do {
|
|
val1 = readSnTX_FSR(s);
|
|
if (val1 != 0)
|
|
val = readSnTX_FSR(s);
|
|
}
|
|
while (val != val1);
|
|
return val;
|
|
}
|
|
|
|
uint16_t W5100Class::getRXReceivedSize(SOCKET s)
|
|
{
|
|
uint16_t val=0,val1=0;
|
|
do {
|
|
val1 = readSnRX_RSR(s);
|
|
if (val1 != 0)
|
|
val = readSnRX_RSR(s);
|
|
}
|
|
while (val != val1);
|
|
return val;
|
|
}
|
|
|
|
|
|
void W5100Class::send_data_processing(SOCKET s, uint8_t *data, uint16_t len)
|
|
{
|
|
uint16_t ptr = readSnTX_WR(s);
|
|
|
|
uint16_t offset = ptr & SMASK;
|
|
uint16_t dstAddr = offset + SBASE[s];
|
|
|
|
if (offset + len > SSIZE)
|
|
{
|
|
// Wrap around circular buffer
|
|
uint16_t size = SSIZE - offset;
|
|
write(dstAddr, data, size);
|
|
write(SBASE[s], data + size, len - size);
|
|
}
|
|
else {
|
|
write(dstAddr, data, len);
|
|
}
|
|
|
|
ptr += len;
|
|
writeSnTX_WR(s, ptr);
|
|
}
|
|
|
|
|
|
void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len)
|
|
{
|
|
uint16_t ptr;
|
|
ptr = readSnRX_RD(s);
|
|
read_data(s, (uint8_t *)ptr, data, len);
|
|
ptr += len;
|
|
writeSnRX_RD(s, ptr);
|
|
}
|
|
|
|
void W5100Class::read_data(SOCKET s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len)
|
|
{
|
|
uint16_t size;
|
|
uint16_t src_mask;
|
|
uint16_t src_ptr;
|
|
|
|
src_mask = (uint16_t)src & RMASK;
|
|
src_ptr = RBASE[s] + src_mask;
|
|
|
|
if( (src_mask + len) > RSIZE )
|
|
{
|
|
size = RSIZE - src_mask;
|
|
read(src_ptr, (uint8_t *)dst, size);
|
|
dst += size;
|
|
read(RBASE[s], (uint8_t *) dst, len - size);
|
|
}
|
|
else
|
|
read(src_ptr, (uint8_t *) dst, len);
|
|
}
|
|
|
|
|
|
uint8_t W5100Class::write(uint16_t _addr, uint8_t _data)
|
|
{
|
|
setSS();
|
|
SPI.send(0xF0);
|
|
SPI.send(_addr >> 8);
|
|
SPI.send(_addr & 0xFF);
|
|
SPI.send(_data);
|
|
resetSS();
|
|
return 1;
|
|
}
|
|
|
|
uint16_t W5100Class::write(uint16_t _addr, uint8_t *_buf, uint16_t _len)
|
|
{
|
|
for (int i=0; i<_len; i++)
|
|
{
|
|
setSS();
|
|
SPI.send(0xF0);
|
|
SPI.send(_addr >> 8);
|
|
SPI.send(_addr & 0xFF);
|
|
_addr++;
|
|
SPI.send(_buf[i]);
|
|
resetSS();
|
|
}
|
|
return _len;
|
|
}
|
|
|
|
uint8_t W5100Class::read(uint16_t _addr)
|
|
{
|
|
setSS();
|
|
SPI.send(0x0F);
|
|
SPI.send(_addr >> 8);
|
|
SPI.send(_addr & 0xFF);
|
|
uint8_t _data = SPI.send(0);
|
|
resetSS();
|
|
return _data;
|
|
}
|
|
|
|
uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
|
|
{
|
|
for (int i=0; i<_len; i++)
|
|
{
|
|
setSS();
|
|
SPI.send(0x0F);
|
|
SPI.send(_addr >> 8);
|
|
SPI.send(_addr & 0xFF);
|
|
_addr++;
|
|
_buf[i] = SPI.send(0);
|
|
resetSS();
|
|
}
|
|
return _len;
|
|
}
|
|
|
|
void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) {
|
|
// Send command to socket
|
|
writeSnCR(s, _cmd);
|
|
// Wait for command to complete
|
|
while (readSnCR(s))
|
|
;
|
|
}
|