diff --git a/README.md b/README.md index c2b4092..2222c74 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ # Silicon Labs Platform Applications # -[![Version Badge](https://img.shields.io/badge/-v2.4.0-green)](https://github.com/SiliconLabs/bluetooth_applications/releases) +[![Version Badge](https://img.shields.io/badge/-v2.5.0-green)](https://github.com/SiliconLabs/bluetooth_applications/releases) [![GSDK Badge](https://img.shields.io/badge/GSDK-v4.4.4-green)](https://github.com/SiliconLabs/gecko_sdk/releases) ![License badge](https://img.shields.io/badge/License-Zlib-green) @@ -82,6 +82,7 @@ This repository provides both SLCP projects (as External Repositories) and SLS p | 55 | Platform - IADC Tailgating |[Click Here](./platform_iadc_tailgating) | | 56 | Platform - IADC scan multiple external inputs |[Click Here](./platform_iadc_scan_multiple_external_input) | | 57 | Platform - LDMA trigger with TIMER |[Click Here](./platform_ldma_trigger_with_timer) | +| 58 | Platform - Multi channel PWM |[Click Here](./platform_multi_channel_pwm) ## Requirements ## diff --git a/platform_multi_channel_pwm/README.md b/platform_multi_channel_pwm/README.md new file mode 100644 index 0000000..dfe524a --- /dev/null +++ b/platform_multi_channel_pwm/README.md @@ -0,0 +1,72 @@ +# Platform - Multi Channel PWM # + +![Type badge](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/SiliconLabs/application_examples_ci/master/platform_applications/platform_multi_channel_pwm_common.json&label=Type&query=type&color=green) +![Technology badge](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/SiliconLabs/application_examples_ci/master/platform_applications/platform_multi_channel_pwm_common.json&label=Technology&query=technology&color=green) +![License badge](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/SiliconLabs/application_examples_ci/master/platform_applications/platform_multi_channel_pwm_common.json&label=License&query=license&color=green) +![SDK badge](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/SiliconLabs/application_examples_ci/master/platform_applications/platform_multi_channel_pwm_common.json&label=SDK&query=sdk&color=green) +![Build badge](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/SiliconLabs/application_examples_ci/master/platform_applications/platform_multi_channel_pwm_build_status.json) +![Flash badge](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/SiliconLabs/application_examples_ci/master/platform_applications/platform_multi_channel_pwm_common.json&label=Flash&query=flash&color=blue) +![RAM badge](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/SiliconLabs/application_examples_ci/master/platform_applications/platform_multi_channel_pwm_common.json&label=RAM&query=ram&color=blue) + +## Overview ## + +The example demonstrate the timer/letimer peripherals configuration in a way, that multiple channels are used and generate a PWM signal on certain GPIO pins. + +## Gecko SDK Version ## + +- GSDK v4.4.3 + +## Hardware Required ## + +- One SiliconLabs Wireless Gecko Starter Kit +- One of the SiliconLabs radio boards that listed below: + + - [EFR32xG21 2.4 GHz 20 dBm Radio Board](https://www.silabs.com/development-tools/wireless/slwrb4180b-efr32xg21-wireless-gecko-radio-board?tab=overview) + + - [EFR32xG22 Wireless Gecko 2.4 GHz +6 dBm 5x5, QFN40 Radio Board](https://www.silabs.com/development-tools/wireless/slwrb4182a-efr32xg22-wireless-gecko-radio-board?tab=overview) + + - [EFR32XG23 868-915 MHz +20 dBm Radio Board](https://www.silabs.com/development-tools/wireless/xg23-rb4210a-efr32xg23-868-915-mhz-20-dbm-radio-board?tab=overview) + + - [EFR32xG24 2.4 GHz 10 dBm Radio Board](https://www.silabs.com/development-tools/wireless/xg24-rb4186c-efr32xg24-wireless-gecko-radio-board?tab=overview) + + - [EFR32FG25 902-928 MHz +16 dBm Radio Board](https://www.silabs.com/development-tools/wireless/proprietary/fg25-rb4270b-efr32fg25-radio-board?tab=overview) + + - [EFR32BG27 Wireless 2.4 GHz +4 dBm Radio Board (Buck)](https://www.silabs.com/development-tools/wireless/bluetooth/bg27-rb4110b-efr32bg27-4-dbm-buck-wireless-radio-board?tab=overview) + +## Connections Required ## + +- Connect the board via a micro-USB cable to your PC to flash the example. + +## Setup ## + +To test this application, you can either create a project based on an example project or start with an empty example project. + +### Create a project based on an example project ### + +1. Make sure that this repository is added to [Preferences > Simplicity Studio > External Repos](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-about-the-launcher/welcome-and-device-tabs). + +2. From the Launcher Home, add your device to My Products, click on it, and click on the **EXAMPLE PROJECTS & DEMOS** tab. Find the example project filtering by **multi** and **pwm**. + +3. Click the **Create** button on the **Platform - Multi Channel PWM** example. Example project creation dialog pops up -> click **Finish** and Project should be generated. + + ![Create_example](image/create_example.png) + +4. Build and flash this example to the board. + +### Start with an empty example project ### + +1. Create an **Empty C Project** project for your hardware using Simplicity Studio 5. + +2. Replace the `app.c` file in the project root folder with the provided `app.c` (located in the src folder). + +3. Open the .slcp file. Select the SOFTWARE COMPONENTS tab and install the software components: + + - [Platform] → [Peripheral] → [TIMER] + +4. Build and flash the project to your device. + +## How It Works ## + +TIMER0 is initialized for PWM on 3 channels (0, 1, and 2) and routed to GPIO pins. PWM duty cycle on channel 0 increases from 0 -> 100%, whereas duty cycle on channel 1 decreases from 100 -> 0%. You can modify the GPIO pins configuration to the LEDs pin on the wireless starter kit or use an oscilloscope to see how PWM works on each channel. + +![result](image/result.png) diff --git a/platform_multi_channel_pwm/SimplicityStudio/platform_multi_channel_pwm.slcp b/platform_multi_channel_pwm/SimplicityStudio/platform_multi_channel_pwm.slcp new file mode 100644 index 0000000..983f4b4 --- /dev/null +++ b/platform_multi_channel_pwm/SimplicityStudio/platform_multi_channel_pwm.slcp @@ -0,0 +1,46 @@ +project_name: platform_multi_channel_pwm +package: platform +label: Platform - Multi channel PWM +description: | + This example project demonstrates the timer/letimer peripherals configuration in a way, that multiple (possibly all) + channels are used and generating a PWM signal on certain GPIO pins. +category: Example|Platform +quality: experimental + +filter: + - name: Device Type + value: [SoC] + - name: MCU + value: [32-bit MCU] + - name: Project Difficulty + value: [Advanced] + +component: + - id: sl_system + - id: device_init + - id: emlib_timer + - id: udelay + +readme: +- path: ../README.md + +include: +- path: ../src + file_list: + - path: app.h + +source: +- path: ../src/main.c +- path: ../src/app.c + +other_file: + - path: ../image/create_example.png + directory: "image" + - path: ../image/result.png + directory: "image" + +ui_hints: + highlight: + - path: readme.md + focus: true + diff --git a/platform_multi_channel_pwm/image/create_example.png b/platform_multi_channel_pwm/image/create_example.png new file mode 100644 index 0000000..7fe08c9 Binary files /dev/null and b/platform_multi_channel_pwm/image/create_example.png differ diff --git a/platform_multi_channel_pwm/image/result.png b/platform_multi_channel_pwm/image/result.png new file mode 100644 index 0000000..010af78 Binary files /dev/null and b/platform_multi_channel_pwm/image/result.png differ diff --git a/platform_multi_channel_pwm/src/app.c b/platform_multi_channel_pwm/src/app.c new file mode 100644 index 0000000..5adc62f --- /dev/null +++ b/platform_multi_channel_pwm/src/app.c @@ -0,0 +1,186 @@ +/***************************************************************************//** + * @file + * @brief app.c + ******************************************************************************* + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * SPDX-License-Identifier: Zlib + * + * The licensor of this software is Silicon Laboratories Inc. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + ******************************************************************************/ + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- +#include "em_gpio.h" +#include "em_timer.h" +#include "em_cmu.h" +#include "sl_udelay.h" + +// ----------------------------------------------------------------------------- +// Macros +// ----------------------------------------------------------------------------- +#define PWM_FREQ 1000 + +#define PWM_CHANNEL0_PORT gpioPortD +#define PWM_CHANNEL0_PIN 3 + +#define PWM_CHANNEL1_PORT gpioPortD +#define PWM_CHANNEL1_PIN 2 + +#define PWM_CHANNEL2_PORT gpioPortB +#define PWM_CHANNEL2_PIN 1 + +// ----------------------------------------------------------------------------- +// Local Variables +// ----------------------------------------------------------------------------- +static const uint32_t dutyCycle[] = { + 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, + 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, + 12, 12, 13, 13, 14, 15, 15, 16, 17, 17, + 18, 19, 19, 20, 21, 22, 23, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, + 37, 39, 40, 41, 43, 44, 46, 48, 49, 51, + 53, 54, 56, 58, 60, 62, 64, 66, 68, 71, + 73, 75, 78, 80, 83, 85, 88, 91, 94, 97, + 100, +}; + +/**************************************************************************//** + * @brief + * GPIO initialization + *****************************************************************************/ +void initGPIO(void) +{ + GPIO_PinModeSet(PWM_CHANNEL0_PORT, PWM_CHANNEL0_PIN, gpioModePushPull, 0); + GPIO_PinModeSet(PWM_CHANNEL1_PORT, PWM_CHANNEL1_PIN, gpioModePushPull, 0); + GPIO_PinModeSet(PWM_CHANNEL2_PORT, PWM_CHANNEL2_PIN, gpioModePushPull, 0); +} + +/**************************************************************************//** + * @brief + * CMU initialization + *****************************************************************************/ +void initCMU(void) +{ + CMU_ClockEnable(cmuClock_GPIO, true); + CMU_ClockEnable(cmuClock_TIMER0, true); +} + +/**************************************************************************//** + * @brief + * TIMER initialization + *****************************************************************************/ +void initTIMER(void) +{ + uint32_t timerFreq, topValue; + TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT; + TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT; + + // Don't start counter on initialization + timerInit.enable = false; + + // PWM mode sets/clears the output on compare/overflow events + timerCCInit.mode = timerCCModePWM; + + TIMER_Init(TIMER0, &timerInit); + + // Route CC0 output to PA6 + GPIO->TIMERROUTE[0].ROUTEEN = GPIO_TIMER_ROUTEEN_CC0PEN + | GPIO_TIMER_ROUTEEN_CC1PEN + | GPIO_TIMER_ROUTEEN_CC2PEN; + + GPIO->TIMERROUTE[0].CC0ROUTE = + (PWM_CHANNEL0_PORT << _GPIO_TIMER_CC0ROUTE_PORT_SHIFT) + | (PWM_CHANNEL0_PIN << + _GPIO_TIMER_CC0ROUTE_PIN_SHIFT); + + GPIO->TIMERROUTE[0].CC1ROUTE = + (PWM_CHANNEL1_PORT << _GPIO_TIMER_CC0ROUTE_PORT_SHIFT) + | (PWM_CHANNEL1_PIN << + _GPIO_TIMER_CC0ROUTE_PIN_SHIFT); + + GPIO->TIMERROUTE[0].CC2ROUTE = + (PWM_CHANNEL2_PORT << _GPIO_TIMER_CC0ROUTE_PORT_SHIFT) + | (PWM_CHANNEL2_PIN << + _GPIO_TIMER_CC0ROUTE_PIN_SHIFT); + + TIMER_InitCC(TIMER0, 0, &timerCCInit); + TIMER_InitCC(TIMER0, 1, &timerCCInit); + TIMER_InitCC(TIMER0, 2, &timerCCInit); + + // Set top value to overflow at the desired PWM_FREQ frequency + timerFreq = CMU_ClockFreqGet(cmuClock_TIMER0) / (timerInit.prescale + 1); + topValue = (timerFreq / PWM_FREQ); + TIMER_TopSet(TIMER0, topValue); + + // Now start the TIMER + TIMER_Enable(TIMER0, true); + + // Trigger DMA on compare event to set CCVB to update duty cycle on next + // period + TIMER_IntEnable(TIMER0, TIMER_IEN_CC0); +} + +/**************************************************************************//** + * @brief + * Set PWM Duty Cycle + *****************************************************************************/ +void PWMsetDutyCycle(uint8_t chan0, + uint8_t chan1, + uint8_t chan2) +{ + uint32_t top = TIMER_TopGet(TIMER0); + + // Set compare value + TIMER_CompareBufSet(TIMER0, 0, (top * chan0) / 100); + TIMER_CompareBufSet(TIMER0, 1, (top * chan1) / 100); + TIMER_CompareBufSet(TIMER0, 2, (top * chan2) / 100); +} + +/***************************************************************************//** + * Initialize application. + ******************************************************************************/ +void app_init(void) +{ + initCMU(); + initGPIO(); + initTIMER(); +} + +/***************************************************************************//** + * App ticking function. + ******************************************************************************/ +void app_process_action(void) +{ + for (uint8_t i = 0; i < 100; i++) { + PWMsetDutyCycle(dutyCycle[i], + dutyCycle[100 - i], + 50); + sl_udelay_wait(10000); + if (i == 0) { + sl_udelay_wait(500000); + } + } +} diff --git a/platform_multi_channel_pwm/src/app.h b/platform_multi_channel_pwm/src/app.h new file mode 100644 index 0000000..1744494 --- /dev/null +++ b/platform_multi_channel_pwm/src/app.h @@ -0,0 +1,44 @@ +/***************************************************************************//** + * @file + * @brief app.h + ******************************************************************************* + * # License + * Copyright 2018 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * SPDX-License-Identifier: Zlib + * + * The licensor of this software is Silicon Laboratories Inc. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + ******************************************************************************/ + +#ifndef APP_H +#define APP_H + +/***************************************************************************//** + * Initialize application. + ******************************************************************************/ +void app_init(void); + +/***************************************************************************//** + * App ticking function. + ******************************************************************************/ +void app_process_action(void); + +#endif // APP_H diff --git a/platform_multi_channel_pwm/src/main.c b/platform_multi_channel_pwm/src/main.c new file mode 100644 index 0000000..610ebbb --- /dev/null +++ b/platform_multi_channel_pwm/src/main.c @@ -0,0 +1,71 @@ +/***************************************************************************//** + * @file + * @brief main.c + ******************************************************************************* + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * SPDX-License-Identifier: Zlib + * + * The licensor of this software is Silicon Laboratories Inc. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + ******************************************************************************/ +#include "sl_component_catalog.h" +#include "sl_system_init.h" +#include "app.h" +#if defined(SL_CATALOG_POWER_MANAGER_PRESENT) +#include "sl_power_manager.h" +#endif +#if defined(SL_CATALOG_KERNEL_PRESENT) +#include "sl_system_kernel.h" +#else // SL_CATALOG_KERNEL_PRESENT +#include "sl_system_process_action.h" +#endif // SL_CATALOG_KERNEL_PRESENT + +int main(void) +{ + // Initialize Silicon Labs device, system, service(s) and protocol stack(s). + // Note that if the kernel is present, processing task(s) will be created by + // this call. + sl_system_init(); + + // Initialize the application. For example, create periodic timer(s) or + // task(s) if the kernel is present. + app_init(); + +#if defined(SL_CATALOG_KERNEL_PRESENT) + // Start the kernel. Task(s) created in app_init() will start running. + sl_system_kernel_start(); +#else // SL_CATALOG_KERNEL_PRESENT + while (1) { + // Do not remove this call: Silicon Labs components process action routine + // must be called from the super loop. + sl_system_process_action(); + + // Application process. + app_process_action(); + +#if defined(SL_CATALOG_POWER_MANAGER_PRESENT) + // Let the CPU go to sleep if the system allows it. + sl_power_manager_sleep(); +#endif + } +#endif // SL_CATALOG_KERNEL_PRESENT +} diff --git a/templates.xml b/templates.xml index ff2cc3b..be99cfb 100644 --- a/templates.xml +++ b/templates.xml @@ -851,4 +851,19 @@ + + + + + + + + + + + + + + + \ No newline at end of file