Added Arduino Uno port for W5100 Ethernet shield. Note: requires an Arduino library that is included with the Arduino board, but not included here. Thank you, Miguel Fernandes!

This commit is contained in:
skarg
2015-07-07 15:02:04 +00:00
parent c3eddc2f1c
commit edcf8404d7
37 changed files with 5942 additions and 0 deletions
+209
View File
@@ -0,0 +1,209 @@
###############################################################################
# Makefile for BACnet
###############################################################################
## General Flags
MCU = atmega328p
AVRDUDE_MCU = m328
TARGET = bacnet
## Tools
CC = avr-gcc
AR = avr-ar
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AVRDUDE = avrdude
LINT = splint
# programmer id--check the avrdude for complete list
# # of available opts. These should include stk500,
# # avr910, avrisp, bsd, pony and more. Set this to
# # one of the valid "-c PROGRAMMER-ID" values
# # described in the avrdude info page.
# #
AVRDUDE_PROGRAMMERID = avrispmkII
#
# # port--serial or parallel port to which your
# # hardware programmer is attached
# #
AVRDUDE_PORT = /dev/ttyUSB0
# Source locations
BACNET_CORE = ../../src
BACNET_INCLUDE = ../../include
BACNET_HANDLER = ../../demo/handler
BACNET_OBJECT = ../../demo/object
BACNET_DEMO = ../../demo
ARDUINO_CORE = external/Arduino/core
ARDUINO_ETHERNET = external/Arduino/Ethernet
# local files for this project
CSRC = main.c \
uart.c \
apdu.c \
h_rp.c \
device.c \
av.c \
bv.c \
h_whois.c \
h_wp.c \
bip.c \
bip-init.c \
bvlc-arduino.c
# common demo files needed
DEMOSRC = $(BACNET_DEMO)/handler/txbuf.c \
$(BACNET_DEMO)/handler/h_npdu.c \
$(BACNET_DEMO)/handler/s_iam.c \
$(BACNET_DEMO)/handler/noserv.c
# core BACnet stack files
CORESRC = \
$(BACNET_CORE)/crc.c \
$(BACNET_CORE)/npdu.c \
$(BACNET_CORE)/bacdcode.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/wp.c \
$(BACNET_CORE)/whois.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/bacapp.c \
# $(BACNET_CORE)/ethernet.c
## Include Directories
INCLUDES = -I. -I$(BACNET_INCLUDE)
INCLUDES += -I$(BACNET_OBJECT)
INCLUDES += -I$(BACNET_HANDLER)
INCLUDES += -I$(ARDUINO_CORE)/include
INCLUDES += -I$(ARDUINO_ETHERNET)/include
# Source to Object conversion
COBJ = $(CSRC:.c=.o)
DEMOOBJ = $(DEMOSRC:.c=.o)
COREOBJ = $(CORESRC:.c=.o)
LIBRARY = lib$(TARGET).a
## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU) -DF_CPU=16000000UL
#OPTIMIZE_FLAGS = -mcall-prologues
#OPTIMIZE_FLAGS += -finline-functions-called-once -ffunction-sections -fdata-sections
#OPTIMIZATION = -Os $(OPTIMIZE_FLAGS)
OPTIMIZATION = -Os
#OPTIMIZATION = -O3 $(OPTIMIZE_FLAGS)
## Compile options common for all C compilation units.
# BFLAGS = -DBACDL_MSTP
#BFLAGS = -DBACDL_ETHERNET=1
BFLAGS = -DBACDL_BIP=1
BFLAGS += -DMAX_APDU=100
BFLAGS += -DBIG_ENDIAN=0
BFLAGS += -DMAX_TSM_TRANSACTIONS=0
#BFLAGS += -DCRC_USE_TABLE
BFLAGS += -DBACAPP_REAL
BFLAGS += -DBACAPP_OBJECT_ID
BFLAGS += -DBACAPP_UNSIGNED
BFLAGS += -DBACAPP_ENUMERATED
BFLAGS += -DBACAPP_CHARACTER_STRING
BFLAGS += -DWRITE_PROPERTY
BFLAGS += -DMAX_ANALOG_VALUES=4
BFLAGS += -DMAX_BINARY_VALUES=4
#BFLAGS += -DDEBUG
CFLAGS = $(COMMON)
# dead code removal
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += -Wall -g2 -gstabs -std=gnu99 $(BFLAGS) $(OPTIMIZATION)
CFLAGS += -MMD -MP -MT $(*F).o -MF dep/$(@F).d
#CFLAGS += -Wall -gdwarf-2 $(BFLAGS) $(OPTIMIZATION) -fsigned-char
#CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d
## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
## Linker flags
LDFLAGS = $(COMMON)
#dead code removal
LDFLAGS += -Wl,--gc-sections,-static
LDFLAGS += -Wl,-Map=$(TARGET).map,-L.,-l$(TARGET)
LDFLAGS += -Wl,-L$(ARDUINO_ETHERNET)/lib,-lArduinoEthernet
LDFLAGS += -Wl,-L$(ARDUINO_CORE)/lib,-lArduinoUnoCore,-lm
## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom
HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings
## Objects that must be built in order to link
OBJECTS = $(COBJ) $(DEMOOBJ)
#OBJECTS = $(COBJ)
## Build
TARGET_ELF=$(TARGET).elf
all: EthernetLib $(LIBRARY) $(TARGET_ELF) $(TARGET).hex $(TARGET).eep $(TARGET).lst \
size Makefile
EthernetLib:
$(MAKE) -s -C external/Arduino/Ethernet all
##Link
$(TARGET_ELF): $(OBJECTS) $(LIBRARY)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
%.hex: $(TARGET_ELF)
$(OBJCOPY) -O ihex $(HEX_FLASH_FLAGS) $< $@
%.eep: $(TARGET_ELF)
-$(OBJCOPY) $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
%.lst: $(TARGET_ELF)
$(OBJDUMP) -h -S $< > $@
lib: $(LIBRARY)
$(LIBRARY): $(COREOBJ) Makefile
$(AR) rcs $@ $(COREOBJ)
$(OBJDUMP) --syms $@ > $(LIBRARY:.a=.lst)
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $*.c -o $@
.cpp.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $*.cpp -o $@
size: ${TARGET_ELF}
@echo
@${SIZE} -C --mcu=${MCU} ${TARGET_ELF}
lint:
$(LINT) $(BFLAGS) $(CSRC)
install: $(TARGET_ELF)
$(AVRDUDE) -c $(AVRDUDE_PROGRAMMERID) \
-p $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -e \
-U flash:w:$(TARGET).hex
## Clean target
.PHONY: clean
clean:
-rm -rf $(OBJECTS) $(TARGET_ELF) dep/*
-rm -rf $(LIBRARY) $(COREOBJ)
# -rm -rf $(LIBRARY) $(COREOBJ) $(LIBRARY:.a=.lst)
-rm -rf $(TARGET).hex $(TARGET).eep $(TARGET).lst $(TARGET).map
cd external/Arduino/Ethernet; make clean
## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
+144
View File
@@ -0,0 +1,144 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2007 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "bits.h"
#include "apdu.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "handlers.h"
bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
{
bool status = false;
if (service_supported == SERVICE_SUPPORTED_READ_PROPERTY) {
status = true;
}
if (service_supported == SERVICE_SUPPORTED_WHO_IS) {
status = true;
}
#ifdef WRITE_PROPERTY
if (service_supported == SERVICE_SUPPORTED_WRITE_PROPERTY) {
status = true;
}
#endif
return status;
}
uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, /* APDU data */
uint16_t apdu_len,
BACNET_CONFIRMED_SERVICE_DATA * service_data,
uint8_t * service_choice,
uint8_t ** service_request,
uint16_t * service_request_len)
{
uint16_t len = 0; /* counts where we are in PDU */
service_data->segmented_message = (apdu[0] & BIT3) ? true : false;
service_data->more_follows = (apdu[0] & BIT2) ? true : false;
service_data->segmented_response_accepted =
(apdu[0] & BIT1) ? true : false;
service_data->max_segs = decode_max_segs(apdu[1]);
service_data->max_resp = decode_max_apdu(apdu[1]);
service_data->invoke_id = apdu[2];
len = 3;
if (service_data->segmented_message) {
service_data->sequence_number = apdu[len++];
service_data->proposed_window_number = apdu[len++];
}
*service_choice = apdu[len++];
*service_request = &apdu[len];
*service_request_len = apdu_len - len;
return len;
}
void apdu_handler(BACNET_ADDRESS * src,
uint8_t * apdu, /* APDU data */
uint16_t apdu_len)
{
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
uint8_t service_choice = 0;
uint8_t *service_request = NULL;
uint16_t service_request_len = 0;
uint16_t len = 0; /* counts where we are in PDU */
if (apdu) {
/* PDU Type */
switch (apdu[0] & 0xF0) {
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
apdu_len, &service_data, &service_choice, &service_request,
&service_request_len);
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
handler_read_property(service_request, service_request_len,
src, &service_data);
}
#ifdef WRITE_PROPERTY
else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
handler_write_property(service_request,
service_request_len, src, &service_data);
}
#endif
else {
handler_unrecognized_service(service_request,
service_request_len, src, &service_data);
}
break;
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
service_choice = apdu[1];
service_request = &apdu[2];
service_request_len = apdu_len - 2;
if (service_choice == SERVICE_UNCONFIRMED_WHO_IS) {
handler_who_is(service_request, service_request_len, src);
}
break;
case PDU_TYPE_SIMPLE_ACK:
case PDU_TYPE_COMPLEX_ACK:
case PDU_TYPE_SEGMENT_ACK:
case PDU_TYPE_ERROR:
case PDU_TYPE_REJECT:
case PDU_TYPE_ABORT:
default:
break;
}
}
return;
}
+254
View File
@@ -0,0 +1,254 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Analog Value Objects - customize for your use */
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "wp.h"
#include "av.h"
#if (MAX_ANALOG_VALUES > 10)
#error Modify the Analog_Value_Name to handle multiple digits
#endif
float AV_Present_Value[MAX_ANALOG_VALUES];
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Analog_Value_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_ANALOG_VALUES)
return true;
return false;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Analog_Value_Count(void)
{
return MAX_ANALOG_VALUES;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Analog_Value_Index_To_Instance(unsigned index)
{
return index;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
{
return object_instance;
}
/* note: the object name must be unique within this device */
char *Analog_Value_Name(uint32_t object_instance)
{
static char text_string[5] = "AV-"; /* okay for single thread */
text_string[3] = '0' + (uint8_t) object_instance;
return text_string;
}
/* return apdu len, or -1 on error */
int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
uint32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned object_index;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
characterstring_init_ansi(&char_string,
Analog_Value_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
object_index = Analog_Value_Instance_To_Index(object_instance);
apdu_len =
encode_application_real(&apdu[0],
AV_Present_Value[object_index]);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) && (array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
return apdu_len;
}
/* returns true if successful */
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
if (!Analog_Value_Valid_Instance(wp_data->object_instance)) {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
return false;
}
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
AV_Present_Value[object_index] = value.type.Real;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
void testAnalog_Value(Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_VALUE;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
len =
Analog_Value_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_ANALOG_VALUE);
ct_test(pTest, decoded_instance == instance);
return;
}
#ifdef TEST_ANALOG_VALUE
int main(void)
{
Test *pTest;
bool rc;
pTest = ct_create("BACnet Analog Value", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testAnalog_Value);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
+75
View File
@@ -0,0 +1,75 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef AV_H
#define AV_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "wp.h"
#ifndef MAX_ANALOG_VALUES
#define MAX_ANALOG_VALUES 4
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Analog_Value_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Analog_Value_Valid_Instance(uint32_t object_instance);
unsigned Analog_Value_Count(void);
uint32_t Analog_Value_Index_To_Instance(unsigned index);
char *Analog_Value_Name(uint32_t object_instance);
int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
uint32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Analog_Value_Present_Value_Set(uint32_t object_instance,
float value,
uint8_t priority);
float Analog_Value_Present_Value(uint32_t object_instance);
void Analog_Value_Init(void);
#ifdef TEST
#include "ctest.h"
void testAnalog_Value(Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+166
View File
@@ -0,0 +1,166 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#include <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */
#include <stdio.h>
#include "bacdcode.h"
#include "bip.h"
#include "socketWrapper.h"
#include "w5100Wrapper.h"
//#include "net.h"
/** @file linux/bip-init.c Initializes BACnet/IP interface (Linux). */
bool BIP_Debug = false;
/* gets an IP address by name, where name can be a
string that is an IP address in dotted form, or
a name that is a domain name
returns 0 if not found, or
an IP address in network byte order */
long bip_getaddrbyname(const char *host_name)
{
return 0;
}
/** Gets the local IP address and local broadcast address from the system,
* and saves it into the BACnet/IP data structures.
*
* @param ifname [in] The named interface to use for the network layer.
* Eg, for Linux, ifname is eth0, ath0, arc0, and others.
*/
void bip_set_interface(char *ifname)
{
uint8_t local_address[] = { 0, 0, 0, 0 };
uint8_t broadcast_address[] = { 0, 0, 0, 0 };
uint8_t netmask[] = { 0, 0, 0, 0 };
uint8_t invertedNetmask[] = { 0, 0, 0, 0 };
getIPAddress_func(CW5100Class_new(), local_address);
bip_set_addr(local_address);
if (BIP_Debug) {
fprintf(stderr, "Interface: %s\n", ifname);
fprintf(stderr, "IP Address: %d.%d.%d.%d\n", local_address[0],
local_address[1], local_address[2], local_address[3]);
}
/* setup local broadcast address */
getSubnetMask_func(CW5100Class_new(), netmask);
for (int i = 0; i < 4; i++) { //FIXME: IPv4 ?
invertedNetmask[i] = ~netmask[i];
broadcast_address[i] = (local_address[i] | invertedNetmask[i]);
}
bip_set_broadcast_addr(broadcast_address);
if (BIP_Debug) {
fprintf(stderr, "IP Broadcast Address: %d.%d.%d.%d\n",
broadcast_address[0], broadcast_address[1], broadcast_address[2],
broadcast_address[3]);
}
}
/** Initialize the BACnet/IP services at the given interface.
* @ingroup DLBIP
* -# Gets the local IP address and local broadcast address from the system,
* and saves it into the BACnet/IP data structures.
* -# Opens a UDP socket
* -# Configures the socket for sending and receiving
* -# Configures the socket so it can send broadcasts
* -# Binds the socket to the local IP address at the specified port for
* BACnet/IP (by default, 0xBAC0 = 47808).
*
* @note For Linux, ifname is eth0, ath0, arc0, and others.
*
* @param ifname [in] The named interface to use for the network layer.
* If NULL, the "eth0" interface is assigned.
* @return True if the socket is successfully opened for BACnet/IP,
* else False if the socket functions fail.
*/
bool bip_init(char *ifname)
{
uint8_t sock_fd = 0;
bool isOpen = false;
if (ifname)
bip_set_interface(ifname);
else
bip_set_interface("eth0");
/* assumes that the driver has already been initialized */
for (sock_fd = 0; sock_fd < MAX_SOCK_NUM; sock_fd++) {
if (readSnSR_func(CW5100Class_new(), sock_fd) == SnSR_CLOSED()) {
socket_func(sock_fd, SnMR_UDP(), (uint16_t) 47808, 0);
listen_func(sock_fd);
isOpen = true;
break;
}
}
if (!isOpen) {
bip_set_socket(MAX_SOCK_NUM);
return false;
} else {
bip_set_socket(sock_fd);
}
return true;
}
/** Cleanup and close out the BACnet/IP services by closing the socket.
* @ingroup DLBIP
*/
void bip_cleanup(void)
{
int sock_fd = 0;
if (bip_valid()) {
sock_fd = bip_socket();
close_func(sock_fd);
}
bip_set_socket(MAX_SOCK_NUM);
return;
}
/** Get the netmask of the BACnet/IP's interface via an ioctl() call.
* @param netmask [out] The netmask, in host order.
* @return 0 on success, else the error from the ioctl() call.
*/
int bip_get_local_netmask(uint8_t * netmask)
{
getSubnetMask_func(CW5100Class_new(), netmask);
return 0;
}
+413
View File
@@ -0,0 +1,413 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#include <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */
#include <string.h>
#include "bacdcode.h"
#include "bacint.h"
#include "bip.h"
#include "bvlc-arduino.h"
#include "socketWrapper.h"
#include "w5100Wrapper.h"
#if PRINT_ENABLED | DEBUG
#include <stdio.h> /* for standard i/o, like printing */
#endif
/** @file bip.c Configuration and Operations for BACnet/IP */
static uint8_t BIP_Socket = MAX_SOCK_NUM;
/* port to use - stored in network byte order */
static uint16_t BIP_Port = 0; /* this will force initialization in demos */
/* IP Address - stored in network byte order */
//static struct in_addr BIP_Address;
static uint8_t BIP_Address[4] = { 0, 0, 0, 0 };
/* Broadcast Address - stored in network byte order */
//static struct in_addr BIP_Broadcast_Address;
static uint8_t BIP_Broadcast_Address[4] = { 0, 0, 0, 0 };
/** Converter from uint8_t[4] type address to uint32_t
*
*/
uint32_t convertBIP_Address2uint32(uint8_t * bip_address)
{
return (uint32_t) ((bip_address[0] * 2 ^ 24) + (bip_address[1] * 2 ^ 16) +
(bip_address[2] * 2 ^ 8) + bip_address[3]);
}
/** Convert from uint32_t IPv4 address to uint8_t[4] address
*
*/
void convertUint32Address_2_uint8Address(uint32_t ip,
uint8_t * address)
{
address[0] = (uint8_t) (ip >> 24);
address[1] = (uint8_t) (ip >> 16);
address[2] = (uint8_t) (ip >> 8);
address[3] = (uint8_t) (ip >> 0);
}
/** Setter for the BACnet/IP socket handle.
*
* @param sock_fd [in] Handle for the BACnet/IP socket.
*/
void bip_set_socket(uint8_t sock_fd)
{
BIP_Socket = sock_fd;
}
/** Getter for the BACnet/IP socket handle.
*
* @return The handle to the BACnet/IP socket.
*/
uint8_t bip_socket(void)
{
return BIP_Socket;
}
bool bip_valid(void)
{
return (BIP_Socket < MAX_SOCK_NUM);
}
void bip_set_addr(uint8_t * net_address)
{ /* in network byte order */
for (uint8_t i = 0; i < 4; i++)
BIP_Address[i] = net_address[i];
}
/* returns network byte order */
uint8_t *bip_get_addr(void)
{
return BIP_Address;
}
void bip_set_broadcast_addr(uint8_t * net_address)
{ /* in network byte order */
for (uint8_t i = 0; i < 4; i++)
BIP_Broadcast_Address[i] = net_address[i];
}
/* returns network byte order */
uint8_t *bip_get_broadcast_addr(void)
{
return BIP_Broadcast_Address;
}
void bip_set_port(uint16_t port)
{ /* in network byte order */
BIP_Port = port;
}
/* returns network byte order */
uint16_t bip_get_port(void)
{
return BIP_Port;
}
static int bip_decode_bip_address(BACNET_ADDRESS * bac_addr,
uint8_t * address, /* in network format */
uint16_t * port)
{ /* in network format */
int len = 0;
if (bac_addr) {
memcpy(address, &bac_addr->mac[0], 4);
memcpy(port, &bac_addr->mac[4], 2);
len = 6;
}
return len;
}
/** Function to send a packet out the BACnet/IP socket (Annex J).
* @ingroup DLBIP
*
* @param dest [in] Destination address (may encode an IP address and port #).
* @param npdu_data [in] The NPDU header (Network) information (not used).
* @param pdu [in] Buffer of data to be sent - may be null (why?).
* @param pdu_len [in] Number of bytes in the pdu buffer.
* @return Number of bytes sent on success, negative number on failure.
*/
int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */
BACNET_NPDU_DATA * npdu_data, /* network information */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* number of bytes of data */
uint8_t mtu[MAX_MPDU] = { 0 };
int mtu_len = 0;
int bytes_sent = 0;
/* addr and port in host format */
uint8_t address[] = { 0, 0, 0, 0 };
uint16_t port = 0;
(void) npdu_data;
/* assumes that the driver has already been initialized */
if (BIP_Socket < 0) {
return BIP_Socket;
}
mtu[0] = BVLL_TYPE_BACNET_IP;
if ((dest->net == BACNET_BROADCAST_NETWORK) || ((dest->net > 0) &&
(dest->len == 0)) || (dest->mac_len == 0)) {
/* broadcast */
for (uint8_t i = 0; i < 4; i++)
address[i] = BIP_Broadcast_Address[i];
port = BIP_Port;
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
#ifdef DEBUG
fprintf(stderr, "Send Broadcast NPDU to %d.%d.%d.%d:%d\n", address[0],
address[1]
, address[2], address[3], port);
#endif
} else if (dest->mac_len == 6) {
bip_decode_bip_address(dest, address, &port);
mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
#ifdef DEBUG
fprintf(stderr, "Send Unicast NPDU to %d.%d.%d.%d:%d\n", address[0],
address[1]
, address[2], address[3], port);
#endif
} else {
/* invalid address */
return -1;
}
mtu_len = 2;
mtu_len +=
encode_unsigned16(&mtu[mtu_len],
(uint16_t) (pdu_len + 4 /*inclusive */ ));
memcpy(&mtu[mtu_len], pdu, pdu_len);
mtu_len += pdu_len;
#ifdef DEBUG
fprintf(stderr, "MTU size %d\n", mtu_len);
#endif
/* Send the packet */
bytes_sent =
sendto_func(BIP_Socket, mtu, (uint16_t) mtu_len, address, port);
return bytes_sent;
}
/** Implementation of the receive() function for BACnet/IP; receives one
* packet, verifies its BVLC header, and removes the BVLC header from
* the PDU data before returning.
*
* @param src [out] Source of the packet - who should receive any response.
* @param pdu [out] A buffer to hold the PDU portion of the received packet,
* after the BVLC portion has been stripped off.
* @param max_pdu [in] Size of the pdu[] buffer.
* @param timeout [in] The number of milliseconds to wait for a packet.
* @return The number of octets (remaining) in the PDU, or zero on failure.
*/
uint16_t bip_receive(BACNET_ADDRESS * src, /* source address */
uint8_t * pdu, /* PDU data */
uint16_t max_pdu, /* amount of space available in the PDU */
unsigned timeout)
{
int received_bytes = 0;
uint16_t pdu_len = 0; /* return value */
uint8_t src_addr[] = { 0, 0, 0, 0 };
uint16_t src_port = 0;
uint16_t i = 0;
int function = 0;
/* Make sure the socket is open */
if (BIP_Socket < 0)
return 0;
if (getRXReceivedSize_func(CW5100Class_new(), BIP_Socket)) {
memcpy(&src_addr, &src->mac[0], 4);
memcpy(&src_port, &src->mac[4], 2);
received_bytes =
(int) recvfrom_func(BIP_Socket, &pdu[0], max_pdu, src_addr,
&src_port);
}
/* See if there is a problem */
if (received_bytes < 0) {
return 0;
}
/* no problem, just no bytes */
if (received_bytes == 0)
return 0;
/* the signature of a BACnet/IP packet */
if (pdu[0] != BVLL_TYPE_BACNET_IP)
return 0;
if (bvlc_for_non_bbmd(src_addr, &src_port, pdu, received_bytes) > 0) {
/* Handled, usually with a NACK. */
#if PRINT_ENABLED
fprintf(stderr, "BIP: BVLC discarded!\n");
#endif
return 0;
}
function = bvlc_get_function_code(); /* aka, pdu[1] */
if ((function == BVLC_ORIGINAL_UNICAST_NPDU) ||
(function == BVLC_ORIGINAL_BROADCAST_NPDU)) {
/* ignore messages from me */
if ((convertBIP_Address2uint32(src_addr) ==
convertBIP_Address2uint32(BIP_Address)) &&
(src_port == BIP_Port)) {
pdu_len = 0;
#if 0
fprintf(stderr, "BIP: src is me. Discarded!\n");
#endif
} else {
/* data in src->mac[] is in network format */
src->mac_len = 6;
memcpy(&src->mac[0], &src_addr, 4);
memcpy(&src->mac[4], &src_port, 2);
#ifdef DEBUG
fprintf(stderr, "BIP receive from %d.%d.%d.%d\n", src->mac[0],
src->mac[1], src->mac[2], src->mac[3]);
#endif
/* FIXME: check destination address */
/* see if it is broadcast or for us */
/* decode the length of the PDU - length is inclusive of BVLC */
(void) decode_unsigned16(&pdu[2], &pdu_len);
/* subtract off the BVLC header */
pdu_len -= 4;
if (pdu_len < max_pdu) {
#if 0
fprintf(stderr, "BIP: NPDU[%hu]:", pdu_len);
#endif
/* shift the buffer to return a valid PDU */
for (i = 0; i < pdu_len; i++) {
pdu[i] = pdu[4 + i];
#if 0
fprintf(stderr, "%02X ", pdu[i]);
#endif
}
#if 0
fprintf(stderr, "\n");
#endif
}
/* ignore packets that are too large */
/* clients should check my max-apdu first */
else {
pdu_len = 0;
#if PRINT_ENABLED
fprintf(stderr, "BIP: PDU too large. Discarded!.\n");
#endif
}
}
} else if (function == BVLC_FORWARDED_NPDU) {
memcpy(&src_addr, &pdu[4], 4);
memcpy(&src_port, &pdu[8], 2);
if ((convertBIP_Address2uint32(src_addr) ==
convertBIP_Address2uint32(BIP_Address)) &&
(src_port == BIP_Port)) {
/* ignore messages from me */
pdu_len = 0;
} else {
/* data in src->mac[] is in network format */
src->mac_len = 6;
memcpy(&src->mac[0], &src_addr, 4);
memcpy(&src->mac[4], &src_port, 2);
/* FIXME: check destination address */
/* see if it is broadcast or for us */
/* decode the length of the PDU - length is inclusive of BVLC */
(void) decode_unsigned16(&pdu[2], &pdu_len);
/* subtract off the BVLC header */
pdu_len -= 10;
if (pdu_len < max_pdu) {
/* shift the buffer to return a valid PDU */
for (i = 0; i < pdu_len; i++) {
pdu[i] = pdu[4 + 6 + i];
}
} else {
/* ignore packets that are too large */
/* clients should check my max-apdu first */
pdu_len = 0;
}
}
}
return pdu_len;
}
void bip_get_my_address(BACNET_ADDRESS * my_address)
{
int i = 0;
if (my_address) {
my_address->mac_len = 6;
memcpy(&my_address->mac[0], &BIP_Address, 4);
memcpy(&my_address->mac[4], &BIP_Port, 2);
my_address->net = 0; /* local only, no routing */
my_address->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) {
/* no SADR */
my_address->adr[i] = 0;
}
}
return;
}
void bip_get_broadcast_address(BACNET_ADDRESS * dest)
{ /* destination address */
int i = 0; /* counter */
if (dest) {
dest->mac_len = 6;
memcpy(&dest->mac[0], &BIP_Broadcast_Address, 4);
memcpy(&dest->mac[4], &BIP_Port, 2);
dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) {
/* no SADR */
dest->adr[i] = 0;
}
}
return;
}
+302
View File
@@ -0,0 +1,302 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Binary Value Objects - customize for your use */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "wp.h"
#include "bv.h"
#if (MAX_BINARY_VALUES > 10)
#error Modify the Binary_Value_Name to handle multiple digits
#endif
static BACNET_BINARY_PV Present_Value[MAX_BINARY_VALUES];
/* we simply have 0-n object instances. */
bool Binary_Value_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_BINARY_VALUES)
return true;
return false;
}
/* we simply have 0-n object instances. */
unsigned Binary_Value_Count(void)
{
return MAX_BINARY_VALUES;
}
/* we simply have 0-n object instances. */
uint32_t Binary_Value_Index_To_Instance(unsigned index)
{
return index;
}
/* we simply have 0-n object instances. */
unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_BINARY_VALUES;
if (object_instance < MAX_BINARY_VALUES)
index = object_instance;
return index;
}
static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
if (object_instance < MAX_BINARY_VALUES) {
value = Present_Value[object_instance];
}
return value;
}
/* note: the object name must be unique within this device */
char *Binary_Value_Name(uint32_t object_instance)
{
static char text_string[5] = "BV-0"; /* okay for single thread */
if (object_instance < MAX_BINARY_VALUES) {
text_string[3] = '0' + (uint8_t) object_instance;
return text_string;
}
return NULL;
}
/* return apdu len, or -1 on error */
int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
uint32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
BACNET_POLARITY polarity = POLARITY_NORMAL;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
characterstring_init_ansi(&char_string,
Binary_Value_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Value_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
/* FIXME: figure out the polarity */
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) && (array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
return apdu_len;
}
/* returns true if successful */
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
if (!Binary_Value_Valid_Instance(wp_data->object_instance)) {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
return false;
}
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
if ((value.type.Enumerated == BINARY_ACTIVE) ||
(value.type.Enumerated == BINARY_INACTIVE)) {
object_index =
Binary_Value_Instance_To_Index(wp_data->
object_instance);
/* NOTE: this Binary value has no priority array */
Present_Value[object_index] =
(BACNET_BINARY_PV) value.type.Enumerated;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. */
if (Present_Value[0] == BINARY_ACTIVE) {
// LED_GREEN_ON();
} else {
// LED_GREEN_OFF();
}
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
void testBinary_Value(Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_BINARY_VALUE;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
len =
Binary_Value_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_BINARY_VALUE);
ct_test(pTest, decoded_instance == instance);
return;
}
#ifdef TEST_BINARY_VALUE
int main(void)
{
Test *pTest;
bool rc;
pTest = ct_create("BACnet Binary_Value", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testBinary_Value);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif /* TEST_BINARY_VALUE */
#endif /* TEST */
+72
View File
@@ -0,0 +1,72 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef BV_H
#define BV_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "wp.h"
#ifndef MAX_BINARY_VALUES
#define MAX_BINARY_VALUES 10
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Binary_Value_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Binary_Value_Valid_Instance(uint32_t object_instance);
unsigned Binary_Value_Count(void);
uint32_t Binary_Value_Index_To_Instance(unsigned index);
char *Binary_Value_Name(uint32_t object_instance);
void Binary_Value_Init(void);
int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
uint32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
#ifdef TEST
#include "ctest.h"
void testBinary_Value(Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
@@ -0,0 +1,124 @@
/**
* @file
* @author Miguel Fernandes <miguelandre.fernandes@gmail.com>
* @date 6 de Jun de 2013
* @brief BACnet Virtual Link Control for Wiznet on Arduino-Uno
*/
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "bvlc-arduino.h"
#include "bip.h"
#include "bacint.h"
#include "socketWrapper.h"
#include "w5100Wrapper.h"
/** result from a client request */
BACNET_BVLC_RESULT BVLC_Result_Code = BVLC_RESULT_SUCCESSFUL_COMPLETION;
/** The current BVLC Function Code being handled. */
BACNET_BVLC_FUNCTION BVLC_Function_Code = BVLC_RESULT; /* A safe default */
static int bvlc_encode_bvlc_result(uint8_t * pdu,
BACNET_BVLC_RESULT result_code)
{
if (pdu) {
pdu[0] = BVLL_TYPE_BACNET_IP;
pdu[1] = BVLC_RESULT;
/* The 2-octet BVLC Length field is the length, in octets,
of the entire BVLL message, including the two octets of the
length field itself, most significant octet first. */
encode_unsigned16(&pdu[2], 6);
encode_unsigned16(&pdu[4], (uint16_t) result_code);
}
return 6;
}
static int bvlc_send_mpdu(uint8_t * dest_addr, /* the destination address */
uint16_t * dest_port, /* the destination port */
uint8_t * mtu, /* the data */
uint16_t mtu_len)
{ /* amount of data to send */
/* assumes that the driver has already been initialized */
if (bip_valid()) {
return 0;
}
return sendto_func(bip_socket(), mtu, mtu_len, dest_addr, *dest_port);
}
static void bvlc_send_result(uint8_t * dest_addr,
uint16_t * dest_port, /* the destination address */
BACNET_BVLC_RESULT result_code)
{
uint8_t mtu[MAX_MPDU] = { 0 };
uint16_t mtu_len = 0;
mtu_len = (uint16_t) bvlc_encode_bvlc_result(&mtu[0], result_code);
bvlc_send_mpdu(dest_addr, dest_port, mtu, mtu_len);
return;
}
uint16_t bvlc_for_non_bbmd(uint8_t * addr,
uint16_t * port,
uint8_t * npdu,
uint16_t received_bytes)
{
uint16_t result_code = 0; /* aka, BVLC_RESULT_SUCCESSFUL_COMPLETION */
BVLC_Function_Code = npdu[1]; /* The BVLC function */
switch (BVLC_Function_Code) {
case BVLC_RESULT:
if (received_bytes >= 6) {
/* This is the result of our foreign device registration */
(void) decode_unsigned16(&npdu[4], &result_code);
BVLC_Result_Code = (BACNET_BVLC_RESULT) result_code;
fprintf(stderr, "BVLC: Result Code=%d\n", BVLC_Result_Code);
/* But don't send any response */
result_code = 0;
}
break;
case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE:
result_code = BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK;
break;
case BVLC_READ_BROADCAST_DIST_TABLE:
result_code = BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK;
break;
/* case BVLC_READ_BROADCAST_DIST_TABLE_ACK: */
case BVLC_REGISTER_FOREIGN_DEVICE:
result_code = BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK;
break;
case BVLC_READ_FOREIGN_DEVICE_TABLE:
result_code = BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK;
break;
/* case BVLC_READ_FOREIGN_DEVICE_TABLE_ACK: */
case BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY:
result_code = BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK;
break;
case BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK:
result_code = BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK;
break;
/* case BVLC_FORWARDED_NPDU: */
/* case BVLC_ORIGINAL_UNICAST_NPDU: */
/* case BVLC_ORIGINAL_BROADCAST_NPDU: */
default:
break;
}
if (result_code > 0) {
bvlc_send_result(addr, port, result_code);
fprintf(stderr, "BVLC: NAK code=%d\n", result_code);
}
return result_code;
}
BACNET_BVLC_FUNCTION bvlc_get_function_code(void)
{
return BVLC_Function_Code;
}
@@ -0,0 +1,29 @@
/**
* @file
* @author Miguel Fernandes <miguelandre.fernandes@gmail.com>
* @date 6 de Jun de 2013
* @brief BACnet Virtual Link Control for Wiznet on Arduino-Uno
*/
#ifndef BVLCARDUINO_H_
#define BVLCARDUINO_H_
#include <stdint.h>
#include "bacenum.h"
#include "bacdef.h"
#include "npdu.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
uint16_t bvlc_for_non_bbmd(uint8_t * addr,
uint16_t * port,
uint8_t * npdu,
uint16_t received_bytes);
BACNET_BVLC_FUNCTION bvlc_get_function_code(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* BVLCARDUINO_H_ */
+136
View File
@@ -0,0 +1,136 @@
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef DATALINK_H
#define DATALINK_H
#include "config.h"
#include "bacdef.h"
#if defined(BACDL_ETHERNET)
#include "ethernet.h"
#define datalink_init ethernet_init
#define datalink_send_pdu ethernet_send_pdu
#define datalink_receive ethernet_receive
#define datalink_cleanup ethernet_cleanup
#define datalink_get_broadcast_address ethernet_get_broadcast_address
#define datalink_get_my_address ethernet_get_my_address
#elif defined(BACDL_ARCNET)
#include "arcnet.h"
#define datalink_init arcnet_init
#define datalink_send_pdu arcnet_send_pdu
#define datalink_receive arcnet_receive
#define datalink_cleanup arcnet_cleanup
#define datalink_get_broadcast_address arcnet_get_broadcast_address
#define datalink_get_my_address arcnet_get_my_address
#elif defined(BACDL_MSTP)
#include "dlmstp.h"
#define datalink_init dlmstp_init
#define datalink_send_pdu dlmstp_send_pdu
#define datalink_receive dlmstp_receive
#define datalink_cleanup dlmstp_cleanup
#define datalink_get_broadcast_address dlmstp_get_broadcast_address
#define datalink_get_my_address dlmstp_get_my_address
#elif defined(BACDL_BIP)
#include "bip.h"
#include "bvlc-arduino.h"
#define datalink_init bip_init
//#if defined(BBMD_ENABLED) && BBMD_ENABLED
//#define datalink_send_pdu bvlc_send_pdu
//#define datalink_receive bvlc_receive
//#else
#define datalink_send_pdu bip_send_pdu
#define datalink_receive bip_receive
//#endif
#define datalink_cleanup bip_cleanup
#define datalink_get_broadcast_address bip_get_broadcast_address
#ifdef BAC_ROUTING
extern void routed_get_my_address(BACNET_ADDRESS * my_address);
#define datalink_get_my_address routed_get_my_address
#else
#define datalink_get_my_address bip_get_my_address
#endif
#else /* Ie, BACDL_ALL */
#include "npdu.h"
#define MAX_HEADER (8)
#define MAX_MPDU (MAX_HEADER+MAX_PDU)
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int datalink_send_pdu(BACNET_ADDRESS * dest,
BACNET_NPDU_DATA * npdu_data,
uint8_t * pdu,
unsigned pdu_len);
extern uint16_t datalink_receive(BACNET_ADDRESS * src,
uint8_t * pdu,
uint16_t max_pdu,
unsigned timeout);
extern void datalink_cleanup(void);
extern void datalink_get_broadcast_address(BACNET_ADDRESS * dest);
extern void datalink_get_my_address(BACNET_ADDRESS * my_address);
extern void datalink_set_interface(char *ifname);
extern void datalink_set(char *datalink_string);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/** @defgroup DataLink The BACnet Network (DataLink) Layer
* <b>6 THE NETWORK LAYER </b><br>
* The purpose of the BACnet network layer is to provide the means by which
* messages can be relayed from one BACnet network to another, regardless of
* the BACnet data link technology in use on that network. Whereas the data
* link layer provides the capability to address messages to a single device
* or broadcast them to all devices on the local network, the network layer
* allows messages to be directed to a single remote device, broadcast on a
* remote network, or broadcast globally to all devices on all networks.
* A BACnet Device is uniquely located by a network number and a MAC address.
*
* Each client or server application must define exactly one of these
* DataLink settings, which will control which parts of the code will be built:
* - BACDL_ETHERNET -- for Clause 7 ISO 8802-3 ("Ethernet") LAN
* - BACDL_ARCNET -- for Clause 8 ARCNET LAN
* - BACDL_MSTP -- for Clause 9 MASTER-SLAVE/TOKEN PASSING (MS/TP) LAN
* - BACDL_BIP -- for ANNEX J - BACnet/IP
* - BACDL_ALL -- Unspecified for the build, so the transport can be
* chosen at runtime from among these choices.
* - Clause 10 POINT-TO-POINT (PTP) and Clause 11 EIA/CEA-709.1 ("LonTalk") LAN
* are not currently supported by this project.
*//** @defgroup DLTemplates DataLink Template Functions
* @ingroup DataLink
* Most of the functions in this group are function templates which are assigned
* to a specific DataLink network layer implementation either at compile time or
* at runtime.
*/
#endif
+140
View File
@@ -0,0 +1,140 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#ifndef DEVICE_H
#define DEVICE_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacenum.h"
#include "wp.h"
#include "readrange.h"
typedef unsigned (*object_count_function) (void);
typedef uint32_t(*object_index_to_instance_function)
(unsigned index);
typedef char *(*object_name_function)
(uint32_t object_instance);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Device_Object_Function_Set(BACNET_OBJECT_TYPE object_type,
object_count_function count_function,
object_index_to_instance_function index_function,
object_name_function name_function);
void Device_Init(void);
void Device_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary);
uint32_t Device_Object_Instance_Number(void);
bool Device_Set_Object_Instance_Number(uint32_t object_id);
bool Device_Valid_Object_Instance_Number(uint32_t object_id);
unsigned Device_Object_List_Count(void);
bool Device_Object_List_Identifier(unsigned array_index,
int *object_type,
uint32_t * instance);
BACNET_DEVICE_STATUS Device_System_Status(void);
void Device_Set_System_Status(BACNET_DEVICE_STATUS status);
const char *Device_Vendor_Name(void);
uint16_t Device_Vendor_Identifier(void);
const char *Device_Model_Name(void);
bool Device_Set_Model_Name(const char *name,
size_t length);
const char *Device_Firmware_Revision(void);
const char *Device_Application_Software_Version(void);
bool Device_Set_Application_Software_Version(const char *name,
size_t length);
bool Device_Set_Object_Name(const char *name,
size_t length);
const char *Device_Object_Name(void);
const char *Device_Description(void);
bool Device_Set_Description(const char *name,
size_t length);
const char *Device_Location(void);
bool Device_Set_Location(const char *name,
size_t length);
/* some stack-centric constant values - no set methods */
uint8_t Device_Protocol_Version(void);
uint8_t Device_Protocol_Revision(void);
BACNET_SEGMENTATION Device_Segmentation_Supported(void);
uint8_t Device_Database_Revision(void);
void Device_Set_Database_Revision(uint8_t revision);
bool Device_Valid_Object_Name(const char *object_name,
int *object_type,
uint32_t * object_instance);
char *Device_Valid_Object_Id(int object_type,
uint32_t object_instance);
int Device_Encode_Property_APDU(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
uint32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool DeviceGetRRInfo(uint32_t Object, /* Which particular object - obviously not important for device object */
BACNET_PROPERTY_ID Property, /* Which property */
RR_PROP_INFO * pInfo, /* Where to put the information */
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
@@ -0,0 +1,118 @@
###############################################################################
# Makefile for BACnet
###############################################################################
## General Flags
MCU = atmega328p
AVRDUDE_MCU = m328
TARGET = ArduinoEthernet
## Tools
CC = avr-gcc
AR = avr-ar
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AVRDUDE = avrdude
LINT = splint
# programmer id--check the avrdude for complete list
# # of available opts. These should include stk500,
# # avr910, avrisp, bsd, pony and more. Set this to
# # one of the valid "-c PROGRAMMER-ID" values
# # described in the avrdude info page.
# #
AVRDUDE_PROGRAMMERID = avrispmkII
#
# # port--serial or parallel port to which your
# # hardware programmer is attached
# #
AVRDUDE_PORT = /dev/ttyUSB0
# local files for this project
#CSRC = main.c
ARDUINOSRC = \
src/socket.cpp \
src/w5100.cpp \
src/SPI.cpp \
src/w5100Wrapper.cpp \
src/socketWrapper.cpp
## Include Directories
INCLUDES = -Iinclude
INCLUDES += -I../core/include
LIBRARY = lib$(TARGET).a
## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)
OPTIMIZE_FLAGS = -mcall-prologues
#OPTIMIZE_FLAGS += -finline-functions
OPTIMIZE_FLAGS += -finline-functions-called-once
#OPTIMIZATION = -O0
#OPTIMIZATION = -Os
OPTIMIZATION = -Os $(OPTIMIZE_FLAGS)
#OPTIMIZATION = -O3 $(OPTIMIZE_FLAGS)
## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
# dead code removal
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += -Wall -gdwarf-2 $(OPTIMIZATION) -fsigned-char
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d
## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
## Linker flags
LDFLAGS = $(COMMON)
#dead code removal
#LDFLAGS += -Wl,-nostartfiles,-nostdlib
LDFLAGS += -Wl,--gc-sections,-static
LDFLAGS += -Wl,-Map=$(TARGET).map,-L.,-l$(TARGET)
#LDFLAGS += -Wl,-Map=$(TARGET).map
LDFLAGS += -L../core/lib,-lArduinoUnoCore
## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom
HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings
## Objects that must be built in order to link
OBJS := ${SRCS:.cpp=.o}
all: $(LIBRARY) size Makefile
default: all
lib: $(LIBRARY)
$(LIBRARY): $(OBJS) Makefile
$(AR) rcs lib/$@ $(OBJS)
$(OBJDUMP) --syms lib/$@ > lib/$(LIBRARY:.a=.lst)
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $*.c -o $@
.cpp.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $*.cpp -o $@
size: ${TARGET_ELF}
@echo
@${SIZE} ${TARGET_ELF}
lint:
$(LINT) $(BFLAGS) $(CSRC)
## Clean target
.PHONY: clean
clean:
-rm -rf $(OBJS) dep/*
-rm -rf $(LIBRARY) $(OBJS)
## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
* SPI Master library for arduino.
*
* 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_INCLUDED
#define _SPI_H_INCLUDED
#include <stdio.h>
#include <Arduino.h>
#include <avr/pgmspace.h>
#define SPI_CLOCK_DIV4 0x00
#define SPI_CLOCK_DIV16 0x01
#define SPI_CLOCK_DIV64 0x02
#define SPI_CLOCK_DIV128 0x03
#define SPI_CLOCK_DIV2 0x04
#define SPI_CLOCK_DIV8 0x05
#define SPI_CLOCK_DIV32 0x06
//#define SPI_CLOCK_DIV64 0x07
#define SPI_MODE0 0x00
#define SPI_MODE1 0x04
#define SPI_MODE2 0x08
#define SPI_MODE3 0x0C
#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
class SPIClass {
public:
inline static byte transfer(byte _data);
// SPI Configuration methods
inline static void attachInterrupt();
inline static void detachInterrupt(); // Default
static void begin(); // Default
static void end();
static void setBitOrder(uint8_t);
static void setDataMode(uint8_t);
static void setClockDivider(uint8_t);
};
extern SPIClass SPI;
byte SPIClass::transfer(byte _data)
{
SPDR = _data;
while (!(SPSR & _BV(SPIF)));
return SPDR;
}
void SPIClass::attachInterrupt()
{
SPCR |= _BV(SPIE);
}
void SPIClass::detachInterrupt()
{
SPCR &= ~_BV(SPIE);
}
#endif
@@ -0,0 +1,13 @@
#ifndef UTIL_H
#define UTIL_H
#define htons(x) ( ((x)<<8) | (((x)>>8)&0xFF) )
#define ntohs(x) htons(x)
#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \
((x)<< 8 & 0x00FF0000UL) | \
((x)>> 8 & 0x0000FF00UL) | \
((x)>>24 & 0x000000FFUL) )
#define ntohl(x) htonl(x)
#endif
@@ -0,0 +1,515 @@
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#ifndef W5100_H_INCLUDED
#define W5100_H_INCLUDED
#include <avr/pgmspace.h>
#include <SPI.h>
#define MAX_SOCK_NUM 4
typedef uint8_t SOCKET;
#define IDM_OR 0x8000
#define IDM_AR0 0x8001
#define IDM_AR1 0x8002
#define IDM_DR 0x8003
/*
class MR {
public:
static const uint8_t RST = 0x80;
static const uint8_t PB = 0x10;
static const uint8_t PPPOE = 0x08;
static const uint8_t LB = 0x04;
static const uint8_t AI = 0x02;
static const uint8_t IND = 0x01;
};
*/
/*
class IR {
public:
static const uint8_t CONFLICT = 0x80;
static const uint8_t UNREACH = 0x40;
static const uint8_t PPPoE = 0x20;
static const uint8_t SOCK0 = 0x01;
static const uint8_t SOCK1 = 0x02;
static const uint8_t SOCK2 = 0x04;
static const uint8_t SOCK3 = 0x08;
static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); };
};
*/
class SnMR {
public:
static const uint8_t CLOSE = 0x00;
static const uint8_t TCP = 0x01;
static const uint8_t UDP = 0x02;
static const uint8_t IPRAW = 0x03;
static const uint8_t MACRAW = 0x04;
static const uint8_t PPPOE = 0x05;
static const uint8_t ND = 0x20;
static const uint8_t MULTI = 0x80;
};
enum SockCMD {
Sock_OPEN = 0x01,
Sock_LISTEN = 0x02,
Sock_CONNECT = 0x04,
Sock_DISCON = 0x08,
Sock_CLOSE = 0x10,
Sock_SEND = 0x20,
Sock_SEND_MAC = 0x21,
Sock_SEND_KEEP = 0x22,
Sock_RECV = 0x40
};
/*class SnCmd {
public:
static const uint8_t OPEN = 0x01;
static const uint8_t LISTEN = 0x02;
static const uint8_t CONNECT = 0x04;
static const uint8_t DISCON = 0x08;
static const uint8_t CLOSE = 0x10;
static const uint8_t SEND = 0x20;
static const uint8_t SEND_MAC = 0x21;
static const uint8_t SEND_KEEP = 0x22;
static const uint8_t RECV = 0x40;
};
*/
class SnIR {
public:
static const uint8_t SEND_OK = 0x10;
static const uint8_t TIMEOUT = 0x08;
static const uint8_t RECV = 0x04;
static const uint8_t DISCON = 0x02;
static const uint8_t CON = 0x01;
};
class SnSR {
public:
static const uint8_t CLOSED = 0x00;
static const uint8_t INIT = 0x13;
static const uint8_t LISTEN = 0x14;
static const uint8_t SYNSENT = 0x15;
static const uint8_t SYNRECV = 0x16;
static const uint8_t ESTABLISHED = 0x17;
static const uint8_t FIN_WAIT = 0x18;
static const uint8_t CLOSING = 0x1A;
static const uint8_t TIME_WAIT = 0x1B;
static const uint8_t CLOSE_WAIT = 0x1C;
static const uint8_t LAST_ACK = 0x1D;
static const uint8_t UDP = 0x22;
static const uint8_t IPRAW = 0x32;
static const uint8_t MACRAW = 0x42;
static const uint8_t PPPOE = 0x5F;
};
class IPPROTO {
public:
static const uint8_t IP = 0;
static const uint8_t ICMP = 1;
static const uint8_t IGMP = 2;
static const uint8_t GGP = 3;
static const uint8_t TCP = 6;
static const uint8_t PUP = 12;
static const uint8_t UDP = 17;
static const uint8_t IDP = 22;
static const uint8_t ND = 77;
static const uint8_t RAW = 255;
};
class W5100Class {
public:
void init();
/**
* @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.
*/
void read_data(SOCKET s,
volatile uint8_t * src,
volatile uint8_t * dst,
uint16_t len);
/**
* @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.
*/
void send_data_processing(SOCKET s,
const uint8_t * data,
uint16_t len);
/**
* @brief A copy of send_data_processing that uses the provided ptr for the
* write offset. Only needed for the "streaming" UDP API, where
* a single UDP packet is built up over a number of calls to
* send_data_processing_ptr, because TX_WR doesn't seem to get updated
* correctly in those scenarios
* @param ptr value to use in place of TX_WR. If 0, then the value is read
* in from TX_WR
* @return New value for ptr, to be used in the next call
*/
// FIXME Update documentation
void send_data_processing_offset(SOCKET s,
uint16_t data_offset,
const uint8_t * data,
uint16_t len);
/**
* @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.
*/
void recv_data_processing(SOCKET s,
uint8_t * data,
uint16_t len,
uint8_t peek = 0);
inline void setGatewayIp(uint8_t * _addr);
inline void getGatewayIp(uint8_t * _addr);
inline void setSubnetMask(uint8_t * _addr);
inline void getSubnetMask(uint8_t * _addr);
inline void setMACAddress(uint8_t * addr);
inline void getMACAddress(uint8_t * addr);
inline void setIPAddress(uint8_t * addr);
inline void getIPAddress(uint8_t * addr);
inline void setRetransmissionTime(uint16_t timeout);
inline void setRetransmissionCount(uint8_t _retry);
void execCmdSn(SOCKET s,
SockCMD _cmd);
uint16_t getTXFreeSize(SOCKET s);
uint16_t getRXReceivedSize(SOCKET s);
// W5100 Registers
// ---------------
private:
static uint8_t write(uint16_t _addr,
uint8_t _data);
static uint16_t write(uint16_t addr,
const uint8_t * buf,
uint16_t len);
static uint8_t read(uint16_t addr);
static uint16_t read(uint16_t addr,
uint8_t * buf,
uint16_t len);
#define __GP_REGISTER8(name, address) \
static inline void write##name(uint8_t _data) { \
write(address, _data); \
} \
static inline uint8_t read##name() { \
return read(address); \
}
#define __GP_REGISTER16(name, address) \
static void write##name(uint16_t _data) { \
write(address, _data >> 8); \
write(address+1, _data & 0xFF); \
} \
static uint16_t read##name() { \
uint16_t res = read(address); \
res = (res << 8) + read(address + 1); \
return res; \
}
#define __GP_REGISTER_N(name, address, size) \
static uint16_t write##name(uint8_t *_buff) { \
return write(address, _buff, size); \
} \
static uint16_t read##name(uint8_t *_buff) { \
return read(address, _buff, size); \
}
public:
__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
// ----------------------
private:
static inline uint8_t readSn(SOCKET _s,
uint16_t _addr);
static inline uint8_t writeSn(SOCKET _s,
uint16_t _addr,
uint8_t _data);
static inline uint16_t readSn(SOCKET _s,
uint16_t _addr,
uint8_t * _buf,
uint16_t len);
static inline uint16_t writeSn(SOCKET _s,
uint16_t _addr,
uint8_t * _buf,
uint16_t len);
static const uint16_t CH_BASE = 0x0400;
static const uint16_t CH_SIZE = 0x0100;
#define __SOCKET_REGISTER8(name, address) \
static inline void write##name(SOCKET _s, uint8_t _data) { \
writeSn(_s, address, _data); \
} \
static inline uint8_t read##name(SOCKET _s) { \
return readSn(_s, address); \
}
#define __SOCKET_REGISTER16(name, address) \
static void write##name(SOCKET _s, uint16_t _data) { \
writeSn(_s, address, _data >> 8); \
writeSn(_s, address+1, _data & 0xFF); \
} \
static uint16_t read##name(SOCKET _s) { \
uint16_t res = readSn(_s, address); \
uint16_t res2 = readSn(_s,address + 1); \
res = res << 8; \
res2 = res2 & 0xFF; \
res = res | res2; \
return res; \
}
#define __SOCKET_REGISTER_N(name, address, size) \
static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \
return writeSn(_s, address, _buff, size); \
} \
static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \
return readSn(_s, address, _buff, size); \
}
public:
__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
private:
static const uint8_t RST = 7; // Reset BIT
static const int SOCKETS = 4;
static const uint16_t SMASK = 0x07FF; // Tx buffer MASK
static const uint16_t RMASK = 0x07FF; // Rx buffer MASK
public:
static const uint16_t SSIZE = 2048; // Max Tx buffer size
private:
static const uint16_t RSIZE = 2048; // Max Rx buffer size
uint16_t SBASE[SOCKETS]; // Tx buffer base address
uint16_t RBASE[SOCKETS]; // Rx buffer base address
private:
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
inline static void initSS() {
DDRB |= _BV(4);
};
inline static void setSS() {
PORTB &= ~_BV(4);
};
inline static void resetSS() {
PORTB |= _BV(4);
};
#elif defined(__AVR_ATmega32U4__)
inline static void initSS() {
DDRB |= _BV(6);
};
inline static void setSS() {
PORTB &= ~_BV(6);
};
inline static void resetSS() {
PORTB |= _BV(6);
};
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
inline static void initSS() {
DDRB |= _BV(0);
};
inline static void setSS() {
PORTB &= ~_BV(0);
};
inline static void resetSS() {
PORTB |= _BV(0);
};
#else
inline static void initSS() {
DDRB |= _BV(2);
};
inline static void setSS() {
PORTB &= ~_BV(2);
};
inline static void resetSS() {
PORTB |= _BV(2);
};
#endif
};
extern W5100Class W5100;
uint8_t W5100Class::readSn(SOCKET _s,
uint16_t _addr)
{
return read(CH_BASE + _s * CH_SIZE + _addr);
}
uint8_t W5100Class::writeSn(SOCKET _s,
uint16_t _addr,
uint8_t _data)
{
return write(CH_BASE + _s * CH_SIZE + _addr, _data);
}
uint16_t W5100Class::readSn(SOCKET _s,
uint16_t _addr,
uint8_t * _buf,
uint16_t _len)
{
return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
}
uint16_t W5100Class::writeSn(SOCKET _s,
uint16_t _addr,
uint8_t * _buf,
uint16_t _len)
{
return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
}
void W5100Class::getGatewayIp(uint8_t * _addr)
{
readGAR(_addr);
}
void W5100Class::setGatewayIp(uint8_t * _addr)
{
writeGAR(_addr);
}
void W5100Class::getSubnetMask(uint8_t * _addr)
{
readSUBR(_addr);
}
void W5100Class::setSubnetMask(uint8_t * _addr)
{
writeSUBR(_addr);
}
void W5100Class::getMACAddress(uint8_t * _addr)
{
readSHAR(_addr);
}
void W5100Class::setMACAddress(uint8_t * _addr)
{
writeSHAR(_addr);
}
void W5100Class::getIPAddress(uint8_t * _addr)
{
readSIPR(_addr);
}
void W5100Class::setIPAddress(uint8_t * _addr)
{
writeSIPR(_addr);
}
void W5100Class::setRetransmissionTime(uint16_t _timeout)
{
writeRTR(_timeout);
}
void W5100Class::setRetransmissionCount(uint8_t _retry)
{
writeRCR(_retry);
}
#endif
@@ -0,0 +1,139 @@
/*
* w5100Wrapper.h
*
* Created on: 26 de Mai de 2013
* Author: mgf
*/
#ifndef W5100WRAPPER_H_
#define W5100WRAPPER_H_
#include <avr/pgmspace.h>
typedef uint8_t SOCKET;
typedef void CSnMR;
typedef void CSnIR;
typedef void CSnSR;
typedef void CIPPROTO;
typedef void CW5100Class;
#define MAX_SOCK_NUM 4
#ifdef __cplusplus
extern "C" {
#endif
CSnMR *CSnMR_new();
void CSnMR_delete(const CSnMR * obj);
uint8_t SnMR_CLOSE();
uint8_t SnMR_UDP();
uint8_t SnMR_TCP();
uint8_t SnMR_IPRAW();
uint8_t SnMR_MACRAW();
uint8_t SnMR_PPPOE();
uint8_t SnMR_ND();
uint8_t SnMR_MULTI();
CSnIR *CSnIR_new();
void CSnIR_delete(const CSnIR * obj);
uint8_t SnIR_SEND_OK();
uint8_t SnIR_TIMEOUT();
uint8_t SnIR_RECV();
uint8_t SnIR_DISCON();
uint8_t SnIR_CON();
CSnSR *CSnSR_new();
void CSnSR_delete(const CSnSR * obj);
uint8_t SnSR_CLOSED();
uint8_t SnSR_INIT();
uint8_t SnSR_LISTEN();
uint8_t SnSR_SYNSENT();
uint8_t SnSR_SYNRECV();
uint8_t SnSR_ESTABLISHED();
uint8_t SnSR_FIN_WAIT();
uint8_t SnSR_CLOSING();
uint8_t SnSR_TIME_WAIT();
uint8_t SnSR_CLOSE_WAIT();
uint8_t SnSR_LAST_ACK();
uint8_t SnSR_UDP();
uint8_t SnSR_IPRAW();
uint8_t SnSR_MACRAW();
uint8_t SnSR_PPPOE();
CIPPROTO *CIPPROTO_new();
void CIPPROTO_delete(const CIPPROTO * obj);
uint8_t IPPROTO_IP();
uint8_t IPPROTO_ICMP();
uint8_t IPPROTO_IGMP();
uint8_t IPPROTO_GGP();
uint8_t IPPROTO_TCP();
uint8_t IPPROTO_PUP();
uint8_t IPPROTO_UDP();
uint8_t IPPROTO_IDP();
uint8_t IPPROTO_ND();
uint8_t IPPROTO_RAW();
CW5100Class *CW5100Class_new();
void init_func(const CW5100Class * obj);
void CW5100Class_delete(const CW5100Class * obj);
void read_data_func(const CW5100Class * obj,
SOCKET s,
volatile uint8_t * src,
volatile uint8_t * dst,
uint16_t len);
void send_data_processing_func(const CW5100Class * obj,
SOCKET s,
const uint8_t * data,
uint16_t len);
void send_data_processing_offset_func(const CW5100Class * obj,
SOCKET s,
uint16_t data_offset,
const uint8_t * data,
uint16_t len);
//FIXME: Removed defaul value of 0(zero) from the peek argument
void recv_data_processing_func(const CW5100Class * obj,
SOCKET s,
uint8_t * data,
uint16_t len,
uint8_t peek);
void setGatewayIp_func(const CW5100Class * obj,
uint8_t * _addr);
void getGatewayIp_func(const CW5100Class * obj,
uint8_t * _addr);
//
void setSubnetMask_func(const CW5100Class * obj,
uint8_t * _addr);
void getSubnetMask_func(const CW5100Class * obj,
uint8_t * _addr);
//
void setMACAddress_func(const CW5100Class * obj,
uint8_t * addr);
void getMACAddress_func(const CW5100Class * obj,
uint8_t * addr);
//
void setIPAddress_func(const CW5100Class * obj,
uint8_t * addr);
void getIPAddress_func(const CW5100Class * obj,
uint8_t * addr);
//
void setRetransmissionTime_func(const CW5100Class * obj,
uint16_t timeout);
void setRetransmissionCount_func(const CW5100Class * obj,
uint8_t _retry);
//
uint16_t getTXFreeSize_func(const CW5100Class * obj,
SOCKET s);
uint16_t getRXReceivedSize_func(const CW5100Class * obj,
SOCKET s);
uint8_t readSnSR_func(const CW5100Class * obj,
SOCKET s);
#ifdef __cplusplus
}
#endif
#endif /* W5100WRAPPER_H_ */
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
* SPI Master library for arduino.
*
* 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 "pins_arduino.h"
#include "SPI.h"
SPIClass SPI;
void SPIClass::begin() {
// Set SS to high so a connected chip will be "deselected" by default
digitalWrite(SS, HIGH);
// When the SS pin is set as OUTPUT, it can be used as
// a general purpose output port (it doesn't influence
// SPI operations).
pinMode(SS, OUTPUT);
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
// automatically switches to Slave, so the data direction of
// the SS pin MUST be kept as OUTPUT.
SPCR |= _BV(MSTR);
SPCR |= _BV(SPE);
// Set direction register for SCK and MOSI pin.
// MISO pin automatically overrides to INPUT.
// By doing this AFTER enabling SPI, we avoid accidentally
// clocking in a single bit since the lines go directly
// from "input" to SPI control.
// http://code.google.com/p/arduino/issues/detail?id=888
pinMode(SCK, OUTPUT);
pinMode(MOSI, OUTPUT);
}
void SPIClass::end() {
SPCR &= ~_BV(SPE);
}
void SPIClass::setBitOrder(uint8_t bitOrder)
{
if(bitOrder == LSBFIRST) {
SPCR |= _BV(DORD);
} else {
SPCR &= ~(_BV(DORD));
}
}
void SPIClass::setDataMode(uint8_t mode)
{
SPCR = (SPCR & ~SPI_MODE_MASK) | mode;
}
void SPIClass::setClockDivider(uint8_t rate)
{
SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK);
SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK);
}
@@ -0,0 +1,400 @@
#include "w5100.h"
#include "socket.h"
static uint16_t local_port;
/**
* @brief This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it.
* @return 1 for success else 0.
*/
uint8_t 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))
{
close(s);
W5100.writeSnMR(s, protocol | flag);
if (port != 0) {
W5100.writeSnPORT(s, port);
}
else {
local_port++; // if don't set the source port, set local_port number.
W5100.writeSnPORT(s, local_port);
}
W5100.execCmdSn(s, Sock_OPEN);
return 1;
}
return 0;
}
/**
* @brief This function close the socket and parameter is "s" which represent the socket number
*/
void close(SOCKET s)
{
W5100.execCmdSn(s, Sock_CLOSE);
W5100.writeSnIR(s, 0xFF);
}
/**
* @brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer.
* @return 1 for success else 0.
*/
uint8_t listen(SOCKET s)
{
if (W5100.readSnSR(s) != SnSR::INIT)
return 0;
W5100.execCmdSn(s, Sock_LISTEN);
return 1;
}
/**
* @brief This function established the connection for the channel in Active (client) mode.
* This function waits for the untill the connection is established.
*
* @return 1 for success else 0.
*/
uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port)
{
if
(
((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
(port == 0x00)
)
return 0;
// set destination IP
W5100.writeSnDIPR(s, addr);
W5100.writeSnDPORT(s, port);
W5100.execCmdSn(s, Sock_CONNECT);
return 1;
}
/**
* @brief This function used for disconnect the socket and parameter is "s" which represent the socket number
* @return 1 for success else 0.
*/
void disconnect(SOCKET s)
{
W5100.execCmdSn(s, Sock_DISCON);
}
/**
* @brief This function used to send the data in TCP mode
* @return 1 for success else 0.
*/
uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len)
{
uint8_t status=0;
uint16_t ret=0;
uint16_t freesize=0;
if (len > W5100.SSIZE)
ret = W5100.SSIZE; // check size not to exceed MAX size.
else
ret = len;
// if freebuf is available, start.
do
{
freesize = W5100.getTXFreeSize(s);
status = W5100.readSnSR(s);
if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT))
{
ret = 0;
break;
}
}
while (freesize < ret);
// copy data
W5100.send_data_processing(s, (uint8_t *)buf, ret);
W5100.execCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
/* m2008.01 [bj] : reduce code */
if ( W5100.readSnSR(s) == SnSR::CLOSED )
{
close(s);
return 0;
}
}
/* +2008.01 bj */
W5100.writeSnIR(s, SnIR::SEND_OK);
return ret;
}
/**
* @brief This function is an application I/F function which is used to receive the data in TCP mode.
* It continues to wait for data as much as the application wants to receive.
*
* @return received data size for success else -1.
*/
int16_t recv(SOCKET s, uint8_t *buf, int16_t len)
{
// Check how much data is available
int16_t ret = W5100.getRXReceivedSize(s);
if ( ret == 0 )
{
// No data available.
uint8_t status = W5100.readSnSR(s);
if ( status == SnSR::LISTEN || status == SnSR::CLOSED || status == SnSR::CLOSE_WAIT )
{
// The remote end has closed its side of the connection, so this is the eof state
ret = 0;
}
else
{
// The connection is still up, but there's no data waiting to be read
ret = -1;
}
}
else if (ret > len)
{
ret = len;
}
if ( ret > 0 )
{
W5100.recv_data_processing(s, buf, ret);
W5100.execCmdSn(s, Sock_RECV);
}
return ret;
}
/**
* @brief Returns the first byte in the receive queue (no checking)
*
* @return
*/
uint16_t peek(SOCKET s, uint8_t *buf)
{
W5100.recv_data_processing(s, buf, 1, 1);
return 1;
}
/**
* @brief This function is an application I/F function which is used to send the data for other then TCP mode.
* Unlike TCP transmission, The peer's destination address and the port is needed.
*
* @return This function return send data size for success else -1.
*/
uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port)
{
uint16_t ret=0;
if (len > W5100.SSIZE) ret = W5100.SSIZE; // check size not to exceed MAX size.
else ret = len;
if
(
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
((port == 0x00)) ||(ret == 0)
)
{
/* +2008.01 [bj] : added return value */
ret = 0;
}
else
{
W5100.writeSnDIPR(s, addr);
W5100.writeSnDPORT(s, port);
// copy data
W5100.send_data_processing(s, (uint8_t *)buf, ret);
W5100.execCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
if (W5100.readSnIR(s) & SnIR::TIMEOUT)
{
/* +2008.01 [bj]: clear interrupt */
W5100.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */
return 0;
}
}
/* +2008.01 bj */
W5100.writeSnIR(s, SnIR::SEND_OK);
}
return ret;
}
/**
* @brief This function is an application I/F function which is used to receive the data in other then
* TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well.
*
* @return This function return received data size for success else -1.
*/
uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port)
{
uint8_t head[8];
uint16_t data_len=0;
uint16_t ptr=0;
if ( len > 0 )
{
ptr = W5100.readSnRX_RD(s);
switch (W5100.readSnMR(s) & 0x07)
{
case SnMR::UDP :
W5100.read_data(s, (uint8_t *)ptr, head, 0x08);
ptr += 8;
// read peer's IP address, port number.
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
*port = head[4];
*port = (*port << 8) + head[5];
data_len = head[6];
data_len = (data_len << 8) + head[7];
W5100.read_data(s, (uint8_t *)ptr, buf, data_len); // data copy.
ptr += data_len;
W5100.writeSnRX_RD(s, ptr);
break;
case SnMR::IPRAW :
W5100.read_data(s, (uint8_t *)ptr, head, 0x06);
ptr += 6;
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
data_len = head[4];
data_len = (data_len << 8) + head[5];
W5100.read_data(s, (uint8_t *)ptr, buf, data_len); // data copy.
ptr += data_len;
W5100.writeSnRX_RD(s, ptr);
break;
case SnMR::MACRAW:
W5100.read_data(s,(uint8_t*)ptr,head,2);
ptr+=2;
data_len = head[0];
data_len = (data_len<<8) + head[1] - 2;
W5100.read_data(s,(uint8_t*) ptr,buf,data_len);
ptr += data_len;
W5100.writeSnRX_RD(s, ptr);
break;
default :
break;
}
W5100.execCmdSn(s, Sock_RECV);
}
return data_len;
}
uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len)
{
uint8_t status=0;
uint16_t ret=0;
if (len > W5100.SSIZE)
ret = W5100.SSIZE; // check size not to exceed MAX size.
else
ret = len;
if (ret == 0)
return 0;
W5100.send_data_processing(s, (uint8_t *)buf, ret);
W5100.execCmdSn(s, Sock_SEND);
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
status = W5100.readSnSR(s);
if (W5100.readSnIR(s) & SnIR::TIMEOUT)
{
/* in case of igmp, if send fails, then socket closed */
/* if you want change, remove this code. */
close(s);
return 0;
}
}
W5100.writeSnIR(s, SnIR::SEND_OK);
return ret;
}
uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len)
{
uint16_t ret =0;
if (len > W5100.getTXFreeSize(s))
{
ret = W5100.getTXFreeSize(s); // check size not to exceed MAX size.
}
else
{
ret = len;
}
W5100.send_data_processing_offset(s, offset, buf, ret);
return ret;
}
int startUDP(SOCKET s, uint8_t* addr, uint16_t port)
{
if
(
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
((port == 0x00))
)
{
return 0;
}
else
{
W5100.writeSnDIPR(s, addr);
W5100.writeSnDPORT(s, port);
return 1;
}
}
int sendUDP(SOCKET s)
{
W5100.execCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
if (W5100.readSnIR(s) & SnIR::TIMEOUT)
{
/* +2008.01 [bj]: clear interrupt */
W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT));
return 0;
}
}
/* +2008.01 bj */
W5100.writeSnIR(s, SnIR::SEND_OK);
/* Sent ok */
return 1;
}
@@ -0,0 +1,188 @@
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <string.h>
#include <avr/interrupt.h>
#include "w5100.h"
// W5100 controller instance
W5100Class W5100;
#define TX_RX_MAX_BUF_SIZE 2048
#define TX_BUF 0x1100
#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
#define TXBUF_BASE 0x4000
#define RXBUF_BASE 0x6000
void W5100Class::init(void)
{
delay(300);
SPI.begin();
initSS();
writeMR(1<<RST);
writeTMSR(0x55);
writeRMSR(0x55);
for (int i=0; i<MAX_SOCK_NUM; i++) {
SBASE[i] = TXBUF_BASE + SSIZE * i;
RBASE[i] = RXBUF_BASE + RSIZE * i;
}
}
uint16_t W5100Class::getTXFreeSize(SOCKET s)
{
uint16_t val=0, val1=0;
do {
val1 = readSnTX_FSR(s);
if (val1 != 0)
val = readSnTX_FSR(s);
}
while (val != val1);
return val;
}
uint16_t W5100Class::getRXReceivedSize(SOCKET s)
{
uint16_t val=0,val1=0;
do {
val1 = readSnRX_RSR(s);
if (val1 != 0)
val = readSnRX_RSR(s);
}
while (val != val1);
return val;
}
void W5100Class::send_data_processing(SOCKET s, const uint8_t *data, uint16_t len)
{
// This is same as having no offset in a call to send_data_processing_offset
send_data_processing_offset(s, 0, data, len);
}
void W5100Class::send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len)
{
uint16_t ptr = readSnTX_WR(s);
ptr += data_offset;
uint16_t offset = ptr & SMASK;
uint16_t dstAddr = offset + SBASE[s];
if (offset + len > SSIZE)
{
// Wrap around circular buffer
uint16_t size = SSIZE - offset;
write(dstAddr, data, size);
write(SBASE[s], data + size, len - size);
}
else {
write(dstAddr, data, len);
}
ptr += len;
writeSnTX_WR(s, ptr);
}
void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
{
uint16_t ptr;
ptr = readSnRX_RD(s);
read_data(s, (uint8_t *)ptr, data, len);
if (!peek)
{
ptr += len;
writeSnRX_RD(s, ptr);
}
}
void W5100Class::read_data(SOCKET s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len)
{
uint16_t size;
uint16_t src_mask;
uint16_t src_ptr;
src_mask = (uint16_t)src & RMASK;
src_ptr = RBASE[s] + src_mask;
if( (src_mask + len) > RSIZE )
{
size = RSIZE - src_mask;
read(src_ptr, (uint8_t *)dst, size);
dst += size;
read(RBASE[s], (uint8_t *) dst, len - size);
}
else
read(src_ptr, (uint8_t *) dst, len);
}
uint8_t W5100Class::write(uint16_t _addr, uint8_t _data)
{
setSS();
SPI.transfer(0xF0);
SPI.transfer(_addr >> 8);
SPI.transfer(_addr & 0xFF);
SPI.transfer(_data);
resetSS();
return 1;
}
uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len)
{
for (uint16_t i=0; i<_len; i++)
{
setSS();
SPI.transfer(0xF0);
SPI.transfer(_addr >> 8);
SPI.transfer(_addr & 0xFF);
_addr++;
SPI.transfer(_buf[i]);
resetSS();
}
return _len;
}
uint8_t W5100Class::read(uint16_t _addr)
{
setSS();
SPI.transfer(0x0F);
SPI.transfer(_addr >> 8);
SPI.transfer(_addr & 0xFF);
uint8_t _data = SPI.transfer(0);
resetSS();
return _data;
}
uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
{
for (uint16_t i=0; i<_len; i++)
{
setSS();
SPI.transfer(0x0F);
SPI.transfer(_addr >> 8);
SPI.transfer(_addr & 0xFF);
_addr++;
_buf[i] = SPI.transfer(0);
resetSS();
}
return _len;
}
void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) {
// Send command to socket
writeSnCR(s, _cmd);
// Wait for command to complete
while (readSnCR(s))
;
}
@@ -0,0 +1,176 @@
/*
* w5100Wrapper.cpp
*
* Created on: 26 de Mai de 2013
* Author: mgf
*/
#include "w5100.h"
#include "w5100Wrapper.h"
extern "C"{
CSnMR * CSnMR_new(){
SnMR* s = new SnMR();
return (CSnMR*)s;
}
void CSnMR_delete(const CSnMR* obj){
SnMR* s = (SnMR*)obj;
delete s;
}
uint8_t SnMR_CLOSE(){ return SnMR::CLOSE; }
uint8_t SnMR_UDP(){ return SnMR::UDP; }
uint8_t SnMR_TCP(){ return SnMR::TCP; }
uint8_t SnMR_IPRAW(){ return SnMR::IPRAW; }
uint8_t SnMR_MACRAW(){ return SnMR::MACRAW; }
uint8_t SnMR_PPPOE(){ return SnMR::PPPOE; }
uint8_t SnMR_ND(){ return SnMR::ND; }
uint8_t SnMR_MULTI(){ return SnMR::MULTI; }
CSnIR * CSnIR_new(){
SnIR* s = new SnIR();
return (CSnIR*) s;
}
void CSnIR_delete(const CSnIR* obj){
SnIR* s = (SnIR*)obj;
delete s;
}
uint8_t SnIR_SEND_OK(){ return SnIR::SEND_OK; }
uint8_t SnIR_TIMEOUT(){ return SnIR::TIMEOUT; }
uint8_t SnIR_RECV(){ return SnIR::RECV; }
uint8_t SnIR_DISCON(){ return SnIR::DISCON; }
uint8_t SnIR_CON(){ return SnIR::CON; }
CSnSR * CSnSR_new(){
SnSR* s = new SnSR();
return (CSnSR*) s;
}
void CSnSR_delete(const CSnSR* obj){
SnSR* s = (SnSR*)obj;
delete s;
}
uint8_t SnSR_CLOSED(){ return SnSR::CLOSED; }
uint8_t SnSR_INIT(){ return SnSR::INIT; }
uint8_t SnSR_LISTEN(){ return SnSR::LISTEN; }
uint8_t SnSR_SYNSENT(){ return SnSR::SYNSENT; }
uint8_t SnSR_SYNRECV(){ return SnSR::SYNRECV; }
uint8_t SnSR_ESTABLISHED(){ return SnSR::ESTABLISHED; }
uint8_t SnSR_FIN_WAIT(){ return SnSR::FIN_WAIT; }
uint8_t SnSR_CLOSING(){ return SnSR::CLOSING; }
uint8_t SnSR_TIME_WAIT(){ return SnSR::TIME_WAIT; }
uint8_t SnSR_CLOSE_WAIT(){ return SnSR::CLOSE_WAIT; }
uint8_t SnSR_LAST_ACK(){ return SnSR::LAST_ACK; }
uint8_t SnSR_UDP(){ return SnSR::UDP; }
uint8_t SnSR_IPRAW(){ return SnSR::IPRAW; }
uint8_t SnSR_MACRAW(){ return SnSR::MACRAW; }
uint8_t SnSR_PPPOE(){ return SnSR::PPPOE; }
CIPPROTO * CIPPROTO_new(){
IPPROTO* i = new IPPROTO();
return (CIPPROTO*) i;
}
void CIPPROTO_delete(const CIPPROTO* obj){
IPPROTO* i = (IPPROTO*) obj;
delete i;
}
uint8_t IPPROTO_IP(){ return IPPROTO::IP; }
uint8_t IPPROTO_ICMP(){ return IPPROTO::ICMP; }
uint8_t IPPROTO_IGMP(){ return IPPROTO::IGMP; }
uint8_t IPPROTO_GGP(){ return IPPROTO::GGP; }
uint8_t IPPROTO_TCP(){ return IPPROTO::TCP; }
uint8_t IPPROTO_PUP(){ return IPPROTO::PUP; }
uint8_t IPPROTO_UDP(){ return IPPROTO::UDP; }
uint8_t IPPROTO_IDP(){ return IPPROTO::IDP; }
uint8_t IPPROTO_ND(){ return IPPROTO::ND; }
uint8_t IPPROTO_RAW(){ return IPPROTO::RAW; }
CW5100Class * CW5100Class_new(){
return (CW5100Class*) &W5100;
}
void init_func(const CW5100Class * obj){
W5100Class* w = (W5100Class*) obj;
w->init();
}
void read_data_func(const CW5100Class * obj, SOCKET s, volatile uint8_t * src, volatile uint8_t * dst,
uint16_t len){
W5100Class* w = (W5100Class*) obj;
w->read_data(s, src, dst, len);
}
void send_data_processing_func(const CW5100Class * obj, SOCKET s, const uint8_t *data, uint16_t len){
W5100Class* w = (W5100Class*) obj;
w->send_data_processing(s, data, len);
}
void send_data_processing_offset_func(const CW5100Class * obj, SOCKET s, uint16_t data_offset,
const uint8_t *data, uint16_t len){
W5100Class* w = (W5100Class*) obj;
w->send_data_processing_offset(s, data_offset, data, len);
}
//FIXME: Removed defaul value of 0(zero) from the peek argument
void recv_data_processing_func(const CW5100Class * obj, SOCKET s, uint8_t *data, uint16_t len,
uint8_t peek){
W5100Class* w = (W5100Class*) obj;
w->recv_data_processing(s, data, len, peek);
}
void setGatewayIp_func(const CW5100Class * obj, uint8_t *_addr){
W5100Class* w = (W5100Class*) obj;
w->setGatewayIp(_addr);
}
void getGatewayIp_func(const CW5100Class * obj, uint8_t *_addr){
W5100Class* w = (W5100Class*) obj;
w->getGatewayIp(_addr);
}
void setSubnetMask_func(const CW5100Class * obj, uint8_t *_addr){
W5100Class* w = (W5100Class*) obj;
w->setSubnetMask(_addr);
}
void getSubnetMask_func(const CW5100Class * obj, uint8_t *_addr){
W5100Class* w = (W5100Class*) obj;
w->getSubnetMask(_addr);
}
void setMACAddress_func(const CW5100Class * obj, uint8_t * addr){
W5100Class* w = (W5100Class*) obj;
w->setMACAddress(addr);
}
void getMACAddress_func(const CW5100Class * obj, uint8_t * addr){
W5100Class* w = (W5100Class*) obj;
w->getMACAddress(addr);
}
void setIPAddress_func(const CW5100Class * obj, uint8_t * addr){
W5100Class* w = (W5100Class*) obj;
w->setIPAddress(addr);
}
void getIPAddress_func(const CW5100Class * obj, uint8_t * addr){
W5100Class* w = (W5100Class*) obj;
w->getIPAddress(addr);
}
void setRetransmissionTime_func(const CW5100Class * obj, uint16_t timeout){
W5100Class* w = (W5100Class*) obj;
w->setRetransmissionTime(timeout);
}
void setRetransmissionCount_func(const CW5100Class * obj, uint8_t _retry){
W5100Class* w = (W5100Class*) obj;
w->setRetransmissionCount(_retry);
}
uint16_t getTXFreeSize_func(const CW5100Class * obj,SOCKET s){
W5100Class* w = (W5100Class*) obj;
return w->getTXFreeSize(s);
}
uint16_t getRXReceivedSize_func(const CW5100Class * obj,SOCKET s){
W5100Class* w = (W5100Class*) obj;
return w->getRXReceivedSize(s);
}
uint8_t readSnSR_func(const CW5100Class* obj, SOCKET s){
W5100Class* w = (W5100Class*) obj;
return w->readSnSR(s);
}
}//externC
@@ -0,0 +1,235 @@
#ifndef Arduino_h
#define Arduino_h
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "binary.h"
#ifdef __cplusplus
extern "C" {
#endif
#define HIGH 0x1
#define LOW 0x0
#define INPUT 0x0
#define OUTPUT 0x1
#define INPUT_PULLUP 0x2
#define true 0x1
#define false 0x0
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105
#define SERIAL 0x0
#define DISPLAY 0x1
#define LSBFIRST 0
#define MSBFIRST 1
#define CHANGE 1
#define FALLING 2
#define RISING 3
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#define DEFAULT 0
#define EXTERNAL 1
#define INTERNAL 2
#else
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__)
#define INTERNAL1V1 2
#define INTERNAL2V56 3
#else
#define INTERNAL 3
#endif
#define DEFAULT 1
#define EXTERNAL 0
#endif
// undefine stdlib's abs if encountered
#ifdef abs
#undef abs
#endif
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))
#define interrupts() sei()
#define noInterrupts() cli()
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
typedef unsigned int word;
#define bit(b) (1UL << (b))
typedef uint8_t boolean;
typedef uint8_t byte;
void init(void);
void pinMode(uint8_t,
uint8_t);
void digitalWrite(uint8_t,
uint8_t);
int digitalRead(uint8_t);
int analogRead(uint8_t);
void analogReference(uint8_t mode);
void analogWrite(uint8_t,
int);
unsigned long millis(void);
unsigned long micros(void);
void delay(unsigned long);
void delayMicroseconds(unsigned int us);
unsigned long pulseIn(uint8_t pin,
uint8_t state,
unsigned long timeout);
void shiftOut(uint8_t dataPin,
uint8_t clockPin,
uint8_t bitOrder,
uint8_t val);
uint8_t shiftIn(uint8_t dataPin,
uint8_t clockPin,
uint8_t bitOrder);
void attachInterrupt(uint8_t,
void (*)(void),
int mode);
void detachInterrupt(uint8_t);
void setup(void);
void loop(void);
// Get the bit location within the hardware port of the given virtual pin.
// This comes from the pins_*.c file for the active board configuration.
#define analogInPinToBit(P) (P)
// On the ATmega1280, the addresses of some of the port registers are
// greater than 255, so we can't store them in uint8_t's.
extern const uint16_t PROGMEM port_to_mode_PGM[];
extern const uint16_t PROGMEM port_to_input_PGM[];
extern const uint16_t PROGMEM port_to_output_PGM[];
extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[];
extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
// Get the bit location within the hardware port of the given virtual pin.
// This comes from the pins_*.c file for the active board configuration.
//
// These perform slightly better as macros compared to inline functions
//
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
#define analogInPinToBit(P) (P)
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
#define NOT_A_PIN 0
#define NOT_A_PORT 0
#ifdef ARDUINO_MAIN
#define PA 1
#define PB 2
#define PC 3
#define PD 4
#define PE 5
#define PF 6
#define PG 7
#define PH 8
#define PJ 10
#define PK 11
#define PL 12
#endif
#define NOT_ON_TIMER 0
#define TIMER0A 1
#define TIMER0B 2
#define TIMER1A 3
#define TIMER1B 4
#define TIMER2 5
#define TIMER2A 6
#define TIMER2B 7
#define TIMER3A 8
#define TIMER3B 9
#define TIMER3C 10
#define TIMER4A 11
#define TIMER4B 12
#define TIMER4C 13
#define TIMER4D 14
#define TIMER5A 15
#define TIMER5B 16
#define TIMER5C 17
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
#include "WCharacter.h"
#include "WString.h"
#include "HardwareSerial.h"
uint16_t makeWord(uint16_t w);
uint16_t makeWord(byte h,
byte l);
#define word(...) makeWord(__VA_ARGS__)
unsigned long pulseIn(uint8_t pin,
uint8_t state,
unsigned long timeout = 1000000L);
void tone(uint8_t _pin,
unsigned int frequency,
unsigned long duration = 0);
void noTone(uint8_t _pin);
// WMath prototypes
long random(long);
long random(long,
long);
void randomSeed(unsigned int);
long map(long,
long,
long,
long,
long);
#endif
#include "pins_arduino.h"
#endif
@@ -0,0 +1,130 @@
/*
HardwareSerial.h - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
*/
#ifndef HardwareSerial_h
#define HardwareSerial_h
#include <inttypes.h>
#include "Stream.h"
struct ring_buffer;
class HardwareSerial:public Stream {
private:
ring_buffer * _rx_buffer;
ring_buffer *_tx_buffer;
volatile uint8_t *_ubrrh;
volatile uint8_t *_ubrrl;
volatile uint8_t *_ucsra;
volatile uint8_t *_ucsrb;
volatile uint8_t *_ucsrc;
volatile uint8_t *_udr;
uint8_t _rxen;
uint8_t _txen;
uint8_t _rxcie;
uint8_t _udrie;
uint8_t _u2x;
bool transmitting;
public:
HardwareSerial(ring_buffer * rx_buffer,
ring_buffer * tx_buffer,
volatile uint8_t * ubrrh,
volatile uint8_t * ubrrl,
volatile uint8_t * ucsra,
volatile uint8_t * ucsrb,
volatile uint8_t * ucsrc,
volatile uint8_t * udr,
uint8_t rxen,
uint8_t txen,
uint8_t rxcie,
uint8_t udrie,
uint8_t u2x);
void begin(unsigned long);
void begin(unsigned long,
uint8_t);
void end();
virtual int available(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t);
inline size_t write(unsigned long n) {
return write((uint8_t) n);
} inline size_t write(long n) {
return write((uint8_t) n);
}
inline size_t write(unsigned int n) {
return write((uint8_t) n);
}
inline size_t write(int n) {
return write((uint8_t) n);
}
using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool();
};
// Define config for Serial.begin(baud, config);
#define SERIAL_5N1 0x00
#define SERIAL_6N1 0x02
#define SERIAL_7N1 0x04
#define SERIAL_8N1 0x06
#define SERIAL_5N2 0x08
#define SERIAL_6N2 0x0A
#define SERIAL_7N2 0x0C
#define SERIAL_8N2 0x0E
#define SERIAL_5E1 0x20
#define SERIAL_6E1 0x22
#define SERIAL_7E1 0x24
#define SERIAL_8E1 0x26
#define SERIAL_5E2 0x28
#define SERIAL_6E2 0x2A
#define SERIAL_7E2 0x2C
#define SERIAL_8E2 0x2E
#define SERIAL_5O1 0x30
#define SERIAL_6O1 0x32
#define SERIAL_7O1 0x34
#define SERIAL_8O1 0x36
#define SERIAL_5O2 0x38
#define SERIAL_6O2 0x3A
#define SERIAL_7O2 0x3C
#define SERIAL_8O2 0x3E
#if defined(UBRRH) || defined(UBRR0H)
extern HardwareSerial Serial;
#elif defined(USBCON)
#include "USBAPI.h"
// extern HardwareSerial Serial_;
#endif
#if defined(UBRR1H)
extern HardwareSerial Serial1;
#endif
#if defined(UBRR2H)
extern HardwareSerial Serial2;
#endif
#if defined(UBRR3H)
extern HardwareSerial Serial3;
#endif
extern void serialEventRun(void) __attribute__ ((weak));
#endif
@@ -0,0 +1,9 @@
#ifndef server_h
#define server_h
class Server:public Print {
public:
virtual void begin() = 0;
};
#endif
@@ -0,0 +1,202 @@
#ifndef __USBAPI__
#define __USBAPI__
#if defined(USBCON)
//================================================================================
//================================================================================
// USB
class USBDevice_ {
public:
USBDevice_();
bool configured();
void attach();
void detach(); // Serial port goes down too...
void poll();
};
extern USBDevice_ USBDevice;
//================================================================================
//================================================================================
// Serial over CDC (Serial1 is the physical port)
class Serial_:public Stream {
private:
ring_buffer * _cdc_rx_buffer;
public:
void begin(uint16_t baud_count);
void end(void);
virtual int available(void);
virtual void accept(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t);
using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool();
};
extern Serial_ Serial;
//================================================================================
//================================================================================
// Mouse
#define MOUSE_LEFT 1
#define MOUSE_RIGHT 2
#define MOUSE_MIDDLE 4
#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)
class Mouse_ {
private:
uint8_t _buttons;
void buttons(uint8_t b);
public:
Mouse_(void);
void begin(void);
void end(void);
void click(uint8_t b = MOUSE_LEFT);
void move(signed char x,
signed char y,
signed char wheel = 0);
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
};
extern Mouse_ Mouse;
//================================================================================
//================================================================================
// Keyboard
#define KEY_LEFT_CTRL 0x80
#define KEY_LEFT_SHIFT 0x81
#define KEY_LEFT_ALT 0x82
#define KEY_LEFT_GUI 0x83
#define KEY_RIGHT_CTRL 0x84
#define KEY_RIGHT_SHIFT 0x85
#define KEY_RIGHT_ALT 0x86
#define KEY_RIGHT_GUI 0x87
#define KEY_UP_ARROW 0xDA
#define KEY_DOWN_ARROW 0xD9
#define KEY_LEFT_ARROW 0xD8
#define KEY_RIGHT_ARROW 0xD7
#define KEY_BACKSPACE 0xB2
#define KEY_TAB 0xB3
#define KEY_RETURN 0xB0
#define KEY_ESC 0xB1
#define KEY_INSERT 0xD1
#define KEY_DELETE 0xD4
#define KEY_PAGE_UP 0xD3
#define KEY_PAGE_DOWN 0xD6
#define KEY_HOME 0xD2
#define KEY_END 0xD5
#define KEY_CAPS_LOCK 0xC1
#define KEY_F1 0xC2
#define KEY_F2 0xC3
#define KEY_F3 0xC4
#define KEY_F4 0xC5
#define KEY_F5 0xC6
#define KEY_F6 0xC7
#define KEY_F7 0xC8
#define KEY_F8 0xC9
#define KEY_F9 0xCA
#define KEY_F10 0xCB
#define KEY_F11 0xCC
#define KEY_F12 0xCD
// Low level key report: up to 6 keys and shift, ctrl etc at once
typedef struct {
uint8_t modifiers;
uint8_t reserved;
uint8_t keys[6];
} KeyReport;
class Keyboard_:public Print {
private:
KeyReport _keyReport;
void sendReport(KeyReport * keys);
public:
Keyboard_(void);
void begin(void);
void end(void);
virtual size_t write(uint8_t k);
virtual size_t press(uint8_t k);
virtual size_t release(uint8_t k);
virtual void releaseAll(void);
};
extern Keyboard_ Keyboard;
//================================================================================
//================================================================================
// Low level API
typedef struct {
uint8_t bmRequestType;
uint8_t bRequest;
uint8_t wValueL;
uint8_t wValueH;
uint16_t wIndex;
uint16_t wLength;
} Setup;
//================================================================================
//================================================================================
// HID 'Driver'
int HID_GetInterface(uint8_t * interfaceNum);
int HID_GetDescriptor(int i);
bool HID_Setup(Setup & setup);
void HID_SendReport(uint8_t id,
const void *data,
int len);
//================================================================================
//================================================================================
// MSC 'Driver'
int MSC_GetInterface(uint8_t * interfaceNum);
int MSC_GetDescriptor(int i);
bool MSC_Setup(Setup & setup);
bool MSC_Data(uint8_t rx,
uint8_t tx);
//================================================================================
//================================================================================
// CSC 'Driver'
int CDC_GetInterface(uint8_t * interfaceNum);
int CDC_GetDescriptor(int i);
bool CDC_Setup(Setup & setup);
//================================================================================
//================================================================================
#define TRANSFER_PGM 0x80
#define TRANSFER_RELEASE 0x40
#define TRANSFER_ZERO 0x20
int USB_SendControl(uint8_t flags,
const void *d,
int len);
int USB_RecvControl(void *d,
int len);
uint8_t USB_Available(uint8_t ep);
int USB_Send(uint8_t ep,
const void *data,
int len); // blocking
int USB_Recv(uint8_t ep,
void *data,
int len); // non-blocking
int USB_Recv(uint8_t ep); // non-blocking
void USB_Flush(uint8_t ep);
#endif
#endif /* if defined(USBCON) */
@@ -0,0 +1,292 @@
// Copyright (c) 2010, Peter Barrett
/*
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
#ifndef __USBCORE_H__
#define __USBCORE_H__
// Standard requests
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define SET_DESCRIPTOR 7
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11
// bmRequestType
#define REQUEST_HOSTTODEVICE 0x00
#define REQUEST_DEVICETOHOST 0x80
#define REQUEST_DIRECTION 0x80
#define REQUEST_STANDARD 0x00
#define REQUEST_CLASS 0x20
#define REQUEST_VENDOR 0x40
#define REQUEST_TYPE 0x60
#define REQUEST_DEVICE 0x00
#define REQUEST_INTERFACE 0x01
#define REQUEST_ENDPOINT 0x02
#define REQUEST_OTHER 0x03
#define REQUEST_RECIPIENT 0x03
#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST + REQUEST_CLASS + REQUEST_INTERFACE)
#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE + REQUEST_CLASS + REQUEST_INTERFACE)
// Class requests
#define CDC_SET_LINE_CODING 0x20
#define CDC_GET_LINE_CODING 0x21
#define CDC_SET_CONTROL_LINE_STATE 0x22
#define MSC_RESET 0xFF
#define MSC_GET_MAX_LUN 0xFE
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
#define HID_SET_REPORT 0x09
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B
// Descriptors
#define USB_DEVICE_DESC_SIZE 18
#define USB_CONFIGUARTION_DESC_SIZE 9
#define USB_INTERFACE_DESC_SIZE 9
#define USB_ENDPOINT_DESC_SIZE 7
#define USB_DEVICE_DESCRIPTOR_TYPE 1
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
#define USB_STRING_DESCRIPTOR_TYPE 3
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
#define USB_DEVICE_CLASS_STORAGE 0x08
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
#define USB_CONFIG_POWERED_MASK 0x40
#define USB_CONFIG_BUS_POWERED 0x80
#define USB_CONFIG_SELF_POWERED 0xC0
#define USB_CONFIG_REMOTE_WAKEUP 0x20
// bMaxPower in Configuration Descriptor
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
// bEndpointAddress in Endpoint Descriptor
#define USB_ENDPOINT_DIRECTION_MASK 0x80
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
#define USB_ENDPOINT_TYPE_MASK 0x03
#define USB_ENDPOINT_TYPE_CONTROL 0x00
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
#define USB_ENDPOINT_TYPE_BULK 0x02
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
#define TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
#define CDC_V1_10 0x0110
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
#define CDC_CALL_MANAGEMENT 0x01
#define CDC_ABSTRACT_CONTROL_MODEL 0x02
#define CDC_HEADER 0x00
#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
#define CDC_UNION 0x06
#define CDC_CS_INTERFACE 0x24
#define CDC_CS_ENDPOINT 0x25
#define CDC_DATA_INTERFACE_CLASS 0x0A
#define MSC_SUBCLASS_SCSI 0x06
#define MSC_PROTOCOL_BULK_ONLY 0x50
#define HID_HID_DESCRIPTOR_TYPE 0x21
#define HID_REPORT_DESCRIPTOR_TYPE 0x22
#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23
// Device
typedef struct {
u8 len; // 18
u8 dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE
u16 usbVersion; // 0x200
u8 deviceClass;
u8 deviceSubClass;
u8 deviceProtocol;
u8 packetSize0; // Packet 0
u16 idVendor;
u16 idProduct;
u16 deviceVersion; // 0x100
u8 iManufacturer;
u8 iProduct;
u8 iSerialNumber;
u8 bNumConfigurations;
} DeviceDescriptor;
// Config
typedef struct {
u8 len; // 9
u8 dtype; // 2
u16 clen; // total length
u8 numInterfaces;
u8 config;
u8 iconfig;
u8 attributes;
u8 maxPower;
} ConfigDescriptor;
// String
// Interface
typedef struct {
u8 len; // 9
u8 dtype; // 4
u8 number;
u8 alternate;
u8 numEndpoints;
u8 interfaceClass;
u8 interfaceSubClass;
u8 protocol;
u8 iInterface;
} InterfaceDescriptor;
// Endpoint
typedef struct {
u8 len; // 7
u8 dtype; // 5
u8 addr;
u8 attr;
u16 packetSize;
u8 interval;
} EndpointDescriptor;
// Interface Association Descriptor
// Used to bind 2 interfaces together in CDC compostite device
typedef struct {
u8 len; // 8
u8 dtype; // 11
u8 firstInterface;
u8 interfaceCount;
u8 functionClass;
u8 funtionSubClass;
u8 functionProtocol;
u8 iInterface;
} IADDescriptor;
// CDC CS interface descriptor
typedef struct {
u8 len; // 5
u8 dtype; // 0x24
u8 subtype;
u8 d0;
u8 d1;
} CDCCSInterfaceDescriptor;
typedef struct {
u8 len; // 4
u8 dtype; // 0x24
u8 subtype;
u8 d0;
} CDCCSInterfaceDescriptor4;
typedef struct {
u8 len;
u8 dtype; // 0x24
u8 subtype; // 1
u8 bmCapabilities;
u8 bDataInterface;
} CMFunctionalDescriptor;
typedef struct {
u8 len;
u8 dtype; // 0x24
u8 subtype; // 1
u8 bmCapabilities;
} ACMFunctionalDescriptor;
typedef struct {
// IAD
IADDescriptor iad; // Only needed on compound device
// Control
InterfaceDescriptor cif; //
CDCCSInterfaceDescriptor header;
CMFunctionalDescriptor callManagement; // Call Management
ACMFunctionalDescriptor controlManagement; // ACM
CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION
EndpointDescriptor cifin;
// Data
InterfaceDescriptor dif;
EndpointDescriptor in;
EndpointDescriptor out;
} CDCDescriptor;
typedef struct {
InterfaceDescriptor msc;
EndpointDescriptor in;
EndpointDescriptor out;
} MSCDescriptor;
typedef struct {
u8 len; // 9
u8 dtype; // 0x21
u8 addr;
u8 versionL; // 0x101
u8 versionH; // 0x101
u8 country;
u8 desctype; // 0x22 report
u8 descLenL;
u8 descLenH;
} HIDDescDescriptor;
typedef struct {
InterfaceDescriptor hid;
HIDDescDescriptor desc;
EndpointDescriptor in;
} HIDDescriptor;
#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \
{ 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }
#define D_CONFIG(_totalLength,_interfaces) \
{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(500) }
#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \
{ 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 }
#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \
{ 7, 5, _addr,_attr,_packetSize, _interval }
#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \
{ 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 }
#define D_HIDREPORT(_descriptorLength) \
{ 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 }
#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
#endif
@@ -0,0 +1,95 @@
/*
* Udp.cpp: Library to send/receive UDP packets.
*
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
* might not happen often in practice, but in larger network topologies, a UDP
* packet can be received out of sequence.
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
* aware of it. Again, this may not be a concern in practice on small local networks.
* For more information, see http://www.cafeaulait.org/course/week12/35.html
*
* MIT License:
* Copyright (c) 2008 Bjoern Hartmann
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* bjoern@cs.stanford.edu 12/30/2008
*/
#ifndef udp_h
#define udp_h
#include <Stream.h>
#include <IPAddress.h>
class UDP:public Stream {
public:
virtual uint8_t begin(uint16_t) = 0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
virtual void stop() = 0; // Finish with the UDP socket
// Sending UDP packets
// Start building up a packet to send to the remote host specific in ip and port
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
virtual int beginPacket(IPAddress ip,
uint16_t port) = 0;
// Start building up a packet to send to the remote host specific in host and port
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
virtual int beginPacket(const char *host,
uint16_t port) = 0;
// Finish off this packet and send it
// Returns 1 if the packet was sent successfully, 0 if there was an error
virtual int endPacket() = 0;
// Write a single byte into the packet
virtual size_t write(uint8_t) = 0;
// Write size bytes from buffer into the packet
virtual size_t write(const uint8_t * buffer,
size_t size) = 0;
// Start processing the next available incoming packet
// Returns the size of the packet in bytes, or 0 if no packets are available
virtual int parsePacket() = 0;
// Number of bytes remaining in the current packet
virtual int available() = 0;
// Read a single byte from the current packet
virtual int read() = 0;
// Read up to len bytes from the current packet and place them into buffer
// Returns the number of bytes read, or 0 if none are available
virtual int read(unsigned char *buffer,
size_t len) = 0;
// Read up to len characters from the current packet and place them into buffer
// Returns the number of characters read, or 0 if none are available
virtual int read(char *buffer,
size_t len) = 0;
// Return the next byte from the current packet without moving on to the next byte
virtual int peek() = 0;
virtual void flush() = 0; // Finish reading the current packet
// Return the IP address of the host who sent the current incoming packet
virtual IPAddress remoteIP() = 0;
// Return the port of the host who sent the current incoming packet
virtual uint16_t remotePort() = 0;
protected:
uint8_t * rawIPAddress(IPAddress & addr) {
return addr.raw_address();
};
};
#endif
@@ -0,0 +1,515 @@
#ifndef Binary_h
#define Binary_h
#define B0 0
#define B00 0
#define B000 0
#define B0000 0
#define B00000 0
#define B000000 0
#define B0000000 0
#define B00000000 0
#define B1 1
#define B01 1
#define B001 1
#define B0001 1
#define B00001 1
#define B000001 1
#define B0000001 1
#define B00000001 1
#define B10 2
#define B010 2
#define B0010 2
#define B00010 2
#define B000010 2
#define B0000010 2
#define B00000010 2
#define B11 3
#define B011 3
#define B0011 3
#define B00011 3
#define B000011 3
#define B0000011 3
#define B00000011 3
#define B100 4
#define B0100 4
#define B00100 4
#define B000100 4
#define B0000100 4
#define B00000100 4
#define B101 5
#define B0101 5
#define B00101 5
#define B000101 5
#define B0000101 5
#define B00000101 5
#define B110 6
#define B0110 6
#define B00110 6
#define B000110 6
#define B0000110 6
#define B00000110 6
#define B111 7
#define B0111 7
#define B00111 7
#define B000111 7
#define B0000111 7
#define B00000111 7
#define B1000 8
#define B01000 8
#define B001000 8
#define B0001000 8
#define B00001000 8
#define B1001 9
#define B01001 9
#define B001001 9
#define B0001001 9
#define B00001001 9
#define B1010 10
#define B01010 10
#define B001010 10
#define B0001010 10
#define B00001010 10
#define B1011 11
#define B01011 11
#define B001011 11
#define B0001011 11
#define B00001011 11
#define B1100 12
#define B01100 12
#define B001100 12
#define B0001100 12
#define B00001100 12
#define B1101 13
#define B01101 13
#define B001101 13
#define B0001101 13
#define B00001101 13
#define B1110 14
#define B01110 14
#define B001110 14
#define B0001110 14
#define B00001110 14
#define B1111 15
#define B01111 15
#define B001111 15
#define B0001111 15
#define B00001111 15
#define B10000 16
#define B010000 16
#define B0010000 16
#define B00010000 16
#define B10001 17
#define B010001 17
#define B0010001 17
#define B00010001 17
#define B10010 18
#define B010010 18
#define B0010010 18
#define B00010010 18
#define B10011 19
#define B010011 19
#define B0010011 19
#define B00010011 19
#define B10100 20
#define B010100 20
#define B0010100 20
#define B00010100 20
#define B10101 21
#define B010101 21
#define B0010101 21
#define B00010101 21
#define B10110 22
#define B010110 22
#define B0010110 22
#define B00010110 22
#define B10111 23
#define B010111 23
#define B0010111 23
#define B00010111 23
#define B11000 24
#define B011000 24
#define B0011000 24
#define B00011000 24
#define B11001 25
#define B011001 25
#define B0011001 25
#define B00011001 25
#define B11010 26
#define B011010 26
#define B0011010 26
#define B00011010 26
#define B11011 27
#define B011011 27
#define B0011011 27
#define B00011011 27
#define B11100 28
#define B011100 28
#define B0011100 28
#define B00011100 28
#define B11101 29
#define B011101 29
#define B0011101 29
#define B00011101 29
#define B11110 30
#define B011110 30
#define B0011110 30
#define B00011110 30
#define B11111 31
#define B011111 31
#define B0011111 31
#define B00011111 31
#define B100000 32
#define B0100000 32
#define B00100000 32
#define B100001 33
#define B0100001 33
#define B00100001 33
#define B100010 34
#define B0100010 34
#define B00100010 34
#define B100011 35
#define B0100011 35
#define B00100011 35
#define B100100 36
#define B0100100 36
#define B00100100 36
#define B100101 37
#define B0100101 37
#define B00100101 37
#define B100110 38
#define B0100110 38
#define B00100110 38
#define B100111 39
#define B0100111 39
#define B00100111 39
#define B101000 40
#define B0101000 40
#define B00101000 40
#define B101001 41
#define B0101001 41
#define B00101001 41
#define B101010 42
#define B0101010 42
#define B00101010 42
#define B101011 43
#define B0101011 43
#define B00101011 43
#define B101100 44
#define B0101100 44
#define B00101100 44
#define B101101 45
#define B0101101 45
#define B00101101 45
#define B101110 46
#define B0101110 46
#define B00101110 46
#define B101111 47
#define B0101111 47
#define B00101111 47
#define B110000 48
#define B0110000 48
#define B00110000 48
#define B110001 49
#define B0110001 49
#define B00110001 49
#define B110010 50
#define B0110010 50
#define B00110010 50
#define B110011 51
#define B0110011 51
#define B00110011 51
#define B110100 52
#define B0110100 52
#define B00110100 52
#define B110101 53
#define B0110101 53
#define B00110101 53
#define B110110 54
#define B0110110 54
#define B00110110 54
#define B110111 55
#define B0110111 55
#define B00110111 55
#define B111000 56
#define B0111000 56
#define B00111000 56
#define B111001 57
#define B0111001 57
#define B00111001 57
#define B111010 58
#define B0111010 58
#define B00111010 58
#define B111011 59
#define B0111011 59
#define B00111011 59
#define B111100 60
#define B0111100 60
#define B00111100 60
#define B111101 61
#define B0111101 61
#define B00111101 61
#define B111110 62
#define B0111110 62
#define B00111110 62
#define B111111 63
#define B0111111 63
#define B00111111 63
#define B1000000 64
#define B01000000 64
#define B1000001 65
#define B01000001 65
#define B1000010 66
#define B01000010 66
#define B1000011 67
#define B01000011 67
#define B1000100 68
#define B01000100 68
#define B1000101 69
#define B01000101 69
#define B1000110 70
#define B01000110 70
#define B1000111 71
#define B01000111 71
#define B1001000 72
#define B01001000 72
#define B1001001 73
#define B01001001 73
#define B1001010 74
#define B01001010 74
#define B1001011 75
#define B01001011 75
#define B1001100 76
#define B01001100 76
#define B1001101 77
#define B01001101 77
#define B1001110 78
#define B01001110 78
#define B1001111 79
#define B01001111 79
#define B1010000 80
#define B01010000 80
#define B1010001 81
#define B01010001 81
#define B1010010 82
#define B01010010 82
#define B1010011 83
#define B01010011 83
#define B1010100 84
#define B01010100 84
#define B1010101 85
#define B01010101 85
#define B1010110 86
#define B01010110 86
#define B1010111 87
#define B01010111 87
#define B1011000 88
#define B01011000 88
#define B1011001 89
#define B01011001 89
#define B1011010 90
#define B01011010 90
#define B1011011 91
#define B01011011 91
#define B1011100 92
#define B01011100 92
#define B1011101 93
#define B01011101 93
#define B1011110 94
#define B01011110 94
#define B1011111 95
#define B01011111 95
#define B1100000 96
#define B01100000 96
#define B1100001 97
#define B01100001 97
#define B1100010 98
#define B01100010 98
#define B1100011 99
#define B01100011 99
#define B1100100 100
#define B01100100 100
#define B1100101 101
#define B01100101 101
#define B1100110 102
#define B01100110 102
#define B1100111 103
#define B01100111 103
#define B1101000 104
#define B01101000 104
#define B1101001 105
#define B01101001 105
#define B1101010 106
#define B01101010 106
#define B1101011 107
#define B01101011 107
#define B1101100 108
#define B01101100 108
#define B1101101 109
#define B01101101 109
#define B1101110 110
#define B01101110 110
#define B1101111 111
#define B01101111 111
#define B1110000 112
#define B01110000 112
#define B1110001 113
#define B01110001 113
#define B1110010 114
#define B01110010 114
#define B1110011 115
#define B01110011 115
#define B1110100 116
#define B01110100 116
#define B1110101 117
#define B01110101 117
#define B1110110 118
#define B01110110 118
#define B1110111 119
#define B01110111 119
#define B1111000 120
#define B01111000 120
#define B1111001 121
#define B01111001 121
#define B1111010 122
#define B01111010 122
#define B1111011 123
#define B01111011 123
#define B1111100 124
#define B01111100 124
#define B1111101 125
#define B01111101 125
#define B1111110 126
#define B01111110 126
#define B1111111 127
#define B01111111 127
#define B10000000 128
#define B10000001 129
#define B10000010 130
#define B10000011 131
#define B10000100 132
#define B10000101 133
#define B10000110 134
#define B10000111 135
#define B10001000 136
#define B10001001 137
#define B10001010 138
#define B10001011 139
#define B10001100 140
#define B10001101 141
#define B10001110 142
#define B10001111 143
#define B10010000 144
#define B10010001 145
#define B10010010 146
#define B10010011 147
#define B10010100 148
#define B10010101 149
#define B10010110 150
#define B10010111 151
#define B10011000 152
#define B10011001 153
#define B10011010 154
#define B10011011 155
#define B10011100 156
#define B10011101 157
#define B10011110 158
#define B10011111 159
#define B10100000 160
#define B10100001 161
#define B10100010 162
#define B10100011 163
#define B10100100 164
#define B10100101 165
#define B10100110 166
#define B10100111 167
#define B10101000 168
#define B10101001 169
#define B10101010 170
#define B10101011 171
#define B10101100 172
#define B10101101 173
#define B10101110 174
#define B10101111 175
#define B10110000 176
#define B10110001 177
#define B10110010 178
#define B10110011 179
#define B10110100 180
#define B10110101 181
#define B10110110 182
#define B10110111 183
#define B10111000 184
#define B10111001 185
#define B10111010 186
#define B10111011 187
#define B10111100 188
#define B10111101 189
#define B10111110 190
#define B10111111 191
#define B11000000 192
#define B11000001 193
#define B11000010 194
#define B11000011 195
#define B11000100 196
#define B11000101 197
#define B11000110 198
#define B11000111 199
#define B11001000 200
#define B11001001 201
#define B11001010 202
#define B11001011 203
#define B11001100 204
#define B11001101 205
#define B11001110 206
#define B11001111 207
#define B11010000 208
#define B11010001 209
#define B11010010 210
#define B11010011 211
#define B11010100 212
#define B11010101 213
#define B11010110 214
#define B11010111 215
#define B11011000 216
#define B11011001 217
#define B11011010 218
#define B11011011 219
#define B11011100 220
#define B11011101 221
#define B11011110 222
#define B11011111 223
#define B11100000 224
#define B11100001 225
#define B11100010 226
#define B11100011 227
#define B11100100 228
#define B11100101 229
#define B11100110 230
#define B11100111 231
#define B11101000 232
#define B11101001 233
#define B11101010 234
#define B11101011 235
#define B11101100 236
#define B11101101 237
#define B11101110 238
#define B11101111 239
#define B11110000 240
#define B11110001 241
#define B11110010 242
#define B11110011 243
#define B11110100 244
#define B11110101 245
#define B11110110 246
#define B11110111 247
#define B11111000 248
#define B11111001 249
#define B11111010 250
#define B11111011 251
#define B11111100 252
#define B11111101 253
#define B11111110 254
#define B11111111 255
#endif
@@ -0,0 +1,21 @@
/* Header to define new/delete operators as they aren't provided by avr-gcc by default
Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453
*/
#ifndef NEW_H
#define NEW_H
#include <stdlib.h>
void *operator new(size_t size);
void operator delete(void *ptr);
__extension__ typedef int __guard __attribute__ ((mode(__DI__)));
extern "C" int __cxa_guard_acquire(__guard *);
extern "C" void __cxa_guard_release(__guard *);
extern "C" void __cxa_guard_abort(__guard *);
extern "C" void __cxa_pure_virtual(void);
#endif
@@ -0,0 +1,218 @@
/*
pins_arduino.h - Pin definition functions for Arduino
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2007 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
*/
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <avr/pgmspace.h>
#define NUM_DIGITAL_PINS 20
#define NUM_ANALOG_INPUTS 6
#define analogInputToDigitalPin(p) ((p < 6) ? (p) + 14 : -1)
#if defined(__AVR_ATmega8__)
#define digitalPinHasPWM(p) ((p) == 9 || (p) == 10 || (p) == 11)
#else
#define digitalPinHasPWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11)
#endif
static const uint8_t SS = 10;
static const uint8_t MOSI = 11;
static const uint8_t MISO = 12;
static const uint8_t SCK = 13;
static const uint8_t SDA = 18;
static const uint8_t SCL = 19;
static const uint8_t LED_BUILTIN = 13;
static const uint8_t A0 = 14;
static const uint8_t A1 = 15;
static const uint8_t A2 = 16;
static const uint8_t A3 = 17;
static const uint8_t A4 = 18;
static const uint8_t A5 = 19;
static const uint8_t A6 = 20;
static const uint8_t A7 = 21;
#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)0))
#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1))
#define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0))))
#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14)))
#ifdef ARDUINO_MAIN
// On the Arduino board, digital pins are also used
// for the analog output (software PWM). Analog input
// pins are a separate set.
// ATMEL ATMEGA8 & 168 / ARDUINO
//
// +-\/-+
// PC6 1| |28 PC5 (AI 5)
// (D 0) PD0 2| |27 PC4 (AI 4)
// (D 1) PD1 3| |26 PC3 (AI 3)
// (D 2) PD2 4| |25 PC2 (AI 2)
// PWM+ (D 3) PD3 5| |24 PC1 (AI 1)
// (D 4) PD4 6| |23 PC0 (AI 0)
// VCC 7| |22 GND
// GND 8| |21 AREF
// PB6 9| |20 AVCC
// PB7 10| |19 PB5 (D 13)
// PWM+ (D 5) PD5 11| |18 PB4 (D 12)
// PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM
// (D 7) PD7 13| |16 PB2 (D 10) PWM
// (D 8) PB0 14| |15 PB1 (D 9) PWM
// +----+
//
// (PWM+ indicates the additional PWM pins on the ATmega168.)
// ATMEL ATMEGA1280 / ARDUINO
//
// 0-7 PE0-PE7 works
// 8-13 PB0-PB5 works
// 14-21 PA0-PA7 works
// 22-29 PH0-PH7 works
// 30-35 PG5-PG0 works
// 36-43 PC7-PC0 works
// 44-51 PJ7-PJ0 works
// 52-59 PL7-PL0 works
// 60-67 PD7-PD0 works
// A0-A7 PF0-PF7
// A8-A15 PK0-PK7
// these arrays map port names (e.g. port B) to the
// appropriate addresses for various functions (e.g. reading
// and writing)
const uint16_t PROGMEM port_to_mode_PGM[] = {
NOT_A_PORT,
NOT_A_PORT,
(uint16_t) & DDRB,
(uint16_t) & DDRC,
(uint16_t) & DDRD,
};
const uint16_t PROGMEM port_to_output_PGM[] = {
NOT_A_PORT,
NOT_A_PORT,
(uint16_t) & PORTB,
(uint16_t) & PORTC,
(uint16_t) & PORTD,
};
const uint16_t PROGMEM port_to_input_PGM[] = {
NOT_A_PORT,
NOT_A_PORT,
(uint16_t) & PINB,
(uint16_t) & PINC,
(uint16_t) & PIND,
};
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, /* 0 */
PD,
PD,
PD,
PD,
PD,
PD,
PD,
PB, /* 8 */
PB,
PB,
PB,
PB,
PB,
PC, /* 14 */
PC,
PC,
PC,
PC,
PC,
};
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
_BV(0), /* 0, port D */
_BV(1),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
_BV(6),
_BV(7),
_BV(0), /* 8, port B */
_BV(1),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
_BV(0), /* 14, port C */
_BV(1),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
};
const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
NOT_ON_TIMER, /* 0 - port D */
NOT_ON_TIMER,
NOT_ON_TIMER,
// on the ATmega168, digital pin 3 has hardware pwm
#if defined(__AVR_ATmega8__)
NOT_ON_TIMER,
#else
TIMER2B,
#endif
NOT_ON_TIMER,
// on the ATmega168, digital pins 5 and 6 have hardware pwm
#if defined(__AVR_ATmega8__)
NOT_ON_TIMER,
NOT_ON_TIMER,
#else
TIMER0B,
TIMER0A,
#endif
NOT_ON_TIMER,
NOT_ON_TIMER, /* 8 - port B */
TIMER1A,
TIMER1B,
#if defined(__AVR_ATmega8__)
TIMER2,
#else
TIMER2A,
#endif
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER, /* 14 - port C */
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
};
#endif
#endif
@@ -0,0 +1,70 @@
/*
wiring_private.h - Internal header file.
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
*/
#ifndef WiringPrivate_h
#define WiringPrivate_h
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdarg.h>
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
#define EXTERNAL_INT_0 0
#define EXTERNAL_INT_1 1
#define EXTERNAL_INT_2 2
#define EXTERNAL_INT_3 3
#define EXTERNAL_INT_4 4
#define EXTERNAL_INT_5 5
#define EXTERNAL_INT_6 6
#define EXTERNAL_INT_7 7
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define EXTERNAL_NUM_INTERRUPTS 8
#elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__)
#define EXTERNAL_NUM_INTERRUPTS 3
#elif defined(__AVR_ATmega32U4__)
#define EXTERNAL_NUM_INTERRUPTS 4
#else
#define EXTERNAL_NUM_INTERRUPTS 2
#endif
typedef void (*voidFuncPtr) (void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+97
View File
@@ -0,0 +1,97 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "whois.h"
#include "iam.h"
#include "device.h"
#include "client.h"
#include "txbuf.h"
bool Send_I_Am_Flag = true;
void sendIamUnicast(uint8_t * buffer,
BACNET_ADDRESS * src)
{
BACNET_ADDRESS dest;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
/* encode the data */
int npdu_len = 0;
int apdu_len = 0;
BACNET_ADDRESS my_address;
/* The destination will be the same as the src, so copy it over. */
memcpy(&dest, src, sizeof(BACNET_ADDRESS));
/* dest->net = 0; - no, must direct back to src->net to meet BTL tests */
datalink_get_my_address(&my_address);
/* encode the NPDU portion of the packet */
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
npdu_len = npdu_encode_pdu(&buffer[0], &dest, &my_address, &npdu_data);
/* encode the APDU portion of the packet */
apdu_len =
iam_encode_apdu(&buffer[npdu_len], Device_Object_Instance_Number(),
MAX_APDU, SEGMENTATION_NONE, Device_Vendor_Identifier());
/* send data */
pdu_len = npdu_len + apdu_len;
int bytes = datalink_send_pdu(&dest, &npdu_data, &buffer[0], pdu_len);
}
void handler_who_is(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
int32_t low_limit = 0;
int32_t high_limit = 0;
int32_t target_device;
len =
whois_decode_service_request(service_request, service_len, &low_limit,
&high_limit);
if (len == 0) {
sendIamUnicast(&Handler_Transmit_Buffer[0], src);
} else if (len != -1) {
/* is my device id within the limits? */
target_device = Device_Object_Instance_Number();
if (((target_device >= low_limit) && (target_device <= high_limit))
||
/* BACnet wildcard is the max instance number - everyone responds */
((BACNET_MAX_INSTANCE >= (uint32_t) low_limit) &&
(BACNET_MAX_INSTANCE <= (uint32_t) high_limit))) {
sendIamUnicast(&Handler_Transmit_Buffer[0], src);
}
}
return;
}
+135
View File
@@ -0,0 +1,135 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
#include "wp.h"
/* demo objects */
#include "device.h"
#include "av.h"
#include "bv.h"
/* too big to reside on stack frame for PIC */
static BACNET_WRITE_PROPERTY_DATA wp_data;
void handler_write_property(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
BACNET_ADDRESS my_address;
/* decode the service request only */
len = wp_decode_service_request(service_request, service_len, &wp_data);
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
/* bad decoding or something we didn't understand - send an abort */
if (len <= 0) {
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
} else if (service_data->segmented_message) {
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
} else {
switch (wp_data.object_type) {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
break;
}
}
pdu_len += len;
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
return;
}
+94
View File
@@ -0,0 +1,94 @@
/**
* @file
* @author Miguel Fernandes <miguelandre.fernandes@gmail.com>
* @date 6 de Jun de 2013
* @brief BACnet/IP for Wiznet on Arduino-Uno
*
* This port is for BACnet/ip and uses part of the Arduino Ethernet
* library so it needs the stock Arduino Etherenet Shield
* (the one with the W5100 chip). The port was done by writting a C
* wrapper around the c++ Ethernet library and adapting the
* existing port for Atmega168 (mainly functions bip.c and bip-init.c)
* to use the wrapper functions. The port also needs Arduino core and
* Ethernet libraries to compile.
*/
#include <stdbool.h>
#include <stdint.h>
#include "datalink.h"
#include "npdu.h"
#include "handlers.h"
#include "txbuf.h"
#include "iam.h"
#include "device.h"
#include "av.h"
#include "uart.h"
#include "w5100Wrapper.h"
#include "Arduino.h"
#include <avr/io.h>
#define BAUD 9600
#include <util/setbaud.h>
/* From the WhoIs hander - performed by the DLMSTP module */
extern bool Send_I_Am_Flag;
/* local version override */
const char *BACnet_Version = "1.0";
static uint8_t Ethernet_MAC_Address[MAX_MAC_LEN] =
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
uint8_t ipAddress[] = { 192, 168, 0, 185 };
uint8_t gateway[] = { 192, 168, 0, 1 };
uint8_t netmask[] = { 255, 255, 255, 0 };
FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_getchar, _FDEV_SETUP_READ);
FILE uart_io = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
/* For porting to IAR, see:
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
/* dummy function - so we can use default demo handlers */
bool dcc_communication_enabled(void)
{
return true;
}
void setup()
{
//INIT W5100
init_func(CW5100Class_new());
setMACAddress_func(CW5100Class_new(), Ethernet_MAC_Address);
setIPAddress_func(CW5100Class_new(), ipAddress);
setGatewayIp_func(CW5100Class_new(), gateway);
setSubnetMask_func(CW5100Class_new(), netmask);
uart_init();
stdout = &uart_output;
stdin = &uart_input;
stderr = &uart_output;
#ifdef DEBUG
fprintf(stderr, "Starting BACNET application..\n");
#endif
}
static uint8_t PDUBuffer[MAX_MPDU];
int main(void)
{
uint16_t pdu_len = 0;
BACNET_ADDRESS src; /* source address */
init();
setup();
datalink_init(NULL);
for (;;) {
/* other tasks */
/* BACnet handling */
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
if (pdu_len) {
npdu_handler(&src, &PDUBuffer[0], pdu_len);
}
}
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef STDBOOL_H
#define STDBOOL_H
/* C99 Boolean types for compilers without C99 support */
#ifndef __cplusplus
/* typedef char _Bool; */
#ifndef bool
#define bool _Bool
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#define __bool_true_false_are_defined 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#endif
+15
View File
@@ -0,0 +1,15 @@
/* Defines the standard integer types that are used in code */
#ifndef STDINT_H
#define STDINT_H 1
#include <stddef.h>
typedef unsigned char uint8_t; /* 1 byte 0 to 255 */
typedef signed char int8_t; /* 1 byte -127 to 127 */
typedef unsigned short uint16_t; /* 2 bytes 0 to 65535 */
typedef signed short int16_t; /* 2 bytes -32767 to 32767 */
typedef unsigned long uint32_t; /* 4 bytes 0 to 4294967295 */
typedef signed long int32_t; /* 4 bytes -2147483647 to 2147483647 */
#endif /* STDINT_H */
+35
View File
@@ -0,0 +1,35 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef TXBUF_H
#define TXBUF_H
#include <stddef.h>
#include <stdint.h>
#include "config.h"
#include "datalink.h"
extern uint8_t Handler_Transmit_Buffer[MAX_PDU];
#endif