Added uBASIC-Plus program object example to STM32F4xx. (#967)

This commit is contained in:
Steve Karg
2025-04-16 12:03:42 -05:00
committed by GitHub
parent a923e3cec9
commit 54bf9b79c6
37 changed files with 7613 additions and 1112 deletions
+25 -5
View File
@@ -1,7 +1,27 @@
---
# Disable formatting for now as there is external code. We should move external
# code to a separate directory and enable formatting for our code.
BasedOnStyle: WebKit
AlignAfterOpenBracket: AlwaysBreak
BinPackArguments: true
BinPackParameters: false
PenaltyBreakBeforeFirstCallParameter: 1
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlignEscapedNewlines: Left
AlignArrayOfStructures: None
PointerAlignment: Right
InsertBraces: true
BreakBeforeBraces: Linux
BreakBeforeBinaryOperators: None
KeepEmptyLinesAtTheStartOfBlocks: false
IndentCaseLabels: true
IndentWidth: 4
UseTab: Never
SortIncludes: false
ColumnLimit: 80
# Const always to left side.
QualifierAlignment: Left
---
Language: JavaScript
DisableFormat: true
# DisableFormat will not disable include sorting with some versions.
SortIncludes: Never
...
+51 -47
View File
@@ -1,49 +1,53 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "cortex-debug",
"request": "launch",
"name": "Debug with OpenOCD",
"cwd": "${workspaceRoot}",
"executable": "${workspaceRoot}/build/bacnet-mstp.elf",
"servertype": "openocd",
"device": "STM32F429ZI",
"serialNumber": "",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"searchDir": [],
"svdFile":"${workspaceRoot}/stm32f429.svd",
"runToEntryPoint": "main",
"liveWatch": {
"enabled": true,
"samplesPerSecond": 1
},
"swoConfig": {
"enabled": true,
"cpuFrequency": 8000000,
"swoFrequency": 2000000,
"source": "probe",
"decoders": [
{ "type": "console", "label": "ITM", "port": 0 }
]
},
"preLaunchCommands": [
// guarantee the halt at soon as possible after reset
"monitor reset",
"monitor sleep 2000",
"monitor reset halt",
// synchronize GDB to the state of the target after reset
"monitor gdb_sync",
"stepi"
],
"postLaunchCommands": [
"monitor reset init",
"monitor sleep 200"
],
"showDevDebugOutput": "raw"
}
]
"version": "0.2.0",
"configurations": [
{
"type": "cortex-debug",
"request": "launch",
"name": "Debug with OpenOCD",
"cwd": "${workspaceRoot}",
"executable": "${workspaceRoot}/build/bacnet-mstp.elf",
"servertype": "openocd",
"device": "STM32F429ZI",
"serialNumber": "",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"searchDir": [],
"svdFile": "${workspaceRoot}/stm32f429.svd",
"runToEntryPoint": "main",
"liveWatch": {
"enabled": true,
"samplesPerSecond": 1
},
"swoConfig": {
"enabled": true,
"cpuFrequency": 8000000,
"swoFrequency": 2000000,
"source": "probe",
"decoders": [
{
"type": "console",
"label": "ITM",
"port": 0
}
]
},
"preLaunchCommands": [
// guarantee the halt at soon as possible after reset
"monitor reset",
"monitor sleep 2000",
"monitor reset halt",
// synchronize GDB to the state of the target after reset
"monitor gdb_sync",
"stepi"
],
"postLaunchCommands": [
"monitor reset init",
"monitor sleep 200"
],
"showDevDebugOutput": "raw"
}
]
}
+6
View File
@@ -151,6 +151,9 @@ set(BACNET_PROJECT_SOURCE
${CMAKE_SOURCE_DIR}/mstimer-init.c
${CMAKE_SOURCE_DIR}/rs485.c
${CMAKE_SOURCE_DIR}/program-ubasic.c
${CMAKE_SOURCE_DIR}/ubasic-port.c
${CMAKE_SOURCE_DIR}/device.c
${CMAKE_SOURCE_DIR}/netport.c
@@ -163,6 +166,9 @@ set(BACNET_PROJECT_SOURCE
${LIBRARY_BACNET_BASIC}/object/ms-input.c
${LIBRARY_BACNET_BASIC}/object/mso.c
${LIBRARY_BACNET_BASIC}/object/msv.c
${LIBRARY_BACNET_BASIC}/object/program.c
${LIBRARY_BACNET_BASIC}/program/ubasic/ubasic.c
${LIBRARY_BACNET_BASIC}/program/ubasic/tokenizer.c
${LIBRARY_BACNET_BASIC}/service/h_dcc.c
${LIBRARY_BACNET_BASIC}/service/h_apdu.c
+6
View File
@@ -29,6 +29,8 @@ PLATFORM_SRC = \
$(PLATFORM_DIR)/netport.c \
$(PLATFORM_DIR)/rs485.c \
$(PLATFORM_DIR)/mstimer-init.c \
$(PLATFORM_DIR)/program-ubasic.c \
$(PLATFORM_DIR)/ubasic-port.c \
$(PLATFORM_DIR)/stm32f4xx_it.c \
$(PLATFORM_DIR)/system_stm32f4xx.c
@@ -43,6 +45,9 @@ BASIC_SRC = \
$(BACNET_BASIC)/object/ms-input.c \
$(BACNET_BASIC)/object/mso.c \
$(BACNET_BASIC)/object/msv.c \
$(BACNET_BASIC)/object/program.c \
$(BACNET_BASIC)/program/ubasic/ubasic.c \
$(BACNET_BASIC)/program/ubasic/tokenizer.c \
$(BACNET_BASIC)/service/h_apdu.c \
$(BACNET_BASIC)/service/h_dcc.c \
$(BACNET_BASIC)/service/h_rd.c \
@@ -173,6 +178,7 @@ BACNET_FLAGS += -DMAX_TSM_TRANSACTIONS=0
BACNET_FLAGS += -DMAX_CHARACTER_STRING_BYTES=64
BACNET_FLAGS += -DMAX_OCTET_STRING_BYTES=64
BACNET_FLAGS += -DBACAPP_MINIMAL
BACNET_FLAGS += -DBACNET_STACK_DEPRECATED_DISABLE
# if called from root Makefile, PRINT was already defined
BACNET_FLAGS += -UPRINT_ENABLED
BACNET_FLAGS += -DPRINT_ENABLED=0
+15 -75
View File
@@ -1,15 +1,16 @@
/**************************************************************************
*
* Copyright (C) 2011 Steve Karg <skarg@users.sourceforge.net>
*
* SPDX-License-Identifier: MIT
*
*********************************************************************/
/**
* @file
* @brief BACnet stack initialization and task processing
* @author Steve Karg
* @date 2011
* @copyright SPDX-License-Identifier: MIT
*/
#include <stdint.h>
#include <stdbool.h>
/* hardware layer includes */
#include "bacnet/basic/sys/mstimer.h"
#include "rs485.h"
#include "program-ubasic.h"
/* BACnet Stack includes */
#include "bacnet/datalink/datalink.h"
#include "bacnet/npdu.h"
@@ -20,15 +21,8 @@
#include "bacnet/iam.h"
/* BACnet objects */
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/object/ai.h"
#include "bacnet/basic/object/ao.h"
#include "bacnet/basic/object/av.h"
#include "bacnet/basic/object/bi.h"
#include "bacnet/basic/object/bo.h"
#include "bacnet/basic/object/bv.h"
#include "bacnet/basic/object/ms-input.h"
#include "bacnet/basic/object/mso.h"
#include "bacnet/basic/object/msv.h"
#include "bacnet/basic/object/program.h"
#include "bacnet/basic/program/ubasic/ubasic.h"
/* me */
#include "bacnet.h"
@@ -38,69 +32,14 @@ static struct mstimer DCC_Timer;
/* Device ID to track changes */
static uint32_t Device_ID = 0xFFFFFFFF;
#ifndef BACNET_ANALOG_INPUTS_MAX
#define BACNET_ANALOG_INPUTS_MAX 12
#endif
#ifndef BACNET_ANALOG_OUTPUTS_MAX
#define BACNET_ANALOG_OUTPUTS_MAX 12
#endif
#ifndef BACNET_ANALOG_VALUES_MAX
#define BACNET_ANALOG_VALUES_MAX 12
#endif
#ifndef BACNET_BINARY_INPUTS_MAX
#define BACNET_BINARY_INPUTS_MAX 12
#endif
#ifndef BACNET_BINARY_OUTPUTS_MAX
#define BACNET_BINARY_OUTPUTS_MAX 12
#endif
#ifndef BACNET_BINARY_VALUES_MAX
#define BACNET_BINARY_VALUES_MAX 12
#endif
#ifndef BACNET_MULTISTATE_INPUTS_MAX
#define BACNET_MULTISTATE_INPUTS_MAX 12
#endif
#ifndef BACNET_MULTISTATE_OUTPUTS_MAX
#define BACNET_MULTISTATE_OUTPUTS_MAX 12
#endif
#ifndef BACNET_MULTISTATE_VALUES_MAX
#define BACNET_MULTISTATE_VALUES_MAX 12
#endif
/**
* @brief Initialize the BACnet device object, the service handlers, and timers
*/
void bacnet_init(void)
{
uint32_t instance;
/* initialize objects */
Device_Init(NULL);
for (instance = 1; instance <= BACNET_ANALOG_INPUTS_MAX; instance++) {
Analog_Input_Create(instance);
}
for (instance = 1; instance <= BACNET_ANALOG_OUTPUTS_MAX; instance++) {
Analog_Output_Create(instance);
}
for (instance = 1; instance <= BACNET_ANALOG_VALUES_MAX; instance++) {
Analog_Value_Create(instance);
}
for (instance = 1; instance <= BACNET_BINARY_INPUTS_MAX; instance++) {
Binary_Input_Create(instance);
}
for (instance = 1; instance <= BACNET_BINARY_OUTPUTS_MAX; instance++) {
Binary_Output_Create(instance);
}
for (instance = 1; instance <= BACNET_BINARY_VALUES_MAX; instance++) {
Binary_Value_Create(instance);
}
for (instance = 1; instance <= BACNET_MULTISTATE_INPUTS_MAX; instance++) {
Multistate_Input_Create(instance);
}
for (instance = 1; instance <= BACNET_MULTISTATE_OUTPUTS_MAX; instance++) {
Multistate_Output_Create(instance);
}
for (instance = 1; instance <= BACNET_MULTISTATE_VALUES_MAX; instance++) {
Multistate_Value_Create(instance);
}
Program_UBASIC_Init(BACNET_MAX_INSTANCE);
/* 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 */
@@ -118,12 +57,12 @@ void bacnet_init(void)
SERVICE_CONFIRMED_WRITE_PROPERTY, handler_write_property);
/* local time and date */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
handler_timesync);
SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION, handler_timesync);
handler_timesync_set_callback_set(datetime_timesync);
datetime_init();
/* handle communication so we can shutup when asked */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
/* start the cyclic 1 second timer for DCC */
mstimer_set(&DCC_Timer, DCC_CYCLE_SECONDS * 1000);
@@ -154,6 +93,7 @@ void bacnet_task(void)
mstimer_reset(&DCC_Timer);
dcc_timer_seconds(DCC_CYCLE_SECONDS);
}
Program_UBASIC_Task();
/* handle the messaging */
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
if (pdu_len) {
+9
View File
@@ -1235,6 +1235,12 @@
</group>
<group>
<name>BACnet Basic System</name>
<file>
<name>$PROJ_DIR$\..\..\src\bacnet\basic\program\ubasic\ubasic.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\src\bacnet\basic\program\ubasic\tokenizer.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\src\bacnet\basic\sys\bigend.c</name>
</file>
@@ -1277,6 +1283,9 @@
<file>
<name>$PROJ_DIR$\system_stm32f4xx.c</name>
</file>
<file>
<name>$PROJ_DIR$\ubasic-port.c</name>
</file>
</group>
<group>
<name>NUCLEO-BACnet</name>
+7 -7
View File
@@ -1,10 +1,10 @@
/**************************************************************************
*
* Copyright (C) 2010 Steve Karg <skarg@users.sourceforge.net>
*
* SPDX-License-Identifier: MIT
*
*********************************************************************/
/**
* @file
* @brief BACnet stack initialization and task processing
* @author Steve Karg
* @date 2021
* @copyright SPDX-License-Identifier: MIT
*/
#ifndef BACNET_H
#define BACNET_H
+61 -41
View File
@@ -1,14 +1,11 @@
/**************************************************************************
*
* Copyright (C) 2011 Steve Karg <skarg@users.sourceforge.net>
*
* SPDX-License-Identifier: MIT
*
*********************************************************************/
/** @file device.c Base "class" for handling all BACnet objects belonging
* to a BACnet device, as well as Device-specific properties. */
/**
* @file
* @brief Base "class" for handling all BACnet objects belonging
* to a BACnet device, as well as Device-specific properties.
* @author Steve Karg
* @date 2021
* @copyright SPDX-License-Identifier: MIT
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
@@ -33,12 +30,12 @@
#include "bacnet/basic/object/ms-input.h"
#include "bacnet/basic/object/mso.h"
#include "bacnet/basic/object/msv.h"
#include "bacnet/basic/object/program.h"
#if (BACNET_PROTOCOL_REVISION >= 17)
#include "bacnet/basic/object/netport.h"
#endif
#include "bacnet/basic/object/device.h"
/* clang-format off */
static struct my_object_functions {
BACNET_OBJECT_TYPE Object_Type;
@@ -93,6 +90,10 @@ static struct my_object_functions {
Multistate_Value_Index_To_Instance, Multistate_Value_Valid_Instance,
Multistate_Value_Object_Name, Multistate_Value_Read_Property,
Multistate_Value_Write_Property, Multistate_Value_Property_Lists},
{ OBJECT_PROGRAM, Program_Init, Program_Count,
Program_Index_To_Instance, Program_Valid_Instance,
Program_Object_Name, Program_Read_Property,
Program_Write_Property, Program_Property_Lists},
#if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
@@ -121,14 +122,27 @@ static uint8_t Device_UUID[16];
static const int Device_Properties_Required[] = {
/* required properties for this object */
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_SYSTEM_STATUS, PROP_VENDOR_NAME,
PROP_VENDOR_IDENTIFIER, PROP_MODEL_NAME, PROP_FIRMWARE_REVISION,
PROP_APPLICATION_SOFTWARE_VERSION, PROP_PROTOCOL_VERSION,
PROP_PROTOCOL_REVISION, PROP_PROTOCOL_SERVICES_SUPPORTED,
PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED, PROP_OBJECT_LIST,
PROP_MAX_APDU_LENGTH_ACCEPTED, PROP_SEGMENTATION_SUPPORTED,
PROP_APDU_TIMEOUT, PROP_NUMBER_OF_APDU_RETRIES, PROP_DEVICE_ADDRESS_BINDING,
PROP_DATABASE_REVISION, -1 };
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_SYSTEM_STATUS,
PROP_VENDOR_NAME,
PROP_VENDOR_IDENTIFIER,
PROP_MODEL_NAME,
PROP_FIRMWARE_REVISION,
PROP_APPLICATION_SOFTWARE_VERSION,
PROP_PROTOCOL_VERSION,
PROP_PROTOCOL_REVISION,
PROP_PROTOCOL_SERVICES_SUPPORTED,
PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED,
PROP_OBJECT_LIST,
PROP_MAX_APDU_LENGTH_ACCEPTED,
PROP_SEGMENTATION_SUPPORTED,
PROP_APDU_TIMEOUT,
PROP_NUMBER_OF_APDU_RETRIES,
PROP_DEVICE_ADDRESS_BINDING,
PROP_DATABASE_REVISION,
-1
};
static const int Device_Properties_Optional[] = {
/* optional properties for this object */
@@ -141,7 +155,8 @@ static const int Device_Properties_Optional[] = {
PROP_LOCAL_TIME,
PROP_UTC_OFFSET,
PROP_DAYLIGHT_SAVINGS_STATUS,
-1 };
-1
};
static const int Device_Properties_Proprietary[] = { -1 };
@@ -153,8 +168,8 @@ static const int Device_Properties_Proprietary[] = { -1 };
* @return Pointer to the group of object helper functions that implement this
* type of Object.
*/
static struct my_object_functions *Device_Objects_Find_Functions(
BACNET_OBJECT_TYPE Object_Type)
static struct my_object_functions *
Device_Objects_Find_Functions(BACNET_OBJECT_TYPE Object_Type)
{
struct my_object_functions *pObject = NULL;
@@ -182,7 +197,8 @@ static struct my_object_functions *Device_Objects_Find_Functions(
* list, separately, the Required, Optional, and Proprietary object
* properties with their counts.
*/
void Device_Objects_Property_List(BACNET_OBJECT_TYPE object_type,
void Device_Objects_Property_List(
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
struct special_property_list_t *pPropertyList)
{
@@ -200,8 +216,9 @@ void Device_Objects_Property_List(BACNET_OBJECT_TYPE object_type,
pObject = Device_Objects_Find_Functions(object_type);
if ((pObject != NULL) && (pObject->Object_RPM_List != NULL)) {
pObject->Object_RPM_List(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList, &pPropertyList->Proprietary.pList);
pObject->Object_RPM_List(
&pPropertyList->Required.pList, &pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
}
/* Fetch the counts if available otherwise zero them */
@@ -430,8 +447,9 @@ bool Device_Set_Object_Instance_Number(uint32_t object_id)
if (object_id <= BACNET_MAX_INSTANCE) {
Object_Instance_Number = object_id;
} else
} else {
status = false;
}
return status;
}
@@ -656,7 +674,8 @@ int Device_Object_List_Element_Encode(
* Object.
* @return True on success or else False if not found.
*/
bool Device_Valid_Object_Name(const BACNET_CHARACTER_STRING *object_name1,
bool Device_Valid_Object_Name(
const BACNET_CHARACTER_STRING *object_name1,
BACNET_OBJECT_TYPE *object_type,
uint32_t *object_instance)
{
@@ -675,7 +694,7 @@ bool Device_Valid_Object_Name(const BACNET_CHARACTER_STRING *object_name1,
pObject = Device_Objects_Find_Functions((BACNET_OBJECT_TYPE)type);
if ((pObject != NULL) && (pObject->Object_Name != NULL) &&
(pObject->Object_Name(instance, &object_name2) &&
characterstring_same(object_name1, &object_name2))) {
characterstring_same(object_name1, &object_name2))) {
found = true;
if (object_type) {
*object_type = type;
@@ -716,7 +735,8 @@ bool Device_Valid_Object_Id(
* @param object_name [out] The Object Name found for this child Object.
* @return True on success or else False if not found.
*/
bool Device_Object_Name_Copy(BACNET_OBJECT_TYPE object_type,
bool Device_Object_Name_Copy(
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
@@ -811,7 +831,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
bitstring_init(&bit_string);
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
/* automatic lookup based on handlers set */
bitstring_set_bit(&bit_string, (uint8_t)i,
bitstring_set_bit(
&bit_string, (uint8_t)i,
apdu_service_supported((BACNET_SERVICES_SUPPORTED)i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
@@ -836,9 +857,9 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index, Device_Object_List_Element_Encode, count,
apdu, apdu_max);
apdu_len = bacnet_array_encode(
rpdata->object_instance, rpdata->array_index,
Device_Object_List_Element_Encode, count, apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -893,8 +914,7 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
break;
case PROP_DAYLIGHT_SAVINGS_STATUS:
datetime_local(&bdate, &btime, &utc_offset_minutes, &dst_active);
apdu_len =
encode_application_boolean(&apdu[0], dst_active);
apdu_len = encode_application_boolean(&apdu[0], dst_active);
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -949,16 +969,16 @@ static int Read_Property_Common(
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(
&apdu[0], rpdata->object_type);
apdu_len =
encode_application_enumerated(&apdu[0], rpdata->object_type);
break;
#if (BACNET_PROTOCOL_REVISION >= 14)
case PROP_PROPERTY_LIST:
Device_Objects_Property_List(
rpdata->object_type, rpdata->object_instance, &property_list);
apdu_len = property_list_encode(rpdata,
property_list.Required.pList, property_list.Optional.pList,
property_list.Proprietary.pList);
apdu_len = property_list_encode(
rpdata, property_list.Required.pList,
property_list.Optional.pList, property_list.Proprietary.pList);
break;
#endif
default:
+7 -7
View File
@@ -1,10 +1,10 @@
/**************************************************************************
*
* Copyright (C) 2011 Steve Karg <skarg@users.sourceforge.net>
*
* SPDX-License-Identifier: MIT
*
*********************************************************************/
/**
* @file
* @brief LED control for the STM32F4xx
* @author Steve Karg
* @date 2021
* @copyright SPDX-License-Identifier: MIT
*/
#include <stdint.h>
#include "stm32f4xx.h"
#include "bacnet/basic/sys/mstimer.h"
+7 -7
View File
@@ -1,10 +1,10 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* SPDX-License-Identifier: MIT
*
*********************************************************************/
/**
* @file
* @brief LED control for the STM32F4xx
* @author Steve Karg
* @date 2021
* @copyright SPDX-License-Identifier: MIT
*/
#ifndef LED_H
#define LED_H
+8 -8
View File
@@ -1,10 +1,10 @@
/************************************************************************
*
* Copyright (C) 2011 Steve Karg <skarg@users.sourceforge.net>
*
* SPDX-License-Identifier: MIT
*
*************************************************************************/
/**
* @file
* @brief Main function for the STM32F4xx NUCLEO board
* @author Steve Karg
* @date 2021
* @copyright SPDX-License-Identifier: MIT
*/
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
@@ -102,7 +102,7 @@ int main(void)
MSTP_Port.ZeroConfigEnabled = true;
MSTP_Port.Zero_Config_Preferred_Station = 0;
MSTP_Port.SlaveNodeEnabled = false;
MSTP_Port.CheckAutoBaud = false;
MSTP_Port.CheckAutoBaud = true;
/* user data */
MSTP_User_Data.RS485_Driver = &RS485_Driver;
MSTP_Port.UserData = &MSTP_User_Data;
+7 -10
View File
@@ -1,13 +1,10 @@
/**************************************************************************
*
* Copyright (C) 2011 Steve Karg <skarg@users.sourceforge.net>
*
* SPDX-License-Identifier: MIT
*
* Module Description:
* Generate a periodic timer tick for use by generic timers in the code.
*
*************************************************************************/
/**
* @file
* @brief Generate a periodic timer tick for use by generic timers in the code.
* @author Steve Karg
* @date 2011
* @copyright SPDX-License-Identifier: MIT
*/
#include <stdbool.h>
#include <stdint.h>
#include "bacnet/basic/sys/mstimer.h"
+38 -29
View File
@@ -1,17 +1,10 @@
/**
* @file
* @brief The Network Port object provides access to the configuration
* and properties of network ports of a device.
* @author Steve Karg
* @date 2016
* @brief Network port objects, customize for your use
*
* @section DESCRIPTION
*
* The Network Port object provides access to the configuration
* and properties of network ports of a device.
*
* @section LICENSE
*
* SPDX-License-Identifier: MIT
* @copyright SPDX-License-Identifier: MIT
*/
#include <stdbool.h>
#include <stdint.h>
@@ -55,9 +48,15 @@ struct object_data Object_List[BACNET_NETWORK_PORTS_MAX];
static uint32_t Link_Speeds[] = { 9600, 19200, 38400, 57600, 76800, 115200 };
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Network_Port_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_STATUS_FLAGS, PROP_RELIABILITY,
PROP_OUT_OF_SERVICE, PROP_NETWORK_TYPE, PROP_PROTOCOL_LEVEL,
static const int Network_Port_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_STATUS_FLAGS,
PROP_RELIABILITY,
PROP_OUT_OF_SERVICE,
PROP_NETWORK_TYPE,
PROP_PROTOCOL_LEVEL,
PROP_CHANGES_PENDING,
#if (BACNET_PROTOCOL_REVISION < 24)
PROP_APDU_LENGTH,
@@ -65,17 +64,22 @@ static const int Network_Port_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
PROP_NETWORK_NUMBER_QUALITY,
PROP_LINK_SPEED,
#endif
-1 };
-1
};
static const int Network_Port_Properties_Optional[] = { PROP_MAC_ADDRESS,
PROP_MAX_MASTER, PROP_MAX_INFO_FRAMES, PROP_LINK_SPEEDS,
static const int Network_Port_Properties_Optional[] = {
PROP_MAC_ADDRESS,
PROP_MAX_MASTER,
PROP_MAX_INFO_FRAMES,
PROP_LINK_SPEEDS,
#if (BACNET_PROTOCOL_REVISION >= 24)
PROP_APDU_LENGTH,
PROP_NETWORK_NUMBER,
PROP_NETWORK_NUMBER_QUALITY,
PROP_LINK_SPEED,
#endif
-1 };
-1
};
static const int Network_Port_Properties_Proprietary[] = { -1 };
@@ -91,7 +95,8 @@ static const int Network_Port_Properties_Proprietary[] = { -1 };
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Network_Port_Property_List(uint32_t object_instance,
void Network_Port_Property_List(
uint32_t object_instance,
const int **pRequired,
const int **pOptional,
const int **pProprietary)
@@ -438,8 +443,9 @@ bool Network_Port_Changes_Pending_Set(uint32_t instance, bool flag)
index = Network_Port_Instance_To_Index(instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
Object_List[index].Changes_Pending = flag;
} else
} else {
return false;
}
return true;
}
@@ -523,8 +529,8 @@ bool Network_Port_MSTP_Max_Info_Frames_Set(
* @param object_property - object-property to be checked
* @return true if the property is a member of this object instance
*/
static bool Network_Port_Property_List_Member(
uint32_t object_instance, int object_property)
static bool
Network_Port_Property_List_Member(uint32_t object_instance, int object_property)
{
bool found = false;
const int *pRequired = NULL;
@@ -640,9 +646,9 @@ int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
break;
case PROP_LINK_SPEEDS:
count = Network_Port_Link_Speeds_Count(rpdata->object_instance);
apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index, Network_Port_Link_Speeds_Encode, count,
apdu, apdu_max);
apdu_len = bacnet_array_encode(
rpdata->object_instance, rpdata->array_index,
Network_Port_Link_Speeds_Encode, count, apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -652,7 +658,8 @@ int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
}
break;
case PROP_CHANGES_PENDING:
apdu_len = encode_application_boolean(&apdu[0],
apdu_len = encode_application_boolean(
&apdu[0],
Network_Port_Changes_Pending(rpdata->object_instance));
break;
case PROP_APDU_LENGTH:
@@ -660,11 +667,13 @@ int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
&apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
break;
case PROP_MAX_MASTER:
apdu_len = encode_application_unsigned(&apdu[0],
apdu_len = encode_application_unsigned(
&apdu[0],
Network_Port_MSTP_Max_Master(rpdata->object_instance));
break;
case PROP_MAX_INFO_FRAMES:
apdu_len = encode_application_unsigned(&apdu[0],
apdu_len = encode_application_unsigned(
&apdu[0],
Network_Port_MSTP_Max_Info_Frames(rpdata->object_instance));
break;
default:
@@ -760,8 +769,8 @@ bool Network_Port_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
break;
case PROP_MAC_ADDRESS:
if (value.tag == BACNET_APPLICATION_TAG_OCTET_STRING) {
if (!Network_Port_MAC_Address_Set(wp_data->object_instance,
value.type.Octet_String.value,
if (!Network_Port_MAC_Address_Set(
wp_data->object_instance, value.type.Octet_String.value,
value.type.Octet_String.length)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+147
View File
@@ -0,0 +1,147 @@
/**
* @file
* @brief uBASIC-Plus program object for BACnet
* @author Steve Karg
* @date 2025
* @copyright SPDX-License-Identifier: MIT
*/
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "bacnet/basic/object/program.h"
#include "bacnet/basic/program/ubasic/ubasic.h"
#include "bacnet/basic/sys/mstimer.h"
/* uBASIC-Plus program object */
static struct ubasic_data UBASIC_DATA = { 0 };
static struct mstimer UBASIC_Timer;
static uint32_t UBASIC_Instance = 0;
static const char *UBASIC_Program =
/* program listing with either \0, \n, or ';' at the end of each line.
note: indentation is not required */
"println 'Demo - BACnet & GPIO';"
"bac_create(0, 1, 'ADC-1');"
"bac_create(0, 2, 'ADC-2');"
"bac_create(4, 1, 'LED-1');"
"bac_create(4, 2, 'LED-2');"
":startover;"
" a = aread(1);"
" c = avgw(a, c, 10);"
" bac_write(0, 1, 85, c);"
" b = aread(2);"
" d = avgw(b, d, 10);"
" bac_write(0, 2, 85, d);"
" h = bac_read(4, 1, 85);"
" dwrite(1, (h % 2));"
" i = bac_read(4, 2, 85);"
" dwrite(2, (i % 2));"
" sleep (0.2);"
"goto startover;"
"end;";
/**
* @brief Load the program into the uBASIC interpreter
* @param context Pointer to the uBASIC data structure
* @return 0 on success
*/
static int Program_Load(void *context)
{
struct ubasic_data *data = (struct ubasic_data *)context;
ubasic_load_program(data, UBASIC_Program);
return 0;
}
/**
* @brief Run the program in the uBASIC interpreter
* @param context Pointer to the uBASIC data structure
* @return 0 while the programm is running, non-zero when finished
* or an error occurred
*/
static int Program_Run(void *context)
{
struct ubasic_data *data = (struct ubasic_data *)context;
int result = 0;
result = ubasic_run_program(data);
if (result <= 0) {
return -1;
}
return 0;
}
/**
* @brief Halt the program in the uBASIC interpreter
* @param context Pointer to the uBASIC data structure
* @return 0 on success, non-zero on error
*/
static int Program_Halt(void *context)
{
struct ubasic_data *data = (struct ubasic_data *)context;
data->status.bit.isRunning = 0;
return 0;
}
/**
* @brief Restart the program in the uBASIC interpreter
* @param context Pointer to the uBASIC data structure
* @return 0 on success, non-zero on error
*/
static int Program_Restart(void *context)
{
struct ubasic_data *data = (struct ubasic_data *)context;
ubasic_clear_variables(data);
ubasic_load_program(data, UBASIC_Program);
return 0;
}
/**
* @brief Unload the program in the uBASIC interpreter
* @param context Pointer to the uBASIC data structure
* @return 0 on success, non-zero on error
*/
static int Program_Unload(void *context)
{
struct ubasic_data *data = (struct ubasic_data *)context;
ubasic_clear_variables(data);
return 0;
}
/**
* @brief Timer task for the uBASIC program object
*/
void Program_UBASIC_Task(void)
{
if (mstimer_expired(&UBASIC_Timer)) {
mstimer_reset(&UBASIC_Timer);
Program_Timer(UBASIC_Instance, mstimer_interval(&UBASIC_Timer));
}
}
/**
* @brief Initialize the uBASIC program object
* @param instance Instance number of the program object
* @return 0 on success, non-zero on error
*/
void Program_UBASIC_Init(uint32_t instance)
{
ubasic_port_init(&UBASIC_DATA);
UBASIC_Instance = Program_Create(instance);
Program_Context_Set(UBASIC_Instance, &UBASIC_DATA);
Program_Load_Set(UBASIC_Instance, Program_Load);
Program_Run_Set(UBASIC_Instance, Program_Run);
Program_Halt_Set(UBASIC_Instance, Program_Halt);
Program_Restart_Set(UBASIC_Instance, Program_Restart);
Program_Unload_Set(UBASIC_Instance, Program_Unload);
/* auto-run the program */
Program_Change_Set(UBASIC_Instance, PROGRAM_REQUEST_RUN);
/* start the cyclic 10ms run timer for the program object */
mstimer_set(&UBASIC_Timer, 10);
}
+23
View File
@@ -0,0 +1,23 @@
/**
* @file
* @brief uBASIC-Plus program object for BACnet
* @author Steve Karg
* @date 2025
* @copyright SPDX-License-Identifier: MIT
*/
#ifndef PROGRAM_UBASIC_H
#define PROGRAM_UBASIC_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Program_UBASIC_Task(void);
void Program_UBASIC_Init(uint32_t instance);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+27 -25
View File
@@ -24,36 +24,36 @@
#include "rs485.h"
#ifndef RS485_LINKSPRITE_ENABLED
#ifndef RS485_DFR0259_ENABLED
#define RS485_DFR0259_ENABLED 1
#endif
#ifndef RS485_DFR0259_ENABLED
#define RS485_DFR0259_ENABLED 1
#endif
#endif
#if defined(RS485_DFR0259_ENABLED) || defined(RS485_LINKSPRITE_ENABLED)
/* DFR0259 RS485 Shield - TXD=PG14, RXD=PG9, USART6 */
#define RS485_USARTx USART6
#define RS485_NVIC_IRQ USART6_IRQn
#define RS485_USARTx_ISR USART6_IRQHandler
#define RS485_USARTx_RCC RCC_APB2Periph_USART6
#define RS485_GPIO_RCC RCC_AHB1Periph_GPIOG
#define RS485_GPIO_PINS GPIO_Pin_9 | GPIO_Pin_14
#define RS485_GPIO GPIOG
/* alternate function (AF) */
#define RS485_AF_PINSOURCE_RX GPIO_PinSource9
#define RS485_AF_PINSOURCE_TX GPIO_PinSource14
#define RS485_AF_FUNCTION GPIO_AF_USART6
/* DFR0259 RS485 Shield - TXD=PG14, RXD=PG9, USART6 */
#define RS485_USARTx USART6
#define RS485_NVIC_IRQ USART6_IRQn
#define RS485_USARTx_ISR USART6_IRQHandler
#define RS485_USARTx_RCC RCC_APB2Periph_USART6
#define RS485_GPIO_RCC RCC_AHB1Periph_GPIOG
#define RS485_GPIO_PINS GPIO_Pin_9 | GPIO_Pin_14
#define RS485_GPIO GPIOG
/* alternate function (AF) */
#define RS485_AF_PINSOURCE_RX GPIO_PinSource9
#define RS485_AF_PINSOURCE_TX GPIO_PinSource14
#define RS485_AF_FUNCTION GPIO_AF_USART6
#endif
#if defined(RS485_DFR0259_ENABLED)
/* DFR0259 RS485 Shield - CE=PF15 */
#define RS485_RTS_RCC RCC_AHB1Periph_GPIOF
#define RS485_RTS_PIN GPIO_Pin_15
#define RS485_RTS_GPIO GPIOF
/* DFR0259 RS485 Shield - CE=PF15 */
#define RS485_RTS_RCC RCC_AHB1Periph_GPIOF
#define RS485_RTS_PIN GPIO_Pin_15
#define RS485_RTS_GPIO GPIOF
#endif
#if defined(RS485_LINKSPRITE_ENABLED)
/* LINKSPRITE RS485 Shield - CE=PD15 */
#define RS485_RTS_RCC RCC_AHB1Periph_GPIOD
#define RS485_RTS_PIN GPIO_Pin_15
#define RS485_RTS_GPIO GPIOD
/* LINKSPRITE RS485 Shield - CE=PD15 */
#define RS485_RTS_RCC RCC_AHB1Periph_GPIOD
#define RS485_RTS_PIN GPIO_Pin_15
#define RS485_RTS_GPIO GPIOD
#endif
/* buffer for storing received bytes - size must be power of two */
@@ -305,9 +305,11 @@ void rs485_init(void)
NVIC_InitTypeDef NVIC_InitStructure;
/* initialize the Rx and Tx byte queues */
FIFO_Init(&Receive_Queue, &Receive_Queue_Data[0],
FIFO_Init(
&Receive_Queue, &Receive_Queue_Data[0],
(unsigned)sizeof(Receive_Queue_Data));
FIFO_Init(&Transmit_Queue, &Transmit_Queue_Data[0],
FIFO_Init(
&Transmit_Queue, &Transmit_Queue_Data[0],
(unsigned)sizeof(Transmit_Queue_Data));
/* Enable GPIOx clock */
+83 -73
View File
@@ -1,23 +1,23 @@
/**
******************************************************************************
* @file stm32f4xx_conf.h
* @author MCD Application Team
* @version V1.0.0
* @date 19-September-2011
* @brief Library configuration file.
******************************************************************************
* @attention
*
* 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 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
******************************************************************************
* @file stm32f4xx_conf.h
* @author MCD Application Team
* @version V1.0.0
* @date 19-September-2011
* @brief Library configuration file.
******************************************************************************
* @attention
*
* 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 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_CONF_H
@@ -25,53 +25,62 @@
/* ########################## HSE/HSI Values adaptation ##################### */
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */
* @brief Adjust the value of External High Speed oscillator (HSE) used in your
* application. This value is used by the RCC HAL module to compute the system
* frequency (when HSE is used as system clock source, directly or through the
* PLL).
*/
#if !defined(HSE_VALUE)
#define HSE_VALUE \
((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */
#if !defined(HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT \
((uint32_t)100U) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system
* frequency (when HSI is used as system clock source, directly or through the
* PLL).
*/
#if !defined(HSI_VALUE)
#define HSI_VALUE \
((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined (LSI_VALUE)
#define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature.*/
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined(LSI_VALUE)
#define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz \
The real value may vary depending on the variations \
in voltage and temperature.*/
/**
* @brief External Low Speed oscillator (LSE) value.
*/
#if !defined (LSE_VALUE)
#define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */
* @brief External Low Speed oscillator (LSE) value.
*/
#if !defined(LSE_VALUE)
#define LSE_VALUE \
((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz \
*/
#endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */
#if !defined(LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT \
((uint32_t)5000U) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */
/**
* @brief External clock source for I2S peripheral
* This value is used by the I2S HAL module to compute the I2S clock source
* frequency, this source is inserted directly through I2S_CKIN pad.
*/
#if !defined (EXTERNAL_CLOCK_VALUE)
#define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/
* @brief External clock source for I2S peripheral
* This value is used by the I2S HAL module to compute the I2S clock
* source frequency, this source is inserted directly through I2S_CKIN pad.
*/
#if !defined(EXTERNAL_CLOCK_VALUE)
#define EXTERNAL_CLOCK_VALUE \
((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */
/* Tip: To avoid modifying this file each time you need to use different HSE,
@@ -79,14 +88,14 @@
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
#define INSTRUCTION_CACHE_ENABLE 1U
#define DATA_CACHE_ENABLE 1U
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
#define INSTRUCTION_CACHE_ENABLE 1U
#define DATA_CACHE_ENABLE 1U
/* Includes ------------------------------------------------------------------*/
@@ -123,29 +132,30 @@
/* If an external clock source is used, then the value of the following define
should be set to the value of the external clock source, else, if no external
clock is used, keep this define commented */
/*#define I2S_EXTERNAL_CLOCK_VAL 12288000 */ /* Value of the external clock in Hz */
/*#define I2S_EXTERNAL_CLOCK_VAL 12288000 */ /* Value of the external clock in
Hz */
/* Uncomment the line below to expanse the "assert_param" macro in the
Standard Peripheral Library drivers code */
/* #define USE_FULL_ASSERT 1 */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
#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__))
* @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);
void assert_failed(uint8_t *file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
#endif /* __STM32F4xx_CONF_H */
+71 -80
View File
@@ -1,37 +1,37 @@
/**
******************************************************************************
* @file IO_Toggle/stm32f4xx_it.c
* @author MCD Application Team
* @version V1.0.0
* @date 19-September-2011
* @brief Main Interrupt Service Routines.
* This file provides template for all exceptions handler and
* peripherals interrupt service routine.
******************************************************************************
* @attention
*
* 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 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
******************************************************************************
* @file IO_Toggle/stm32f4xx_it.c
* @author MCD Application Team
* @version V1.0.0
* @date 19-September-2011
* @brief Main Interrupt Service Routines.
* This file provides template for all exceptions handler and
* peripherals interrupt service routine.
******************************************************************************
* @attention
*
* 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 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_it.h"
#include "stm32f4xx.h"
/** @addtogroup STM32F4_Discovery_Peripheral_Examples
* @{
*/
* @{
*/
/** @addtogroup IO_Toggle
* @{
*/
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
@@ -45,89 +45,81 @@
/******************************************************************************/
/**
* @brief This function handles NMI exception.
* @param None
* @retval None
*/
* @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
*/
* @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)
{
}
/* Go to infinite loop when Hard Fault exception occurs */
while (1) { }
}
/**
* @brief This function handles Memory Manage exception.
* @param None
* @retval None
*/
* @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)
{
}
/* Go to infinite loop when Memory Manage exception occurs */
while (1) { }
}
/**
* @brief This function handles Bus Fault exception.
* @param None
* @retval None
*/
* @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)
{
}
/* Go to infinite loop when Bus Fault exception occurs */
while (1) { }
}
/**
* @brief This function handles Usage Fault exception.
* @param None
* @retval None
*/
* @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)
{
}
/* Go to infinite loop when Usage Fault exception occurs */
while (1) { }
}
/**
* @brief This function handles SVCall exception.
* @param None
* @retval None
*/
* @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
*/
* @brief This function handles Debug Monitor exception.
* @param None
* @retval None
*/
void DebugMon_Handler(void)
{
}
/**
* @brief This function handles PendSVC exception.
* @param None
* @retval None
*/
* @brief This function handles PendSVC exception.
* @param None
* @retval None
*/
void PendSV_Handler(void)
{
}
@@ -140,17 +132,16 @@ void PendSV_Handler(void)
/******************************************************************************/
/**
* @brief This function handles PPP interrupt request.
* @param None
* @retval None
*/
* @brief This function handles PPP interrupt request.
* @param None
* @retval None
*/
/*void PPP_IRQHandler(void)
{
}*/
/**
* @}
*/
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
+20 -20
View File
@@ -1,30 +1,30 @@
/**
******************************************************************************
* @file GPIO/IOToggle/stm32f4xx_it.h
* @author MCD Application Team
* @version V1.0.0
* @date 19-September-2011
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* 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 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
******************************************************************************
* @file GPIO/IOToggle/stm32f4xx_it.h
* @author MCD Application Team
* @version V1.0.0
* @date 19-September-2011
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* 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 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_IT_H
#define __STM32F4xx_IT_H
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
File diff suppressed because it is too large Load Diff
+51 -53
View File
@@ -1,89 +1,87 @@
/**
******************************************************************************
* @file system_stm32f4xx.h
* @author MCD Application Team
* @version V1.0.0
* @date 30-September-2011
* @brief CMSIS Cortex-M4 Device System Source File for STM32F4xx devices.
******************************************************************************
* @attention
*
* 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 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
******************************************************************************
* @file system_stm32f4xx.h
* @author MCD Application Team
* @version V1.0.0
* @date 30-September-2011
* @brief CMSIS Cortex-M4 Device System Source File for STM32F4xx devices.
******************************************************************************
* @attention
*
* 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 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
* @{
*/
/** @addtogroup stm32f4xx_system
* @{
*/
* @{
*/
/**
* @brief Define to prevent recursive inclusion
*/
* @brief Define to prevent recursive inclusion
*/
#ifndef __SYSTEM_STM32F4XX_H
#define __SYSTEM_STM32F4XX_H
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
/** @addtogroup STM32F4xx_System_Includes
* @{
*/
* @{
*/
/**
* @}
*/
* @}
*/
/** @addtogroup STM32F4xx_System_Exported_types
* @{
*/
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
* @{
*/
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
/**
* @}
*/
* @}
*/
/** @addtogroup STM32F4xx_System_Exported_Constants
* @{
*/
* @{
*/
/**
* @}
*/
* @}
*/
/** @addtogroup STM32F4xx_System_Exported_Macros
* @{
*/
* @{
*/
/**
* @}
*/
* @}
*/
/** @addtogroup STM32F4xx_System_Exported_Functions
* @{
*/
* @{
*/
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
extern void System_LSE_Init(void);
/**
* @}
*/
* @}
*/
#ifdef __cplusplus
}
@@ -92,10 +90,10 @@ extern void System_LSE_Init(void);
#endif /*__SYSTEM_STM32F4XX_H */
/**
* @}
*/
* @}
*/
/**
* @}
*/
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
+644
View File
@@ -0,0 +1,644 @@
/**
* @file
* @brief Example uBASIC-Plus porting layer for the uBASIC-Plus interpreter
* for STM32F4xx NUCLIO board
* @author Steve Karg
* @date 2025
* @copyright SPDX-License-Identifier: MIT
*/
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <limits.h>
#include <ctype.h>
#include "bacnet/basic/object/ai.h"
#include "bacnet/basic/object/ao.h"
#include "bacnet/basic/object/av.h"
#include "bacnet/basic/object/bi.h"
#include "bacnet/basic/object/bo.h"
#include "bacnet/basic/object/bv.h"
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/object/ms-input.h"
#include "bacnet/basic/object/mso.h"
#include "bacnet/basic/object/msv.h"
#include "bacnet/basic/program/ubasic/ubasic.h"
#include "bacnet/basic/sys/mstimer.h"
#include "bacnet/wp.h"
#include "led.h"
#if defined(UBASIC_SCRIPT_PRINT_TO_SERIAL)
/**
* @brief Write a buffer to the serial port
* @param msg Pointer to the buffer to write
* @param n Number of bytes to write
*/
static void serial_write(const char *msg, uint16_t n)
{
(void)msg;
(void)n;
}
/**
* @brief Gather key presses until new-line is recieved or buffer is full
* @return return the next byte from the input stream, or EOF(-1) if no byte is
* available
*/
static int serial_getc(void)
{
int ch = -1;
return ch;
}
#endif
#if defined(UBASIC_SCRIPT_HAVE_HARDWARE_EVENTS)
static uint32_t Event_Mask;
/**
* @brief Hardware event status bit
* @param bit Event bit
* @return 1 if the event is set, 0 otherwise
*/
static int8_t hw_event(uint8_t bit)
{
if (bit < 32) {
if (Event_Mask & (1UL << bit)) {
return 1; // Event is set
}
}
return 0; // Event is not set
}
/**
* @brief Clear a hardware event state bit
* @param bit Event bit
*/
static void hw_event_clear(uint8_t bit)
{
if (bit < 32) {
Event_Mask &= ~(1UL << bit);
}
}
#endif
#if defined(UBASIC_SCRIPT_HAVE_STORE_VARS_IN_FLASH)
static uint8_t EEPROM_Buffer[256];
/**
* @brief Read some data from the EEPROM
* @param start_address EEPROM starting memory address
* @param buffer data to store
* @param length number of bytes of data to read
*/
static size_t
eepromRead(uint16_t start_address, uint8_t *buffer, uint16_t length)
{
size_t bytes_read = 0;
uint16_t i = 0;
for (i = 0; i < length; i++) {
if (start_address + i < sizeof(EEPROM_Buffer)) {
buffer[i] = EEPROM_Buffer[start_address + i];
bytes_read++;
} else {
break;
}
}
return bytes_read;
}
/**
* @brief Write some data to the EEPROM
* @param start_address EEPROM starting memory address
* @param buffer data to send
* @param length number of bytes of data
*/
static size_t
eepromWrite(uint16_t start_address, uint8_t *buffer, uint16_t length)
{
size_t bytes_written = 0;
uint16_t i = 0;
for (i = 0; i < length; i++) {
if (start_address + i < sizeof(EEPROM_Buffer)) {
EEPROM_Buffer[start_address + i] = buffer[i];
bytes_written++;
} else {
break;
}
}
return bytes_written;
}
#define UBASIC_FLASH_PAGE_SIZE 256
/**
* @brief Write a variable to the EEPROM
* @param Name Variable name
* @param Vartype Variable type
* @param datalen_bytes Data length in bytes
* @param dataptr Pointer to the data
*/
static void variable_write(
uint8_t Name, uint8_t vartype, uint8_t datalen_bytes, uint8_t *dataptr)
{
// Calculate the starting address based on variable name
uint16_t start_address = Name * UBASIC_FLASH_PAGE_SIZE;
uint8_t buffer[UBASIC_FLASH_PAGE_SIZE];
// Prepare the buffer with the variable type and data length
buffer[0] = vartype; // First byte is the variable type
buffer[1] = datalen_bytes; // Second byte is the data length
for (uint8_t i = 0; i < datalen_bytes; i++) {
buffer[i + 2] = dataptr[i]; // Copy the actual data into the buffer
}
// Write the buffer to EEPROM
eepromWrite(start_address, buffer, datalen_bytes + 2);
}
/**
* @brief Read a variable from the EEPROM
* @param Name Variable name
* @param Vartype Variable type
* @param dataptr Pointer to store the data
* @param datalen Pointer to store the data length
*/
static void
variable_read(uint8_t Name, uint8_t vartype, uint8_t *dataptr, uint8_t *datalen)
{
// Calculate the starting address based on variable name
uint8_t buffer[UBASIC_FLASH_PAGE_SIZE] = { 0 };
uint16_t start_address = Name * UBASIC_FLASH_PAGE_SIZE;
// Read the data from EEPROM
eepromRead(start_address, buffer, UBASIC_FLASH_PAGE_SIZE);
// Check if the variable type matches
if (buffer[0] == vartype) {
*datalen = buffer[1]; // Get the data length
for (uint8_t i = 0; i < *datalen; i++) {
dataptr[i] =
buffer[i + 2]; // Copy the actual data into the provided pointer
}
} else {
*datalen = 0; // If type does not match, set length to 0
}
}
#endif
#if ( \
defined(UBASIC_SCRIPT_HAVE_TICTOC_CHANNELS) || \
defined(UBASIC_SCRIPT_HAVE_SLEEP) || \
defined(UBASIC_SCRIPT_HAVE_INPUT_FROM_SERIAL))
/* defined in mstimer.h */
#endif
#if defined(UBASIC_SCRIPT_HAVE_RANDOM_NUMBER_GENERATOR)
/**
* @brief Generate a random number
* @param size Size of the random number in bits
* @return Random number size-bits wide
*/
static uint32_t random_uint32(uint8_t size)
{
uint32_t value = 0, grains = 0;
uint8_t k, i;
static bool initialized = false;
if (!initialized) {
srand(0);
initialized = true;
}
for (k = 0; k < 4; k++) {
grains = 0;
for (i = 0; i < (size >> 1); i++) {
/* Two LS bits are most likely most random */
grains |= (rand() & 0x00000003) << (2 * i);
}
value ^= grains;
}
return value;
}
#endif
#if defined(UBASIC_SCRIPT_HAVE_PWM_CHANNELS)
static int32_t dutycycle_pwm_ch[UBASIC_SCRIPT_HAVE_PWM_CHANNELS];
/**
* @brief Configure the PWM
* @param psc Prescaler
* @param per Period
*/
static void pwm_config(uint16_t psc, uint16_t per)
{
(void)psc;
(void)per;
}
/**
* @brief Write a value to the PWM
* @param ch Channel
* @param dutycycle Duty cycle
*/
static void pwm_write(uint8_t ch, int32_t dutycycle)
{
if (ch < UBASIC_SCRIPT_HAVE_PWM_CHANNELS) {
dutycycle_pwm_ch[ch] = dutycycle;
}
}
/**
* @brief Read a value from the PWM
* @param ch Channel
* @return Duty cycle
*/
static int32_t pwm_read(uint8_t ch)
{
if (ch < UBASIC_SCRIPT_HAVE_PWM_CHANNELS) {
return dutycycle_pwm_ch[ch];
}
return 0;
}
#endif
#if defined(UBASIC_SCRIPT_HAVE_ANALOG_READ)
/**
* @brief Configure the ADC
* @param sampletime Sample time
* @param nreads Number of reads
*/
static void adc_config(uint8_t sampletime, uint8_t nreads)
{
(void)sampletime;
(void)nreads;
}
/**
* @brief Read a value from the ADC
* @param channel Channel
* @return ADC value
*/
static int32_t adc_read(uint8_t channel)
{
return (int32_t)random_uint32(12);
}
#endif
#if defined(UBASIC_SCRIPT_HAVE_GPIO_CHANNELS)
/**
* @brief Configure the GPIO
* @param ch Channel
* @param mode Mode
* @param freq Frequency
*/
static void gpio_config(uint8_t ch, int8_t mode, uint8_t freq)
{
(void)ch;
(void)mode;
(void)freq;
}
/**
* @brief Write a value to the GPIO
* @param ch Channel
* @param pin_state Pin state
*/
static void gpio_write(uint8_t ch, uint8_t pin_state)
{
switch (ch) {
case 1:
if (pin_state) {
led_on(LED_LD1);
} else {
led_off(LED_LD1);
}
break;
case 2:
if (pin_state) {
led_on(LED_LD2);
} else {
led_off(LED_LD2);
}
break;
default:
break;
}
}
/**
* @brief Read a value from the GPIO
* @param ch Channel
* @return GPIO value
*/
static int32_t gpio_read(uint8_t ch)
{
return 0;
}
#endif
#if defined(UBASIC_SCRIPT_HAVE_BACNET)
/**
* @brief Create a BACnet object
* @param object_type Object type
* @param instance Object instance
* @param object_name Object name
*/
static void
bacnet_create_object(uint16_t object_type, uint32_t instance, char *object_name)
{
uint32_t r;
switch (object_type) {
case OBJECT_ANALOG_INPUT:
if (!Analog_Input_Valid_Instance(instance)) {
r = Analog_Input_Create(instance);
if (r == instance) {
Analog_Input_Name_Set(instance, strdup(object_name));
}
}
break;
case OBJECT_ANALOG_OUTPUT:
if (!Analog_Output_Valid_Instance(instance)) {
r = Analog_Output_Create(instance);
if (r == instance) {
Analog_Output_Name_Set(instance, strdup(object_name));
}
}
break;
case OBJECT_ANALOG_VALUE:
if (!Analog_Value_Valid_Instance(instance)) {
r = Analog_Value_Create(instance);
if (r == instance) {
Analog_Value_Name_Set(instance, strdup(object_name));
}
}
break;
case OBJECT_BINARY_INPUT:
if (!Binary_Input_Valid_Instance(instance)) {
r = Binary_Input_Create(instance);
if (r == instance) {
Binary_Input_Name_Set(instance, strdup(object_name));
}
}
break;
case OBJECT_BINARY_OUTPUT:
if (!Binary_Output_Valid_Instance(instance)) {
r = Binary_Output_Create(instance);
if (r == instance) {
Binary_Output_Name_Set(instance, strdup(object_name));
}
}
break;
case OBJECT_BINARY_VALUE:
if (!Binary_Value_Valid_Instance(instance)) {
r = Binary_Value_Create(instance);
if (r == instance) {
Binary_Value_Name_Set(instance, strdup(object_name));
}
}
break;
case OBJECT_MULTI_STATE_INPUT:
if (!Multistate_Input_Valid_Instance(instance)) {
r = Multistate_Input_Create(instance);
if (r == instance) {
Multistate_Input_Name_Set(instance, strdup(object_name));
}
}
break;
case OBJECT_MULTI_STATE_OUTPUT:
if (!Multistate_Output_Valid_Instance(instance)) {
r = Multistate_Output_Create(instance);
if (r == instance) {
Multistate_Output_Name_Set(instance, strdup(object_name));
}
}
break;
case OBJECT_MULTI_STATE_VALUE:
if (!Multistate_Value_Valid_Instance(instance)) {
r = Multistate_Value_Create(instance);
if (r == instance) {
Multistate_Value_Name_Set(instance, strdup(object_name));
}
}
break;
default:
break;
}
}
/**
* @brief Write a property to a BACnet object
* @param object_type Object type
* @param instance Object instance
* @param property_id Property ID
* @param value Property value
*/
static void bacnet_write_property(
uint16_t object_type,
uint32_t instance,
uint32_t property_id,
VARIABLE_TYPE value)
{
BACNET_BINARY_PV value_binary = BINARY_INACTIVE;
switch (object_type) {
case OBJECT_ANALOG_INPUT:
if (property_id == PROP_PRESENT_VALUE) {
Analog_Input_Present_Value_Set(
instance, fixedpt_tofloat(value));
}
break;
case OBJECT_ANALOG_OUTPUT:
if (property_id == PROP_PRESENT_VALUE) {
Analog_Output_Present_Value_Set(
instance, fixedpt_tofloat(value), BACNET_MAX_PRIORITY);
}
break;
case OBJECT_ANALOG_VALUE:
if (property_id == PROP_PRESENT_VALUE) {
Analog_Value_Present_Value_Set(
instance, fixedpt_tofloat(value), BACNET_MAX_PRIORITY);
}
break;
case OBJECT_BINARY_INPUT:
if (property_id == PROP_PRESENT_VALUE) {
if (fixedpt_toint(value) != 0) {
value_binary = BINARY_ACTIVE;
}
Binary_Input_Present_Value_Set(instance, value_binary);
}
break;
case OBJECT_BINARY_OUTPUT:
if (property_id == PROP_PRESENT_VALUE) {
if (fixedpt_toint(value) != 0) {
value_binary = BINARY_ACTIVE;
}
Binary_Output_Present_Value_Set(
instance, value_binary, BACNET_MAX_PRIORITY);
}
break;
case OBJECT_BINARY_VALUE:
if (property_id == PROP_PRESENT_VALUE) {
if (fixedpt_toint(value) != 0) {
value_binary = BINARY_ACTIVE;
}
Binary_Value_Present_Value_Set(instance, value_binary);
}
break;
case OBJECT_MULTI_STATE_INPUT:
if (property_id == PROP_PRESENT_VALUE) {
Multistate_Input_Present_Value_Set(
instance, fixedpt_toint(value));
}
break;
case OBJECT_MULTI_STATE_OUTPUT:
if (property_id == PROP_PRESENT_VALUE) {
Multistate_Output_Present_Value_Set(
instance, fixedpt_toint(value), BACNET_MAX_PRIORITY);
}
break;
case OBJECT_MULTI_STATE_VALUE:
if (property_id == PROP_PRESENT_VALUE) {
Multistate_Value_Present_Value_Set(
instance, fixedpt_toint(value));
}
break;
default:
break;
}
}
/**
* @brief Read a property from a BACnet object
* @param object_type Object type
* @param instance Object instance
* @param property_id Property ID
* @return Property value
*/
static VARIABLE_TYPE bacnet_read_property(
uint16_t object_type, uint32_t instance, uint32_t property_id)
{
VARIABLE_TYPE value = 0;
float value_float = 0.0;
BACNET_BINARY_PV value_binary = BINARY_INACTIVE;
switch (object_type) {
case OBJECT_ANALOG_INPUT:
if (property_id == PROP_PRESENT_VALUE) {
value_float = Analog_Input_Present_Value(instance);
value = fixedpt_fromfloat(value_float);
}
break;
case OBJECT_ANALOG_OUTPUT:
if (property_id == PROP_PRESENT_VALUE) {
value_float = Analog_Output_Present_Value(instance);
value = fixedpt_fromfloat(value_float);
}
break;
case OBJECT_ANALOG_VALUE:
if (property_id == PROP_PRESENT_VALUE) {
value_float = Analog_Value_Present_Value(instance);
value = fixedpt_fromfloat(value_float);
}
break;
case OBJECT_BINARY_INPUT:
if (property_id == PROP_PRESENT_VALUE) {
value_binary = Binary_Input_Present_Value(instance);
value =
fixedpt_fromint((value_binary == BINARY_ACTIVE) ? 1 : 0);
}
break;
case OBJECT_BINARY_OUTPUT:
if (property_id == PROP_PRESENT_VALUE) {
value_binary = Binary_Output_Present_Value(instance);
value =
fixedpt_fromint((value_binary == BINARY_ACTIVE) ? 1 : 0);
}
break;
case OBJECT_BINARY_VALUE:
if (property_id == PROP_PRESENT_VALUE) {
value_binary = Binary_Value_Present_Value(instance);
value =
fixedpt_fromint((value_binary == BINARY_ACTIVE) ? 1 : 0);
}
break;
case OBJECT_MULTI_STATE_INPUT:
if (property_id == PROP_PRESENT_VALUE) {
value =
fixedpt_fromint(Multistate_Input_Present_Value(instance));
}
break;
case OBJECT_MULTI_STATE_OUTPUT:
if (property_id == PROP_PRESENT_VALUE) {
value =
fixedpt_fromint(Multistate_Output_Present_Value(instance));
}
break;
case OBJECT_MULTI_STATE_VALUE:
if (property_id == PROP_PRESENT_VALUE) {
value =
fixedpt_fromint(Multistate_Value_Present_Value(instance));
}
break;
default:
break;
}
return value;
}
#endif
/**
* @brief Initialize the hardware drivers
* @param data Pointer to the ubasic data structure
*/
void ubasic_port_init(struct ubasic_data *data)
{
#if ( \
defined(UBASIC_SCRIPT_HAVE_TICTOC_CHANNELS) || \
defined(UBASIC_SCRIPT_HAVE_SLEEP) || \
defined(UBASIC_SCRIPT_HAVE_INPUT_FROM_SERIAL))
data->mstimer_now = mstimer_now;
#endif
data->variable_write = variable_write;
data->variable_read = variable_read;
#if defined(UBASIC_SCRIPT_HAVE_HARDWARE_EVENTS)
data->hw_event = hw_event;
data->hw_event_clear = hw_event_clear;
#endif
#if defined(UBASIC_SCRIPT_HAVE_PWM_CHANNELS)
data->pwm_config = pwm_config;
data->pwm_write = pwm_write;
data->pwm_read = pwm_read;
#endif
#if defined(UBASIC_SCRIPT_HAVE_PWM_CHANNELS)
data->adc_config = adc_config;
data->adc_read = adc_read;
#endif
#if defined(UBASIC_SCRIPT_HAVE_GPIO_CHANNELS)
data->gpio_config = gpio_config;
data->gpio_write = gpio_write;
data->gpio_read = gpio_read;
#endif
#if defined(UBASIC_SCRIPT_HAVE_RANDOM_NUMBER_GENERATOR)
data->random_uint32 = random_uint32;
#endif
#if defined(UBASIC_SCRIPT_PRINT_TO_SERIAL)
data->serial_write = serial_write;
#endif
#if defined(UBASIC_SCRIPT_HAVE_INPUT_FROM_SERIAL)
data->ubasic_getc = serial_getc;
#endif
#if defined(UBASIC_SCRIPT_HAVE_BACNET)
data->bacnet_create_object = bacnet_create_object;
data->bacnet_write_property = bacnet_write_property;
data->bacnet_read_property = bacnet_read_property;
#endif
}