From 4536d4003f2b00e01ddcc487d2529355db28e8b7 Mon Sep 17 00:00:00 2001
From: Your Name <dooku@gunther>
Date: Thu, 11 Nov 2021 19:21:15 +0100
Subject: [PATCH] Basic RGB LED implementation + minor changes

---
 fw/Core/Inc/i2c.h       |   6 +-
 fw/Core/Inc/main.h      |   7 +-
 fw/Core/Inc/rgbled.h    |  47 +++++++++
 fw/Core/Src/i2c.c       |   8 +-
 fw/Core/Src/main.c      | 222 ++++++++++++++++++++++++++++++----------
 fw/Core/Src/rgbled.c    |  36 +++++++
 fw/iaq_wired_sensor.ioc |  34 +++---
 7 files changed, 281 insertions(+), 79 deletions(-)
 create mode 100644 fw/Core/Inc/rgbled.h
 create mode 100644 fw/Core/Src/rgbled.c

diff --git a/fw/Core/Inc/i2c.h b/fw/Core/Inc/i2c.h
index f346e68..29b78dd 100644
--- a/fw/Core/Inc/i2c.h
+++ b/fw/Core/Inc/i2c.h
@@ -39,8 +39,8 @@ typedef struct {
  * Function declarations
  */
 
-int i2c_init(i2c_context_t *context);
-int i2c_transmit(uint8_t address, uint8_t *buffer, int len);
-int i2c_receive(uint8_t address, uint8_t *buffer, int len);
+int8_t i2c_init(i2c_context_t *context);
+int8_t i2c_transmit(uint8_t address, uint8_t *buffer, int len);
+int8_t i2c_receive(uint8_t address, uint8_t *buffer, int len);
 
 #endif /* INC_I2C_H_ */
diff --git a/fw/Core/Inc/main.h b/fw/Core/Inc/main.h
index dd3504d..d1fec8e 100644
--- a/fw/Core/Inc/main.h
+++ b/fw/Core/Inc/main.h
@@ -54,6 +54,7 @@ extern "C" {
 #include "sps30.h"
 #include "modbus.h"
 #include "config.h"
+#include "rgbled.h"
 /* USER CODE END Includes */
 
 /* Exported types ------------------------------------------------------------*/
@@ -81,12 +82,6 @@ int8_t uart_enable_interrupts(void);
 /* USER CODE END EFP */
 
 /* Private defines -----------------------------------------------------------*/
-#define LED_B_Pin LL_GPIO_PIN_5
-#define LED_B_GPIO_Port GPIOA
-#define LED_G_Pin LL_GPIO_PIN_6
-#define LED_G_GPIO_Port GPIOA
-#define LED_R_Pin LL_GPIO_PIN_7
-#define LED_R_GPIO_Port GPIOA
 #ifndef NVIC_PRIORITYGROUP_0
 #define NVIC_PRIORITYGROUP_0         ((uint32_t)0x00000007) /*!< 0 bit  for pre-emption priority,
                                                                  4 bits for subpriority */
diff --git a/fw/Core/Inc/rgbled.h b/fw/Core/Inc/rgbled.h
new file mode 100644
index 0000000..d285d2a
--- /dev/null
+++ b/fw/Core/Inc/rgbled.h
@@ -0,0 +1,47 @@
+/*
+ * rgbled.h
+ *
+ *  Created on: Nov 11, 2021
+ *      Author: dooku
+ */
+
+#ifndef INC_RGBLED_H_
+#define INC_RGBLED_H_
+
+#include "stm32l0xx_ll_tim.h"
+#include "stddef.h"
+
+/*
+ * Return values for I2C functions
+ */
+
+#define RGBLED_OK 0
+#define RGBLED_ERROR -1 // generic error
+
+/*
+ * Type definitions
+ */
+
+typedef struct {
+	// tim2 ch1 B
+	// tim22 ch1 G
+	// tim22 ch2 R
+	TIM_TypeDef *timer_R;
+	TIM_TypeDef *timer_G;
+	TIM_TypeDef *timer_B;
+	uint8_t channel_R;
+	uint8_t channel_G;
+	uint8_t channel_B;
+
+} rgbled_context_t;
+
+/*
+ * Function declarations
+ */
+
+int8_t rgbled_init(rgbled_context_t *context);
+int8_t rgbled_set_color(uint16_t R, uint16_t G, uint16_t B);
+int8_t rgbled_off(void);
+
+
+#endif /* INC_RGBLED_H_ */
diff --git a/fw/Core/Src/i2c.c b/fw/Core/Src/i2c.c
index b0991b8..4279d27 100644
--- a/fw/Core/Src/i2c.c
+++ b/fw/Core/Src/i2c.c
@@ -8,9 +8,9 @@
 #include "i2c.h"
 #include "stm32l0xx_ll_usart.h"
 
-i2c_context_t *i2c_context;
+static i2c_context_t *i2c_context;
 
-int i2c_init(i2c_context_t *context)
+int8_t i2c_init(i2c_context_t *context)
 {
 	if (context == NULL) {
 		return I2C_ERROR;
@@ -19,7 +19,7 @@ int i2c_init(i2c_context_t *context)
 	return I2C_OK;
 }
 
-int i2c_transmit(uint8_t address, uint8_t *buffer, int len)
+int8_t i2c_transmit(uint8_t address, uint8_t *buffer, int len)
 {
 	/* prevent interrupts during I2C communication (e.g. collision with MODBUS) */
 //	LL_LPUART_Disable(LPUART1);
@@ -52,7 +52,7 @@ int i2c_transmit(uint8_t address, uint8_t *buffer, int len)
 	return I2C_OK;
 }
 
-int i2c_receive(uint8_t address, uint8_t *buffer, int len)
+int8_t i2c_receive(uint8_t address, uint8_t *buffer, int len)
 {
 //	__disable_irq();
 //	LL_LPUART_Disable(LPUART1);
diff --git a/fw/Core/Src/main.c b/fw/Core/Src/main.c
index 930de14..26fa05b 100644
--- a/fw/Core/Src/main.c
+++ b/fw/Core/Src/main.c
@@ -120,6 +120,8 @@ static void MX_GPIO_Init(void);
 static void MX_I2C1_Init(void);
 static void MX_USART2_UART_Init(void);
 static void MX_TIM21_Init(void);
+static void MX_TIM2_Init(void);
+static void MX_TIM22_Init(void);
 /* USER CODE BEGIN PFP */
 void USART2_TX_Buffer(uint8_t* buffer_tx, uint16_t buffer_tx_len);
 /* USER CODE END PFP */
@@ -178,12 +180,14 @@ int main(void)
   MX_I2C1_Init();
   MX_USART2_UART_Init();
   MX_TIM21_Init();
+  MX_TIM2_Init();
+  MX_TIM22_Init();
   /* USER CODE BEGIN 2 */
 
   /* Turn on MAGENTA LED to signal startup state */
-  LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
-  LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
-  LL_GPIO_ResetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
+//  LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
+//  LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
+//  LL_GPIO_ResetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
 
   /* Enable I2C for sensors */
   LL_I2C_Enable(I2C1);
@@ -199,11 +203,34 @@ int main(void)
   LL_TIM_EnableCounter(TIM21);
   LL_TIM_EnableIT_UPDATE(TIM21);
 
+  /* Enable PWM */
+  LL_TIM_CC_EnableChannel(TIM22, LL_TIM_CHANNEL_CH1);
+  LL_TIM_CC_EnableChannel(TIM22, LL_TIM_CHANNEL_CH2);
+  LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1);
+  LL_TIM_EnableCounter(TIM22);
+  LL_TIM_EnableCounter(TIM2);
+
   /* I2C context init (for SHT4x and SCD4x) */
   i2c_context_t i2c_context;
   i2c_context.i2c = I2C1;
   i2c_init(&i2c_context);
 
+  /* RGB LED context init */
+  rgbled_context_t rgbled_context;
+  rgbled_context.timer_R = TIM22;
+  rgbled_context.timer_G = TIM22;
+  rgbled_context.timer_B = TIM2;
+  rgbled_init(&rgbled_context);
+
+	LL_TIM_OC_SetCompareCH1(TIM2, 0); // B
+	LL_TIM_OC_SetCompareCH1(TIM22, 65535); // G
+	LL_TIM_OC_SetCompareCH2(TIM22, 65535); // R
+
+  while (1) {
+//	  rgbled_set_color(30000, 0, 0);
+	  LL_mDelay(1000);
+  }
+
   LL_mDelay(2000);
 
   scd4x_start_periodic_measurement();
@@ -320,33 +347,33 @@ int main(void)
 		  if (co2_valid == 1) {
 			  if (CO2 <= sensor_config.led_co2_alert_limit1) {
 				  /* CO2 is OK -> GREEN */
-				  LL_GPIO_SetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
-				  LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
-				  LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
+//				  LL_GPIO_SetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
+//				  LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
+//				  LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
 
 			  } else if ((sensor_config.led_co2_alert_limit1 < CO2) && (CO2 <= sensor_config.led_co2_alert_limit2)) {
-				  /* CO2 is NOT OK -> YELLOW */
-				  LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
-				  LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
-				  LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
+//				  /* CO2 is NOT OK -> YELLOW */
+//				  LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
+//				  LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
+//				  LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
 
 			  } else if (sensor_config.led_co2_alert_limit2 < CO2) {
 				  /* CO2 is CRITICAL -> RED */
-				  LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
-				  LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
-				  LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
+//				  LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
+//				  LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
+//				  LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
 			  }
 		  } else {
 
-			  LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
-			  LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
-			  LL_GPIO_ResetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
+//			  LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
+//			  LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
+//			  LL_GPIO_ResetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
 		  }
 
 	  } else {
-		  LL_GPIO_SetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
-		  LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
-		  LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
+//		  LL_GPIO_SetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
+//		  LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
+//		  LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
 	  }
     /* USER CODE END WHILE */
 
@@ -463,6 +490,61 @@ static void MX_I2C1_Init(void)
 
 }
 
+/**
+  * @brief TIM2 Initialization Function
+  * @param None
+  * @retval None
+  */
+static void MX_TIM2_Init(void)
+{
+
+  /* USER CODE BEGIN TIM2_Init 0 */
+
+  /* USER CODE END TIM2_Init 0 */
+
+  LL_TIM_InitTypeDef TIM_InitStruct = {0};
+  LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
+
+  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
+
+  /* Peripheral clock enable */
+  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
+
+  /* USER CODE BEGIN TIM2_Init 1 */
+
+  /* USER CODE END TIM2_Init 1 */
+  TIM_InitStruct.Prescaler = 0;
+  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
+  TIM_InitStruct.Autoreload = 65535;
+  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
+  LL_TIM_Init(TIM2, &TIM_InitStruct);
+  LL_TIM_DisableARRPreload(TIM2);
+  LL_TIM_OC_EnablePreload(TIM2, LL_TIM_CHANNEL_CH1);
+  TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
+  TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
+  TIM_OC_InitStruct.CompareValue = 0;
+  TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
+  LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH1, &TIM_OC_InitStruct);
+  LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH1);
+  LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET);
+  LL_TIM_DisableMasterSlaveMode(TIM2);
+  /* USER CODE BEGIN TIM2_Init 2 */
+
+  /* USER CODE END TIM2_Init 2 */
+  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
+  /**TIM2 GPIO Configuration
+  PA5   ------> TIM2_CH1
+  */
+  GPIO_InitStruct.Pin = LL_GPIO_PIN_5;
+  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
+  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
+  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
+  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
+  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
+  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+}
+
 /**
   * @brief TIM21 Initialization Function
   * @param None
@@ -502,6 +584,74 @@ static void MX_TIM21_Init(void)
 
 }
 
+/**
+  * @brief TIM22 Initialization Function
+  * @param None
+  * @retval None
+  */
+static void MX_TIM22_Init(void)
+{
+
+  /* USER CODE BEGIN TIM22_Init 0 */
+
+  /* USER CODE END TIM22_Init 0 */
+
+  LL_TIM_InitTypeDef TIM_InitStruct = {0};
+  LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
+
+  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
+
+  /* Peripheral clock enable */
+  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM22);
+
+  /* USER CODE BEGIN TIM22_Init 1 */
+
+  /* USER CODE END TIM22_Init 1 */
+  TIM_InitStruct.Prescaler = 0;
+  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
+  TIM_InitStruct.Autoreload = 65535;
+  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
+  LL_TIM_Init(TIM22, &TIM_InitStruct);
+  LL_TIM_DisableARRPreload(TIM22);
+  LL_TIM_OC_EnablePreload(TIM22, LL_TIM_CHANNEL_CH1);
+  TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
+  TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
+  TIM_OC_InitStruct.CompareValue = 32768;
+  TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
+  LL_TIM_OC_Init(TIM22, LL_TIM_CHANNEL_CH1, &TIM_OC_InitStruct);
+  LL_TIM_OC_DisableFast(TIM22, LL_TIM_CHANNEL_CH1);
+  LL_TIM_OC_EnablePreload(TIM22, LL_TIM_CHANNEL_CH2);
+  TIM_OC_InitStruct.CompareValue = 0;
+  LL_TIM_OC_Init(TIM22, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct);
+  LL_TIM_OC_DisableFast(TIM22, LL_TIM_CHANNEL_CH2);
+  LL_TIM_SetTriggerOutput(TIM22, LL_TIM_TRGO_RESET);
+  LL_TIM_DisableMasterSlaveMode(TIM22);
+  /* USER CODE BEGIN TIM22_Init 2 */
+
+  /* USER CODE END TIM22_Init 2 */
+  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
+  /**TIM22 GPIO Configuration
+  PA6   ------> TIM22_CH1
+  PA7   ------> TIM22_CH2
+  */
+  GPIO_InitStruct.Pin = LL_GPIO_PIN_6;
+  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
+  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
+  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
+  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
+  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
+  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+  GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
+  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
+  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
+  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
+  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
+  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
+  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+}
+
 /**
   * @brief USART2 Initialization Function
   * @param None
@@ -594,44 +744,10 @@ static void MX_USART2_UART_Init(void)
   */
 static void MX_GPIO_Init(void)
 {
-  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
 
   /* GPIO Ports Clock Enable */
   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
 
-  /**/
-  LL_GPIO_ResetOutputPin(LED_B_GPIO_Port, LED_B_Pin);
-
-  /**/
-  LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin);
-
-  /**/
-  LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin);
-
-  /**/
-  GPIO_InitStruct.Pin = LED_B_Pin;
-  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
-  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
-  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
-  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
-  LL_GPIO_Init(LED_B_GPIO_Port, &GPIO_InitStruct);
-
-  /**/
-  GPIO_InitStruct.Pin = LED_G_Pin;
-  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
-  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
-  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
-  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
-  LL_GPIO_Init(LED_G_GPIO_Port, &GPIO_InitStruct);
-
-  /**/
-  GPIO_InitStruct.Pin = LED_R_Pin;
-  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
-  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
-  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
-  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
-  LL_GPIO_Init(LED_R_GPIO_Port, &GPIO_InitStruct);
-
 }
 
 /* USER CODE BEGIN 4 */
