TOSAs OTA bootloader, test nodejs gateway and other misc changes.
Merge commit '5968ddf21964dff4043e70df8bd65286c90b5127' into development * commit '5968ddf21964dff4043e70df8bd65286c90b5127': Send reboot msg after message retrieval to deal with sensors going to sleep Node JS controller OTA Bootloader Binary message payload handling Remote reboot capability Misc fixes Conflicts: EthernetGateway/EthernetGateway.ino libraries/MySensors/MyGateway.cpp libraries/MySensors/MyMessage.h
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
*.o
|
||||
*.hex
|
||||
*.elf
|
||||
@@ -0,0 +1,66 @@
|
||||
PROJECT = MyOtaBootloader
|
||||
INCLUDES = ../libraries/MySensors
|
||||
|
||||
MCU = atmega328p
|
||||
CLK = 16000000L
|
||||
|
||||
ISP_PORT = com5
|
||||
ISP_SPEED = 115200
|
||||
ISP_PROTOCOL = stk500v2
|
||||
ISP_MCU = m328p
|
||||
# HFUSE = D8 - 4096 byte boot
|
||||
ISP_HFUSE = D8
|
||||
# LFUSE = 4E - Low power resonator (16MHz), fast start, clkdiv/8
|
||||
ISP_LFUSE = FF
|
||||
# EFUSE = 06 - 1.8V brownout
|
||||
ISP_EFUSE = 06
|
||||
ISP_ARGS = -c$(ISP_PROTOCOL) -P$(ISP_PORT) -b$(ISP_SPEED) -p$(ISP_MCU)
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
BINPATH = C:/Program Files (x86)/Arduino/hardware/tools/avr/bin/
|
||||
JAVAPATH = C:/Program Files/Java/jdk1.7.0_40/bin/
|
||||
JAVAC = $(JAVAPATH)javac.exe
|
||||
JAVA = $(JAVAPATH)java.exe
|
||||
else
|
||||
UNAME_S := $(shell uname -s)
|
||||
UNAME_P := $(shell uname -p)
|
||||
UNAME_M := $(shell uname -m)
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
ifeq ($(UNAME_P),x86_64)
|
||||
BINPATH = ../arduino/bin-linux64/bin/
|
||||
else ifneq ($(filter %86,$(UNAME_P)),)
|
||||
BINPATH = ../arduino/bin-linux32/bin/
|
||||
else ifneq ($(filter arm%,$(UNAME_M)),)
|
||||
BINPATH = /usr/bin/
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS = -c -g -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls -Wall -mmcu=$(MCU) -DF_CPU=$(CLK) -std=gnu99
|
||||
LDFLAGS = -Os -Wl,--section-start=.text=0x7000 -nostartfiles -mmcu=$(MCU)
|
||||
|
||||
all: clean out
|
||||
|
||||
clean:
|
||||
- rm *.o
|
||||
- rm *.elf
|
||||
- rm *.hex
|
||||
|
||||
$(PROJECT).o: $(PROJECT).c
|
||||
"$(BINPATH)avr-gcc" $(CFLAGS) -I$(INCLUDES) $< -o $@
|
||||
|
||||
$(PROJECT).elf: $(PROJECT).o
|
||||
"$(BINPATH)avr-gcc" $(LDFLAGS) -o $@ $< -lm
|
||||
|
||||
$(PROJECT).hex: $(PROJECT).elf
|
||||
"$(BINPATH)avr-objcopy" -O ihex -R .eeprom $< $@
|
||||
|
||||
out: $(PROJECT).hex
|
||||
"$(BINPATH)avr-size" $(PROJECT).elf
|
||||
|
||||
load: clean out isp
|
||||
|
||||
isp: $(PROJECT).hex
|
||||
"$(BINPATH)avrdude" $(ISP_ARGS) -e -u -Ulock:w:0x3f:m -qq -Uefuse:w:0x$(ISP_EFUSE):m -Uhfuse:w:0x$(ISP_HFUSE):m -Ulfuse:w:0x$(ISP_LFUSE):m -Ulock:w:0x0f:m
|
||||
"$(BINPATH)avrdude" $(ISP_ARGS) -V -q -s -Uflash:w:$(PROJECT).hex
|
||||
"$(BINPATH)avrdude" $(ISP_ARGS)
|
||||
@@ -0,0 +1,207 @@
|
||||
#include "MyOtaBootloader.h"
|
||||
|
||||
int main(void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
|
||||
|
||||
volatile char dummy;
|
||||
|
||||
EMPTY_INTERRUPT(WDT_vect);
|
||||
|
||||
static uint16_t calcCRCrom (const void* ptr, uint16_t len) {
|
||||
uint16_t crc = ~0;
|
||||
for (uint16_t i = 0; i < len; ++i)
|
||||
crc = _crc16_update(crc, pgm_read_byte((uint16_t) ptr + i));
|
||||
return crc;
|
||||
}
|
||||
|
||||
static uint8_t validFirmware () {
|
||||
return calcCRCrom(0, fc.blocks * FIRMWARE_BLOCK_SIZE) == fc.crc;
|
||||
}
|
||||
|
||||
static void reboot() {
|
||||
wdt_enable(WDTO_15MS);
|
||||
for (;;);
|
||||
}
|
||||
|
||||
static void startup() {
|
||||
if (validFirmware()) {
|
||||
wdt_disable();
|
||||
clock_prescale_set(orgClockDiv);
|
||||
((void(*)()) 0)();
|
||||
} else
|
||||
reboot();
|
||||
}
|
||||
|
||||
static void boot_program_page(uint32_t page, uint8_t *buf) {
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
eeprom_busy_wait();
|
||||
boot_page_erase(page);
|
||||
boot_spm_busy_wait();
|
||||
for (uint16_t i = 0; i < SPM_PAGESIZE; i += 2) {
|
||||
uint16_t w = *buf++;
|
||||
w += (*buf++) << 8;
|
||||
boot_page_fill(page + i, w);
|
||||
}
|
||||
boot_page_write(page);
|
||||
boot_spm_busy_wait();
|
||||
boot_rww_enable();
|
||||
SREG = sreg;
|
||||
}
|
||||
|
||||
static boolean sendWrite(MyMessage message) {
|
||||
return write(nc.parentNodeId, message.array, HEADER_SIZE + mGetLength(message), (message.destination == BROADCAST_ADDRESS));
|
||||
}
|
||||
|
||||
static uint8_t sendAndWait(uint8_t reqType, uint8_t resType) {
|
||||
msg.type = reqType;
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
sendWrite(msg);
|
||||
for (uint16_t j = 0; j < 20; j++) {
|
||||
wdt_reset();
|
||||
for (uint16_t j = 0; j < 100; j++) {
|
||||
wdt_reset();
|
||||
uint8_t pipe;
|
||||
boolean avail = available(&pipe);
|
||||
if (avail && pipe<=6) {
|
||||
read(rmsg.array,pipe);
|
||||
if(!(mGetVersion(rmsg) == PROTOCOL_VERSION))
|
||||
continue;
|
||||
if (rmsg.destination == nc.nodeId) {
|
||||
if (mGetCommand(rmsg) == C_INTERNAL) {
|
||||
if (rmsg.type == I_PING_ACK) {
|
||||
if (rmsg.data[0] < nc.distance - 1) {
|
||||
nc.distance = rmsg.data[0] + 1;
|
||||
nc.parentNodeId = rmsg.sender;
|
||||
eeprom_write_byte((uint8_t*)EEPROM_PARENT_NODE_ID_ADDRESS, nc.parentNodeId);
|
||||
eeprom_write_byte((uint8_t*)EEPROM_DISTANCE_ADDRESS, nc.distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((mGetCommand(rmsg) == mGetCommand(msg)) && (rmsg.type == resType))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
delaym(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main () {
|
||||
asm volatile ("clr __zero_reg__");
|
||||
// switch to 4 MHz
|
||||
orgClockDiv = clock_prescale_get();
|
||||
clock_prescale_set(F_CPU_DIV);
|
||||
MCUSR = 0;
|
||||
// enable watchdog to avoid deadlock
|
||||
wdt_enable(WDTO_8S);
|
||||
|
||||
#ifdef LED_DEBUG
|
||||
// enable LEDs for debugging and blink once as visual "bootloader started" sign
|
||||
led_init();
|
||||
blink(LED_MBOTH, 250);
|
||||
#endif
|
||||
#ifdef UART_DEBUG
|
||||
// enable UART for debugging and send start message
|
||||
uart_init();
|
||||
uart_puts("Go\n");
|
||||
#endif
|
||||
|
||||
wdt_reset();
|
||||
// initialize RF module
|
||||
begin();
|
||||
wdt_reset();
|
||||
// Read settings from EEPROM
|
||||
eeprom_read_block((void*)&nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(struct NodeConfig));
|
||||
wdt_reset();
|
||||
|
||||
msg.sender = nc.nodeId;
|
||||
msg.last = nc.nodeId;
|
||||
address(nc.nodeId);
|
||||
|
||||
msg.sensor = NODE_SENSOR_ID;
|
||||
mSetLength(msg, 0);
|
||||
mSetPayloadType(msg, P_STRING);
|
||||
mSetAck(msg,false);
|
||||
mSetVersion(msg, PROTOCOL_VERSION);
|
||||
|
||||
nc.distance = 255;
|
||||
mSetCommand(msg, C_INTERNAL);
|
||||
msg.destination = BROADCAST_ADDRESS;
|
||||
if (!sendAndWait(I_PING, I_PING_ACK))
|
||||
// starting existing firmware if no ping response (if firmware is valid)
|
||||
// reboot();
|
||||
startup();
|
||||
|
||||
msg.destination = GATEWAY_ADDRESS;
|
||||
|
||||
if (nc.nodeId == AUTO) {
|
||||
openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(nc.nodeId));
|
||||
if (!sendAndWait(I_ID_REQUEST, I_ID_RESPONSE))
|
||||
reboot();
|
||||
if (mGetPayloadType(rmsg) == P_BYTE)
|
||||
nc.nodeId = rmsg.data[0];
|
||||
else if (mGetPayloadType(rmsg) == P_STRING)
|
||||
nc.nodeId = atoi(rmsg.data);
|
||||
if (nc.nodeId == AUTO)
|
||||
reboot();
|
||||
eeprom_write_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, nc.nodeId);
|
||||
msg.sender = nc.nodeId;
|
||||
msg.last = nc.nodeId;
|
||||
address(nc.nodeId);
|
||||
}
|
||||
|
||||
// Read settings from EEPROM
|
||||
eeprom_read_block((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(struct FirmwareConfig));
|
||||
|
||||
mSetPayloadType(msg,P_CUSTOM);
|
||||
|
||||
FirmwareConfigRequest *firmwareConfigRequest = (FirmwareConfigRequest *)msg.data;
|
||||
mSetLength(msg, sizeof(FirmwareConfigRequest));
|
||||
mSetCommand(msg, C_STREAM);
|
||||
firmwareConfigRequest->type = fc.type;
|
||||
firmwareConfigRequest->version = fc.version;
|
||||
if (!sendAndWait(ST_FIRMWARE_CONFIG_REQUEST, ST_FIRMWARE_CONFIG_RESPONSE))
|
||||
// starting existing firmware if no firmware config response (if firmware is valid)
|
||||
// reboot();
|
||||
startup();
|
||||
FirmwareConfigResponse *firmwareConfigResponse = (FirmwareConfigResponse *)rmsg.data;
|
||||
if (firmwareConfigResponse->version == fc.version)
|
||||
if (firmwareConfigResponse->blocks == fc.blocks)
|
||||
if (firmwareConfigResponse->crc == fc.crc)
|
||||
if (validFirmware())
|
||||
startup();
|
||||
fc.type = firmwareConfigResponse->type;
|
||||
fc.version = firmwareConfigResponse->version;
|
||||
fc.blocks = firmwareConfigResponse->blocks;
|
||||
fc.crc = firmwareConfigResponse->crc;
|
||||
|
||||
FirmwareRequest *firmwareRequest = (FirmwareRequest *)msg.data;
|
||||
mSetLength(msg, sizeof(FirmwareRequest));
|
||||
firmwareRequest->type = fc.type;
|
||||
firmwareRequest->version = fc.version;
|
||||
for (uint16_t block = 0; block < fc.blocks; block++) {
|
||||
firmwareRequest->block = block;
|
||||
if (!sendAndWait(ST_FIRMWARE_REQUEST, ST_FIRMWARE_RESPONSE))
|
||||
reboot();
|
||||
FirmwareResponse *firmwareResponse = (FirmwareResponse *)rmsg.data;
|
||||
uint8_t offset = (block * FIRMWARE_BLOCK_SIZE) % SPM_PAGESIZE;
|
||||
memcpy(progBuf + offset, firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
|
||||
if (offset == SPM_PAGESIZE - FIRMWARE_BLOCK_SIZE)
|
||||
boot_program_page((block * FIRMWARE_BLOCK_SIZE) - offset, progBuf);
|
||||
}
|
||||
|
||||
wdt_reset();
|
||||
|
||||
if (validFirmware()) {
|
||||
eeprom_write_block((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(struct FirmwareConfig));
|
||||
#ifdef UART_DEBUG
|
||||
uart_puts("fw ok\n");
|
||||
} else {
|
||||
uart_puts("fw nok\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
reboot();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef MyOtaBootloader_H
|
||||
#define MyOtaBootloader_H
|
||||
|
||||
#include <avr/boot.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/power.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <util/crc16.h>
|
||||
|
||||
#include "MyMessage.h"
|
||||
#include "MySensor.h"
|
||||
#include "MyOtaBootloaderRF24.h"
|
||||
|
||||
#define FIRMWARE_BLOCK_SIZE 16
|
||||
|
||||
struct FirmwareConfig
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t version;
|
||||
uint16_t blocks;
|
||||
uint16_t crc;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t version;
|
||||
} FirmwareConfigRequest;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t version;
|
||||
uint16_t blocks;
|
||||
uint16_t crc;
|
||||
} FirmwareConfigResponse;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t version;
|
||||
uint16_t block;
|
||||
} FirmwareRequest;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t version;
|
||||
uint16_t block;
|
||||
uint8_t data[FIRMWARE_BLOCK_SIZE];
|
||||
} FirmwareResponse;
|
||||
|
||||
static struct NodeConfig nc;
|
||||
static struct FirmwareConfig fc;
|
||||
static MyMessage msg;
|
||||
static MyMessage rmsg;
|
||||
|
||||
static clock_div_t orgClockDiv = 0;
|
||||
|
||||
static uint8_t progBuf[SPM_PAGESIZE];
|
||||
|
||||
#endif // MyOtaBootloader_H
|
||||
@@ -0,0 +1,154 @@
|
||||
#ifndef MyOtaBootloaderHW_H
|
||||
#define MyOtaBootloaderHW_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <avr/power.h>
|
||||
|
||||
//#define LED_DEBUG
|
||||
//#define UART_DEBUG
|
||||
|
||||
// hardware
|
||||
// ********
|
||||
|
||||
#define F_CPU_DIV clock_div_4
|
||||
#define F_CPU_REAL F_CPU / (1 << F_CPU_DIV)
|
||||
#define UART_BAUD 9600UL
|
||||
#define DELAY_M 125 * (1 << F_CPU_DIV)
|
||||
|
||||
// boolean definition
|
||||
// ******************
|
||||
|
||||
typedef uint8_t bool;
|
||||
typedef uint8_t boolean;
|
||||
#define false 0x0
|
||||
#define true 0x1
|
||||
#define LOW 0x0
|
||||
#define HIGH 0x1
|
||||
|
||||
// delay
|
||||
// *****
|
||||
|
||||
static void delayu() {
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
static void delaym(uint16_t t) {
|
||||
uint16_t d, a;
|
||||
for (d = 0; d < t; d++)
|
||||
for (a = 0; a < DELAY_M; a++)
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
// LED debug
|
||||
// *********
|
||||
|
||||
#ifdef LED_DEBUG
|
||||
#define LED_DDR DDRD
|
||||
#define LED_PORT PORTD
|
||||
#define LED_RED 6 // Arduino Pin 6 <-> Bit 6 of port D
|
||||
#define LED_GREEN 7 // Arduino Pin 7 <-> Bit 7 of port D
|
||||
#define LED_MRED (1 << LED_RED)
|
||||
#define LED_MGREEN (1 << LED_GREEN)
|
||||
#define LED_MBOTH (LED_MRED | LED_MGREEN)
|
||||
|
||||
static void led_init() {
|
||||
LED_DDR |= LED_MBOTH;
|
||||
LED_PORT &= ~LED_MBOTH;
|
||||
}
|
||||
|
||||
static void blink(uint8_t mask, uint16_t time) {
|
||||
LED_PORT |= mask;
|
||||
if (time > 0)
|
||||
{
|
||||
delaym(time);
|
||||
LED_PORT &= ~mask;
|
||||
delaym(time);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// UART debug
|
||||
// **********
|
||||
|
||||
#ifdef UART_DEBUG
|
||||
static void uart_init()
|
||||
{
|
||||
UCSR0A = _BV(U2X0); //Double speed mode USART0
|
||||
UCSR0B = _BV(RXEN0) | _BV(TXEN0);
|
||||
UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
|
||||
UBRR0L = (uint8_t)( (F_CPU_REAL + UART_BAUD * 4L) / (UART_BAUD * 8L) - 1 );
|
||||
}
|
||||
|
||||
static void uart_putc(char ch) {
|
||||
while (!(UCSR0A & _BV(UDRE0)));
|
||||
UDR0 = ch;
|
||||
}
|
||||
|
||||
static void uart_puts(char *s)
|
||||
{
|
||||
while (*s)
|
||||
uart_putc(*s++);
|
||||
}
|
||||
|
||||
static void uart_puti(uint8_t i)
|
||||
{
|
||||
char s[5];
|
||||
itoa( i, s, 10 );
|
||||
uart_puts( s );
|
||||
}
|
||||
#endif
|
||||
|
||||
// SPI communication
|
||||
// *****************
|
||||
|
||||
#define SPI_DDR DDRB
|
||||
#define SPI_PORT PORTB
|
||||
#define SPI_PIN PINB
|
||||
#define SPI_SCLK 5 // Arduino Pin 13 <-> Bit 5 of port B
|
||||
#define SPI_MISO 4 // Arduino Pin 12 <-> Bit 4 of port B
|
||||
#define SPI_MOSI 3 // Arduino Pin 11 <-> Bit 3 of port B
|
||||
#define SPI_CSN 2 // Arduino Pin 10 <-> Bit 2 of port B
|
||||
#define SPI_CE 1 // Arduino Pin 9 <-> Bit 1 of port B
|
||||
|
||||
#define csnlow() SPI_PORT &= ~(1<<SPI_CSN);delaym(1)
|
||||
#define csnhigh() SPI_PORT |= (1<<SPI_CSN);delaym(1)
|
||||
#define celow() SPI_PORT &= ~(1<<SPI_CE);delaym(1)
|
||||
#define cehigh() SPI_PORT |= (1<<SPI_CE);delaym(1)
|
||||
|
||||
static void SPIinit()
|
||||
{
|
||||
SPI_DDR |= (1 << SPI_MOSI) + (1 << SPI_SCLK) + (1 << SPI_CE) + (1 << SPI_CSN);
|
||||
SPI_DDR &= ~(1 << SPI_MISO);
|
||||
SPI_PORT &= ~((1 << SPI_MOSI) + (1 << SPI_SCLK) + (1 << SPI_CE));
|
||||
SPI_PORT |= (1 << SPI_CSN);
|
||||
}
|
||||
|
||||
static uint8_t SPItransfer(uint8_t value)
|
||||
{
|
||||
uint8_t i;
|
||||
for(i = 0 ;i < 8;i++) {
|
||||
delayu();
|
||||
if ((value & 0x80) == 0x00)
|
||||
SPI_PORT &= ~(1 << SPI_MOSI);
|
||||
else
|
||||
SPI_PORT |= (1 << SPI_MOSI);
|
||||
value = (value << 1); // shift next bit into MSB..
|
||||
delayu();
|
||||
SPI_PORT |= (1 << SPI_SCLK);
|
||||
value |= ((SPI_PIN >> SPI_MISO) & 0x01); // capture current MISO bit
|
||||
delayu();
|
||||
SPI_PORT &= ~(1 << SPI_SCLK);
|
||||
delayu();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint8_t spiTrans(uint8_t cmd){
|
||||
uint8_t status;
|
||||
csnlow();
|
||||
status = SPItransfer( cmd );
|
||||
csnhigh();
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif // MyOtaBootloaderHW_H
|
||||
@@ -0,0 +1,253 @@
|
||||
#ifndef MyOtaBootloaderRF24_H
|
||||
#define MyOtaBootloaderRF24_H
|
||||
|
||||
#include "MyOtaBootloaderHW.h"
|
||||
#include "../libraries/MySensors/utility/nRF24L01.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// hardware-agnostic interface to transceiver
|
||||
// ******************************************
|
||||
// static void begin()
|
||||
// static void address(uint8_t addr)
|
||||
// static boolean write(uint8_t next, uint8_t* packet, uint8_t length, boolean multicast)
|
||||
// static bool available(uint8_t* pipe_num)
|
||||
// static void read(uint8_t* buf, uint8_t pipe)
|
||||
|
||||
typedef enum { RF24_PA_MIN = 0,RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_PA_ERROR } rf24_pa_dbm_e ;
|
||||
typedef enum { RF24_1MBPS = 0, RF24_2MBPS, RF24_250KBPS } rf24_datarate_e;
|
||||
|
||||
uint64_t pipe0_reading_address; /**< Last address set on pipe 0 for reading. */
|
||||
|
||||
static uint8_t read_register(uint8_t reg)
|
||||
{
|
||||
csnlow();
|
||||
SPItransfer( R_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
uint8_t result = SPItransfer(0xff);
|
||||
csnhigh();
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint8_t write_registers(uint8_t reg, const uint8_t* buf, uint8_t len)
|
||||
{
|
||||
uint8_t status;
|
||||
csnlow();
|
||||
status = SPItransfer( W_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
while ( len-- )
|
||||
SPItransfer(*buf++);
|
||||
csnhigh();
|
||||
return status;
|
||||
}
|
||||
|
||||
static uint8_t write_register(uint8_t reg, uint8_t value)
|
||||
{
|
||||
uint8_t status;
|
||||
csnlow();
|
||||
status = SPItransfer( W_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
SPItransfer(value);
|
||||
csnhigh();
|
||||
return status;
|
||||
}
|
||||
|
||||
static uint8_t read_payload(uint8_t* buf, uint8_t data_len)
|
||||
{
|
||||
#ifdef UART_DEBUG
|
||||
uart_puts("-> ");
|
||||
#endif
|
||||
uint8_t status;
|
||||
uint8_t* current = buf;
|
||||
csnlow();
|
||||
status = SPItransfer( R_RX_PAYLOAD );
|
||||
while ( data_len-- ) {
|
||||
*current = SPItransfer(0xFF);
|
||||
#ifdef UART_DEBUG
|
||||
uart_puti(*current);
|
||||
uart_putc(',');
|
||||
#endif
|
||||
current++;
|
||||
}
|
||||
csnhigh();
|
||||
#ifdef UART_DEBUG
|
||||
uart_putc('\n');
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
#define get_status() spiTrans(NOP)
|
||||
|
||||
static void powerUp(void)
|
||||
{
|
||||
if (!(read_register(CONFIG) & _BV(PWR_UP))){
|
||||
write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP));
|
||||
delaym(5);
|
||||
}
|
||||
}
|
||||
|
||||
#define convert_64_bit_to_byte_array(value, data) ((*(uint64_t *)(data)) = (uint64_t)(value))
|
||||
|
||||
static void startListening(void)
|
||||
{
|
||||
powerUp();
|
||||
write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX));
|
||||
write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
|
||||
if (pipe0_reading_address){
|
||||
uint8_t addressa[8];
|
||||
convert_64_bit_to_byte_array(pipe0_reading_address, addressa);
|
||||
write_registers(RX_ADDR_P0, addressa, 5);
|
||||
}
|
||||
spiTrans(FLUSH_RX);
|
||||
spiTrans(FLUSH_TX);
|
||||
cehigh();
|
||||
}
|
||||
|
||||
static void stopListening(void)
|
||||
{
|
||||
celow();
|
||||
spiTrans(FLUSH_TX);
|
||||
spiTrans(FLUSH_RX);
|
||||
write_register(CONFIG, read_register(CONFIG) & ~_BV(PRIM_RX));
|
||||
}
|
||||
|
||||
static void write_payload(const uint8_t* buf, uint8_t data_len, const uint8_t writeType)
|
||||
{
|
||||
#ifdef UART_DEBUG
|
||||
uart_puts("<- ");
|
||||
#endif
|
||||
const uint8_t* current = buf;
|
||||
csnlow();
|
||||
SPItransfer(writeType);
|
||||
while ( data_len-- ) {
|
||||
#ifdef UART_DEBUG
|
||||
uart_puti(*current);
|
||||
uart_putc(',');
|
||||
#endif
|
||||
SPItransfer(*current++);
|
||||
}
|
||||
csnhigh();
|
||||
#ifdef UART_DEBUG
|
||||
uart_putc('\n');
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool writem( const uint8_t* buf, uint8_t len, const bool multicast )
|
||||
{
|
||||
write_payload( buf, len, multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD) ;
|
||||
cehigh();
|
||||
celow();
|
||||
while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { }
|
||||
uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
|
||||
if( status & _BV(MAX_RT)){
|
||||
spiTrans(FLUSH_TX);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t getDynamicPayloadSize(void)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
csnlow();
|
||||
SPItransfer( R_RX_PL_WID );
|
||||
result = SPItransfer(0xff);
|
||||
csnhigh();
|
||||
if(result > 32) {
|
||||
spiTrans(FLUSH_RX);
|
||||
return 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool available(uint8_t* pipe_num)
|
||||
{
|
||||
if (!(read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){
|
||||
if (pipe_num) {
|
||||
uint8_t status = get_status();
|
||||
*pipe_num = ( status >> RX_P_NO ) & 0b111;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void writeAckPayload(uint8_t pipe, const uint8_t* buf, uint8_t len)
|
||||
{
|
||||
const uint8_t* current = buf;
|
||||
uint8_t data_len = len;
|
||||
csnlow();
|
||||
SPItransfer(W_ACK_PAYLOAD | ( pipe & 0b111 ) );
|
||||
while ( data_len-- )
|
||||
SPItransfer(*current++);
|
||||
csnhigh();
|
||||
}
|
||||
|
||||
static void read( uint8_t* buf, uint8_t pipe ){
|
||||
read_payload(buf, getDynamicPayloadSize());
|
||||
write_register(STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS));
|
||||
writeAckPayload(pipe,&pipe, 1 );
|
||||
}
|
||||
|
||||
static void openWritingPipe(uint64_t value)
|
||||
{
|
||||
uint8_t valuea[8];
|
||||
convert_64_bit_to_byte_array(value, valuea);
|
||||
write_registers(RX_ADDR_P0, valuea, 5);
|
||||
write_registers(TX_ADDR, valuea, 5);
|
||||
}
|
||||
|
||||
static void openReadingPipe(uint8_t child, uint64_t address)
|
||||
{
|
||||
if (child == 0)
|
||||
pipe0_reading_address = address;
|
||||
uint8_t addressa[8];
|
||||
convert_64_bit_to_byte_array(address, addressa);
|
||||
if ( child < 2 )
|
||||
write_registers(RX_ADDR_P0 + child, addressa, 5);
|
||||
write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(ERX_P0 + child));
|
||||
}
|
||||
|
||||
static boolean write(uint8_t next, uint8_t* packet, uint8_t length, boolean multicast) {
|
||||
powerUp();
|
||||
stopListening();
|
||||
openWritingPipe(TO_ADDR(next));
|
||||
bool ok = writem(packet, length, multicast);
|
||||
startListening();
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void address(uint8_t addr)
|
||||
{
|
||||
if (addr != BROADCAST_ADDRESS) {
|
||||
openReadingPipe(WRITE_PIPE, TO_ADDR(addr));
|
||||
openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(addr));
|
||||
}
|
||||
}
|
||||
|
||||
static void begin(void)
|
||||
{
|
||||
pipe0_reading_address = 0;
|
||||
|
||||
SPIinit();
|
||||
delaym( 10 ) ;
|
||||
|
||||
write_register(SETUP_RETR, 5 << ARD | 15 << ARC);
|
||||
write_register(EN_AA, 0b00111111 & ~_BV(BROADCAST_PIPE)) ;
|
||||
write_register(RF_CH, RF24_CHANNEL);
|
||||
write_register(RF_SETUP, (read_register(RF_SETUP) & 0b11010000) | ((RF24_PA_LEVEL << 1) + 1) | ((RF24_DATARATE & 0b00000010 ) << 4) | ((RF24_DATARATE & 0b00000001 ) << 3));
|
||||
write_register(CONFIG, read_register(CONFIG) | _BV(CRCO) | _BV(EN_CRC)) ;
|
||||
write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));
|
||||
|
||||
csnlow();
|
||||
SPItransfer(ACTIVATE);
|
||||
SPItransfer(0x73);
|
||||
csnhigh();
|
||||
write_register(FEATURE, read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) );
|
||||
write_register(DYNPD, read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0));
|
||||
|
||||
spiTrans(FLUSH_RX);
|
||||
spiTrans(FLUSH_TX);
|
||||
|
||||
powerUp(); //Power up by default when begin() is called
|
||||
write_register(CONFIG, read_register(CONFIG) & ~_BV(PRIM_RX));
|
||||
openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS));
|
||||
}
|
||||
#endif // MyOtaBootloaderRF24_H
|
||||
@@ -48,7 +48,6 @@
|
||||
|
||||
|
||||
#include <SPI.h>
|
||||
#include <EEPROM.h>
|
||||
#include <MsTimer2.h>
|
||||
#include <PinChangeInt.h>
|
||||
#include <MyGateway.h>
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
:100000000C9461000C947E000C947E000C947E0095
|
||||
:100010000C947E000C947E000C947E000C947E0068
|
||||
:100020000C947E000C947E000C947E000C947E0058
|
||||
:100030000C947E000C947E000C947E000C947E0048
|
||||
:100040000C949A000C947E000C947E000C947E001C
|
||||
:100050000C947E000C947E000C947E000C947E0028
|
||||
:100060000C947E000C947E00000000002400270009
|
||||
:100070002A0000000000250028002B0000000000DE
|
||||
:1000800023002600290004040404040404040202DA
|
||||
:100090000202020203030303030301020408102007
|
||||
:1000A0004080010204081020010204081020000012
|
||||
:1000B0000007000201000003040600000000000029
|
||||
:1000C000000011241FBECFEFD8E0DEBFCDBF11E08E
|
||||
:1000D000A0E0B1E0E4E5F4E002C005900D92A030AC
|
||||
:1000E000B107D9F711E0A0E0B1E001C01D92A9303D
|
||||
:1000F000B107E1F70E9418020C9428020C9400004A
|
||||
:1001000087E061E00E94C4016AEF70E080E090E067
|
||||
:100110000E941D0187E060E00E94C4016AEF70E068
|
||||
:1001200080E090E00E941D01089587E061E00E9458
|
||||
:10013000850108951F920F920FB60F9211242F93ED
|
||||
:100140003F938F939F93AF93BF93809104019091BE
|
||||
:100150000501A0910601B0910701309108010196B7
|
||||
:10016000A11DB11D232F2D5F2D3720F02D57019696
|
||||
:10017000A11DB11D209308018093040190930501F6
|
||||
:10018000A0930601B09307018091000190910101B5
|
||||
:10019000A0910201B09103010196A11DB11D8093B0
|
||||
:1001A000000190930101A0930201B0930301BF915C
|
||||
:1001B000AF919F918F913F912F910F900FBE0F9014
|
||||
:1001C0001F901895789484B5826084BD84B5816051
|
||||
:1001D00084BD85B5826085BD85B5816085BDEEE64F
|
||||
:1001E000F0E0808181608083E1E8F0E0108280812E
|
||||
:1001F00082608083808181608083E0E8F0E080819C
|
||||
:1002000081608083E1EBF0E0808184608083E0EBBB
|
||||
:10021000F0E0808181608083EAE7F0E080818460A3
|
||||
:1002200080838081826080838081816080838081FF
|
||||
:10023000806880831092C1000895EF92FF920F931F
|
||||
:100240001F93CF93DF937B018C013FB7F89480918C
|
||||
:10025000000190910101A0910201B091030126B526
|
||||
:10026000A89B05C02F3F19F00196A11DB11D3FBFEE
|
||||
:10027000BA2FA92F982F8827820F911DA11DB11D7C
|
||||
:1002800052E0880F991FAA1FBB1F5A95D1F7EC01A6
|
||||
:1002900030C00E9427023FB7F894809100019091EE
|
||||
:1002A0000101A0910201B091030126B5A89B05C0F0
|
||||
:1002B0002F3F19F00196A11DB11D3FBFBA2FA92FE5
|
||||
:1002C000982F8827820F911DA11DB11D32E0880F44
|
||||
:1002D000991FAA1FBB1F3A95D1F78C1B9D0B885EF7
|
||||
:1002E0009340B8F20894E108F10801091109C851D6
|
||||
:1002F000DC4FE114F1040105110559F6DF91CF91AE
|
||||
:100300001F910F91FF90EF900895CF93DF93482FA7
|
||||
:1003100050E0CA0186569F4FFC0134914A575F4F07
|
||||
:10032000FA018491882369F190E0880F991FFC01FC
|
||||
:10033000E859FF4FA591B491FC01EE58FF4FC591CC
|
||||
:10034000D491662351F42FB7F8948C91932F909504
|
||||
:1003500089238C93888189230BC0623061F42FB785
|
||||
:10036000F8948C91932F909589238C938881832B7B
|
||||
:1003700088832FBF06C09FB7F8948C91832B8C93F2
|
||||
:100380009FBFDF91CF910895482F50E0CA01825559
|
||||
:100390009F4FFC012491CA0186569F4FFC01949106
|
||||
:1003A0004A575F4FFA013491332309F440C02223A6
|
||||
:1003B00051F1233071F0243028F42130A1F02230A3
|
||||
:1003C00011F514C02630B1F02730C1F02430D9F433
|
||||
:1003D00004C0809180008F7703C0809180008F7D62
|
||||
:1003E0008093800010C084B58F7702C084B58F7D64
|
||||
:1003F00084BD09C08091B0008F7703C08091B000A8
|
||||
:100400008F7D8093B000E32FF0E0EE0FFF1FEE58DA
|
||||
:10041000FF4FA591B4912FB7F894662321F48C91E6
|
||||
:100420009095892302C08C91892B8C932FBF0895BE
|
||||
:10043000CF93DF930E94E2000E949500C0E0D0E0DD
|
||||
:100440000E9480002097E1F30E940000F9CF0895F8
|
||||
:04045000F894FFCF4E
|
||||
:00000001FF
|
||||
@@ -0,0 +1,71 @@
|
||||
:100000000C9461000C947E000C947E000C947E0095
|
||||
:100010000C947E000C947E000C947E000C947E0068
|
||||
:100020000C947E000C947E000C947E000C947E0058
|
||||
:100030000C947E000C947E000C947E000C947E0048
|
||||
:100040000C949A000C947E000C947E000C947E001C
|
||||
:100050000C947E000C947E000C947E000C947E0028
|
||||
:100060000C947E000C947E00000000002400270009
|
||||
:100070002A0000000000250028002B0000000000DE
|
||||
:1000800023002600290004040404040404040202DA
|
||||
:100090000202020203030303030301020408102007
|
||||
:1000A0004080010204081020010204081020000012
|
||||
:1000B0000007000201000003040600000000000029
|
||||
:1000C000000011241FBECFEFD8E0DEBFCDBF11E08E
|
||||
:1000D000A0E0B1E0E4E5F4E002C005900D92A030AC
|
||||
:1000E000B107D9F711E0A0E0B1E001C01D92A9303D
|
||||
:1000F000B107E1F70E9418020C9428020C9400004A
|
||||
:1001000086E061E00E94C4016AEF70E080E090E068
|
||||
:100110000E941D0186E060E00E94C4016AEF70E069
|
||||
:1001200080E090E00E941D01089586E061E00E9459
|
||||
:10013000850108951F920F920FB60F9211242F93ED
|
||||
:100140003F938F939F93AF93BF93809104019091BE
|
||||
:100150000501A0910601B0910701309108010196B7
|
||||
:10016000A11DB11D232F2D5F2D3720F02D57019696
|
||||
:10017000A11DB11D209308018093040190930501F6
|
||||
:10018000A0930601B09307018091000190910101B5
|
||||
:10019000A0910201B09103010196A11DB11D8093B0
|
||||
:1001A000000190930101A0930201B0930301BF915C
|
||||
:1001B000AF919F918F913F912F910F900FBE0F9014
|
||||
:1001C0001F901895789484B5826084BD84B5816051
|
||||
:1001D00084BD85B5826085BD85B5816085BDEEE64F
|
||||
:1001E000F0E0808181608083E1E8F0E0108280812E
|
||||
:1001F00082608083808181608083E0E8F0E080819C
|
||||
:1002000081608083E1EBF0E0808184608083E0EBBB
|
||||
:10021000F0E0808181608083EAE7F0E080818460A3
|
||||
:1002200080838081826080838081816080838081FF
|
||||
:10023000806880831092C1000895EF92FF920F931F
|
||||
:100240001F93CF93DF937B018C013FB7F89480918C
|
||||
:10025000000190910101A0910201B091030126B526
|
||||
:10026000A89B05C02F3F19F00196A11DB11D3FBFEE
|
||||
:10027000BA2FA92F982F8827820F911DA11DB11D7C
|
||||
:1002800052E0880F991FAA1FBB1F5A95D1F7EC01A6
|
||||
:1002900030C00E9427023FB7F894809100019091EE
|
||||
:1002A0000101A0910201B091030126B5A89B05C0F0
|
||||
:1002B0002F3F19F00196A11DB11D3FBFBA2FA92FE5
|
||||
:1002C000982F8827820F911DA11DB11D32E0880F44
|
||||
:1002D000991FAA1FBB1F3A95D1F78C1B9D0B885EF7
|
||||
:1002E0009340B8F20894E108F10801091109C851D6
|
||||
:1002F000DC4FE114F1040105110559F6DF91CF91AE
|
||||
:100300001F910F91FF90EF900895CF93DF93482FA7
|
||||
:1003100050E0CA0186569F4FFC0134914A575F4F07
|
||||
:10032000FA018491882369F190E0880F991FFC01FC
|
||||
:10033000E859FF4FA591B491FC01EE58FF4FC591CC
|
||||
:10034000D491662351F42FB7F8948C91932F909504
|
||||
:1003500089238C93888189230BC0623061F42FB785
|
||||
:10036000F8948C91932F909589238C938881832B7B
|
||||
:1003700088832FBF06C09FB7F8948C91832B8C93F2
|
||||
:100380009FBFDF91CF910895482F50E0CA01825559
|
||||
:100390009F4FFC012491CA0186569F4FFC01949106
|
||||
:1003A0004A575F4FFA013491332309F440C02223A6
|
||||
:1003B00051F1233071F0243028F42130A1F02230A3
|
||||
:1003C00011F514C02630B1F02730C1F02430D9F433
|
||||
:1003D00004C0809180008F7703C0809180008F7D62
|
||||
:1003E0008093800010C084B58F7702C084B58F7D64
|
||||
:1003F00084BD09C08091B0008F7703C08091B000A8
|
||||
:100400008F7D8093B000E32FF0E0EE0FFF1FEE58DA
|
||||
:10041000FF4FA591B4912FB7F894662321F48C91E6
|
||||
:100420009095892302C08C91892B8C932FBF0895BE
|
||||
:10043000CF93DF930E94E2000E949500C0E0D0E0DD
|
||||
:100440000E9480002097E1F30E940000F9CF0895F8
|
||||
:04045000F894FFCF4E
|
||||
:00000001FF
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
||||
// Example sketch showing how to send in OneWire temperature readings
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
#include <DallasTemperature.h>
|
||||
#include <OneWire.h>
|
||||
|
||||
#define ONE_WIRE_BUS 3 // Pin where dallase sensor is connected
|
||||
#define MAX_ATTACHED_DS18B20 16
|
||||
unsigned long WAIT_TIME = 30000; // Wait for feedback from controller after sending and before going to sleep (in milliseconds)
|
||||
unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
|
||||
OneWire oneWire(ONE_WIRE_BUS);
|
||||
DallasTemperature sensors(&oneWire);
|
||||
MySensor gw;
|
||||
float lastTemperature[MAX_ATTACHED_DS18B20];
|
||||
int numSensors=0;
|
||||
boolean receivedConfig = false;
|
||||
boolean metric = true;
|
||||
// Initialize temperature message
|
||||
MyMessage msg(0,V_TEMP);
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Startup OneWire
|
||||
sensors.begin();
|
||||
|
||||
// Startup and initialize MySensors library. Set callback for incoming messages.
|
||||
gw.begin();
|
||||
|
||||
// Send the sketch version information to the gateway and Controller
|
||||
gw.sendSketchInfo("Temperature Sensor", "1.0");
|
||||
|
||||
// Fetch the number of attached temperature sensors
|
||||
numSensors = sensors.getDeviceCount();
|
||||
|
||||
// Present all sensors to controller
|
||||
for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
|
||||
gw.present(i, S_TEMP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Process incoming messages (like config from server)
|
||||
gw.process();
|
||||
|
||||
// Fetch temperatures from Dallas sensors
|
||||
sensors.requestTemperatures();
|
||||
|
||||
// Read temperatures and send them to controller
|
||||
for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
|
||||
|
||||
// Fetch and round temperature to one decimal
|
||||
float temperature = static_cast<float>(static_cast<int>((gw.getConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;
|
||||
|
||||
// Only send data if temperature has changed and no error
|
||||
if (lastTemperature[i] != temperature && temperature != -127.00) {
|
||||
|
||||
// Send in the new temperature
|
||||
gw.send(msg.setSensor(i).set(temperature,1));
|
||||
lastTemperature[i]=temperature;
|
||||
}
|
||||
}
|
||||
delay(WAIT_TIME);
|
||||
gw.process();
|
||||
gw.sleep(SLEEP_TIME);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
const dbAddress = '127.0.0.1';
|
||||
const dbPort = 27017;
|
||||
const dbName = 'MySensorsDb';
|
||||
|
||||
var dbc = require('mongodb').MongoClient;
|
||||
dbc.connect('mongodb://' + dbAddress + ':' + dbPort + '/' + dbName, function(err, db) {
|
||||
if (err) {
|
||||
console.log('Error connecting to database at mongodb://' + dbAddress + ':' + dbPort + '/' + dbName);
|
||||
} else {
|
||||
db.dropDatabase(function(err, result) {
|
||||
if (err)
|
||||
console.log('Error dropping database at mongodb://' + dbAddress + ':' + dbPort + '/' + dbName);
|
||||
else
|
||||
console.log('Successfully dropped database at mongodb://' + dbAddress + ':' + dbPort + '/' + dbName);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,666 @@
|
||||
const gwType = 'Ethernet';
|
||||
const gwAddress = '10.0.1.99';
|
||||
const gwPort = 9999;
|
||||
|
||||
//const gwType = 'Serial';
|
||||
//const gwPort = 'COM4';
|
||||
//const gwBaud = 115200;
|
||||
|
||||
const dbAddress = '127.0.0.1';
|
||||
const dbPort = 27017;
|
||||
const dbName = 'MySensorsDb';
|
||||
|
||||
const fwHexFiles = [ 'BlinkRed.hex', 'BlinkGreen.hex', 'DallasTemperatureSensor.cpp.hex' ];
|
||||
const fwDefaultType = 2; // index of hex file from array above
|
||||
|
||||
const FIRMWARE_BLOCK_SIZE = 16;
|
||||
const BROADCAST_ADDRESS = 255;
|
||||
const NODE_SENSOR_ID = 255;
|
||||
|
||||
const C_PRESENTATION = 0;
|
||||
const C_SET = 1;
|
||||
const C_REQ = 2;
|
||||
const C_INTERNAL = 3;
|
||||
const C_STREAM = 4;
|
||||
|
||||
const V_TEMP = 0;
|
||||
const V_HUM = 1;
|
||||
const V_LIGHT = 2;
|
||||
const V_DIMMER = 3;
|
||||
const V_PRESSURE = 4;
|
||||
const V_FORECAST = 5;
|
||||
const V_RAIN = 6;
|
||||
const V_RAINRATE = 7;
|
||||
const V_WIND = 8;
|
||||
const V_GUST = 9;
|
||||
const V_DIRECTION = 10;
|
||||
const V_UV = 11;
|
||||
const V_WEIGHT = 12;
|
||||
const V_DISTANCE = 13;
|
||||
const V_IMPEDANCE = 14;
|
||||
const V_ARMED = 15;
|
||||
const V_TRIPPED = 16;
|
||||
const V_WATT = 17;
|
||||
const V_KWH = 18;
|
||||
const V_SCENE_ON = 19;
|
||||
const V_SCENE_OFF = 20;
|
||||
const V_HEATER = 21;
|
||||
const V_HEATER_SW = 22;
|
||||
const V_LIGHT_LEVEL = 23;
|
||||
const V_VAR1 = 24;
|
||||
const V_VAR2 = 25;
|
||||
const V_VAR3 = 26;
|
||||
const V_VAR4 = 27;
|
||||
const V_VAR5 = 28;
|
||||
const V_UP = 29;
|
||||
const V_DOWN = 30;
|
||||
const V_STOP = 31;
|
||||
const V_IR_SEND = 32;
|
||||
const V_IR_RECEIVE = 33;
|
||||
const V_FLOW = 34;
|
||||
const V_VOLUME = 35;
|
||||
const V_LOCK_STATUS = 36;
|
||||
|
||||
const I_BATTERY_LEVEL = 0;
|
||||
const I_TIME = 1;
|
||||
const I_VERSION = 2;
|
||||
const I_ID_REQUEST = 3;
|
||||
const I_ID_RESPONSE = 4;
|
||||
const I_INCLUSION_MODE = 5;
|
||||
const I_CONFIG = 6;
|
||||
const I_PING = 7;
|
||||
const I_PING_ACK = 8;
|
||||
const I_LOG_MESSAGE = 9;
|
||||
const I_CHILDREN = 10;
|
||||
const I_SKETCH_NAME = 11;
|
||||
const I_SKETCH_VERSION = 12;
|
||||
const I_REBOOT = 13;
|
||||
|
||||
const S_DOOR = 0;
|
||||
const S_MOTION = 1;
|
||||
const S_SMOKE = 2;
|
||||
const S_LIGHT = 3;
|
||||
const S_DIMMER = 4;
|
||||
const S_COVER = 5;
|
||||
const S_TEMP = 6;
|
||||
const S_HUM = 7;
|
||||
const S_BARO = 8;
|
||||
const S_WIND = 9;
|
||||
const S_RAIN = 10;
|
||||
const S_UV = 11;
|
||||
const S_WEIGHT = 12;
|
||||
const S_POWER = 13;
|
||||
const S_HEATER = 14;
|
||||
const S_DISTANCE = 15;
|
||||
const S_LIGHT_LEVEL = 16;
|
||||
const S_ARDUINO_NODE = 17;
|
||||
const S_ARDUINO_REPEATER_NODE = 18;
|
||||
const S_LOCK = 19;
|
||||
const S_IR = 20;
|
||||
const S_WATER = 21;
|
||||
const S_AIR_QUALITY = 22;
|
||||
|
||||
const ST_FIRMWARE_CONFIG_REQUEST = 0;
|
||||
const ST_FIRMWARE_CONFIG_RESPONSE = 1;
|
||||
const ST_FIRMWARE_REQUEST = 2;
|
||||
const ST_FIRMWARE_RESPONSE = 3;
|
||||
const ST_SOUND = 4;
|
||||
const ST_IMAGE = 5;
|
||||
|
||||
const P_STRING = 0;
|
||||
const P_BYTE = 1;
|
||||
const P_INT16 = 2;
|
||||
const P_UINT16 = 3;
|
||||
const P_LONG32 = 4;
|
||||
const P_ULONG32 = 5;
|
||||
const P_CUSTOM = 6;
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
function crcUpdate(old, value) {
|
||||
var c = old ^ value;
|
||||
for (var i = 0; i < 8; ++i) {
|
||||
if ((c & 1) > 0)
|
||||
c = ((c >> 1) ^ 0xA001);
|
||||
else
|
||||
c = (c >> 1);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function pullWord(arr, pos) {
|
||||
return arr[pos] + 256 * arr[pos + 1];
|
||||
}
|
||||
|
||||
function pushWord(arr, val) {
|
||||
arr.push(val & 0x00FF);
|
||||
arr.push((val >> 8) & 0x00FF);
|
||||
}
|
||||
|
||||
function pushDWord(arr, val) {
|
||||
arr.push(val & 0x000000FF);
|
||||
arr.push((val >> 8) & 0x000000FF);
|
||||
arr.push((val >> 16) & 0x000000FF);
|
||||
arr.push((val >> 24) & 0x000000FF);
|
||||
}
|
||||
|
||||
function loadFirmware(fwtype, fwversion, filename, db) {
|
||||
console.log("loading firmware: " + filename);
|
||||
fwdata = [];
|
||||
var start = 0;
|
||||
var end = 0;
|
||||
var pos = 0;
|
||||
var hex = fs.readFileSync(filename).toString().split("\n");
|
||||
for(l in hex) {
|
||||
line = hex[l].trim();
|
||||
if (line.length > 0) {
|
||||
while (line.substring(0, 1) != ":")
|
||||
line = line.substring(1);
|
||||
var reclen = parseInt(line.substring(1, 3), 16);
|
||||
var offset = parseInt(line.substring(3, 7), 16);
|
||||
var rectype = parseInt(line.substring(7, 9), 16);
|
||||
var data = line.substring(9, 9 + 2 * reclen);
|
||||
var chksum = parseInt(line.substring(9 + (2 * reclen), 9 + (2 * reclen) + 2), 16);
|
||||
if (rectype == 0) {
|
||||
if ((start == 0) && (end == 0)) {
|
||||
if (offset % 128 > 0)
|
||||
throw new Error("error loading hex file - offset can't be devided by 128");
|
||||
start = offset;
|
||||
end = offset;
|
||||
}
|
||||
if (offset < end)
|
||||
throw new Error("error loading hex file - offset lower than end");
|
||||
while (offset > end) {
|
||||
fwdata.push(255);
|
||||
pos++;
|
||||
end++;
|
||||
}
|
||||
for (var i = 0; i < reclen; i++) {
|
||||
fwdata.push(parseInt(data.substring(i * 2, (i * 2) + 2), 16));
|
||||
pos++;
|
||||
}
|
||||
end += reclen;
|
||||
}
|
||||
}
|
||||
}
|
||||
var pad = end % 128; // ATMega328 has 64 words per page / 128 bytes per page
|
||||
for (var i = 0; i < 128 - pad; i++) {
|
||||
fwdata.push(255);
|
||||
pos++;
|
||||
end++;
|
||||
}
|
||||
var blocks = (end - start) / FIRMWARE_BLOCK_SIZE;
|
||||
var crc = 0xFFFF;
|
||||
for (var i = 0; i < blocks * FIRMWARE_BLOCK_SIZE; ++i) {
|
||||
var v = crc;
|
||||
crc = crcUpdate(crc, fwdata[i]);
|
||||
}
|
||||
db.collection('firmware', function(err, c) {
|
||||
c.update({
|
||||
'type': fwtype,
|
||||
'version': fwversion
|
||||
}, {
|
||||
$set: {
|
||||
'filename': filename,
|
||||
'blocks': blocks,
|
||||
'crc': crc,
|
||||
'data': fwdata
|
||||
}
|
||||
}, {
|
||||
upsert: true
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log('Error writing firmware to database');
|
||||
});
|
||||
});
|
||||
console.log("loading firmware done. blocks: " + blocks + " / crc: " + crc);
|
||||
}
|
||||
|
||||
/*
|
||||
function decode(msg) {
|
||||
var msgs = msg.toString().split(";");
|
||||
rsender = +msgs[0];
|
||||
rsensor = +msgs[1];
|
||||
rcommand = +msgs[2];
|
||||
rtype = +msgs[3];
|
||||
var pl = msgs[4].trim();
|
||||
rpayload = [];
|
||||
for (var i = 0; i < pl.length; i+=2) {
|
||||
var b = parseInt(pl.substring(i, i + 2), 16);
|
||||
rpayload.push(b);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
function encode(destination, sensor, command, acknowledge, type, payload) {
|
||||
var msg = destination.toString(10) + ";" + sensor.toString(10) + ";" + command.toString(10) + ";" + acknowledge.toString(10) + ";" + type.toString(10) + ";";
|
||||
if (command == 4) {
|
||||
for (var i = 0; i < payload.length; i++) {
|
||||
if (payload[i] < 16)
|
||||
msg += "0";
|
||||
msg += payload[i].toString(16);
|
||||
}
|
||||
} else {
|
||||
msg += payload;
|
||||
}
|
||||
msg += '\n';
|
||||
return msg.toString();
|
||||
}
|
||||
|
||||
function saveProtocol(sender, payload, db) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': sender
|
||||
}, {
|
||||
$set: {
|
||||
'protocol': payload
|
||||
}
|
||||
}, {
|
||||
upsert: true
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing protocol to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveSensor(sender, sensor, type, db) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': sender
|
||||
}, {
|
||||
$addToSet: {
|
||||
sensor: type
|
||||
}
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing sensor to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveValue(sender, sensor, type, payload, db) {
|
||||
var cn = "Value-" + sender.toString() + "-" + sensor.toString();
|
||||
db.createCollection(cn, function(err, c) {
|
||||
c.save({
|
||||
'timestamp': new Date().getTime(),
|
||||
'type': type,
|
||||
'value': payload
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing value to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveBatteryLevel(sender, payload, db) {
|
||||
var cn = "BatteryLevel-" + sender.toString();
|
||||
db.createCollection(cn, function(err, c) {
|
||||
c.save({
|
||||
'timestamp': new Date().getTime(),
|
||||
'value': payload
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing battery level to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveSketchName(sender, payload, db) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': sender
|
||||
}, {
|
||||
$set: {
|
||||
'sketchName': payload
|
||||
}
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing sketch name to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveSketchVersion(sender, payload, db) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': sender
|
||||
}, {
|
||||
$set: {
|
||||
'sketchVersion': payload
|
||||
}
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing sketch version to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function sendTime(destination, sensor, gw) {
|
||||
var payload = new Date().getTime();
|
||||
var command = C_INTERNAL;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = I_TIME;
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
}
|
||||
|
||||
function sendNextAvailableSensorId(db, gw) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.find({
|
||||
$query: { },
|
||||
$orderby: {
|
||||
'id': 1
|
||||
}
|
||||
}).toArray(function(err, results) {
|
||||
if (err)
|
||||
console.log('Error finding nodes');
|
||||
var id = 1;
|
||||
for (var i = 0; i < results.length; i++)
|
||||
if (results[i].id > i + 1) {
|
||||
id = i + 1;
|
||||
break;
|
||||
}
|
||||
if (id < 255) {
|
||||
c.save({
|
||||
'id': id
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log('Error writing node to database');
|
||||
var destination = BROADCAST_ADDRESS;
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = C_INTERNAL;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = I_ID_RESPONSE;
|
||||
var payload = id;
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function sendConfig(destination, gw) {
|
||||
var payload = "M";
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = C_INTERNAL;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = I_CONFIG;
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
}
|
||||
|
||||
function sendFirmwareConfigResponse(destination, fwtype, fwversion, db, gw) {
|
||||
// keep track of type/versin info for each node
|
||||
// at the same time update the last modified date
|
||||
// could be used to remove nodes not seen for a long time etc.
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': destination
|
||||
}, {
|
||||
$set: {
|
||||
'type': fwtype,
|
||||
'version': fwversion,
|
||||
'reboot': 0
|
||||
}
|
||||
}, {
|
||||
upsert: true
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing node type and version to database");
|
||||
});
|
||||
});
|
||||
if (fwtype == 0xFFFF) {
|
||||
// sensor does not know which type / blank EEPROM
|
||||
// take predefined type (ideally selected in UI prior to connection of new sensor)
|
||||
if (fwDefaultType == 0xFFFF)
|
||||
throw new Error('No default sensor type defined');
|
||||
fwtype = fwDefaultType;
|
||||
}
|
||||
db.collection('firmware', function(err, c) {
|
||||
c.findOne({
|
||||
$query: {
|
||||
'type': fwtype
|
||||
},
|
||||
$orderby: {
|
||||
'version': -1
|
||||
}
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log('Error finding firmware for type ' + fwtype);
|
||||
else if (!result)
|
||||
console.log('No firmware found for type ' + fwtype);
|
||||
else {
|
||||
var payload = [];
|
||||
pushWord(payload, result.type);
|
||||
pushWord(payload, result.version);
|
||||
pushWord(payload, result.blocks);
|
||||
pushWord(payload, result.crc);
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = C_STREAM;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = ST_FIRMWARE_CONFIG_RESPONSE;
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function sendFirmwareResponse(destination, fwtype, fwversion, fwblock, db, gw) {
|
||||
db.collection('firmware', function(err, c) {
|
||||
c.findOne({
|
||||
'type': fwtype,
|
||||
'version': fwversion
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log('Error finding firmware version ' + fwversion + ' for type ' + fwtype);
|
||||
var payload = [];
|
||||
pushWord(payload, result.type);
|
||||
pushWord(payload, result.version);
|
||||
pushWord(payload, fwblock);
|
||||
for (var i = 0; i < FIRMWARE_BLOCK_SIZE; i++)
|
||||
payload.push(result.data[fwblock * FIRMWARE_BLOCK_SIZE + i]);
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = C_STREAM;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = ST_FIRMWARE_RESPONSE;
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveRebootRequest(destination, db) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': destination
|
||||
}, {
|
||||
$set: {
|
||||
'reboot': 1
|
||||
}
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing reboot request to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkRebootRequest(destination, db, gw) {
|
||||
db.collection('node', function(err, c) {
|
||||
c.find({
|
||||
'id': destination
|
||||
}, function(err, item) {
|
||||
if (err)
|
||||
console.log('Error checking reboot request');
|
||||
else if (item.reboot == 1)
|
||||
sendRebootMessage(destination, gw);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function sendRebootMessage(destination, gw) {
|
||||
var sensor = NODE_SENSOR_ID;
|
||||
var command = C_INTERNAL;
|
||||
var acknowledge = 0; // no ack
|
||||
var type = I_REBOOT;
|
||||
var payload = "";
|
||||
var td = encode(destination, sensor, command, acknowledge, type, payload);
|
||||
console.log('-> ' + td.toString());
|
||||
gw.write(td);
|
||||
}
|
||||
|
||||
function rfReceived(data, db, gw) {
|
||||
if ((data != null) && (data != "")) {
|
||||
console.log('<- ' + data);
|
||||
// decoding message
|
||||
var datas = data.toString().split(";");
|
||||
var sender = +datas[0];
|
||||
var sensor = +datas[1];
|
||||
var command = +datas[2];
|
||||
var type = +datas[3];
|
||||
var rawpayload = datas[4].trim();
|
||||
var payload;
|
||||
if (command == C_STREAM) {
|
||||
payload = [];
|
||||
for (var i = 0; i < rawpayload.length; i+=2)
|
||||
payload.push(parseInt(rawpayload.substring(i, i + 2), 16));
|
||||
} else {
|
||||
payload = rawpayload;
|
||||
}
|
||||
// decision on appropriate response
|
||||
switch (command) {
|
||||
case C_PRESENTATION:
|
||||
if (sensor == NODE_SENSOR_ID)
|
||||
saveProtocol(sender, payload, db);
|
||||
saveSensor(sender, sensor, type, db);
|
||||
break;
|
||||
case C_SET:
|
||||
saveValue(sender, sensor, type, payload, db);
|
||||
break;
|
||||
case C_REQ:
|
||||
break;
|
||||
case C_INTERNAL:
|
||||
switch (type) {
|
||||
case I_BATTERY_LEVEL:
|
||||
saveBatteryLevel(sender, payload, db);
|
||||
break;
|
||||
case I_TIME:
|
||||
sendTime(sender, sensor, gw);
|
||||
break;
|
||||
case I_VERSION:
|
||||
break;
|
||||
case I_ID_REQUEST:
|
||||
sendNextAvailableSensorId(db, gw);
|
||||
break;
|
||||
case I_ID_RESPONSE:
|
||||
break;
|
||||
case I_INCLUSION_MODE:
|
||||
break;
|
||||
case I_CONFIG:
|
||||
sendConfig(sender, gw);
|
||||
break;
|
||||
case I_PING:
|
||||
break;
|
||||
case I_PING_ACK:
|
||||
break;
|
||||
case I_LOG_MESSAGE:
|
||||
break;
|
||||
case I_CHILDREN:
|
||||
break;
|
||||
case I_SKETCH_NAME:
|
||||
saveSketchName(sender, payload, db);
|
||||
break;
|
||||
case I_SKETCH_VERSION:
|
||||
saveSketchVersion(sender, payload, db);
|
||||
break;
|
||||
case I_REBOOT:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case C_STREAM:
|
||||
switch (type) {
|
||||
case ST_FIRMWARE_CONFIG_REQUEST:
|
||||
var fwtype = pullWord(payload, 0);
|
||||
var fwversion = pullWord(payload, 2);
|
||||
sendFirmwareConfigResponse(sender, fwtype, fwversion, db, gw);
|
||||
break;
|
||||
case ST_FIRMWARE_CONFIG_RESPONSE:
|
||||
break;
|
||||
case ST_FIRMWARE_REQUEST:
|
||||
var fwtype = pullWord(payload, 0);
|
||||
var fwversion = pullWord(payload, 2);
|
||||
var fwblock = pullWord(payload, 4);
|
||||
sendFirmwareResponse(sender, fwtype, fwversion, fwblock, db, gw);
|
||||
break;
|
||||
case ST_FIRMWARE_RESPONSE:
|
||||
break;
|
||||
case ST_SOUND:
|
||||
break;
|
||||
case ST_IMAGE:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
checkRebootRequest(sender, db, gw);
|
||||
}
|
||||
}
|
||||
|
||||
var dbc = require('mongodb').MongoClient;
|
||||
dbc.connect('mongodb://' + dbAddress + ':' + dbPort + '/' + dbName, function(err, db) {
|
||||
if(err) {
|
||||
console.log('Error connecting to database at mongodb://' + dbAddress + ':' + dbPort + '/' + dbName);
|
||||
return;
|
||||
}
|
||||
console.log('Connected to database at mongodb://' + dbAddress + ':' + dbPort + '/' + dbName);
|
||||
db.createCollection('node', function(err, collection) { });
|
||||
db.createCollection('firmware', function(err, collection) { });
|
||||
|
||||
// ToDo : check for new hex files / only load if new / get type and version from filename
|
||||
for (var i = 0; i < fwHexFiles.length; i++)
|
||||
loadFirmware(i, 1, fwHexFiles[i], db);
|
||||
|
||||
var gw;
|
||||
if (gwType == 'Ethernet') {
|
||||
gw = require('net').Socket();
|
||||
gw.connect(gwPort, gwAddress);
|
||||
gw.setEncoding('ascii');
|
||||
gw.on('connect', function() {
|
||||
console.log('connected to ethernet gateway at ' + gwAddress + ":" + gwPort);
|
||||
}).on('data', function(rd) {
|
||||
var rds = rd.toString().split('\n');
|
||||
for (var i = 0; i < rds.length; i++)
|
||||
rfReceived(rds[i].trim(), db, gw);
|
||||
}).on('end', function() {
|
||||
console.log('disconnected from gateway');
|
||||
}).on('error', function() {
|
||||
console.log('connection error - trying to reconnect');
|
||||
gw.connect(gwPort, gwAddress);
|
||||
gw.setEncoding('ascii');
|
||||
});
|
||||
} else if (gwType == 'Serial') {
|
||||
gw = require('serialport').SerialPort(gwPort, { baudrate: gwBaud }, false);
|
||||
gw.open();
|
||||
gw.on('open', function() {
|
||||
console.log('connected to serial gateway at ' + gwPort);
|
||||
}).on('data', function(rd) {
|
||||
var rds = rd.toString().split('\n');
|
||||
for (var i = 0; i < rds.length; i++)
|
||||
rfReceived(rds[i].trim(), db, gw);
|
||||
}).on('end', function() {
|
||||
console.log('disconnected from gateway');
|
||||
}).on('error', function() {
|
||||
console.log('connection error - trying to reconnect');
|
||||
gw.open();
|
||||
});
|
||||
} else {
|
||||
throw new Error('unknown Gateway type');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
var NodeIdToReboot = 1;
|
||||
|
||||
const dbAddress = '127.0.0.1';
|
||||
const dbPort = 27017;
|
||||
const dbName = 'MySensorsDb';
|
||||
|
||||
var dbc = require('mongodb').MongoClient;
|
||||
dbc.connect('mongodb://' + dbAddress + ':' + dbPort + '/' + dbName, function(err, db) {
|
||||
if (err) {
|
||||
console.log('Error connecting to database at mongodb://' + dbAddress + ':' + dbPort + '/' + dbName);
|
||||
} else {
|
||||
db.collection('node', function(err, c) {
|
||||
c.update({
|
||||
'id': NodeIdToReboot
|
||||
}, {
|
||||
$set: {
|
||||
'reboot': 1
|
||||
}
|
||||
}, function(err, result) {
|
||||
if (err)
|
||||
console.log("Error writing reboot request to database");
|
||||
else
|
||||
console.log("Reboot request saved to database");
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "NodeJsController",
|
||||
"version": "0.0.1",
|
||||
"description": "MySensors Controller based on Node JS",
|
||||
"dependencies": {
|
||||
"net": "~1.0.2",
|
||||
"mongodb": "~1.4.7"
|
||||
}
|
||||
}
|
||||
@@ -105,10 +105,22 @@ void MyGateway::checkInclusionFinished() {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t MyGateway::h2i(char c) {
|
||||
uint8_t i = 0;
|
||||
if (c <= '9')
|
||||
i += c - '0';
|
||||
else if (c >= 'a')
|
||||
i += c - 'a' + 10;
|
||||
else
|
||||
i += c - 'A' + 10;
|
||||
return i;
|
||||
}
|
||||
|
||||
void MyGateway::parseAndSend(char *commandBuffer) {
|
||||
boolean ok = false;
|
||||
char *str, *p, *value=NULL;
|
||||
uint8_t bvalue[MAX_PAYLOAD];
|
||||
uint8_t blen = 0;
|
||||
int i = 0;
|
||||
uint16_t destination = 0;
|
||||
uint8_t sensor = 0;
|
||||
@@ -138,7 +150,18 @@ void MyGateway::parseAndSend(char *commandBuffer) {
|
||||
type = atoi(str);
|
||||
break;
|
||||
case 5: // Variable value
|
||||
value = str;
|
||||
if (command == C_STREAM) {
|
||||
blen = 0;
|
||||
uint8_t val;
|
||||
while (*str) {
|
||||
val = h2i(*str++) << 4;
|
||||
val += h2i(*str++);
|
||||
bvalue[blen] = val;
|
||||
blen++;
|
||||
}
|
||||
} else {
|
||||
value = str;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
@@ -163,6 +186,10 @@ void MyGateway::parseAndSend(char *commandBuffer) {
|
||||
mSetRequestAck(msg,ack?1:0);
|
||||
mSetAck(msg,false);
|
||||
msg.set(value);
|
||||
if (command == C_STREAM)
|
||||
msg.set(bvalue, blen);
|
||||
else
|
||||
msg.set(value);
|
||||
ok = sendRoute(msg);
|
||||
if (!ok) {
|
||||
errBlink(1);
|
||||
|
||||
@@ -68,6 +68,8 @@ class MyGateway : public MySensor
|
||||
uint8_t pinTx;
|
||||
uint8_t pinEr;
|
||||
|
||||
uint8_t h2i(char c);
|
||||
|
||||
void serial(const char *fmt, ... );
|
||||
void serial(MyMessage &msg);
|
||||
void interruptStartInclusion();
|
||||
|
||||
@@ -33,6 +33,30 @@ const char* MyMessage::getString() const {
|
||||
}
|
||||
}
|
||||
|
||||
// handles single character hex (0 - 15)
|
||||
char MyMessage::i2h(uint8_t i) const {
|
||||
uint8_t k = i & 0x0F;
|
||||
if (k <= 9)
|
||||
return '0' + k;
|
||||
else
|
||||
return 'A' + k - 10;
|
||||
}
|
||||
|
||||
char* MyMessage::getStream(char *buffer) const {
|
||||
uint8_t cmd = miGetCommand();
|
||||
if ((cmd == C_STREAM) && (buffer != NULL)) {
|
||||
for (uint8_t i = 0; i < miGetLength(); i++)
|
||||
{
|
||||
buffer[i * 2] = i2h(data[i] >> 4);
|
||||
buffer[(i * 2) + 1] = i2h(data[i]);
|
||||
}
|
||||
buffer[miGetLength() * 2] = '\0';
|
||||
return buffer;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char* MyMessage::getString(char *buffer) const {
|
||||
uint8_t payloadType = miGetPayloadType();
|
||||
if (payloadType == P_STRING) {
|
||||
@@ -57,10 +81,7 @@ char* MyMessage::getString(char *buffer) const {
|
||||
ultoa(ulValue, buffer, 10);
|
||||
break;
|
||||
case P_CUSTOM:
|
||||
// TODO: Ok, what do we do here? We should probably convert this to hex
|
||||
// Mostly gateway interested in this so we do the special handling of this
|
||||
// over there.
|
||||
|
||||
return getStream(buffer);
|
||||
break;
|
||||
}
|
||||
return buffer;
|
||||
|
||||
@@ -12,11 +12,15 @@
|
||||
#ifndef MyMessage_h
|
||||
#define MyMessage_h
|
||||
|
||||
#include <SPI.h>
|
||||
#ifdef __cplusplus
|
||||
#include <Arduino.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define PROTOCOL_VERSION 2
|
||||
#define MAX_MESSAGE_LENGTH 32
|
||||
#define HEADER_SIZE 8
|
||||
#define HEADER_SIZE 7
|
||||
#define MAX_PAYLOAD (MAX_MESSAGE_LENGTH - HEADER_SIZE)
|
||||
|
||||
// Message types
|
||||
@@ -41,7 +45,8 @@ typedef enum {
|
||||
typedef enum {
|
||||
I_BATTERY_LEVEL, I_TIME, I_VERSION, I_ID_REQUEST, I_ID_RESPONSE,
|
||||
I_INCLUSION_MODE, I_CONFIG, I_PING, I_PING_ACK,
|
||||
I_LOG_MESSAGE, I_CHILDREN, I_SKETCH_NAME, I_SKETCH_VERSION
|
||||
I_LOG_MESSAGE, I_CHILDREN, I_SKETCH_NAME, I_SKETCH_VERSION,
|
||||
I_REBOOT
|
||||
} internal;
|
||||
|
||||
// Type of sensor (for presentation message)
|
||||
@@ -53,7 +58,8 @@ typedef enum {
|
||||
|
||||
// Type of data stream (for streamed message)
|
||||
typedef enum {
|
||||
ST_FIRMWARE, ST_SOUND, ST_IMAGE
|
||||
ST_FIRMWARE_CONFIG_REQUEST, ST_FIRMWARE_CONFIG_RESPONSE, ST_FIRMWARE_REQUEST, ST_FIRMWARE_RESPONSE,
|
||||
ST_SOUND, ST_IMAGE
|
||||
} stream;
|
||||
|
||||
typedef enum {
|
||||
@@ -96,6 +102,8 @@ typedef enum {
|
||||
|
||||
|
||||
// internal access for special fields
|
||||
#define miGetCommand() BF_GET(command_ack_payload, 0, 3)
|
||||
|
||||
#define miSetLength(_length) BF_SET(version_length, _length, 3, 5)
|
||||
#define miGetLength() BF_GET(version_length, 3, 5)
|
||||
|
||||
@@ -109,7 +117,7 @@ typedef enum {
|
||||
#define miGetPayloadType() BF_GET(command_ack_payload, 5, 3)
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
class MyMessage
|
||||
{
|
||||
public:
|
||||
@@ -118,11 +126,14 @@ public:
|
||||
|
||||
MyMessage(uint8_t sensor, uint8_t type);
|
||||
|
||||
char i2h(uint8_t i) const;
|
||||
|
||||
/**
|
||||
* If payload is something else than P_STRING you can have the payload value converted
|
||||
* into string representation by supplying a buffer with the minimum size of
|
||||
* 2*MAX_PAYLOAD+1. This is to be able to fit hex-conversion of a full binary payload.
|
||||
*/
|
||||
char* getStream(char *buffer) const;
|
||||
char* getString(char *buffer) const;
|
||||
const char* getString() const;
|
||||
void* getCustom() const;
|
||||
@@ -152,6 +163,13 @@ public:
|
||||
MyMessage& set(unsigned int value);
|
||||
MyMessage& set(int value);
|
||||
|
||||
#else
|
||||
|
||||
typedef union {
|
||||
struct
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
uint8_t version_length; // 3 bit - Protocol version
|
||||
// 5 bit - Length of payload
|
||||
@@ -176,6 +194,12 @@ public:
|
||||
int iValue;
|
||||
char data[MAX_PAYLOAD + 1];
|
||||
} __attribute__((packed));
|
||||
#ifdef __cplusplus
|
||||
} __attribute__((packed));
|
||||
#else
|
||||
};
|
||||
uint8_t array[HEADER_SIZE + MAX_PAYLOAD + 1];
|
||||
} __attribute__((packed)) MyMessage;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -328,6 +328,10 @@ boolean MySensor::process() {
|
||||
bool isMetric;
|
||||
|
||||
switch (type) {
|
||||
case I_REBOOT:
|
||||
wdt_enable(WDTO_15MS);
|
||||
for (;;);
|
||||
break;
|
||||
case I_ID_RESPONSE:
|
||||
if (nc.nodeId == AUTO) {
|
||||
nc.nodeId = msg.getByte();
|
||||
|
||||
@@ -15,15 +15,19 @@
|
||||
#include "Version.h" // Auto generated by bot
|
||||
#include "MyConfig.h"
|
||||
#include "MyMessage.h"
|
||||
#include <Arduino.h>
|
||||
#include <stddef.h>
|
||||
#include <SPI.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#include "utility/LowPower.h"
|
||||
#include "utility/RF24.h"
|
||||
#include "utility/RF24_config.h"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define debug(x,...) debugPrint(x, ##__VA_ARGS__)
|
||||
@@ -46,7 +50,11 @@
|
||||
#define EEPROM_DISTANCE_ADDRESS (EEPROM_PARENT_NODE_ID_ADDRESS+1)
|
||||
#define EEPROM_ROUTES_ADDRESS (EEPROM_DISTANCE_ADDRESS+1) // Where to start storing routing information in EEPROM. Will allocate 256 bytes.
|
||||
#define EEPROM_CONTROLLER_CONFIG_ADDRESS (EEPROM_ROUTES_ADDRESS+256) // Location of controller sent configuration (we allow one payload of config data from controller)
|
||||
#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_CONTROLLER_CONFIG_ADDRESS+24) // First free address for sketch static configuration
|
||||
#define EEPROM_FIRMWARE_TYPE_ADDRESS (EEPROM_CONTROLLER_CONFIG_ADDRESS+24)
|
||||
#define EEPROM_FIRMWARE_VERSION_ADDRESS (EEPROM_FIRMWARE_TYPE_ADDRESS+2)
|
||||
#define EEPROM_FIRMWARE_BLOCKS_ADDRESS (EEPROM_FIRMWARE_VERSION_ADDRESS+2)
|
||||
#define EEPROM_FIRMWARE_CRC_ADDRESS (EEPROM_FIRMWARE_BLOCKS_ADDRESS+2)
|
||||
#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_FIRMWARE_CRC_ADDRESS+2) // First free address for sketch static configuration
|
||||
|
||||
// This is the nodeId for sensor net gateway receiver sketch (where all sensors should send their data).
|
||||
// This is also act as base value for sensor nodeId
|
||||
@@ -73,8 +81,7 @@ struct ControllerConfig {
|
||||
uint8_t isMetric;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
class MySensor : public RF24
|
||||
{
|
||||
public:
|
||||
@@ -266,5 +273,6 @@ class MySensor : public RF24
|
||||
void removeChildRoute(uint8_t childId);
|
||||
void internalSleep(unsigned long ms);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,554 +0,0 @@
|
||||
/*
|
||||
Enc28J60Network.h
|
||||
UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface.
|
||||
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
based on enc28j60.c file from the AVRlib library by Pascal Stang.
|
||||
For AVRlib See http://www.procyonengineering.com/
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Enc28J60Network.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
extern "C" {
|
||||
#include <avr/io.h>
|
||||
#include "enc28j60.h"
|
||||
#include "uip.h"
|
||||
}
|
||||
|
||||
#ifdef ENC28J60DEBUG
|
||||
#include "HardwareSerial.h"
|
||||
#endif
|
||||
|
||||
// set CS to 0 = active
|
||||
#define CSACTIVE digitalWrite(ENC28J60_CONTROL_CS, LOW)
|
||||
// set CS to 1 = passive
|
||||
#define CSPASSIVE digitalWrite(ENC28J60_CONTROL_CS, HIGH)
|
||||
//
|
||||
#define waitspi() while(!(SPSR&(1<<SPIF)))
|
||||
|
||||
Enc28J60Network::Enc28J60Network() :
|
||||
MemoryPool(TXSTART_INIT+1, TXSTOP_INIT-TXSTART_INIT), // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte
|
||||
bank(0xff)
|
||||
{
|
||||
}
|
||||
|
||||
void Enc28J60Network::init(uint8_t* macaddr)
|
||||
{
|
||||
// initialize I/O
|
||||
// ss as output:
|
||||
pinMode(ENC28J60_CONTROL_CS, OUTPUT);
|
||||
CSPASSIVE; // ss=0
|
||||
//
|
||||
pinMode(SPI_MOSI, OUTPUT);
|
||||
pinMode(SPI_SCK, OUTPUT);
|
||||
pinMode(SPI_MISO, INPUT);
|
||||
pinMode(SPI_SS, OUTPUT);
|
||||
|
||||
digitalWrite(SPI_MOSI, LOW);
|
||||
digitalWrite(SPI_SCK, LOW);
|
||||
|
||||
/*DDRB |= 1<<PB3 | 1<<PB5; // mosi, sck output
|
||||
cbi(DDRB,PINB4); // MISO is input
|
||||
//
|
||||
cbi(PORTB,PB3); // MOSI low
|
||||
cbi(PORTB,PB5); // SCK low
|
||||
*/
|
||||
//
|
||||
// initialize SPI interface
|
||||
// master mode and Fosc/2 clock:
|
||||
SPCR = (1<<SPE)|(1<<MSTR);
|
||||
SPSR |= (1<<SPI2X);
|
||||
// perform system reset
|
||||
writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
|
||||
delay(50);
|
||||
// check CLKRDY bit to see if reset is complete
|
||||
// The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait.
|
||||
//while(!(readReg(ESTAT) & ESTAT_CLKRDY));
|
||||
// do bank 0 stuff
|
||||
// initialize receive buffer
|
||||
// 16-bit transfers, must write low byte first
|
||||
// set receive buffer start address
|
||||
nextPacketPtr = RXSTART_INIT;
|
||||
// Rx start
|
||||
writeRegPair(ERXSTL, RXSTART_INIT);
|
||||
// set receive pointer address
|
||||
writeRegPair(ERXRDPTL, RXSTART_INIT);
|
||||
// RX end
|
||||
writeRegPair(ERXNDL, RXSTOP_INIT);
|
||||
// TX start
|
||||
//writeRegPair(ETXSTL, TXSTART_INIT);
|
||||
// TX end
|
||||
//writeRegPair(ETXNDL, TXSTOP_INIT);
|
||||
// do bank 1 stuff, packet filter:
|
||||
// For broadcast packets we allow only ARP packtets
|
||||
// All other packets should be unicast only for our mac (MAADR)
|
||||
//
|
||||
// The pattern to match on is therefore
|
||||
// Type ETH.DST
|
||||
// ARP BROADCAST
|
||||
// 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
|
||||
// in binary these poitions are:11 0000 0011 1111
|
||||
// This is hex 303F->EPMM0=0x3f,EPMM1=0x30
|
||||
//TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN!
|
||||
writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN);
|
||||
writeRegPair(EPMM0, 0x303f);
|
||||
writeRegPair(EPMCSL, 0xf7f9);
|
||||
//
|
||||
//
|
||||
// do bank 2 stuff
|
||||
// enable MAC receive
|
||||
// and bring MAC out of reset (writes 0x00 to MACON2)
|
||||
writeRegPair(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
|
||||
// enable automatic padding to 60bytes and CRC operations
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
|
||||
// set inter-frame gap (non-back-to-back)
|
||||
writeRegPair(MAIPGL, 0x0C12);
|
||||
// set inter-frame gap (back-to-back)
|
||||
writeReg(MABBIPG, 0x12);
|
||||
// Set the maximum packet size which the controller will accept
|
||||
// Do not send packets longer than MAX_FRAMELEN:
|
||||
writeRegPair(MAMXFLL, MAX_FRAMELEN);
|
||||
// do bank 3 stuff
|
||||
// write MAC address
|
||||
// NOTE: MAC address in ENC28J60 is byte-backward
|
||||
writeReg(MAADR5, macaddr[0]);
|
||||
writeReg(MAADR4, macaddr[1]);
|
||||
writeReg(MAADR3, macaddr[2]);
|
||||
writeReg(MAADR2, macaddr[3]);
|
||||
writeReg(MAADR1, macaddr[4]);
|
||||
writeReg(MAADR0, macaddr[5]);
|
||||
// no loopback of transmitted frames
|
||||
phyWrite(PHCON2, PHCON2_HDLDIS);
|
||||
// switch to bank 0
|
||||
setBank(ECON1);
|
||||
// enable interrutps
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
|
||||
// enable packet reception
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
|
||||
//Configure leds
|
||||
phyWrite(PHLCON,0x476);
|
||||
}
|
||||
|
||||
memhandle
|
||||
Enc28J60Network::receivePacket()
|
||||
{
|
||||
uint16_t rxstat;
|
||||
uint16_t len;
|
||||
// check if a packet has been received and buffered
|
||||
//if( !(readReg(EIR) & EIR_PKTIF) ){
|
||||
// The above does not work. See Rev. B4 Silicon Errata point 6.
|
||||
if (readReg(EPKTCNT) != 0)
|
||||
{
|
||||
uint16_t readPtr = nextPacketPtr+6;
|
||||
// Set the read pointer to the start of the received packet
|
||||
writeRegPair(ERDPTL, nextPacketPtr);
|
||||
// read the next packet pointer
|
||||
nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0);
|
||||
nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
|
||||
// read the packet length (see datasheet page 43)
|
||||
len = readOp(ENC28J60_READ_BUF_MEM, 0);
|
||||
len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
|
||||
len -= 4; //remove the CRC count
|
||||
// read the receive status (see datasheet page 43)
|
||||
rxstat = readOp(ENC28J60_READ_BUF_MEM, 0);
|
||||
rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
|
||||
// decrement the packet counter indicate we are done with this packet
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
|
||||
// check CRC and symbol errors (see datasheet page 44, table 7-3):
|
||||
// The ERXFCON.CRCEN is set by default. Normally we should not
|
||||
// need to check this.
|
||||
if ((rxstat & 0x80) != 0)
|
||||
{
|
||||
receivePkt.begin = readPtr;
|
||||
receivePkt.size = len;
|
||||
return UIP_RECEIVEBUFFERHANDLE;
|
||||
}
|
||||
// Move the RX read pointer to the start of the next received packet
|
||||
// This frees the memory we just read out
|
||||
setERXRDPT();
|
||||
}
|
||||
return (NOBLOCK);
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::setERXRDPT()
|
||||
{
|
||||
writeRegPair(ERXRDPTL, nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr-1);
|
||||
}
|
||||
|
||||
memaddress
|
||||
Enc28J60Network::blockSize(memhandle handle)
|
||||
{
|
||||
return handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size;
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::sendPacket(memhandle handle)
|
||||
{
|
||||
memblock *packet = &blocks[handle];
|
||||
uint16_t start = packet->begin-1;
|
||||
uint16_t end = start + packet->size;
|
||||
|
||||
// backup data at control-byte position
|
||||
uint8_t data = readByte(start);
|
||||
// write control-byte (if not 0 anyway)
|
||||
if (data)
|
||||
writeByte(start, 0);
|
||||
|
||||
#ifdef ENC28J60DEBUG
|
||||
Serial.print("sendPacket(");
|
||||
Serial.print(handle);
|
||||
Serial.print(") [");
|
||||
Serial.print(start);
|
||||
Serial.print("-");
|
||||
Serial.print(end);
|
||||
Serial.println("]:");
|
||||
for (uint16_t i=start; i<=end; i++)
|
||||
{
|
||||
Serial.print(readByte(i),HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
#endif
|
||||
|
||||
// TX start
|
||||
writeRegPair(ETXSTL, start);
|
||||
// Set the TXND pointer to correspond to the packet size given
|
||||
writeRegPair(ETXNDL, end);
|
||||
// send the contents of the transmit buffer onto the network
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
|
||||
// Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
|
||||
if( (readReg(EIR) & EIR_TXERIF) )
|
||||
{
|
||||
writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
|
||||
}
|
||||
|
||||
//restore data on control-byte position
|
||||
if (data)
|
||||
writeByte(start, data);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len)
|
||||
{
|
||||
memblock *packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle];
|
||||
memaddress start = packet->begin + position;
|
||||
|
||||
writeRegPair(ERDPTL, start);
|
||||
|
||||
if (len > packet->size - position)
|
||||
len = packet->size - position;
|
||||
return len;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len)
|
||||
{
|
||||
len = setReadPtr(handle, position, len);
|
||||
readBuffer(len, buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len)
|
||||
{
|
||||
memblock *packet = &blocks[handle];
|
||||
uint16_t start = packet->begin + position;
|
||||
|
||||
writeRegPair(EWRPTL, start);
|
||||
|
||||
if (len > packet->size - position)
|
||||
len = packet->size - position;
|
||||
writeBuffer(len, buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
uint8_t Enc28J60Network::readByte(uint16_t addr)
|
||||
{
|
||||
writeRegPair(ERDPTL, addr);
|
||||
|
||||
CSACTIVE;
|
||||
// issue read command
|
||||
SPDR = ENC28J60_READ_BUF_MEM;
|
||||
waitspi();
|
||||
// read data
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
CSPASSIVE;
|
||||
return (SPDR);
|
||||
}
|
||||
|
||||
void Enc28J60Network::writeByte(uint16_t addr, uint8_t data)
|
||||
{
|
||||
writeRegPair(EWRPTL, addr);
|
||||
|
||||
CSACTIVE;
|
||||
// issue write command
|
||||
SPDR = ENC28J60_WRITE_BUF_MEM;
|
||||
waitspi();
|
||||
// write data
|
||||
SPDR = data;
|
||||
waitspi();
|
||||
CSPASSIVE;
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, uint16_t len)
|
||||
{
|
||||
memblock *dest = &blocks[dest_pkt];
|
||||
memblock *src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt];
|
||||
memblock_mv_cb(dest->begin+dest_pos,src->begin+src_pos,len);
|
||||
// Move the RX read pointer to the start of the next received packet
|
||||
// This frees the memory we just read out
|
||||
setERXRDPT();
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len)
|
||||
{
|
||||
//as ENC28J60 DMA is unable to copy single bytes:
|
||||
if (len == 1)
|
||||
{
|
||||
writeByte(dest,readByte(src));
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate address of last byte
|
||||
len += src - 1;
|
||||
|
||||
/* 1. Appropriately program the EDMAST, EDMAND
|
||||
and EDMADST register pairs. The EDMAST
|
||||
registers should point to the first byte to copy
|
||||
from, the EDMAND registers should point to the
|
||||
last byte to copy and the EDMADST registers
|
||||
should point to the first byte in the destination
|
||||
range. The destination range will always be
|
||||
linear, never wrapping at any values except from
|
||||
8191 to 0 (the 8-Kbyte memory boundary).
|
||||
Extreme care should be taken when
|
||||
programming the start and end pointers to
|
||||
prevent a never ending DMA operation which
|
||||
would overwrite the entire 8-Kbyte buffer.
|
||||
*/
|
||||
writeRegPair(EDMASTL, src);
|
||||
writeRegPair(EDMADSTL, dest);
|
||||
|
||||
if ((src <= RXSTOP_INIT)&& (len > RXSTOP_INIT))len -= (RXSTOP_INIT-RXSTART_INIT);
|
||||
writeRegPair(EDMANDL, len);
|
||||
|
||||
/*
|
||||
2. If an interrupt at the end of the copy process is
|
||||
desired, set EIE.DMAIE and EIE.INTIE and
|
||||
clear EIR.DMAIF.
|
||||
|
||||
3. Verify that ECON1.CSUMEN is clear. */
|
||||
writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN);
|
||||
|
||||
/* 4. Start the DMA copy by setting ECON1.DMAST. */
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST);
|
||||
|
||||
// wait until runnig DMA is completed
|
||||
while (readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::freePacket()
|
||||
{
|
||||
setERXRDPT();
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Enc28J60Network::readOp(uint8_t op, uint8_t address)
|
||||
{
|
||||
CSACTIVE;
|
||||
// issue read command
|
||||
SPDR = op | (address & ADDR_MASK);
|
||||
waitspi();
|
||||
// read data
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
// do dummy read if needed (for mac and mii, see datasheet page 29)
|
||||
if(address & 0x80)
|
||||
{
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
}
|
||||
// release CS
|
||||
CSPASSIVE;
|
||||
return(SPDR);
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data)
|
||||
{
|
||||
CSACTIVE;
|
||||
// issue write command
|
||||
SPDR = op | (address & ADDR_MASK);
|
||||
waitspi();
|
||||
// write data
|
||||
SPDR = data;
|
||||
waitspi();
|
||||
CSPASSIVE;
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::readBuffer(uint16_t len, uint8_t* data)
|
||||
{
|
||||
CSACTIVE;
|
||||
// issue read command
|
||||
SPDR = ENC28J60_READ_BUF_MEM;
|
||||
waitspi();
|
||||
while(len)
|
||||
{
|
||||
len--;
|
||||
// read data
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
*data = SPDR;
|
||||
data++;
|
||||
}
|
||||
//*data='\0';
|
||||
CSPASSIVE;
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data)
|
||||
{
|
||||
CSACTIVE;
|
||||
// issue write command
|
||||
SPDR = ENC28J60_WRITE_BUF_MEM;
|
||||
waitspi();
|
||||
while(len)
|
||||
{
|
||||
len--;
|
||||
// write data
|
||||
SPDR = *data;
|
||||
data++;
|
||||
waitspi();
|
||||
}
|
||||
CSPASSIVE;
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::setBank(uint8_t address)
|
||||
{
|
||||
// set the bank (if needed)
|
||||
if((address & BANK_MASK) != bank)
|
||||
{
|
||||
// set the bank
|
||||
writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
|
||||
bank = (address & BANK_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Enc28J60Network::readReg(uint8_t address)
|
||||
{
|
||||
// set the bank
|
||||
setBank(address);
|
||||
// do the read
|
||||
return readOp(ENC28J60_READ_CTRL_REG, address);
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::writeReg(uint8_t address, uint8_t data)
|
||||
{
|
||||
// set the bank
|
||||
setBank(address);
|
||||
// do the write
|
||||
writeOp(ENC28J60_WRITE_CTRL_REG, address, data);
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::writeRegPair(uint8_t address, uint16_t data)
|
||||
{
|
||||
// set the bank
|
||||
setBank(address);
|
||||
// do the write
|
||||
writeOp(ENC28J60_WRITE_CTRL_REG, address, (data&0xFF));
|
||||
writeOp(ENC28J60_WRITE_CTRL_REG, address+1, (data) >> 8);
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::phyWrite(uint8_t address, uint16_t data)
|
||||
{
|
||||
// set the PHY register address
|
||||
writeReg(MIREGADR, address);
|
||||
// write the PHY data
|
||||
writeRegPair(MIWRL, data);
|
||||
// wait until the PHY write completes
|
||||
while(readReg(MISTAT) & MISTAT_BUSY){
|
||||
delayMicroseconds(15);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::clkout(uint8_t clk)
|
||||
{
|
||||
//setup clkout: 2 is 12.5MHz:
|
||||
writeReg(ECOCON, clk & 0x7);
|
||||
}
|
||||
|
||||
// read the revision of the chip:
|
||||
uint8_t
|
||||
Enc28J60Network::getrev(void)
|
||||
{
|
||||
return(readReg(EREVID));
|
||||
}
|
||||
|
||||
uint16_t
|
||||
Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len)
|
||||
{
|
||||
uint16_t t;
|
||||
len = setReadPtr(handle, pos, len)-1;
|
||||
CSACTIVE;
|
||||
// issue read command
|
||||
SPDR = ENC28J60_READ_BUF_MEM;
|
||||
waitspi();
|
||||
uint16_t i;
|
||||
for (i = 0; i < len; i+=2)
|
||||
{
|
||||
// read data
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
t = SPDR << 8;
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
t += SPDR;
|
||||
sum += t;
|
||||
if(sum < t) {
|
||||
sum++; /* carry */
|
||||
}
|
||||
}
|
||||
if(i == len) {
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
t = (SPDR << 8) + 0;
|
||||
sum += t;
|
||||
if(sum < t) {
|
||||
sum++; /* carry */
|
||||
}
|
||||
}
|
||||
CSPASSIVE;
|
||||
|
||||
/* Return sum in host byte order. */
|
||||
return sum;
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
Enc28J60Network.h
|
||||
UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface.
|
||||
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
inspired by enc28j60.c file from the AVRlib library by Pascal Stang.
|
||||
For AVRlib See http://www.procyonengineering.com/
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ENC28J60NETWORK_H_
|
||||
#define ENC28J60NETWORK_H_
|
||||
|
||||
#include "mempool.h"
|
||||
|
||||
#define ENC28J60_CONTROL_CS SS
|
||||
#define SPI_MOSI MOSI
|
||||
#define SPI_MISO MISO
|
||||
#define SPI_SCK SCK
|
||||
#define SPI_SS SS
|
||||
|
||||
#define UIP_RECEIVEBUFFERHANDLE 0xff
|
||||
|
||||
//#define ENC28J60DEBUG
|
||||
|
||||
/*
|
||||
* Empfangen von ip-header, arp etc...
|
||||
* wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection
|
||||
*/
|
||||
|
||||
class Enc28J60Network : public MemoryPool
|
||||
{
|
||||
|
||||
private:
|
||||
uint16_t nextPacketPtr;
|
||||
uint8_t bank;
|
||||
|
||||
struct memblock receivePkt;
|
||||
|
||||
uint8_t readOp(uint8_t op, uint8_t address);
|
||||
void writeOp(uint8_t op, uint8_t address, uint8_t data);
|
||||
uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len);
|
||||
void setERXRDPT();
|
||||
void readBuffer(uint16_t len, uint8_t* data);
|
||||
void writeBuffer(uint16_t len, uint8_t* data);
|
||||
uint8_t readByte(uint16_t addr);
|
||||
void writeByte(uint16_t addr, uint8_t data);
|
||||
void setBank(uint8_t address);
|
||||
uint8_t readReg(uint8_t address);
|
||||
void writeReg(uint8_t address, uint8_t data);
|
||||
void writeRegPair(uint8_t address, uint16_t data);
|
||||
void phyWrite(uint8_t address, uint16_t data);
|
||||
void clkout(uint8_t clk);
|
||||
uint8_t getrev(void);
|
||||
|
||||
protected:
|
||||
void memblock_mv_cb(memaddress dest, memaddress src, memaddress size);
|
||||
|
||||
public:
|
||||
Enc28J60Network();
|
||||
void init(uint8_t* macaddr);
|
||||
memhandle receivePacket();
|
||||
void freePacket();
|
||||
memaddress blockSize(memhandle handle);
|
||||
void sendPacket(memhandle handle);
|
||||
uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len);
|
||||
uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len);
|
||||
void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len);
|
||||
uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len);
|
||||
};
|
||||
|
||||
#endif /* ENC28J60NETWORK_H_ */
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
clock-arch.c - Arduino implementation of uIP clock device.
|
||||
Copyright (c) 2010 Adam Nielsen <malvineous@shikadi.net>
|
||||
All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "clock-arch.h"
|
||||
|
||||
clock_time_t
|
||||
clock_time(void)
|
||||
{
|
||||
return (clock_time_t) millis();
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
clock-arch.h - Arduino implementation of uIP clock device.
|
||||
Copyright (c) 2010 Adam Nielsen <malvineous@shikadi.net>
|
||||
All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef clock_h_
|
||||
#define clock_h_
|
||||
|
||||
typedef unsigned long clock_time_t;
|
||||
#define CLOCK_CONF_SECOND 1000
|
||||
|
||||
#endif
|
||||
@@ -1,257 +0,0 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Title : Microchip ENC28J60 Ethernet Interface Driver
|
||||
* Author : Pascal Stang (c)2005
|
||||
* Modified by Norbert Truchsess
|
||||
* Copyright: GPL V2
|
||||
*
|
||||
*This driver provides initialization and transmit/receive
|
||||
*functions for the Microchip ENC28J60 10Mb Ethernet Controller and PHY.
|
||||
*This chip is novel in that it is a full MAC+PHY interface all in a 28-pin
|
||||
*chip, using an SPI interface to the host processor.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ENC28J60_H
|
||||
#define ENC28J60_H
|
||||
#include <inttypes.h>
|
||||
|
||||
// ENC28J60 Control Registers
|
||||
// Control register definitions are a combination of address,
|
||||
// bank number, and Ethernet/MAC/PHY indicator bits.
|
||||
// - Register address (bits 0-4)
|
||||
// - Bank number (bits 5-6)
|
||||
// - MAC/PHY indicator (bit 7)
|
||||
#define ADDR_MASK 0x1F
|
||||
#define BANK_MASK 0x60
|
||||
#define SPRD_MASK 0x80
|
||||
// All-bank registers
|
||||
#define EIE 0x1B
|
||||
#define EIR 0x1C
|
||||
#define ESTAT 0x1D
|
||||
#define ECON2 0x1E
|
||||
#define ECON1 0x1F
|
||||
// Bank 0 registers
|
||||
#define ERDPTL (0x00|0x00)
|
||||
#define ERDPTH (0x01|0x00)
|
||||
#define EWRPTL (0x02|0x00)
|
||||
#define EWRPTH (0x03|0x00)
|
||||
#define ETXSTL (0x04|0x00)
|
||||
#define ETXSTH (0x05|0x00)
|
||||
#define ETXNDL (0x06|0x00)
|
||||
#define ETXNDH (0x07|0x00)
|
||||
#define ERXSTL (0x08|0x00)
|
||||
#define ERXSTH (0x09|0x00)
|
||||
#define ERXNDL (0x0A|0x00)
|
||||
#define ERXNDH (0x0B|0x00)
|
||||
#define ERXRDPTL (0x0C|0x00)
|
||||
#define ERXRDPTH (0x0D|0x00)
|
||||
#define ERXWRPTL (0x0E|0x00)
|
||||
#define ERXWRPTH (0x0F|0x00)
|
||||
#define EDMASTL (0x10|0x00)
|
||||
#define EDMASTH (0x11|0x00)
|
||||
#define EDMANDL (0x12|0x00)
|
||||
#define EDMANDH (0x13|0x00)
|
||||
#define EDMADSTL (0x14|0x00)
|
||||
#define EDMADSTH (0x15|0x00)
|
||||
#define EDMACSL (0x16|0x00)
|
||||
#define EDMACSH (0x17|0x00)
|
||||
// Bank 1 registers
|
||||
#define EHT0 (0x00|0x20)
|
||||
#define EHT1 (0x01|0x20)
|
||||
#define EHT2 (0x02|0x20)
|
||||
#define EHT3 (0x03|0x20)
|
||||
#define EHT4 (0x04|0x20)
|
||||
#define EHT5 (0x05|0x20)
|
||||
#define EHT6 (0x06|0x20)
|
||||
#define EHT7 (0x07|0x20)
|
||||
#define EPMM0 (0x08|0x20)
|
||||
#define EPMM1 (0x09|0x20)
|
||||
#define EPMM2 (0x0A|0x20)
|
||||
#define EPMM3 (0x0B|0x20)
|
||||
#define EPMM4 (0x0C|0x20)
|
||||
#define EPMM5 (0x0D|0x20)
|
||||
#define EPMM6 (0x0E|0x20)
|
||||
#define EPMM7 (0x0F|0x20)
|
||||
#define EPMCSL (0x10|0x20)
|
||||
#define EPMCSH (0x11|0x20)
|
||||
#define EPMOL (0x14|0x20)
|
||||
#define EPMOH (0x15|0x20)
|
||||
#define EWOLIE (0x16|0x20)
|
||||
#define EWOLIR (0x17|0x20)
|
||||
#define ERXFCON (0x18|0x20)
|
||||
#define EPKTCNT (0x19|0x20)
|
||||
// Bank 2 registers
|
||||
#define MACON1 (0x00|0x40|0x80)
|
||||
#define MACON2 (0x01|0x40|0x80)
|
||||
#define MACON3 (0x02|0x40|0x80)
|
||||
#define MACON4 (0x03|0x40|0x80)
|
||||
#define MABBIPG (0x04|0x40|0x80)
|
||||
#define MAIPGL (0x06|0x40|0x80)
|
||||
#define MAIPGH (0x07|0x40|0x80)
|
||||
#define MACLCON1 (0x08|0x40|0x80)
|
||||
#define MACLCON2 (0x09|0x40|0x80)
|
||||
#define MAMXFLL (0x0A|0x40|0x80)
|
||||
#define MAMXFLH (0x0B|0x40|0x80)
|
||||
#define MAPHSUP (0x0D|0x40|0x80)
|
||||
#define MICON (0x11|0x40|0x80)
|
||||
#define MICMD (0x12|0x40|0x80)
|
||||
#define MIREGADR (0x14|0x40|0x80)
|
||||
#define MIWRL (0x16|0x40|0x80)
|
||||
#define MIWRH (0x17|0x40|0x80)
|
||||
#define MIRDL (0x18|0x40|0x80)
|
||||
#define MIRDH (0x19|0x40|0x80)
|
||||
// Bank 3 registers
|
||||
#define MAADR1 (0x00|0x60|0x80)
|
||||
#define MAADR0 (0x01|0x60|0x80)
|
||||
#define MAADR3 (0x02|0x60|0x80)
|
||||
#define MAADR2 (0x03|0x60|0x80)
|
||||
#define MAADR5 (0x04|0x60|0x80)
|
||||
#define MAADR4 (0x05|0x60|0x80)
|
||||
#define EBSTSD (0x06|0x60)
|
||||
#define EBSTCON (0x07|0x60)
|
||||
#define EBSTCSL (0x08|0x60)
|
||||
#define EBSTCSH (0x09|0x60)
|
||||
#define MISTAT (0x0A|0x60|0x80)
|
||||
#define EREVID (0x12|0x60)
|
||||
#define ECOCON (0x15|0x60)
|
||||
#define EFLOCON (0x17|0x60)
|
||||
#define EPAUSL (0x18|0x60)
|
||||
#define EPAUSH (0x19|0x60)
|
||||
// PHY registers
|
||||
#define PHCON1 0x00
|
||||
#define PHSTAT1 0x01
|
||||
#define PHHID1 0x02
|
||||
#define PHHID2 0x03
|
||||
#define PHCON2 0x10
|
||||
#define PHSTAT2 0x11
|
||||
#define PHIE 0x12
|
||||
#define PHIR 0x13
|
||||
#define PHLCON 0x14
|
||||
|
||||
// ENC28J60 ERXFCON Register Bit Definitions
|
||||
#define ERXFCON_UCEN 0x80
|
||||
#define ERXFCON_ANDOR 0x40
|
||||
#define ERXFCON_CRCEN 0x20
|
||||
#define ERXFCON_PMEN 0x10
|
||||
#define ERXFCON_MPEN 0x08
|
||||
#define ERXFCON_HTEN 0x04
|
||||
#define ERXFCON_MCEN 0x02
|
||||
#define ERXFCON_BCEN 0x01
|
||||
// ENC28J60 EIE Register Bit Definitions
|
||||
#define EIE_INTIE 0x80
|
||||
#define EIE_PKTIE 0x40
|
||||
#define EIE_DMAIE 0x20
|
||||
#define EIE_LINKIE 0x10
|
||||
#define EIE_TXIE 0x08
|
||||
#define EIE_WOLIE 0x04
|
||||
#define EIE_TXERIE 0x02
|
||||
#define EIE_RXERIE 0x01
|
||||
// ENC28J60 EIR Register Bit Definitions
|
||||
#define EIR_PKTIF 0x40
|
||||
#define EIR_DMAIF 0x20
|
||||
#define EIR_LINKIF 0x10
|
||||
#define EIR_TXIF 0x08
|
||||
#define EIR_WOLIF 0x04
|
||||
#define EIR_TXERIF 0x02
|
||||
#define EIR_RXERIF 0x01
|
||||
// ENC28J60 ESTAT Register Bit Definitions
|
||||
#define ESTAT_INT 0x80
|
||||
#define ESTAT_LATECOL 0x10
|
||||
#define ESTAT_RXBUSY 0x04
|
||||
#define ESTAT_TXABRT 0x02
|
||||
#define ESTAT_CLKRDY 0x01
|
||||
// ENC28J60 ECON2 Register Bit Definitions
|
||||
#define ECON2_AUTOINC 0x80
|
||||
#define ECON2_PKTDEC 0x40
|
||||
#define ECON2_PWRSV 0x20
|
||||
#define ECON2_VRPS 0x08
|
||||
// ENC28J60 ECON1 Register Bit Definitions
|
||||
#define ECON1_TXRST 0x80
|
||||
#define ECON1_RXRST 0x40
|
||||
#define ECON1_DMAST 0x20
|
||||
#define ECON1_CSUMEN 0x10
|
||||
#define ECON1_TXRTS 0x08
|
||||
#define ECON1_RXEN 0x04
|
||||
#define ECON1_BSEL1 0x02
|
||||
#define ECON1_BSEL0 0x01
|
||||
// ENC28J60 MACON1 Register Bit Definitions
|
||||
#define MACON1_LOOPBK 0x10
|
||||
#define MACON1_TXPAUS 0x08
|
||||
#define MACON1_RXPAUS 0x04
|
||||
#define MACON1_PASSALL 0x02
|
||||
#define MACON1_MARXEN 0x01
|
||||
// ENC28J60 MACON2 Register Bit Definitions
|
||||
#define MACON2_MARST 0x80
|
||||
#define MACON2_RNDRST 0x40
|
||||
#define MACON2_MARXRST 0x08
|
||||
#define MACON2_RFUNRST 0x04
|
||||
#define MACON2_MATXRST 0x02
|
||||
#define MACON2_TFUNRST 0x01
|
||||
// ENC28J60 MACON3 Register Bit Definitions
|
||||
#define MACON3_PADCFG2 0x80
|
||||
#define MACON3_PADCFG1 0x40
|
||||
#define MACON3_PADCFG0 0x20
|
||||
#define MACON3_TXCRCEN 0x10
|
||||
#define MACON3_PHDRLEN 0x08
|
||||
#define MACON3_HFRMLEN 0x04
|
||||
#define MACON3_FRMLNEN 0x02
|
||||
#define MACON3_FULDPX 0x01
|
||||
// ENC28J60 MICMD Register Bit Definitions
|
||||
#define MICMD_MIISCAN 0x02
|
||||
#define MICMD_MIIRD 0x01
|
||||
// ENC28J60 MISTAT Register Bit Definitions
|
||||
#define MISTAT_NVALID 0x04
|
||||
#define MISTAT_SCAN 0x02
|
||||
#define MISTAT_BUSY 0x01
|
||||
// ENC28J60 PHY PHCON1 Register Bit Definitions
|
||||
#define PHCON1_PRST 0x8000
|
||||
#define PHCON1_PLOOPBK 0x4000
|
||||
#define PHCON1_PPWRSV 0x0800
|
||||
#define PHCON1_PDPXMD 0x0100
|
||||
// ENC28J60 PHY PHSTAT1 Register Bit Definitions
|
||||
#define PHSTAT1_PFDPX 0x1000
|
||||
#define PHSTAT1_PHDPX 0x0800
|
||||
#define PHSTAT1_LLSTAT 0x0004
|
||||
#define PHSTAT1_JBSTAT 0x0002
|
||||
// ENC28J60 PHY PHCON2 Register Bit Definitions
|
||||
#define PHCON2_FRCLINK 0x4000
|
||||
#define PHCON2_TXDIS 0x2000
|
||||
#define PHCON2_JABBER 0x0400
|
||||
#define PHCON2_HDLDIS 0x0100
|
||||
|
||||
// ENC28J60 Packet Control Byte Bit Definitions
|
||||
#define PKTCTRL_PHUGEEN 0x08
|
||||
#define PKTCTRL_PPADEN 0x04
|
||||
#define PKTCTRL_PCRCEN 0x02
|
||||
#define PKTCTRL_POVERRIDE 0x01
|
||||
|
||||
// SPI operation codes
|
||||
#define ENC28J60_READ_CTRL_REG 0x00
|
||||
#define ENC28J60_READ_BUF_MEM 0x3A
|
||||
#define ENC28J60_WRITE_CTRL_REG 0x40
|
||||
#define ENC28J60_WRITE_BUF_MEM 0x7A
|
||||
#define ENC28J60_BIT_FIELD_SET 0x80
|
||||
#define ENC28J60_BIT_FIELD_CLR 0xA0
|
||||
#define ENC28J60_SOFT_RESET 0xFF
|
||||
|
||||
|
||||
// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata
|
||||
// buffer boundaries applied to internal 8K ram
|
||||
// the entire available packet buffer space is allocated
|
||||
//
|
||||
// start with recbuf at 0/
|
||||
#define RXSTART_INIT 0x0
|
||||
// receive buffer end. make sure this is an odd value ( See Rev. B1,B4,B5,B7 Silicon Errata 'Memory (Ethernet Buffer)')
|
||||
#define RXSTOP_INIT (0x1FFF-0x1800)
|
||||
// start TX buffer RXSTOP_INIT+1
|
||||
#define TXSTART_INIT (RXSTOP_INIT+1)
|
||||
// stp TX buffer at end of mem
|
||||
#define TXSTOP_INIT 0x1FFF
|
||||
//
|
||||
// max frame length which the conroller will accept:
|
||||
#define MAX_FRAMELEN 1500 // (note: maximum ethernet frame length would be 1518)
|
||||
//#define MAX_FRAMELEN 600
|
||||
|
||||
#endif
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
mempool.cpp - sleek implementation of a memory pool
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mempool.h"
|
||||
#include <string.h>
|
||||
|
||||
#define POOLOFFSET 1
|
||||
|
||||
MemoryPool::MemoryPool(memaddress start, memaddress size)
|
||||
{
|
||||
memset(&blocks[0], 0, sizeof(blocks));
|
||||
blocks[POOLSTART].begin = start;
|
||||
blocks[POOLSTART].size = 0;
|
||||
blocks[POOLSTART].nextblock = NOBLOCK;
|
||||
poolsize = size;
|
||||
}
|
||||
|
||||
memhandle
|
||||
MemoryPool::allocBlock(memaddress size)
|
||||
{
|
||||
memblock* best = NULL;
|
||||
memhandle cur = POOLSTART;
|
||||
memblock* block = &blocks[POOLSTART];
|
||||
memaddress bestsize = poolsize + 1;
|
||||
|
||||
do
|
||||
{
|
||||
memhandle next = block->nextblock;
|
||||
memaddress freesize = ( next == NOBLOCK ? blocks[POOLSTART].begin + poolsize : blocks[next].begin) - block->begin - block->size;
|
||||
if (freesize == size)
|
||||
{
|
||||
best = &blocks[cur];
|
||||
goto found;
|
||||
}
|
||||
if (freesize > size && freesize < bestsize)
|
||||
{
|
||||
bestsize = freesize;
|
||||
best = &blocks[cur];
|
||||
}
|
||||
if (next == NOBLOCK)
|
||||
{
|
||||
if (best)
|
||||
goto found;
|
||||
else
|
||||
goto collect;
|
||||
}
|
||||
block = &blocks[next];
|
||||
cur = next;
|
||||
}
|
||||
while (true);
|
||||
|
||||
collect:
|
||||
{
|
||||
cur = POOLSTART;
|
||||
block = &blocks[POOLSTART];
|
||||
memhandle next;
|
||||
while ((next = block->nextblock) != NOBLOCK)
|
||||
{
|
||||
memaddress dest = block->begin + block->size;
|
||||
memblock* nextblock = &blocks[next];
|
||||
memaddress* src = &nextblock->begin;
|
||||
if (dest != *src)
|
||||
{
|
||||
#ifdef MEMBLOCK_MV
|
||||
memblock_mv_cb(dest,*src,nextblock->size);
|
||||
#endif
|
||||
*src = dest;
|
||||
}
|
||||
block = nextblock;
|
||||
}
|
||||
if (blocks[POOLSTART].begin + poolsize - block->begin - block->size >= size)
|
||||
best = block;
|
||||
else
|
||||
goto notfound;
|
||||
}
|
||||
|
||||
found:
|
||||
{
|
||||
block = &blocks[POOLOFFSET];
|
||||
for (cur = POOLOFFSET; cur < NUM_MEMBLOCKS + POOLOFFSET; cur++)
|
||||
{
|
||||
if (block->size)
|
||||
{
|
||||
block++;
|
||||
continue;
|
||||
}
|
||||
memaddress address = best->begin + best->size;
|
||||
#ifdef MEMBLOCK_ALLOC
|
||||
MEMBLOCK_ALLOC(address,size);
|
||||
#endif
|
||||
block->begin = address;
|
||||
block->size = size;
|
||||
block->nextblock = best->nextblock;
|
||||
best->nextblock = cur;
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
|
||||
notfound: return NOBLOCK;
|
||||
}
|
||||
|
||||
void
|
||||
MemoryPool::freeBlock(memhandle handle)
|
||||
{
|
||||
memblock *b = &blocks[POOLSTART];
|
||||
|
||||
do
|
||||
{
|
||||
memhandle next = b->nextblock;
|
||||
if (next == handle)
|
||||
{
|
||||
memblock *f = &blocks[next];
|
||||
#ifdef MEMBLOCK_FREE
|
||||
MEMBLOCK_FREE(f->begin,f->size);
|
||||
#endif
|
||||
b->nextblock = f->nextblock;
|
||||
f->size = 0;
|
||||
f->nextblock = NOBLOCK;
|
||||
return;
|
||||
}
|
||||
if (next == NOBLOCK)
|
||||
return;
|
||||
b = &blocks[next];
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
void
|
||||
MemoryPool::resizeBlock(memhandle handle, memaddress position)
|
||||
{
|
||||
memblock * block = &blocks[handle];
|
||||
block->begin += position;
|
||||
block->size -= position;
|
||||
}
|
||||
|
||||
void
|
||||
MemoryPool::resizeBlock(memhandle handle, memaddress position, memaddress size)
|
||||
{
|
||||
memblock * block = &blocks[handle];
|
||||
block->begin += position;
|
||||
block->size = size;
|
||||
}
|
||||
|
||||
memaddress
|
||||
MemoryPool::blockSize(memhandle handle)
|
||||
{
|
||||
return blocks[handle].size;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
mempool.h - sleek implementation of a memory pool
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MEMPOOL_H
|
||||
#define MEMPOOL_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define POOLSTART 0
|
||||
#define NOBLOCK 0
|
||||
|
||||
#include "mempool_conf.h"
|
||||
|
||||
//#ifdef MEMBLOCK_MV
|
||||
//#define memblock_mv_cb(dest,src,size) MEMBLOCK_MV(dest,src,size)
|
||||
//#endif
|
||||
|
||||
#ifdef MEMBLOCK_ALLOC
|
||||
#define memblock_alloc_cb(address,size) MEMBLOCK_ALLOC(address,size)
|
||||
#endif
|
||||
|
||||
#ifdef MEMBLOCK_FREE
|
||||
#define memblock_free_cb(address,size) MEMBLOCK_FREE(address,size)
|
||||
#endif
|
||||
|
||||
struct memblock
|
||||
{
|
||||
memaddress begin;
|
||||
memaddress size;
|
||||
memhandle nextblock;
|
||||
};
|
||||
|
||||
class MemoryPool
|
||||
{
|
||||
#ifdef MEMPOOLTEST_H
|
||||
friend class MemoryPoolTest;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
memaddress poolsize;
|
||||
struct memblock blocks[NUM_MEMBLOCKS+1];
|
||||
#ifdef MEMBLOCK_MV
|
||||
virtual void memblock_mv_cb(memaddress dest, memaddress src, memaddress size) = 0;
|
||||
#endif
|
||||
|
||||
public:
|
||||
MemoryPool(memaddress start, memaddress size);
|
||||
memhandle
|
||||
allocBlock(memaddress);
|
||||
void freeBlock(memhandle);
|
||||
void resizeBlock(memhandle handle, memaddress position);
|
||||
void resizeBlock(memhandle handle, memaddress position, memaddress size);
|
||||
memaddress blockSize(memhandle);
|
||||
};
|
||||
#endif
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef MEMPOOLCONF_H
|
||||
#define MEMPOOLCONF_H
|
||||
#include "uipethernet-conf.h"
|
||||
extern "C" {
|
||||
#include "uipopt.h"
|
||||
}
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef uint16_t memaddress;
|
||||
typedef uint8_t memhandle;
|
||||
|
||||
#if UIP_SOCKET_NUMPACKETS and UIP_CONNS
|
||||
#define NUM_TCP_MEMBLOCKS (UIP_SOCKET_NUMPACKETS*2)*UIP_CONNS
|
||||
#else
|
||||
#define NUM_TCP_MEMBLOCKS 0
|
||||
#endif
|
||||
|
||||
#if UIP_UDP and UIP_UDP_NUMPACKETS and UIP_UDP_CONNS
|
||||
#define NUM_UDP_MEMBLOCKS (UIP_UDP_NUMPACKETS+1)*UIP_UDP_CONNS
|
||||
#else
|
||||
#define NUM_UDP_MEMBLOCKS 0
|
||||
#endif
|
||||
|
||||
#define NUM_MEMBLOCKS (NUM_TCP_MEMBLOCKS+NUM_UDP_MEMBLOCKS)
|
||||
|
||||
#define MEMBLOCK_MV
|
||||
|
||||
#endif
|
||||
@@ -1,185 +0,0 @@
|
||||
/**
|
||||
* UIPEthernet Project-specific configuration options
|
||||
* Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
* @{
|
||||
*
|
||||
* uIP has a number of configuration options that can be overridden
|
||||
* for each project. These are kept in a project-specific uip-conf.h
|
||||
* file and all configuration names have the prefix UIP_CONF.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UIP_CONF_H__
|
||||
#define __UIP_CONF_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "uipethernet-conf.h"
|
||||
|
||||
/**
|
||||
* 8 bit datatype
|
||||
*
|
||||
* This typedef defines the 8-bit type used throughout uIP.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
typedef uint8_t u8_t;
|
||||
|
||||
/**
|
||||
* 16 bit datatype
|
||||
*
|
||||
* This typedef defines the 16-bit type used throughout uIP.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
typedef uint16_t u16_t;
|
||||
|
||||
/**
|
||||
* Statistics datatype
|
||||
*
|
||||
* This typedef defines the dataype used for keeping statistics in
|
||||
* uIP.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
typedef unsigned short uip_stats_t;
|
||||
|
||||
/**
|
||||
* Maximum number of TCP connections.
|
||||
* (see uipethernet-conf.h)
|
||||
* \hideinitializer
|
||||
*
|
||||
* #define UIP_CONF_MAX_CONNECTIONS 4
|
||||
*/
|
||||
|
||||
/**
|
||||
* Maximum number of listening TCP ports.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_MAX_LISTENPORTS 4
|
||||
|
||||
/**
|
||||
* uIP buffer size.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_BUFFER_SIZE 98
|
||||
//#define UIP_CONF_BUFFER_SIZE 118
|
||||
|
||||
/**
|
||||
* The TCP maximum segment size.
|
||||
*
|
||||
* This is should not be to set to more than
|
||||
* UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
|
||||
*/
|
||||
|
||||
#define UIP_CONF_TCP_MSS 512
|
||||
|
||||
/**
|
||||
* The size of the advertised receiver's window.
|
||||
*
|
||||
* Should be set low (i.e., to the size of the uip_buf buffer) is the
|
||||
* application is slow to process incoming data, or high (32768 bytes)
|
||||
* if the application processes data quickly.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_RECEIVE_WINDOW 512
|
||||
|
||||
/**
|
||||
* CPU byte order.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
/**
|
||||
* Logging on or off
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_LOGGING 0
|
||||
|
||||
/**
|
||||
* UDP support on or off
|
||||
* (see uipethernet-conf.h)
|
||||
* \hideinitializer
|
||||
*
|
||||
* #define UIP_CONF_UDP 1
|
||||
*
|
||||
* #define UIP_CONF_UDP_CONNS 4
|
||||
*/
|
||||
|
||||
/**
|
||||
* UDP checksums on or off
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_UDP_CHECKSUMS 1
|
||||
|
||||
/**
|
||||
* UDP Broadcast (receive) on or off
|
||||
* (see uipethernet-conf.h)
|
||||
* \hideinitializer
|
||||
* #define UIP_CONF_BROADCAST 1
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* uIP statistics on or off
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_STATISTICS 0
|
||||
|
||||
// SLIP
|
||||
//#define UIP_CONF_LLH_LEN 0
|
||||
|
||||
typedef void* uip_tcp_appstate_t;
|
||||
|
||||
void uipclient_appcall(void);
|
||||
|
||||
#define UIP_APPCALL uipclient_appcall
|
||||
|
||||
typedef void* uip_udp_appstate_t;
|
||||
|
||||
void uipudp_appcall(void);
|
||||
|
||||
#define UIP_UDP_APPCALL uipudp_appcall
|
||||
|
||||
#define CC_REGISTER_ARG register
|
||||
|
||||
#define UIP_ARCH_CHKSUM 1
|
||||
|
||||
#endif /* __UIP_CONF_H__ */
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* $Id: uip-neighbor.c,v 1.2 2006/06/12 08:00:30 adam Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Database of link-local neighbors, used by IPv6 code and
|
||||
* to be used by a future ARP code rewrite.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
#include "uip-neighbor.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_TIME 128
|
||||
|
||||
#ifdef UIP_NEIGHBOR_CONF_ENTRIES
|
||||
#define ENTRIES UIP_NEIGHBOR_CONF_ENTRIES
|
||||
#else /* UIP_NEIGHBOR_CONF_ENTRIES */
|
||||
#define ENTRIES 8
|
||||
#endif /* UIP_NEIGHBOR_CONF_ENTRIES */
|
||||
|
||||
struct neighbor_entry {
|
||||
uip_ipaddr_t ipaddr;
|
||||
struct uip_neighbor_addr addr;
|
||||
u8_t time;
|
||||
};
|
||||
static struct neighbor_entry entries[ENTRIES];
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_neighbor_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ENTRIES; ++i) {
|
||||
entries[i].time = MAX_TIME;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_neighbor_periodic(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ENTRIES; ++i) {
|
||||
if(entries[i].time < MAX_TIME) {
|
||||
entries[i].time++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr)
|
||||
{
|
||||
int i, oldest;
|
||||
u8_t oldest_time;
|
||||
|
||||
printf("Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
addr->addr.addr[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3],
|
||||
addr->addr.addr[4], addr->addr.addr[5]);
|
||||
|
||||
/* Find the first unused entry or the oldest used entry. */
|
||||
oldest_time = 0;
|
||||
oldest = 0;
|
||||
for(i = 0; i < ENTRIES; ++i) {
|
||||
if(entries[i].time == MAX_TIME) {
|
||||
oldest = i;
|
||||
break;
|
||||
}
|
||||
if(uip_ipaddr_cmp(entries[i].ipaddr, addr)) {
|
||||
oldest = i;
|
||||
break;
|
||||
}
|
||||
if(entries[i].time > oldest_time) {
|
||||
oldest = i;
|
||||
oldest_time = entries[i].time;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use the oldest or first free entry (either pointed to by the
|
||||
"oldest" variable). */
|
||||
entries[oldest].time = 0;
|
||||
uip_ipaddr_copy(entries[oldest].ipaddr, ipaddr);
|
||||
memcpy(&entries[oldest].addr, addr, sizeof(struct uip_neighbor_addr));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct neighbor_entry *
|
||||
find_entry(uip_ipaddr_t ipaddr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ENTRIES; ++i) {
|
||||
if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) {
|
||||
return &entries[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_neighbor_update(uip_ipaddr_t ipaddr)
|
||||
{
|
||||
struct neighbor_entry *e;
|
||||
|
||||
e = find_entry(ipaddr);
|
||||
if(e != NULL) {
|
||||
e->time = 0;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct uip_neighbor_addr *
|
||||
uip_neighbor_lookup(uip_ipaddr_t ipaddr)
|
||||
{
|
||||
struct neighbor_entry *e;
|
||||
|
||||
e = find_entry(ipaddr);
|
||||
if(e != NULL) {
|
||||
/* printf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3],
|
||||
e->addr.addr.addr[4], e->addr.addr.addr[5]);*/
|
||||
|
||||
return &e->addr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* $Id: uip-neighbor.h,v 1.2 2006/06/12 08:00:30 adam Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Header file for database of link-local neighbors, used by
|
||||
* IPv6 code and to be used by future ARP code.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef __UIP_NEIGHBOR_H__
|
||||
#define __UIP_NEIGHBOR_H__
|
||||
|
||||
#include "uip.h"
|
||||
|
||||
struct uip_neighbor_addr {
|
||||
#if UIP_NEIGHBOR_CONF_ADDRTYPE
|
||||
UIP_NEIGHBOR_CONF_ADDRTYPE addr;
|
||||
#else
|
||||
struct uip_eth_addr addr;
|
||||
#endif
|
||||
};
|
||||
|
||||
void uip_neighbor_init(void);
|
||||
void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr);
|
||||
void uip_neighbor_update(uip_ipaddr_t ipaddr);
|
||||
struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr);
|
||||
void uip_neighbor_periodic(void);
|
||||
|
||||
#endif /* __UIP-NEIGHBOR_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,138 +0,0 @@
|
||||
/**
|
||||
* \addtogroup uip
|
||||
* {@
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup uiparch Architecture specific uIP functions
|
||||
* @{
|
||||
*
|
||||
* The functions in the architecture specific module implement the IP
|
||||
* check sum and 32-bit additions.
|
||||
*
|
||||
* The IP checksum calculation is the most computationally expensive
|
||||
* operation in the TCP/IP stack and it therefore pays off to
|
||||
* implement this in efficient assembler. The purpose of the uip-arch
|
||||
* module is to let the checksum functions to be implemented in
|
||||
* architecture specific assembler.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Declarations of architecture specific functions.
|
||||
* \author Adam Dunkels <adam@dunkels.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: uip_arch.h,v 1.2 2006/06/07 09:15:19 adam Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UIP_ARCH_H__
|
||||
#define __UIP_ARCH_H__
|
||||
|
||||
#include "uip.h"
|
||||
|
||||
/**
|
||||
* Carry out a 32-bit addition.
|
||||
*
|
||||
* Because not all architectures for which uIP is intended has native
|
||||
* 32-bit arithmetic, uIP uses an external C function for doing the
|
||||
* required 32-bit additions in the TCP protocol processing. This
|
||||
* function should add the two arguments and place the result in the
|
||||
* global variable uip_acc32.
|
||||
*
|
||||
* \note The 32-bit integer pointed to by the op32 parameter and the
|
||||
* result in the uip_acc32 variable are in network byte order (big
|
||||
* endian).
|
||||
*
|
||||
* \param op32 A pointer to a 4-byte array representing a 32-bit
|
||||
* integer in network byte order (big endian).
|
||||
*
|
||||
* \param op16 A 16-bit integer in host byte order.
|
||||
*/
|
||||
void uip_add32(u8_t *op32, u16_t op16);
|
||||
|
||||
/**
|
||||
* Calculate the Internet checksum over a buffer.
|
||||
*
|
||||
* The Internet checksum is the one's complement of the one's
|
||||
* complement sum of all 16-bit words in the buffer.
|
||||
*
|
||||
* See RFC1071.
|
||||
*
|
||||
* \note This function is not called in the current version of uIP,
|
||||
* but future versions might make use of it.
|
||||
*
|
||||
* \param buf A pointer to the buffer over which the checksum is to be
|
||||
* computed.
|
||||
*
|
||||
* \param len The length of the buffer over which the checksum is to
|
||||
* be computed.
|
||||
*
|
||||
* \return The Internet checksum of the buffer.
|
||||
*/
|
||||
u16_t uip_chksum(u16_t *buf, u16_t len);
|
||||
|
||||
/**
|
||||
* Calculate the IP header checksum of the packet header in uip_buf.
|
||||
*
|
||||
* The IP header checksum is the Internet checksum of the 20 bytes of
|
||||
* the IP header.
|
||||
*
|
||||
* \return The IP header checksum of the IP header in the uip_buf
|
||||
* buffer.
|
||||
*/
|
||||
u16_t uip_ipchksum(void);
|
||||
|
||||
/**
|
||||
* Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
|
||||
*
|
||||
* The TCP checksum is the Internet checksum of data contents of the
|
||||
* TCP segment, and a pseudo-header as defined in RFC793.
|
||||
*
|
||||
* \note The uip_appdata pointer that points to the packet data may
|
||||
* point anywhere in memory, so it is not possible to simply calculate
|
||||
* the Internet checksum of the contents of the uip_buf buffer.
|
||||
*
|
||||
* \return The TCP checksum of the TCP segment in uip_buf and pointed
|
||||
* to by uip_appdata.
|
||||
*/
|
||||
u16_t uip_tcpchksum(void);
|
||||
|
||||
u16_t uip_udpchksum(void);
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
#endif /* __UIP_ARCH_H__ */
|
||||
@@ -1,423 +0,0 @@
|
||||
/**
|
||||
* \addtogroup uip
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup uiparp uIP Address Resolution Protocol
|
||||
* @{
|
||||
*
|
||||
* The Address Resolution Protocol ARP is used for mapping between IP
|
||||
* addresses and link level addresses such as the Ethernet MAC
|
||||
* addresses. ARP uses broadcast queries to ask for the link level
|
||||
* address of a known IP address and the host which is configured with
|
||||
* the IP address for which the query was meant, will respond with its
|
||||
* link level address.
|
||||
*
|
||||
* \note This ARP implementation only supports Ethernet.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Implementation of the ARP Address Resolution Protocol.
|
||||
* \author Adam Dunkels <adam@dunkels.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "uip_arp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct arp_hdr {
|
||||
struct uip_eth_hdr ethhdr;
|
||||
u16_t hwtype;
|
||||
u16_t protocol;
|
||||
u8_t hwlen;
|
||||
u8_t protolen;
|
||||
u16_t opcode;
|
||||
struct uip_eth_addr shwaddr;
|
||||
u16_t sipaddr[2];
|
||||
struct uip_eth_addr dhwaddr;
|
||||
u16_t dipaddr[2];
|
||||
};
|
||||
|
||||
struct ethip_hdr {
|
||||
struct uip_eth_hdr ethhdr;
|
||||
/* IP header. */
|
||||
u8_t vhl,
|
||||
tos,
|
||||
len[2],
|
||||
ipid[2],
|
||||
ipoffset[2],
|
||||
ttl,
|
||||
proto;
|
||||
u16_t ipchksum;
|
||||
u16_t srcipaddr[2],
|
||||
destipaddr[2];
|
||||
};
|
||||
|
||||
#define ARP_REQUEST 1
|
||||
#define ARP_REPLY 2
|
||||
|
||||
#define ARP_HWTYPE_ETH 1
|
||||
|
||||
struct arp_entry {
|
||||
u16_t ipaddr[2];
|
||||
struct uip_eth_addr ethaddr;
|
||||
u8_t time;
|
||||
};
|
||||
|
||||
static const struct uip_eth_addr broadcast_ethaddr =
|
||||
{{0xff,0xff,0xff,0xff,0xff,0xff}};
|
||||
static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff};
|
||||
|
||||
static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
|
||||
static u16_t ipaddr[2];
|
||||
static u8_t i, c;
|
||||
|
||||
static u8_t arptime;
|
||||
static u8_t tmpage;
|
||||
|
||||
#define BUF ((struct arp_hdr *)&uip_buf[0])
|
||||
#define IPBUF ((struct ethip_hdr *)&uip_buf[0])
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Initialize the ARP module.
|
||||
*
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_init(void)
|
||||
{
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
memset(arp_table[i].ipaddr, 0, 4);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Periodic ARP processing function.
|
||||
*
|
||||
* This function performs periodic timer processing in the ARP module
|
||||
* and should be called at regular intervals. The recommended interval
|
||||
* is 10 seconds between the calls.
|
||||
*
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_timer(void)
|
||||
{
|
||||
struct arp_entry *tabptr;
|
||||
|
||||
++arptime;
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
|
||||
arptime - tabptr->time >= UIP_ARP_MAXAGE) {
|
||||
memset(tabptr->ipaddr, 0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void
|
||||
uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
|
||||
{
|
||||
register struct arp_entry *tabptr;
|
||||
/* Walk through the ARP mapping table and try to find an entry to
|
||||
update. If none is found, the IP -> MAC address mapping is
|
||||
inserted in the ARP table. */
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
|
||||
tabptr = &arp_table[i];
|
||||
/* Only check those entries that are actually in use. */
|
||||
if(tabptr->ipaddr[0] != 0 &&
|
||||
tabptr->ipaddr[1] != 0) {
|
||||
|
||||
/* Check if the source IP address of the incoming packet matches
|
||||
the IP address in this ARP table entry. */
|
||||
if(ipaddr[0] == tabptr->ipaddr[0] &&
|
||||
ipaddr[1] == tabptr->ipaddr[1]) {
|
||||
|
||||
/* An old entry found, update this and return. */
|
||||
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
|
||||
tabptr->time = arptime;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we get here, no existing ARP table entry was found, so we
|
||||
create one. */
|
||||
|
||||
/* First, we try to find an unused entry in the ARP table. */
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(tabptr->ipaddr[0] == 0 &&
|
||||
tabptr->ipaddr[1] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no unused entry is found, we try to find the oldest entry and
|
||||
throw it away. */
|
||||
if(i == UIP_ARPTAB_SIZE) {
|
||||
tmpage = 0;
|
||||
c = 0;
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(arptime - tabptr->time > tmpage) {
|
||||
tmpage = arptime - tabptr->time;
|
||||
c = i;
|
||||
}
|
||||
}
|
||||
i = c;
|
||||
tabptr = &arp_table[i];
|
||||
}
|
||||
|
||||
/* Now, i is the ARP table entry which we will fill with the new
|
||||
information. */
|
||||
memcpy(tabptr->ipaddr, ipaddr, 4);
|
||||
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
|
||||
tabptr->time = arptime;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* ARP processing for incoming IP packets
|
||||
*
|
||||
* This function should be called by the device driver when an IP
|
||||
* packet has been received. The function will check if the address is
|
||||
* in the ARP cache, and if so the ARP cache entry will be
|
||||
* refreshed. If no ARP cache entry was found, a new one is created.
|
||||
*
|
||||
* This function expects an IP packet with a prepended Ethernet header
|
||||
* in the uip_buf[] buffer, and the length of the packet in the global
|
||||
* variable uip_len.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
//#if 0
|
||||
void
|
||||
uip_arp_ipin(void)
|
||||
{
|
||||
uip_len -= sizeof(struct uip_eth_hdr);
|
||||
|
||||
/* Only insert/update an entry if the source IP address of the
|
||||
incoming IP packet comes from a host on the local network. */
|
||||
if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
|
||||
(uip_hostaddr[0] & uip_netmask[0])) {
|
||||
return;
|
||||
}
|
||||
if((IPBUF->srcipaddr[1] & uip_netmask[1]) !=
|
||||
(uip_hostaddr[1] & uip_netmask[1])) {
|
||||
return;
|
||||
}
|
||||
uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
|
||||
|
||||
return;
|
||||
}
|
||||
//#endif /* 0 */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* ARP processing for incoming ARP packets.
|
||||
*
|
||||
* This function should be called by the device driver when an ARP
|
||||
* packet has been received. The function will act differently
|
||||
* depending on the ARP packet type: if it is a reply for a request
|
||||
* that we previously sent out, the ARP cache will be filled in with
|
||||
* the values from the ARP reply. If the incoming ARP packet is an ARP
|
||||
* request for our IP address, an ARP reply packet is created and put
|
||||
* into the uip_buf[] buffer.
|
||||
*
|
||||
* When the function returns, the value of the global variable uip_len
|
||||
* indicates whether the device driver should send out a packet or
|
||||
* not. If uip_len is zero, no packet should be sent. If uip_len is
|
||||
* non-zero, it contains the length of the outbound packet that is
|
||||
* present in the uip_buf[] buffer.
|
||||
*
|
||||
* This function expects an ARP packet with a prepended Ethernet
|
||||
* header in the uip_buf[] buffer, and the length of the packet in the
|
||||
* global variable uip_len.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_arpin(void)
|
||||
{
|
||||
|
||||
if(uip_len < sizeof(struct arp_hdr)) {
|
||||
uip_len = 0;
|
||||
return;
|
||||
}
|
||||
uip_len = 0;
|
||||
|
||||
switch(BUF->opcode) {
|
||||
case HTONS(ARP_REQUEST):
|
||||
/* ARP request. If it asked for our address, we send out a
|
||||
reply. */
|
||||
if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
|
||||
/* First, we register the one who made the request in our ARP
|
||||
table, since it is likely that we will do more communication
|
||||
with this host in the future. */
|
||||
uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
|
||||
|
||||
/* The reply opcode is 2. */
|
||||
BUF->opcode = HTONS(2);
|
||||
|
||||
memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
|
||||
memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
|
||||
memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||
memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
|
||||
|
||||
BUF->dipaddr[0] = BUF->sipaddr[0];
|
||||
BUF->dipaddr[1] = BUF->sipaddr[1];
|
||||
BUF->sipaddr[0] = uip_hostaddr[0];
|
||||
BUF->sipaddr[1] = uip_hostaddr[1];
|
||||
|
||||
BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
|
||||
uip_len = sizeof(struct arp_hdr);
|
||||
}
|
||||
break;
|
||||
case HTONS(ARP_REPLY):
|
||||
/* ARP reply. We insert or update the ARP table if it was meant
|
||||
for us. */
|
||||
if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
|
||||
uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Prepend Ethernet header to an outbound IP packet and see if we need
|
||||
* to send out an ARP request.
|
||||
*
|
||||
* This function should be called before sending out an IP packet. The
|
||||
* function checks the destination IP address of the IP packet to see
|
||||
* what Ethernet MAC address that should be used as a destination MAC
|
||||
* address on the Ethernet.
|
||||
*
|
||||
* If the destination IP address is in the local network (determined
|
||||
* by logical ANDing of netmask and our IP address), the function
|
||||
* checks the ARP cache to see if an entry for the destination IP
|
||||
* address is found. If so, an Ethernet header is prepended and the
|
||||
* function returns. If no ARP cache entry is found for the
|
||||
* destination IP address, the packet in the uip_buf[] is replaced by
|
||||
* an ARP request packet for the IP address. The IP packet is dropped
|
||||
* and it is assumed that they higher level protocols (e.g., TCP)
|
||||
* eventually will retransmit the dropped packet.
|
||||
*
|
||||
* If the destination IP address is not on the local network, the IP
|
||||
* address of the default router is used instead.
|
||||
*
|
||||
* When the function returns, a packet is present in the uip_buf[]
|
||||
* buffer, and the length of the packet is in the global variable
|
||||
* uip_len.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_out(void)
|
||||
{
|
||||
struct arp_entry *tabptr;
|
||||
|
||||
/* Find the destination IP address in the ARP table and construct
|
||||
the Ethernet header. If the destination IP addres isn't on the
|
||||
local network, we use the default router's IP address instead.
|
||||
|
||||
If not ARP table entry is found, we overwrite the original IP
|
||||
packet with an ARP request for the IP address. */
|
||||
|
||||
/* First check if destination is a local broadcast. */
|
||||
if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) {
|
||||
memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
|
||||
} else {
|
||||
/* Check if the destination address is on the local network. */
|
||||
if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) {
|
||||
/* Destination address was not on the local network, so we need to
|
||||
use the default router's IP address instead of the destination
|
||||
address when determining the MAC address. */
|
||||
uip_ipaddr_copy(ipaddr, uip_draddr);
|
||||
} else {
|
||||
/* Else, we use the destination IP address. */
|
||||
uip_ipaddr_copy(ipaddr, IPBUF->destipaddr);
|
||||
}
|
||||
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == UIP_ARPTAB_SIZE) {
|
||||
/* The destination address was not in our ARP table, so we
|
||||
overwrite the IP packet with an ARP request. */
|
||||
|
||||
memset(BUF->ethhdr.dest.addr, 0xff, 6);
|
||||
memset(BUF->dhwaddr.addr, 0x00, 6);
|
||||
memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||
memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
|
||||
|
||||
uip_ipaddr_copy(BUF->dipaddr, ipaddr);
|
||||
uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr);
|
||||
BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
|
||||
BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
|
||||
BUF->protocol = HTONS(UIP_ETHTYPE_IP);
|
||||
BUF->hwlen = 6;
|
||||
BUF->protolen = 4;
|
||||
BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
|
||||
|
||||
uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
|
||||
|
||||
uip_len = sizeof(struct arp_hdr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build an ethernet header. */
|
||||
memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
|
||||
}
|
||||
memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||
|
||||
IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
|
||||
|
||||
uip_len += sizeof(struct uip_eth_hdr);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
@@ -1,144 +0,0 @@
|
||||
/**
|
||||
* \addtogroup uip
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uiparp
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Macros and definitions for the ARP module.
|
||||
* \author Adam Dunkels <adam@dunkels.com>
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: uip_arp.h,v 1.5 2006/06/11 21:46:39 adam Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UIP_ARP_H__
|
||||
#define __UIP_ARP_H__
|
||||
|
||||
#include "uip.h"
|
||||
|
||||
|
||||
extern struct uip_eth_addr uip_ethaddr;
|
||||
|
||||
/**
|
||||
* The Ethernet header.
|
||||
*/
|
||||
struct uip_eth_hdr {
|
||||
struct uip_eth_addr dest;
|
||||
struct uip_eth_addr src;
|
||||
u16_t type;
|
||||
};
|
||||
|
||||
#define UIP_ETHTYPE_ARP 0x0806
|
||||
#define UIP_ETHTYPE_IP 0x0800
|
||||
#define UIP_ETHTYPE_IP6 0x86dd
|
||||
|
||||
|
||||
/* The uip_arp_init() function must be called before any of the other
|
||||
ARP functions. */
|
||||
void uip_arp_init(void);
|
||||
|
||||
/* The uip_arp_ipin() function should be called whenever an IP packet
|
||||
arrives from the Ethernet. This function refreshes the ARP table or
|
||||
inserts a new mapping if none exists. The function assumes that an
|
||||
IP packet with an Ethernet header is present in the uip_buf buffer
|
||||
and that the length of the packet is in the uip_len variable. */
|
||||
void uip_arp_ipin(void);
|
||||
//#define uip_arp_ipin()
|
||||
|
||||
/* The uip_arp_arpin() should be called when an ARP packet is received
|
||||
by the Ethernet driver. This function also assumes that the
|
||||
Ethernet frame is present in the uip_buf buffer. When the
|
||||
uip_arp_arpin() function returns, the contents of the uip_buf
|
||||
buffer should be sent out on the Ethernet if the uip_len variable
|
||||
is > 0. */
|
||||
void uip_arp_arpin(void);
|
||||
|
||||
/* The uip_arp_out() function should be called when an IP packet
|
||||
should be sent out on the Ethernet. This function creates an
|
||||
Ethernet header before the IP header in the uip_buf buffer. The
|
||||
Ethernet header will have the correct Ethernet MAC destination
|
||||
address filled in if an ARP table entry for the destination IP
|
||||
address (or the IP address of the default router) is present. If no
|
||||
such table entry is found, the IP packet is overwritten with an ARP
|
||||
request and we rely on TCP to retransmit the packet that was
|
||||
overwritten. In any case, the uip_len variable holds the length of
|
||||
the Ethernet frame that should be transmitted. */
|
||||
void uip_arp_out(void);
|
||||
|
||||
/* The uip_arp_timer() function should be called every ten seconds. It
|
||||
is responsible for flushing old entries in the ARP table. */
|
||||
void uip_arp_timer(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \addtogroup uipconffunc
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Specifiy the Ethernet MAC address.
|
||||
*
|
||||
* The ARP code needs to know the MAC address of the Ethernet card in
|
||||
* order to be able to respond to ARP queries and to generate working
|
||||
* Ethernet headers.
|
||||
*
|
||||
* \note This macro only specifies the Ethernet MAC address to the ARP
|
||||
* code. It cannot be used to change the MAC address of the Ethernet
|
||||
* card.
|
||||
*
|
||||
* \param eaddr A pointer to a struct uip_eth_addr containing the
|
||||
* Ethernet MAC address of the Ethernet card.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \
|
||||
uip_ethaddr.addr[1] = eaddr.addr[1];\
|
||||
uip_ethaddr.addr[2] = eaddr.addr[2];\
|
||||
uip_ethaddr.addr[3] = eaddr.addr[3];\
|
||||
uip_ethaddr.addr[4] = eaddr.addr[4];\
|
||||
uip_ethaddr.addr[5] = eaddr.addr[5];} while(0)
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
#endif /* __UIP_ARP_H__ */
|
||||
@@ -1,88 +0,0 @@
|
||||
/**
|
||||
* \defgroup clock Clock interface
|
||||
*
|
||||
* The clock interface is the interface between the \ref timer "timer library"
|
||||
* and the platform specific clock functionality. The clock
|
||||
* interface must be implemented for each platform that uses the \ref
|
||||
* timer "timer library".
|
||||
*
|
||||
* The clock interface does only one this: it measures time. The clock
|
||||
* interface provides a macro, CLOCK_SECOND, which corresponds to one
|
||||
* second of system time.
|
||||
*
|
||||
* \sa \ref timer "Timer library"
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: clock.h,v 1.3 2006/06/11 21:46:39 adam Exp $
|
||||
*/
|
||||
#ifndef __UIP_CLOCK_H__
|
||||
#define __UIP_CLOCK_H__
|
||||
|
||||
#include "clock-arch.h"
|
||||
|
||||
/**
|
||||
* Initialize the clock library.
|
||||
*
|
||||
* This function initializes the clock library and should be called
|
||||
* from the main() function of the system.
|
||||
*
|
||||
*/
|
||||
void uip_clock_init(void);
|
||||
|
||||
/**
|
||||
* Get the current clock time.
|
||||
*
|
||||
* This function returns the current system clock time.
|
||||
*
|
||||
* \return The current clock time, measured in system ticks.
|
||||
*/
|
||||
clock_time_t clock_time(void);
|
||||
|
||||
/**
|
||||
* A second, measured in system clock time.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifdef CLOCK_CONF_SECOND
|
||||
#define CLOCK_SECOND CLOCK_CONF_SECOND
|
||||
#else
|
||||
#define CLOCK_SECOND (clock_time_t)32
|
||||
#endif
|
||||
|
||||
#endif /* __CLOCK_H__ */
|
||||
|
||||
/** @} */
|
||||
@@ -1,170 +0,0 @@
|
||||
#include <Arduino.h>
|
||||
#include <HardwareSerial.h>
|
||||
#include <inttypes.h>
|
||||
#include <utility/uip_debug.h>
|
||||
extern "C" {
|
||||
#import "utility/uip.h"
|
||||
}
|
||||
|
||||
struct uip_conn con[UIP_CONNS];
|
||||
|
||||
void
|
||||
UIPDebug::uip_debug_printconns()
|
||||
{
|
||||
for(uint8_t i=0;i<UIP_CONNS;i++)
|
||||
{
|
||||
if (uip_debug_printcon(&con[i],&uip_conns[i]))
|
||||
{
|
||||
Serial.print("connection[");
|
||||
Serial.print(i);
|
||||
Serial.println("] changed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
UIPDebug::uip_debug_printcon(struct uip_conn *lhs,struct uip_conn *rhs)
|
||||
{
|
||||
bool changed = false;
|
||||
if (!uip_ipaddr_cmp(lhs->ripaddr,rhs->ripaddr))
|
||||
{
|
||||
Serial.print(" ripaddr: ");
|
||||
uip_debug_printbytes((const uint8_t *)lhs->ripaddr,4);
|
||||
Serial.print(" -> ");
|
||||
uip_debug_printbytes((const uint8_t *)rhs->ripaddr,4);
|
||||
Serial.println();
|
||||
uip_ipaddr_copy(lhs->ripaddr,rhs->ripaddr);
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->lport != rhs->lport)
|
||||
{
|
||||
Serial.print(" lport: ");
|
||||
Serial.print(htons(lhs->lport));
|
||||
Serial.print(" -> ");
|
||||
Serial.println(htons(rhs->lport));
|
||||
lhs->lport = rhs->lport;
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->rport != rhs->rport)
|
||||
{
|
||||
Serial.print(" rport: ");
|
||||
Serial.print(htons(lhs->rport));
|
||||
Serial.print(" -> ");
|
||||
Serial.println(htons(rhs->rport));
|
||||
lhs->rport = rhs->rport;
|
||||
changed = true;
|
||||
}
|
||||
if ((uint32_t)lhs->rcv_nxt[0] != (uint32_t)rhs->rcv_nxt[0])
|
||||
{
|
||||
Serial.print(" rcv_nxt: ");
|
||||
uip_debug_printbytes(lhs->rcv_nxt,4);
|
||||
Serial.print(" -> ");
|
||||
uip_debug_printbytes(rhs->rcv_nxt,4);
|
||||
*((uint32_t *)&lhs->rcv_nxt[0]) = (uint32_t)rhs->rcv_nxt[0];
|
||||
Serial.println();
|
||||
changed = true;
|
||||
}
|
||||
if ((uint32_t)lhs->snd_nxt[0] != (uint32_t)rhs->snd_nxt[0])
|
||||
{
|
||||
Serial.print(" snd_nxt: ");
|
||||
uip_debug_printbytes(lhs->snd_nxt,4);
|
||||
Serial.print(" -> ");
|
||||
uip_debug_printbytes(rhs->snd_nxt,4);
|
||||
*((uint32_t *)&lhs->snd_nxt[0]) = (uint32_t)rhs->snd_nxt[0];
|
||||
Serial.println();
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->len != rhs->len)
|
||||
{
|
||||
Serial.print(" len: ");
|
||||
Serial.print(lhs->len);
|
||||
Serial.print(" -> ");
|
||||
Serial.println(rhs->len);
|
||||
lhs->len = rhs->len;
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->mss != rhs->mss)
|
||||
{
|
||||
Serial.print(" mss: ");
|
||||
Serial.print(lhs->mss);
|
||||
Serial.print(" -> ");
|
||||
Serial.println(rhs->mss);
|
||||
lhs->mss = rhs->mss;
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->initialmss != rhs->initialmss)
|
||||
{
|
||||
Serial.print(" initialmss: ");
|
||||
Serial.print(lhs->initialmss);
|
||||
Serial.print(" -> ");
|
||||
Serial.println(rhs->initialmss);
|
||||
lhs->initialmss = rhs->initialmss;
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->sa != rhs->sa)
|
||||
{
|
||||
Serial.print(" sa: ");
|
||||
Serial.print(lhs->sa);
|
||||
Serial.print(" -> ");
|
||||
Serial.println(rhs->sa);
|
||||
lhs->sa = rhs->sa;
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->sv != rhs->sv)
|
||||
{
|
||||
Serial.print(" sv: ");
|
||||
Serial.print(lhs->sv);
|
||||
Serial.print(" -> ");
|
||||
Serial.println(rhs->sv);
|
||||
lhs->sv = rhs->sv;
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->rto != rhs->rto)
|
||||
{
|
||||
Serial.print(" rto: ");
|
||||
Serial.print(lhs->rto);
|
||||
Serial.print(" -> ");
|
||||
Serial.println(rhs->rto);
|
||||
lhs->rto = rhs->rto;
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->tcpstateflags != rhs->tcpstateflags)
|
||||
{
|
||||
Serial.print(" tcpstateflags: ");
|
||||
Serial.print(lhs->tcpstateflags);
|
||||
Serial.print(" -> ");
|
||||
Serial.println(rhs->tcpstateflags);
|
||||
lhs->tcpstateflags = rhs->tcpstateflags;
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->timer != rhs->timer)
|
||||
{
|
||||
Serial.print(" timer: ");
|
||||
Serial.print(lhs->timer);
|
||||
Serial.print(" -> ");
|
||||
Serial.println(rhs->timer);
|
||||
lhs->timer = rhs->timer;
|
||||
changed = true;
|
||||
}
|
||||
if (lhs->nrtx != rhs->nrtx)
|
||||
{
|
||||
Serial.print(" nrtx: ");
|
||||
Serial.print(lhs->nrtx);
|
||||
Serial.print(" -> ");
|
||||
Serial.println(rhs->nrtx);
|
||||
lhs->nrtx = rhs->nrtx;
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void
|
||||
UIPDebug::uip_debug_printbytes(const uint8_t *data, uint8_t len)
|
||||
{
|
||||
for(uint8_t i=0;i<len;i++)
|
||||
{
|
||||
Serial.print(data[i]);
|
||||
if (i<len-1)
|
||||
Serial.print(",");
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef UIP_DEBUG_H
|
||||
#define UIP_DEBUG_H
|
||||
extern "C" {
|
||||
#import "utility/uip.h"
|
||||
}
|
||||
|
||||
class UIPDebug {
|
||||
|
||||
public:
|
||||
|
||||
static void uip_debug_printconns();
|
||||
static bool uip_debug_printcon(struct uip_conn *lhs,struct uip_conn *rhs);
|
||||
static void uip_debug_printbytes(const uint8_t *data, uint8_t len);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,127 +0,0 @@
|
||||
/**
|
||||
* \addtogroup timer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Timer library implementation.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $
|
||||
*/
|
||||
|
||||
#include "uip_clock.h"
|
||||
#include "uip_timer.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Set a timer.
|
||||
*
|
||||
* This function is used to set a timer for a time sometime in the
|
||||
* future. The function timer_expired() will evaluate to true after
|
||||
* the timer has expired.
|
||||
*
|
||||
* \param t A pointer to the timer
|
||||
* \param interval The interval before the timer expires.
|
||||
*
|
||||
*/
|
||||
void
|
||||
uip_timer_set(struct uip_timer *t, clock_time_t interval)
|
||||
{
|
||||
t->interval = interval;
|
||||
t->start = clock_time();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Reset the timer with the same interval.
|
||||
*
|
||||
* This function resets the timer with the same interval that was
|
||||
* given to the timer_set() function. The start point of the interval
|
||||
* is the exact time that the timer last expired. Therefore, this
|
||||
* function will cause the timer to be stable over time, unlike the
|
||||
* timer_rester() function.
|
||||
*
|
||||
* \param t A pointer to the timer.
|
||||
*
|
||||
* \sa timer_restart()
|
||||
*/
|
||||
void
|
||||
uip_timer_reset(struct uip_timer *t)
|
||||
{
|
||||
t->start += t->interval;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Restart the timer from the current point in time
|
||||
*
|
||||
* This function restarts a timer with the same interval that was
|
||||
* given to the timer_set() function. The timer will start at the
|
||||
* current time.
|
||||
*
|
||||
* \note A periodic timer will drift if this function is used to reset
|
||||
* it. For preioric timers, use the timer_reset() function instead.
|
||||
*
|
||||
* \param t A pointer to the timer.
|
||||
*
|
||||
* \sa timer_reset()
|
||||
*/
|
||||
void
|
||||
uip_timer_restart(struct uip_timer *t)
|
||||
{
|
||||
t->start = clock_time();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Check if a timer has expired.
|
||||
*
|
||||
* This function tests if a timer has expired and returns true or
|
||||
* false depending on its status.
|
||||
*
|
||||
* \param t A pointer to the timer
|
||||
*
|
||||
* \return Non-zero if the timer has expired, zero otherwise.
|
||||
*
|
||||
*/
|
||||
int
|
||||
uip_timer_expired(struct uip_timer *t)
|
||||
{
|
||||
return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** @} */
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* \defgroup timer Timer library
|
||||
*
|
||||
* The timer library provides functions for setting, resetting and
|
||||
* restarting timers, and for checking if a timer has expired. An
|
||||
* application must "manually" check if its timers have expired; this
|
||||
* is not done automatically.
|
||||
*
|
||||
* A timer is declared as a \c struct \c timer and all access to the
|
||||
* timer is made by a pointer to the declared timer.
|
||||
*
|
||||
* \note The timer library uses the \ref clock "Clock library" to
|
||||
* measure time. Intervals should be specified in the format used by
|
||||
* the clock library.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Timer library header file.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $
|
||||
*/
|
||||
#ifndef __UIP_TIMER_H__
|
||||
#define __UIP_TIMER_H__
|
||||
|
||||
#include "uip_clock.h"
|
||||
|
||||
/**
|
||||
* A timer.
|
||||
*
|
||||
* This structure is used for declaring a timer. The timer must be set
|
||||
* with timer_set() before it can be used.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
struct uip_timer {
|
||||
clock_time_t start;
|
||||
clock_time_t interval;
|
||||
};
|
||||
|
||||
void uip_timer_set(struct uip_timer *t, clock_time_t interval);
|
||||
void uip_timer_reset(struct uip_timer *t);
|
||||
void uip_timer_restart(struct uip_timer *t);
|
||||
int uip_timer_expired(struct uip_timer *t);
|
||||
|
||||
#endif /* __UIP_TIMER_H__ */
|
||||
|
||||
/** @} */
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef UIPETHERNET_CONF_H
|
||||
#define UIPETHERNET_CONF_H
|
||||
|
||||
/* for TCP */
|
||||
#define UIP_SOCKET_NUMPACKETS 5
|
||||
#define UIP_CONF_MAX_CONNECTIONS 4
|
||||
|
||||
/* for UDP */
|
||||
#define UIP_CONF_UDP 0//1
|
||||
#define UIP_CONF_BROADCAST 0//1
|
||||
#define UIP_CONF_UDP_CONNS 0//4
|
||||
#define UIP_UDP_NUMPACKETS 0//5
|
||||
|
||||
/* number of attempts on write before returning number of bytes sent so far
|
||||
* set to -1 to block until connection is closed by timeout */
|
||||
#define UIP_ATTEMPTS_ON_WRITE -1
|
||||
|
||||
#endif
|
||||
@@ -1,543 +0,0 @@
|
||||
/**
|
||||
* \defgroup uipopt Configuration options for uIP
|
||||
* @{
|
||||
*
|
||||
* uIP is configured using the per-project configuration file
|
||||
* uipopt.h. This file contains all compile-time options for uIP and
|
||||
* should be tweaked to match each specific project. The uIP
|
||||
* distribution contains a documented example "uipopt.h" that can be
|
||||
* copied and modified for each project.
|
||||
*
|
||||
* \note Most of the configuration options in the uipopt.h should not
|
||||
* be changed, but rather the per-project uip-conf.h file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Configuration options for uIP.
|
||||
* \author Adam Dunkels <adam@dunkels.com>
|
||||
*
|
||||
* This file is used for tweaking various configuration options for
|
||||
* uIP. You should make a copy of this file into one of your project's
|
||||
* directories instead of editing this example "uipopt.h" file that
|
||||
* comes with the uIP distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: uipopt.h,v 1.4 2006/06/12 08:00:31 adam Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UIPOPT_H__
|
||||
#define __UIPOPT_H__
|
||||
|
||||
#ifndef UIP_LITTLE_ENDIAN
|
||||
#define UIP_LITTLE_ENDIAN 3412
|
||||
#endif /* UIP_LITTLE_ENDIAN */
|
||||
#ifndef UIP_BIG_ENDIAN
|
||||
#define UIP_BIG_ENDIAN 1234
|
||||
#endif /* UIP_BIG_ENDIAN */
|
||||
|
||||
#include "uip-conf.h"
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \name Static configuration options
|
||||
* @{
|
||||
*
|
||||
* These configuration options can be used for setting the IP address
|
||||
* settings statically, but only if UIP_FIXEDADDR is set to 1. The
|
||||
* configuration options for a specific node includes IP address,
|
||||
* netmask and default router as well as the Ethernet address. The
|
||||
* netmask, default router and Ethernet address are appliciable only
|
||||
* if uIP should be run over Ethernet.
|
||||
*
|
||||
* All of these should be changed to suit your project.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determines if uIP should use a fixed IP address or not.
|
||||
*
|
||||
* If uIP should use a fixed IP address, the settings are set in the
|
||||
* uipopt.h file. If not, the macros uip_sethostaddr(),
|
||||
* uip_setdraddr() and uip_setnetmask() should be used instead.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_FIXEDADDR 0
|
||||
|
||||
/**
|
||||
* Ping IP address asignment.
|
||||
*
|
||||
* uIP uses a "ping" packets for setting its own IP address if this
|
||||
* option is set. If so, uIP will start with an empty IP address and
|
||||
* the destination IP address of the first incoming "ping" (ICMP echo)
|
||||
* packet will be used for setting the hosts IP address.
|
||||
*
|
||||
* \note This works only if UIP_FIXEDADDR is 0.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifdef UIP_CONF_PINGADDRCONF
|
||||
#define UIP_PINGADDRCONF UIP_CONF_PINGADDRCONF
|
||||
#else /* UIP_CONF_PINGADDRCONF */
|
||||
#define UIP_PINGADDRCONF 0
|
||||
#endif /* UIP_CONF_PINGADDRCONF */
|
||||
|
||||
|
||||
/**
|
||||
* Specifies if the uIP ARP module should be compiled with a fixed
|
||||
* Ethernet MAC address or not.
|
||||
*
|
||||
* If this configuration option is 0, the macro uip_setethaddr() can
|
||||
* be used to specify the Ethernet address at run-time.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_FIXEDETHADDR 0
|
||||
|
||||
/** @} */
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \name IP configuration options
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* The IP TTL (time to live) of IP packets sent by uIP.
|
||||
*
|
||||
* This should normally not be changed.
|
||||
*/
|
||||
#define UIP_TTL 64
|
||||
|
||||
/**
|
||||
* Turn on support for IP packet reassembly.
|
||||
*
|
||||
* uIP supports reassembly of fragmented IP packets. This features
|
||||
* requires an additonal amount of RAM to hold the reassembly buffer
|
||||
* and the reassembly code size is approximately 700 bytes. The
|
||||
* reassembly buffer is of the same size as the uip_buf buffer
|
||||
* (configured by UIP_BUFSIZE).
|
||||
*
|
||||
* \note IP packet reassembly is not heavily tested.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_REASSEMBLY 0
|
||||
|
||||
/**
|
||||
* The maximum time an IP fragment should wait in the reassembly
|
||||
* buffer before it is dropped.
|
||||
*
|
||||
*/
|
||||
#define UIP_REASS_MAXAGE 40
|
||||
|
||||
/** @} */
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \name UDP configuration options
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Toggles wether UDP support should be compiled in or not.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifdef UIP_CONF_UDP
|
||||
#define UIP_UDP UIP_CONF_UDP
|
||||
#else /* UIP_CONF_UDP */
|
||||
#define UIP_UDP 0
|
||||
#endif /* UIP_CONF_UDP */
|
||||
|
||||
/**
|
||||
* Toggles if UDP checksums should be used or not.
|
||||
*
|
||||
* \note Support for UDP checksums is currently not included in uIP,
|
||||
* so this option has no function.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifdef UIP_CONF_UDP_CHECKSUMS
|
||||
#define UIP_UDP_CHECKSUMS UIP_CONF_UDP_CHECKSUMS
|
||||
#else
|
||||
#define UIP_UDP_CHECKSUMS 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The maximum amount of concurrent UDP connections.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifdef UIP_CONF_UDP_CONNS
|
||||
#define UIP_UDP_CONNS UIP_CONF_UDP_CONNS
|
||||
#else /* UIP_CONF_UDP_CONNS */
|
||||
#define UIP_UDP_CONNS 10
|
||||
#endif /* UIP_CONF_UDP_CONNS */
|
||||
|
||||
/**
|
||||
* The name of the function that should be called when UDP datagrams arrive.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
|
||||
|
||||
/** @} */
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \name TCP configuration options
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determines if support for opening connections from uIP should be
|
||||
* compiled in.
|
||||
*
|
||||
* If the applications that are running on top of uIP for this project
|
||||
* do not need to open outgoing TCP connections, this configration
|
||||
* option can be turned off to reduce the code size of uIP.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_ACTIVE_OPEN 1
|
||||
|
||||
/**
|
||||
* The maximum number of simultaneously open TCP connections.
|
||||
*
|
||||
* Since the TCP connections are statically allocated, turning this
|
||||
* configuration knob down results in less RAM used. Each TCP
|
||||
* connection requires approximatly 30 bytes of memory.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifndef UIP_CONF_MAX_CONNECTIONS
|
||||
#define UIP_CONNS 10
|
||||
#else /* UIP_CONF_MAX_CONNECTIONS */
|
||||
#define UIP_CONNS UIP_CONF_MAX_CONNECTIONS
|
||||
#endif /* UIP_CONF_MAX_CONNECTIONS */
|
||||
|
||||
|
||||
/**
|
||||
* The maximum number of simultaneously listening TCP ports.
|
||||
*
|
||||
* Each listening TCP port requires 2 bytes of memory.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifndef UIP_CONF_MAX_LISTENPORTS
|
||||
#define UIP_LISTENPORTS 20
|
||||
#else /* UIP_CONF_MAX_LISTENPORTS */
|
||||
#define UIP_LISTENPORTS UIP_CONF_MAX_LISTENPORTS
|
||||
#endif /* UIP_CONF_MAX_LISTENPORTS */
|
||||
|
||||
/**
|
||||
* Determines if support for TCP urgent data notification should be
|
||||
* compiled in.
|
||||
*
|
||||
* Urgent data (out-of-band data) is a rarely used TCP feature that
|
||||
* very seldom would be required.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_URGDATA 0
|
||||
|
||||
/**
|
||||
* The initial retransmission timeout counted in timer pulses.
|
||||
*
|
||||
* This should not be changed.
|
||||
*/
|
||||
#define UIP_RTO 3
|
||||
|
||||
/**
|
||||
* The maximum number of times a segment should be retransmitted
|
||||
* before the connection should be aborted.
|
||||
*
|
||||
* This should not be changed.
|
||||
*/
|
||||
#define UIP_MAXRTX 8
|
||||
|
||||
/**
|
||||
* The maximum number of times a SYN segment should be retransmitted
|
||||
* before a connection request should be deemed to have been
|
||||
* unsuccessful.
|
||||
*
|
||||
* This should not need to be changed.
|
||||
*/
|
||||
#define UIP_MAXSYNRTX 5
|
||||
|
||||
/**
|
||||
* The TCP maximum segment size.
|
||||
*
|
||||
* This is should not be to set to more than
|
||||
* UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
|
||||
*/
|
||||
#ifndef UIP_CONF_TCP_MSS
|
||||
#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
|
||||
#else
|
||||
#define UIP_TCP_MSS UIP_CONF_TCP_MSS
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The size of the advertised receiver's window.
|
||||
*
|
||||
* Should be set low (i.e., to the size of the uip_buf buffer) is the
|
||||
* application is slow to process incoming data, or high (32768 bytes)
|
||||
* if the application processes data quickly.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifndef UIP_CONF_RECEIVE_WINDOW
|
||||
#define UIP_RECEIVE_WINDOW UIP_TCP_MSS
|
||||
#else
|
||||
#define UIP_RECEIVE_WINDOW UIP_CONF_RECEIVE_WINDOW
|
||||
#endif
|
||||
|
||||
/**
|
||||
* How long a connection should stay in the TIME_WAIT state.
|
||||
*
|
||||
* This configiration option has no real implication, and it should be
|
||||
* left untouched.
|
||||
*/
|
||||
#define UIP_TIME_WAIT_TIMEOUT 120
|
||||
|
||||
|
||||
/** @} */
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \name ARP configuration options
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The size of the ARP table.
|
||||
*
|
||||
* This option should be set to a larger value if this uIP node will
|
||||
* have many connections from the local network.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifdef UIP_CONF_ARPTAB_SIZE
|
||||
#define UIP_ARPTAB_SIZE UIP_CONF_ARPTAB_SIZE
|
||||
#else
|
||||
#define UIP_ARPTAB_SIZE 8
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The maxium age of ARP table entries measured in 10ths of seconds.
|
||||
*
|
||||
* An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD
|
||||
* default).
|
||||
*/
|
||||
#define UIP_ARP_MAXAGE 120
|
||||
|
||||
/** @} */
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \name General configuration options
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The size of the uIP packet buffer.
|
||||
*
|
||||
* The uIP packet buffer should not be smaller than 60 bytes, and does
|
||||
* not need to be larger than 1500 bytes. Lower size results in lower
|
||||
* TCP throughput, larger size results in higher TCP throughput.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifndef UIP_CONF_BUFFER_SIZE
|
||||
#define UIP_BUFSIZE 400
|
||||
#else /* UIP_CONF_BUFFER_SIZE */
|
||||
#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE
|
||||
#endif /* UIP_CONF_BUFFER_SIZE */
|
||||
|
||||
|
||||
/**
|
||||
* Determines if statistics support should be compiled in.
|
||||
*
|
||||
* The statistics is useful for debugging and to show the user.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifndef UIP_CONF_STATISTICS
|
||||
#define UIP_STATISTICS 0
|
||||
#else /* UIP_CONF_STATISTICS */
|
||||
#define UIP_STATISTICS UIP_CONF_STATISTICS
|
||||
#endif /* UIP_CONF_STATISTICS */
|
||||
|
||||
/**
|
||||
* Determines if logging of certain events should be compiled in.
|
||||
*
|
||||
* This is useful mostly for debugging. The function uip_log()
|
||||
* must be implemented to suit the architecture of the project, if
|
||||
* logging is turned on.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifndef UIP_CONF_LOGGING
|
||||
#define UIP_LOGGING 0
|
||||
#else /* UIP_CONF_LOGGING */
|
||||
#define UIP_LOGGING UIP_CONF_LOGGING
|
||||
#endif /* UIP_CONF_LOGGING */
|
||||
|
||||
/**
|
||||
* Broadcast support.
|
||||
*
|
||||
* This flag configures IP broadcast support. This is useful only
|
||||
* together with UDP.
|
||||
*
|
||||
* \hideinitializer
|
||||
*
|
||||
*/
|
||||
#if UIP_UDP && UIP_CONF_BROADCAST
|
||||
#define UIP_BROADCAST UIP_CONF_BROADCAST
|
||||
#else /* UIP_CONF_BROADCAST */
|
||||
#define UIP_BROADCAST 0
|
||||
#endif /* UIP_CONF_BROADCAST */
|
||||
|
||||
/**
|
||||
* Print out a uIP log message.
|
||||
*
|
||||
* This function must be implemented by the module that uses uIP, and
|
||||
* is called by uIP whenever a log message is generated.
|
||||
*/
|
||||
void uip_log(char *msg);
|
||||
|
||||
/**
|
||||
* The link level header length.
|
||||
*
|
||||
* This is the offset into the uip_buf where the IP header can be
|
||||
* found. For Ethernet, this should be set to 14. For SLIP, this
|
||||
* should be set to 0.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifdef UIP_CONF_LLH_LEN
|
||||
#define UIP_LLH_LEN UIP_CONF_LLH_LEN
|
||||
#else /* UIP_CONF_LLH_LEN */
|
||||
#define UIP_LLH_LEN 14
|
||||
#endif /* UIP_CONF_LLH_LEN */
|
||||
|
||||
/** @} */
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \name CPU architecture configuration
|
||||
* @{
|
||||
*
|
||||
* The CPU architecture configuration is where the endianess of the
|
||||
* CPU on which uIP is to be run is specified. Most CPUs today are
|
||||
* little endian, and the most notable exception are the Motorolas
|
||||
* which are big endian. The BYTE_ORDER macro should be changed to
|
||||
* reflect the CPU architecture on which uIP is to be run.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The byte order of the CPU architecture on which uIP is to be run.
|
||||
*
|
||||
* This option can be either BIG_ENDIAN (Motorola byte order) or
|
||||
* LITTLE_ENDIAN (Intel byte order).
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#ifdef UIP_CONF_BYTE_ORDER
|
||||
#define UIP_BYTE_ORDER UIP_CONF_BYTE_ORDER
|
||||
#else /* UIP_CONF_BYTE_ORDER */
|
||||
#define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN
|
||||
#endif /* UIP_CONF_BYTE_ORDER */
|
||||
|
||||
/** @} */
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \name Appication specific configurations
|
||||
* @{
|
||||
*
|
||||
* An uIP application is implemented using a single application
|
||||
* function that is called by uIP whenever a TCP/IP event occurs. The
|
||||
* name of this function must be registered with uIP at compile time
|
||||
* using the UIP_APPCALL definition.
|
||||
*
|
||||
* uIP applications can store the application state within the
|
||||
* uip_conn structure by specifying the type of the application
|
||||
* structure by typedef:ing the type uip_tcp_appstate_t and uip_udp_appstate_t.
|
||||
*
|
||||
* The file containing the definitions must be included in the
|
||||
* uipopt.h file.
|
||||
*
|
||||
* The following example illustrates how this can look.
|
||||
\code
|
||||
|
||||
void httpd_appcall(void);
|
||||
#define UIP_APPCALL httpd_appcall
|
||||
|
||||
struct httpd_state {
|
||||
u8_t state;
|
||||
u16_t count;
|
||||
char *dataptr;
|
||||
char *script;
|
||||
};
|
||||
typedef struct httpd_state uip_tcp_appstate_t
|
||||
\endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var #define UIP_APPCALL
|
||||
*
|
||||
* The name of the application function that uIP should call in
|
||||
* response to TCP/IP events.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var typedef uip_tcp_appstate_t
|
||||
*
|
||||
* The type of the application state that is to be stored in the
|
||||
* uip_conn structure. This usually is typedef:ed to a struct holding
|
||||
* application state information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var typedef uip_udp_appstate_t
|
||||
*
|
||||
* The type of the application state that is to be stored in the
|
||||
* uip_conn structure. This usually is typedef:ed to a struct holding
|
||||
* application state information.
|
||||
*/
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
#endif /* __UIPOPT_H__ */
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#define htons(x) ( ((x)<<8) | (((x)>>8)&0xFF) )
|
||||
#define ntohs(x) htons(x)
|
||||
|
||||
#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \
|
||||
((x)<< 8 & 0x00FF0000UL) | \
|
||||
((x)>> 8 & 0x0000FF00UL) | \
|
||||
((x)>>24 & 0x000000FFUL) )
|
||||
#define ntohl(x) htonl(x)
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user