Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F1820934
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Size
49 KB
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
rBC BlindControl
Event Timeline
Log In to Comment