diff --git a/fw/Core/Src/rgbled.c b/fw/Core/Src/rgbled.c
new file mode 100644
index 0000000..9cc6334
--- /dev/null
+++ b/fw/Core/Src/rgbled.c
@@ -0,0 +1,36 @@
+/*
+ * rgbled.c
+ *
+ *  Created on: Nov 11, 2021
+ *      Author: dooku
+ */
+
+#include "rgbled.h"
+
+static rgbled_context_t *rgbled_context;
+
+
+int8_t rgbled_init(rgbled_context_t *context)
+{
+	if (context == NULL) {
+		return RGBLED_ERROR;
+	}
+	rgbled_context = context;
+
+	return RGBLED_OK;
+}
+
+int8_t rgbled_set_color(uint16_t R, uint16_t G, uint16_t B)
+{
+	// tim2 ch1 B
+	// tim22 ch1 G
+	// tim22 ch2 R
+	LL_TIM_OC_SetCompareCH1(TIM2, (uint32_t)B); // B
+	LL_TIM_OC_SetCompareCH1(TIM22, (uint32_t)G); // G
+	LL_TIM_OC_SetCompareCH2(TIM22, (uint32_t)R); // R
+}
+
+int8_t rgbled_off(void)
+{
+
+}
diff --git a/fw/iaq_wired_sensor.ioc b/fw/iaq_wired_sensor.ioc
index 77b23fd..91fa60c 100644
--- a/fw/iaq_wired_sensor.ioc
+++ b/fw/iaq_wired_sensor.ioc
@@ -9,9 +9,11 @@ Mcu.IP0=I2C1
 Mcu.IP1=NVIC
 Mcu.IP2=RCC
 Mcu.IP3=SYS
