Page MenuHomePhabricator

No OneTemporary

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,32 @@
+PROJECT(BlindControl)
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+SET(CMAKE_SYSTEM_NAME Generic)
+SET(CMAKE_VERBOSE_MAKEFILE ON)
+
+SET(CMAKE_C_COMPILER avr-gcc)
+#SET(CMAKE_CXX_COMPILER avr-g++)
+
+SET(CSTANDARD "-std=gnu99")
+SET(CDEBUG "-gstabs")
+SET(CWARN "-Wall -Wstrict-prototypes")
+SET(CTUNING "-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums")
+SET(COPT "-Os")
+SET(CMCU "-mmcu=atmega2560")
+SET(CDEFS "-DF_CPU=16000000")
+
+SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-T ${CMAKE_CURRENT_SOURCE_DIR}/linker_script.x")
+
+
+SET(CFLAGS "${CMCU} ${CDEBUG} ${CDEFS} ${COPT} ${CWARN} ${CSTANDARD} ${CEXTRA}")
+#SET(CXXFLAGS "${CMCU} ${CDEFS} ${CINCS} ${COPT}")
+
+SET(CMAKE_C_FLAGS ${CFLAGS})
+#SET(CMAKE_CXX_FLAGS ${CXXFLAGS})
+
+ADD_EXECUTABLE(BlindControl main.c w5100.c ethernet.c spi.c)
+ADD_CUSTOM_COMMAND(TARGET BlindControl POST_BUILD COMMAND avr-objcopy -O ihex -R .eeprom ${CMAKE_CURRENT_BINARY_DIR}/BlindControl ${CMAKE_CURRENT_BINARY_DIR}/BlindControl.hex)
+
+ADD_CUSTOM_TARGET(upload ${CMAKE_COMMAND} ${PROJECT_SOURCE_DIR})
+ADD_CUSTOM_COMMAND(TARGET upload POST_BUILD COMMAND avrdude -V -c stk500v2 -p m2560 -b 115200 -P /dev/ttyACM0 -U flash:w:${CMAKE_CURRENT_BINARY_DIR}/BlindControl.hex)
+SET_TARGET_PROPERTIES(BlindControl PROPERTIES COMPILE_FLAGS -D__AVR_LIBC_DEPRECATED_ENABLE__)
diff --git a/ethernet.c b/ethernet.c
new file mode 100644
--- /dev/null
+++ b/ethernet.c
@@ -0,0 +1,200 @@
+/*
+ * Simple socket server for FreeRTOS based on the Arduino Ethernet Library
+ * (c) 2011 Andreas Boehler <andreas@aboehler.at>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ */
+
+
+#include "ethernet.h"
+#include "main.h"
+
+/**
+ * \file ethernet.c
+ * \brief Main ethernet source code
+ * This file contains the main ethernet handling code.
+ */
+
+/********************
+ * Global variables *
+ ********************/
+uint8_t eth_state[MAX_SOCK_NUM] = { 0, 0, 0, 0 }; ///< Ethernet states
+uint16_t eth_server_port[MAX_SOCK_NUM] = { 0, 0, 0, 0 }; ///< Ethernet ports
+
+uint8_t ethernet_init(uint8_t *mac, uint8_t *ip, uint8_t *gateway, uint8_t *subnet)
+{
+ w5100_init();
+ w5100_setMACAddress(mac);
+ w5100_setIPAddress(ip);
+ w5100_setGatewayIp(gateway);
+ w5100_setSubnetMask(subnet);
+ return TRUE;
+}
+
+uint8_t socket_server_init(uint16_t port)
+{
+ uint8_t sock;
+ for(sock = 0; sock < MAX_SOCK_NUM; sock++)
+ {
+ if(w5100_readSnSR(sock) == SNSR_CLOSED)
+ {
+ eth_server_port[sock] = port;
+ socket_server_create_socket(sock, SNMR_TCP, eth_server_port[sock], 0);
+ if(socket_server_listen(sock))
+ return sock+1;
+ else
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+uint8_t socket_server_socket_status(SOCKET s)
+{
+ return w5100_readSnSR(s);
+}
+
+uint8_t socket_server_create_socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag)
+{
+ if((protocol == SNMR_TCP) || (protocol == SNMR_UDP) || (protocol == SNMR_IPRAW) || (protocol == SNMR_MACRAW) || (protocol == SNMR_PPPOE))
+ {
+ socket_server_close_socket(s);
+ w5100_writeSnMR(s, protocol | flag);
+ if(port != 0)
+ w5100_writeSnPORT(s, port);
+ else
+ w5100_writeSnPORT(s, 80); // We hardcode a default port here
+ w5100_execCmdSn(s, Sock_OPEN);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+uint8_t socket_server_close_socket(SOCKET s)
+{
+ w5100_execCmdSn(s, Sock_CLOSE);
+ w5100_writeSnIR(s, 0xFF);
+ return TRUE;
+}
+
+uint8_t socket_server_listen(SOCKET s)
+{
+ if(w5100_readSnSR(s) != SNSR_INIT)
+ return FALSE;
+ else
+ w5100_execCmdSn(s, Sock_LISTEN);
+ return TRUE;
+}
+
+uint8_t socket_server_data_available(SOCKET s)
+{
+ //uint8_t stat = socket_server_socket_status(s);
+ //if((stat == SNSR_ESTABLISHED) || (stat == SNSR_CLOSE_WAIT))
+ return w5100_getRXReceivedSize(s);
+ //else
+ // return FALSE;
+}
+
+uint8_t socket_server_socket_connected(SOCKET s)
+{
+ uint8_t stat = socket_server_socket_status(s);
+ if((stat == SNSR_ESTABLISHED))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+uint8_t socket_server_socket_closed(SOCKET s)
+{
+ uint8_t stat = socket_server_socket_status(s);
+ if((stat == SNSR_CLOSE_WAIT))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+uint8_t socket_server_handle_interrupt(void)
+{
+ uint8_t ir = w5100_readIR();
+ uint8_t sock = 0;
+ uint8_t sr = 0;
+ uint8_t i;
+
+ for(i=0; i<MAX_SOCK_NUM; i++)
+ {
+ if(ir & (1<<i))
+ {
+ sr = w5100_readSnIR(i);
+ sock = i;
+ }
+ }
+ if(sock != MAX_SOCK_NUM)
+ {
+ w5100_writeSnIR(sock, sr);
+ return sock;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+uint16_t socket_server_write(SOCKET s, uint8_t *buffer, size_t size)
+{
+ uint16_t ret = 0;
+ uint16_t freesize = 0;
+ if(socket_server_socket_status(s) == SNSR_ESTABLISHED)
+ {
+ if(size > SSIZE)
+ ret = SSIZE;
+ else
+ ret = size;
+ freesize = w5100_getTXFreeSize(s);
+ if(freesize < ret)
+ ret = 0;
+ /*
+ do
+ {
+ freesize = w5100_getTXFreeSize(s);
+
+ stat = w5100_readSnSR(s);
+ if((stat != SNSR_ESTABLISHED) && (stat != SNSR_CLOSE_WAIT))
+ {
+ ret = 0;
+ break;
+ }
+ }
+ while(freesize < ret);
+ */
+ w5100_send_data_processing(s, (uint8_t *) buffer, ret);
+ w5100_execCmdSn(s, Sock_SEND);
+
+ while((w5100_readSnIR(s) & SNIR_SEND_OK) != SNIR_SEND_OK)
+ {
+ if(w5100_readSnSR(s) == SNSR_CLOSED)
+ {
+ socket_server_close_socket(s);
+ return FALSE;
+ }
+ }
+ w5100_writeSnIR(s, SNIR_SEND_OK);
+ return ret;
+ }
+ return FALSE;
+}
+
+uint16_t socket_server_receive(SOCKET s, uint8_t *buf, uint16_t len)
+{
+ uint16_t ret = FALSE;
+ if(len>0)
+ {
+ w5100_recv_data_processing(s, buf, len, 0);
+ w5100_execCmdSn(s, Sock_RECV);
+ ret = len;
+ }
+ return ret;
+}
diff --git a/ethernet.h b/ethernet.h
new file mode 100644
--- /dev/null
+++ b/ethernet.h
@@ -0,0 +1,195 @@
+/*
+ * Simple socket server for FreeRTOS based on the Arduino Ethernet Library
+ * (c) 2011 Andreas Boehler <andreas@aboehler.at>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ */
+
+/**
+ * \file ethernet.h
+ * Simple socket server for FreeRTOS based on the Arduino Ethernet Library for the
+ * W5100 Ethernet controller.
+ */
+
+#ifndef ETHERNET_H
+#define ETHERNET_H
+
+#include "w5100.h"
+
+/**
+ * ethernet.h
+ *
+ * <pre>ethernet_init(uint8_t *mac, uint8_t *ip, uint8_t *gateway, uint8_t *subnet)</pre>
+ *
+ * <i>Function</i> that initializes the ethernet controller with the given parameters.
+ *
+ * @param mac Pointer to a byte holding the mac address of the ethernet controller
+ * @param ip Pointer to an array of bytes holding the IP address for the ethernet controller
+ * @param gateway Pointer to an array of bytes holding the Gateway IP Address
+ * @param subnet Pointer to an array of bytes holding the Subnet address
+ * @return TRUE on success, FALSE on failure.
+ * \ingroup Ethernet
+ */
+
+uint8_t ethernet_init(uint8_t *mac, uint8_t *ip, uint8_t *gateway, uint8_t *subnet);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_init(uint16_t port)</pre>
+ *
+ * <i>Function</i> that initializes a new socket server on the given port.
+ *
+ * @param port Integer that specifies the Port Number to create
+ * @return Socket Number +1 on success, 0 on failure.
+ * \ingroup Ethernet
+ */
+uint8_t socket_server_init(uint16_t port);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_create_socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag)</pre>
+ *
+ * <i>Function</i> used e.g. by socker_server_init that creates a new socket server on the
+ * specified socket number using given protocol, port and flags.
+ * If the socket is already opened, it is automatically closed.
+ *
+ * @param s The socket number to create (0-3)
+ * @param protocol The protocol the socket should use
+ * @param port The port the new socket should listen one
+ * @param flag Additional flags to use
+ * @return TRUE on success, FALSE on failure.
+ * \ingroup Ethernet
+ */
+uint8_t socket_server_create_socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_close_socket(SOCKET s)</pre>
+ *
+ * <i>Function</i> that closes a previously opened socket.
+ *
+ * @param s The socket to close
+ * @return TRUE on success, FALSE on failure.
+ * \ingroup Ethernet
+ */
+uint8_t socket_server_close_socket(SOCKET s);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_listen(SOCKET s)</pre>
+ *
+ * <i>Function</i> to start listening on the given socket.
+ *
+ * @param s The socket number to start listening on
+ * @return TRUE on success, FALSE on failure.
+ * \ingroup Ethernet
+ */
+uint8_t socket_server_listen(SOCKET s);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_socket_status(SOCKET s)</pre>
+ *
+ * <i>Function</i> that checks the status of a given socket.
+ *
+ * @param s The socket number to check.
+ * @return The status of the socket
+ * \ingroup Ethernet
+ */
+uint8_t socket_server_socket_status(SOCKET s);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_socket_connected(SOCKET s)</pre>
+ *
+ * <i>Function</i> that checks whether a socket is connected or not.
+ *
+ * @param s The socket number to check
+ * @return TRUE if a node is connected, FALSE if nothing is connected to the socket.
+ * \ingroup Ethernet
+ */
+uint8_t socket_server_socket_connected(SOCKET s);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_socket_closed(SOCKET s)</pre>
+ *
+ * <i>Function</i> that checks whether a given socket is closed or no.
+ *
+ * @param s The socket number to check
+ * @return TRUE if the socket's status is closed, otherwise FALSE.
+ * \ingroup Ethernet
+ */
+uint8_t socket_server_socket_closed(SOCKET s);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_data_available(SOCKET s)</pre>
+ *
+ * <i>Function</i> that checks if and how many data is available on a given socket.
+ *
+ * @param s The socket number to check
+ * @return FALSE if no data is available, otherwise the number of bytes that have been received.
+ * \ingroup Ethernet
+ */
+uint8_t socket_server_data_available(SOCKET s);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_handle_interrupt(void)</pre>
+ *
+ * <i>Function</i> that handles the W5100 interrupt. It reads the interrupt register,
+ * extracts the socket number the interrupt happened on and clears the interrupt register
+ * (by mirroring the register values back).
+ *
+ * @return The socket number if successful, otherwise FALSE
+ * \warning If the socket number is 0, it might be misinterpreted as FALSE!
+ * \ingroup Ethernet
+ */
+uint8_t socket_server_handle_interrupt(void);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_write(SOCKET s, uint8_t *buffer, size_t size)</pre>
+ *
+ * <i>Function</i> that writes a character array, buffer, of length size to a given socket.
+ *
+ * @param s The socket to write to
+ * @param buffer Pointer to an array of uint8_t that holds the data
+ * @param size The length of the buffer array
+ * @return TRUE on success, FALSE on failure.
+ * \ingroup Ethernet
+ */
+uint16_t socket_server_write(SOCKET s, uint8_t *buffer, size_t size);
+
+/**
+ * ethernet.h
+ *
+ * <pre>socket_server_receive(SOCKET s, uint8_t *buf, uint16_t len)</pre>
+ *
+ * <i>Function</i> that receives a given number of bytes from a given socket to the
+ * buffer specified.
+ *
+ * @param s The socket to receive from
+ * @param buf Pointer to a character Array to store the bytes to
+ * @param len Maximum number of characters to receive, usually retrieved by socket_server_data_available
+ * \ingroup Ethernet
+ */
+uint16_t socket_server_receive(SOCKET s, uint8_t *buf, uint16_t len);
+
+
+
+#endif //ETHERNET_H
diff --git a/iomacro.h b/iomacro.h
new file mode 100644
--- /dev/null
+++ b/iomacro.h
@@ -0,0 +1,53 @@
+#ifndef IOMACRO_H
+#define IOMACRO_H
+
+/**
+ * \file iomacro.h
+ * \brief I/O Macro Functions
+ * Definitions of various macro functions used in various parts of the system,
+ * especially concerning I/O ports.
+ */
+
+/** \def RESET(x)
+ * A macro that resets the I/O port given in \a x.
+ */
+#define RESET(x) _XRS(x)
+/** \def SET(x)
+ * A macro that sets the I/O port given in \a x.
+ */
+#define SET(x) _XS(x)
+/** \def TOGGLE(X)
+ * A macro that toggles the state of the I/O port given in \a x.
+ */
+#define TOGGLE(x) _XT(x)
+/** \def SET_OUTPUT(X)
+ * A macro that sets the direction of the I/O port given in \a x to output.
+ */
+#define SET_OUTPUT(x) _XSO(x)
+/** \def SET_INPUT(x)
+ * A macro that sets the direction of the I/O port given in \a x to input.
+ */
+#define SET_INPUT(x) _XSI(x)
+/** \def IS_SET(x)
+ * A macro that checks whether the I/O port given in \a x is set or not.
+ */
+#define IS_SET(x) _XR(x)
+
+#define PORT(x) _port2(x)
+#define DDR(x) _ddr2(x)
+#define PIN(x) _pin2(x)
+
+#define _XRS(x,y) PORT(x) &= ~(1<<y)
+#define _XS(x,y) PORT(x) |= (1<<y)
+#define _XT(x,y) PORT(x) ^= (1<<y)
+
+#define _XSO(x,y) DDR(x) |= (1<<y)
+#define _XSI(x,y) DDR(x) &= ~(1<<y)
+
+#define _XR(x,y) ((PIN(x) & (1<<y)) != 0)
+
+#define _port2(x) PORT ## x
+#define _ddr2(x) DDR ## x
+#define _pin2(x) PIN ## x
+
+#endif // IOMACRO_H
diff --git a/linker_script.x b/linker_script.x
new file mode 100644
--- /dev/null
+++ b/linker_script.x
@@ -0,0 +1,223 @@
+/* Default linker script, for normal executables */
+OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
+OUTPUT_ARCH(avr:6)
+MEMORY
+{
+ text (rx) : ORIGIN = 0, LENGTH = 1024K
+ data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0
+ eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
+}
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text :
+ {
+ *(.rel.text)
+ *(.rel.text.*)
+ *(.rel.gnu.linkonce.t*)
+ }
+ .rela.text :
+ {
+ *(.rela.text)
+ *(.rela.text.*)
+ *(.rela.gnu.linkonce.t*)
+ }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.rodata :
+ {
+ *(.rel.rodata)
+ *(.rel.rodata.*)
+ *(.rel.gnu.linkonce.r*)
+ }
+ .rela.rodata :
+ {
+ *(.rela.rodata)
+ *(.rela.rodata.*)
+ *(.rela.gnu.linkonce.r*)
+ }
+ .rel.data :
+ {
+ *(.rel.data)
+ *(.rel.data.*)
+ *(.rel.gnu.linkonce.d*)
+ }
+ .rela.data :
+ {
+ *(.rela.data)
+ *(.rela.data.*)
+ *(.rela.gnu.linkonce.d*)
+ }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ /* Internal text space or external memory. */
+ .text :
+ {
+ *(.vectors)
+ KEEP(*(.vectors))
+ *(.length)
+ /* KEEP(*(.length)) - don't need to keep if it isn't defined */
+ /* For data that needs to reside in the lower 64k of progmem. */
+ *(.progmem.gcc*)
+ *(.progmem*)
+ . = ALIGN(2);
+ __trampolines_start = . ;
+ /* The jump trampolines for the 16-bit limited relocs will reside here. */
+ *(.trampolines)
+ *(.trampolines*)
+ __trampolines_end = . ;
+ /* For future tablejump instruction arrays for 3 byte pc devices.
+ We don't relax jump/call instructions within these sections. */
+ *(.jumptables)
+ *(.jumptables*)
+ /* For code that needs to reside in the lower 128k progmem. */
+ *(.lowtext)
+ *(.lowtext*)
+ __ctors_start = . ;
+ *(.ctors)
+ __ctors_end = . ;
+ __dtors_start = . ;
+ *(.dtors)
+ __dtors_end = . ;
+ KEEP(SORT(*)(.ctors))
+ KEEP(SORT(*)(.dtors))
+ /* From this point on, we don't bother about wether the insns are
+ below or above the 16 bits boundary. */
+ *(.init0) /* Start here after reset. */
+ KEEP (*(.init0))
+ *(.init1)
+ KEEP (*(.init1))
+ *(.init2) /* Clear __zero_reg__, set up stack pointer. */
+ KEEP (*(.init2))
+ *(.init3)
+ KEEP (*(.init3))
+ *(.init4) /* Initialize data and BSS. */
+ KEEP (*(.init4))
+ *(.init5)
+ KEEP (*(.init5))
+ *(.init6) /* C++ constructors. */
+ KEEP (*(.init6))
+ *(.init7)
+ KEEP (*(.init7))
+ *(.init8)
+ KEEP (*(.init8))
+ *(.init9) /* Call main(). */
+ KEEP (*(.init9))
+ /* Interrupt Service Routine code needs to be in the lower 128K program */
+ *(.isr)
+ KEEP(*(.isr))
+ /* Any code that is the target of a function pointer must also
+ reside in lower memory */
+ *(.fptr_target)
+ KEEP(*(.fptr_target))
+ /* An RTOS task should also be in low mmeory. */
+ *(.task)
+ KEEP(*(.task))
+ /* Main code starts here - this code can oveflow into the upper 128K program */
+ *(.text)
+ . = ALIGN(2);
+ *(.text.*)
+ . = ALIGN(2);
+ *(.fini9) /* _exit() starts here. */
+ KEEP (*(.fini9))
+ *(.fini8)
+ KEEP (*(.fini8))
+ *(.fini7)
+ KEEP (*(.fini7))
+ *(.fini6) /* C++ destructors. */
+ KEEP (*(.fini6))
+ *(.fini5)
+ KEEP (*(.fini5))
+ *(.fini4)
+ KEEP (*(.fini4))
+ *(.fini3)
+ KEEP (*(.fini3))
+ *(.fini2)
+ KEEP (*(.fini2))
+ *(.fini1)
+ KEEP (*(.fini1))
+ *(.fini0) /* Infinite loop after program termination. */
+ KEEP (*(.fini0))
+ _etext = . ;
+ } > text
+ .data : AT (ADDR (.text) + SIZEOF (.text))
+ {
+ PROVIDE (__data_start = .) ;
+ *(.data)
+ *(.data*)
+ *(.rodata) /* We need to include .rodata here if gcc is used */
+ *(.rodata*) /* with -fdata-sections. */
+ *(.gnu.linkonce.d*)
+ . = ALIGN(2);
+ _edata = . ;
+ PROVIDE (__data_end = .) ;
+ } > data
+ .bss SIZEOF(.data) + ADDR(.data) :
+ {
+ PROVIDE (__bss_start = .) ;
+ *(.bss)
+ *(.bss*)
+ *(COMMON)
+ PROVIDE (__bss_end = .) ;
+ } > data
+ __data_load_start = LOADADDR(.data);
+ __data_load_end = __data_load_start + SIZEOF(.data);
+ /* Global data not cleared after reset. */
+ .noinit SIZEOF(.bss) + ADDR(.bss) :
+ {
+ PROVIDE (__noinit_start = .) ;
+ *(.noinit*)
+ PROVIDE (__noinit_end = .) ;
+ _end = . ;
+ PROVIDE (__heap_start = .) ;
+ } > data
+ .eeprom :
+ {
+ *(.eeprom*)
+ __eeprom_end = . ;
+ } > eeprom
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+}
diff --git a/main.c b/main.c
new file mode 100644
--- /dev/null
+++ b/main.c
@@ -0,0 +1,446 @@
+/*
+ * This is COSMICrtOS based on FreeRTOS port to ATmega2560.
+ * (c) 2011 Andreas Boehler <andreas@aboehler.at>
+ *
+ * ATTENTION: Software licenses apply! GPL is probably incompatible
+ * with our NDA! Can we link to a binary blob instead?
+ */
+
+// FIXME: Get rid of FreeRTOS
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <avr/eeprom.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+
+#include "iomacro.h"
+#include "main.h"
+
+#include "ethernet.h"
+
+volatile int gEthFired = FALSE;
+SOCKET gSock = MAX_SOCK_NUM;
+
+
+#define TOGGLE_DELAY 300
+#define INCR_DELAY 200
+#define CMD_STOP 5
+#define CMD_SELECT 6
+#define CMD_UP 7
+#define CMD_DOWN 8
+
+#define AI_PIN0 F,0
+#define AI_PIN1 F,1
+#define AI_PIN2 F,2
+#define AI_PIN3 F,3
+
+#define DO_PIN_STOP E,3
+#define DO_PIN_SELECT H,3
+#define DO_PIN_UP H,4
+#define DO_PIN_DOWN H,5
+
+/***************************************
+ * Helper function to setup interrupts *
+ ***************************************/
+void setupExternalInterrupts(void)
+{
+ EICRB |= (1 << ISC41); // Enable falling edge interrupt
+ EIMSK |= (1 << INT4); // enable external interrupt 4
+}
+
+/****************************************************
+ * Setup the interrupt handler for ethernet traffic *
+ ****************************************************/
+ISR(INT4_vect)
+{
+ gEthFired = TRUE;
+}
+
+/************************************************
+ * Setup and initialize the ethernet controller *
+ ************************************************/
+void setupEthernet(void)
+{
+ uint8_t mac[] = { 0x00, 0x01, 0x02, 0x0D, 0x74, 0x47 };
+ uint8_t ip[] = { 192, 168, 1, 20 };
+ uint8_t gateway[] = { 192, 168, 1, 1 };
+ uint8_t subnet[] = { 255, 255, 255, 0 };
+
+ if(ethernet_init(mac, ip, gateway, subnet))
+ {
+ if((gSock = socket_server_init(SOCK_PORT)))
+ {
+ gSock -= 1;
+ }
+ }
+}
+
+
+/*****************
+ * Main function *
+ *****************/
+int main( void )
+{
+
+ // Setup registers for input and output
+ setupIOPorts();
+ setupExternalInterrupts();
+ if(spi_init())
+ setupEthernet();
+ sei();
+
+/*
+ selectBlindChannel(5);
+ _delay_ms(5000);
+ blindUp(1);
+ blindDown(1);
+ blindDown(2);
+ blindDown(3);
+ blindDown(4);
+ blindDown(5);
+*/
+
+ uint8_t new_connect[MAX_SOCK_NUM];
+ uint8_t connected[MAX_SOCK_NUM];
+ uint8_t i;
+ uint16_t len;
+ SOCKET sock;
+
+ unsigned char clientline[BUF_SIZE];
+
+ for(i=0; i < MAX_SOCK_NUM; i++)
+ {
+ new_connect[i] = TRUE;
+ connected[i] = FALSE;
+ }
+
+ for( ;; )
+ {
+ if(gEthFired)
+ {
+ gEthFired = FALSE;
+ sock = socket_server_handle_interrupt();
+ connected[sock] = socket_server_socket_connected(sock);
+ if(connected[sock])
+ {
+ if(new_connect[sock])
+ {
+ socket_server_write(sock, (unsigned char*)"BlindControl ready\n", (uint16_t)19);
+ new_connect[sock] = FALSE;
+ }
+ }
+ else
+ {
+ if (!new_connect[sock])
+ new_connect[sock] = TRUE;
+ if(socket_server_socket_closed(sock))
+ {
+ socket_server_close_socket(gSock);
+ setupEthernet();
+ }
+
+ }
+ if(connected[sock] && (len = socket_server_data_available(sock)))
+ {
+ if(len > BUF_SIZE)
+ len = BUF_SIZE;
+ socket_server_receive(sock, clientline, len);
+ if(!handle_req((signed char*)clientline))
+ {
+ socket_server_close_socket(gSock);
+ new_connect[sock] = TRUE;
+ setupEthernet();
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int handle_req(signed char *clientline)
+{
+ int blindNum;
+ char helpStr[] = "Available Commands: SelectBlind N, BlindUp[ N], BlindDown[ N], "
+ "BlindStop[ N], BlindIncr[ N], BlindDecr[ N], AllUp, AllDown, help, quit\n\n";
+ if(strncmp(clientline, "SelectBlind ", 12) == 0)
+ {
+ blindNum = atoi(&clientline[12]);
+ if((blindNum > 5) || (blindNum < 0))
+ {
+ socket_server_write(gSock, (unsigned char *)"ERR\n", 4);
+ }
+ else
+ {
+ selectBlindChannel(blindNum);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ }
+ else if(strncmp(clientline, "BlindUp ", 8) == 0)
+ {
+ blindNum = atoi(&clientline[8]);
+ if((blindNum > 5) || (blindNum < 0))
+ {
+ socket_server_write(gSock, (unsigned char *)"ERR\n", 4);
+ }
+ else
+ {
+ blindUp(blindNum);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ }
+ else if(strncmp(clientline, "BlindDown ", 10) == 0)
+ {
+ blindNum = atoi(&clientline[10]);
+ if((blindNum > 5) || (blindNum < 0))
+ {
+ socket_server_write(gSock, (unsigned char *)"ERR\n", 4);
+ }
+ else
+ {
+ blindDown(blindNum);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ }
+ else if(strncmp(clientline, "BlindStop ", 10) == 0)
+ {
+ blindNum = atoi(&clientline[10]);
+ if((blindNum > 5) || (blindNum < 0))
+ {
+ socket_server_write(gSock, (unsigned char *)"ERR\n", 4);
+ }
+ else
+ {
+ blindStop(blindNum);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ }
+ else if(strncmp(clientline, "BlindIncr ", 10) == 0)
+ {
+ blindNum = atoi(&clientline[10]);
+ if((blindNum > 5) || (blindNum < 0))
+ {
+ socket_server_write(gSock, (unsigned char *)"ERR\n", 4);
+ }
+ else
+ {
+ selectBlindChannel(blindNum);
+ sendCommand(CMD_UP);
+ _delay_ms(INCR_DELAY);
+ sendCommand(CMD_STOP);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ }
+ else if(strncmp(clientline, "BlindDecr ", 10) == 0)
+ {
+ blindNum = atoi(&clientline[10]);
+ if((blindNum > 5) || (blindNum < 0))
+ {
+ socket_server_write(gSock, (unsigned char *)"ERR\n", 4);
+ }
+ else
+ {
+ selectBlindChannel(blindNum);
+ sendCommand(CMD_DOWN);
+ _delay_ms(INCR_DELAY);
+ sendCommand(CMD_STOP); socket_server_write(gSock, "OK\n", 3);
+ }
+ }
+ else if(strncmp(clientline, "BlindUp", 7) == 0)
+ {
+ sendCommand(CMD_UP);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ else if(strncmp(clientline, "BlindDown", 9) == 0)
+ {
+ sendCommand(CMD_DOWN);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ else if(strncmp(clientline, "BlindStop", 9) == 0)
+ {
+ sendCommand(CMD_STOP);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ else if(strncmp(clientline, "BlindIncr", 9) == 0)
+ {
+ sendCommand(CMD_UP);
+ _delay_ms(INCR_DELAY);
+ sendCommand(CMD_STOP);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ else if(strncmp(clientline, "BlindDecr", 9) == 0)
+ {
+ sendCommand(CMD_DOWN);
+ _delay_ms(INCR_DELAY);
+ sendCommand(CMD_STOP);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ else if(strncmp(clientline, "AllUp", 5) == 0)
+ {
+ for(blindNum=1; blindNum<6; blindNum++)
+ {
+ blindUp(blindNum);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ }
+ else if(strncmp(clientline, "AllDown", 7) == 0)
+ {
+ for(blindNum=1; blindNum<6; blindNum++)
+ {
+ blindDown(blindNum);
+ socket_server_write(gSock, "OK\n", 3);
+ }
+ }
+ else if(strncmp(clientline, "help", 4) == 0)
+ {
+ socket_server_write(gSock, helpStr, strlen(helpStr));
+ }
+ else if(strncmp(clientline, "quit", 4) == 0)
+ {
+ return FALSE;
+ }
+ else
+ {
+ socket_server_write(gSock, "ERR\n", 4);
+ }
+ return TRUE;
+}
+
+int getCurrentBlindChannel(void)
+{
+ int currentChannel = 0;
+ int readValues;
+ readValues = readFromADC();
+ if(readValues == 0)
+ {
+ sendCommand(CMD_SELECT);
+ readValues = readFromADC();
+ }
+ switch(readValues)
+ {
+ case 1:
+ currentChannel = 1;
+ break;
+ case 2:
+ currentChannel = 2;
+ break;
+ case 4:
+ currentChannel = 3;
+ break;
+ case 8:
+ currentChannel = 4;
+ break;
+ case 15:
+ currentChannel = 5;
+ break;
+ default:
+ currentChannel = 0;
+ }
+ return currentChannel;
+}
+
+int readFromADC(void)
+{
+ int j;
+ int channel = 0;
+ for(j=0;j<200;j++)
+ {
+ if(!IS_SET(AI_PIN0))
+ channel |= 0x01;
+ if(!IS_SET(AI_PIN1))
+ channel |= 0x02;
+ if(!IS_SET(AI_PIN2))
+ channel |= 0x04;
+ if(!IS_SET(AI_PIN3))
+ channel |= 0x08;
+ }
+ return channel;
+}
+
+int selectBlindChannel(int telisChannel)
+{
+ while(getCurrentBlindChannel() != telisChannel)
+ sendCommand(CMD_SELECT);
+ return TRUE;
+}
+
+int blindUp(int telisChannel)
+{
+ selectBlindChannel(telisChannel);
+ sendCommand(CMD_UP);
+ return TRUE;
+}
+
+int blindDown(int telisChannel)
+{
+ selectBlindChannel(telisChannel);
+ sendCommand(CMD_DOWN);
+ return TRUE;
+}
+
+int blindStop(int telisChannel)
+{
+ selectBlindChannel(telisChannel);
+ sendCommand(CMD_STOP);
+ return TRUE;
+}
+
+int sendCommand(int digitalChannel)
+{
+ switch(digitalChannel)
+ {
+ case CMD_STOP:
+ SET(DO_PIN_STOP);
+ _delay_ms(TOGGLE_DELAY);
+ RESET(DO_PIN_STOP);
+ break;
+ case CMD_SELECT:
+ SET(DO_PIN_SELECT);
+ _delay_ms(TOGGLE_DELAY);
+ RESET(DO_PIN_SELECT);
+ break;
+ case CMD_UP:
+ SET(DO_PIN_UP);
+ _delay_ms(TOGGLE_DELAY);
+ RESET(DO_PIN_UP);
+ break;
+ case CMD_DOWN:
+ SET(DO_PIN_DOWN);
+ _delay_ms(TOGGLE_DELAY);
+ RESET(DO_PIN_DOWN);
+ break;
+ }
+ _delay_ms(TOGGLE_DELAY);
+
+ return TRUE;
+}
+
+
+/****************************************
+ * Setup all required I/O Ports for use *
+ ****************************************/
+uint8_t setupIOPorts( void )
+{
+
+ SET_INPUT(AI_PIN0);
+ SET_INPUT(AI_PIN1);
+ SET_INPUT(AI_PIN2);
+ SET_INPUT(AI_PIN3);
+
+ RESET(DO_PIN_STOP);
+ RESET(DO_PIN_SELECT);
+ RESET(DO_PIN_UP);
+ RESET(DO_PIN_DOWN);
+
+ SET_OUTPUT(DO_PIN_STOP);
+ SET_OUTPUT(DO_PIN_SELECT);
+ SET_OUTPUT(DO_PIN_UP);
+ SET_OUTPUT(DO_PIN_DOWN);
+
+
+ return TRUE;
+}
+
+//EOF
diff --git a/main.h b/main.h
new file mode 100644
--- /dev/null
+++ b/main.h
@@ -0,0 +1,31 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#define TRUE 1
+#define FALSE 0
+
+#define P_MOSI B,2
+#define P_MISO B,3
+#define P_SCK B,1
+#define P_SS B,0
+
+#define BUF_SIZE 255
+
+#define W5100_CS B,4
+#define W5100_INT E,4 // #D,2
+
+#define SOCK_PORT 63543
+
+int readADC(int digitalChannel);
+int getCurrentBlindChannel(void);
+int selectBlindChannel(int telisChannel);
+int blindUp(int telisChannel);
+int blindDown(int telisChannel);
+int blindStop(int telisChannel);
+int sendCommand(int digitalChannel);
+int readFromADC(void);
+int main(void);
+void setupExternalInterrupts(void);
+int handle_req(signed char* clientline);
+uint8_t setupIOPorts(void);
+#endif
diff --git a/spi.c b/spi.c
new file mode 100644
--- /dev/null
+++ b/spi.c
@@ -0,0 +1,43 @@
+/*
+ * Simple SPI interface for RTOS based on the Arduino SPI library and the
+ * MCP2515 CAN interface.
+ * (c) 2011 Andreas Boehler <andreas@aboehler.at>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ */
+
+#include <avr/io.h>
+#include "spi.h"
+#include "main.h"
+
+uint8_t spi_putc( uint8_t data )
+{
+ // put byte in send-buffer
+ SPDR = data;
+
+ // wait until byte was sent
+ while( !( SPSR & (1<<SPIF) ) )
+ ;
+
+ return SPDR;
+}
+
+uint8_t spi_init(void)
+{
+ RESET(P_SCK);
+ RESET(P_MOSI);
+ RESET(P_MISO);
+
+ SET_OUTPUT(P_SCK);
+ SET_OUTPUT(P_MOSI);
+ SET_INPUT(P_MISO);
+ SET_OUTPUT(P_SS);
+
+ // active SPI master interface, this gives us fOSC/2
+ SPCR = (1<<SPE)|(1<<MSTR) | (0<<SPR1)|(1<<SPR1);
+ SPSR = (1<<SPI2X);
+ return TRUE;
+}
diff --git a/spi.h b/spi.h
new file mode 100644
--- /dev/null
+++ b/spi.h
@@ -0,0 +1,47 @@
+/*
+ * Simple SPI interface for RTOS based on the Arduino SPI library and the
+ * MCP2515 CAN interface.
+ * (c) 2011 Andreas Boehler <andreas@aboehler.at>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ */
+#ifndef SPI_H
+#define SPI_H
+
+#include <inttypes.h>
+#include "iomacro.h"
+
+/**
+ * \file spi.h
+ * \brief SPI function definitions
+ * This header contains the SPI related functions used by the various drivers.
+ */
+
+/**
+ * spi.h
+ *
+ * <pre>spi_putc(uint8_t data)</pre>
+ *
+ * <i>Function</i> that puts a single character to the SPI interface.
+ *
+ * @param data The byte to put to the SPI interface
+ * @return Mirrors back the data sent.
+ * \ingroup SPI
+ */
+uint8_t spi_putc( uint8_t data );
+
+/**
+ * spi.h
+ *
+ * <pre>spi_init(void)</pre>
+ *
+ * <i>Function</i> that initializes the SPI interface.
+ *
+ * \ingroup SPI
+ */
+uint8_t spi_init(void);
+
+#endif // SPI_H
diff --git a/w5100.c b/w5100.c
new file mode 100644
--- /dev/null
+++ b/w5100.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
+ * Ported to plain C and FreeRTOS by Andreas Boehler <andreas@aboehler.at>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <avr/interrupt.h>
+#include <avr/delay.h>
+
+#include "w5100.h"
+#include "main.h"
+
+#define TX_RX_MAX_BUF_SIZE 2048
+#define TX_BUF 0x1100
+#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
+
+#define TXBUF_BASE 0x4000
+#define RXBUF_BASE 0x6000
+
+uint8_t w5100_init(void)
+{
+ _delay_ms(300);
+
+ SET_INPUT(W5100_INT);
+ SET(W5100_INT);
+
+ SET_OUTPUT(W5100_CS);
+ w5100_writeMR(1<<RST);
+ w5100_writeTMSR(0x55);
+ w5100_writeRMSR(0x55);
+ w5100_writeIMR((1<<IM_IR3)|(1<<IM_IR2)|(1<<IM_IR1)|(1<<IM_IR0));
+
+ for (int i=0; i<MAX_SOCK_NUM; i++) {
+ SBASE[i] = TXBUF_BASE + SSIZE * i;
+ RBASE[i] = RXBUF_BASE + RSIZE * i;
+ }
+ return TRUE;
+}
+
+uint16_t w5100_getTXFreeSize(SOCKET s)
+{
+ uint16_t val=0, val1=0;
+ do {
+ val1 = w5100_readSnTX_FSR(s);
+ if (val1 != 0)
+ val = w5100_readSnTX_FSR(s);
+ }
+ while (val != val1);
+ return val;
+}
+
+uint16_t w5100_getRXReceivedSize(SOCKET s)
+{
+ uint16_t val=0,val1=0;
+ do {
+ val1 = w5100_readSnRX_RSR(s);
+ if (val1 != 0)
+ val = w5100_readSnRX_RSR(s);
+ }
+ while (val != val1);
+ return val;
+}
+
+
+void w5100_send_data_processing(SOCKET s, uint8_t *data, uint16_t len)
+{
+ uint16_t ptr = w5100_readSnTX_WR(s);
+
+ uint16_t offset = ptr & SMASK;
+ uint16_t dstAddr = offset + SBASE[s];
+
+ if (offset + len > SSIZE)
+ {
+ // Wrap around circular buffer
+ uint16_t size = SSIZE - offset;
+ w5100_write_16(dstAddr, data, size);
+ w5100_write_16(SBASE[s], data + size, len - size);
+ }
+ else {
+ w5100_write_16(dstAddr, data, len);
+ }
+
+ ptr += len;
+ w5100_writeSnTX_WR(s, ptr);
+}
+
+
+void w5100_recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
+{
+ uint16_t ptr;
+ ptr = w5100_readSnRX_RD(s);
+ w5100_read_data(s, (uint8_t *)ptr, data, len);
+ if (!peek)
+ {
+ ptr += len;
+ w5100_writeSnRX_RD(s, ptr);
+ }
+}
+
+void w5100_read_data(SOCKET s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len)
+{
+ uint16_t size;
+ uint16_t src_mask;
+ uint16_t src_ptr;
+
+ src_mask = (uint16_t)src & RMASK;
+ src_ptr = RBASE[s] + src_mask;
+
+ if( (src_mask + len) > RSIZE )
+ {
+ size = RSIZE - src_mask;
+ w5100_read_16(src_ptr, (uint8_t *)dst, size);
+ dst += size;
+ w5100_read_16(RBASE[s], (uint8_t *) dst, len - size);
+ }
+ else
+ w5100_read_16(src_ptr, (uint8_t *) dst, len);
+}
+
+
+uint8_t w5100_write_8(uint16_t _addr, uint8_t _data)
+{
+ RESET(W5100_CS);
+ spi_putc(0xF0);
+ spi_putc(_addr >> 8);
+ spi_putc(_addr & 0xFF);
+ spi_putc(_data);
+ SET(W5100_CS);
+ return TRUE;
+}
+
+uint16_t w5100_write_16(uint16_t _addr, uint8_t *_buf, uint16_t _len)
+{
+ for (int i=0; i<_len; i++)
+ {
+ RESET(W5100_CS);
+ spi_putc(0xF0);
+ spi_putc(_addr >> 8);
+ spi_putc(_addr & 0xFF);
+ _addr++;
+ spi_putc(_buf[i]);
+ SET(W5100_CS);
+ }
+ return _len;
+}
+
+uint8_t w5100_read_8(uint16_t _addr)
+{
+ RESET(W5100_CS);
+ spi_putc(0x0F);
+ spi_putc(_addr >> 8);
+ spi_putc(_addr & 0xFF);
+ uint8_t _data = spi_putc(0);
+ SET(W5100_CS);
+ return _data;
+}
+
+uint16_t w5100_read_16(uint16_t _addr, uint8_t *_buf, uint16_t _len)
+{
+ for (int i=0; i<_len; i++)
+ {
+ RESET(W5100_CS);
+ spi_putc(0x0F);
+ spi_putc(_addr >> 8);
+ spi_putc(_addr & 0xFF);
+ _addr++;
+ _buf[i] = spi_putc(0);
+ SET(W5100_CS);
+ }
+ return _len;
+}
+
+void w5100_execCmdSn(SOCKET s, enum SockCMD _cmd) {
+ // Send command to socket
+ w5100_writeSnCR(s, _cmd);
+ // Wait for command to complete
+ while (w5100_readSnCR(s))
+ ;
+}
+
+void w5100_clearIR()
+{
+ w5100_writeIR(0x00);
+}
diff --git a/w5100.h b/w5100.h
new file mode 100644
--- /dev/null
+++ b/w5100.h
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
+ * Ported to plain C and FreeRTOS by Andreas Boehler <andreas@aboehler.at>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef W5100_H_INCLUDED
+#define W5100_H_INCLUDED
+
+#include <avr/pgmspace.h>
+#include "spi.h"
+
+/**
+ * \file w5100.h
+ * \brief Low level W5100 functions
+ * This file contains the function and parameter definitions of the low level
+ * driver for the W5100 SPI ethernet interface.
+ */
+
+#define MAX_SOCK_NUM 4 ///< Maximum number of available sockets
+
+typedef uint8_t SOCKET; ///< Socket definition
+
+/**
+ * \name Various register definitions
+ */
+/*@{*/
+#define IDM_OR 0x8000
+#define IDM_AR0 0x8001
+#define IDM_AR1 0x8002
+#define IDM_DR 0x8003
+/*@}*/
+
+/**
+ * \name Socket n Mode Register definitions
+ */
+/*@{*/
+#define SNMR_CLOSE 0x00
+#define SNMR_TCP 0x01
+#define SNMR_UDP 0x02
+#define SNMR_IPRAW 0x03
+#define SNMR_MACRAW 0x04
+#define SNMR_PPPOE 0x05
+#define SNMR_ND 0x20
+#define SNMR_MULTI 0x80
+/*@}*/
+/**
+ * \name Socket command definitions
+ */
+enum SockCMD {
+ Sock_OPEN = 0x01,//!< Sock_OPEN
+ Sock_LISTEN = 0x02,//!< Sock_LISTEN
+ Sock_CONNECT = 0x04,//!< Sock_CONNECT
+ Sock_DISCON = 0x08,//!< Sock_DISCON
+ Sock_CLOSE = 0x10,//!< Sock_CLOSE
+ Sock_SEND = 0x20,//!< Sock_SEND
+ Sock_SEND_MAC = 0x21,//!< Sock_SEND_MAC
+ Sock_SEND_KEEP = 0x22,//!< Sock_SEND_KEEP
+ Sock_RECV = 0x40 //!< Sock_RECV
+};
+
+/**
+ * \name Socket n Interrupt Register definitions
+ */
+/*@{*/
+#define SNIR_SEND_OK 0x10
+#define SNIR_TIMEOUT 0x08
+#define SNIR_RECV 0x04
+#define SNIR_DISCON 0x02
+#define SNIR_CON 0x01
+/*@}*/
+
+/**
+ * \name Socket n Status Register definitions
+ */
+/*@{*/
+#define SNSR_CLOSED 0x00
+#define SNSR_INIT 0x13
+#define SNSR_LISTEN 0x14
+#define SNSR_SYNSENT 0x15
+#define SNSR_SYNRECV 0x16
+#define SNSR_ESTABLISHED 0x17
+#define SNSR_FIN_WAIT 0x18
+#define SNSR_CLOSING 0x1A
+#define SNSR_TIME_WAIT 0x1B
+#define SNSR_CLOSE_WAIT 0x1C
+#define SNSR_LAST_ACK 0x1D
+#define SNSR_UDP 0x22
+#define SNSR_IPRAW 0x32
+#define SNSR_MACRAW 0x42
+#define SNSR_PPPOE 0x5F
+/*@}*/
+
+/**
+ * \name IP protocol definitions
+ */
+/*@{*/
+#define IPPROTO_IP 0
+#define IPPROTO_ICMP 1
+#define IPPROTO_IGMP 2
+#define IPPROTO_GGP 3
+#define IPPROTO_TCP 6
+#define IPPROTO_PUP 12
+#define IPPROTO_UDP 17
+#define IPPROTO_IDP 22
+#define IPPROTO_ND 77
+#define IPPROTO_RAW 255
+/*@}*/
+
+/**
+ * w5100.h
+ *
+ * <pre>w5100_init(void)</pre>
+ *
+ * <i>Function</i> that initializes the w5100
+ * @return TRUE on success, FALSE on failure.
+ * \ingroup W5100
+ */
+uint8_t w5100_init(void);
+
+/**
+ * w5100.h
+ *
+ * <pre>w5100_clearIR(void)</pre>
+ *
+ * <i>Function</i> that clears the Interrupt Register
+ * \ingroup W5100
+ */
+void w5100_clearIR(void);
+
+/**
+ * w5100.h
+ *
+ * @brief This function is being used for copy the data form Receive buffer of the chip to application buffer.
+ *
+ * It calculate the actual physical address where one has to read
+ * the data from Receive buffer. Here also take care of the condition while it exceed
+ * the Rx memory uper-bound of socket.
+ *
+ * @param s The socket to read from
+ * @param src Pointer where the source address will be stored at
+ * @param dst Pointer where the destination address will be stored at
+ * @param len Length of the received data
+ * \ingroup W5100
+ */
+void w5100_read_data(SOCKET s, volatile uint8_t * src, volatile uint8_t * dst, uint16_t len);
+
+/**
+ * w5100.h
+*
+* @brief This function is being called by send() and sendto() function also.
+*
+* This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
+* register. User should read upper byte first and lower byte later to get proper value.
+*
+* @param s The socket to send
+* @param data Pointer to a byte array of data to be sent
+* @param len the Lenght of the byte array to send
+* \ingroup W5100
+*/
+void w5100_send_data_processing(SOCKET s, uint8_t *data, uint16_t len);
+
+/**
+ * w5100.h
+ *
+* @brief This function is being called by recv() also.
+*
+* This function read the Rx read pointer register
+* and after copy the data from receive buffer update the Rx write pointer register.
+* User should read upper byte first and lower byte later to get proper value.
+* @param s The socket to receive from
+* @param data Pointer to a data array
+* @param len The lenght of the received data
+* @param peek If this is set, data is not actually received but only peeked at.
+* \ingroup W5100
+*/
+void w5100_recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek);
+
+
+static inline void w5100_setGatewayIp(uint8_t *_addr);
+static inline void w5100_getGatewayIp(uint8_t *_addr);
+
+static inline void w5100_setSubnetMask(uint8_t *_addr);
+static inline void w5100_getSubnetMask(uint8_t *_addr);
+
+static inline void w5100_setMACAddress(uint8_t * addr);
+static inline void w5100_getMACAddress(uint8_t * addr);
+
+static inline void w5100_setIPAddress(uint8_t * addr);
+static inline void w5100_getIPAddress(uint8_t * addr);
+
+static inline void w5100_setRetransmissionTime(uint16_t timeout);
+static inline void w5100_setRetransmissionCount(uint8_t _retry);
+
+
+void w5100_execCmdSn(SOCKET s, enum SockCMD _cmd);
+
+uint16_t w5100_getTXFreeSize(SOCKET s);
+uint16_t w5100_getRXReceivedSize(SOCKET s);
+
+#define IM_IR0 0
+#define IM_IR1 1
+#define IM_IR2 2
+#define IM_IR3 3
+
+uint8_t w5100_write_8(uint16_t _addr, uint8_t _data);
+uint16_t w5100_write_16(uint16_t addr, uint8_t *buf, uint16_t len);
+uint8_t w5100_read_8(uint16_t addr);
+uint16_t w5100_read_16(uint16_t addr, uint8_t *buf, uint16_t len);
+
+#define __GP_REGISTER8(name, address) \
+ static inline void w5100_write##name(uint8_t _data) { \
+ w5100_write_8(address, _data); \
+ } \
+ static inline uint8_t w5100_read##name(void) { \
+ return w5100_read_8(address); \
+ }
+#define __GP_REGISTER16(name, address) \
+ static void w5100_write##name(uint16_t _data) { \
+ w5100_write_8(address, _data >> 8); \
+ w5100_write_8(address+1, _data & 0xFF); \
+ } \
+ static uint16_t w5100_read##name(void) { \
+ uint16_t res = w5100_read_8(address); \
+ res = (res << 8) + w5100_read_8(address + 1); \
+ return res; \
+ }
+#define __GP_REGISTER_N(name, address, size) \
+ static uint16_t w5100_write##name(uint8_t *_buff) { \
+ return w5100_write_16(address, _buff, size); \
+ } \
+ static uint16_t w5100_read##name(uint8_t *_buff) { \
+ return w5100_read_16(address, _buff, size); \
+ }
+
+
+ __GP_REGISTER8 (MR, 0x0000); // Mode
+ __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address
+ __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address
+ __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address
+ __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address
+ __GP_REGISTER8 (IR, 0x0015); // Interrupt
+ __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask
+ __GP_REGISTER16(RTR, 0x0017); // Timeout address
+ __GP_REGISTER8 (RCR, 0x0019); // Retry count
+ __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size
+ __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size
+ __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode
+ __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer
+ __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number
+// __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode
+// __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode
+
+#undef __GP_REGISTER8
+#undef __GP_REGISTER16
+#undef __GP_REGISTER_N
+
+ // W5100 Socket registers
+ // ----------------------
+inline static uint8_t w5100_readSn_8(SOCKET _s, uint16_t _addr);
+inline static uint8_t w5100_writeSn_8(SOCKET _s, uint16_t _addr, uint8_t _data);
+inline static uint16_t w5100_readSn_16(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
+inline static uint16_t w5100_writeSn_16(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
+
+#define CH_BASE 0x0400
+#define CH_SIZE 0x0100
+
+#define __SOCKET_REGISTER8(name, address) \
+ static inline void w5100_write##name(SOCKET _s, uint8_t _data) { \
+ w5100_writeSn_8(_s, address, _data); \
+ } \
+ static inline uint8_t w5100_read##name(SOCKET _s) { \
+ return w5100_readSn_8(_s, address); \
+ }
+#define __SOCKET_REGISTER16(name, address) \
+ static void w5100_write##name(SOCKET _s, uint16_t _data) { \
+ w5100_writeSn_8(_s, address, _data >> 8); \
+ w5100_writeSn_8(_s, address+1, _data & 0xFF); \
+ } \
+ static uint16_t w5100_read##name(SOCKET _s) { \
+ uint16_t res = w5100_readSn_8(_s, address); \
+ res = (res << 8) + w5100_readSn_8(_s, address + 1); \
+ return res; \
+ }
+#define __SOCKET_REGISTER_N(name, address, size) \
+ static uint16_t w5100_write##name(SOCKET _s, uint8_t *_buff) { \
+ return w5100_writeSn_16(_s, address, _buff, size); \
+ } \
+ static uint16_t w5100_read##name(SOCKET _s, uint8_t *_buff) { \
+ return w5100_readSn_16(_s, address, _buff, size); \
+ }
+
+ __SOCKET_REGISTER8(SnMR, 0x0000) // Mode
+ __SOCKET_REGISTER8(SnCR, 0x0001) // Command
+ __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt
+ __SOCKET_REGISTER8(SnSR, 0x0003) // Status
+ __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port
+// __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr
+// __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr
+// __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port
+// __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size
+ __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode
+ __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS
+ __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL
+ __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size
+// __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer
+ __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer
+ __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size
+ __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer
+// __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?)
+
+#undef __SOCKET_REGISTER8
+#undef __SOCKET_REGISTER16
+#undef __SOCKET_REGISTER_N
+
+
+#define RST 7 // Reset BIT
+
+
+#define SOCKETS 4
+#define SMASK 0x07FF // Tx buffer MASK
+#define RMASK 0x07FF // Rx buffer MASK
+#define SSIZE 2048 // Max Tx buffer size
+
+#define RSIZE 2048 // Max Rx buffer size
+
+uint16_t SBASE[SOCKETS]; // Tx buffer base address
+uint16_t RBASE[SOCKETS]; // Rx buffer base address
+
+uint8_t w5100_readSn_8(SOCKET _s, uint16_t _addr) {
+ return w5100_read_8(CH_BASE + _s * CH_SIZE + _addr);
+}
+
+uint8_t w5100_writeSn_8(SOCKET _s, uint16_t _addr, uint8_t _data) {
+ return w5100_write_8(CH_BASE + _s * CH_SIZE + _addr, _data);
+}
+
+uint16_t w5100_readSn_16(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) {
+ return w5100_read_16(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
+}
+
+uint16_t w5100_writeSn_16(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) {
+ return w5100_write_16(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
+}
+
+void w5100_getGatewayIp(uint8_t *_addr) {
+ w5100_readGAR(_addr);
+}
+
+void w5100_setGatewayIp(uint8_t *_addr) {
+ w5100_writeGAR(_addr);
+}
+
+void w5100_getSubnetMask(uint8_t *_addr) {
+ w5100_readSUBR(_addr);
+}
+
+void w5100_setSubnetMask(uint8_t *_addr) {
+ w5100_writeSUBR(_addr);
+}
+
+void w5100_getMACAddress(uint8_t *_addr) {
+ w5100_readSHAR(_addr);
+}
+
+void w5100_setMACAddress(uint8_t *_addr) {
+ w5100_writeSHAR(_addr);
+}
+
+void w5100_getIPAddress(uint8_t *_addr) {
+ w5100_readSIPR(_addr);
+}
+
+void w5100_setIPAddress(uint8_t *_addr) {
+ w5100_writeSIPR(_addr);
+}
+
+void w5100_setRetransmissionTime(uint16_t _timeout) {
+ w5100_writeRTR(_timeout);
+}
+
+void w5100_setRetransmissionCount(uint8_t _retry) {
+ w5100_writeRCR(_retry);
+}
+
+
+#endif
+
+//EOF

File Metadata

Mime Type
text/x-diff
Expires
Sun, Dec 22, 9:53 PM (2 d, 9 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
532547
Default Alt Text
(49 KB)

Event Timeline