From 6d773f566bed77f775225ebd9e9ce05950073fc7 Mon Sep 17 00:00:00 2001 From: Cecille Freeman Date: Tue, 22 Oct 2024 11:22:55 -0400 Subject: [PATCH] very early draft of silabs port --- examples/valve/silabs/.gn | 29 +++ examples/valve/silabs/BUILD.gn | 235 ++++++++++++++++++ examples/valve/silabs/README.md | 2 + examples/valve/silabs/build_for_wifi_args.gni | 14 ++ .../valve/silabs/build_for_wifi_gnfile.gn | 28 +++ examples/valve/silabs/build_overrides | 1 + examples/valve/silabs/include/AppConfig.h | 28 +++ examples/valve/silabs/include/AppEvent.h | 55 ++++ examples/valve/silabs/include/AppTask.h | 80 ++++++ .../valve/silabs/include/CHIPProjectConfig.h | 68 +++++ .../include/DrinksMachineDeviceDriver.h | 28 +++ examples/valve/silabs/openthread.gn | 30 +++ examples/valve/silabs/openthread.gni | 29 +++ examples/valve/silabs/src/AppTask.cpp | 225 +++++++++++++++++ .../silabs/src/DrinksMachineDeviceDriver.cpp | 104 ++++++++ examples/valve/silabs/src/ZclCallbacks.cpp | 25 ++ .../valve/silabs/third_party/connectedhomeip | 1 + examples/valve/silabs/with_pw_rpc.gni | 29 +++ 18 files changed, 1011 insertions(+) create mode 100644 examples/valve/silabs/.gn create mode 100644 examples/valve/silabs/BUILD.gn create mode 100644 examples/valve/silabs/README.md create mode 100644 examples/valve/silabs/build_for_wifi_args.gni create mode 100644 examples/valve/silabs/build_for_wifi_gnfile.gn create mode 120000 examples/valve/silabs/build_overrides create mode 100644 examples/valve/silabs/include/AppConfig.h create mode 100644 examples/valve/silabs/include/AppEvent.h create mode 100644 examples/valve/silabs/include/AppTask.h create mode 100644 examples/valve/silabs/include/CHIPProjectConfig.h create mode 100644 examples/valve/silabs/include/DrinksMachineDeviceDriver.h create mode 100644 examples/valve/silabs/openthread.gn create mode 100644 examples/valve/silabs/openthread.gni create mode 100644 examples/valve/silabs/src/AppTask.cpp create mode 100644 examples/valve/silabs/src/DrinksMachineDeviceDriver.cpp create mode 100644 examples/valve/silabs/src/ZclCallbacks.cpp create mode 120000 examples/valve/silabs/third_party/connectedhomeip create mode 100644 examples/valve/silabs/with_pw_rpc.gni diff --git a/examples/valve/silabs/.gn b/examples/valve/silabs/.gn new file mode 100644 index 00000000000000..b05216fc9d7eae --- /dev/null +++ b/examples/valve/silabs/.gn @@ -0,0 +1,29 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") + +# The location of the build configuration file. +buildconfig = "${build_root}/config/BUILDCONFIG.gn" + +# CHIP uses angle bracket includes. +check_system_includes = true + +default_args = { + target_cpu = "arm" + target_os = "freertos" + chip_openthread_ftd = true + + import("//openthread.gni") +} diff --git a/examples/valve/silabs/BUILD.gn b/examples/valve/silabs/BUILD.gn new file mode 100644 index 00000000000000..efd707a752fd58 --- /dev/null +++ b/examples/valve/silabs/BUILD.gn @@ -0,0 +1,235 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") +import("//build_overrides/efr32_sdk.gni") +import("//build_overrides/pigweed.gni") + +import("${build_root}/config/defaults.gni") +import("${efr32_sdk_build_root}/silabs_executable.gni") + +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") +import("${chip_root}/src/platform/device.gni") +import("${chip_root}/third_party/silabs/silabs_board.gni") + +if (chip_enable_pw_rpc) { + import("//build_overrides/pigweed.gni") + import("$dir_pw_build/target_types.gni") +} + +assert(current_os == "freertos") + +silabs_project_dir = "${chip_root}/examples/valve/silabs" +examples_common_plat_dir = "${chip_root}/examples/platform/silabs" + +if (wifi_soc) { + import("${chip_root}/third_party/silabs/SiWx917_sdk.gni") + examples_plat_dir = "${chip_root}/examples/platform/silabs/SiWx917" +} else { + import("${efr32_sdk_build_root}/efr32_sdk.gni") + examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32" +} + +import("${examples_common_plat_dir}/args.gni") + +declare_args() { + # Dump memory usage at link time. + chip_print_memory_usage = false +} + +if (slc_generate) { + # Generate Project Specific config (Board, hardware used etc..) + print(exec_script("${chip_root}/third_party/silabs/slc_gen/run_slc.py", + [ + rebase_path(chip_root), + "${silabs_board}", + "${disable_lcd}", + "${use_wstk_buttons}", + "${use_wstk_leds}", + "${use_external_flash}", + "${silabs_mcu}", + rebase_path(slc_gen_path), + ], + "list lines")) +} + +if (wifi_soc) { + siwx917_sdk("sdk") { + sources = [ + "${examples_common_plat_dir}/FreeRTOSConfig.h", + "${silabs_project_dir}/include/CHIPProjectConfig.h", + ] + + include_dirs = [ + "${chip_root}/src/platform/silabs/SiWx917", + "${silabs_project_dir}/include", + "${examples_plat_dir}", + "${chip_root}/src/lib", + "${examples_common_plat_dir}", + ] + + defines = [] + if (chip_enable_pw_rpc) { + defines += [ + "HAL_VCOM_ENABLE=1", + "PW_RPC_ENABLED", + ] + } + } +} else { + efr32_sdk("sdk") { + sources = [ + "${examples_common_plat_dir}/FreeRTOSConfig.h", + "${silabs_project_dir}/include/CHIPProjectConfig.h", + ] + + include_dirs = [ + "${chip_root}/src/platform/silabs/efr32", + "${silabs_project_dir}/include", + "${examples_plat_dir}", + "${chip_root}/src/lib", + "${examples_common_plat_dir}", + ] + + if (use_wf200) { + # TODO efr32_sdk should not need a header from this location + include_dirs += [ "${examples_plat_dir}/wf200" ] + } + + if (chip_enable_ble_rs911x) { + # TODO efr32_sdk should not need a header from this location + include_dirs += [ + "${examples_plat_dir}/rs911x", + "${examples_plat_dir}/rs911x/hal", + ] + } + + defines = [] + if (chip_enable_pw_rpc) { + defines += [ + "HAL_VCOM_ENABLE=1", + "PW_RPC_ENABLED", + ] + } + } +} +silabs_executable("drink-machine") { + output_name = "drink-machine.out" + include_dirs = [ "include" ] + defines = [] + + if (silabs_board == "BRD2704A") { + defines += [ "SL_STATUS_LED=0" ] + } + + sources = [ + "${examples_common_plat_dir}/main.cpp", + "include/DrinksMachineDeviceDriver.h", + "src/AppTask.cpp", + "src/DrinksMachineDeviceDriver.cpp", + "src/ZclCallbacks.cpp", + ] + + deps = [ + ":sdk", + app_data_model, + ] + + if (wifi_soc) { + deps += [ "${examples_plat_dir}:siwx917-common" ] + } else { + deps += [ "${examples_plat_dir}:efr32-common" ] + } + + if (chip_enable_pw_rpc) { + defines += [ + "PW_RPC_ENABLED", + "PW_RPC_ATTRIBUTE_SERVICE=1", + "PW_RPC_BUTTON_SERVICE=1", + "PW_RPC_DESCRIPTOR_SERVICE=1", + "PW_RPC_DEVICE_SERVICE=1", + "PW_RPC_OTCLI_SERVICE=1", + "PW_RPC_THREAD_SERVICE=1", + "PW_RPC_TRACING_SERVICE=1", + ] + + sources += [ + "${chip_root}/examples/common/pigweed/RpcService.cpp", + "${chip_root}/examples/common/pigweed/efr32/PigweedLoggerMutex.cpp", + "${examples_common_plat_dir}/PigweedLogger.cpp", + "${examples_common_plat_dir}/Rpc.cpp", + ] + + deps += [ + "$dir_pw_hdlc:default_addresses", + "$dir_pw_hdlc:rpc_channel_output", + "$dir_pw_stream:sys_io_stream", + "$dir_pw_trace", + "$dir_pw_trace_tokenized", + "$dir_pw_trace_tokenized:trace_rpc_service", + "${chip_root}/config/efr32/lib/pw_rpc:pw_rpc", + "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:ot_cli_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:thread_service.nanopb_rpc", + ] + + if (wifi_soc) { + deps += [ "${examples_plat_dir}/pw_sys_io:pw_sys_io_siwx917" ] + } else { + deps += [ "${examples_common_plat_dir}/pw_sys_io:pw_sys_io_silabs" ] + } + + deps += pw_build_LINK_DEPS + + include_dirs += [ + "${chip_root}/examples/common", + "${chip_root}/examples/common/pigweed/efr32", + ] + } + + ldscript = "${examples_common_plat_dir}/ldscripts/${silabs_family}.ld" + + inputs = [ ldscript ] + + ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ] + + if (chip_print_memory_usage) { + ldflags += [ + "-Wl,--print-memory-usage", + "-fstack-usage", + ] + } + + # WiFi Settings + if (chip_enable_wifi) { + ldflags += [ + "-Wl,--defsym", + "-Wl,SILABS_WIFI=1", + ] + } + + output_dir = root_out_dir +} + +group("silabs") { + deps = [ ":drink-machine" ] +} + +group("default") { + deps = [ ":silabs" ] +} diff --git a/examples/valve/silabs/README.md b/examples/valve/silabs/README.md new file mode 100644 index 00000000000000..ce763dfe45a37f --- /dev/null +++ b/examples/valve/silabs/README.md @@ -0,0 +1,2 @@ +./scripts/examples/gn_silabs_example.sh ./examples/valve/silabs/ +./out/drink-machine-efr BRD2703A diff --git a/examples/valve/silabs/build_for_wifi_args.gni b/examples/valve/silabs/build_for_wifi_args.gni new file mode 100644 index 00000000000000..a63ee60138ebcc --- /dev/null +++ b/examples/valve/silabs/build_for_wifi_args.gni @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Google, all rights reserved +# + +import("//build_overrides/chip.gni") +import("${chip_root}/config/standalone/args.gni") + +silabs_sdk_target = get_label_info(":sdk", "label_no_toolchain") +chip_enable_openthread = false +import("${chip_root}/src/platform/silabs/wifi_args.gni") + +chip_enable_read_client = false + +chip_enable_ota_requestor = false +app_data_model = "${chip_root}/examples/valve/valve-common:valve-common" diff --git a/examples/valve/silabs/build_for_wifi_gnfile.gn b/examples/valve/silabs/build_for_wifi_gnfile.gn new file mode 100644 index 00000000000000..d391814190d09f --- /dev/null +++ b/examples/valve/silabs/build_for_wifi_gnfile.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") + +# The location of the build configuration file. +buildconfig = "${build_root}/config/BUILDCONFIG.gn" + +# CHIP uses angle bracket includes. +check_system_includes = true + +default_args = { + target_cpu = "arm" + target_os = "freertos" + chip_enable_wifi = true + import("//build_for_wifi_args.gni") +} diff --git a/examples/valve/silabs/build_overrides b/examples/valve/silabs/build_overrides new file mode 120000 index 00000000000000..e578e73312ebd1 --- /dev/null +++ b/examples/valve/silabs/build_overrides @@ -0,0 +1 @@ +../../build_overrides \ No newline at end of file diff --git a/examples/valve/silabs/include/AppConfig.h b/examples/valve/silabs/include/AppConfig.h new file mode 100644 index 00000000000000..5c3615290da705 --- /dev/null +++ b/examples/valve/silabs/include/AppConfig.h @@ -0,0 +1,28 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "silabs_utils.h" + +#define APP_TASK_NAME "app_task" + +#define BLE_DEV_NAME "DMDEV" + +#define APP_EVENT_QUEUE_SIZE 30 diff --git a/examples/valve/silabs/include/AppEvent.h b/examples/valve/silabs/include/AppEvent.h new file mode 100644 index 00000000000000..7a19b719edad25 --- /dev/null +++ b/examples/valve/silabs/include/AppEvent.h @@ -0,0 +1,55 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +struct AppEvent; +typedef void (*EventHandler)(AppEvent *); + +struct AppEvent +{ + enum AppEventTypes + { + kEventType_Button = 0, + kEventType_Timer, + kEventType_Light, + kEventType_Install, + }; + + uint16_t Type; + + union + { + struct + { + uint8_t Action; + } ButtonEvent; + struct + { + void * Context; + } TimerEvent; + struct + { + uint8_t Action; + int32_t Actor; + } LightEvent; + }; + + EventHandler Handler; +}; diff --git a/examples/valve/silabs/include/AppTask.h b/examples/valve/silabs/include/AppTask.h new file mode 100644 index 00000000000000..a525405698ccda --- /dev/null +++ b/examples/valve/silabs/include/AppTask.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +/********************************************************** + * Includes + *********************************************************/ + +#include +#include + +#include "AppEvent.h" +#include "BaseApplication.h" +#include +#include +#include +#include + +#include "DrinksMachineDeviceDriver.h" + +/********************************************************** + * Defines + *********************************************************/ + +// Application-defined error codes in the CHIP_ERROR space. +#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01) +#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02) +#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03) +#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04) +#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05) +#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06) + +/********************************************************** + * AppTask Declaration + *********************************************************/ + +class AppTask : public BaseApplication +{ + +public: + AppTask() = default; + + static AppTask & GetAppTask() { return sAppTask; } + + /** + * @brief AppTask task main loop function + * + * @param pvParameter FreeRTOS task parameter + */ + static void AppTaskMain(void * pvParameter); + + CHIP_ERROR StartAppTask(); + +private: + static AppTask sAppTask; + + /** + * @brief AppTask initialisation function + * + * @return CHIP_ERROR + */ + CHIP_ERROR Init(); +}; diff --git a/examples/valve/silabs/include/CHIPProjectConfig.h b/examples/valve/silabs/include/CHIPProjectConfig.h new file mode 100644 index 00000000000000..c64f4b0c453062 --- /dev/null +++ b/examples/valve/silabs/include/CHIPProjectConfig.h @@ -0,0 +1,68 @@ + +#pragma once + +// Use a default pairing code if one hasn't been provisioned in flash. +#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 +#endif + +// #ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR +// #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 3840 +// #endif + +// #define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 3 +// #define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "1.0.3" + +// For convenience, Chip Security Test Mode can be enabled and the +// requirement for authentication in various protocols can be disabled. +// +// WARNING: These options make it possible to circumvent basic Chip security functionality, +// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS. +// +#define CHIP_CONFIG_SECURITY_TEST_MODE 0 + +#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x6006 + +#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xCAFE + +/** + * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + * + * Enable support for Chip-over-BLE (CHIPoBLE). + */ +#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1 + +/** + * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER + * + * Enables the use of a hard-coded default serial number if none + * is found in Chip NV storage. + */ +#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "1" + +/** + * CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS + * + * Enable recording UTC timestamps. + */ +#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1 + +/** + * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE + * + * A size, in bytes, of the individual debug event logging buffer. + */ +#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) + +/** + * @def CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL + * + * @brief + * Active retransmit interval, or time to wait before retransmission after + * subsequent failures in milliseconds. + * + * This is the default value, that might be adjusted by end device depending on its + * needs (e.g. sleeping period) using Service Discovery TXT record CRA key. + * + */ +#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) diff --git a/examples/valve/silabs/include/DrinksMachineDeviceDriver.h b/examples/valve/silabs/include/DrinksMachineDeviceDriver.h new file mode 100644 index 00000000000000..cf46c29d34c9d6 --- /dev/null +++ b/examples/valve/silabs/include/DrinksMachineDeviceDriver.h @@ -0,0 +1,28 @@ +// Copyrigh 2024 Google, All Rights Reserved. + +#pragma once + +#include +#include + +namespace google { +namespace matter { + +class DrinksMachineSilabsDriver +{ +public: + DrinksMachineSilabsDriver() {} + + void Init(); + + void SetPumpEnabled(uint8_t pump, bool enabled); + + static DrinksMachineSilabsDriver & GetInstance() + { + static DrinksMachineSilabsDriver sInstance; + return sInstance; + } +}; + +} // namespace matter +} // namespace google diff --git a/examples/valve/silabs/openthread.gn b/examples/valve/silabs/openthread.gn new file mode 100644 index 00000000000000..acc23ef549aa3b --- /dev/null +++ b/examples/valve/silabs/openthread.gn @@ -0,0 +1,30 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") + +# The location of the build configuration file. +buildconfig = "${build_root}/config/BUILDCONFIG.gn" + +# CHIP uses angle bracket includes. +check_system_includes = true + +default_args = { + target_cpu = "arm" + target_os = "freertos" + chip_openthread_ftd = true + optimize_debug_level = "s" + + import("//openthread.gni") +} diff --git a/examples/valve/silabs/openthread.gni b/examples/valve/silabs/openthread.gni new file mode 100644 index 00000000000000..650fc128c79251 --- /dev/null +++ b/examples/valve/silabs/openthread.gni @@ -0,0 +1,29 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("${chip_root}/config/standalone/args.gni") +import("${chip_root}/src/platform/silabs/efr32/args.gni") + +silabs_sdk_target = get_label_info(":sdk", "label_no_toolchain") + +app_data_model = "${chip_root}/examples/valve/valve-common:valve-common" +chip_enable_ota_requestor = false +chip_enable_openthread = true + +# Not needed for the Lighting-app +chip_enable_read_client = false + +openthread_external_platform = + "${chip_root}/third_party/openthread/platforms/efr32:libopenthread-efr32" diff --git a/examples/valve/silabs/src/AppTask.cpp b/examples/valve/silabs/src/AppTask.cpp new file mode 100644 index 00000000000000..9253686b46e137 --- /dev/null +++ b/examples/valve/silabs/src/AppTask.cpp @@ -0,0 +1,225 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AppTask.h" +#include "AppConfig.h" + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +#include + +#include "DrinksMachineDeviceDriver.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::ValveConfigurationAndControl; +using namespace chip::DeviceLayer; +using namespace chip::DeviceLayer::Silabs; +using namespace google::matter; + +// HACK: on Silabs to remove the Example DAC provider. Dunno why it's even needed. +namespace chip { +namespace Credentials { +namespace Examples { + +DeviceAttestationCredentialsProvider * GetExampleDACProvider() +{ + return nullptr; +} + +} // namespace Examples +} // namespace Credentials +} // namespace chip + +namespace { +class PrintOnlyDelegate : public NonLevelControlDelegate +{ +public: + PrintOnlyDelegate(EndpointId endpoint) : mEndpoint(endpoint) {} + CHIP_ERROR HandleOpenValve(ValveStateEnum & currentState, BitMask & valveFault) override + { + ChipLogError(NotSpecified, "\n\nVALVE IS OPENING on endpoint %u!!!!!\n\n", mEndpoint); + state = ValveStateEnum::kOpen; + currentState = state; + return CHIP_NO_ERROR; + } + ValveStateEnum GetCurrentValveState() override { return state; } + CHIP_ERROR HandleCloseValve(ValveStateEnum & currentState, BitMask & valveFault) override + { + ChipLogError(NotSpecified, "\n\nVALVE IS CLOSING on endpoint %u!!!!!\n\n", mEndpoint); + state = ValveStateEnum::kClosed; + currentState = state; + return CHIP_NO_ERROR; + } + +private: + ValveStateEnum state = ValveStateEnum::kClosed; + EndpointId mEndpoint; +}; + +// TODO: Does this conflict with the kvs delegate that's statically allocated in the AppMain? +// I think as long as the manager is the same, we're ok, but need to confirm. +KvsPersistentStorageDelegate sStorage; + +class NonLevelValveEndpoint +{ +public: + NonLevelValveEndpoint(EndpointId endpoint) : + mEndpoint(endpoint), mContext(mEndpoint, sStorage), mDelegate(mEndpoint), mLogic(mDelegate, mContext), + mInterface(mEndpoint, mLogic) + {} + CHIP_ERROR Init() + { + ReturnErrorOnFailure(mLogic.Init(kConformance, kInitParams)); + ReturnErrorOnFailure(mInterface.Init()); + return CHIP_NO_ERROR; + } + +private: + const ClusterConformance kConformance = { + .featureMap = 0, .supportsDefaultOpenLevel = false, .supportsValveFault = false, .supportsLevelStep = false + }; + const ClusterInitParameters kInitParams = { .currentState = DataModel::MakeNullable(ValveStateEnum::kClosed), + .currentLevel = DataModel::NullNullable, + .valveFault = 0, + .levelStep = 1 }; + EndpointId mEndpoint; + MatterContext mContext; + PrintOnlyDelegate mDelegate; + ClusterLogic mLogic; + Interface mInterface; +}; + +NonLevelValveEndpoint ep1(1); +NonLevelValveEndpoint ep2(2); +NonLevelValveEndpoint ep3(3); +NonLevelValveEndpoint ep4(4); +NonLevelValveEndpoint ep5(5); +NonLevelValveEndpoint ep6(6); + +// from https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/namespaces/Namespace-Common-Position.adoc +constexpr const uint8_t kNamespaceCommonPosition = 0x8; +constexpr const uint8_t kNamespaceCommonPositionRow = 0x5; + +const Clusters::Descriptor::Structs::SemanticTagStruct::Type gEp1TagList[] = { + { .namespaceID = kNamespaceCommonPosition, + .tag = kNamespaceCommonPositionRow, + .label = chip::MakeOptional(DataModel::Nullable("1"_span)) }, +}; +const Clusters::Descriptor::Structs::SemanticTagStruct::Type gEp2TagList[] = { + { .namespaceID = kNamespaceCommonPosition, + .tag = kNamespaceCommonPositionRow, + .label = chip::MakeOptional(DataModel::Nullable("2"_span)) }, +}; +const Clusters::Descriptor::Structs::SemanticTagStruct::Type gEp3TagList[] = { + { .namespaceID = kNamespaceCommonPosition, + .tag = kNamespaceCommonPositionRow, + .label = chip::MakeOptional(DataModel::Nullable("3"_span)) }, +}; +const Clusters::Descriptor::Structs::SemanticTagStruct::Type gEp4TagList[] = { + { .namespaceID = kNamespaceCommonPosition, + .tag = kNamespaceCommonPositionRow, + .label = chip::MakeOptional(DataModel::Nullable("4"_span)) }, +}; +const Clusters::Descriptor::Structs::SemanticTagStruct::Type gEp5TagList[] = { + { .namespaceID = kNamespaceCommonPosition, + .tag = kNamespaceCommonPositionRow, + .label = chip::MakeOptional(DataModel::Nullable("5"_span)) }, +}; +const Clusters::Descriptor::Structs::SemanticTagStruct::Type gEp6TagList[] = { + { .namespaceID = kNamespaceCommonPosition, + .tag = kNamespaceCommonPositionRow, + .label = chip::MakeOptional(DataModel::Nullable("6"_span)) }, +}; +} // namespace + +using namespace chip::TLV; +using namespace ::chip::DeviceLayer; + +AppTask AppTask::sAppTask; + +CHIP_ERROR AppTask::Init() +{ + // DrinksMachineSilabsDriver::GetInstance().Init(); + + CHIP_ERROR err = BaseApplication::Init(); + if (err != CHIP_NO_ERROR) + { + SILABS_LOG("BaseApplication::Init() failed"); + appError(err); + } + + return err; +} + +CHIP_ERROR AppTask::StartAppTask() +{ + return BaseApplication::StartAppTask(AppTaskMain); +} + +void AppTask::AppTaskMain(void * pvParameter) +{ + AppEvent event; + + osMessageQueueId_t sAppEventQueue = *(static_cast(pvParameter)); + + CHIP_ERROR err = sAppTask.Init(); + if (err != CHIP_NO_ERROR) + { + SILABS_LOG("AppTask.Init() failed"); + appError(err); + } + +#if !(defined(CHIP_CONFIG_ENABLE_ICD_SERVER) && CHIP_CONFIG_ENABLE_ICD_SERVER) + sAppTask.StartStatusLEDTimer(); +#endif + + SILABS_LOG("App Task started"); + + while (true) + { + osStatus_t eventReceived = osMessageQueueGet(sAppEventQueue, &event, NULL, osWaitForever); + while (eventReceived == osOK) + { + sAppTask.DispatchEvent(&event); + eventReceived = osMessageQueueGet(sAppEventQueue, &event, NULL, 0); + } + } +} diff --git a/examples/valve/silabs/src/DrinksMachineDeviceDriver.cpp b/examples/valve/silabs/src/DrinksMachineDeviceDriver.cpp new file mode 100644 index 00000000000000..44f7650909742f --- /dev/null +++ b/examples/valve/silabs/src/DrinksMachineDeviceDriver.cpp @@ -0,0 +1,104 @@ +// Copyrigh 2024 Google, All Rights Reserved. + +#include + +#include +#include + +#include "DrinksMachineDeviceDriver.h" + +#include "gpiointerrupt.h" + +#include "em_chip.h" +#include "em_cmu.h" +#include "em_gpio.h" + +#include "FreeRTOS.h" +#include "timers.h" + +#include "silabs_utils.h" + +#include + +// ========= Pin definitions (local) ======= +// Right side pin 8 +#define PUMP_0_PORT gpioPortC +#define PUMP_0_OUT_PIN 0 +// Right side pin 7 +#define PUMP_1_PORT gpioPortC +#define PUMP_1_OUT_PIN 1 +// Right side pin 6 +#define PUMP_2_PORT gpioPortC +#define PUMP_2_OUT_PIN 2 +// Left side pin 8 +#define PUMP_3_PORT gpioPortD +#define PUMP_3_OUT_PIN 5 +// Left side pin 7 +#define PUMP_4_PORT gpioPortD +#define PUMP_4_OUT_PIN 4 +// Left side pin 6 +#define PUMP_5_PORT gpioPortB +#define PUMP_5_OUT_PIN 4 + +// ============ Start of driver code ============= + +namespace google { +namespace matter { + +namespace { + +struct PortAndPin +{ + PortAndPin(unsigned the_port, unsigned the_pin) : port(the_port), pin(the_pin) {} + + unsigned port; + unsigned pin; +}; + +const PortAndPin gPumpMappings[] = { PortAndPin{ PUMP_0_PORT, PUMP_0_OUT_PIN }, PortAndPin{ PUMP_1_PORT, PUMP_1_OUT_PIN }, + PortAndPin{ PUMP_2_PORT, PUMP_2_OUT_PIN }, PortAndPin{ PUMP_3_PORT, PUMP_3_OUT_PIN }, + PortAndPin{ PUMP_4_PORT, PUMP_4_OUT_PIN }, PortAndPin{ PUMP_5_PORT, PUMP_5_OUT_PIN } }; + +const size_t kNumPumps = sizeof(gPumpMappings) / sizeof(PortAndPin); +} // namespace + +// Singleton instance. + +void DrinksMachineSilabsDriver::Init() +{ + /* Enable GPIO in CMU */ + CMU_ClockEnable(cmuClock_GPIO, true); + + /* Initialize GPIO interrupt dispatcher */ + GPIOINT_Init(); + + for (size_t i = 0; i < kNumPumps; ++i) + { + GPIO_PinModeSet(gPumpMappings[i].port, gPumpMappings[i].pin, gpioModePushPull, 0); + } +} + +void DrinksMachineSilabsDriver::SetPumpEnabled(uint8_t pump, bool enabled) +{ + if (pump >= kNumPumps) + { + SILABS_LOG("Unknown pump number %u", pump); + return; + } + + PortAndPin port_and_pin = gPumpMappings[pump]; + + if (enabled) + { + SILABS_LOG("Setting pump %u enabled", pump); + GPIO_PinOutSet(port_and_pin.port, port_and_pin.pin); + } + else + { + SILABS_LOG("Setting pump %u disabled", pump); + GPIO_PinOutClear(port_and_pin.port, port_and_pin.pin); + } +} + +} // namespace matter +} // namespace google diff --git a/examples/valve/silabs/src/ZclCallbacks.cpp b/examples/valve/silabs/src/ZclCallbacks.cpp new file mode 100644 index 00000000000000..67054a6f8c7a72 --- /dev/null +++ b/examples/valve/silabs/src/ZclCallbacks.cpp @@ -0,0 +1,25 @@ +// Copyright 2024 Google + +#include "AppConfig.h" + +#include +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::app::Clusters; + +void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, + uint8_t * value) +{ + ClusterId clusterId = attributePath.mClusterId; + AttributeId attributeId = attributePath.mAttributeId; + ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); + + if (clusterId == Identify::Id) + { + ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", + ChipLogValueMEI(attributeId), type, *value, size); + } +} diff --git a/examples/valve/silabs/third_party/connectedhomeip b/examples/valve/silabs/third_party/connectedhomeip new file mode 120000 index 00000000000000..c866b86874994d --- /dev/null +++ b/examples/valve/silabs/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../.. \ No newline at end of file diff --git a/examples/valve/silabs/with_pw_rpc.gni b/examples/valve/silabs/with_pw_rpc.gni new file mode 100644 index 00000000000000..b53832f4b3d468 --- /dev/null +++ b/examples/valve/silabs/with_pw_rpc.gni @@ -0,0 +1,29 @@ +# Copyright (c) 2021 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# add this gni as import in your build args to use pigweed in the example +# 'import("//with_pw_rpc.gni")' + +import("//build_overrides/chip.gni") +import("${chip_root}/config/efr32/lib/pw_rpc/pw_rpc.gni") +import("${chip_root}/examples/platform/silabs/args.gni") + +silabs_sdk_target = get_label_info(":sdk", "label_no_toolchain") + +app_data_model = "${chip_root}/examples/lighting-app/lighting-common" +chip_enable_pw_rpc = true +chip_enable_openthread = true + +# Light app on EFR enables tracing server +pw_trace_BACKEND = "$dir_pw_trace_tokenized"