Fixing DOS/Unix/MAC EOL and line endings using fixup.sh script.

This commit is contained in:
skarg
2011-07-09 17:25:42 +00:00
parent 51c6134e15
commit ff393a665a
28 changed files with 8475 additions and 8475 deletions
+176 -176
View File
@@ -1,187 +1,187 @@
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* 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"
#include "wpm.h"
/* device object has the handling for all objects */
#include "device.h"
#include "handlers.h"
/** @file h_wpm.c Handles Write Property Multiple requests. */
/** Handler for a WriteProperty Service request.
* @ingroup DSWP
* This handler will be invoked by apdu_handler() if it has been enabled
* by a call to apdu_set_confirmed_handler().
* This handler builds a response packet, which is
* - an Abort if
* - the message is segmented
* - if decoding fails
* - an ACK if Device_Write_Property_Multiple() succeeds
* - an Error if Device_Write_PropertyMultiple() encounters an error
*
* @param service_request [in] The contents of the service request.
* @param service_len [in] The length of the service_request.
* @param src [in] BACNET_ADDRESS of the source of the message
* @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
* decoded from the APDU header of this message.
*/
void handler_write_property_multiple(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int apdu_len = 0;
int npdu_len = 0;
int pdu_len = 0;
int decode_len = 0;
bool error = false;
BACNET_WRITE_PROPERTY_DATA wp_data;
BACNET_NPDU_DATA npdu_data;
BACNET_ADDRESS my_address;
int bytes_sent = 0;
if (service_data->segmented_message) {
len = abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
#if PRINT_ENABLED
fprintf(stderr, "WPM: Segmented message. Sending Abort!\n");
#endif
goto WPM_ABORT;
}
/* decode service request */
decode_len = 0;
do
{
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* 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"
#include "wpm.h"
/* device object has the handling for all objects */
#include "device.h"
#include "handlers.h"
/** @file h_wpm.c Handles Write Property Multiple requests. */
/** Handler for a WriteProperty Service request.
* @ingroup DSWP
* This handler will be invoked by apdu_handler() if it has been enabled
* by a call to apdu_set_confirmed_handler().
* This handler builds a response packet, which is
* - an Abort if
* - the message is segmented
* - if decoding fails
* - an ACK if Device_Write_Property_Multiple() succeeds
* - an Error if Device_Write_PropertyMultiple() encounters an error
*
* @param service_request [in] The contents of the service request.
* @param service_len [in] The length of the service_request.
* @param src [in] BACNET_ADDRESS of the source of the message
* @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
* decoded from the APDU header of this message.
*/
void handler_write_property_multiple(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int apdu_len = 0;
int npdu_len = 0;
int pdu_len = 0;
int decode_len = 0;
bool error = false;
BACNET_WRITE_PROPERTY_DATA wp_data;
BACNET_NPDU_DATA npdu_data;
BACNET_ADDRESS my_address;
int bytes_sent = 0;
if (service_data->segmented_message) {
len = abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
#if PRINT_ENABLED
fprintf(stderr, "WPM: Segmented message. Sending Abort!\n");
#endif
goto WPM_ABORT;
}
/* decode service request */
decode_len = 0;
do
{
/* decode Object Identifier
*/
len = wpm_decode_object_id(&service_request[decode_len],
service_len - decode_len, &wp_data);
if (len > 0)
{
uint8_t tag_number = 0;
*/
len = wpm_decode_object_id(&service_request[decode_len],
service_len - decode_len, &wp_data);
if (len > 0)
{
uint8_t tag_number = 0;
decode_len += len;
/* Opening tag 1 - List of Properties
*/
if (decode_is_opening_tag_number(&service_request[decode_len++], 1))
{
/* Opening tag 1 - List of Properties
*/
if (decode_is_opening_tag_number(&service_request[decode_len++], 1))
{
do
{
/* decode a 'Property Identifier'; (3) an optional 'Property Array Index';
*/
/* (4) a 'Property Value'; and (5) an optional 'Priority'.
*/
len = wpm_decode_object_property(&service_request[decode_len],
service_len - decode_len, &wp_data);
if (len > 0)
{
/* decode a 'Property Identifier'; (3) an optional 'Property Array Index';
*/
/* (4) a 'Property Value'; and (5) an optional 'Priority'.
*/
len = wpm_decode_object_property(&service_request[decode_len],
service_len - decode_len, &wp_data);
if (len > 0)
{
decode_len += len;
if (Device_Write_Property(&wp_data) == false)
{
error = true;
break; /* do while (decoding List of Properties)
*/
}
}
else
{
#if PRINT_ENABLED
if (Device_Write_Property(&wp_data) == false)
{
error = true;
break; /* do while (decoding List of Properties)
*/
}
}
else
{
#if PRINT_ENABLED
fprintf(stderr, "Bad Encoding!\n");
#endif
wp_data.error_class = ERROR_CLASS_PROPERTY;
#endif
wp_data.error_class = ERROR_CLASS_PROPERTY;
wp_data.error_code = ERROR_CODE_OTHER;
error = true;
break; /* do while (decoding List of Properties)
*/
}
/* Closing tag 1 - List of Properties
error = true;
break; /* do while (decoding List of Properties)
*/
}
/* Closing tag 1 - List of Properties
*/
if (decode_is_closing_tag_number(&service_request[decode_len], 1))
{
if (decode_is_closing_tag_number(&service_request[decode_len], 1))
{
tag_number = 1;
decode_len++;
}
decode_len++;
}
else
tag_number = 0; /* it was not tag 1, decode next Property Identifier ...
*/
}
while(tag_number != 1); /* end decoding List of Properties for "that" object
*/
if (error)
break; /*do while (decode service request)
*/
tag_number = 0; /* it was not tag 1, decode next Property Identifier ...
*/
}
while(tag_number != 1); /* end decoding List of Properties for "that" object
*/
if (error)
break; /*do while (decode service request)
*/
}
}
else
{
#if PRINT_ENABLED
fprintf(stderr, "Bad Encoding!\n");
#endif
wp_data.error_class = ERROR_CLASS_OBJECT;
wp_data.error_code = ERROR_CODE_OTHER;
error = true;
break; /*do while (decode service request)
*/
}
}
while(decode_len < service_len);
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
npdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
apdu_len = 0;
if (error == false)
apdu_len = wpm_ack_encode_apdu_init(&Handler_Transmit_Buffer[npdu_len],
}
else
{
#if PRINT_ENABLED
fprintf(stderr, "Bad Encoding!\n");
#endif
wp_data.error_class = ERROR_CLASS_OBJECT;
wp_data.error_code = ERROR_CODE_OTHER;
error = true;
break; /*do while (decode service request)
*/
}
}
while(decode_len < service_len);
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
npdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
apdu_len = 0;
if (error == false)
apdu_len = wpm_ack_encode_apdu_init(&Handler_Transmit_Buffer[npdu_len],
File diff suppressed because it is too large Load Diff
+123 -123
View File
@@ -1,124 +1,124 @@
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* 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 NC_H
#define NC_H
#include "event.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define NC_RESCAN_RECIPIENTS_SECS 60
/* max "length" of recipient_list */
#define NC_MAX_RECIPIENTS 10
/* Recipient types */
typedef enum {
RECIPIENT_TYPE_NOTINITIALIZED = 0,
RECIPIENT_TYPE_DEVICE = 1,
RECIPIENT_TYPE_ADDRESS = 2
} NC_RECIPIENT_TYPE;
/* BACnetRecipient sructuer*/
/*
BACnetRecipient ::= CHOICE {
device [0] BACnetObjectIdentifier,
address [1] BACnetAddress
}
*/
typedef struct BACnet_Recipient {
uint8_t RecipientType; /* Type of Recipient */
union {
uint32_t DeviceIdentifier;
BACNET_ADDRESS Address;
} _;
} BACNET_RECIPIENT;
/* BACnetDestination structure */
typedef struct BACnet_Destination {
uint8_t ValidDays;
BACNET_TIME FromTime;
BACNET_TIME ToTime;
BACNET_RECIPIENT Recipient;
uint32_t ProcessIdentifier;
uint8_t Transitions;
bool ConfirmedNotify;
} BACNET_DESTINATION;
/* Structure containing configuration for a Notification Class */
typedef struct Notification_Class_info {
uint8_t Priority[3]; /* BACnetARRAY[3] of Unsigned */
uint8_t Ack_Required; /* BACnetEventTransitionBits */
BACNET_DESTINATION Recipient_List[NC_MAX_RECIPIENTS]; /* List of BACnetDestination */
} NOTIFICATION_CLASS_INFO;
void Notification_Class_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
void Notification_Class_Init(void);
bool Notification_Class_Valid_Instance(
uint32_t object_instance);
unsigned Notification_Class_Count(void);
uint32_t Notification_Class_Index_To_Instance(unsigned index);
unsigned Notification_Class_Instance_To_Index(
uint32_t object_instance);
bool Notification_Class_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name);
int Notification_Class_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata);
bool Notification_Class_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data);
void Notification_Class_common_reporting_function(
BACNET_EVENT_NOTIFICATION_DATA * event_data);
void Notification_Class_find_recipient(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define NOTIFICATION_CLASS_OBJ_FUNCTIONS \
OBJECT_NOTIFICATION_CLASS, Notification_Class_Init, Notification_Class_Count, \
Notification_Class_Index_To_Instance, Notification_Class_Valid_Instance, \
Notification_Class_Object_Name, Notification_Class_Read_Property, \
Notification_Class_Write_Property, Notification_Class_Property_Lists, \
NULL, NULL, NULL
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* 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 NC_H
#define NC_H
#include "event.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define NC_RESCAN_RECIPIENTS_SECS 60
/* max "length" of recipient_list */
#define NC_MAX_RECIPIENTS 10
/* Recipient types */
typedef enum {
RECIPIENT_TYPE_NOTINITIALIZED = 0,
RECIPIENT_TYPE_DEVICE = 1,
RECIPIENT_TYPE_ADDRESS = 2
} NC_RECIPIENT_TYPE;
/* BACnetRecipient sructuer*/
/*
BACnetRecipient ::= CHOICE {
device [0] BACnetObjectIdentifier,
address [1] BACnetAddress
}
*/
typedef struct BACnet_Recipient {
uint8_t RecipientType; /* Type of Recipient */
union {
uint32_t DeviceIdentifier;
BACNET_ADDRESS Address;
} _;
} BACNET_RECIPIENT;
/* BACnetDestination structure */
typedef struct BACnet_Destination {
uint8_t ValidDays;
BACNET_TIME FromTime;
BACNET_TIME ToTime;
BACNET_RECIPIENT Recipient;
uint32_t ProcessIdentifier;
uint8_t Transitions;
bool ConfirmedNotify;
} BACNET_DESTINATION;
/* Structure containing configuration for a Notification Class */
typedef struct Notification_Class_info {
uint8_t Priority[3]; /* BACnetARRAY[3] of Unsigned */
uint8_t Ack_Required; /* BACnetEventTransitionBits */
BACNET_DESTINATION Recipient_List[NC_MAX_RECIPIENTS]; /* List of BACnetDestination */
} NOTIFICATION_CLASS_INFO;
void Notification_Class_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
void Notification_Class_Init(void);
bool Notification_Class_Valid_Instance(
uint32_t object_instance);
unsigned Notification_Class_Count(void);
uint32_t Notification_Class_Index_To_Instance(unsigned index);
unsigned Notification_Class_Instance_To_Index(
uint32_t object_instance);
bool Notification_Class_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name);
int Notification_Class_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata);
bool Notification_Class_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data);
void Notification_Class_common_reporting_function(
BACNET_EVENT_NOTIFICATION_DATA * event_data);
void Notification_Class_find_recipient(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define NOTIFICATION_CLASS_OBJ_FUNCTIONS \
OBJECT_NOTIFICATION_CLASS, Notification_Class_Init, Notification_Class_Count, \
Notification_Class_Index_To_Instance, Notification_Class_Valid_Instance, \
Notification_Class_Object_Name, Notification_Class_Read_Property, \
Notification_Class_Write_Property, Notification_Class_Property_Lists, \
NULL, NULL, NULL
#endif /* NC_H
+77 -77
View File
@@ -1,77 +1,77 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2006 John Minack
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 LSO_H
#define LSO_H
#include <stdint.h>
#include <stdbool.h>
#include "bacenum.h"
#include "bacdef.h"
#include "bacstr.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Life Safety Operation Service */
typedef struct {
uint32_t processId;
BACNET_CHARACTER_STRING requestingSrc;
BACNET_LIFE_SAFETY_OPERATION operation;
BACNET_OBJECT_ID targetObject;
} BACNET_LSO_DATA;
int lso_encode_adpu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_LSO_DATA * data);
/* decode the service request only */
int lso_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_LSO_DATA * data);
#ifdef TEST
#include "ctest.h"
void testLSO(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2006 John Minack
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 LSO_H
#define LSO_H
#include <stdint.h>
#include <stdbool.h>
#include "bacenum.h"
#include "bacdef.h"
#include "bacstr.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Life Safety Operation Service */
typedef struct {
uint32_t processId;
BACNET_CHARACTER_STRING requestingSrc;
BACNET_LIFE_SAFETY_OPERATION operation;
BACNET_OBJECT_ID targetObject;
} BACNET_LSO_DATA;
int lso_encode_adpu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_LSO_DATA * data);
/* decode the service request only */
int lso_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_LSO_DATA * data);
#ifdef TEST
#include "ctest.h"
void testLSO(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+78 -78
View File
@@ -1,78 +1,78 @@
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* 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 WRITEPROPERTYMULTIPLE_H
#define WRITEPROPERTYMULTIPLE_H
#include <stdint.h>
#include <stdbool.h>
#include "bacdcode.h"
#include "bacapp.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* decode the service request only */
int wpm_decode_object_id(uint8_t * apdu, uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA * data);
int wpm_decode_object_property(uint8_t * apdu,
uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA * wpm_data);
/* encode service */
int wpm_ack_encode_apdu_init(uint8_t *apdu, uint8_t invoke_id);
int wpm_error_ack_encode_apdu(uint8_t * apdu, uint8_t invoke_id,
BACNET_WRITE_PROPERTY_DATA * wp_data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/** @defgroup DSWP Data Sharing - Write Property Multiple Service (DS-WPM)
* @ingroup DataShare
* 15.10 WriteProperty Multiple Service <br>
* The WritePropertyMultiple service is used by a client BACnet-user
* to modify the value of one or more specified properties of a BACnet object.
* This service potentially allows write access to any property of any object,
* whether a BACnet-defined object or not.
* Properties shall be modified by the WritePropertyMultiple service
* in the order specified in the 'List of Write Access Specifications' parameter,
* and execution of the service shall continue until all of the specified
* properties have been written to or a property is encountered that
* for some reason cannot be modified as requested.
* Some implementors may wish to restrict write access to certain properties
* of certain objects. In such cases, an attempt to modify a restricted property
* shall result in the return of an error of 'Error Class' PROPERTY and 'Error Code'
* WRITE_ACCESS_DENIED. Note that these restricted properties may be accessible
* through the use of Virtual Terminal services or other means at the discretion
* of the implementor.
*/
#endif
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* 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 WRITEPROPERTYMULTIPLE_H
#define WRITEPROPERTYMULTIPLE_H
#include <stdint.h>
#include <stdbool.h>
#include "bacdcode.h"
#include "bacapp.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* decode the service request only */
int wpm_decode_object_id(uint8_t * apdu, uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA * data);
int wpm_decode_object_property(uint8_t * apdu,
uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA * wpm_data);
/* encode service */
int wpm_ack_encode_apdu_init(uint8_t *apdu, uint8_t invoke_id);
int wpm_error_ack_encode_apdu(uint8_t * apdu, uint8_t invoke_id,
BACNET_WRITE_PROPERTY_DATA * wp_data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/** @defgroup DSWP Data Sharing - Write Property Multiple Service (DS-WPM)
* @ingroup DataShare
* 15.10 WriteProperty Multiple Service <br>
* The WritePropertyMultiple service is used by a client BACnet-user
* to modify the value of one or more specified properties of a BACnet object.
* This service potentially allows write access to any property of any object,
* whether a BACnet-defined object or not.
* Properties shall be modified by the WritePropertyMultiple service
* in the order specified in the 'List of Write Access Specifications' parameter,
* and execution of the service shall continue until all of the specified
* properties have been written to or a property is encountered that
* for some reason cannot be modified as requested.
* Some implementors may wish to restrict write access to certain properties
* of certain objects. In such cases, an attempt to modify a restricted property
* shall result in the return of an error of 'Error Class' PROPERTY and 'Error Code'
* WRITE_ACCESS_DENIED. Note that these restricted properties may be accessible
* through the use of Virtual Terminal services or other means at the discretion
* of the implementor.
*/
#endif
+275 -275
View File
@@ -1,275 +1,275 @@
/**************************************************************************
*
* Copyright (C) 2011 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 <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "hardware.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacstr.h"
#include "nvdata.h"
#include "seeprom.h"
#include "device.h"
#include "bname.h"
/* Basic UTF-8 manipulation routines
by Jeff Bezanson
placed in the public domain Fall 2005 */
static const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
/* based on the valid_utf8 routine from the PCRE library by Philip Hazel
length is in bytes, since without knowing whether the string is valid
it's hard to know how many characters there are! */
static int utf8_isvalid(const char *str, int length)
{
const unsigned char *p, *pend = (unsigned char*)str + length;
unsigned char c;
int ab;
for (p = (unsigned char*)str; p < pend; p++) {
c = *p;
/* null in middle of string */
if (c == 0) {
return 0;
}
/* ASCII character */
if (c < 128) {
continue;
}
if ((c & 0xc0) != 0xc0) {
return 0;
}
ab = trailingBytesForUTF8[c];
if (length < ab) {
return 0;
}
length -= ab;
p++;
/* Check top bits in the second byte */
if ((*p & 0xc0) != 0x80) {
return 0;
}
/* Check for overlong sequences for each different length */
switch (ab) {
/* Check for xx00 000x */
case 1:
if ((c & 0x3e) == 0) return 0;
continue; /* We know there aren't any more bytes to check */
/* Check for 1110 0000, xx0x xxxx */
case 2:
if (c == 0xe0 && (*p & 0x20) == 0) return 0;
break;
/* Check for 1111 0000, xx00 xxxx */
case 3:
if (c == 0xf0 && (*p & 0x30) == 0) return 0;
break;
/* Check for 1111 1000, xx00 0xxx */
case 4:
if (c == 0xf8 && (*p & 0x38) == 0) return 0;
break;
/* Check for leading 0xfe or 0xff,
and then for 1111 1100, xx00 00xx */
case 5:
if (c == 0xfe || c == 0xff ||
(c == 0xfc && (*p & 0x3c) == 0)) return 0;
break;
}
/* Check for valid bytes after the 2nd, if any; all must start 10 */
while (--ab > 0) {
if ((*(++p) & 0xc0) != 0x80) return 0;
}
}
return 1;
}
static bool bacnet_name_isvalid(
uint8_t encoding,
uint8_t length,
char *str)
{
bool valid = false;
if ((encoding < MAX_CHARACTER_STRING_ENCODING) &&
(length <= NV_EEPROM_NAME_SIZE)) {
if (encoding == CHARACTER_ANSI_X34) {
if (utf8_isvalid(str, length)) {
valid = true;
}
} else {
valid = true;
}
}
return valid;
}
bool bacnet_name_set(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string)
{
uint8_t encoding = 0;
uint8_t length = 0;
char *str = NULL;
length = characterstring_length(char_string);
encoding = characterstring_encoding(char_string);
str = characterstring_value(char_string);
if (bacnet_name_isvalid(encoding, length, str)) {
seeprom_bytes_write(
NV_EEPROM_NAME_LENGTH(offset),
&length, 1);
seeprom_bytes_write(
NV_EEPROM_NAME_ENCODING(offset),
&encoding, 1);
seeprom_bytes_write(
NV_EEPROM_NAME_STRING(offset),
(uint8_t *)str,
length);
return true;
}
return false;
}
bool bacnet_name_write(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
bool status = false;
size_t length = 0;
uint8_t encoding = 0;
length = characterstring_length(char_string);
if (length < 1) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
} else if (length <= NV_EEPROM_NAME_SIZE) {
encoding = characterstring_encoding(char_string);
if (encoding < MAX_CHARACTER_STRING_ENCODING) {
if (Device_Valid_Object_Name(char_string, NULL, NULL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_DUPLICATE_NAME;
} else {
status = bacnet_name_set(offset, char_string);
if (status) {
Device_Inc_Database_Revision();
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
}
return status;
}
/* no required minumum length or duplicate checking */
bool bacnet_name_write_other(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
bool status = false;
size_t length = 0;
uint8_t encoding = 0;
length = characterstring_length(char_string);
if (length <= NV_EEPROM_NAME_SIZE) {
encoding = characterstring_encoding(char_string);
if (encoding < MAX_CHARACTER_STRING_ENCODING) {
status = bacnet_name_set(offset, char_string);
if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
}
return status;
}
void bacnet_name_init(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
char *default_string)
{
characterstring_init_ansi(char_string, default_string);
(void)bacnet_name_set(offset, char_string);
}
void bacnet_name(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
char *default_string)
{
uint8_t encoding = 0;
uint8_t length = 0;
char name[NV_EEPROM_NAME_SIZE + 1] = "";
seeprom_bytes_read(NV_EEPROM_NAME_ENCODING(offset), &encoding, 1);
seeprom_bytes_read(NV_EEPROM_NAME_LENGTH(offset), &length, 1);
seeprom_bytes_read(NV_EEPROM_NAME_STRING(offset), (uint8_t *) & name,
NV_EEPROM_NAME_SIZE);
if (bacnet_name_isvalid(length, encoding, name)) {
characterstring_init(char_string, encoding, &name[0], length);
} else if (default_string) {
bacnet_name_init(offset, char_string, default_string);
}
}
/**************************************************************************
*
* Copyright (C) 2011 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 <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "hardware.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacstr.h"
#include "nvdata.h"
#include "seeprom.h"
#include "device.h"
#include "bname.h"
/* Basic UTF-8 manipulation routines
by Jeff Bezanson
placed in the public domain Fall 2005 */
static const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
/* based on the valid_utf8 routine from the PCRE library by Philip Hazel
length is in bytes, since without knowing whether the string is valid
it's hard to know how many characters there are! */
static int utf8_isvalid(const char *str, int length)
{
const unsigned char *p, *pend = (unsigned char*)str + length;
unsigned char c;
int ab;
for (p = (unsigned char*)str; p < pend; p++) {
c = *p;
/* null in middle of string */
if (c == 0) {
return 0;
}
/* ASCII character */
if (c < 128) {
continue;
}
if ((c & 0xc0) != 0xc0) {
return 0;
}
ab = trailingBytesForUTF8[c];
if (length < ab) {
return 0;
}
length -= ab;
p++;
/* Check top bits in the second byte */
if ((*p & 0xc0) != 0x80) {
return 0;
}
/* Check for overlong sequences for each different length */
switch (ab) {
/* Check for xx00 000x */
case 1:
if ((c & 0x3e) == 0) return 0;
continue; /* We know there aren't any more bytes to check */
/* Check for 1110 0000, xx0x xxxx */
case 2:
if (c == 0xe0 && (*p & 0x20) == 0) return 0;
break;
/* Check for 1111 0000, xx00 xxxx */
case 3:
if (c == 0xf0 && (*p & 0x30) == 0) return 0;
break;
/* Check for 1111 1000, xx00 0xxx */
case 4:
if (c == 0xf8 && (*p & 0x38) == 0) return 0;
break;
/* Check for leading 0xfe or 0xff,
and then for 1111 1100, xx00 00xx */
case 5:
if (c == 0xfe || c == 0xff ||
(c == 0xfc && (*p & 0x3c) == 0)) return 0;
break;
}
/* Check for valid bytes after the 2nd, if any; all must start 10 */
while (--ab > 0) {
if ((*(++p) & 0xc0) != 0x80) return 0;
}
}
return 1;
}
static bool bacnet_name_isvalid(
uint8_t encoding,
uint8_t length,
char *str)
{
bool valid = false;
if ((encoding < MAX_CHARACTER_STRING_ENCODING) &&
(length <= NV_EEPROM_NAME_SIZE)) {
if (encoding == CHARACTER_ANSI_X34) {
if (utf8_isvalid(str, length)) {
valid = true;
}
} else {
valid = true;
}
}
return valid;
}
bool bacnet_name_set(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string)
{
uint8_t encoding = 0;
uint8_t length = 0;
char *str = NULL;
length = characterstring_length(char_string);
encoding = characterstring_encoding(char_string);
str = characterstring_value(char_string);
if (bacnet_name_isvalid(encoding, length, str)) {
seeprom_bytes_write(
NV_EEPROM_NAME_LENGTH(offset),
&length, 1);
seeprom_bytes_write(
NV_EEPROM_NAME_ENCODING(offset),
&encoding, 1);
seeprom_bytes_write(
NV_EEPROM_NAME_STRING(offset),
(uint8_t *)str,
length);
return true;
}
return false;
}
bool bacnet_name_write(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
bool status = false;
size_t length = 0;
uint8_t encoding = 0;
length = characterstring_length(char_string);
if (length < 1) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
} else if (length <= NV_EEPROM_NAME_SIZE) {
encoding = characterstring_encoding(char_string);
if (encoding < MAX_CHARACTER_STRING_ENCODING) {
if (Device_Valid_Object_Name(char_string, NULL, NULL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_DUPLICATE_NAME;
} else {
status = bacnet_name_set(offset, char_string);
if (status) {
Device_Inc_Database_Revision();
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
}
return status;
}
/* no required minumum length or duplicate checking */
bool bacnet_name_write_other(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
bool status = false;
size_t length = 0;
uint8_t encoding = 0;
length = characterstring_length(char_string);
if (length <= NV_EEPROM_NAME_SIZE) {
encoding = characterstring_encoding(char_string);
if (encoding < MAX_CHARACTER_STRING_ENCODING) {
status = bacnet_name_set(offset, char_string);
if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
}
return status;
}
void bacnet_name_init(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
char *default_string)
{
characterstring_init_ansi(char_string, default_string);
(void)bacnet_name_set(offset, char_string);
}
void bacnet_name(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
char *default_string)
{
uint8_t encoding = 0;
uint8_t length = 0;
char name[NV_EEPROM_NAME_SIZE + 1] = "";
seeprom_bytes_read(NV_EEPROM_NAME_ENCODING(offset), &encoding, 1);
seeprom_bytes_read(NV_EEPROM_NAME_LENGTH(offset), &length, 1);
seeprom_bytes_read(NV_EEPROM_NAME_STRING(offset), (uint8_t *) & name,
NV_EEPROM_NAME_SIZE);
if (bacnet_name_isvalid(length, encoding, name)) {
characterstring_init(char_string, encoding, &name[0], length);
} else if (default_string) {
bacnet_name_init(offset, char_string, default_string);
}
}
+60 -60
View File
@@ -1,60 +1,60 @@
/**************************************************************************
*
* Copyright (C) 2010 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 BACNET_NAME_H
#define BACNET_NAME_H
#include <stdint.h>
#include "bacstr.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
bool bacnet_name_set(
uint16_t eeprom_offset,
BACNET_CHARACTER_STRING *char_string);
void bacnet_name_init(
uint16_t eeprom_offset,
BACNET_CHARACTER_STRING *char_string,
char *default_string);
void bacnet_name(
uint16_t eeprom_offset,
BACNET_CHARACTER_STRING *char_string,
char *default_string);
bool bacnet_name_write(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
/* no required minumum length or duplicate checking */
bool bacnet_name_write_other(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2010 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 BACNET_NAME_H
#define BACNET_NAME_H
#include <stdint.h>
#include "bacstr.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
bool bacnet_name_set(
uint16_t eeprom_offset,
BACNET_CHARACTER_STRING *char_string);
void bacnet_name_init(
uint16_t eeprom_offset,
BACNET_CHARACTER_STRING *char_string,
char *default_string);
void bacnet_name(
uint16_t eeprom_offset,
BACNET_CHARACTER_STRING *char_string,
char *default_string);
bool bacnet_name_write(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
/* no required minumum length or duplicate checking */
bool bacnet_name_write_other(
uint16_t offset,
BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+426 -426
View File
@@ -1,426 +1,426 @@
/**************************************************************************
*
* Copyright (C) 2010 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 <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h"
#include "mstpdef.h"
#include "automac.h"
/* MS/TP Auto MAC address functionality */
/* table to track tokens and poll-for-master frames */
typedef struct {
/* Poll For Master indicates empty slot */
bool pfm:1;
/* a device that emits a frame indicates a used slot */
bool emitter:1;
/* token - indicates a token was passed from this slot */
/* important to know who the Next Station is */
bool token:1;
/* reserve some slots for fixed addresses */
bool reserved:1;
} AUTO_MAC_DATA;
/* starting number available for AutoMAC */
#define MAC_SLOTS_OFFSET 32
/* total number of slots */
#define MAC_SLOTS_MAX 128
static AUTO_MAC_DATA Auto_MAC_Data[MAC_SLOTS_MAX];
/* my automatic MAC address */
static uint8_t My_MAC_Address;
/* my no-token silence timer time slot in milliseconds */
static uint16_t My_Time_Slot;
/* indication that PFM has happened for a full cycle */
static bool PFM_Cycle_Complete;
/* indicate that we are an auto-mode node */
static bool Auto_Mode_Enabled;
/****************************************************************************
* DESCRIPTION: Indication that we are an automode node
* RETURN: true if automode enabled
* NOTES: none
*****************************************************************************/
bool automac_enabled(void)
{
return Auto_Mode_Enabled;
}
/****************************************************************************
* DESCRIPTION: Sets the automode status
* RETURN: nothing
* NOTES: none
*****************************************************************************/
void automac_enabled_set(bool status)
{
Auto_Mode_Enabled = status;
}
/****************************************************************************
* DESCRIPTION: Indication that PFM has happened for a full cycle
* RETURN: true if full
* NOTES: none
*****************************************************************************/
bool automac_pfm_cycle_complete(void)
{
return PFM_Cycle_Complete;
}
/****************************************************************************
* DESCRIPTION: Indicates that an address is used or taken
* RETURN: true if used
* NOTES: none
*****************************************************************************/
static bool automac_address_used(uint8_t mac)
{
bool status = false;
if (mac < MAC_SLOTS_MAX) {
if ((Auto_MAC_Data[mac].emitter) ||
(Auto_MAC_Data[mac].reserved) ||
(Auto_MAC_Data[mac].token)) {
status = true;
}
}
return status;
}
/****************************************************************************
* DESCRIPTION: Validates an address as available, not taken, and within bounds
* RETURN: true if valid
* NOTES: none
*****************************************************************************/
bool automac_free_address_valid(uint8_t mac)
{
bool status = false;
if (mac < MAC_SLOTS_MAX) {
if ((Auto_MAC_Data[mac].pfm) &&
(!automac_address_used(mac))) {
status = true;
}
}
return status;
}
/****************************************************************************
* DESCRIPTION: Determines the next station address to send the token
* RETURN: Next_Station, or 255 if there are no next stations
* NOTES: none
*****************************************************************************/
uint8_t automac_next_station(uint8_t mac)
{
uint8_t i = 0; /* loop counter */
uint8_t next_station = 255; /* return value */
uint8_t test_station = 0; /* station number to test for token */
test_station = (mac + 1) % 128;
for (i = 0; i < MAC_SLOTS_MAX; i++) {
if (Auto_MAC_Data[test_station].token) {
next_station = test_station;
break;
}
test_station = (test_station + 1) % MAC_SLOTS_MAX;
}
return next_station;
}
/****************************************************************************
* DESCRIPTION: Determines the number of free MAC addresses
* RETURN: Number of free MAC addresses
* NOTES: none
*****************************************************************************/
uint8_t automac_free_address_count(void)
{
uint8_t i = 0;
uint8_t slots = 0;
for (i = 0; i < MAC_SLOTS_MAX; i++) {
if (automac_free_address_valid(i)) {
slots++;
}
}
return slots;
}
/****************************************************************************
* DESCRIPTION: Determines the number of free MAC addresses
* RETURN: Number of free MAC addresses
* NOTES: none
*****************************************************************************/
uint8_t automac_free_address_mac(uint8_t count)
{
uint8_t i = 0;
uint8_t slots = 0;
uint8_t mac = 255;
for (i = 0; i < MAC_SLOTS_MAX; i++) {
if (automac_free_address_valid(i)) {
if (slots == count) {
mac = i;
break;
}
slots++;
}
}
return mac;
}
/****************************************************************************
* DESCRIPTION: Gets a free random address to use
* RETURN: free MAC addresses
* NOTES: none
*****************************************************************************/
uint8_t automac_free_address_random(void)
{
uint8_t count = 0;
uint8_t random_count = 0;
uint8_t mac = 255;
count = automac_free_address_count();
if (count) {
random_count = rand()%count;
mac = automac_free_address_mac(random_count);
}
return mac;
}
/****************************************************************************
* DESCRIPTION: Gets the address stored.
* RETURN: MAC addresses
* NOTES: none
*****************************************************************************/
uint8_t automac_address(void)
{
return My_MAC_Address;
}
/****************************************************************************
* DESCRIPTION: Sets the MAC address
* RETURN: MAC addresses
* NOTES: none
*****************************************************************************/
void automac_address_set(uint8_t mac)
{
My_MAC_Address = mac;
}
/****************************************************************************
* DESCRIPTION: Gets the address stored.
* RETURN: MAC addresses
* NOTES: none
*****************************************************************************/
uint16_t automac_time_slot(void)
{
return My_Time_Slot;
}
/****************************************************************************
* DESCRIPTION: Sets the MAC address
* RETURN: MAC addresses
* NOTES: none
*****************************************************************************/
void automac_address_init(void)
{
My_MAC_Address = MAC_SLOTS_OFFSET + rand()%(MAC_SLOTS_MAX-MAC_SLOTS_OFFSET);
/* at least as long as a dropped token - worst case */
My_Time_Slot = Tno_token + (MAC_SLOTS_MAX * Tslot);
My_Time_Slot += (uint16_t)My_MAC_Address * Tslot;
}
/****************************************************************************
* DESCRIPTION: Sets an open address slot
* RETURN: nothing
* NOTES: none
*****************************************************************************/
void automac_pfm_set(uint8_t mac)
{
if (mac < MAC_SLOTS_MAX) {
if (Auto_MAC_Data[mac].pfm) {
/* indicate that we have completed enough PFM to continue */
if (automac_free_address_count() > 0) {
PFM_Cycle_Complete = true;
}
}
Auto_MAC_Data[mac].pfm = true;
}
}
/****************************************************************************
* DESCRIPTION: Sets a used address slot
* RETURN: nothing
* NOTES: none
*****************************************************************************/
void automac_token_set(uint8_t mac)
{
if (mac < MAC_SLOTS_MAX) {
Auto_MAC_Data[mac].token = true;
}
}
/****************************************************************************
* DESCRIPTION: Sets a used address slot
* RETURN: nothing
* NOTES: none
*****************************************************************************/
void automac_emitter_set(uint8_t mac)
{
if (mac < MAC_SLOTS_MAX) {
Auto_MAC_Data[mac].emitter = true;
}
}
/****************************************************************************
* DESCRIPTION: Initializes the auto MAC module
* RETURN: nothing
* NOTES: none
*****************************************************************************/
void automac_init(void)
{
uint8_t i = 0;
for (i = 0; i < MAC_SLOTS_MAX; i++) {
Auto_MAC_Data[i].token = false;
Auto_MAC_Data[i].emitter = false;
Auto_MAC_Data[i].pfm = false;
if (i < MAC_SLOTS_OFFSET) {
Auto_MAC_Data[i].reserved = true;
} else {
Auto_MAC_Data[i].reserved = false;
}
}
automac_address_init();
PFM_Cycle_Complete = false;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "ctest.h"
/* test the ring buffer */
void test_Auto_MAC(
Test * pTest)
{
uint8_t mac = 255;
automac_init();
ct_test(pTest, automac_free_address_count() == 0);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == 255);
automac_pfm_set(MAC_SLOTS_OFFSET);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == MAC_SLOTS_OFFSET);
ct_test(pTest, automac_free_address_count() == 1);
automac_token_set(MAC_SLOTS_OFFSET);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == 255);
ct_test(pTest, automac_free_address_count() == 0);
automac_pfm_set(127);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == 127);
ct_test(pTest, automac_free_address_count() == 1);
automac_token_set(127);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == 255);
ct_test(pTest, automac_free_address_count() == 0);
/* the ANSI rand() uses consistent sequence based on seed */
srand(42);
mac = automac_free_address_random();
ct_test(pTest, mac == 255);
automac_pfm_set(MAC_SLOTS_OFFSET+1);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+1));
mac = automac_free_address_random();
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+1));
/* test 2 free addresses */
automac_pfm_set(MAC_SLOTS_OFFSET+2);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+1));
mac = automac_free_address_mac(1);
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+2));
mac = automac_free_address_random();
ct_test(pTest,
(mac == (MAC_SLOTS_OFFSET+1)) ||
(mac == (MAC_SLOTS_OFFSET+2)));
/* test 3 free addresses */
automac_pfm_set(126);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+1));
mac = automac_free_address_mac(1);
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+2));
mac = automac_free_address_mac(2);
ct_test(pTest, mac == 126);
mac = automac_free_address_random();
ct_test(pTest,
(mac == (MAC_SLOTS_OFFSET+1))||
(mac == (MAC_SLOTS_OFFSET+2))||
(mac == 126));
/* test the stored address */
mac = automac_address();
ct_test(pTest, mac < MAC_SLOTS_MAX);
automac_address_set(MAC_SLOTS_OFFSET);
mac = automac_address();
ct_test(pTest, mac == MAC_SLOTS_OFFSET);
automac_init();
automac_token_set(0x6B);
mac = automac_next_station(0x25);
ct_test(pTest, mac == 0x6B);
}
#ifdef TEST_AUTOMAC
int main(
void)
{
Test *pTest;
bool rc;
pTest = ct_create("Auto MAC", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, test_Auto_MAC);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif
#endif
/**************************************************************************
*
* Copyright (C) 2010 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 <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h"
#include "mstpdef.h"
#include "automac.h"
/* MS/TP Auto MAC address functionality */
/* table to track tokens and poll-for-master frames */
typedef struct {
/* Poll For Master indicates empty slot */
bool pfm:1;
/* a device that emits a frame indicates a used slot */
bool emitter:1;
/* token - indicates a token was passed from this slot */
/* important to know who the Next Station is */
bool token:1;
/* reserve some slots for fixed addresses */
bool reserved:1;
} AUTO_MAC_DATA;
/* starting number available for AutoMAC */
#define MAC_SLOTS_OFFSET 32
/* total number of slots */
#define MAC_SLOTS_MAX 128
static AUTO_MAC_DATA Auto_MAC_Data[MAC_SLOTS_MAX];
/* my automatic MAC address */
static uint8_t My_MAC_Address;
/* my no-token silence timer time slot in milliseconds */
static uint16_t My_Time_Slot;
/* indication that PFM has happened for a full cycle */
static bool PFM_Cycle_Complete;
/* indicate that we are an auto-mode node */
static bool Auto_Mode_Enabled;
/****************************************************************************
* DESCRIPTION: Indication that we are an automode node
* RETURN: true if automode enabled
* NOTES: none
*****************************************************************************/
bool automac_enabled(void)
{
return Auto_Mode_Enabled;
}
/****************************************************************************
* DESCRIPTION: Sets the automode status
* RETURN: nothing
* NOTES: none
*****************************************************************************/
void automac_enabled_set(bool status)
{
Auto_Mode_Enabled = status;
}
/****************************************************************************
* DESCRIPTION: Indication that PFM has happened for a full cycle
* RETURN: true if full
* NOTES: none
*****************************************************************************/
bool automac_pfm_cycle_complete(void)
{
return PFM_Cycle_Complete;
}
/****************************************************************************
* DESCRIPTION: Indicates that an address is used or taken
* RETURN: true if used
* NOTES: none
*****************************************************************************/
static bool automac_address_used(uint8_t mac)
{
bool status = false;
if (mac < MAC_SLOTS_MAX) {
if ((Auto_MAC_Data[mac].emitter) ||
(Auto_MAC_Data[mac].reserved) ||
(Auto_MAC_Data[mac].token)) {
status = true;
}
}
return status;
}
/****************************************************************************
* DESCRIPTION: Validates an address as available, not taken, and within bounds
* RETURN: true if valid
* NOTES: none
*****************************************************************************/
bool automac_free_address_valid(uint8_t mac)
{
bool status = false;
if (mac < MAC_SLOTS_MAX) {
if ((Auto_MAC_Data[mac].pfm) &&
(!automac_address_used(mac))) {
status = true;
}
}
return status;
}
/****************************************************************************
* DESCRIPTION: Determines the next station address to send the token
* RETURN: Next_Station, or 255 if there are no next stations
* NOTES: none
*****************************************************************************/
uint8_t automac_next_station(uint8_t mac)
{
uint8_t i = 0; /* loop counter */
uint8_t next_station = 255; /* return value */
uint8_t test_station = 0; /* station number to test for token */
test_station = (mac + 1) % 128;
for (i = 0; i < MAC_SLOTS_MAX; i++) {
if (Auto_MAC_Data[test_station].token) {
next_station = test_station;
break;
}
test_station = (test_station + 1) % MAC_SLOTS_MAX;
}
return next_station;
}
/****************************************************************************
* DESCRIPTION: Determines the number of free MAC addresses
* RETURN: Number of free MAC addresses
* NOTES: none
*****************************************************************************/
uint8_t automac_free_address_count(void)
{
uint8_t i = 0;
uint8_t slots = 0;
for (i = 0; i < MAC_SLOTS_MAX; i++) {
if (automac_free_address_valid(i)) {
slots++;
}
}
return slots;
}
/****************************************************************************
* DESCRIPTION: Determines the number of free MAC addresses
* RETURN: Number of free MAC addresses
* NOTES: none
*****************************************************************************/
uint8_t automac_free_address_mac(uint8_t count)
{
uint8_t i = 0;
uint8_t slots = 0;
uint8_t mac = 255;
for (i = 0; i < MAC_SLOTS_MAX; i++) {
if (automac_free_address_valid(i)) {
if (slots == count) {
mac = i;
break;
}
slots++;
}
}
return mac;
}
/****************************************************************************
* DESCRIPTION: Gets a free random address to use
* RETURN: free MAC addresses
* NOTES: none
*****************************************************************************/
uint8_t automac_free_address_random(void)
{
uint8_t count = 0;
uint8_t random_count = 0;
uint8_t mac = 255;
count = automac_free_address_count();
if (count) {
random_count = rand()%count;
mac = automac_free_address_mac(random_count);
}
return mac;
}
/****************************************************************************
* DESCRIPTION: Gets the address stored.
* RETURN: MAC addresses
* NOTES: none
*****************************************************************************/
uint8_t automac_address(void)
{
return My_MAC_Address;
}
/****************************************************************************
* DESCRIPTION: Sets the MAC address
* RETURN: MAC addresses
* NOTES: none
*****************************************************************************/
void automac_address_set(uint8_t mac)
{
My_MAC_Address = mac;
}
/****************************************************************************
* DESCRIPTION: Gets the address stored.
* RETURN: MAC addresses
* NOTES: none
*****************************************************************************/
uint16_t automac_time_slot(void)
{
return My_Time_Slot;
}
/****************************************************************************
* DESCRIPTION: Sets the MAC address
* RETURN: MAC addresses
* NOTES: none
*****************************************************************************/
void automac_address_init(void)
{
My_MAC_Address = MAC_SLOTS_OFFSET + rand()%(MAC_SLOTS_MAX-MAC_SLOTS_OFFSET);
/* at least as long as a dropped token - worst case */
My_Time_Slot = Tno_token + (MAC_SLOTS_MAX * Tslot);
My_Time_Slot += (uint16_t)My_MAC_Address * Tslot;
}
/****************************************************************************
* DESCRIPTION: Sets an open address slot
* RETURN: nothing
* NOTES: none
*****************************************************************************/
void automac_pfm_set(uint8_t mac)
{
if (mac < MAC_SLOTS_MAX) {
if (Auto_MAC_Data[mac].pfm) {
/* indicate that we have completed enough PFM to continue */
if (automac_free_address_count() > 0) {
PFM_Cycle_Complete = true;
}
}
Auto_MAC_Data[mac].pfm = true;
}
}
/****************************************************************************
* DESCRIPTION: Sets a used address slot
* RETURN: nothing
* NOTES: none
*****************************************************************************/
void automac_token_set(uint8_t mac)
{
if (mac < MAC_SLOTS_MAX) {
Auto_MAC_Data[mac].token = true;
}
}
/****************************************************************************
* DESCRIPTION: Sets a used address slot
* RETURN: nothing
* NOTES: none
*****************************************************************************/
void automac_emitter_set(uint8_t mac)
{
if (mac < MAC_SLOTS_MAX) {
Auto_MAC_Data[mac].emitter = true;
}
}
/****************************************************************************
* DESCRIPTION: Initializes the auto MAC module
* RETURN: nothing
* NOTES: none
*****************************************************************************/
void automac_init(void)
{
uint8_t i = 0;
for (i = 0; i < MAC_SLOTS_MAX; i++) {
Auto_MAC_Data[i].token = false;
Auto_MAC_Data[i].emitter = false;
Auto_MAC_Data[i].pfm = false;
if (i < MAC_SLOTS_OFFSET) {
Auto_MAC_Data[i].reserved = true;
} else {
Auto_MAC_Data[i].reserved = false;
}
}
automac_address_init();
PFM_Cycle_Complete = false;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "ctest.h"
/* test the ring buffer */
void test_Auto_MAC(
Test * pTest)
{
uint8_t mac = 255;
automac_init();
ct_test(pTest, automac_free_address_count() == 0);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == 255);
automac_pfm_set(MAC_SLOTS_OFFSET);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == MAC_SLOTS_OFFSET);
ct_test(pTest, automac_free_address_count() == 1);
automac_token_set(MAC_SLOTS_OFFSET);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == 255);
ct_test(pTest, automac_free_address_count() == 0);
automac_pfm_set(127);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == 127);
ct_test(pTest, automac_free_address_count() == 1);
automac_token_set(127);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == 255);
ct_test(pTest, automac_free_address_count() == 0);
/* the ANSI rand() uses consistent sequence based on seed */
srand(42);
mac = automac_free_address_random();
ct_test(pTest, mac == 255);
automac_pfm_set(MAC_SLOTS_OFFSET+1);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+1));
mac = automac_free_address_random();
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+1));
/* test 2 free addresses */
automac_pfm_set(MAC_SLOTS_OFFSET+2);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+1));
mac = automac_free_address_mac(1);
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+2));
mac = automac_free_address_random();
ct_test(pTest,
(mac == (MAC_SLOTS_OFFSET+1)) ||
(mac == (MAC_SLOTS_OFFSET+2)));
/* test 3 free addresses */
automac_pfm_set(126);
mac = automac_free_address_mac(0);
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+1));
mac = automac_free_address_mac(1);
ct_test(pTest, mac == (MAC_SLOTS_OFFSET+2));
mac = automac_free_address_mac(2);
ct_test(pTest, mac == 126);
mac = automac_free_address_random();
ct_test(pTest,
(mac == (MAC_SLOTS_OFFSET+1))||
(mac == (MAC_SLOTS_OFFSET+2))||
(mac == 126));
/* test the stored address */
mac = automac_address();
ct_test(pTest, mac < MAC_SLOTS_MAX);
automac_address_set(MAC_SLOTS_OFFSET);
mac = automac_address();
ct_test(pTest, mac == MAC_SLOTS_OFFSET);
automac_init();
automac_token_set(0x6B);
mac = automac_next_station(0x25);
ct_test(pTest, mac == 0x6B);
}
#ifdef TEST_AUTOMAC
int main(
void)
{
Test *pTest;
bool rc;
pTest = ct_create("Auto MAC", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, test_Auto_MAC);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif
#endif
+59 -59
View File
@@ -1,59 +1,59 @@
/**************************************************************************
*
* Copyright (C) 2010 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 AUTOMAC_H
#define AUTOMAC_H
#include <stdbool.h>
#include <stdint.h>
/* MS/TP Auto MAC address functionality */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void automac_init(void);
bool automac_free_address_valid(uint8_t mac);
uint8_t automac_free_address_count(void);
uint8_t automac_free_address_mac(uint8_t count);
uint8_t automac_free_address_random(void);
void automac_pfm_set(uint8_t mac);
void automac_token_set(uint8_t mac);
void automac_emitter_set(uint8_t mac);
uint8_t automac_next_station(uint8_t mac);
uint8_t automac_address(void);
void automac_address_set(uint8_t mac);
void automac_address_init(void);
uint16_t automac_time_slot(void);
bool automac_pfm_cycle_complete(void);
bool automac_enabled(void);
void automac_enabled_set(bool status);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2010 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 AUTOMAC_H
#define AUTOMAC_H
#include <stdbool.h>
#include <stdint.h>
/* MS/TP Auto MAC address functionality */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void automac_init(void);
bool automac_free_address_valid(uint8_t mac);
uint8_t automac_free_address_count(void);
uint8_t automac_free_address_mac(uint8_t count);
uint8_t automac_free_address_random(void);
void automac_pfm_set(uint8_t mac);
void automac_token_set(uint8_t mac);
void automac_emitter_set(uint8_t mac);
uint8_t automac_next_station(uint8_t mac);
uint8_t automac_address(void);
void automac_address_set(uint8_t mac);
void automac_address_init(void);
uint16_t automac_time_slot(void);
bool automac_pfm_cycle_complete(void);
bool automac_enabled(void);
void automac_enabled_set(bool status);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+133 -133
View File
@@ -1,133 +1,133 @@
/**************************************************************************
*
* Copyright (C) 2011 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 <stdint.h>
#include <stdbool.h>
/* hardware layer includes */
#include "hardware.h"
#include "timer.h"
#include "rs485.h"
/* BACnet Stack includes */
#include "datalink.h"
#include "npdu.h"
#include "handlers.h"
#include "client.h"
#include "txbuf.h"
#include "dcc.h"
#include "iam.h"
/* BACnet objects */
#include "device.h"
#include "bo.h"
/* me */
#include "bacnet.h"
/* timer for device communications control */
static struct itimer DCC_Timer;
#define DCC_CYCLE_SECONDS 1
void bacnet_init(
void)
{
dlmstp_set_mac_address(255);
dlmstp_set_max_master(127);
/* initialize datalink layer */
dlmstp_init(NULL);
/* initialize objects */
Device_Init(NULL);
/* set up our confirmed service unrecognized service handler - required! */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has);
/* Set the handlers for any confirmed services that we support. */
/* We must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
handler_read_property_multiple);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
handler_reinitialize_device);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
handler_write_property);
/* handle communication so we can shutup when asked */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
/* start the cyclic 1 second timer for DCC */
timer_interval_start_seconds(&DCC_Timer, DCC_CYCLE_SECONDS);
/* Hello World! */
Send_I_Am(&Handler_Transmit_Buffer[0]);
}
static uint8_t PDUBuffer[MAX_MPDU];
void bacnet_task(
void)
{
uint16_t pdu_len;
BACNET_ADDRESS src; /* source address */
uint8_t i;
BACNET_BINARY_PV binary_value = BINARY_INACTIVE;
BACNET_POLARITY polarity;
bool out_of_service;
/* Binary Output */
for (i = 0; i < MAX_BINARY_OUTPUTS; i++) {
out_of_service = Binary_Output_Out_Of_Service(i);
if (!out_of_service) {
binary_value = Binary_Output_Present_Value(i);
polarity = Binary_Output_Polarity(i);
if (polarity != POLARITY_NORMAL) {
if (binary_value == BINARY_ACTIVE) {
binary_value = BINARY_INACTIVE;
} else {
binary_value = BINARY_ACTIVE;
}
}
if (binary_value == BINARY_ACTIVE) {
if (i == 0) {
/* led_on(LED_2); */
} else {
/* led_on(LED_3); */
}
} else {
if (i == 0) {
/* led_off(LED_2); */
} else {
/* led_off(LED_3); */
}
}
}
}
/* handle the communication timer */
if (timer_interval_expired(&DCC_Timer)) {
timer_interval_reset(&DCC_Timer);
dcc_timer_seconds(DCC_CYCLE_SECONDS);
}
/* handle the messaging */
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
if (pdu_len) {
npdu_handler(&src, &PDUBuffer[0], pdu_len);
}
}
/**************************************************************************
*
* Copyright (C) 2011 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 <stdint.h>
#include <stdbool.h>
/* hardware layer includes */
#include "hardware.h"
#include "timer.h"
#include "rs485.h"
/* BACnet Stack includes */
#include "datalink.h"
#include "npdu.h"
#include "handlers.h"
#include "client.h"
#include "txbuf.h"
#include "dcc.h"
#include "iam.h"
/* BACnet objects */
#include "device.h"
#include "bo.h"
/* me */
#include "bacnet.h"
/* timer for device communications control */
static struct itimer DCC_Timer;
#define DCC_CYCLE_SECONDS 1
void bacnet_init(
void)
{
dlmstp_set_mac_address(255);
dlmstp_set_max_master(127);
/* initialize datalink layer */
dlmstp_init(NULL);
/* initialize objects */
Device_Init(NULL);
/* set up our confirmed service unrecognized service handler - required! */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has);
/* Set the handlers for any confirmed services that we support. */
/* We must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
handler_read_property_multiple);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
handler_reinitialize_device);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
handler_write_property);
/* handle communication so we can shutup when asked */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
/* start the cyclic 1 second timer for DCC */
timer_interval_start_seconds(&DCC_Timer, DCC_CYCLE_SECONDS);
/* Hello World! */
Send_I_Am(&Handler_Transmit_Buffer[0]);
}
static uint8_t PDUBuffer[MAX_MPDU];
void bacnet_task(
void)
{
uint16_t pdu_len;
BACNET_ADDRESS src; /* source address */
uint8_t i;
BACNET_BINARY_PV binary_value = BINARY_INACTIVE;
BACNET_POLARITY polarity;
bool out_of_service;
/* Binary Output */
for (i = 0; i < MAX_BINARY_OUTPUTS; i++) {
out_of_service = Binary_Output_Out_Of_Service(i);
if (!out_of_service) {
binary_value = Binary_Output_Present_Value(i);
polarity = Binary_Output_Polarity(i);
if (polarity != POLARITY_NORMAL) {
if (binary_value == BINARY_ACTIVE) {
binary_value = BINARY_INACTIVE;
} else {
binary_value = BINARY_ACTIVE;
}
}
if (binary_value == BINARY_ACTIVE) {
if (i == 0) {
/* led_on(LED_2); */
} else {
/* led_on(LED_3); */
}
} else {
if (i == 0) {
/* led_off(LED_2); */
} else {
/* led_off(LED_3); */
}
}
}
}
/* handle the communication timer */
if (timer_interval_expired(&DCC_Timer)) {
timer_interval_reset(&DCC_Timer);
dcc_timer_seconds(DCC_CYCLE_SECONDS);
}
/* handle the messaging */
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
if (pdu_len) {
npdu_handler(&src, &PDUBuffer[0], pdu_len);
}
}
+41 -41
View File
@@ -1,41 +1,41 @@
/**************************************************************************
*
* Copyright (C) 2010 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 BACNET_H
#define BACNET_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void bacnet_init(
void);
void bacnet_task(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2010 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 BACNET_H
#define BACNET_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void bacnet_init(
void);
void bacnet_task(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+33 -33
View File
@@ -1,33 +1,33 @@
/**************************************************************************
*
* Copyright (C) 2011 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 HARDWARE_H
#define HARDWARE_H
#include "stm32f10x_conf.h"
#include "stm32f10x_it.h"
#define MAX_BINARY_OUTPUTS 2
#endif
/**************************************************************************
*
* Copyright (C) 2011 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 HARDWARE_H
#define HARDWARE_H
#include "stm32f10x_conf.h"
#include "stm32f10x_it.h"
#define MAX_BINARY_OUTPUTS 2
#endif
+308 -308
View File
@@ -1,308 +1,308 @@
/**************************************************************************
*
* Copyright (C) 2011 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 <stdint.h>
#include "hardware.h"
#include "timer.h"
#include "led.h"
static struct itimer Off_Delay_Timer_Rx;
static struct itimer Off_Delay_Timer_Tx;
static bool Rx_State;
static bool Tx_State;
static bool LD3_State;
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_tx_on(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_15, Bit_SET);
timer_interval_no_expire(&Off_Delay_Timer_Tx);
Tx_State = true;
}
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_rx_on(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_14, Bit_SET);
timer_interval_no_expire(&Off_Delay_Timer_Rx);
Rx_State = true;
}
/*************************************************************************
* Description: Deactivate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_tx_off(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_15, Bit_RESET);
timer_interval_no_expire(&Off_Delay_Timer_Tx);
Tx_State = false;
}
/*************************************************************************
* Description: Deactivate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_rx_off(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_14, Bit_RESET);
timer_interval_no_expire(&Off_Delay_Timer_Rx);
Rx_State = false;
}
/*************************************************************************
* Description: Get the state of the LED
* Returns: true if on, false if off.
* Notes: none
*************************************************************************/
bool led_rx_state(void)
{
return Rx_State;
}
/*************************************************************************
* Description: Get the state of the LED
* Returns: true if on, false if off.
* Notes: none
*************************************************************************/
bool led_tx_state(void)
{
return Tx_State;
}
/*************************************************************************
* Description: Toggle the state of the LED
* Returns: none
* Notes: none
*************************************************************************/
void led_tx_toggle(void)
{
if (led_tx_state()) {
led_tx_off();
} else {
led_tx_on();
}
}
/*************************************************************************
* Description: Toggle the state of the LED
* Returns: none
* Notes: none
*************************************************************************/
void led_rx_toggle(void)
{
if (led_rx_state()) {
led_rx_off();
} else {
led_rx_on();
}
}
/*************************************************************************
* Description: Delay before going off to give minimum brightness.
* Returns: none
* Notes: none
*************************************************************************/
void led_rx_off_delay(
uint32_t delay_ms)
{
timer_interval_start(&Off_Delay_Timer_Rx, delay_ms);
}
/*************************************************************************
* Description: Delay before going off to give minimum brightness.
* Returns: none
* Notes: none
*************************************************************************/
void led_tx_off_delay(
uint32_t delay_ms)
{
timer_interval_start(&Off_Delay_Timer_Tx, delay_ms);
}
/*************************************************************************
* Description: Turn on, and delay before going off.
* Returns: none
* Notes: none
*************************************************************************/
void led_rx_on_interval(
uint16_t interval_ms)
{
led_rx_on();
timer_interval_start(&Off_Delay_Timer_Rx, interval_ms);
}
/*************************************************************************
* Description: Turn on, and delay before going off.
* Returns: none
* Notes: none
*************************************************************************/
void led_tx_on_interval(
uint16_t interval_ms)
{
led_tx_on();
timer_interval_start(&Off_Delay_Timer_Tx, interval_ms);
}
/*************************************************************************
* Description: Task for blinking LED
* Returns: none
* Notes: none
*************************************************************************/
void led_task(
void)
{
if (timer_interval_expired(&Off_Delay_Timer_Rx)) {
timer_interval_no_expire(&Off_Delay_Timer_Rx);
led_rx_off();
}
if (timer_interval_expired(&Off_Delay_Timer_Tx)) {
timer_interval_no_expire(&Off_Delay_Timer_Tx);
led_tx_off();
}
}
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_ld4_on(
void)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET);
}
/*************************************************************************
* Description: Deactivate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_ld4_off(
void)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_RESET);
}
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_ld3_on(
void)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_SET);
LD3_State = true;
}
/*************************************************************************
* Description: Deactivate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_ld3_off(
void)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_RESET);
LD3_State = false;
}
/*************************************************************************
* Description: Get the state of the LED
* Returns: true if on, false if off.
* Notes: none
*************************************************************************/
bool led_ld3_state(void)
{
return LD3_State;
}
/*************************************************************************
* Description: Toggle the state of the LED
* Returns: none
* Notes: none
*************************************************************************/
void led_ld3_toggle(void)
{
if (led_ld3_state()) {
led_ld3_off();
} else {
led_ld3_on();
}
}
/*************************************************************************
* Description: Initialize the LED hardware
* Returns: none
* Notes: none
*************************************************************************/
void led_init(
void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
/* Configure the Receive LED on MS/TP board */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure the Transmit LED on MS/TP board */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* Configure the LD4 on Discovery board */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure the LD3 on Discovery board */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Enable the GPIO_LED Clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
led_tx_on();
led_rx_on();
led_ld3_on();
led_ld4_on();
}
/**************************************************************************
*
* Copyright (C) 2011 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 <stdint.h>
#include "hardware.h"
#include "timer.h"
#include "led.h"
static struct itimer Off_Delay_Timer_Rx;
static struct itimer Off_Delay_Timer_Tx;
static bool Rx_State;
static bool Tx_State;
static bool LD3_State;
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_tx_on(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_15, Bit_SET);
timer_interval_no_expire(&Off_Delay_Timer_Tx);
Tx_State = true;
}
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_rx_on(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_14, Bit_SET);
timer_interval_no_expire(&Off_Delay_Timer_Rx);
Rx_State = true;
}
/*************************************************************************
* Description: Deactivate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_tx_off(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_15, Bit_RESET);
timer_interval_no_expire(&Off_Delay_Timer_Tx);
Tx_State = false;
}
/*************************************************************************
* Description: Deactivate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_rx_off(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_14, Bit_RESET);
timer_interval_no_expire(&Off_Delay_Timer_Rx);
Rx_State = false;
}
/*************************************************************************
* Description: Get the state of the LED
* Returns: true if on, false if off.
* Notes: none
*************************************************************************/
bool led_rx_state(void)
{
return Rx_State;
}
/*************************************************************************
* Description: Get the state of the LED
* Returns: true if on, false if off.
* Notes: none
*************************************************************************/
bool led_tx_state(void)
{
return Tx_State;
}
/*************************************************************************
* Description: Toggle the state of the LED
* Returns: none
* Notes: none
*************************************************************************/
void led_tx_toggle(void)
{
if (led_tx_state()) {
led_tx_off();
} else {
led_tx_on();
}
}
/*************************************************************************
* Description: Toggle the state of the LED
* Returns: none
* Notes: none
*************************************************************************/
void led_rx_toggle(void)
{
if (led_rx_state()) {
led_rx_off();
} else {
led_rx_on();
}
}
/*************************************************************************
* Description: Delay before going off to give minimum brightness.
* Returns: none
* Notes: none
*************************************************************************/
void led_rx_off_delay(
uint32_t delay_ms)
{
timer_interval_start(&Off_Delay_Timer_Rx, delay_ms);
}
/*************************************************************************
* Description: Delay before going off to give minimum brightness.
* Returns: none
* Notes: none
*************************************************************************/
void led_tx_off_delay(
uint32_t delay_ms)
{
timer_interval_start(&Off_Delay_Timer_Tx, delay_ms);
}
/*************************************************************************
* Description: Turn on, and delay before going off.
* Returns: none
* Notes: none
*************************************************************************/
void led_rx_on_interval(
uint16_t interval_ms)
{
led_rx_on();
timer_interval_start(&Off_Delay_Timer_Rx, interval_ms);
}
/*************************************************************************
* Description: Turn on, and delay before going off.
* Returns: none
* Notes: none
*************************************************************************/
void led_tx_on_interval(
uint16_t interval_ms)
{
led_tx_on();
timer_interval_start(&Off_Delay_Timer_Tx, interval_ms);
}
/*************************************************************************
* Description: Task for blinking LED
* Returns: none
* Notes: none
*************************************************************************/
void led_task(
void)
{
if (timer_interval_expired(&Off_Delay_Timer_Rx)) {
timer_interval_no_expire(&Off_Delay_Timer_Rx);
led_rx_off();
}
if (timer_interval_expired(&Off_Delay_Timer_Tx)) {
timer_interval_no_expire(&Off_Delay_Timer_Tx);
led_tx_off();
}
}
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_ld4_on(
void)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET);
}
/*************************************************************************
* Description: Deactivate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_ld4_off(
void)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_RESET);
}
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_ld3_on(
void)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_SET);
LD3_State = true;
}
/*************************************************************************
* Description: Deactivate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
void led_ld3_off(
void)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_RESET);
LD3_State = false;
}
/*************************************************************************
* Description: Get the state of the LED
* Returns: true if on, false if off.
* Notes: none
*************************************************************************/
bool led_ld3_state(void)
{
return LD3_State;
}
/*************************************************************************
* Description: Toggle the state of the LED
* Returns: none
* Notes: none
*************************************************************************/
void led_ld3_toggle(void)
{
if (led_ld3_state()) {
led_ld3_off();
} else {
led_ld3_on();
}
}
/*************************************************************************
* Description: Initialize the LED hardware
* Returns: none
* Notes: none
*************************************************************************/
void led_init(
void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
/* Configure the Receive LED on MS/TP board */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure the Transmit LED on MS/TP board */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* Configure the LD4 on Discovery board */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure the LD3 on Discovery board */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Enable the GPIO_LED Clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
led_tx_on();
led_rx_on();
led_ld3_on();
led_ld4_on();
}
+75 -75
View File
@@ -1,75 +1,75 @@
/**************************************************************************
*
* Copyright (C) 2009 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 LED_H
#define LED_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void led_ld3_on(
void);
void led_ld4_on(
void);
void led_ld3_off(
void);
void led_ld4_off(
void);
bool led_ld3_state(void);
void led_ld3_toggle(void);
void led_tx_on(void);
void led_rx_on(void);
void led_tx_on_interval(
uint16_t interval_ms);
void led_rx_on_interval(
uint16_t interval_ms);
void led_tx_off(void);
void led_rx_off(void);
void led_tx_off_delay(
uint32_t delay_ms);
void led_rx_off_delay(
uint32_t delay_ms);
void led_tx_toggle(void);
void led_rx_toggle(void);
bool led_tx_state(void);
bool led_rx_state(void);
void led_task(
void);
void led_init(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2009 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 LED_H
#define LED_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void led_ld3_on(
void);
void led_ld4_on(
void);
void led_ld3_off(
void);
void led_ld4_off(
void);
bool led_ld3_state(void);
void led_ld3_toggle(void);
void led_tx_on(void);
void led_rx_on(void);
void led_tx_on_interval(
uint16_t interval_ms);
void led_rx_on_interval(
uint16_t interval_ms);
void led_tx_off(void);
void led_rx_off(void);
void led_tx_off_delay(
uint32_t delay_ms);
void led_rx_off_delay(
uint32_t delay_ms);
void led_tx_toggle(void);
void led_rx_toggle(void);
bool led_tx_state(void);
bool led_rx_state(void);
void led_task(
void);
void led_init(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+142 -142
View File
@@ -1,142 +1,142 @@
/************************************************************************
*
* Copyright (C) 2011 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 <stdbool.h>
#include <stdint.h>
#include "hardware.h"
#include "timer.h"
#include "timer.h"
#include "rs485.h"
#include "led.h"
#include "bacnet.h"
/* local version override */
char *BACnet_Version = "1.0";
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/* Private define ------------------------------------------------------------*/
#define LSE_FAIL_FLAG 0x80
#define LSE_PASS_FLAG 0x100
void lse_init(void)
{
uint32_t LSE_Delay = 0;
struct etimer Delay_Timer;
/* Enable access to the backup register => LSE can be enabled */
PWR_BackupAccessCmd(ENABLE);
/* Enable LSE (Low Speed External Oscillation) */
RCC_LSEConfig(RCC_LSE_ON);
/* Check the LSE Status */
while(1)
{
if(LSE_Delay < LSE_FAIL_FLAG)
{
timer_elapsed_start(&Delay_Timer);
while (!timer_elapsed_milliseconds(&Delay_Timer,500)) {
/* do nothing */
}
/* check whether LSE is ready, with 4 seconds timeout */
LSE_Delay += 0x10;
if(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != RESET)
{
/* Set flag: LSE PASS */
LSE_Delay |= LSE_PASS_FLAG;
led_ld4_off();
/* Disable LSE */
RCC_LSEConfig(RCC_LSE_OFF);
break;
}
}
/* LSE_FAIL_FLAG = 0x80 */
else if(LSE_Delay >= LSE_FAIL_FLAG)
{
if(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
/* Set flag: LSE FAIL */
LSE_Delay |= LSE_FAIL_FLAG;
led_ld4_on();
}
/* Disable LSE */
RCC_LSEConfig(RCC_LSE_OFF);
break;
}
}
}
int main(
void)
{
struct itimer Blink_Timer;
/*At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f10x_xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f10x.c file */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
led_init();
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
RCC_APB2Periph_GPIOE, ENABLE);
timer_init();
lse_init();
led_init();
rs485_init();
bacnet_init();
timer_interval_start(&Blink_Timer, 125);
for (;;) {
if (timer_interval_expired(&Blink_Timer)) {
timer_interval_reset(&Blink_Timer);
led_ld3_toggle();
}
led_task();
bacnet_task();
}
}
/************************************************************************
*
* Copyright (C) 2011 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 <stdbool.h>
#include <stdint.h>
#include "hardware.h"
#include "timer.h"
#include "timer.h"
#include "rs485.h"
#include "led.h"
#include "bacnet.h"
/* local version override */
char *BACnet_Version = "1.0";
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/* Private define ------------------------------------------------------------*/
#define LSE_FAIL_FLAG 0x80
#define LSE_PASS_FLAG 0x100
void lse_init(void)
{
uint32_t LSE_Delay = 0;
struct etimer Delay_Timer;
/* Enable access to the backup register => LSE can be enabled */
PWR_BackupAccessCmd(ENABLE);
/* Enable LSE (Low Speed External Oscillation) */
RCC_LSEConfig(RCC_LSE_ON);
/* Check the LSE Status */
while(1)
{
if(LSE_Delay < LSE_FAIL_FLAG)
{
timer_elapsed_start(&Delay_Timer);
while (!timer_elapsed_milliseconds(&Delay_Timer,500)) {
/* do nothing */
}
/* check whether LSE is ready, with 4 seconds timeout */
LSE_Delay += 0x10;
if(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != RESET)
{
/* Set flag: LSE PASS */
LSE_Delay |= LSE_PASS_FLAG;
led_ld4_off();
/* Disable LSE */
RCC_LSEConfig(RCC_LSE_OFF);
break;
}
}
/* LSE_FAIL_FLAG = 0x80 */
else if(LSE_Delay >= LSE_FAIL_FLAG)
{
if(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
/* Set flag: LSE FAIL */
LSE_Delay |= LSE_FAIL_FLAG;
led_ld4_on();
}
/* Disable LSE */
RCC_LSEConfig(RCC_LSE_OFF);
break;
}
}
}
int main(
void)
{
struct itimer Blink_Timer;
/*At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f10x_xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f10x.c file */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
led_init();
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
RCC_APB2Periph_GPIOE, ENABLE);
timer_init();
lse_init();
led_init();
rs485_init();
bacnet_init();
timer_interval_start(&Blink_Timer, 125);
for (;;) {
if (timer_interval_expired(&Blink_Timer)) {
timer_interval_reset(&Blink_Timer);
led_ld3_toggle();
}
led_task();
bacnet_task();
}
}
+340 -340
View File
@@ -1,340 +1,340 @@
/**************************************************************************
*
* Copyright (C) 2011 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.
*
* Module Description:
* Handle the configuration and operation of the RS485 bus.
**************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "timer.h"
#include "bits.h"
#include "fifo.h"
#include "led.h"
#include "rs485.h"
/* buffer for storing received bytes - size must be power of two */
static uint8_t Receive_Buffer_Data[512];
static FIFO_BUFFER Receive_Buffer;
/* amount of silence on the wire */
static struct etimer Silence_Timer;
/* baud rate */
static uint32_t Baud_Rate = 38400;
/* The minimum time after the end of the stop bit of the final octet of a */
/* received frame before a node may enable its EIA-485 driver: 40 bit times. */
/* At 9600 baud, 40 bit times would be about 4.166 milliseconds */
/* At 19200 baud, 40 bit times would be about 2.083 milliseconds */
/* At 38400 baud, 40 bit times would be about 1.041 milliseconds */
/* At 57600 baud, 40 bit times would be about 0.694 milliseconds */
/* At 76800 baud, 40 bit times would be about 0.520 milliseconds */
/* At 115200 baud, 40 bit times would be about 0.347 milliseconds */
/* 40 bits is 4 octets including a start and stop bit with each octet */
#define Tturnaround (40UL)
/*************************************************************************
* Description: Reset the silence on the wire timer.
* Returns: nothing
* Notes: none
**************************************************************************/
void rs485_silence_reset(void)
{
timer_elapsed_start(&Silence_Timer);
}
/*************************************************************************
* Description: Determine the amount of silence on the wire from the timer.
* Returns: true if the amount of time has elapsed
* Notes: none
**************************************************************************/
bool rs485_silence_elapsed(uint32_t interval)
{
return timer_elapsed_milliseconds(&Silence_Timer, interval);
}
/*************************************************************************
* Description: Baud rate determines turnaround time.
* Returns: amount of milliseconds
* Notes: none
**************************************************************************/
static uint16_t rs485_turnaround_time(
void)
{
/* delay after reception before transmitting - per MS/TP spec */
/* wait a minimum 40 bit times since reception */
/* at least 2 ms for errors: rounding, clock tick */
return (2 + ((Tturnaround * 1000UL) / Baud_Rate));
}
/*************************************************************************
* Description: Use the silence timer to determine turnaround time.
* Returns: true if turnaround time has expired.
* Notes: none
**************************************************************************/
bool rs485_turnaround_elapsed(
void)
{
return timer_elapsed_milliseconds(
&Silence_Timer,
rs485_turnaround_time());
}
/*************************************************************************
* Description: Determines if an error occured while receiving
* Returns: true an error occurred.
* Notes: none
**************************************************************************/
bool rs485_receive_error(
void)
{
return false;
}
/*********************************************************************//**
* @brief USARTx interrupt handler sub-routine
* @param[in] None
* @return None
**********************************************************************/
void USART2_IRQHandler(void)
{
uint8_t data_byte;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
/* Read one byte from the receive data register */
data_byte = USART_ReceiveData(USART2);
(void)FIFO_Put(&Receive_Buffer, data_byte);
}
}
/*************************************************************************
* DESCRIPTION: Return true if a byte is available
* RETURN: true if a byte is available, with the byte in the parameter
* NOTES: none
**************************************************************************/
bool rs485_byte_available(
uint8_t * data_register)
{
bool data_available = false; /* return value */
if (!FIFO_Empty(&Receive_Buffer)) {
*data_register = FIFO_Get(&Receive_Buffer);
timer_elapsed_start(&Silence_Timer);
data_available = true;
led_rx_on_interval(10);
}
return data_available;
}
/*************************************************************************
* DESCRIPTION: Sends a byte of data
* RETURN: nothing
* NOTES: none
**************************************************************************/
void rs485_byte_send(uint8_t tx_byte)
{
led_tx_on_interval(10);
USART_SendData(USART2, tx_byte);
timer_elapsed_start(&Silence_Timer);
}
/*************************************************************************
* Description: Determines if a byte in the USART has been shifted from
* register
* Returns: true if the USART register is empty
* Notes: none
**************************************************************************/
bool rs485_byte_sent(void)
{
return USART_GetFlagStatus(USART2, USART_FLAG_TXE);
}
/*************************************************************************
* Description: Determines if the entire frame is sent from USART FIFO
* Returns: true if the USART FIFO is empty
* Notes: none
**************************************************************************/
bool rs485_frame_sent(void)
{
return USART_GetFlagStatus(USART2, USART_FLAG_TC);
}
/*************************************************************************
* DESCRIPTION: Send some data and wait until it is sent
* RETURN: true if a collision or timeout occurred
* NOTES: none
**************************************************************************/
void rs485_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes) /* number of bytes of data */
{
uint8_t tx_byte;
while (nbytes) {
/* Send the data byte */
tx_byte = *buffer;
/* Send one byte */
USART_SendData(USART2, tx_byte);
while (!rs485_byte_sent()) {
/* do nothing - wait until Tx buffer is empty */
}
buffer++;
nbytes--;
}
/* was the frame sent? */
while (!rs485_frame_sent()) {
/* do nothing - wait until the entire frame in the
Transmit Shift Register has been shifted out */
}
timer_elapsed_start(&Silence_Timer);
return;
}
/*************************************************************************
* Description: Configures the baud rate of the USART
* Returns: nothing
* Notes: none
**************************************************************************/
static void rs485_baud_rate_configure(
void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = Baud_Rate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USARTx */
USART_Init(USART2, &USART_InitStructure);
}
/*************************************************************************
* Description: Sets the baud rate to non-volatile storeage and configures USART
* Returns: true if a value baud rate was saved
* Notes: none
**************************************************************************/
bool rs485_baud_rate_set(
uint32_t baud)
{
bool valid = true;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
Baud_Rate = baud;
rs485_baud_rate_configure();
break;
default:
valid = false;
break;
}
return valid;
}
/*************************************************************************
* Description: Determines the baud rate in bps
* Returns: baud rate in bps
* Notes: none
**************************************************************************/
uint32_t rs485_baud_rate(
void)
{
return Baud_Rate;
}
/*************************************************************************
* Description: Enable the Request To Send (RTS) aka Transmit Enable pin
* Returns: nothing
* Notes: none
**************************************************************************/
void rs485_rts_enable(
bool enable)
{
if (enable) {
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
} else {
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);
}
}
/*************************************************************************
* Description: Initialize the room network USART
* Returns: nothing
* Notes: none
**************************************************************************/
void rs485_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
/* Configure USARTx Rx as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USARTx Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure the Request To Send (RTS) aka Transmit Enable pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable USARTx Clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* Enable GPIO Clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* enable the USART to generate interrupts */
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
rs485_baud_rate_set(Baud_Rate);
USART_Cmd(USART2, ENABLE);
FIFO_Init(&Receive_Buffer, &Receive_Buffer_Data[0],
(unsigned)sizeof(Receive_Buffer_Data));
timer_elapsed_start(&Silence_Timer);
}
/**************************************************************************
*
* Copyright (C) 2011 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.
*
* Module Description:
* Handle the configuration and operation of the RS485 bus.
**************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "timer.h"
#include "bits.h"
#include "fifo.h"
#include "led.h"
#include "rs485.h"
/* buffer for storing received bytes - size must be power of two */
static uint8_t Receive_Buffer_Data[512];
static FIFO_BUFFER Receive_Buffer;
/* amount of silence on the wire */
static struct etimer Silence_Timer;
/* baud rate */
static uint32_t Baud_Rate = 38400;
/* The minimum time after the end of the stop bit of the final octet of a */
/* received frame before a node may enable its EIA-485 driver: 40 bit times. */
/* At 9600 baud, 40 bit times would be about 4.166 milliseconds */
/* At 19200 baud, 40 bit times would be about 2.083 milliseconds */
/* At 38400 baud, 40 bit times would be about 1.041 milliseconds */
/* At 57600 baud, 40 bit times would be about 0.694 milliseconds */
/* At 76800 baud, 40 bit times would be about 0.520 milliseconds */
/* At 115200 baud, 40 bit times would be about 0.347 milliseconds */
/* 40 bits is 4 octets including a start and stop bit with each octet */
#define Tturnaround (40UL)
/*************************************************************************
* Description: Reset the silence on the wire timer.
* Returns: nothing
* Notes: none
**************************************************************************/
void rs485_silence_reset(void)
{
timer_elapsed_start(&Silence_Timer);
}
/*************************************************************************
* Description: Determine the amount of silence on the wire from the timer.
* Returns: true if the amount of time has elapsed
* Notes: none
**************************************************************************/
bool rs485_silence_elapsed(uint32_t interval)
{
return timer_elapsed_milliseconds(&Silence_Timer, interval);
}
/*************************************************************************
* Description: Baud rate determines turnaround time.
* Returns: amount of milliseconds
* Notes: none
**************************************************************************/
static uint16_t rs485_turnaround_time(
void)
{
/* delay after reception before transmitting - per MS/TP spec */
/* wait a minimum 40 bit times since reception */
/* at least 2 ms for errors: rounding, clock tick */
return (2 + ((Tturnaround * 1000UL) / Baud_Rate));
}
/*************************************************************************
* Description: Use the silence timer to determine turnaround time.
* Returns: true if turnaround time has expired.
* Notes: none
**************************************************************************/
bool rs485_turnaround_elapsed(
void)
{
return timer_elapsed_milliseconds(
&Silence_Timer,
rs485_turnaround_time());
}
/*************************************************************************
* Description: Determines if an error occured while receiving
* Returns: true an error occurred.
* Notes: none
**************************************************************************/
bool rs485_receive_error(
void)
{
return false;
}
/*********************************************************************//**
* @brief USARTx interrupt handler sub-routine
* @param[in] None
* @return None
**********************************************************************/
void USART2_IRQHandler(void)
{
uint8_t data_byte;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
/* Read one byte from the receive data register */
data_byte = USART_ReceiveData(USART2);
(void)FIFO_Put(&Receive_Buffer, data_byte);
}
}
/*************************************************************************
* DESCRIPTION: Return true if a byte is available
* RETURN: true if a byte is available, with the byte in the parameter
* NOTES: none
**************************************************************************/
bool rs485_byte_available(
uint8_t * data_register)
{
bool data_available = false; /* return value */
if (!FIFO_Empty(&Receive_Buffer)) {
*data_register = FIFO_Get(&Receive_Buffer);
timer_elapsed_start(&Silence_Timer);
data_available = true;
led_rx_on_interval(10);
}
return data_available;
}
/*************************************************************************
* DESCRIPTION: Sends a byte of data
* RETURN: nothing
* NOTES: none
**************************************************************************/
void rs485_byte_send(uint8_t tx_byte)
{
led_tx_on_interval(10);
USART_SendData(USART2, tx_byte);
timer_elapsed_start(&Silence_Timer);
}
/*************************************************************************
* Description: Determines if a byte in the USART has been shifted from
* register
* Returns: true if the USART register is empty
* Notes: none
**************************************************************************/
bool rs485_byte_sent(void)
{
return USART_GetFlagStatus(USART2, USART_FLAG_TXE);
}
/*************************************************************************
* Description: Determines if the entire frame is sent from USART FIFO
* Returns: true if the USART FIFO is empty
* Notes: none
**************************************************************************/
bool rs485_frame_sent(void)
{
return USART_GetFlagStatus(USART2, USART_FLAG_TC);
}
/*************************************************************************
* DESCRIPTION: Send some data and wait until it is sent
* RETURN: true if a collision or timeout occurred
* NOTES: none
**************************************************************************/
void rs485_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes) /* number of bytes of data */
{
uint8_t tx_byte;
while (nbytes) {
/* Send the data byte */
tx_byte = *buffer;
/* Send one byte */
USART_SendData(USART2, tx_byte);
while (!rs485_byte_sent()) {
/* do nothing - wait until Tx buffer is empty */
}
buffer++;
nbytes--;
}
/* was the frame sent? */
while (!rs485_frame_sent()) {
/* do nothing - wait until the entire frame in the
Transmit Shift Register has been shifted out */
}
timer_elapsed_start(&Silence_Timer);
return;
}
/*************************************************************************
* Description: Configures the baud rate of the USART
* Returns: nothing
* Notes: none
**************************************************************************/
static void rs485_baud_rate_configure(
void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = Baud_Rate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USARTx */
USART_Init(USART2, &USART_InitStructure);
}
/*************************************************************************
* Description: Sets the baud rate to non-volatile storeage and configures USART
* Returns: true if a value baud rate was saved
* Notes: none
**************************************************************************/
bool rs485_baud_rate_set(
uint32_t baud)
{
bool valid = true;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
Baud_Rate = baud;
rs485_baud_rate_configure();
break;
default:
valid = false;
break;
}
return valid;
}
/*************************************************************************
* Description: Determines the baud rate in bps
* Returns: baud rate in bps
* Notes: none
**************************************************************************/
uint32_t rs485_baud_rate(
void)
{
return Baud_Rate;
}
/*************************************************************************
* Description: Enable the Request To Send (RTS) aka Transmit Enable pin
* Returns: nothing
* Notes: none
**************************************************************************/
void rs485_rts_enable(
bool enable)
{
if (enable) {
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
} else {
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);
}
}
/*************************************************************************
* Description: Initialize the room network USART
* Returns: nothing
* Notes: none
**************************************************************************/
void rs485_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
/* Configure USARTx Rx as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USARTx Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure the Request To Send (RTS) aka Transmit Enable pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable USARTx Clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* Enable GPIO Clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* enable the USART to generate interrupts */
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
rs485_baud_rate_set(Baud_Rate);
USART_Cmd(USART2, ENABLE);
FIFO_Init(&Receive_Buffer, &Receive_Buffer_Data[0],
(unsigned)sizeof(Receive_Buffer_Data));
timer_elapsed_start(&Silence_Timer);
}
+66 -66
View File
@@ -1,66 +1,66 @@
/**************************************************************************
*
* Copyright (C) 2011 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.
*
* Module Description:
* Handle the configuration and operation of the RS485 bus.
**************************************************************************/
#ifndef RS485_H
#define RS485_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void rs485_init(
void);
void rs485_rts_enable(
bool enable);
bool rs485_byte_available(
uint8_t * data_register);
bool rs485_receive_error(
void);
void rs485_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes); /* number of bytes of data */
uint32_t rs485_baud_rate(
void);
bool rs485_baud_rate_set(
uint32_t baud);
/* a granular approach */
void rs485_byte_send(
uint8_t data_register);
bool rs485_byte_sent(void);
bool rs485_frame_sent(void);
bool rs485_turnaround_elapsed(
void);
void rs485_silence_reset(void);
bool rs485_silence_elapsed(uint32_t interval);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2011 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.
*
* Module Description:
* Handle the configuration and operation of the RS485 bus.
**************************************************************************/
#ifndef RS485_H
#define RS485_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void rs485_init(
void);
void rs485_rts_enable(
bool enable);
bool rs485_byte_available(
uint8_t * data_register);
bool rs485_receive_error(
void);
void rs485_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes); /* number of bytes of data */
uint32_t rs485_baud_rate(
void);
bool rs485_baud_rate_set(
uint32_t baud);
/* a granular approach */
void rs485_byte_send(
uint8_t data_register);
bool rs485_byte_sent(void);
bool rs485_frame_sent(void);
bool rs485_turnaround_elapsed(
void);
void rs485_silence_reset(void);
bool rs485_silence_elapsed(uint32_t interval);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+74 -74
View File
@@ -1,74 +1,74 @@
/**
******************************************************************************
* @file I2C/EEPROM/stm32f10x_conf.h
* @author MCD Application Team
* @version V3.4.0
* @date 10/15/2010
* @brief Library configuration file.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_CONF_H
#define __STM32F10x_CONF_H
/* Includes ------------------------------------------------------------------*/
/* Uncomment the line below to enable peripheral header file inclusion */
#include "stm32f10x_adc.h"
#include "stm32f10x_bkp.h"
#include "stm32f10x_can.h"
#include "stm32f10x_cec.h"
#include "stm32f10x_crc.h"
#include "stm32f10x_dac.h"
#include "stm32f10x_dbgmcu.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_fsmc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_iwdg.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_sdio.h"
#include "stm32f10x_spi.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_wwdg.h"
#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Uncomment the line below to expanse the "assert_param" macro in the
Standard Peripheral Library drivers code */
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
#endif /* __STM32F10x_CONF_H */
/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file I2C/EEPROM/stm32f10x_conf.h
* @author MCD Application Team
* @version V3.4.0
* @date 10/15/2010
* @brief Library configuration file.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_CONF_H
#define __STM32F10x_CONF_H
/* Includes ------------------------------------------------------------------*/
/* Uncomment the line below to enable peripheral header file inclusion */
#include "stm32f10x_adc.h"
#include "stm32f10x_bkp.h"
#include "stm32f10x_can.h"
#include "stm32f10x_cec.h"
#include "stm32f10x_crc.h"
#include "stm32f10x_dac.h"
#include "stm32f10x_dbgmcu.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_fsmc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_iwdg.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_sdio.h"
#include "stm32f10x_spi.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_wwdg.h"
#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Uncomment the line below to expanse the "assert_param" macro in the
Standard Peripheral Library drivers code */
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
#endif /* __STM32F10x_CONF_H */
/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
+133 -133
View File
@@ -1,133 +1,133 @@
/**
******************************************************************************
* @file I2C/EEPROM/stm32f10x_it.c
* @author MCD Application Team
* @version V3.4.0
* @date 10/15/2010
* @brief Main Interrupt Service Routines.
* This file provides template for all exceptions handler and
* peripherals interrupt service routine.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
/** @addtogroup STM32F10x_StdPeriph_Examples
* @{
*/
/** @addtogroup I2C_EEPROM
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/******************************************************************************/
/* Cortex-M3 Processor Exceptions Handlers */
/******************************************************************************/
/**
* @brief This function handles NMI exception.
* @param None
* @retval None
*/
void NMI_Handler(void)
{
}
/**
* @brief This function handles Hard Fault exception.
* @param None
* @retval None
*/
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{
}
}
/**
* @brief This function handles Memory Manage exception.
* @param None
* @retval None
*/
void MemManage_Handler(void)
{
/* Go to infinite loop when Memory Manage exception occurs */
while (1)
{
}
}
/**
* @brief This function handles Bus Fault exception.
* @param None
* @retval None
*/
void BusFault_Handler(void)
{
/* Go to infinite loop when Bus Fault exception occurs */
while (1)
{
}
}
/**
* @brief This function handles Usage Fault exception.
* @param None
* @retval None
*/
void UsageFault_Handler(void)
{
/* Go to infinite loop when Usage Fault exception occurs */
while (1)
{
}
}
/**
* @brief This function handles SVCall exception.
* @param None
* @retval None
*/
void SVC_Handler(void)
{
}
/**
* @brief This function handles Debug Monitor exception.
* @param None
* @retval None
*/
void DebugMon_Handler(void)
{
}
/**
* @brief This function handles PendSV_Handler exception.
* @param None
* @retval None
*/
void PendSV_Handler(void)
{
}
/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file I2C/EEPROM/stm32f10x_it.c
* @author MCD Application Team
* @version V3.4.0
* @date 10/15/2010
* @brief Main Interrupt Service Routines.
* This file provides template for all exceptions handler and
* peripherals interrupt service routine.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
/** @addtogroup STM32F10x_StdPeriph_Examples
* @{
*/
/** @addtogroup I2C_EEPROM
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/******************************************************************************/
/* Cortex-M3 Processor Exceptions Handlers */
/******************************************************************************/
/**
* @brief This function handles NMI exception.
* @param None
* @retval None
*/
void NMI_Handler(void)
{
}
/**
* @brief This function handles Hard Fault exception.
* @param None
* @retval None
*/
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{
}
}
/**
* @brief This function handles Memory Manage exception.
* @param None
* @retval None
*/
void MemManage_Handler(void)
{
/* Go to infinite loop when Memory Manage exception occurs */
while (1)
{
}
}
/**
* @brief This function handles Bus Fault exception.
* @param None
* @retval None
*/
void BusFault_Handler(void)
{
/* Go to infinite loop when Bus Fault exception occurs */
while (1)
{
}
}
/**
* @brief This function handles Usage Fault exception.
* @param None
* @retval None
*/
void UsageFault_Handler(void)
{
/* Go to infinite loop when Usage Fault exception occurs */
while (1)
{
}
}
/**
* @brief This function handles SVCall exception.
* @param None
* @retval None
*/
void SVC_Handler(void)
{
}
/**
* @brief This function handles Debug Monitor exception.
* @param None
* @retval None
*/
void DebugMon_Handler(void)
{
}
/**
* @brief This function handles PendSV_Handler exception.
* @param None
* @retval None
*/
void PendSV_Handler(void)
{
}
/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
+44 -44
View File
@@ -1,44 +1,44 @@
/**
******************************************************************************
* @file I2C/EEPROM/stm32f10x_it.h
* @author MCD Application Team
* @version V3.4.0
* @date 10/15/2010
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_IT_H
#define __STM32F10x_IT_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
#endif /* __STM32F10x_IT_H */
/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file I2C/EEPROM/stm32f10x_it.h
* @author MCD Application Team
* @version V3.4.0
* @date 10/15/2010
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_IT_H
#define __STM32F10x_IT_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
#endif /* __STM32F10x_IT_H */
/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
File diff suppressed because it is too large Load Diff
+431 -431
View File
@@ -1,431 +1,431 @@
/**************************************************************************
*
* Copyright (C) 2009 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 <stdbool.h>
#include <stdint.h>
#include "timer.h"
/* generic elapsed timer handling */
/* interval not to exceed 49.7 days */
/* interval of 1ms may be 0 to 1ms */
/*************************************************************************
* Description: Sets the start time for an elapsed timer
* Returns: the value of the start timer
* Notes: none
*************************************************************************/
void timer_elapsed_start(
struct etimer *t)
{
uint32_t now = timer_milliseconds();
if (t) {
t->start = now;
}
}
/*************************************************************************
* Description: Gets the amount of elapsed time in milliseconds
* Returns: elapsed time in milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_elapsed_time(
struct etimer *t)
{
uint32_t now = timer_milliseconds();
uint32_t delta = 0;
if (t) {
delta = now - t->start;
}
return delta;
}
/*************************************************************************
* Description: Sets the start time with an offset
* Returns: elapsed time in milliseconds
* Notes: none
*************************************************************************/
void timer_elapsed_start_offset(
struct etimer *t,
uint32_t offset)
{
uint32_t now = timer_milliseconds();
if (t) {
t->start = now + offset;
}
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_milliseconds(
struct etimer *t,
uint32_t milliseconds)
{
return (timer_elapsed_time(t) >= milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_seconds(
struct etimer * t,
uint32_t seconds)
{
uint32_t milliseconds = seconds;
milliseconds *= 1000L;
return timer_elapsed_milliseconds(t, milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_minutes(
struct etimer * t,
uint32_t minutes)
{
uint32_t milliseconds = minutes;
milliseconds *= 1000L;
milliseconds *= 60L;
return timer_elapsed_milliseconds(t, milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_milliseconds_short(
struct etimer * t,
uint16_t value)
{
uint32_t milliseconds;
milliseconds = value;
return (timer_elapsed_time(t) >= milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_seconds_short(
struct etimer * t,
uint16_t value)
{
return timer_elapsed_seconds(t, value);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_minutes_short(
struct etimer * t,
uint16_t value)
{
return timer_elapsed_minutes(t, value);
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start(
struct itimer *t,
uint32_t interval)
{
if (t) {
t->start = timer_milliseconds();
t->interval = interval;
}
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start_seconds(
struct itimer *t,
uint32_t seconds)
{
uint32_t interval = seconds;
interval *= 1000L;
timer_interval_start(t, interval);
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start_minutes(
struct itimer *t,
uint32_t minutes)
{
uint32_t interval = minutes;
interval *= 1000L;
interval *= 60L;
timer_interval_start(t, interval);
}
/*************************************************************************
* Description: Determines the amount of time that has elapsed
* Returns: elapsed milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_interval_elapsed(
struct itimer *t)
{
uint32_t now = timer_milliseconds();
uint32_t delta = 0;
if (t) {
delta = now - t->start;
}
return delta;
}
/*************************************************************************
* Description: Determines the amount of time that has elapsed
* Returns: elapsed milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_interval(
struct itimer * t)
{
uint32_t interval = 0;
if (t) {
interval = t->interval;
}
return interval;
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_interval_expired(
struct itimer * t)
{
bool expired = false;
if (t) {
if (t->interval) {
expired = timer_interval_elapsed(t) >= t->interval;
}
}
return expired;
}
/*************************************************************************
* Description: Sets the interval value to zero so it never expires
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_no_expire(
struct itimer *t)
{
if (t) {
t->interval = 0;
}
}
/*************************************************************************
* Description: Adds another interval to the start time. Used for cyclic
* timers that won't lose ticks.
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_reset(
struct itimer *t)
{
if (t) {
t->start += t->interval;
}
}
/*************************************************************************
* Description: Restarts the timer with the same interval
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_restart(
struct itimer *t)
{
if (t) {
t->start = timer_milliseconds();
}
}
/*************************************************************************
* Description: Return the elapsed time
* Returns: number of milliseconds elapsed
* Notes: only up to 255ms elapsed
**************************************************************************/
uint8_t timer_milliseconds_delta(
uint8_t start)
{
return (timer_milliseconds_byte() - start);
}
/*************************************************************************
* Description: Mark the start of a delta timer
* Returns: mark timer starting tick
* Notes: only up to 255ms elapsed
**************************************************************************/
uint8_t timer_milliseconds_mark(
void)
{
return timer_milliseconds_byte();
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
static uint32_t Milliseconds;
uint32_t timer_milliseconds(
void)
{
return Milliseconds;
}
uint32_t timer_milliseconds_set(
uint32_t value)
{
uint32_t old_value = Milliseconds;
Milliseconds = value;
return old_value;
}
void testElapsedTimer(
Test * pTest)
{
struct etimer t;
uint32_t test_time = 0;
timer_milliseconds_set(test_time);
timer_elapsed_start(&t);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
test_time = 0xffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
test_time = 0xffffffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
}
void testIntervalTimer(
Test * pTest)
{
struct itimer t;
uint32_t interval = 0;
uint32_t test_time = 0;
timer_milliseconds_set(test_time);
timer_interval_start(&t, interval);
test_time = 0xffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_interval(&t) == interval);
ct_test(pTest, timer_interval_elapsed(&t) == test_time);
test_time = 0xffffffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_interval(&t) == interval);
ct_test(pTest, timer_interval_elapsed(&t) == test_time);
test_time = 0;
timer_milliseconds_set(test_time);
interval = 0xffff;
timer_interval_start(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 0xffffffff;
timer_interval_start(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 0;
timer_interval_start_seconds(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 60L;
timer_interval_start_seconds(&t, interval);
interval *= 1000L;
ct_test(pTest, timer_interval(&t) == interval);
}
#ifdef TEST_TIMER
int main(
void)
{
Test *pTest;
bool rc;
pTest = ct_create("Timer", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testElapsedTimer);
assert(rc);
rc = ct_addTestFunction(pTest, testIntervalTimer);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif
#endif
/**************************************************************************
*
* Copyright (C) 2009 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 <stdbool.h>
#include <stdint.h>
#include "timer.h"
/* generic elapsed timer handling */
/* interval not to exceed 49.7 days */
/* interval of 1ms may be 0 to 1ms */
/*************************************************************************
* Description: Sets the start time for an elapsed timer
* Returns: the value of the start timer
* Notes: none
*************************************************************************/
void timer_elapsed_start(
struct etimer *t)
{
uint32_t now = timer_milliseconds();
if (t) {
t->start = now;
}
}
/*************************************************************************
* Description: Gets the amount of elapsed time in milliseconds
* Returns: elapsed time in milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_elapsed_time(
struct etimer *t)
{
uint32_t now = timer_milliseconds();
uint32_t delta = 0;
if (t) {
delta = now - t->start;
}
return delta;
}
/*************************************************************************
* Description: Sets the start time with an offset
* Returns: elapsed time in milliseconds
* Notes: none
*************************************************************************/
void timer_elapsed_start_offset(
struct etimer *t,
uint32_t offset)
{
uint32_t now = timer_milliseconds();
if (t) {
t->start = now + offset;
}
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_milliseconds(
struct etimer *t,
uint32_t milliseconds)
{
return (timer_elapsed_time(t) >= milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_seconds(
struct etimer * t,
uint32_t seconds)
{
uint32_t milliseconds = seconds;
milliseconds *= 1000L;
return timer_elapsed_milliseconds(t, milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_minutes(
struct etimer * t,
uint32_t minutes)
{
uint32_t milliseconds = minutes;
milliseconds *= 1000L;
milliseconds *= 60L;
return timer_elapsed_milliseconds(t, milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_milliseconds_short(
struct etimer * t,
uint16_t value)
{
uint32_t milliseconds;
milliseconds = value;
return (timer_elapsed_time(t) >= milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_seconds_short(
struct etimer * t,
uint16_t value)
{
return timer_elapsed_seconds(t, value);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_minutes_short(
struct etimer * t,
uint16_t value)
{
return timer_elapsed_minutes(t, value);
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start(
struct itimer *t,
uint32_t interval)
{
if (t) {
t->start = timer_milliseconds();
t->interval = interval;
}
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start_seconds(
struct itimer *t,
uint32_t seconds)
{
uint32_t interval = seconds;
interval *= 1000L;
timer_interval_start(t, interval);
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start_minutes(
struct itimer *t,
uint32_t minutes)
{
uint32_t interval = minutes;
interval *= 1000L;
interval *= 60L;
timer_interval_start(t, interval);
}
/*************************************************************************
* Description: Determines the amount of time that has elapsed
* Returns: elapsed milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_interval_elapsed(
struct itimer *t)
{
uint32_t now = timer_milliseconds();
uint32_t delta = 0;
if (t) {
delta = now - t->start;
}
return delta;
}
/*************************************************************************
* Description: Determines the amount of time that has elapsed
* Returns: elapsed milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_interval(
struct itimer * t)
{
uint32_t interval = 0;
if (t) {
interval = t->interval;
}
return interval;
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_interval_expired(
struct itimer * t)
{
bool expired = false;
if (t) {
if (t->interval) {
expired = timer_interval_elapsed(t) >= t->interval;
}
}
return expired;
}
/*************************************************************************
* Description: Sets the interval value to zero so it never expires
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_no_expire(
struct itimer *t)
{
if (t) {
t->interval = 0;
}
}
/*************************************************************************
* Description: Adds another interval to the start time. Used for cyclic
* timers that won't lose ticks.
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_reset(
struct itimer *t)
{
if (t) {
t->start += t->interval;
}
}
/*************************************************************************
* Description: Restarts the timer with the same interval
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_restart(
struct itimer *t)
{
if (t) {
t->start = timer_milliseconds();
}
}
/*************************************************************************
* Description: Return the elapsed time
* Returns: number of milliseconds elapsed
* Notes: only up to 255ms elapsed
**************************************************************************/
uint8_t timer_milliseconds_delta(
uint8_t start)
{
return (timer_milliseconds_byte() - start);
}
/*************************************************************************
* Description: Mark the start of a delta timer
* Returns: mark timer starting tick
* Notes: only up to 255ms elapsed
**************************************************************************/
uint8_t timer_milliseconds_mark(
void)
{
return timer_milliseconds_byte();
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
static uint32_t Milliseconds;
uint32_t timer_milliseconds(
void)
{
return Milliseconds;
}
uint32_t timer_milliseconds_set(
uint32_t value)
{
uint32_t old_value = Milliseconds;
Milliseconds = value;
return old_value;
}
void testElapsedTimer(
Test * pTest)
{
struct etimer t;
uint32_t test_time = 0;
timer_milliseconds_set(test_time);
timer_elapsed_start(&t);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
test_time = 0xffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
test_time = 0xffffffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
}
void testIntervalTimer(
Test * pTest)
{
struct itimer t;
uint32_t interval = 0;
uint32_t test_time = 0;
timer_milliseconds_set(test_time);
timer_interval_start(&t, interval);
test_time = 0xffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_interval(&t) == interval);
ct_test(pTest, timer_interval_elapsed(&t) == test_time);
test_time = 0xffffffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_interval(&t) == interval);
ct_test(pTest, timer_interval_elapsed(&t) == test_time);
test_time = 0;
timer_milliseconds_set(test_time);
interval = 0xffff;
timer_interval_start(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 0xffffffff;
timer_interval_start(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 0;
timer_interval_start_seconds(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 60L;
timer_interval_start_seconds(&t, interval);
interval *= 1000L;
ct_test(pTest, timer_interval(&t) == interval);
}
#ifdef TEST_TIMER
int main(
void)
{
Test *pTest;
bool rc;
pTest = ct_create("Timer", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testElapsedTimer);
assert(rc);
rc = ct_addTestFunction(pTest, testIntervalTimer);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif
#endif
+115 -115
View File
@@ -1,115 +1,115 @@
/**************************************************************************
*
* Copyright (C) 2009 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 TIMER_H
#define TIMER_H
#include <stdbool.h>
#include <stdint.h>
/* Timer Module */
/* elapsed timer structure */
struct etimer {
uint32_t start;
};
/* interval timer structure */
struct itimer {
uint32_t start;
uint32_t interval;
};
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* these 3 functions are created in the hardware specific module */
void timer_init(
void);
uint32_t timer_milliseconds(
void);
uint8_t timer_milliseconds_byte(
void);
/* these functions are in the generic timer.c module */
/* elapsed timer */
void timer_elapsed_start(
struct etimer *t);
void timer_elapsed_start_offset(
struct etimer *t,
uint32_t offset);
uint32_t timer_elapsed_time(
struct etimer *t);
bool timer_elapsed_milliseconds(
struct etimer *t,
uint32_t value);
bool timer_elapsed_seconds(
struct etimer *t,
uint32_t value);
bool timer_elapsed_minutes(
struct etimer *t,
uint32_t value);
bool timer_elapsed_milliseconds_short(
struct etimer *t,
uint16_t value);
bool timer_elapsed_seconds_short(
struct etimer *t,
uint16_t value);
bool timer_elapsed_minutes_short(
struct etimer *t,
uint16_t value);
/* interval timer */
void timer_interval_start(
struct itimer *t,
uint32_t interval);
void timer_interval_start_seconds(
struct itimer *t,
uint32_t interval);
void timer_interval_start_minutes(
struct itimer *t,
uint32_t interval);
bool timer_interval_expired(
struct itimer *t);
uint32_t timer_interval(
struct itimer *t);
uint32_t timer_interval_elapsed(
struct itimer *t);
void timer_interval_no_expire(
struct itimer *t);
void timer_interval_reset(
struct itimer *t);
void timer_interval_restart(
struct itimer *t);
/* special for 8-bit microcontrollers - limited to 255ms */
uint8_t timer_milliseconds_delta(
uint8_t start);
uint8_t timer_milliseconds_mark(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2009 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 TIMER_H
#define TIMER_H
#include <stdbool.h>
#include <stdint.h>
/* Timer Module */
/* elapsed timer structure */
struct etimer {
uint32_t start;
};
/* interval timer structure */
struct itimer {
uint32_t start;
uint32_t interval;
};
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* these 3 functions are created in the hardware specific module */
void timer_init(
void);
uint32_t timer_milliseconds(
void);
uint8_t timer_milliseconds_byte(
void);
/* these functions are in the generic timer.c module */
/* elapsed timer */
void timer_elapsed_start(
struct etimer *t);
void timer_elapsed_start_offset(
struct etimer *t,
uint32_t offset);
uint32_t timer_elapsed_time(
struct etimer *t);
bool timer_elapsed_milliseconds(
struct etimer *t,
uint32_t value);
bool timer_elapsed_seconds(
struct etimer *t,
uint32_t value);
bool timer_elapsed_minutes(
struct etimer *t,
uint32_t value);
bool timer_elapsed_milliseconds_short(
struct etimer *t,
uint16_t value);
bool timer_elapsed_seconds_short(
struct etimer *t,
uint16_t value);
bool timer_elapsed_minutes_short(
struct etimer *t,
uint16_t value);
/* interval timer */
void timer_interval_start(
struct itimer *t,
uint32_t interval);
void timer_interval_start_seconds(
struct itimer *t,
uint32_t interval);
void timer_interval_start_minutes(
struct itimer *t,
uint32_t interval);
bool timer_interval_expired(
struct itimer *t);
uint32_t timer_interval(
struct itimer *t);
uint32_t timer_interval_elapsed(
struct itimer *t);
void timer_interval_no_expire(
struct itimer *t);
void timer_interval_reset(
struct itimer *t);
void timer_interval_restart(
struct itimer *t);
/* special for 8-bit microcontrollers - limited to 255ms */
uint8_t timer_milliseconds_delta(
uint8_t start);
uint8_t timer_milliseconds_mark(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+121 -121
View File
@@ -1,121 +1,121 @@
/**************************************************************************
*
* Copyright (C) 2011 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.
*
* Module Description:
* Generate a periodic timer tick for use by generic timers in the code.
*
*************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "hardware.h"
#include "timer.h"
#include "debug.h"
/* counter for the various timers */
static volatile uint32_t Millisecond_Counter;
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
static void timer_debug_on(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_13, Bit_SET);
}
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
static void timer_debug_off(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_13, Bit_RESET);
}
/*************************************************************************
* Description: Toggle the state of the setup LED
* Returns: none
* Notes: none
*************************************************************************/
void timer_debug_toggle(void)
{
static bool state = false;
if (state) {
timer_debug_off();
state = false;
} else {
timer_debug_on();
state = true;
}
}
/*************************************************************************
* Description: Interrupt Service Routine
* Returns: nothing
* Notes: reserved name for ISR handlers
*************************************************************************/
void SysTick_Handler(void)
{
/* increment the tick count */
Millisecond_Counter++;
timer_debug_toggle();
}
/*************************************************************************
* Description: returns the current millisecond count
* Returns: none
* Notes: none
*************************************************************************/
uint32_t timer_milliseconds(void)
{
return Millisecond_Counter;
}
/*************************************************************************
* Description: Timer setup for 1 millisecond timer
* Returns: none
* Notes: peripheral frequency defined in hardware.h
*************************************************************************/
void timer_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
/* Configure the Receive LED */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Setup SysTick Timer for 1ms interrupts */
if (SysTick_Config(SystemCoreClock / 1000)) {
/* Capture error */
while (1);
}
}
/**************************************************************************
*
* Copyright (C) 2011 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.
*
* Module Description:
* Generate a periodic timer tick for use by generic timers in the code.
*
*************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "hardware.h"
#include "timer.h"
#include "debug.h"
/* counter for the various timers */
static volatile uint32_t Millisecond_Counter;
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
static void timer_debug_on(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_13, Bit_SET);
}
/*************************************************************************
* Description: Activate the LED
* Returns: nothing
* Notes: none
**************************************************************************/
static void timer_debug_off(
void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_13, Bit_RESET);
}
/*************************************************************************
* Description: Toggle the state of the setup LED
* Returns: none
* Notes: none
*************************************************************************/
void timer_debug_toggle(void)
{
static bool state = false;
if (state) {
timer_debug_off();
state = false;
} else {
timer_debug_on();
state = true;
}
}
/*************************************************************************
* Description: Interrupt Service Routine
* Returns: nothing
* Notes: reserved name for ISR handlers
*************************************************************************/
void SysTick_Handler(void)
{
/* increment the tick count */
Millisecond_Counter++;
timer_debug_toggle();
}
/*************************************************************************
* Description: returns the current millisecond count
* Returns: none
* Notes: none
*************************************************************************/
uint32_t timer_milliseconds(void)
{
return Millisecond_Counter;
}
/*************************************************************************
* Description: Timer setup for 1 millisecond timer
* Returns: none
* Notes: peripheral frequency defined in hardware.h
*************************************************************************/
void timer_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
/* Configure the Receive LED */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Setup SysTick Timer for 1ms interrupts */
if (SysTick_Config(SystemCoreClock / 1000)) {
/* Capture error */
while (1);
}
}
+173 -173
View File
@@ -1,180 +1,180 @@
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* 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 <stdint.h>
#include "bacapp.h"
#include "bacenum.h"
#include "bacdcode.h"
#include "bacdef.h"
#include "wp.h"
#include "wpm.h"
/** @file wpm.c Encode/Decode BACnet Write Property Multiple APDUs */
/* decode service */
int wpm_decode_object_id(uint8_t * apdu, uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA * data)
{
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint32_t object_instance = 0;
uint16_t object_type = 0;
uint16_t len = 0;
if((apdu )&& (apdu_len))
{
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* 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 <stdint.h>
#include "bacapp.h"
#include "bacenum.h"
#include "bacdcode.h"
#include "bacdef.h"
#include "wp.h"
#include "wpm.h"
/** @file wpm.c Encode/Decode BACnet Write Property Multiple APDUs */
/* decode service */
int wpm_decode_object_id(uint8_t * apdu, uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA * data)
{
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint32_t object_instance = 0;
uint16_t object_type = 0;
uint16_t len = 0;
if((apdu )&& (apdu_len))
{
/* Context tag 0 - Object ID
*/
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if(tag_number == 0)
{
len += decode_object_id(&apdu[len], &object_type, &object_instance);
data->object_type = object_type;
data->object_instance = object_instance;
}
else
return -1;
}
else
return -1;
return len;
}
int wpm_decode_object_property(uint8_t * apdu,
uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint32_t ulVal = 0;
int len = 0, i = 0;
if((apdu) && (apdu_len) && (wp_data))
{
wp_data->array_index = BACNET_ARRAY_ALL;
wp_data->priority = BACNET_NO_PRIORITY;
wp_data->application_data_len = 0;
*/
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if(tag_number == 0)
{
len += decode_object_id(&apdu[len], &object_type, &object_instance);
data->object_type = object_type;
data->object_instance = object_instance;
}
else
return -1;
}
else
return -1;
return len;
}
int wpm_decode_object_property(uint8_t * apdu,
uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint32_t ulVal = 0;
int len = 0, i = 0;
if((apdu) && (apdu_len) && (wp_data))
{
wp_data->array_index = BACNET_ARRAY_ALL;
wp_data->priority = BACNET_NO_PRIORITY;
wp_data->application_data_len = 0;
/* tag 0 - Property Identifier
*/
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if(tag_number == 0)
{
len += decode_enumerated(&apdu[len], len_value, &ulVal);
wp_data->object_property = ulVal;
}
else
/* tag 0 - Property Identifier
*/
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if(tag_number == 0)
{
len += decode_enumerated(&apdu[len], len_value, &ulVal);
wp_data->object_property = ulVal;
}
else
return -1;
/* tag 1 - Property Array Index - optional
*/
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if(tag_number ==1)
{
len += decode_unsigned(&apdu[len],len_value, &ulVal);
wp_data->array_index = ulVal;
/* tag 1 - Property Array Index - optional
*/
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if(tag_number ==1)
{
len += decode_unsigned(&apdu[len],len_value, &ulVal);
wp_data->array_index = ulVal;
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
}
/* tag 2 - Property Value
*/
if((tag_number == 2) && (decode_is_opening_tag(&apdu[len-1])))
{
len--;
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
}
/* tag 2 - Property Value
*/
if((tag_number == 2) && (decode_is_opening_tag(&apdu[len-1])))
{
len--;
wp_data->application_data_len = bacapp_data_len(&apdu[len],
apdu_len - len, wp_data->object_property);
len++;
/* copy application data
*/
apdu_len - len, wp_data->object_property);
len++;
/* copy application data
*/
for(i = 0; i < wp_data->application_data_len; i++)
wp_data->application_data[i] = apdu[len+i];
len += wp_data->application_data_len;
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
/* closing tag 2
*/
wp_data->application_data[i] = apdu[len+i];
len += wp_data->application_data_len;
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
/* closing tag 2
*/
if((tag_number != 2) &&(decode_is_closing_tag(&apdu[len-1])))
return -1;
}
else
return -1;
/* tag 3 - Priority - optional
*/
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if(tag_number == 3)
{
uint32_t priority = BACNET_NO_PRIORITY;
len += decode_unsigned(&apdu[len], len_value, &priority);
wp_data->priority = priority;
}
else
len--;
}
else
return -1;
return len;
}
int wpm_ack_encode_apdu_init(uint8_t * apdu, uint8_t invoke_id)
{
int len = 0;
if (apdu) {
apdu[len++] = PDU_TYPE_SIMPLE_ACK;
apdu[len++] = invoke_id;
apdu[len++] = SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE;
}
return len;
}
int wpm_error_ack_encode_apdu(uint8_t * apdu, uint8_t invoke_id,
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
int len = 0;
if (apdu)
{
apdu[len++] = PDU_TYPE_ERROR;
apdu[len++] = invoke_id;
apdu[len++] = SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE;
len += encode_opening_tag(&apdu[len], 0);
len += encode_application_enumerated(&apdu[len], wp_data->error_class);
len += encode_application_enumerated(&apdu[len], wp_data->error_code);
len += encode_closing_tag(&apdu[len], 0);
len += encode_opening_tag(&apdu[len], 1);
len += encode_context_object_id(&apdu[len], 0,
wp_data->object_type, wp_data->object_instance);
len += encode_context_enumerated(&apdu[len], 1,
wp_data->object_property);
return -1;
}
else
return -1;
/* tag 3 - Priority - optional
*/
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
if(tag_number == 3)
{
uint32_t priority = BACNET_NO_PRIORITY;
len += decode_unsigned(&apdu[len], len_value, &priority);
wp_data->priority = priority;
}
else
len--;
}
else
return -1;
return len;
}
int wpm_ack_encode_apdu_init(uint8_t * apdu, uint8_t invoke_id)
{
int len = 0;
if (apdu) {
apdu[len++] = PDU_TYPE_SIMPLE_ACK;
apdu[len++] = invoke_id;
apdu[len++] = SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE;
}
return len;
}
int wpm_error_ack_encode_apdu(uint8_t * apdu, uint8_t invoke_id,
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
int len = 0;
if (apdu)
{
apdu[len++] = PDU_TYPE_ERROR;
apdu[len++] = invoke_id;
apdu[len++] = SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE;
len += encode_opening_tag(&apdu[len], 0);
len += encode_application_enumerated(&apdu[len], wp_data->error_class);
len += encode_application_enumerated(&apdu[len], wp_data->error_code);
len += encode_closing_tag(&apdu[len], 0);
len += encode_opening_tag(&apdu[len], 1);
len += encode_context_object_id(&apdu[len], 0,
wp_data->object_type, wp_data->object_instance);
len += encode_context_enumerated(&apdu[len], 1,
wp_data->object_property);