-Mcu.IP4=TIM21
-Mcu.IP5=USART2
-Mcu.IPNb=6
+Mcu.IP4=TIM2
+Mcu.IP5=TIM21
+Mcu.IP6=TIM22
+Mcu.IP7=USART2
+Mcu.IPNb=8
 Mcu.Name=STM32L031G(4-6)Ux
 Mcu.Package=UFQFPN28
 Mcu.Pin0=PA1
@@ -54,18 +56,12 @@ PA2.Mode=Asynchronous
 PA2.Signal=USART2_TX
 PA3.Mode=Asynchronous
 PA3.Signal=USART2_RX
-PA5.GPIOParameters=GPIO_Label
-PA5.GPIO_Label=LED_B
 PA5.Locked=true
-PA5.Signal=GPIO_Output
-PA6.GPIOParameters=GPIO_Label
-PA6.GPIO_Label=LED_G
+PA5.Signal=S_TIM2_CH1
 PA6.Locked=true
-PA6.Signal=GPIO_Output
-PA7.GPIOParameters=GPIO_Label
-PA7.GPIO_Label=LED_R
+PA6.Signal=S_TIM22_CH1
 PA7.Locked=true
-PA7.Signal=GPIO_Output
+PA7.Signal=S_TIM22_CH2
 PA9.GPIOParameters=GPIO_Pu
 PA9.GPIO_Pu=GPIO_PULLUP
 PA9.Mode=I2C
