Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 712da91397
Fetching contributors…

Cannot retrieve contributors at this time

340 lines (314 sloc) 8.092 kB
// This code slightly follows the conventions of, but is not derived from:
// EHTERSHIELD_H library for Arduino etherShield
// Copyright (c) 2008 Xing Yu. All right reserved. (this is LGPL v2.1)
// It is however derived from the enc28j60 and ip code (which is GPL v2)
// Author: Pascal Stang
// Modified by: Guido Socher
// DHCP code: Andrew Lindsay
// Hence: GPL V2
//
// 2010-05-19 <jc@wippler.nl>
#include <EtherCard.h>
#include <stdarg.h>
#include <avr/eeprom.h>
byte Stash::map[256/8];
Stash::Block Stash::bufs[2];
uint8_t Stash::allocBlock () {
for (uint8_t i = 0; i < sizeof map; ++i)
if (map[i] != 0)
for (uint8_t j = 0; j < 8; ++j)
if (bitRead(map[i], j)) {
bitClear(map[i], j);
return (i << 3) + j;
}
return 0;
}
void Stash::freeBlock (uint8_t block) {
bitSet(map[block>>3], block & 7);
}
uint8_t Stash::fetchByte (uint8_t blk, uint8_t off) {
return blk == bufs[0].bnum ? bufs[0].bytes[off] :
blk == bufs[1].bnum ? bufs[1].bytes[off] :
ether.peekin(blk, off);
}
void Stash::initMap (uint8_t last) {
while (--last > 0)
freeBlock(last);
}
void Stash::load (uint8_t idx, uint8_t blk) {
if (blk != bufs[idx].bnum) {
if (idx == 0) {
ether.copyout(bufs[idx].bnum, bufs[idx].bytes);
if (blk == bufs[1].bnum)
bufs[1].bnum = 255; // forget read page if same
} else if (blk == bufs[0].bnum) {
// special case: read page is same as write buffer
memcpy(&bufs[1], &bufs[0], sizeof bufs[0]);
return;
}
bufs[idx].bnum = blk;
ether.copyin(bufs[idx].bnum, bufs[idx].bytes);
}
}
uint8_t Stash::freeCount () {
uint8_t count = 0;
for (uint8_t i = 0; i < 256/8; ++i)
for (uint8_t m = 0x80; m != 0; m >>= 1)
if (map[i] & m)
++count;
return count;
}
uint8_t Stash::create () {
uint8_t blk = allocBlock();
load(0, blk);
bufs[0].head.count = 0;
bufs[0].head.first = bufs[0].head.last = blk;
bufs[0].tail = sizeof (StashHeader);
bufs[0].next = 0;
return open(blk);
}
uint8_t Stash::open (uint8_t blk) {
curr = blk;
offs = sizeof (StashHeader);
load(1, curr);
memcpy((StashHeader*) this, bufs[1].bytes, sizeof (StashHeader));
return curr;
}
void Stash::save () {
load(0, first);
memcpy(bufs[0].bytes, (StashHeader*) this, sizeof (StashHeader));
if (bufs[1].bnum == first)
load(1, 0); // invalidates original in case it was the same block
}
void Stash::release () {
while (first > 0) {
freeBlock(first);
first = ether.peekin(first, 63);
}
}
void Stash::put (char c) {
load(0, last);
uint8_t t = bufs[0].tail;
bufs[0].bytes[t++] = c;
if (t <= 62)
bufs[0].tail = t;
else {
bufs[0].next = allocBlock();
last = bufs[0].next;
load(0, last);
bufs[0].tail = bufs[0].next = 0;
++count;
}
}
char Stash::get () {
load(1, curr);
if (curr == last && offs >= bufs[1].tail)
return 0;
uint8_t b = bufs[1].bytes[offs];
if (++offs >= 63 && curr != last) {
curr = bufs[1].next;
offs = 0;
}
return b;
}
uint16_t Stash::size () {
return 63 * count + fetchByte(last, 62) - sizeof (StashHeader);
}
static char* wtoa (word value, char* ptr) {
if (value > 9)
ptr = wtoa(value / 10, ptr);
*ptr = '0' + value % 10;
*++ptr = 0;
return ptr;
}
void Stash::prepare (PGM_P fmt, ...) {
Stash::load(0, 0);
word* segs = Stash::bufs[0].words;
*segs++ = strlen_P(fmt);
*segs++ = (word) fmt;
va_list ap;
va_start(ap, fmt);
for (;;) {
char c = pgm_read_byte(fmt++);
if (c == 0)
break;
if (c == '$') {
word argval = va_arg(ap, word), arglen = 0;
switch (pgm_read_byte(fmt++)) {
case 'D': {
char buf[7];
wtoa(argval, buf);
arglen = strlen(buf);
break;
}
case 'S':
arglen = strlen((const char*) argval);
break;
case 'F':
arglen = strlen_P((PGM_P) argval);
break;
case 'E': {
byte* s = (byte*) argval;
char c;
while ((c = eeprom_read_byte(s++)) != 0)
++arglen;
break;
}
case 'H': {
Stash stash (argval);
arglen = stash.size();
break;
}
}
*segs++ = argval;
Stash::bufs[0].words[0] += arglen - 2;
}
}
va_end(ap);
}
word Stash::length () {
Stash::load(0, 0);
return Stash::bufs[0].words[0];
}
void Stash::extract (word offset, word count, void* buf) {
Stash::load(0, 0);
word* segs = Stash::bufs[0].words;
PGM_P fmt = (PGM_P) *++segs;
Stash stash;
char mode = '@', tmp[7], *ptr, *out = (char*) buf;
for (word i = 0; i < offset + count; ) {
char c = 0;
switch (mode) {
case '@': {
c = pgm_read_byte(fmt++);
if (c == 0)
return;
if (c != '$')
break;
word arg = *++segs;
mode = pgm_read_byte(fmt++);
switch (mode) {
case 'D':
wtoa(arg, tmp);
ptr = tmp;
break;
case 'S':
case 'F':
case 'E':
ptr = (char*) arg;
break;
case 'H':
stash.open(arg);
ptr = (char*) &stash;
break;
}
continue;
}
case 'D':
case 'S':
c = *ptr++;
break;
case 'F':
c = pgm_read_byte(ptr++);
break;
case 'E':
c = eeprom_read_byte((byte*) ptr++);
break;
case 'H':
c = ((Stash*) ptr)->get();
break;
}
if (c == 0) {
mode = '@';
continue;
}
if (i >= offset)
*out++ = c;
++i;
}
}
word Stash::cleanup () {
Stash::load(0, 0);
word* segs = Stash::bufs[0].words;
PGM_P fmt = (PGM_P) *++segs;
for (;;) {
char c = pgm_read_byte(fmt++);
if (c == 0)
break;
if (c == '$') {
word arg = *++segs;
if (pgm_read_byte(fmt++) == 'H') {
Stash stash (arg);
stash.release();
}
}
}
}
void BufferFiller::emit_p(PGM_P fmt, ...) {
va_list ap;
va_start(ap, fmt);
for (;;) {
char c = pgm_read_byte(fmt++);
if (c == 0)
break;
if (c != '$') {
*ptr++ = c;
continue;
}
c = pgm_read_byte(fmt++);
switch (c) {
case 'D':
wtoa(va_arg(ap, word), (char*) ptr);
break;
case 'S':
strcpy((char*) ptr, va_arg(ap, const char*));
break;
case 'F': {
PGM_P s = va_arg(ap, PGM_P);
char c;
while ((c = pgm_read_byte(s++)) != 0)
*ptr++ = c;
continue;
}
case 'E': {
byte* s = va_arg(ap, byte*);
char c;
while ((c = eeprom_read_byte(s++)) != 0)
*ptr++ = c;
continue;
}
default:
*ptr++ = c;
continue;
}
ptr += strlen((char*) ptr);
}
va_end(ap);
}
EtherCard ether;
uint8_t EtherCard::mymac[6]; // my MAC address
uint8_t EtherCard::myip[4]; // my ip address
uint8_t EtherCard::mymask[4]; // my net mask
uint8_t EtherCard::gwip[4]; // gateway
uint8_t EtherCard::dhcpip[4]; // dhcp server
uint8_t EtherCard::dnsip[4]; // dns server
uint8_t EtherCard::hisip[4]; // dns result
uint16_t EtherCard::hisport = 80; // tcp port to browse to
uint8_t EtherCard::begin (const uint16_t size,
const uint8_t* macaddr,
uint8_t csPin) {
Stash::initMap(56);
copyMac(mymac, macaddr);
return initialize(size, mymac, csPin);
}
bool EtherCard::staticSetup (const uint8_t* my_ip,
const uint8_t* gw_ip,
const uint8_t* dns_ip) {
if (my_ip != 0)
copyIp(myip, my_ip);
if (gw_ip != 0)
setGwIp(gw_ip);
if (dns_ip != 0)
copyIp(dnsip, dns_ip);
return true;
}
Jump to Line
Something went wrong with that request. Please try again.