From 3d328fb7a2322e700f64d8f562a0d822aaa4f9fa Mon Sep 17 00:00:00 2001 From: Eduard Iten Date: Mon, 8 Dec 2025 11:27:15 +0100 Subject: [PATCH] Add initial CAN FD CDC composite firmware - Custom board definition for STM32G0B1KBU6 (ews_board) - Zephyr-based firmware with modular architecture - USB composite device: gs_usb CAN FD + CDC ACM interfaces - PFET control via CDC text commands (PA8, PB2) - Status LED on PB4, CAN FD on PB0/PB1 - No external crystal - uses HSI with USB clock recovery - Ready for build testing with: west build -b ews_board --- firmware/canfd_cdc_composite/CMakeLists.txt | 11 ++ firmware/canfd_cdc_composite/README.md | 47 ++++++++ .../boards/arm/ews_board/board.yml | 10 ++ .../boards/arm/ews_board/doc/index.rst | 47 ++++++++ .../boards/arm/ews_board/ews_board.dts | 104 ++++++++++++++++++ .../boards/arm/ews_board/ews_board_defconfig | 22 ++++ firmware/canfd_cdc_composite/prj.conf | 28 +++++ .../canfd_cdc_composite/src/cdc_handler.c | 87 +++++++++++++++ .../canfd_cdc_composite/src/cdc_handler.h | 20 ++++ firmware/canfd_cdc_composite/src/gs_usb_can.c | 62 +++++++++++ firmware/canfd_cdc_composite/src/gs_usb_can.h | 23 ++++ firmware/canfd_cdc_composite/src/main.c | 82 ++++++++++++++ .../canfd_cdc_composite/src/pfet_control.c | 78 +++++++++++++ .../canfd_cdc_composite/src/pfet_control.h | 31 ++++++ 14 files changed, 652 insertions(+) create mode 100644 firmware/canfd_cdc_composite/CMakeLists.txt create mode 100644 firmware/canfd_cdc_composite/README.md create mode 100644 firmware/canfd_cdc_composite/boards/arm/ews_board/board.yml create mode 100644 firmware/canfd_cdc_composite/boards/arm/ews_board/doc/index.rst create mode 100644 firmware/canfd_cdc_composite/boards/arm/ews_board/ews_board.dts create mode 100644 firmware/canfd_cdc_composite/boards/arm/ews_board/ews_board_defconfig create mode 100644 firmware/canfd_cdc_composite/prj.conf create mode 100644 firmware/canfd_cdc_composite/src/cdc_handler.c create mode 100644 firmware/canfd_cdc_composite/src/cdc_handler.h create mode 100644 firmware/canfd_cdc_composite/src/gs_usb_can.c create mode 100644 firmware/canfd_cdc_composite/src/gs_usb_can.h create mode 100644 firmware/canfd_cdc_composite/src/main.c create mode 100644 firmware/canfd_cdc_composite/src/pfet_control.c create mode 100644 firmware/canfd_cdc_composite/src/pfet_control.h diff --git a/firmware/canfd_cdc_composite/CMakeLists.txt b/firmware/canfd_cdc_composite/CMakeLists.txt new file mode 100644 index 0000000..0c5e6e4 --- /dev/null +++ b/firmware/canfd_cdc_composite/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(ews_canfd_cdc_composite) + +target_sources(app PRIVATE + src/main.c + src/cdc_handler.c + src/pfet_control.c + src/gs_usb_can.c +) \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/README.md b/firmware/canfd_cdc_composite/README.md new file mode 100644 index 0000000..d7208de --- /dev/null +++ b/firmware/canfd_cdc_composite/README.md @@ -0,0 +1,47 @@ +# CAN FD CDC Composite Firmware + +A Zephyr-based firmware for the EWS board that provides: +- CAN FD to gs_usb interface (similar to candlelight) +- USB CDC interface for PFET control +- USB composite device functionality + +## Features + +- **CAN FD Support**: Full CAN FD protocol support via gs_usb interface +- **USB Composite**: Single USB device with multiple interfaces: + - gs_usb interface for CAN communication + - CDC ACM interface for PFET control and status +- **PFET Control**: Control both output PFETs via CDC commands +- **Status LEDs**: Control status LEDs for visual feedback +- **Compatible**: Works with standard CAN utilities (can-utils, etc.) + +## Hardware Target + +- **MCU**: STM32G0B1KBU6 (on EWS board) +- **CAN**: CAN FD via FDCAN1 (PB0/PB1) with SN65HVD230 transceiver +- **USB**: USB 2.0 Full Speed (PA11/PA12) +- **GPIOs**: + - PFET1 control: PA8 + - PFET2 control: PB2 + - Status LED: PB4 + +## Build Requirements + +- Zephyr RTOS (v3.5+) +- West build tool +- ARM GCC toolchain + +## Building + +```bash +west build -b ews_board +``` + +## CDC Protocol + +The CDC interface uses simple text commands: +- `PFET1_ON\n` - Turn on PFET1 +- `PFET1_OFF\n` - Turn off PFET1 +- `PFET2_ON\n` - Turn on PFET2 +- `PFET2_OFF\n` - Turn off PFET2 +- `STATUS\n` - Get current PFET status \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/boards/arm/ews_board/board.yml b/firmware/canfd_cdc_composite/boards/arm/ews_board/board.yml new file mode 100644 index 0000000..5d3995b --- /dev/null +++ b/firmware/canfd_cdc_composite/boards/arm/ews_board/board.yml @@ -0,0 +1,10 @@ +identifier: ews_board +name: EWS Board +type: mcu +arch: arm +family: stm32 +series: stm32g0x +socs: + - name: stm32g0b1xx +testing: + default: true \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/boards/arm/ews_board/doc/index.rst b/firmware/canfd_cdc_composite/boards/arm/ews_board/doc/index.rst new file mode 100644 index 0000000..69fad32 --- /dev/null +++ b/firmware/canfd_cdc_composite/boards/arm/ews_board/doc/index.rst @@ -0,0 +1,47 @@ +# EWS Board + +## Overview + +The EWS Board is based on the STM32G0B1KBU6 microcontroller in UFQFPN32 package. + +## Hardware Features + +- STM32G0B1KBU6 MCU (Arm Cortex-M0+ core, 128 KB Flash, 36 KB RAM) +- Internal HSI oscillator with USB clock recovery +- USB 2.0 Full Speed interface +- CAN FD interface +- Status LED on PB4 +- Two PFET control outputs (PA8, PB2) + +## Pin Configuration + +| Function | Pin | Notes | +|----------|-----|-------| +| Status LED | PB4 | Active high | +| PFET1 Control | PA8 | Active high | +| PFET2 Control | PB2 | Active high | +| CAN RX | PB0 | FDCAN1_RX | +| CAN TX | PB1 | FDCAN1_TX | +| USB D- | PA11 | USB_DM | +| USB D+ | PA12 | USB_DP | + +## Clock Configuration + +The board uses the internal HSI oscillator (16 MHz) with PLL to generate: +- System clock: 64 MHz +- USB clock: 48 MHz (from PLL Q output) +- CAN clock: 64 MHz + +No external crystal is used; USB clock recovery ensures accurate timing for USB communication. + +## Programming and Debugging + +The board supports programming via: +- USB DFU (built-in STM32 bootloader) +- SWD interface (if exposed) + +## Building Firmware + +```bash +west build -b ews_board +``` \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/boards/arm/ews_board/ews_board.dts b/firmware/canfd_cdc_composite/boards/arm/ews_board/ews_board.dts new file mode 100644 index 0000000..1057fda --- /dev/null +++ b/firmware/canfd_cdc_composite/boards/arm/ews_board/ews_board.dts @@ -0,0 +1,104 @@ +/dts-v1/; +#include +#include + +/ { + model = "EWS Board STM32G0B1KBU6"; + compatible = "ews,ews-board"; + + chosen { + zephyr,console = &cdc_acm_uart0; + zephyr,shell-uart = &cdc_acm_uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,canbus = &fdcan1; + }; + + leds { + compatible = "gpio-leds"; + status_led: led_0 { + gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; + label = "Status LED"; + }; + }; + + pfets { + compatible = "gpio-leds"; + pfet1: pfet_1 { + gpios = <&gpioa 8 GPIO_ACTIVE_HIGH>; + label = "PFET1 Control"; + }; + pfet2: pfet_2 { + gpios = <&gpiob 2 GPIO_ACTIVE_HIGH>; + label = "PFET2 Control"; + }; + }; + + aliases { + led0 = &status_led; + pfet0 = &pfet1; + pfet1 = &pfet2; + }; +}; + +&clk_hsi { + status = "okay"; +}; + +&pll { + div-m = <1>; + mul-n = <8>; + div-q = <2>; + div-r = <2>; + clocks = <&clk_hsi>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; +}; + +&fdcan1 { + pinctrl-0 = <&fdcan1_rx_pb0 &fdcan1_tx_pb1>; + pinctrl-names = "default"; + bus-speed = <500000>; + bus-speed-data = <2000000>; + status = "okay"; +}; + +&usb { + pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; +}; + +&gpioa { + status = "okay"; +}; + +&gpiob { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x00002000>; + }; + slot0_partition: partition@2000 { + label = "image-0"; + reg = <0x00002000 0x0001E000>; + }; + }; +}; \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/boards/arm/ews_board/ews_board_defconfig b/firmware/canfd_cdc_composite/boards/arm/ews_board/ews_board_defconfig new file mode 100644 index 0000000..360dd30 --- /dev/null +++ b/firmware/canfd_cdc_composite/boards/arm/ews_board/ews_board_defconfig @@ -0,0 +1,22 @@ +# EWS Board Configuration + +CONFIG_SOC_SERIES_STM32G0X=y +CONFIG_SOC_STM32G0B1XX=y + +# Clock configuration - USB clock sync, no external crystal +CONFIG_CLOCK_CONTROL=y +CONFIG_CLOCK_STM32_HSI=y +CONFIG_CLOCK_STM32_PLL_SRC_HSI=y +CONFIG_CLOCK_STM32_PLL_M_DIVISOR=1 +CONFIG_CLOCK_STM32_PLL_N_MULTIPLIER=8 +CONFIG_CLOCK_STM32_PLL_Q_DIVISOR=2 +CONFIG_CLOCK_STM32_PLL_R_DIVISOR=2 + +# USB 48MHz from PLL +CONFIG_CLOCK_STM32_PLL_Q_DIVISOR=2 + +# Enable GPIO +CONFIG_GPIO=y + +# Enable CAN +CONFIG_CAN=y \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/prj.conf b/firmware/canfd_cdc_composite/prj.conf new file mode 100644 index 0000000..750ca54 --- /dev/null +++ b/firmware/canfd_cdc_composite/prj.conf @@ -0,0 +1,28 @@ +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_COMPOSITE=y + +# USB CDC ACM +CONFIG_USB_CDC_ACM=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=n +CONFIG_USB_UART_CONSOLE=y + +# CAN configuration +CONFIG_CAN=y +CONFIG_CAN_FD_MODE=y + +# Networking for gs_usb +CONFIG_NETWORKING=y +CONFIG_NET_SOCKETS=y +CONFIG_NET_SOCKETS_CAN=y + +# GPIO for PFET control +CONFIG_GPIO=y + +# Logging +CONFIG_LOG=y +CONFIG_USB_DEVICE_LOG_LEVEL_DBG=y + +# System +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/src/cdc_handler.c b/firmware/canfd_cdc_composite/src/cdc_handler.c new file mode 100644 index 0000000..eebbb33 --- /dev/null +++ b/firmware/canfd_cdc_composite/src/cdc_handler.c @@ -0,0 +1,87 @@ +/* + * CDC Handler Module + * Handles USB CDC ACM commands for PFET control + */ + +#include +#include +#include +#include +#include +#include + +#include "cdc_handler.h" +#include "pfet_control.h" + +LOG_MODULE_REGISTER(cdc_handler, LOG_LEVEL_DBG); + +#define CDC_DEVICE_NAME "CDC_ACM_0" +#define RX_BUF_SIZE 64 + +static const struct device *cdc_dev; +static char rx_buf[RX_BUF_SIZE]; +static int rx_pos = 0; + +static void process_command(char *cmd) +{ + char response[128]; + + if (strncmp(cmd, "PFET1_ON", 8) == 0) { + pfet_set_state(1, true); + strcpy(response, "PFET1 ON\r\n"); + } else if (strncmp(cmd, "PFET1_OFF", 9) == 0) { + pfet_set_state(1, false); + strcpy(response, "PFET1 OFF\r\n"); + } else if (strncmp(cmd, "PFET2_ON", 8) == 0) { + pfet_set_state(2, true); + strcpy(response, "PFET2 ON\r\n"); + } else if (strncmp(cmd, "PFET2_OFF", 9) == 0) { + pfet_set_state(2, false); + strcpy(response, "PFET2 OFF\r\n"); + } else if (strncmp(cmd, "STATUS", 6) == 0) { + snprintf(response, sizeof(response), + "PFET1: %s, PFET2: %s\r\n", + pfet_get_state(1) ? "ON" : "OFF", + pfet_get_state(2) ? "ON" : "OFF"); + } else { + strcpy(response, "ERROR: Unknown command\r\n"); + } + + /* Send response */ + uart_poll_out_string(cdc_dev, response); +} + +int cdc_handler_init(void) +{ + cdc_dev = device_get_binding(CDC_DEVICE_NAME); + if (!cdc_dev) { + LOG_ERR("CDC ACM device not found"); + return -ENODEV; + } + + LOG_INF("CDC handler initialized"); + return 0; +} + +void cdc_handler_process(void) +{ + char c; + + /* Check for incoming characters */ + while (uart_poll_in(cdc_dev, (unsigned char *)&c) == 0) { + if (c == '\n' || c == '\r') { + /* End of command */ + if (rx_pos > 0) { + rx_buf[rx_pos] = '\0'; + process_command(rx_buf); + rx_pos = 0; + } + } else if (rx_pos < (RX_BUF_SIZE - 1)) { + /* Add character to buffer */ + rx_buf[rx_pos++] = c; + } else { + /* Buffer full, reset */ + rx_pos = 0; + } + } +} \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/src/cdc_handler.h b/firmware/canfd_cdc_composite/src/cdc_handler.h new file mode 100644 index 0000000..f038993 --- /dev/null +++ b/firmware/canfd_cdc_composite/src/cdc_handler.h @@ -0,0 +1,20 @@ +/* + * CDC Handler Header + */ + +#ifndef CDC_HANDLER_H +#define CDC_HANDLER_H + +/** + * Initialize CDC handler + * @return 0 on success, negative error code on failure + */ +int cdc_handler_init(void); + +/** + * Process incoming CDC commands + * Should be called regularly from main loop + */ +void cdc_handler_process(void); + +#endif /* CDC_HANDLER_H */ \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/src/gs_usb_can.c b/firmware/canfd_cdc_composite/src/gs_usb_can.c new file mode 100644 index 0000000..b3e023d --- /dev/null +++ b/firmware/canfd_cdc_composite/src/gs_usb_can.c @@ -0,0 +1,62 @@ +/* + * gs_usb CAN Interface + * Implements gs_usb protocol for CAN FD communication + */ + +#include +#include +#include +#include + +#include "gs_usb_can.h" + +LOG_MODULE_REGISTER(gs_usb_can, LOG_LEVEL_DBG); + +/* CAN device */ +static const struct device *can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)); + +int gs_usb_can_init(void) +{ + int ret; + + if (!device_is_ready(can_dev)) { + LOG_ERR("CAN device not ready"); + return -ENODEV; + } + + /* Configure CAN timing for 500kbps (adjust as needed) */ + struct can_timing timing = { + .sjw = 1, + .prop_seg = 6, + .phase_seg1 = 7, + .phase_seg2 = 2, + .prescaler = 6 + }; + + ret = can_set_timing(can_dev, &timing); + if (ret < 0) { + LOG_ERR("Failed to set CAN timing: %d", ret); + return ret; + } + + /* Start CAN controller */ + ret = can_start(can_dev); + if (ret < 0) { + LOG_ERR("Failed to start CAN: %d", ret); + return ret; + } + + LOG_INF("gs_usb CAN interface initialized"); + return 0; +} + +int gs_usb_can_send_frame(const struct can_frame *frame) +{ + return can_send(can_dev, frame, K_FOREVER, NULL, NULL); +} + +/* TODO: Implement full gs_usb protocol */ +/* This would require implementing the USB bulk endpoints and + gs_usb command/response protocol as defined in: + https://github.com/candle-usb/candleLight_fw +*/ \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/src/gs_usb_can.h b/firmware/canfd_cdc_composite/src/gs_usb_can.h new file mode 100644 index 0000000..a02136d --- /dev/null +++ b/firmware/canfd_cdc_composite/src/gs_usb_can.h @@ -0,0 +1,23 @@ +/* + * gs_usb CAN Interface Header + */ + +#ifndef GS_USB_CAN_H +#define GS_USB_CAN_H + +#include + +/** + * Initialize gs_usb CAN interface + * @return 0 on success, negative error code on failure + */ +int gs_usb_can_init(void); + +/** + * Send a CAN frame + * @param frame CAN frame to send + * @return 0 on success, negative error code on failure + */ +int gs_usb_can_send_frame(const struct can_frame *frame); + +#endif /* GS_USB_CAN_H */ \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/src/main.c b/firmware/canfd_cdc_composite/src/main.c new file mode 100644 index 0000000..5f2329b --- /dev/null +++ b/firmware/canfd_cdc_composite/src/main.c @@ -0,0 +1,82 @@ +/* + * EWS CAN FD CDC Composite Firmware + * Main application entry point + */ + +#include +#include +#include +#include +#include + +#include "cdc_handler.h" +#include "pfet_control.h" +#include "gs_usb_can.h" + +LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); + +/* LED definitions - adjust to actual EWS board pins */ +#define LED_STATUS_NODE DT_ALIAS(led0) +static const struct gpio_dt_spec led_status = GPIO_DT_SPEC_GET(LED_STATUS_NODE, gpios); + +int main(void) +{ + int ret; + + LOG_INF("EWS CAN FD CDC Composite Firmware starting..."); + + /* Initialize status LED */ + if (!gpio_is_ready_dt(&led_status)) { + LOG_ERR("Status LED device not ready"); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&led_status, GPIO_OUTPUT_ACTIVE); + if (ret < 0) { + LOG_ERR("Error configuring status LED: %d", ret); + return ret; + } + + /* Initialize PFET control */ + ret = pfet_control_init(); + if (ret < 0) { + LOG_ERR("Failed to initialize PFET control: %d", ret); + return ret; + } + + /* Initialize USB composite device */ + ret = usb_enable(NULL); + if (ret != 0) { + LOG_ERR("Failed to enable USB: %d", ret); + return ret; + } + + /* Initialize CDC handler */ + ret = cdc_handler_init(); + if (ret < 0) { + LOG_ERR("Failed to initialize CDC handler: %d", ret); + return ret; + } + + /* Initialize gs_usb CAN interface */ + ret = gs_usb_can_init(); + if (ret < 0) { + LOG_ERR("Failed to initialize gs_usb CAN: %d", ret); + return ret; + } + + LOG_INF("EWS firmware initialized successfully"); + + /* Main loop */ + while (1) { + /* Toggle status LED to show activity */ + gpio_pin_toggle_dt(&led_status); + + /* Handle CDC commands */ + cdc_handler_process(); + + k_msleep(500); + } + + return 0; +} \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/src/pfet_control.c b/firmware/canfd_cdc_composite/src/pfet_control.c new file mode 100644 index 0000000..740cd89 --- /dev/null +++ b/firmware/canfd_cdc_composite/src/pfet_control.c @@ -0,0 +1,78 @@ +/* + * PFET Control Module + * Controls the two output PFETs on the EWS board + */ + +#include +#include +#include +#include + +#include "pfet_control.h" + +LOG_MODULE_REGISTER(pfet_control, LOG_LEVEL_DBG); + +/* PFET control pin definitions */ +static const struct gpio_dt_spec pfet1 = GPIO_DT_SPEC_GET(DT_ALIAS(pfet0), gpios); +static const struct gpio_dt_spec pfet2 = GPIO_DT_SPEC_GET(DT_ALIAS(pfet1), gpios); +static bool pfet1_state = false; +static bool pfet2_state = false; + +int pfet_control_init(void) +{ + int ret; + + if (!gpio_is_ready_dt(&pfet1) || !gpio_is_ready_dt(&pfet2)) { + LOG_ERR("PFET GPIO devices not ready"); + return -ENODEV; + } + + /* Configure PFET pins as output, initially off */ + ret = gpio_pin_configure_dt(&pfet1, GPIO_OUTPUT_INACTIVE); + if (ret < 0) { + LOG_ERR("Failed to configure PFET1 pin: %d", ret); + return ret; + } + + ret = gpio_pin_configure_dt(&pfet2, GPIO_OUTPUT_INACTIVE); + if (ret < 0) { + LOG_ERR("Failed to configure PFET2 pin: %d", ret); + return ret; + } + + LOG_INF("PFET control initialized"); + return 0; +} + +int pfet_set_state(int pfet_num, bool state) +{ + int ret; + + if (pfet_num == 1) { + ret = gpio_pin_set_dt(&pfet1, state ? 1 : 0); + if (ret == 0) { + pfet1_state = state; + LOG_INF("PFET1 %s", state ? "ON" : "OFF"); + } + } else if (pfet_num == 2) { + ret = gpio_pin_set_dt(&pfet2, state ? 1 : 0); + if (ret == 0) { + pfet2_state = state; + LOG_INF("PFET2 %s", state ? "ON" : "OFF"); + } + } else { + return -EINVAL; + } + + return ret; +} + +bool pfet_get_state(int pfet_num) +{ + if (pfet_num == 1) { + return pfet1_state; + } else if (pfet_num == 2) { + return pfet2_state; + } + return false; +} \ No newline at end of file diff --git a/firmware/canfd_cdc_composite/src/pfet_control.h b/firmware/canfd_cdc_composite/src/pfet_control.h new file mode 100644 index 0000000..6e5cc48 --- /dev/null +++ b/firmware/canfd_cdc_composite/src/pfet_control.h @@ -0,0 +1,31 @@ +/* + * PFET Control Header + */ + +#ifndef PFET_CONTROL_H +#define PFET_CONTROL_H + +#include + +/** + * Initialize PFET control + * @return 0 on success, negative error code on failure + */ +int pfet_control_init(void); + +/** + * Set PFET state + * @param pfet_num PFET number (1 or 2) + * @param state true for ON, false for OFF + * @return 0 on success, negative error code on failure + */ +int pfet_set_state(int pfet_num, bool state); + +/** + * Get current PFET state + * @param pfet_num PFET number (1 or 2) + * @return current state (true=ON, false=OFF) + */ +bool pfet_get_state(int pfet_num); + +#endif /* PFET_CONTROL_H */ \ No newline at end of file