@@ -98,7 +94,7 @@ ProjectManager.StackSize=0x400
 ProjectManager.TargetToolchain=STM32CubeIDE
 ProjectManager.ToolChainLocation=
 ProjectManager.UnderRoot=true
-ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_I2C1_Init-I2C1-false-LL-true,4-MX_USART2_UART_Init-USART2-false-LL-true,5-MX_TIM21_Init-TIM21-false-LL-true
+ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_I2C1_Init-I2C1-false-LL-true,4-MX_USART2_UART_Init-USART2-false-LL-true,5-MX_TIM21_Init-TIM21-false-LL-true,6-MX_TIM2_Init-TIM2-false-LL-true,7-MX_TIM22_Init-TIM22-false-LL-true
 RCC.AHBFreq_Value=12000000
 RCC.APB1Freq_Value=12000000
 RCC.APB1TimFreq_Value=12000000
@@ -130,11 +126,23 @@ RCC.TimerFreq_Value=12000000
 RCC.USART2Freq_Value=12000000
 RCC.VCOOutputFreq_Value=48000000
 RCC.WatchDogFreq_Value=37000
+SH.S_TIM22_CH1.0=TIM22_CH1,PWM Generation1 CH1
+SH.S_TIM22_CH1.ConfNb=1
+SH.S_TIM22_CH2.0=TIM22_CH2,PWM Generation2 CH2
+SH.S_TIM22_CH2.ConfNb=1
+SH.S_TIM2_CH1.0=TIM2_CH1,PWM Generation1 CH1
+SH.S_TIM2_CH1.ConfNb=1
+TIM2.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
+TIM2.IPParameters=Channel-PWM Generation1 CH1
 TIM21.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
 TIM21.IPParameters=Prescaler,Period,AutoReloadPreload
 TIM21.IPParametersWithoutCheck=Prescaler,Period
 TIM21.Period=tim21_period
 TIM21.Prescaler=tim21_prescaler
+TIM22.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
+TIM22.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
+TIM22.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Pulse-PWM Generation1 CH1
+TIM22.Pulse-PWM\ Generation1\ CH1=32768
 USART2.BaudRate=config_baudrates[sensor_config.baudrate_index]
 USART2.IPParameters=VirtualMode-Asynchronous,VirtualMode-Hardware Flow Control (RS485),BaudRate,WordLength,Parity
 USART2.IPParametersWithoutCheck=BaudRate