From ba3e1161b9b06f084b850b5bb2eb7406f51e3053 Mon Sep 17 00:00:00 2001 From: Sebastien Vayrette Date: Sat, 28 Feb 2026 11:58:23 -0500 Subject: [PATCH] Balance firmware + USB CDC bug --- .pio/build/f722/.sconsign39.dblite | Bin 0 -> 255925 bytes .../gcc/startup_stm32f722xx.o | Bin 0 -> 6120 bytes .../FrameworkCMSISDevice/system_stm32f7xx.o | Bin 0 -> 1620 bytes .../FrameworkHALDriver/Src/stm32f7xx_hal.o | Bin 0 -> 6580 bytes .../Src/stm32f7xx_hal_adc.o | Bin 0 -> 7732 bytes .../Src/stm32f7xx_hal_adc_ex.o | Bin 0 -> 5736 bytes .../Src/stm32f7xx_hal_can.o | Bin 0 -> 8492 bytes .../Src/stm32f7xx_hal_cec.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_cortex.o | Bin 0 -> 4640 bytes .../Src/stm32f7xx_hal_crc.o | Bin 0 -> 2684 bytes .../Src/stm32f7xx_hal_crc_ex.o | Bin 0 -> 1372 bytes .../Src/stm32f7xx_hal_cryp.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_cryp_ex.o | Bin 0 -> 800 bytes .../Src/stm32f7xx_hal_dac.o | Bin 0 -> 5080 bytes .../Src/stm32f7xx_hal_dac_ex.o | Bin 0 -> 3172 bytes .../Src/stm32f7xx_hal_dcmi.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_dcmi_ex.o | Bin 0 -> 800 bytes .../Src/stm32f7xx_hal_dfsdm.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_dma.o | Bin 0 -> 4836 bytes .../Src/stm32f7xx_hal_dma2d.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_dma_ex.o | Bin 0 -> 4176 bytes .../Src/stm32f7xx_hal_dsi.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_eth.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_exti.o | Bin 0 -> 2692 bytes .../Src/stm32f7xx_hal_flash.o | Bin 0 -> 5024 bytes .../Src/stm32f7xx_hal_flash_ex.o | Bin 0 -> 2816 bytes .../Src/stm32f7xx_hal_gpio.o | Bin 0 -> 2812 bytes .../Src/stm32f7xx_hal_hash.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_hash_ex.o | Bin 0 -> 800 bytes .../Src/stm32f7xx_hal_hcd.o | Bin 0 -> 9232 bytes .../Src/stm32f7xx_hal_i2c.o | Bin 0 -> 29756 bytes .../Src/stm32f7xx_hal_i2c_ex.o | Bin 0 -> 1688 bytes .../Src/stm32f7xx_hal_i2s.o | Bin 0 -> 7572 bytes .../Src/stm32f7xx_hal_irda.o | Bin 0 -> 12212 bytes .../Src/stm32f7xx_hal_iwdg.o | Bin 0 -> 1236 bytes .../Src/stm32f7xx_hal_jpeg.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_lptim.o | Bin 0 -> 11204 bytes .../Src/stm32f7xx_hal_ltdc.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_ltdc_ex.o | Bin 0 -> 800 bytes .../Src/stm32f7xx_hal_mdios.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_hal_mmc.o | Bin 0 -> 13604 bytes .../Src/stm32f7xx_hal_nand.o | Bin 0 -> 9152 bytes .../Src/stm32f7xx_hal_nor.o | Bin 0 -> 7344 bytes .../Src/stm32f7xx_hal_pcd.o | Bin 0 -> 11252 bytes .../Src/stm32f7xx_hal_pcd_ex.o | Bin 0 -> 1772 bytes .../Src/stm32f7xx_hal_pwr.o | Bin 0 -> 3956 bytes .../Src/stm32f7xx_hal_pwr_ex.o | Bin 0 -> 4280 bytes .../Src/stm32f7xx_hal_qspi.o | Bin 0 -> 11908 bytes .../Src/stm32f7xx_hal_rcc.o | Bin 0 -> 6136 bytes .../Src/stm32f7xx_hal_rcc_ex.o | Bin 0 -> 4328 bytes .../Src/stm32f7xx_hal_rng.o | Bin 0 -> 3420 bytes .../Src/stm32f7xx_hal_rtc.o | Bin 0 -> 7660 bytes .../Src/stm32f7xx_hal_rtc_ex.o | Bin 0 -> 10492 bytes .../Src/stm32f7xx_hal_sai.o | Bin 0 -> 12252 bytes .../Src/stm32f7xx_hal_sai_ex.o | Bin 0 -> 800 bytes .../FrameworkHALDriver/Src/stm32f7xx_hal_sd.o | Bin 0 -> 13636 bytes .../Src/stm32f7xx_hal_sdram.o | Bin 0 -> 6856 bytes .../Src/stm32f7xx_hal_smartcard.o | Bin 0 -> 11920 bytes .../Src/stm32f7xx_hal_smartcard_ex.o | Bin 0 -> 1584 bytes .../Src/stm32f7xx_hal_smbus.o | Bin 0 -> 10572 bytes .../Src/stm32f7xx_hal_spdifrx.o | Bin 0 -> 800 bytes .../Src/stm32f7xx_hal_spi.o | Bin 0 -> 20940 bytes .../Src/stm32f7xx_hal_spi_ex.o | Bin 0 -> 976 bytes .../Src/stm32f7xx_hal_sram.o | Bin 0 -> 5324 bytes .../Src/stm32f7xx_hal_tim.o | Bin 0 -> 33252 bytes .../Src/stm32f7xx_hal_tim_ex.o | Bin 0 -> 13276 bytes .../Src/stm32f7xx_hal_uart.o | Bin 0 -> 19596 bytes .../Src/stm32f7xx_hal_uart_ex.o | Bin 0 -> 2844 bytes .../Src/stm32f7xx_hal_usart.o | Bin 0 -> 13048 bytes .../Src/stm32f7xx_hal_wwdg.o | Bin 0 -> 1648 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_adc.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_crc.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_dac.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_dma.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_ll_dma2d.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_ll_exti.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_fmc.o | Bin 0 -> 5056 bytes .../Src/stm32f7xx_ll_gpio.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_i2c.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_ll_lptim.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_pwr.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_rcc.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_rng.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_rtc.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_ll_sdmmc.o | Bin 0 -> 10976 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_spi.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_tim.o | Bin 0 -> 796 bytes .../Src/stm32f7xx_ll_usart.o | Bin 0 -> 796 bytes .../FrameworkHALDriver/Src/stm32f7xx_ll_usb.o | Bin 0 -> 12828 bytes .../Src/stm32f7xx_ll_utils.o | Bin 0 -> 3064 bytes .pio/build/f722/firmware.bin | Bin 0 -> 25708 bytes .pio/build/f722/firmware.elf | Bin 0 -> 155520 bytes .pio/build/f722/lib737/USB_CDC/usbd_cdc.o | Bin 0 -> 5860 bytes .pio/build/f722/lib737/USB_CDC/usbd_cdc_if.o | Bin 0 -> 3716 bytes .pio/build/f722/lib737/USB_CDC/usbd_conf.o | Bin 0 -> 7692 bytes .pio/build/f722/lib737/USB_CDC/usbd_core.o | Bin 0 -> 5800 bytes .pio/build/f722/lib737/USB_CDC/usbd_ctlreq.o | Bin 0 -> 4036 bytes .pio/build/f722/lib737/USB_CDC/usbd_desc.o | Bin 0 -> 3724 bytes .pio/build/f722/lib737/USB_CDC/usbd_ioreq.o | Bin 0 -> 2332 bytes .pio/build/f722/lib737/libUSB_CDC.a | Bin 0 -> 35470 bytes .pio/build/f722/libFrameworkCMSISDevice.a | Bin 0 -> 10346 bytes .pio/build/f722/src/balance.o | Bin 0 -> 2392 bytes .pio/build/f722/src/bmp280.o | Bin 0 -> 4116 bytes .pio/build/f722/src/hoverboard.o | Bin 0 -> 1580 bytes .pio/build/f722/src/icm42688.o | Bin 0 -> 4000 bytes .pio/build/f722/src/main.o | Bin 0 -> 3624 bytes .pio/build/f722/src/status.o | Bin 0 -> 1896 bytes .pio/build/project.checksum | 1 + flash.sh | 13 + include/balance.h | 46 + include/bmp280.h | 6 + include/config.h | 143 ++ include/crsf.h | 19 + include/hoverboard.h | 29 + include/icm42688.h | 10 + include/mpu6000.h | 17 + include/status.h | 7 + lib/USB_CDC/include/usbd_cdc.h | 184 +++ lib/USB_CDC/include/usbd_cdc_if.h | 14 + lib/USB_CDC/include/usbd_conf.h | 27 + lib/USB_CDC/include/usbd_core.h | 175 +++ lib/USB_CDC/include/usbd_ctlreq.h | 101 ++ lib/USB_CDC/include/usbd_def.h | 523 +++++++ lib/USB_CDC/include/usbd_desc.h | 5 + lib/USB_CDC/include/usbd_ioreq.h | 113 ++ lib/USB_CDC/src/usbd_cdc.c | 893 ++++++++++++ lib/USB_CDC/src/usbd_cdc_if.c | 135 ++ lib/USB_CDC/src/usbd_conf.c | 97 ++ lib/USB_CDC/src/usbd_core.c | 1215 +++++++++++++++++ lib/USB_CDC/src/usbd_ctlreq.c | 1058 ++++++++++++++ lib/USB_CDC/src/usbd_desc.c | 63 + lib/USB_CDC/src/usbd_ioreq.c | 224 +++ platformio.ini | 18 + src/balance.c | 113 ++ src/bmp280.c | 107 ++ src/hoverboard.c | 41 + src/icm42688.c | 175 +++ src/main.c | 141 ++ src/main.c.bak | 147 ++ src/status.c | 67 + ui/index.html | 375 +++++ 141 files changed, 6302 insertions(+) create mode 100644 .pio/build/f722/.sconsign39.dblite create mode 100644 .pio/build/f722/FrameworkCMSISDevice/gcc/startup_stm32f722xx.o create mode 100644 .pio/build/f722/FrameworkCMSISDevice/system_stm32f7xx.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_adc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_adc_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_can.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_cec.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_cortex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_crc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_crc_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_cryp.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_cryp_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dac.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dac_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dcmi.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dcmi_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dfsdm.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dma.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dma2d.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dma_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dsi.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_eth.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_exti.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_flash.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_flash_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_gpio.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_hash.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_hash_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_hcd.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_i2c.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_i2c_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_i2s.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_irda.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_iwdg.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_jpeg.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_lptim.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_ltdc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_ltdc_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_mdios.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_mmc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_nand.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_nor.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_pcd.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_pcd_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_pwr.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_pwr_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_qspi.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rcc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rcc_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rng.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rtc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rtc_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sai.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sai_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sd.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sdram.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_smartcard.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_smartcard_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_smbus.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_spdifrx.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_spi.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_spi_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sram.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_tim.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_tim_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_uart.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_uart_ex.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_usart.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_wwdg.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_adc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_crc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_dac.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_dma.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_dma2d.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_exti.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_fmc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_gpio.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_i2c.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_lptim.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_pwr.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_rcc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_rng.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_rtc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_sdmmc.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_spi.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_tim.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_usart.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_usb.o create mode 100644 .pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_utils.o create mode 100755 .pio/build/f722/firmware.bin create mode 100755 .pio/build/f722/firmware.elf create mode 100644 .pio/build/f722/lib737/USB_CDC/usbd_cdc.o create mode 100644 .pio/build/f722/lib737/USB_CDC/usbd_cdc_if.o create mode 100644 .pio/build/f722/lib737/USB_CDC/usbd_conf.o create mode 100644 .pio/build/f722/lib737/USB_CDC/usbd_core.o create mode 100644 .pio/build/f722/lib737/USB_CDC/usbd_ctlreq.o create mode 100644 .pio/build/f722/lib737/USB_CDC/usbd_desc.o create mode 100644 .pio/build/f722/lib737/USB_CDC/usbd_ioreq.o create mode 100644 .pio/build/f722/lib737/libUSB_CDC.a create mode 100644 .pio/build/f722/libFrameworkCMSISDevice.a create mode 100644 .pio/build/f722/src/balance.o create mode 100644 .pio/build/f722/src/bmp280.o create mode 100644 .pio/build/f722/src/hoverboard.o create mode 100644 .pio/build/f722/src/icm42688.o create mode 100644 .pio/build/f722/src/main.o create mode 100644 .pio/build/f722/src/status.o create mode 100644 .pio/build/project.checksum create mode 100755 flash.sh create mode 100644 include/balance.h create mode 100644 include/bmp280.h create mode 100644 include/config.h create mode 100644 include/crsf.h create mode 100644 include/hoverboard.h create mode 100644 include/icm42688.h create mode 100644 include/mpu6000.h create mode 100644 include/status.h create mode 100644 lib/USB_CDC/include/usbd_cdc.h create mode 100644 lib/USB_CDC/include/usbd_cdc_if.h create mode 100644 lib/USB_CDC/include/usbd_conf.h create mode 100644 lib/USB_CDC/include/usbd_core.h create mode 100644 lib/USB_CDC/include/usbd_ctlreq.h create mode 100644 lib/USB_CDC/include/usbd_def.h create mode 100644 lib/USB_CDC/include/usbd_desc.h create mode 100644 lib/USB_CDC/include/usbd_ioreq.h create mode 100644 lib/USB_CDC/src/usbd_cdc.c create mode 100644 lib/USB_CDC/src/usbd_cdc_if.c create mode 100644 lib/USB_CDC/src/usbd_conf.c create mode 100644 lib/USB_CDC/src/usbd_core.c create mode 100644 lib/USB_CDC/src/usbd_ctlreq.c create mode 100644 lib/USB_CDC/src/usbd_desc.c create mode 100644 lib/USB_CDC/src/usbd_ioreq.c create mode 100644 platformio.ini create mode 100644 src/balance.c create mode 100644 src/bmp280.c create mode 100644 src/hoverboard.c create mode 100644 src/icm42688.c create mode 100644 src/main.c create mode 100644 src/main.c.bak create mode 100644 src/status.c create mode 100644 ui/index.html diff --git a/.pio/build/f722/.sconsign39.dblite b/.pio/build/f722/.sconsign39.dblite new file mode 100644 index 0000000000000000000000000000000000000000..b96eb99f1bdf809697130aff467cb6d2e7b711b4 GIT binary patch literal 255925 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

#XL$3gWYxTYB8Re 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkCMSISDevice/gcc/startup_stm32f722xx.o b/.pio/build/f722/FrameworkCMSISDevice/gcc/startup_stm32f722xx.o new file mode 100644 index 0000000000000000000000000000000000000000..988a3cc883f8e971f7abf7cfa4346ee9fb444c4b GIT binary patch literal 6120 zcmeI0Yit`;7RUc_>b3-eT3VpIOCL}kHFc6UDUYR&9mj6t)U};7Kw&ybrmd;t1lxgj zwXjH3fS@b&!-`gj535}k5CRDh5)UoXekc;+At3=0h+PpRq+KCENFV_M0sk|eG54Ml z!Dqx&lmGpld*9)2ugjXBZ;U@x~Ki%(%_V}_6r=l}-we*9pd*1xv ztM7j}CDWPh+=|taxwprT=NEJzUvaqqo3}c)b_`*4+uX9<3%dT^|Lt4iDfi5vHHZP< z|IdKmo4>&fBvx`!uIG-I(RK!#(d2Zk;T>3?>&3#(MY)qAw9S9DTe}o!=Rfmm#{v`C z8&yw4eUB9_uP7F?eVW0t^)EH}EVeH)xYcB%9gDEmG?2~r2xRkW=WN|H^tFsppIfM& zZbt_;{nUx2d_EblWNHb=FB<(z*uFvWxZ<+nX~nZ-S%bv5iut=s_1~}f0mY9gev&NX zNxZ8V?+c1wQ~Y1WpDC7)Epxn1#pf$tulO3pImNpa*A(Ba_^9GX6hEi<6~*r<{#fz1 zikC5wG_~@1nc}448x+?S->>)|il0&Zvf}p?f2z2Ruc#UCa>eTvrxi~szD@BxijOLO zRPl?7-%vcK_zT7D{D?8vvrO??#l4ENif>X}SA3u1hZVo1_ z$X551Y4;rQ#F|O$b!PTdN4<&0bghn*x5u5WG@OiEove5@IQ8-*N1`^x3rI$CJo#Jj z>Ym~6)f?`_eiRSZ8{U*3fa6rk;}ecd>bSLF%79)BJLC$ zHP4;0#y0HM6o%cJ$*@}!8ut0--8fG?n@oEmW#uB77>+xoG1J306~?Sp1U730zO9%X zFrSswZg#9dO4(f8=`U<^*w}3P`W>vCs5P12Q7Q~N$?ZA6*P7PvwF^pN?SjCd;ds&syP;tyo5ii9*Tp@GU3$SP@Ge;~O12FS6GY6}L8J zM!CH-=%kA$yaQZvUzqi{HJRTNq}`g+?=aJD<;?H3({60ZUNfY0&e~$dR4&JS8!s)# zvbG3wW<@f>lv$ID!FqxtY;sZwYaZIHFc@CfJa1%Zx1uuqt%MnND@wy|1shbvSg+w} zt-`Qd@2Fw7R^;y-%ahx-`@}s;Q^Cx)M3gBy1NpeKeWWx`Pj>icI`l_tFp{yh!m#zB zoz9P#!${%mCD71kda(9Z_Q+O_iV5|8CG7WW$4DZ@XUrjo^4tnmY5gr|6_tkqITtL0 zf5we0hkv$>@IZTt*m>NR^I_!7W`D=oK#bgR4$vifZu86+;eq#R@#FJbMEQJ5l;dVZ zInIzM$B|3?`4tlp9;)Rm9XT(U@BCoC3jhv<$Vx!Y-H{7{%SBfK8$?$J^R5ZzT^r1M zQ84et!My8&c`pI-@*EH8CDF@(F;Nb>OLRT3Ta=5N6uko2C(6kxqH$nGl#6bN@<4t- zvB|;C0a~@TTZi;BC=uz`LSDz<)$@ zz?|qX@R8_t;Qyj|;1kguz~`a`;7d{dfbg|w3HVNQgn#&jG&0J%itc1xMaNiI(d$@O z(d$`PQU2htLUb2!uIP=xO3|BuHKGo%PINcxF6y%GqT{Tm=mhI2I>~y9daS4D9@bNI zFY76~kM$Jg4;cGIZ)QD3_p_d&71mR9iuDt%vVNlcf#Y7$8P-qq7S>O+#`=lYSvS!J z>mxeL`iS1j`iS1fyow%RUSjowQw?{V+Nd>kU)ZX7l^B1?Y9Qu+n~llW*jQ+c*w}dKd4RgmPF7E&yr(bx5S_5KYR)etwyOvT?)EFrh3sg)~AetzVZM(SDwu`%~0b{~d z&mKK^_29vTn0PT5ym;_n^yVMniqsn>IX$nlwt99rZ|6I zvA2k)<0V~glvPnz9#@U3))159E5P(6nR5Mi)!F-m)q~*aRj> zc!ms8$uK}7hvdpf!d`PbopbEWthM$6CkB$P(VkLgrjECx8mX++>q-ODz-E?Y)6}b_ zN2X$6;{P{Jpp5RR$CkJL1?{!06HnPX)`{IZ*57AQM|b)!-8p+d_qpsW3^`vwrb{=0 zoO*~2*7=vwL0vg%2U3^-^%7knbvx-OuVtK+E6eW#76%l0G7a-;B5bQEv~5mTO2 g6IpsEtX72Z1sB~TU=Oxm7`a<_70G)hLd$f20U)i?cK`qY literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal.o new file mode 100644 index 0000000000000000000000000000000000000000..90bc0825a3a80e0916fadaf0c66da00c9dbbc7b8 GIT binary patch literal 6580 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 UX?T(9!#%`^y9x2TbsyY+0C*N%3;+NC literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_adc_ex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_adc_ex.o new file mode 100644 index 0000000000000000000000000000000000000000..107e14b6b318bbb6d9636e5cf20e01fa1956cf39 GIT binary patch literal 5736 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_can.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_can.o new file mode 100644 index 0000000000000000000000000000000000000000..ab9d5d2a00d117e63d0d630b1552f91636e25123 GIT binary patch literal 8492 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 e7*9)KbUvqZs8dPaB~B#4q!-v0o-&c~7f literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_cec.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_cec.o new file mode 100644 index 0000000000000000000000000000000000000000..d8750d51bfd8791fa3818aa2e565ee5ce4cce3c7 GIT binary patch literal 796 zcmaJ;O-lnY5S`f8+Jm5C@e3q+aSQIcU0W8tl~TP}5m69CB)g5Y(rq+}QcwOU{ZU^1 z1v=?&v@K|0GV^9$CV7+B*2xhe1neT2nrrFi2)7j^}w&)KqJ7nFwUYL5C_9TQ%KE+Zaak8`C_{?vy@*Z zWwMf6C2M4zZ05Je1!Y3VQ+fFO%F-j3o0tGV4ra#7h;vgoKZOebN+bo{V1sc2#(+s>wDez*EBz%B59E-=amc8gnb2V|(|6l{lM(1os zOaJiqj8(Oj@vN$8o}JYW^6>Y6)c?iX&HDN1%`&{#QIu|`pRqa`-uaMb0p2j!w*bAp s*LeF@Q~p3Rhl-h*=`Wy_(5waw;R+9yO^_|yZxQi0FTp~~lF(b;H?)sdT>t<8 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_cortex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_cortex.o new file mode 100644 index 0000000000000000000000000000000000000000..0d7607e42ba891210d3389738281feae7774d8c5 GIT binary patch literal 4640 zcma){iCso4?G`938bq`^yF0jxZFiYn zu;2rrZ-xXCeb5Kvo6#qYk;FuBB@!Rh7r_UT8dDz(v5Cnxty&ue&%HBuX7;iLZ@P2u zIp@3Q{+x5~Oi%9|dqxlhU`2okI1)giiCVk^w2Htc*a*H+@LbQr(p<88X)fIz5- zIsR?dvox0qs^2Av2Fm~5L_3Zl!HQRS{F8+&xBEzR)|#4qUCE z5MRx6I41Jt#fkIMXyR!1(wY853PPUvA+jUX*9El8qeB$|iiWo_L@3> zRy~W)n0f`Df*M1;&@JFIhW!e|#J?wgBm32&hpvUJ10scsU3LU6EQ2Uid;<8dEcm3R zjnWp3WLWOO_-@5WZi6l_#!p!h{`9U03lCr%m3aYLlkG_}Zo-&y_~)Bu%=~s-hG<+o zG%hS2;->o9Lw&0T; zC@OOqW+NbLTvx;M|8_Y&tOl= z(5BN_#n4aWin;u>(zkVMU+=(+5bMJer|DWM2SNm!UNvu&^qHRBgCIBgcKba6sa0qb z){E`J2BAaPB!%3^mY!C(LV|_cRB1iLs#6Xig2!z}S>$91+N(4YbfT=-I>~O4h6rAc z_fr0_O?mB>$;%usQ{EX<=6D~+`zRl_DWBak{nv4P9p&${sXDu5@_vr@bN>AtU(fON z-2Ce~zJcQ#xcM}2d?Uv{! zd1n@D-8jytnd6%&f54`kl@OH(EgauMc_&^ic2AQJaD0IBicJOVmdOV>KFIkGa(pYt zw{relIlhhK+bHi)Z5+Rj@)m0M!~2%3P`MsHwq%oUfG;hXtT_OUaJ@=yg5NB8jM~@0 zElVbu5WxKE#0!kvVF#()484}DP`L$$E!i9|054V9gYasVy%pZHWOAnjpbb8-WODO` zU>$s6$>b&o0Pb(GG}YgCWN>C?BCAbKr0E45O+&Z@;SB7GjZN%%ZbY3(=%sNZmp5{y zlfy>-cp*3aa!sS7+&QhKCiRj1`yAENx#AtV#K~ewpW3e%^%4aW&nFIysPPFkKYb); zjH3E6wmz4UI=6R3pU&V$RIQP)HPkA; z8I4*7sl+onxUrnK}cRUL2+yR_-dq;6nbNv!J=_=pxy zPL;G2)+NKNv#f=$*%CxET1kUws#t_5QAF<=@6{2$w-bA=k1GQ>i#rb-lf7m$8ytf> zC#tnpX4FzzL9aGdXGyiKDpwrSsu{C7!tW3{PfnWD=(nno&!jv1TKVJ{>|Nxtss_Pw zD~jK8cbZ*U7ER};ru1pdA^g^hYNe8qOC2xiMa;VYUC6f;UPpKuNT{-bfCY}W|Kb2oXAf{4owASdKZO$CRhv+35%#* szDI5x|AiuFDTY5XE{Qjp8=CBLA1bbq&Q@Vf^7ZWImT?`&T>~)gKQvqLnE(I) literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_crc.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_crc.o new file mode 100644 index 0000000000000000000000000000000000000000..e58c1b75048061749b963fc85ab35391cccba329 GIT binary patch literal 2684 zcma)8T}&fY6h8CQ77#bkvRZM)k;2;LXDEeTP!k0T1strS7y$KIgSHn9Qfe~0kpad#xZI*KRf^@p;msk>AtW-{S5l>y*>Jg`RTN9o-w}oEx)Oqqf1JT=6zORYY(v?zZm-qFr3Yu4| zZC);6tZizS>+V~9zw~Q0R|f4;6Zk%ya&G_V;(s2l_XdPj&~lsH-W%d@-52FX5^qiK zI;X|xAJyC}KwDW1H*IiI+h%A*sO|Hf4ZgVl&%J%#7ccsjZ*TZC&vTcRHLbhm<=3LI zWuJCy917{HoRgkV`^U`EKEzP83Y9gT~qzn0MTrCu``GPby7z_-L4PF}^Oe>4o{26IX4$8w4 z1p`k6MkRkl7} zC6)xvk5fk|o7dIS;QSak?|02N^KP+&JIOsLc)5qTPOeMrwjNL8R9XWf{JC!g%@3jB zGy@30TWQ3C4U2ffttNsOA=OyK!GmZe@o9%m?|@!YFB^J?P4Benoi^TO<6SU3TY<#PYZ?*9!Z2Sou-)7_6Y<#;7yWt#0Xg}#qbb}MZCf3or z!37KGnNhYBjw5|DylUbAdN;1`Z4*xzxD`G&@tlEAz)cg=n{xwZEa>Tx;MK8GDWWN< zNIV~x0e_G-893@%U1DDW&M@VdjvMiZ@1PReeDx33T9ET228($#(%r&*<@p z&>pwot2W|@pEfbbh2^xa#L(;c1Fx|eUOOG+grX}T#|j0IDIhoO%CQjc%|Xn*Ju-HJ zM#fluW9VpCj?2ycIZjx1>Nt6{XN{E(cTSFH(`hw>3&jQ{E4rRf#+G!ofcx`*?O_zs zd1N>D;J5MUY1UyLGj*)P*mabH>~S1TIQ~mFfEs&U>PgI4-Dfah)qRARdJ!|GqkCr6 zZ6RhHY1uq&(^U}DU1i2PViE(?eI`ueOKg2~e?2&;YmtuDxr)PDcNzh!h1B8v1Dh_4 zI=b`B*fZ~8z*_e^tV?yME_FLrw~TXZ-RlS@Fvg7KTgQMkU&XQx>W(bmEu35PeU5;7 z4l|bT2Mk#A?O5_rH)Z*Dac<3b4*_w^SU&o@Mmn|^JQ6ERgq}DWE%iAY&4cFVrNaWb`U!(lA AX8-^I literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_crc_ex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_crc_ex.o new file mode 100644 index 0000000000000000000000000000000000000000..2e11e330106da9fd62d47ab0ab25deb56eea0ec4 GIT binary patch literal 1372 zcma)5%}*0S6o1?82MCQ7F&0d8uqGC2*Rm~XF*g9%rOCVpJ-P1_0E6{0VB`{wJ$Dp_Q9g*uMS9Fk9~naOYM4{SD0 z@`|cV5)NjrWO5|QXq_4k9Vhn+OY@g$cZqa9U1mn3ViHDIYfjB>5Or!w&E)PwLB$>z z)F{_LO5!l2+03P_^n4z|(a3y%U??~&osv$=acM*vmCgpwdmGvAAN2G#2z&coxE`vjK0fT@!#+OZ%lqIABK)^z(TA`;zZX2``xwG{ zw|a71&vC7+x}0ydbknHo6;{z{OR2yG7iJ4{y0)avwDd*0zTU8{8VYVxFLAxG(scE! zhHL0cbd@rPdS)#&-M?5+oOR1J${1bNiKZCgS-GH8aWPQJjspq@lp}ZHrw`eSUvk)v zl!|Rxw1JiJnkk0svRb+6QV09=zb1MvPN(x04`z#7GKLU83vo;QI?i#sh~9_(FWn{7 z@HyVP{M?0!x;GH;>NYU<-b^9O$x6vd@d-6x=kMim- z&`EcrZ9xN*nK$z?$(y{^PfrLTU>5-gei6WX3JT>R!GR*o0yJv1W9l@{uIQx@T}AJO zq*a;FdJ^$gi?`^x6fsvyNJT?8@DD@xsq7}~LC8HCdVzOHP0~N|%hZv)%bDVP^rm{z zJm6UiH*_P(dU2ad{?bt$(W61768Pm?s0R2J##z(>;$T>)38{JCZH6#CH`6RmE#{ZV zGFi>7k#({`w(>ipf-<3_sXTmsW$B^IjZFX`2UDYE#JLHapTGqGrIS){ANKoqZPvYu z<>1ka0X#KGG>gz{nfkVkP=W@p#WVviQVP6SBnj_f4(H-Atz{>A)?AHU^)J}Os?j-} zvC=>MJz`aDXFRKFl4obNi#+`OAN7Cn_OpIIdb14gbr_|a>1V8hhIc-uS%5bTN*18E t_Zn~CYRVsI=Fm)LX8QAJMKr4cL%7C+D<;U6?YDqlX*X)Qa^v*zm8Y5$W= zOq*V3Ggw7M_3gjhHL literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dac.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dac.o new file mode 100644 index 0000000000000000000000000000000000000000..634c7fdd4a9ea3c72e088b8c868e64dedf04afcf GIT binary patch literal 5080 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 MzQ=EzM2bM|t%Z z=%l;RTF}5`=FPlJ@+L2><3mCS*hRpB9|Z80gGy~caG(m407uQ{0dFYtD$N&5SKjXIKdIa7R#UNz3z zJG^M&hHfNTFYZvupHh{I9u4aCz^`3HBfz&X&Y~2EgJGp9q~?9M9m4q3M7ugRTb?8H zWU;hFmdOfPD{l-7DufQF%JA`7qzA6_YXSfz7#l7lE{)*w2(ADqo$Up;VZVRVVcnY~ z&QdQ1@YHjrS%hB8+;?n*5;S-T(+s>wDez*EWxR(uoQub_mTB~;x%ze0zhD)sM(23J z%Kz}^h*h;-@T{s)o}JYu^6>Y+)&IrYF8cZC%`&`~L6mQ%pRqa`-g%#A0bViKvjDxl t*LeF@Q+`J?hb9U$)1OAGqFD_X!X+MDFhQ|wzZt~CydD->mW1B&z5rgtR?z?e literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dcmi_ex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dcmi_ex.o new file mode 100644 index 0000000000000000000000000000000000000000..0e183be37d4bb1353ddfec13ebf19927314e8121 GIT binary patch literal 800 zcmaJ<-%Gj!!S?g%CYO zZ-t}{nbB4j@g(61J(D8lN(rfG=m!2?=swikjNJ*jO+zp6_NWQ^2Y!t@lJ_`Me4Ac3 z&fB}ZDB*@~Bw0W1QpulEm5M$M>h-{{-9RJ2yD-k86o`Xvr75K51GgQ*Ez{^xbM@=A|H&Gr zO|O%MEPuzJJ+`xrLT5W0*V%b(p$`9m?+N^++bQb#h-Mkx%h1a|rk=4n8lHKdM*&{Z y*|!AIo@>zF)ui9i%%-Wr%nQt-Rncq@=)x6lTrp0uY`r<;qq+x7w5$lx>b?Mg=U5j2 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dfsdm.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dfsdm.o new file mode 100644 index 0000000000000000000000000000000000000000..5b9dd48c1adb3b2406b6206d366ed239d573e3db GIT binary patch literal 796 zcmaJ;O-lnY5S`do?Lkmc`~rzy+=9EVYs;dyQmPj#A_{^?$#zp(={A}~sV9Gw{wS~h z0-ba>_5(C9nRzoWlf21W{rr>=0(KE_V1xiZQcx%l2@Vut9^kB2JE6|m#SOg{qNiwE zNLrN%ttSzWV;<8>DOy}9Ar%eXz&{M#r?Q){2O&!|^aAgYnxud1m#HIpk2A$f^sai< zIN(_eH*_P(`mGL?{H3e9qECZLCGgAlPz~@cjI*c<#KEvo6H@bm+X!KHVXje}SrnT%w&zh@=yZ!@PSTs6k zGgA78qZ3xuPR6sUrg?T&d&tAz|5g7NZ$Injqc_X&-iA@SnSRD9Xn5yingw{r;K%~> u_Fm)dTTS^B%^aG`%uIg~t%zndUXwAw@_qmY-B&~a literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dma.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dma.o new file mode 100644 index 0000000000000000000000000000000000000000..9e1cde0a3cc37b932df344a1c1d142427595eef5 GIT binary patch literal 4836 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dma2d.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dma2d.o new file mode 100644 index 0000000000000000000000000000000000000000..c1848234e76ccfacf3204a4f25af07941780025e GIT binary patch literal 796 zcmaJ;O-lnY5S{eH+Jm5?)DMv8#TDFjyS6NPE2Vm|BBCIOlx#QBO1IG@NCPcP|(5CcVT zg`^Fc&{h)hIOZ`ulcLL&5>nC74g6~8KGfWV-3hrvLoe{E)Fk}_zeXL&2b?LsL$4d> z?LD5ga6>neY}oBl$)EbFFNQRz*8{(H1C0RR!Z?fiKpYHlarrT!3w#3u!RG@^`ugtczkV1;__?3u~zhCY5I zxp4R1@0>H|JNMjkXYQWt*#9uYFvMsK@sN2$$l(3Drldt5JY*%QApUd1vg+lgyK`zf zA~C%G!suK}h-qS`ZTy_ZxKu!+bFCn`K5cV_yeiCz%*lIms*4j?kv$y|%BEitE()w1 z$ucY}5dK%~W#N)=T^l_2s;v6veGj5uk= zZow&Xr{lt&=`+HNaQV^k@Y&gsc=*bAc-PcdU1Q(G8W!3Wt&xFV_`4g5g4~2 zZa}>g@fOtABHoDlb%?7byR#(Log?;7_KkBj=vh>&f zm-Ycf5Q12C!qZPd6an<+LvM}9=0WU2J&$-3>T3|MNBtVa^U;hzG_ON6-$6A0UF99u z^*Hos>{;!UC60k5jpJxRR*K^ohy6GVu`FF4x-btvLLS(eV*WkA-Ii;Z$k#+$&M}d% ziniQlkkPuR$ILn~)7Cnm`fAj#Mg3~aPN+~9s=XdF@V#2@U}iuPn}xkl?boy|I{S8$ zz0qWM-y{3&qN8K_}2@Tz_a6mLV%2Vpc9gR&rOZ zS$S7y_n296npvs6$E@6aPlhoo3)x@N*&9uEx5>^g0y|OQJ>WQkYyVc|95-R@M4=Ty z9M`nxmVvz!*S?UwO=l09YY&)f_b%Gn8*aPy{ApNPcH=ZGTsxW6&jURNa3(J4nedyL z*k)#;ei1UELKUcvk1-RMRmQ2G0KE!SsDiW0!2SkS!Oy^6Lf=XzJN-7a<(78s{kZmD zfW5SUJ+TbzQC#~pu#*Dzy>MS>%LOOS&dO;z3rw)HYMjozARB?%uBp7FWh!suN8ALM z>KhT)quzlS-pDzXh2GrM^@HGqo6kDdDa89CS(S~8Y=6c1Q~focQF%GYoigF+-N-52 zy7A(dA?NS(i_tuzZPMebH{+`_MIuTJG%ye{ie=7r)|+0x0#If zCS%>AF_v`=TNvSvdBDcsx^eM~`F8><+s|Ktd+K0kwRlq_osr0cyr=WAC;5Y^RDYW9 zO(}f4lH@y*F)5Ld68r%r6_?WKl#=Fy-hh8c(0i=Kn-q_xl&yTw7x3-isnEaM-@5SMvHdcH5+mm1&$t*rrn%VE+UAcTmL80#a92c{*F zl#-E#ywM;jT~!ucVY72p%vxqWyMd`@HZrxG!+NEM2S~vkpCfc-f`lgVS?G4ck==;j0S-H??`g#J?~)z-lXNE89Ow-W4fV)k ze@`MQ_DDm%IB{i&D?uJ<-`}%0+TJnL6FuIa=?fq4?Uj@#GNO{XgQ{oWL5nsbivvfb zsFX}8CkXMSPb4#9491L-A7x_(g^?k?gqRVDFP2Ud9~JoS5W(FHXdJ~h1=0B8sbo?b z09L4HpP0!geX-*iDGjN)=SKIB=G)kr{QuAS$Bl}tLp!5%itUWTZveY;=y$VgLVs3X zy5~kSc%vY&#y1L>)`HQD6L1U!Ry$7xA^E@5c}v6Jn`q}p2Rp&;B+ltTebD|kbXdb6 z40<~UcFhKWk=oEkN5eP8e}dg02x*8_&}n>?(CLveaspFwXcZv?bb`(Bw;Hh3?rX67 K$S{J@u=^h+QtNgA literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dsi.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_dsi.o new file mode 100644 index 0000000000000000000000000000000000000000..e8c0cc4c0a719ecfce95a1136465415235b5e490 GIT binary patch literal 796 zcmaJ;O-lnY5S`do?Lknn_yrQZxPrT`+m=OdrBp9gL=*%O$#x@M={A}~si*!Z{ZU^1 z1v=?&v=%flnRzoWlf22Wb#g=q0lNq|@Ph!}GEl0G2o98C7T~zqJfzO?=_S1oqNnJc zkhCFF+DaoH$2_KIQgpadLMj@%fxjQRk2N=C_d@Q_&whzk?AIDtz5N~hJ}E*uPQyR3H` ztHkR7cY+)&IrY&HMT2%`&{8Xd+vQz)E=7kcC8VOE8~EkWeXP1MyBBhghF;*6sY&{Wew8|s4>(hNkKWWT zS_eFB;f8J`*|5{2l0WxVUkqtbs|9}b7U}`Mg>e@3fjAiE8$xP6a$6zHEfiYC%yMpp zl*np!jjWRmvX$GJ7L*E|PUYa^Gfhui_SXaevXGfBBhJp?+zieGC>>XVyKppW_t>D# zbwDeyWXj`ifj s*LeF@Q+`J?hYG2g=`W%c(X0jx;TjK?Opq?yZwc`l>(P7=$6=ZSxPGE!?XizyS4^ej7DQRv%6Dfwfn=_ z(bNY6QFxG`Ap#E|CO*g?fIy-T*cwfIkeFgLAyE^J5+c4#K@zet(Q{{Krn?u2o@Dl( zbH1NF_s-dS?;hASzMBvNz7dGQas+Up$yGvw?hu1c=z#J?h>a~me`>MSBz=;0f=JE= zpjEgP`{6y4jdwYu?X07&MV;bg5*%CZ4)dV zRNe=;eI{{2Ic#peA%`xTa#gyyMSV*fH6!VEtk{7Sdel>DyCXq|7EbRq>0(3$Hl>v> zZM;G0lvce?*q!Sz4^I(=uklG-*tS{oI9dXXCdicvE$Xz9iTWLC7iXSDfn? zZ?2BdMzrSL(Icfg98Qq<&xFUhT_TiR>qTw9f?5}vy53ouNeL8 z#o@_`#|*E;z|cU((u-M>S;p)6O1@NN$?e;diNTj(IEnjHH}p&%NDSSOTC!|oZeU^v z!Yi95TBJ^S4S9e(NV`c7d5El+qxGBI-P_Qx?`2r}$4k2dZBPLyNcA$tRETBhYRJgY zgYic}P7XZoPzVWp$mI_OR4DLjd|2SaE}sjiaNyPWCV_7f^kzYC7W5WDZ*k}A4XBpD z;|_&Zfp2yB?tp3yyc!=7_=wB52UH~RYWxa;Um@@-1b(FuuL8byz70OcrxRq@=EX1oTm=`lwZ*lAL`h1>F?8m1#@_3CKN8sCr7^_z7!nWkh z(A?a#sn1Rub9O$Sg-teW%E9RH`1G#l_l-?Y8May~&gA!x=ZnU2I(6@~is#6>7e8t2 z&sS{2QuW!{jGld^q0*>c%+1ynADi4;OIZ!r9;2Ac7xypc+}ZBRri`Lt>9#TT+!#Q- z@e?bG z_!Ykmg3{0;L91_6JX2+g3jFnr&2Y%lvO!izMG~{!LK(4`2See}irG zIR6F{IbMU?Blz%J;lH>?krC(RXUsR*b8tH}a91(rXU{jEo54hVy&MMoO#0??hcQvl zUB-Z)Rp0#gJ&TEY?&^KG&js#xeI0^j_4tFTyo zy}|o%{T`R_3XCFmz%Pa)ufd-re&BCb_NA|p<9D5JoZ-etlmh!3gJbycJDB0a*T;Q+ g)BAe>T{wz=O}}x+GrwL3#`RnYH{ysdqUO8*0#(?%U;qFB literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_flash.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_flash.o new file mode 100644 index 0000000000000000000000000000000000000000..0555039f88b22b17993562ce4c7da727c73895b7 GIT binary patch literal 5024 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_hash.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_hash.o new file mode 100644 index 0000000000000000000000000000000000000000..041cc341935ff28797192c2e4fa5f5c3ceac0f84 GIT binary patch literal 796 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_i2c_ex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_i2c_ex.o new file mode 100644 index 0000000000000000000000000000000000000000..a4f54989057d0e09e92a77374747acc6dc438e59 GIT binary patch literal 1688 zcma)6%}*0i5TDoW2SiCK(byuA2Q;xLT}y!!_0kUtic}lLgBa6p+l8*#c5!zh^+e-e zK%(*D(SLxDa4{MWUOo76@eeRD;e<&KJ(%dcWgoOl{g`Aj^PBm-d9&}$+s(}493cd_ z5D3E&0@!j}8PAku!q5jNVXKv-pLgg*|L*xuTdhQtTnc^+jW$}zs8AWKg!YMhuzOVPgyamQlh;QK+nym+skUI*+?yyAE@31q1i~2XXNGGN+6vpxVG2k;T_Dl5->v& zf98(v0oZJt3-jspRT`eZb&oD-nrhG$O{Yn{N;B1>TrSIHn$xwCY#5qu(0C*korp&s zPerQIBTXNpaWN)NP!^0{iB8e5E~~O+$YbV_Y`?675ojx2xxuJ$xy!GYZn=!hH)2@eV2apXNbWmy5dj=UGnVJ39Q@*aB35y0o* z`y70qgWu!8y)c9kb}Wmi{osacHeRr>2kzT=+`?Yi=)hRtFsqZXm3Y0LuSjZMiIwtl zT`WP!gisl-Cl~WKV(CmhpVn$C%4)JEsoLtCqMEXPEIF&JDyF0!%Vug)QI+Q;!^~=B zIj620ZA)hr<5(6%<4M(&ifB#!z*e}217d<$mP`r6qG5o@0^(o$>`v+I*2(G8vy;-T zbFrjVt8xuH#5W*Hrl~8%byGI*(En4|ys-P^lXCEXI$F#pc-ZFg33l@MQ@MaVHZ}j^ zvH5WB%VvrT-}g2K+IbDcY}UAN9{c2W-Uq~N4=(&=y}&>_uZ6f9@3qZ~+66+mXw&wY zVKtb(N5yYlLu1J+3{G-@mT{Oc%X?+`D+Y3?C(u8I%KG!8_M-B$Ll?pbo-@Z5UXQJ5 N=e7-fuP;4|o6o literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_i2s.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_i2s.o new file mode 100644 index 0000000000000000000000000000000000000000..cafb4aac39d2c0b3dba99c4e879a1f0958597a7b GIT binary patch literal 7572 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_lptim.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_lptim.o new file mode 100644 index 0000000000000000000000000000000000000000..3c2dbcc308194e0c1876d0101227552abd7cac05 GIT binary patch literal 11204 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 YJP?C{UZGcp_cCu7^LPPc5k>I+3nhMVasU7T literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_ltdc.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_ltdc.o new file mode 100644 index 0000000000000000000000000000000000000000..a38c178c0baf2266952a1885e8d05c662d77c0de GIT binary patch literal 796 zcmaJ;O-lnY5S`f8+Jm6tw;<7rE4b^rZCUhIO7&tzL_rXd>~5r$Zlg(*dh$o$8ZTi>9iW$hJ(RPhxKlH zI*Gj)z*EnuW)XTVGvBchO3>gXOf&EzrNE0tn({v8a4sIxT6UvH&DF1~{sn7TH99AA zR`!QKN35!ioM%;y^X#m)kcYqjt^P0GPTtQ)ZO;!pC` zU!a$@(K*n-^}Fxx%O!W|uz7k+2m!kYIPk*&-ZE0Ejsy;rVHV(|(Kw>c$=MaX6r!i- zoshIHQ`$@;o+Lb>=TgL6DIpaN-N4@u-N&k%vU?$SXy^srJ~cuA(63TQ@*Zc3@6en2 zMQe}eCEU=BBwDez*Ero4|a9F51cmfh${bM@=A|H(S0 zO|R3rEPKbFJ+`yWTxUC*)Y*A$qYnRo?+N^++s*6wh-MkxaO7nlQ_olp4bObYq5!Yx x99V*A&oyZ8YSQm$X46b=<^|@_%4oI+bm1B|R*aJ`TWwiYxnnRzoWlf21m^W>Ni0(KE_V1xkPGf=7y2@aHD7NFH=98srrdPy&Y=qY+9 zB(2MoHq(g5F^}n)6dkUVkcx(G;8#NTvFfJmUdUYH)rmaTX;&91KehAvGVk?GUEtX4>Vc#o`iK zCM$(ivPRa)W^sF5P%d;lRfNy4JUw)UUlRZ*z|?pdabW@%CvXWs>GUAD3kQSSF6-T< zaUzu00r1pIs#%0y%glFegc>w>G1CmZNGb3-B29T8b2u1}X)TlJNptn`*I|@xrk}AI8s7PkWdYtWIIsY{ tz1MjAR#W~!Glyn!Gt-|(E2CKr7{V1ETrokuY`+D><2-?drX``byl)<$S5g1~ literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_mmc.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_mmc.o new file mode 100644 index 0000000000000000000000000000000000000000..84ad917c88184e39b7e9f415c641a04fef33729d GIT binary patch literal 13604 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 Hn7QvS25J4Z literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_pwr.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_pwr.o new file mode 100644 index 0000000000000000000000000000000000000000..58e595eb94615fa03dfe7d701d12059ee0dd62c4 GIT binary patch literal 3956 zcma);&u<$=6vy9Y*LHr_*ePjD1>2+&DQb-Crlduch_f+i)1)zJ+Ny<;UE5pMjqNpS z13{|PAdWq>QhR`k1AhPq4pf2z$_WW>M5UL&p$DW&6-b6gzyVR-%bM`!ZVNne4=KL%(H>JW^!s(aq>hJ^Hmf|9fZy_}=TYb2eTYX)1EuSbw~5WBsvxLpmUB zq}FRQlj|z};aji6ukfG`*I}e7%X_rmQ&BxpnrbQ?i9k#UV-lrdYGtv1Jj7UBGZG&n z>)7nTc`G=gMn@#0Fh8~+dN(vzDE%la_n-Xv&yxjQhk}8#UiaP`qcGk;68pov;JkUQ zk#*qwEe$i8_Od!UbNZ~hWZUJsdf9f=j8jpwmAqLjnng9|*afp*x1G8=F_umpnizX~ ze5_(zv7H0zL^7Q`q!MH5SZZ7ybzT#*7fr8=v5B#~V^j;4>X`4A>Lt6X zrjHy+r^YWqCXIW|FpYc(q)}{!G}~#It7G#M5blf2cXh;+0cp21DDRPmq=fXWG928n zbe{sZhZXqkiD#yj%y|K1=m@$|%Ys&5H)l~`59$HmruZ$=kRc@SAiEZ~0WjZ@K+<3Vf%~f2Y8A34E8pcL{vAz;{!AuTORREz*#oN8o#e{@p`| z1=O80fs4=54yP|qtgbFw zMtQmRo|7!V{s!zX!imh>a_;=%^0axfT59+*TQ%}!b86*mEmI(et?!sF)pzh{cJ*@U zt=ze3pLIJ4TD<6>$%W1vE9Ti+u2l7dJ#@PxTWy%mnYnB>H*XhBpLfkm3vI2L)6-KI zI2@;-8Rc@`D6IHhpl$i&;%g_2YO!oOzS*7OnX+lt7OL6Rz$$rjZ0GWVvga16IkOsA zXLtS1_zrS9bx-5JWc~e0!^mUZaNOErExdplkSrPv1Cn`6Mv@qkLh5*fL0cH@3tiKZXwm}oGjsOeXX?f?qKqh_=&L18{7uG)5~jM zGw}X4TY?9?4*dM{UKZYR7wk&KtYZ4{114!S8cr$yPQ$F@hWUSmorUZccfX}uvFz(( zADZyk!1LEFB1e3rJdY2#vHy!ZhzyAdj@!D^08eGNWCU&wb?}B_oGx&0?7*!FTp2Yv z*I8lxeT0VK{Ky&IZrslW?w1|7?*#5|)G9u#uyG%vAvo?{6z#?hqdmwSL_zKoR#<-{ z0=I;El0jHA?iGQ%jaqHPy(w^Cpk{l7;H-UB;J!pn?kiT^LVcJCk0Fw<=<>_AC_cr-7(&Z2e8{?xd62bZzcp-vg`d}-kYKN{=2NJHTrUQu I0s}DaUv4!`RsaA1 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_pwr_ex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_pwr_ex.o new file mode 100644 index 0000000000000000000000000000000000000000..f19d8acae97d79468b9cf789965bf1f7f3976477 GIT binary patch literal 4280 zcma);O>7fK6vy9s9p}pq#v~;lh;A`bO-qbPLX)Caa$@3CjRR2#EfT7dwY^{$$7^;M zlA=oF&|?o&NL5REs8nunh(x&+g;u?_2arH&Dh`oa5dmuJN(tOb-`kya*29`G(t74U z^PBhP&AeUDh2d0E5CpJ`01?VItv}Cq4NAhXSS;#mgkQOmxP5d#nv0H#P+-Bzejz* z`ur)1ctLE!hoghPUWyyZ@8sWT7KE>nq%Wi#em=DFX;m8`Ey zOMkE0Yk|LD#WUKTgSB`ZPjZR&LcbBgsKSK=?s+&HHuoMb!NPYrvFsNc-hB5q?m&57 zw^rs$hI3yFJMZp5E4ZR~B+)+IMQcs4^Qw>`vYNXr1n<#K1;oX8KW$o5{mnZTY zuF$hsV&~+EJXn6Ry0Nbhmj785BwT&v++ZY;I4DI%4j+>yRkff?Csj=v)MljNnY5D4 zDp_ezz-f&w&FyvA&OBum|5kS&`Fu5F*&DOQ@Qm%yp0TgD+4& z*60a&TZJ}ZyVx#t2%W-C?=I(yY`(ux^=^CN-)F4bti-BO01-USVbmh0z0h9O>k6cHLZzLDb_9W=$)#PLlW-^B6F9N*0G z%^dINct6K)L_!lq2ylFW;{%-i7LIQ*`CNr+skEpeLXhKwCZDZP!Ai^GLmVG6`Ohj; zsM50dR*rAw*5AtUZ5-cb@>eQUTcu^$-_GfF*oi%q<^%YIFyG#C5ERW2J{#jcIKecH zg)o24SLsH$T&0`frz+hHkE^sFLTH@qTlNBQkm(Zkg`fo{nJ$<*2rAPTO&x+Sn6~D( z!d0fPnd2D0Zp`%doa~>Qo65#PHnIa8XVdl%dnd zN)yT{vwuV}Ci9uo4(3o^=OO3hWI@(*AdO*zZlk#iWBmOtmRBDbO8qM>NVidi=4=;V>{F*WO)j2p~i zoREuEfhN?Vp{WHndNd;!^2JjCl>JTn0CuyQ*AnZe?Pc3oS#7YI-eck@7paD*{>h9Xr?ECPtIpXi{G%}-nw1S1qG?@+DE@s#sWVzD z2i*uR1Kka9dB#J`#wOH@bFzlbTA9h?FU(IKX6vnyrEa^#=c^mTtZrnk8&oTY`6cq1 z>}Jb7r=uBlW=1JuYTzX%DjSBDPoFgu9h2$h3f&j*lZQ70t59w`i+uxm4LgamZy-EJ zV^m(phi(O%arCb6e(68NE?(Byi#6RE;!GD%1hL(L4>9zRKY9n9_UL=>X74ceJMDey zut$4f+dISAyMmhh+J!hOU*hBR`#owm?gx(hxd!)$)b?04?p=O`qE=sf7QLmZvQH=I41M`vOe+um24y=xA8w2!vEA31v~s4v>a z7)SCZXYW_X`O;SHeVhJGTJ#BU*Vs=26q#z%F(ijo9zpm-{GU2+_XKEz0)W z%k0q@mA&|)T(FwvFZrV99prGRWDi|M(Q6CFkR%q-N?Aef7CxQW6UB%8Qe3n)?5>n= Y>j8eD$*kDTt*D)xAFtpkhXb4Y9|uGwp#T5? literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_qspi.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_qspi.o new file mode 100644 index 0000000000000000000000000000000000000000..b5a2b52c42d66bcf72f7246239762a1d9e116458 GIT binary patch literal 11908 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 roC_yX#rG&aGdI1coM6^8qNYUk|m literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rcc.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rcc.o new file mode 100644 index 0000000000000000000000000000000000000000..660b0caacbcbd3d60a374459f4faafd96f324aaf GIT binary patch literal 6136 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rcc_ex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rcc_ex.o new file mode 100644 index 0000000000000000000000000000000000000000..53a446137d514c84aeaa2623953bfbf5d071dbd8 GIT binary patch literal 4328 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rtc.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rtc.o new file mode 100644 index 0000000000000000000000000000000000000000..d1ba7b6498db44212dd4141503cb618b627114b3 GIT binary patch literal 7660 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 V;MNT!9%{IJv+ZbpbpyHGe*vxdexCpU literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rtc_ex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_rtc_ex.o new file mode 100644 index 0000000000000000000000000000000000000000..99c8106acc1c037043dfef17e0361f2987d6ad96 GIT binary patch literal 10492 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 G^Zp0(cJ3zt literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sai.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sai.o new file mode 100644 index 0000000000000000000000000000000000000000..fbb0ef9a0f2e952a0ff46b1f1c1ca4a2f80552ce GIT binary patch literal 12252 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sd.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sd.o new file mode 100644 index 0000000000000000000000000000000000000000..563e2f1eb5390ba855912e21319e2158f88e29c8 GIT binary patch literal 13636 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 z z-Vq&Z2&qHfOXwNT(MSlcsSY0@QKX=ccTUGzLeE%^CS1R@`mIR4ggk{bKnR`%9L6Pp#CdJy@Wi8G(^Y&q%DN}8Y$p7P`?%WXYIa*^KlceFB3fcI2 zfOH#+!()Vak$;>JXi6NwQ~yA`zK=Z6myvE~vE$FJ`oY(S?lG zG5RH>Q9@dgg7Y3n3U=*63VHGp(w%VjLkdO=AO+lWjQ*a{j~N}0cBpvH0@?`=QiwC2 z(Xk!u#uRrMQWyt>min~=>9+}a4XKai6SOHQKZ=ute-!!s$47a)k^>9n0@(4w~Q44njj5Q2#@u5dQ;h zB;*X^so$YrylvuNbSa^J;L+P~NKrgB4bJWl-G_BU0~4ho}&51WIw zgYdQ5mNBZ9J35S#aR-P|veCzgwAoq^jYr{8&FD^(I%td%vF#K0@0-@c4xR3XMKg8$ zxT)kuebxut&u`WZ-Mw!>yTv|!gPsB3Z|Gff3iG}(r6HoL*iGODEW?(bmNEC+J!JnA9wXjjz$<_{v@aVT9q)hP+lcoh1nVuR(+lch`4k=_-YNqg z{*tfb;rYjiS7Rjvf1lEej)(Cy;)MVY&lYH39y~hUA`Z_BXF!axUUawsCrkKu@%N8F`d88M;-^HBX0O;ZGWO~tk`2eT47$zhBKByO6Zxz%T$6+oZUk3xKL$`8xzX3dbeSyyu-V+?&F2K9lIJR+ke*%yP00-^EHD32~ z4~O>|EaJr=*9(Yg>ErYySOoBnq8HsS?{NLrz+zelO4x5HJbJ$$adsKRPXoq z9NyD_r~3u>ARW&N>!LAVLZIX|;OX|6K+hPr9|E2PdT3t-JUZSK4)0fh=LWf6bo&Z8 zyyFHu7bxp^b2+>$SoH9BQoZQ*xj4Mv16~xA&^|o->v(k>o*foF9Rt)-{=1jMYl7gz zl11_G44~r$IJ_*tYeyhf^zq_v-bVk008gL4nAbYq77p)gfVWErV|vJbmBZTxcnhH( z$BR_QdxqhmPqAd(M#vWJlfKcF_`Cpm@Ru@uC+N-L^pHheeN4#rf!=-?*yrK literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sdram.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sdram.o new file mode 100644 index 0000000000000000000000000000000000000000..44163d8818f6a734ee35d24968a3ef1f55c91f7f GIT binary patch literal 6856 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 BA|n6* literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_smartcard_ex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_smartcard_ex.o new file mode 100644 index 0000000000000000000000000000000000000000..9900c78645ab55ea844acb41f90a04be21feb72d GIT binary patch literal 1584 zcma)6O>fgc5S^`)l!_Kg1)>G1S_l#;5aXt)A`q9!iCr+~Qf3lIm8IBg&D>~9-_Pu#K>se2{+gM#9gn%*vCD=y*rCgNB zSEEpZF&Kp*XU#4C+%?Vbggs(zZ81{|%cgmomX_~r&~@MM1$5IFv@Sf_@GRcx@D6<-e47V>F9KRC zSB%+O`9-ztv1h)Rp*6jt&r(Smw~Q(+3Etx@;4}15z16(Q;}Yds*%GX8J5=x;H*ozv zt<29?jOr7pSMUZHXO;`3gv-3?i;xe>%^DQOhMOZp6S=eG967H|k|}b5Oy@2quQ9s4 zB$0z(e zE+Hd(97msk94yB8RD|{R+5!y_2+I*nfa3zGh z_0{%Tv))=a>#fDcpuN!Z?dPk!-wmC%>GwC??jgy#>+$>B;Zf;EpIJTL;x>18xQNAv ziY&T8mJIaZr57>_V<`5bqgFT?A?O_zGSICc09_LLF&fAgrrO9BWjB+pJ)$Mu_C1gH z@zL>bp|da)uC*QV0N>Q{>>|qK45(?^`)=&-Ra32IMNM^DCu>N%iY_PZe>yo+>2u{A zDpTifAd%F`8I|*?OzB=Bk<_&i%QKWI-3KI+y4Q%abYEkg5f}J~aW`JeAZtkfhK{{% zVTf!7$vFiuN{uub)iX%^7zqRYB(6`R%ddg#e*|6K9WLP=Zu%q_v8j4z5GQqa5d2Ug Hj7s+piZSzW literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_smbus.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_smbus.o new file mode 100644 index 0000000000000000000000000000000000000000..f62b7e504d2a4d363403bafe2ff2f62102f1c44c GIT binary patch literal 10572 zcma)A4|G%4dB5*HTQ&|5BST^gCC?InjD?Lc5S%|O~W`PfzzFI4PFyI7Dcmb%0R<1Y>i$#H4iwnDAnBB8#ZOPo6% zJY`S*LUJVQq~b|tyBxPC>%>cmH!Pne*qSRbA=w}_tTx3(rA6Fv+L3Gk@>NMxEYp%C zx#~vCod27UlmY*fMZyHL40I0o&lXAJ1Aco_5C`0$=DL&8GX+Z1v}kuJWscXc%n>Ub z(w{q~?`f5%B_=vL!7<~RDH;pBU=!oaI_3#Aj|E=7TD?n*?@IQ0K1rzBjij;2N2L9+ zde>!WXFL}Zp_2v9dCr+nznC#Ot;#X~8AoYSW@WMcORvSKwr|N3cHtdXlZ+1r1=;F- z);kq+Buk|!FS9;=ZA)EfG}PPx4p#LSv4g=Sr}|Jw?L_OK*Q!(~7I;zN>Vyn+R=C^! zmK3wMlT4Dd1lrvL3e^p`#xF^gta@WiSX~#lt2OPIeHNzoc32B5OC0~>w@(X}^U#V{ zj9)4dsvSR4PF!U-+NYTa3!XysW{R&%F|!n}Q0%F``U+Qt!epAw3YTD=^jf`x-iA?o zssMe8tA7*Um13RkuD23`d?gWTE`=|T42z0rJ?Je{tVuyCbCEwxp7g?BCSwLlM+N!w zL@8oMbc(XDW^w!}crDl##mbZ;-f~4w3as1(nd;k3QgAGGEmj(ng0R@dtVg}&&I7=g zj%FFkHHL-PF@#*3r-jP=?HP+;w0%L-GeT7$e)QTFmr%PeMx!*#ot|gCG-l7C-+L-f zO$Ov73r%`vY==+JSgnWT{=>r?vHtVp=2LN(wQ&wZff|)H-s7D8OPnql8#ERe>Bj%cA@fU1M zV~D{U7t{Y;H^nIC%3@OiCbJ{ywpL}2vPbx@32Q&Iy%rPhpx)9wzmrHKrUJs&L_(Bb zN}yHWCe>G=Y6p3`Td3KpdTPmdYC7gQGzniX1Q1){3mIQM{g(cLv=`OpIQek%R`Nj~ zhtY==e2`Amjmkkw)s66Bp6Wx1>O+z0LqUwmQ-QN1?8y7tD5b4afuq+N;Meak*7p-^ zIgR!4V4+i3V~ZbABV$!e3Swt$Hrp1)+42{?f`#_tWp9;}9i`}cG5CaPy&+z$lqu=C z6ep#i#g>T4P8!jRc>h1mnvyzaSAaV z5#%ZFCyCE0i61kD`20gmuv!$^N&EJ8>`!K$@-9#sQ+?|exb9XeQ>^iBm+#PCPr^fO zW@`Qxv9jV2tqVVctWur9Ckba&iY-h&@2*hez@GdJ`|PI)R(WsHm>po zZTtn!`OYOpiwxtp7{>oOH~va({M)thm#BNZ#I;?`BHPvRuQ-(UfFi6c+1G=9W1>xn z2{v<_RcfpCq#lL2qyHSE|5*ZYS}9oAljP-eLR5;84JgtnbCaCFQukEX5pM6hBO;^2d<(O;|Tsv^bOOFQ4-^r`UZ{UaQ}t2)4PW?{GR( za%-!asUAZfAMhXdzj0-=dF%=+6Hj@Dt;%Zb*yH~9OqOvP?W@BAVrBGV^5FiZ2{q3@ z`{5k+yj?iQYTl0vGN0uyCaj8VIqw!I=d(fYWJ2}1>bMbcqoNetmnU0b#wzW9_#M8~5e-SN25yQud%c5||8tQ39g_j1G;_$oF(&sHkwl5fGKK zYr>KzJO7ZVHMLDR`j3y4yb{{j6CQ9eTW`ueL}y8F>cJta@}ROP$sX!W-8V$@SCW~( z!5~Jx+v*jtUf)vZq&L+xr2A~NrswU}#C}un)eS>5UgBOmWDiJ+`{&j z-?(ZWI;i!NUbA!$={fp(;vnX}H?;u$WUUV({!0?MabkH)ScNz-BN{@idT-3xUuuz* zS4PgeS#49C+EN5PZ@PVAFu1sA6IOD--%>Ph;>*_a6Ky?ZXM@^1cCwR3Pq(UkaYXS| zj0dNK=Q*0KIt$LL=d>)RN9V!dCzX=-V9=VZmkz4Z4oM@N3d&B3>?tj>i9z)`@%oiB z!lQ`(@A?19zf6IjjVqJIre!YpB)@sZX(!Z?#D{Yn(@#t96-6cvVyDp#y94#yn$z^r;g_IQw52dH9q*=NN}eb|P{yX1g?~j_v{6 zhHu9yWsEnA(uxet9IdYHSU2o-sUBNmH7d0Q($19yx>0biLs1(&& z9F@*xTD*%E7qk|%F3U45B4GR-)=U^rnyeGVKaQRVy%hXQiWW~0_vppYW~}jP>d`Ej zZEt7V|1v>!7Rh3JH&ZvB2#xjyL(OOKux5wjcDbtgu6yLRo}OSt-rEzF8^c|4Q&*?Y z>-Bl%-QgaOFB0hqN90X4^>ynu)qHD1O_zIrPk6PwskXj$olKQ=x7BTstHQpZ&mHlt zmiIKa>|E>9C~7v7Es#*OuL8y;kh_4uvm_PIO#IE(RG=;#SY zeUH@a+{8@tigwNs%>@gEMZ(Qexv*HM5SA5Kj6XQl-=fw=loOz=ci7n*t3swB{8PvkeTN-~8 zhrfxlmvi=V&R)UUDY~*nLe%8OA4O5NNbGBz{cBkx-XwMlXHS2W(LoZEIlHWzR4FkF zXSZ{M; z8#((%&VDOrr!0~!65Etj@FuYacGgfsyYs*CkUtn6qNju6caA%)YJZKUVdH?3kwSRrQX%GO{YC= zMmE2s>68h~*l!XBjw&_Jo3X!^X*%sZGxpOaO{bl1W-_~5)4x!43-fC_1pHsl4(I4A z*uUoJE7>n|^i^ysN3UX^<>-iK98okrRD-{ot<`ioiOj5qHETM>rwRv2bXT`C=-ziv zchnzj^LP1r9*Wj_fQW{|J)zq58gN@%Q#jlc-snhSNHg>y%J^P&gAckNdOdGfO z_xYpl;B{7Q#Oh>q`J)}%+6+xKV~fw@^OGBSY>l0`4dq(WKIdml+wu}Nb<>LO@M8wM za|yM@&Sy$DYQzd~gV5UKv22TM!4=QrYw@|gk6!0&+ar!pFzRpzgPrc&l~R|sWj3?w z*sP6J>#S`Xz20!19@GBLG8{Gd@-%8{p*^8TB?VnN(3g!$hD;Wye;< zO^>mX`_uPCl9WqJ9$>hUK<;7e+az&)dR3F>N#eTGrs+pDo$i~2TS*evzjm$ufL8y{ zoc)`cy-%yB8yL0I1XWcn(jn$qw#-JlSfGcM|qs&FG%iZ>@!U-MZA5>FRn_mV`vUXAy!NCp}E2dzG)$qzKyp!Itf$pFJi2)TSrgUyKh6B2Y9o{fDy$!4jtHZ`^8X`toUd`)zdIt^K-JV}`6&6kSv^^hki ze+kTxO}_+{N!0l;*Qe~+QO54LDd1ChK9cK_IX_8UO8*j$OmfeM$xZWoC+QjH@^yX? zm$rFOzQmsw^A$WfhX7BI=P2MIxd%daM$-F~yRBr++4#*pIkE`tqLRJY@TPR|&>bgh zG0^55Jp8CL$4?$Z`Vhj^tE#0vyt#dX`ZW%K65E zRH>Fq{3jf)qH5uBWTUbQPcfda!cp$$`|U%WUi5yqpu&jz33R&G>qW=mxXr=Epc{W# z(p{U%!+4B**P!D@ohdrs4^U&o)k3jnQ0coosRMZC;Mt6a%I?MKd%$gYr+J`$N&Y(? zBVP!L-WN=n_e&fu4BXoU(2CyX_t1^~y3jB6L;cbh9lhT#@NVq)P7vrEFlFAC0%XMf z89>zp(2Cxs93W%AilJY+f9Usiv<0}V_=7oMQ>f`$n$9E0^`{O)(KjiohgOBcc#JAAE_iK*tadbrY8olWLzRB?& z1E0QbHvz1V?<058?T_x%a$*)-HHRCS1$P&R`^hXg{hNc{?<=$5`Z>N=XTgndxS!5~8|QGZ0rxA- zcM|%%#DFu#X(@tA-($91X>REm1P)6Q(oL;6 zT#R2v2}6aXJ_gbc1GgD5b35Me$3tVKxS+KFU#7gZh_NRO6*?b&p6B2iFfT6?iB@#n F{{wmLugd@c literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_spdifrx.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_spdifrx.o new file mode 100644 index 0000000000000000000000000000000000000000..cad5c8cf1204d885f49ae30ca658087ada549d3d GIT binary patch literal 800 zcmaJ+YUXHs;yQbH;kx`DqRx(_usWp_gE(9jFKeQJXKfnTGJnYL)D%+lq1z5&dTyp&o?0v} zk!7+{SS1y*MmCCD;|=AFj)#iy@tKE5Q1~?gfC5a7r;!&XcyWT40F+LvK{p%@Z+onN ztM22ZD~DbOz*EnuW)Y&68TPD)U1;!PrWtsVQs8w&n(_h0a5Ns%S|-t>=IYmJ|C4o0 zn_j1LS@w=Udu(T$xz2Vrsk8IiMjieE-xK&tx0~1V5zR8Xmywr!Og&?DG(7V@ivql& xQ?&%qo@>zF)ui9i%%+*#%nQt;mCw%!8raoqzZT2_Q;bzj52SUvy% literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_spi.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_spi.o new file mode 100644 index 0000000000000000000000000000000000000000..4056031ed8a45456aefa43d4d3d8d5403ccf5642 GIT binary patch literal 20940 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 F{RZLwdUpT- literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sram.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_sram.o new file mode 100644 index 0000000000000000000000000000000000000000..ab6c9b3c537c9188f8172ece5b6b3ecbd1ac63ed GIT binary patch literal 5324 zcma)9U2G#)6}~f`Bwpudvv#tZ{ZTaQq-}On8?Se_Np}Gy@lUq9@oq@NPbrl%j%RDP zc5KE23KF8bQYCmoTZE8`1nSRgA7~(zDiIY`Ab0?jRDGio511^|Ez>t-b{y`z1U2%;hp-TTDtvwa63|(fOlj~ zo45^M!UuQ!7R6(cy#ij_HrBBGw=E^6>}s*&dv}`YIpxtC2dXx@t32GFzSYdkVQp(K zFZAxQ2}sM35@Xr=&XJ~aO+~-Aujn7`>)C(pCtNN+PXsJ!_+{q4ztFd*5KDr%h$pcV z28V)v;PTX69?EIblar2|L`LItKU^5es`oVY(B9CS{iTUp{`>|?>g8xtTl!2>yEZux zZK_Lm5#d8*da&P)FzsP~WS8;`94I{$;|C7=&|VDe(Qlm`IH^Ta{cHaG>pMxrP%kH& zYGq(;pp^bgZ+adPe~(xPi1l|*ELzPmPrQg{HPfh|_TEy?%H;+8eh8j_gXf=~-Su;b zy*>Z75~V!_k52o#!Z|1xdO|IZ*1ENhL@}NYN85-?!A}!(beibI!4oH%Ev8bJ^r^+`pVe1uwMs+3S+n$ctEy+J1+!Q* zi~6!vTQ?hxn$^%}V#&n0nb?;v#Hz+~HS3H%6Hms^>7-0Np17b-S!TsF8s-`O>G_r1 zCrpPTHWMpY#>RR{x6H4W8|B)Dp1gQ5nYi!_n@?f`4AUr-v2U36q-vIJZpLymtaq?4 zcSsFuBg&|9EHI`VS57G7TGV?eFaGDZqLp zdyi!Alk9zxJt*0Ol078ZLz2B;viGy&K+qnXKv!A6gdddfgY2viKPcf3OZdZ*eOR&& zvl$=Xu!Ijw_^@P;NcM%aTOZL-}9Ob!Fz0gUBGL1cjk>oF; zhf&|pVib*@=B5xZl6*&!--O)e>tjE6WXd$mg6w?>zwg6`SPz`r{)gG5BQJ6PFuUl; zwC7$U%#=!5gm%va<#ni zY`#OE*|g0KT>E)1z#AxS`a?OgH&_QGH=qB)P1B-frHo3YV5~pi&K2wBR=%uG^NMK{ z^RtCE{_|GZHhmfnIrmrx#;4+-^T`g7PsKqNCx*PNcxro9f)?K z?vrqjMi*Plk_2m*R=I z-^Sb<_eYQg2d3`)EeW>;+55F5d`Rz&J223SM{()vSH#`J+#C1Tkh}5y26`{wh=-59 zjs@QzCBD0mMNXKy^Fajl#{Cm)-Qpes$Q$>RCob)yhlf zpAJ3M0lfpo{=Fyhr33!`6MVmw_|o7b9^#|tC;0v$@!bI*UaM|Hy1e~W;`5K1 LSHXH~U2y*eVQa7K literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_tim.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_tim.o new file mode 100644 index 0000000000000000000000000000000000000000..51b3311cb27de24a4208e833138bc67b73eac25d GIT binary patch literal 33252 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_tim_ex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_tim_ex.o new file mode 100644 index 0000000000000000000000000000000000000000..e1cdce200a3fbb5bb4a488f6231497a22d511b46 GIT binary patch literal 13276 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 Dkm@J( literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_uart.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_uart.o new file mode 100644 index 0000000000000000000000000000000000000000..a98df6b801f9907611c52563baa2182b16a5fab8 GIT binary patch literal 19596 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_uart_ex.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_uart_ex.o new file mode 100644 index 0000000000000000000000000000000000000000..b62bd8c62bee10b766fc056296675117a6bf90ec GIT binary patch literal 2844 zcma);Z){Ul6u{4GyRnUbqvMYhST668tQ+=G){*fik(IhP(M`-42?D0;+PA&J*4FlI z7GtskYWU{#gC8VO6ZuT|8(0hxMH4@^8j@uRksz@XzjS0|&uE zZuXzKEt07HI#8!cCBa$O8$Diki7Dite+u4>d8YYXXSDW*%AwFqE_9~%l(u;Wg1bVe zdY!mxG$YNl1vZ5$&Xp2a^ShMg3fuaza@X+Y+Daehpb<(R+bxlf^63xv&el&@`Lh zEB;hOa;i{-hKZu2O~wnAOYbzFy=}0IyDvE;VA1}04%XtM$@nLgEAAXUUj5MNygS}t zIQ9h23ITI>zp&@rWjwL}#`N6Y>v?*YFaM~4wsyzFjcHhUp}-_3qw`D_D-2=J{i1{2 zDGKc8V(J=Js@J73*;A+<7g*{hH2syQihvX{Ya%6tt&a+|qNI8HM6G)Y_J&He&V5th z2k&g*HzYlxWoRGC7!G{mC>7 zriWPjP@fu$sWJ9OIvG_nnPfV{T7Av_?XAAITYN*2X*Yn7Yj?TnoMUH%s4O{;@y zB%?O6qrvX3ZE6|eYxVV|BZ;WS(&|V&6Hg{s^NtRqDs+L*V+>TtpIoarn-oC|IlfD;_nFxpO= z?Sl0SJgxsNoaul}c@Jg^V+H3f?g@8gQl`T+g0T@rjp)N^HIz*B#|Oal9#nO!8Pe3~iT$xb^`IWnRTJGc zJgCS2yAQZWFcwSW-RM*k1G*MQfSE=#40fwgH9n&DBne^$I#j(U9zF5Yr11Wp@=ORlP^J9*EU+NWH_`WZqqZ+lX92mocGMukM zrMpQ=`@M#0p+K_XEzYyiNpAFXO^_-=f3H%UgKVRVanUu@fWOvesgAO+ib*OX( hswcez|E6#XofQBfT3i-BrMg@5Ch&bX^B~6f^k0o}I=%n^ literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_usart.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_usart.o new file mode 100644 index 0000000000000000000000000000000000000000..520694095761ae244a33236ba697234956a0018e GIT binary patch literal 13048 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_wwdg.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_hal_wwdg.o new file mode 100644 index 0000000000000000000000000000000000000000..913ad7ba3cc6335053722b875d63d6d1f9138080 GIT binary patch literal 1648 zcma)5&rcIU6rN>UT0pcS{s4&?k;G!`T1v6#$!3K@LXD!PiA3AkcIp<|Zrxo3yx_^Z z2NUJypI{6(xp?+u!e8LQE1tX<@x9#+T}Bdp$=i9~``*lZ^Y+c=%)+dqC`5=t;-rHJ z*;73xoc5MDiIEeem5XhMW?LWjfBxS8W{#SK>U%F$W}Yfts`csb%|88pDYm1~U*A>p zGqA&@R<4zcZmZ@a^L03~yJdcjgm$exrE9B%XGC{MPSShhnmiBxhTlX#X+G}y9bkJF5n(k3W6lQ)uS8n=0!Gl!4UrR-w< z8gCzw$RrG#HOnTo`SY4nvzjzDHI+)HACqhfZpSz?YD9^H8P+Y^XBa^-xC%QAt;j2JAOkI8_oNX9V!p&>^If zu*8QYJ|giEiH}NrRN{LizDMHwBz%kvfd_klHyefeue33?a{%g{ZsT4LN635|`|(jy zZQ~J-hkTCPm`qhO>+406)r)Ium8V*njJaekyHG3?Zs&@5r#0WK1ssRbBCp!qF+1@y z%&u<~*a}~5>8xHiSb3#G&M)4ZW6esP+mOE-wD%K!bUo0LEDrBF@A42*#O!1&6W1eka8(1IF1FBI4eF zBUs-^pg#1A`aXh4D}~Y_ literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_adc.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_adc.o new file mode 100644 index 0000000000000000000000000000000000000000..bcf9dc64a154c7176741f7863288fb5d51dbe5d3 GIT binary patch literal 796 zcmah`O-lnY5S`do?Lkmc`~rzyT)|z}wPn#;DYX|XA_{_tWOpN0b{kEi)KhS_@)eGV^9$CV7)V>-dNe0(KE_;0FP`<)Bg<5*(<)G(fxAJfu$h53aNSD?SwEnGu5e1%$FC) zB3UXelNGW`*2|ltf(oIdsWNeog8fHkZeos$JG z|HGd{R@Fwqv#Q2f@0ZzbBITIDHd9mgx>PL04TRr`v3p{ literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_crc.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_crc.o new file mode 100644 index 0000000000000000000000000000000000000000..8ad44d15ca0136a5279fe166dd4af24d0f1c9fa4 GIT binary patch literal 796 zcmah`O-lnY5S`do?Lknf_yrQZxPrT`Ys;dyQmPj#A_{_tWVb0+b{kEi)RR9-f0S2$ zflj&``vGELGV^9$CV7*$=IJpZ1neT)k9)#SXp%-}j)Fk~wze*j+6V4Rhp*Qu5 z)*jDWxS<AP$D5hLD=~-Bt+Gb2F{-)MBwh zmdJ8pg{+b_vQgX`6_g7dO%>tmJ5LW>VQc~b1(+HwBQ8wf;sh=MD4iYzov`1(OOm@- z#$F8Isn=Aq2)&k>zqb(z(BQS1X5d9ifftK3_*R;tFepz0qa;dI;V49 z_J_kmR@G+Cv#KU}c2?WS!{7f^{}*pJ@8_d8%kbU?QMQ?W#%gGI=VO)yc*o$t0`&G? sOg07MB^3jhEB literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_dac.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_dac.o new file mode 100644 index 0000000000000000000000000000000000000000..4b7b332bbb4ef687ac501b85493da5bf801c720b GIT binary patch literal 796 zcmah`O-lnY5S`do?Lkmc`~rzyT)|z}wPn#;DYX|XA_{_tWOpN0b{kEi)KhS_@)eGV^9$CV7)V>-dNe0(KE_;0FP`<)Bg<5*(<)G(fxAJfu$h53aNSD?SwEnGu5e1%$FC) zB3UXelNGW`*2|ltf(oIdsWNeog8fHkZeos$JG z|HGd{R@Fwqv#Q2f@0ZzbBITIDHd9mgx>PL04Tau`v3p{ literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_dma.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_dma.o new file mode 100644 index 0000000000000000000000000000000000000000..787f3081ac1a5c5d5cfac3d2be6af54e419bd1b3 GIT binary patch literal 796 zcmah`O-lnY5S`do?Lknf_yrQZxPrT`Ys;dyQmPj#A_{_tWVdK>2O)Q8=mp+BHA(-_uTn?ygfqo==uQ2i zwa4=oZsz`Fg5{z0!)pT5f>(KaRQeBlui$VPT23?CCOc! zGOrEbsn=Aq2)&k>zqb(z(BQ>PGw>p%z-x;%_*R;tFepz0qa;dI;V49 z_J_kmR@G+Cv#KU}c2?WS!{7f^{}*pJ@8_d8%kbU?QMQ?W#%gGI=VO)yc*o$t0`&G? sOg06ET91poj5 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_dma2d.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_dma2d.o new file mode 100644 index 0000000000000000000000000000000000000000..5c5b8b64cc7317046afbbf906fb37c2e8b0b8aaa GIT binary patch literal 796 zcmaJ;O-lnY5S`do?LkoSTaf6*72I`QTNb^QQhTu?q9BM!wwq$5+h`J{p8BKoM|t%Z z=%l-`AE1HB%$s?cPYwN&na{QAhF)XNvF9+sb9* zfM+e-(2XSPHXo?uuWi*9T^f|jfnU0VN`P-+oJDOQ4u*xQkec`0MhMe$GmYZZVt$D% zlhxcBStlE0E59=;C=)uG%EQ-pmL9m=*aQG_Fg036oSVS;30weBIynkjVXt@J>DiNOf&EzrNC>7B;j4m;aohXwQNT(nyay^{so&@H9Ds= zR{Dp-BUaUR#d3IL2$iv_NRsR=nKkMhCH_Pz)gDBlhKVxMyyz?o|0=#2zWC416 tukrS+ru>O!4$Wj{razBXM6((&gd04#VuEbhehY|4d0i~jED62k{QwFLR-XU> literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_exti.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_exti.o new file mode 100644 index 0000000000000000000000000000000000000000..215d2a4b2b0c032645879fe2cf1b606abedef80f GIT binary patch literal 796 zcmaJ;O-lnY5S{cx?Lkmc`~rzyT)|z}ZOfv!Qfe<&L=*&(l5HcdbQ?{g)KhwiYxnnRzoWlf22Wae6`s0lNq|Fh&6HDJWJ(1P4km2hgn7kEzoi#`pi)xfXZLM_0zFwUYFh=XCVE~MrIw-v(7{A{a~TPiG* z6|$ONBkN>?Y!!AU1!Y1fQw8|^%F-j3|1|-CJmewDeyWXNq8S~I2Mm-E#v4}bM@<{|G_4fjn0{j zmj2=Rj8(Or@vN$8o}JY$^6>Y6)c?iX&-(f3%`&{7&-702IlNqtfhL&~;ntMN)Jph^@njHpC)th%H|AF*pmhNv_~(?VQP>+IU1 z$dW5p?IBX^L*b+mQX_{p2#Pj`qK96JLMV(zh!J0!v~bM=E(!!Kaw!za{n*${ss=&T zH@iF3a!4f|dpz^r|F>_x-g3t)qi4nhK>$_+=!HEC;6|&Z_y(+|7bG|aP1@O=?x<`E zqPae)#j*bq_2e4*$abB0OY^@qWybweCir8dRgaNLtZP_rVQsyDHr6$)w=NX7{4+6f z_2T+RtH;Q;PbAx3tb*8lO4zO!Xpe0BMLI%5@$@f6jg(eHVoKCHi8m#@4-fyR2$H$6 z>b6ByMOdRcpiwlYQ{-cw!iWGm?`mF+m4$qh7M@k()I7EcVh@=xoPt*3@oVnyAU97k95i7E^JVq^8VIV^>m4BW4^m8iR7I zzq9TeYaQzx+x_={ck9P4YR}e*cP{E6#Zo&PbDbaGrv4j8e=;om86NppQIzg)hPO=8 zq!o91UMX(X6P)R};+FXL;+F4{Oy0Oowi`Wy_Au!x?Iwn|8^kVi1#_a+%83&sMw+da zZhT-~@!+Z&#qQG1FkSs9vUom7c9(XCX$EzhD<1kph>+CZHh-syAMOr)RX5j#6K&cV zZB0AsYte}K)(ubpl2;Dz(VI_u4hg%Mm$5Uetsq@w7vtLeH7#a%m+gnJ|m50=G6IlbzVA~&!*Kv zA)7BqgW>+@V}s#u4TLkwg>3#IX)w|sc}$|t=<(=))SFiqRHdLkBt4s$o_JJsLWBpy zb9rSktx0+Hl3viWi&FpNkM~Chz6ptb08mtAP6weEyFQZ58|rd+Vi4+D>L(gKL2tWo zKsY3J2#19u!h_y!0jY}Oc6i~#UAHKLTLloo<3-ChE1$!bLiaC(5#gPb1Z^bn_qIK7?IE3-p{1Dt+4!P}2&W(6^rM{J36!93&8t|0;DtWNrf+Hx^Zle_ z&scUHe9f_kEV~}Q?b!4rf|##As<0d3O~)Rv^d@-Mu{$lh8SYlterUtV(D~SU3mkK7 znrT63g;<5%22VM*J>LMFqYpcU&S~D!FJV83e+rJhVA&zK>evrjc00W0*!Fr3z;7z- zgYXx}?y>koaNn_MrUdc)0{D}IF6`5K7#?+On(0Bh+XW*N>pwrZyga+GFnd0ej-;W- zfS!36n;^53Q`5=m#Ki2WMct@yjHp$v89k#fK39#7E*t71{*=$|2RxJ44RtD~<`n~f zoM%TDmAM7AVl<8z(F=P>VsgYaCbdX5lgTb7b4psR9+LtI!^rD%ONROxjC+CfnNdP2 zX2yI~a~W3+WZ|jAnOW@4=;@2rQj#MT`)Hf|j@Vw;(6+-`K7I%dHO=o(ZNNP#n@Hjj z(0x%B?Sr+w81uQjl9^V|=hcEXtr+&Uvqy}?l96@9$tC=p=3Ps{#Z6@A)uf>qO9j9; z4WNktNKOlp!gn%;GKZ~^w_A<%@Dpo5WL_~8h|CoV5TTApRlZfbot>!`+#6Y~*37_a zjLR}74?mYOZZxAM5Nz#Dj_ru+N_thA;3Li6cOF5dGPkKS2WLDMQljw_)+?=q|~?jIbN!i1%F z999_T#SWt7^LQS)T6xgNaclc+7>i0nRzoWlf21m^Z1Yu0(KE_;1>bBr=Uj=rdRc| z)-KOlxS<THsf&p&sB{7-vxo#KEx85K{Aj+X`WNZl+b7TFftz z5?RizkX5oqHu77ef-<3_sXTmsW$B^IjZFX`2UDYE#JLHapTGqGrIWqjHXICYdcB*w zhgf)R08hOnnnmcfOnuizs6d0)VVZ##DFt3zBnj_h4#(m#tz{fNX|Bd@`X8)g+31|k zXz3sRp0TPnGoDp7$+NTCMjrnDkNUrOJ6S&;y;+9$I*iiI^fOjN!#f|+EWjHEdlsO# t_Zn~CYRVsI=Fm)LX8QAJMKr4cL%76)B@<-J_FF(a%1f}&v?TPF_YLS_@)eGV^9$CV7)V>-dNe0(KE_;0FP`<)Bg<5*(<)G(fxAJfu$h&16e^5;Y)qDO;zJ@9MS&53aNSD?SwEnGu5e1%$FC) zB3UXelNGW`*2|ltf(oIdsWNGsh3Q%2)&lMzq1hv(BO5MX5d9ifftJ`<2}sbR6M4&Orj^v)vt^G0c%({IwuQW z{)az@tg4NIXH|{!?5wtshrj=={x9B6(a%S3mf;PCQNEde#_DKz=R=+ac*S7f0`&G? sH)rmaTdiu91KehAvN#2tq>+>rds8R`Qidu zB+G>rvP#y-MsaIYP%d;dRfLbvJUw)UUlRZ*z{F@7abXM>$8ZTi>9i7b!+!rZNp6z| z9j9I!z*8@&W)XTVGk<3zl%T=uFwMY=lmf3U(vi4bDmW-&a<=HMjrnDxB9<$yLmq!y;+7g7)IG<`WdUC;hhgz7T^_wiUsKH ty~f+On({lEIW(1_I5U%jxk_qx<`^_O9<@K=8v?TPF_XVl%R{a0~ literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_pwr.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_pwr.o new file mode 100644 index 0000000000000000000000000000000000000000..3fff953fb6b5636ac2a46b447ff37e5f891577cd GIT binary patch literal 796 zcmah`O-lnY5S`do?Lknf_yrQZxCM7z*Ook2zDkOs{L_ z&0U_ga6>neY|!pe$shZwF9tNIRs+9s1GNC(!Z?fiKpYGUbs;q$y3G)#=VqG4sl|MW zERp5h3RxvKVwxiyz?&20=#0dZvlFH sukrS+ru>d(4$Wj{razBXM6((&geyE)GC{U%zXinOyci1&OG0mXUwm9vEC2ui literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_rcc.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_rcc.o new file mode 100644 index 0000000000000000000000000000000000000000..7370fbb8805fd4ae3600ffa7fd4a11dda545b553 GIT binary patch literal 796 zcmah`O-lnY5S`do?Lknf_yrQZxPrT`Ys;dyQmPj#A_{_tWVb0+b{kEi)RR9-f0S2$ zflj&``vGELGV^9$CV7*$=IJpZ1neT)k9)#SXp%-}j)Fk~wze*j+6V4Rhp*Qu5 z)*jDWxS<AP$D5hLD=~-Bt+Gb2F{-)MBwh zmdJ8pg{+b_vQgX`6_g7dO%>tmJ5LW>VQc~b1(+HwBQ8wf;sh=MD4iYzov`1(OOiVo z$6gHJsn=Aq2)&k>zqb(z(BQS1X5d9ifftK3_*R;tFepz0qa;dI;V49 z_J_kmR@G+Cv#KU}c2?WS!{7f^{}*pJ@8_d8%kbU?QMQ?W#%gGI=VO)yc*o$t0`&G? sOg07Mv83jhEB literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_rng.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_rng.o new file mode 100644 index 0000000000000000000000000000000000000000..6ee60651405605d5f713053f2a8ebc1bd0fc3c79 GIT binary patch literal 796 zcmah`O-lnY5S{c(dk|CtQR)N1!Y3VQw8|=%+e#5|1|-CJmkj9i1QP;FoBBzN+p%z-x;n;RDR!R6M4&>_?B9t6vxW1J)k9)#SXp%-}j)Fk~wze*j+6V4Rhp*Qu5 z)*jDWxS<AP$D5hLD=~-Bt+Gb2F{-)MBwh zmdJ8pg{+b_vQgX`6_g7dO%>tmJ5LW>VQc~b1(+HwBQ8wf;sh=MD4iYzov`1(OOiXO zV=o5q)N86)gkHp%z>7ti@*d`JDjw5XcB5y_)!0SL9q^D)Z;ykl@+0eX9{ r@%F8z{E21`&E#gLKaW;Mvl=jjYdlynLB4Fi1;nGg1Pe_|LT`CLVI5W+ literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_sdmmc.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_sdmmc.o new file mode 100644 index 0000000000000000000000000000000000000000..2e0a73e4d414e385371442ef4053f1876cdfa4f6 GIT binary patch literal 10976 zcmd5?Yiu0V6+YuxKN361W;Z6zll86%Ho=acaS{|*XYAdWU~KHrgpewJ>?B_N*zN8H zl0FoRgg~WK5LzVCQk1Gl6|^81a9bf+m{-LQqB>$Dl>lvus+v?3OjrmH(e#|zxx05x zX4{xwz0&O5bHDF?_uR*vJ9F(rZMOszMFEi%sD!Kq5M5;;`HjY{621ku!;x|4g!-E! z?=OVnfaAoL!D21{gg5o|mSU~ogm?B(Ua?kqqF5`!Yw~@k->o^uwO;T)$qbxc}w5PM^rj<;hd$m4;L2)rL+)^M8El;=eByZ|h8b*}Y=$xvwr^RzbP zo^4xHG`%vvAgK-AS(tyu;X6D~7I01~n?9V;hTbVu&nQ@;cs`wZ4ex6B?PpJHxp-O& z*KaNJL*+lGVeNHq?}D|-$MAX!ujR`1$=ynI@-3w%xjb)Oa(7;B@i)pE@=q-LplDN?yd?)pn);re?_NN&1bxFyr_9VP?$pyBS2I z&*3jb$0^_YH067rqI}n{DBtx2<^8{)y#I0ft^FC5cpjy^=Ml;~AEvzXLCV81b6kqf zUHZCq!tc9(+*twM{D5+tMm$eL&cLbj4j+v-j&Xf?pfW)D!tvV4G=K3N`K~$g%jU>m zHb=f^j{NdD@_lpUSImJAIA3cj{4`%UTdEJAkw%)a^z+eqp{(CJU&JrT$yaZd+4#Kt z?bH1992Zt#3lD?$O4mg59Qr_OuHcIKxb|MG#h7sactg&9*soKyVxD7eD|^8edzJQR z!5lp*x?+6*mu;*oeRIo@3uD*k)2{r_jM$}`u`3#+sHUjOwBq}0<~8rV11X9n+Q;Ve zo{p<|UNf@RPkCwmWY>`&2-F<|T%m2b8VEip#1f{mhclA^zY(f{I1I_j66rX4^FyHmaXywfX6++!ci>~fSO z-6`l4(R-}xJ)=i|ol!jRQmpMdJ41bo8he?Ft7Kuo{)w#*h$paMJUY3=c08A}@w^jv zCo!6|8kD^BoYVaK)la7V=&w8Qkum!p7=Ab>I#Xw2N5_kN{&E^$#RnKUR5y*W@?<)8 zWM>tEnzqSP8NBs&&-O@UIPTdSiFsOLBc8UAemxY@L!Pc!WI&I{BeA%rxw^i#uDSX< zjnyN4cST}Vp5~hRnmP{^)^4nA^i;<5VZAS|S9$Ji>F!vkn-bN{)%~%)(SbovOusuE z4@X8l^-WFnwT<6~mUq zmDLWf{E9@wZh2>Nz{i)2Li0zppa3f5$uQa~vmJ1irNm*eRLEy|KEn$bUcm4|h8Hrt zh~Y&HpU3cd44=>N`3x^+crn9E7+%8g1q@%n@P!Ot$nZrBU&L@H!<`IY%<#pq3>mj% zSc@|`%BbLGe7C`0l37J=#xG_3Qid;O_)>;1V>o%2O)9Kl_=+ruITcnhJpB- z@T&!6+*K%Ncsav;4EHho8irrP@M{@1#PAk|w=i5| zxMsBH&#<&ijxs8=F@77vgA5Ncyq)3gMtk4Su-Y>@%BZl7@wYL&gW(;9-u4WuBa@?y z3Z0DK$?)5l-3=?Tgu=%Lyjf+}dU;A>%r#jb`Si@gqhVA|>NtAig|@CJC?wCT;o z1x@h01#gDeE%rt@XR&X9lxe5OdovW^D+u-HIz#U!SZc9bpwhHk4P1jwrk!rT4Z1D- zAnY^kF@xU@2TeOYUfbZ9Y40@f4tU(OYYZFLe>^eLP`|hNz=1u(!+YYPk&%I#0jNko zMF@IYJ36#I?W5s@neEp5LV@-`r)lnpg%i4DcSY{eV?Bw!gubWqR+A%_1p;PaP)}sb z&9WYSG^9mFM*2oY!^koVy7hQ8G8)&j)me!a8QmM+*V>op%TmbFBKt=ZdMsN=-Wr9O zRue`qsb@R-!ikPZNVKAjgo2Uw(6Daw2zn026Z#0guurBrDl_bEeP0;oOU%6C+Gwb4=XR~9)#TFhN>5$A zRGU^|yP%lW?CLaR>tGiKRegR$9JX zX!;#E?`|;SIo)ZWqH_AInt#v#uTA^bH}Mav!Rq@i@7HS5!+ujd{U*BfEg_GemvoM0 z+Yz?kjwSp2OKNQ3o8us&cHifqB%=L6L&F4db$% zAQ$Jq%kbU7M#Z{M*buBcMlOQ6cjSWY#?i8$*i_8yEH;?5$Jn5m-Nptp_Z>UL+<|N% zX)m(HGrN)oKbRt9Vwq1WeWW1>yyaE)H z_5O%FyLMMG-UrB|Z$goTe;XKY772F#-NtyIA#b4&!@JPCoADfI)3>5X!iN}^)9J6@ z1h!rU_%#pEgBP8G5|8HR5vI2tZTglMN$Amcx~#Vo^{77Sx$zQuzh!z+bez5|MH2mZ zn(6gQ{?Vzb(3@s@Cv)h%!Ste%9-YDpy-%3lbPm0bnBJJAN2j(zuN3PeH9M#HAlvnK zG4kZ`dq~owm?HExGQHXydQD94q@+iu!a{F1)9cNlx0C6OOL}yQEc6aBy@zt>eUIr) zNqXgy9?hpbep5O09%FjblAce}dx`1cKd#u$$0XA`C+X3tw&?FUrsqMxZhqfkdb5%q z#dx9j1=H(7K;9dON9j|h2e^pE^IL_u&|8N6lgIA}0(SnDB2Qj_PDzhW)rDRY(|bOL zULDi(NP2V%FZ6nt-rsZRbuztLNpGE`7h!r!^3!c0#Yi}8MjB#ze$*53ica~3e?Me; zWvFL2e)loGt&)EYlHLp2oM}H*|dUr6rqdD|$XL{q3UW=rcV0z=I*D9Pd zd1OYJ-jvi|&E!%4A7Xkb)U#WE$C%#hl7DTI-m^?^O`-kxJ;U_=Ea?R$z0*vu3-!hj z7YSh_onm_LOZ{y}2JxuB|H6#C{-#mS?)g2>^kyah=&wXVZ$7SHS&tf_vv84!N2vgL z@_MF&HnINbuSh~~4b$6+q#8pZ{Ug?&m+2Luo)anbe$|PW(7Vyp6Ma02dWX_d#xMC! zR}gvl2uB5!kIqt@5{WpJ=q`L9djs-%@!F30LA^7Q2sV9Gw{wS~h z0-ba>S_@)eGV^9$CV7*W*2xhe1neT2nr z?LD5ia6>neY|!mf$)92sivbPl^}w&)KqJ7nFwUYFh=XCdDWv8@w;jUN>~yH`rG=a+iN~in5Z8#iulBA>V zW3LO~spnL)2)&k>@7o9kXz+SWGw>p%!0U=M9{>OV literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_tim.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_tim.o new file mode 100644 index 0000000000000000000000000000000000000000..704de3992732f9881c6f6cb55b0cfd9abe9de683 GIT binary patch literal 796 zcmah`O-lnY5S`do?Lknf_yrQZxPrT`Ys;dyQmPj#A_{_tWZM*1b{kEi)RR9-f0S2$ zflj&``vGELGV^9$CV7*$=IJpZ1neT^38`r42L68NK2_b6JqWo&Loe|5sY&{Wew8|sC!8t1LvQLA ztv#N%a6>netk=G$lE1_%7Cjo&YJp$9g?fN*VVp%V5C_9jLrBg0ZYzZ8xtUgZYOz=$ zOJupQLRQHd*(h#}3d)6!ri$?Oou>z`Fg5{z0!)pT5f>(KaRQeBlui$VZrJbNCCQzR zQ?Cu+sn=Aq2)&k>zqb(z(BO5LX5d9if!7vk%6pi@sd!9l8As2WtFepz0qa;dI;V49 z_J_kmR@G+Cv#KU}c2?WS!{7f^{}*pJ@8_d8%kbU?QMQ?W#%gGI=VO)yc*o$t0`&G? sOg0Ak8k9RL6T literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_usart.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_usart.o new file mode 100644 index 0000000000000000000000000000000000000000..a782c15c9905d7841dcec1c0ad35e8e3b3d9e360 GIT binary patch literal 796 zcmaJ;O-lnY5S`c$?LkoSTaf6*Ex7A;ZCUhIO7&tzL_rXdY@5Hai(~Y-c~Og z2Rv=zhHfNTzuBRZKX+AE^l4D31b+DrssX-*aTaxfI2h(?LTWyA8zJQ9XB&l?rR*|U zA#0g+vOzYG&{chr{80uXjIC zOlq$Q;Hj5bvk1MGiSO75C1~(kOf&EzrNC>7IOcuK;aohXwd_U%&DF1~{smiDH9GSt zEBV8pBUaT;%CoAbd3IKN$iv_NR{s}oKketEH_Pxw<0#ooKVua%yz?>10=!~yXaRbA tukrS+ru>d(4$Y=!roVtzK(iV!gd04#YJzmxev61Fd3`L@EeXBleF3>aR|Wt8 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_usb.o b/.pio/build/f722/FrameworkHALDriver/Src/stm32f7xx_ll_usb.o new file mode 100644 index 0000000000000000000000000000000000000000..965791463e637cc419d9146fa8238d32ce93ac19 GIT binary patch literal 12828 zcma)C4_H*!l|OIZ3?Lwk0~(BA9zIlHbb^2tgVDzfj7Bt2(Z)2{IuDq1Mi2;~A2zm5 z)MQ)RjZL(>NsX;3$u{*%S0tsan^Fmww%extn8a*R(}vVd$3WXWWk#pTR`;AY@6Dep zwtGL{+4Ni{ZKu;VLLQDeKvsgt;!Mu1eDHFGWTYOgvu>lAG*S;D_TUdtPt+sn>}|mw%6gkd z0|18Nt$thW-Rsk;58KzCx7FIzQuX;4Lf!n5^}Qi;!(scH^DkW4-(?7ml=g-Kj^m|= z?G@)2)hJ+aFnaLt7gRp{-b#e|{cv zEGj45c-VgAOtP3H4to{^J2nlwhCTL){o;rVgpReD;#43*yb_oxeiTR-{~SmYCj+VC zhk+SlAdn({5P&mM!{VDa%hN%cKkw!mdnW9yvw-V|AKch>X%4{Kzqv8=(5pAbH$Qk| zKhB@y_p4g>qfPX3#lVP%D>6AnWymq&%Jh$TpunL(!-y+YNG&I8wRq1bXP^7Ul52iW zs2GHzPmq)DbSOUL$2b>~4et==Pk|S&{DR+V-&%D!aC?9H3I}49B5>$u)A*B+;7_+| z$&T|%vpAhcniDjPhM{7vV<-$cWK)0xeM>(KJB-d5FZ<9(K|B^N=r|T$EF23Lne&{- z!ZsIwMFOtOIO&5-YmMu=-xvZn*u4H0w4#A;arL4vLsoB-sCt#?qTI)eF5D+YXTz}i zAwLv9;D`K(51X~z;Ec#nSm!tA=A7XK5RD;oW1aH#4Rs2%&2`pY+go9kTjWXk+x9hM zu)r89Y0}YID*A7B=a|)tJE_YmgV-y#<2p3S$HI$B=AG`v9ct!#hRS2{whvX=uWBWo_QpkkG8 zG@MeAr6hrIG)pmLW}h(#nYbP$12cQL0ti8)Ny+44vc~+pRNKQ@-}dJCa~Y1^7WGa;`fTMOeCLYJcPX_h{lg{iUCDVkXaOL{XF+HNp^!Oz9i0iy^xP=q>k4>T3jyIY>PzI5S{brmy z=)uxs!#LX1-H~zb!*M>@P)V&Shg<3}{`?_e9!TxEuLmaWS=29AWKc3W!H@PVg5tCb zl-m_(L>m@G%04@lxdmri4oYu1vZb?4uX|IaVL5v};&W3aLP0POqGZ)HSTzk+s$@0Npr`Cl&@=VXEh99{rxDJDB6Wmws}zv2-?>y*rTD7!a()oh zGM7K%w4fidQ>KQ z)J!i-uFZZg{L1V2ye}ySe7Mt_HolhUHBF?O^5i^kO%N7RZkotInJb>T+v)$M*Kq2y zGPg9{ukMwgZ!h^``WcGITwA_K^-Q3cj`}4dDm7yAS913jtX<&KvU0&|qflsboyLY2$;%7DY zIxYpMCvK_USDH6{6s&KIruB@5%h&NrrhyX=OCs*P@{0cq;CQzl?VlYP@q_7SYEWy9 z;@g5FelWcUo>}1hFAtq2F9k5BJyPc7Co=dlneueZzv@}@n(0)UoYuJ9J2GYAtq#I) z=ZIW!nQZX?%EO=PlGAo`)&$E`CRnBt$6Kk5w(`*cEFBxotN!n>d5GpU6*}4fm?Nn! zdE$+lv_|Tq2G?P^yxePbyh;8J;k$0$OdiMlX2$@CM`(q&7!=;nYoGHrH+g_Nc#76M z-3g+}Glr+b!jC~QhPkw7`}f)LY`o{0ey(&@b&9iN(B`QMi!QG0{lNO3v>vV)CLLxA zt|;y6q>I*56wySC!xXcqjPuNj#IKIEDC6GMSd|*95^F0pR^?ybe9L0(F@=jIguT19fC8#o)~*QAwte<60Rj@aEX1kFI3E)QYjBDRaY1cK$rhqZXFTxd;VZQLdcp ztqwwgnkzZRNIq1ZD<}CsOD7uHUPPUhbY`WNY_2=d*D+vpnzS1U?wZy59pjScp`=yk zj)m{QdoX%z2qQ5Q( zT}_Sr6<=3xV^%HdSw?s4_}fEpJ#wJ+NW`78;%0H%7x!IlYUBijAi{VtuK+Ss*Xuj;0E96FQ45)hnHR zU&&zPzR0$`U`#s46&d}i4%`)}_vl5V>7D%3s69ygKq?3IoJeT@?9fz|M5hPN#O3p- zz6Er9L@&A{7w?J%F0^r3a_D&Lo8gp_hJN1m*w}lQlN3X{!6RKgRs+^I!|CwU zMR<|2e%ikp`odnrSQehyAw21E-3H@XAv~qb<+`S+f2iqqnx^wOBbr0fdJtX@n-`K! zQN2e;dPncT^CQJ~y!KhUGLY_kqR-^KuP4LL72o0S-IJyKEi=X6ySwc4bG7_rRo0kC zPDbtIfL^v9l`T;Vb$Wx)5jQ@sZ-$$8_wUw$>@+pG9#eL*nc>3)2VxScDMlyCaR zJwLI+m768f)u(*D2f4ztA10R>#th;m7dL)3oIb<}-~FNq$GJBdZQYct4Ba2_{(Q=k zeE&pp^4f_ZDMwB{b=%;O&SIrzh1dvKJ;eGXX09M_t1@&zc~8{Bmg zY_16-!G?maSO&X!+6| z^7i)5B4LHC)V55Z%952OB{sy1!B+pVcsx?*W#r`*=$5jx$wyj|Y* zHlcL+^3sy>e}bw~+}yHTZuA2BD}c$--r4Q$S-NorB+X3TIKyBuW^=Q-JNO)KE_Ww4 z-?#v+o|xh*jJQGLQ6Az^03HnSFv>h58zDQP#t3(yOj?}y7{Hi-@?c{4CI(Mt@MKts zjG-tiIa;Cuk0*Fy|0xVUgTZGocq)UZGI%$*vl$B_09%eKA*-<7Hc$mZB_?<5<@#rmy z8p(TNiN}v%iFl4Wo*zf;lM^FjiHAEG{+$dykHP0LcrJtIGI$Ue}Gt0G#W0*{|X6W4#G%0CbtUj+YhoJ=0t96hEYcz2vk_<=Z?`q2}Que6E%RqBwM z^KdVN-^<{u8GJQ^uVG{f|FRW1A78=Tg6H9KO}?zk$@p3x!Re&2;Q6*KL7oBKn*6Ye zr@}vDt|v1Vp2mmFL+7sr(%}V7wyW|?IHk#S5?KIm&6?bUjVyQ`{aTYLQd{u6`JE>3 zQDqBU)#NX!au%4e9sYwCRXH0LYx0w-JR8<(@;+6b1E0}kvV#TV|09}w7IO>6`(2v6 zUd8W(Cp7spsyq*lX!0gi&V`pWSyJUZ_<<%1s(csxOp_^+TR?z!66AacXmW~*FMy9V znQUnR5i-$tunHn_0W3+77s5JCrjyo!@v%{pY0p_O9zLeY5&ea5C_yfQqna$J{9^dN zCT~z>EBsWGM^$+V{7RF_(<~T|-qYk&s(d&6S(7DIUIw3Na%4SAAsw%9G#|R@STLRl znp}XD7K|TD67Ww!l_sB6`72 z#94H8?=!@N(^)Y-`@^-QiX#HEnWZt9xy0d!yWXUt5G(?d`g?5}P}Ac6Pekx;M5ryJ20`hHcgE zR(ZFo#o4;E%d@%1>3yU({=SoQSHYU&%h+dH;C;_g%j{XnO;+g&d=wV(mXoCM3A-BEm# zTW(H--QCD&ZPnNgd^zciRgi9+r?)9$=!glbnwvZEZAWc^prgI5&E2F~-MtG9-xOCv z9paj}J3DuFbVu4ymBTYlB`T|GZLQncUDFXo)n2GY1iY{9HW;<4pSBe?VE}cKQEp^V zxPq!rkkRyo!s+hp&M+5wgm>=+q>W7|5pRny;I?``|MUY)q)w1(83 zit1C_~g-^^8j0i~nzfWFJ5- z#+KBt0N%DD@;#W(N1RT7;z?Tl0?JVz-FhfLK>2Y1iiN2!0W30Lj(X_4H*5#+XnCua zcW61qV$w^uf9fA>UAuR5%Z-?KcSdrLUc%SsZm>1W-7?r3(UWadVM`1@HhfV}tXG#K zR)yZd#G)9+Mx+>WOI%9q2bIQ0s93xB=)}}&F)CIY*`^WqN>q=Vh?zxv}JG(ef4s6EknY6C-B~X5(iJ(W7Xr zM)xE%7)F{{eNBB_L`^h!G`7arY=lj05R0|37S+*+8>_?7#o}&4bwcz_RIbP282^@N zoB*jYIaX60iOjd?jK%0gC>pI}Ds&Sj#OxS+o5*czYTvN~Z#rPZ?~FFNySvldxU<{c zg^}_9o#;ym-5Zm%7Kv|)^sO(F@-ZVGUh~w%@(80uUk2z-{Ev8aX0ZLzyN#aoeygz} zp7#ZmU(rdJ>pTg|^c9eDN-yU}?)Ft!HsNE$hsN~)KJoerQMinCdLkYrGGaW>j2)$` zNaRQF_g@%Z?rnH9=6HRD$a{DieJ^8O{5*b~ADai=?e%%Q!RVuR;pyymk>ULkd3LPR z6N+lOg1_OfYPKNg)@?MOxBI6_R5W`!C8|BG3 zp000z;r#}A`=;UjlHt|ky{m8<-v2PX9^}!xw4TU*l*X|x-p=Fs5kId&jO%2-V z#Lwe0&V$}1X&&@7R-eaaMqeB16A;&vu8;1H@#A|6dAT|XbDj4%!#i;s-g6A^XUHSF z>Pgqv&+vYOJer4|bl$HS-tTY2QyAV~Zo{+SK8&C54dl^%Sx3~$wKcwc0A)yNa3>GvB9uNiq8;&{5>_c6Raz(7+yW{&=sOdpT}y3_b~G4Talhq%GrJw{(W>eJ&DeQnnD4Ke!mp+1VsdeZg1$MC+1yy@ZwU1n&R zXzY|uAP--OqlqwjW*`q;t3wBh@K1vAe^nq3CCc?Nko++6j^o1FvAi1}ng@-8Y=`=y a>3=aOpNOl__03{U zBy6;aJQzcuiKO~s&_}hRm=Gmvf)CzeS_IO*?TgXyG}x^+lvvN1oqs#5ik#&9=l1>Q z%=vGb^WDK7hG7ULhP04Xi;!uH8ZmaLqJ`9vT4D;+OAS(^bcqb-zFzQ!7`{d!srnql zkM)v0tnXmqRhc-ZmlqT+!0b61nhF^m4WY5#>O9F?0&uY`E1o}oMH~~ThZ!VSEE}2e2CyPq@cFMT`VLxWYYN%+)){x;ihs+T3r5ep z$+Hi{zkjmU~bY{zT2G(9PeLd{7-u%@WpXE~s@#_N$ep>uY-q zJ?ncmYG2nj+bPMCS=mp%kUn2l3bz(4e6u*5N=7IV8}% zj*wN2!#4yg21IG654`MN!7KRhzhRG*e+Tr6-#~f=VK3j(`}`4pIF*Xa{K-_B?@A~5 z?nFc!9Ti9UL+Mmhl;u=f<~vhoCsiI1b*vjVHRD7s} zvXwMcI8s@LuT=5pN~p?`R>W7A+3QFUJotUMCw5r>W15Wz$`0!*YBpB3!}^>8NeQ#P z28{C+U^}TGZ-bXIHLbc)hR7d$RNF*^zjBJWXbR|cJUWsL*($Kh^5fcQl$ylZ>ArHr*r_f9s z5aZ!-)P}@N5e1h-6ym939K1d8uq*|`88I0hCtZF1LupZt4r2wJhV_M1@?`8qZ8pvv z=^N^QQm`9(!!yOgLBzhT+X%ruL5X|MK10Y`S{!eH6^`8tAh&D)U9;1gP2BQ$A`^~) z%%qD_q8eQG3~`T!GhyP6$TD%G!~KtiE4rZ({o<6I+7h|p`6>DSWwG?J$Chk$VzKal z?#?RkiR=1Qux{dxrV!LYtnG^ zwJXPA4y5hCxbOdm+Xa~Nx;*$O;h8`Zfc3axu<@Q!qPU~r(BsCy#`{Z&;_xi$aaX{$ zQ4mOqlR(Fp%?FIs0p}C@vIFA_i8!<`0PFL805-k@lxV&W!J)@Zf`RWLC5n3=9QwNZ zpcoH6tc&-8*8K@|eZCghDC~_A&G$Vx^!biMK75lfANEc2ErPDkHwpPBz(taq-PQB9|3m}95tXf j0b^b43%?CQB{~iV`(DXf&9@GGdfYkaqm34W7*+oU%=s($ literal 0 HcmV?d00001 diff --git a/.pio/build/f722/firmware.bin b/.pio/build/f722/firmware.bin new file mode 100755 index 0000000000000000000000000000000000000000..1f82f8cbdf5fd6c6e65e2a08dfb234ed9c7428dd GIT binary patch literal 25708 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 F+5rqToooOA literal 0 HcmV?d00001 diff --git a/.pio/build/f722/firmware.elf b/.pio/build/f722/firmware.elf new file mode 100755 index 0000000000000000000000000000000000000000..a11c4bd14ce9dcd0b01672a94bbc2228a5675f3b GIT binary patch literal 155520 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 R4n5BXulT-{Sbvn>{|3!)X@39! literal 0 HcmV?d00001 diff --git a/.pio/build/f722/lib737/USB_CDC/usbd_cdc.o b/.pio/build/f722/lib737/USB_CDC/usbd_cdc.o new file mode 100644 index 0000000000000000000000000000000000000000..1fbf3fe2166772577cc773c53a7ffbc73c0cd408 GIT binary patch literal 5860 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/lib737/USB_CDC/usbd_cdc_if.o b/.pio/build/f722/lib737/USB_CDC/usbd_cdc_if.o new file mode 100644 index 0000000000000000000000000000000000000000..71e9635cc6cfda30b117f686707f3d8a2754ed8c GIT binary patch literal 3716 zcma)8U2GIp6h5=FOS^^2w%giL5XLUVV(ri_g;o-iZMXCvB>fSSMwk7WvMakgWoAl> zF@b~^9!SvO14e!INfR2WFH)QM^MWrn!3STIH;jo9rHOkDyXYhyCvDVQ?e?NTGV*irj zyB1n)o{Z$9(I91VSrylhj@}rVKNG(9tFD*8LmN@G`Z3 zbHAybl+dc1E4<>Zk*?5VHEt`sH`usN?QL2*AKy41PiNA38JgEqJFz``;a=^<8tAJd z5AX20@h;sp(%oHtJpC(MC+mh$&D84hkN2CRbIV)C!&zy6rZap({)r;rAr?L%DZ$&) zaH(=-c=gx*7*@0v>a|*9~RBC@6;uDJ_%HGRiSS zPiv;B8>Z6N747cn>pI=rRY<<28+(;LHLCU~9PEC%yI1Kjw7ixywY|#Rz|@g_nnTgm z*OfAo#dKCNv@HJw8K5XI1wAnL$vyFdU0FZZ!O!Xdoy^W8RLG@*e4H@VG5kXNBe6FV= z)o)v-5FHgs8z1uELn3QynHoI#2AXpayk8RXZjrH@)${Z2Rz#+-Cm*gPVaeFZyc6Mf zEWxkltL!wxWNP;0o1M`mB~y#XZ}s@w=xtYoSAW^#f8z1W2QuP}zv;>U0-tN=bu?ms z|8o3M+pj102gKuB7!2W+HDEn^9G_JK-dBH>-$nx@?r#fRdF zA#JRfE17YB*c4zF&l$O?VXEfWkF|(#-Of3yA&d+NGu`?r_)S`Jdk=7TBmf90N z*xO4y%L0y&gub8^X?A*WD8Z9WYgUCo1f6+~CDW%gi$(_~6UUBEB@P#psk}CLYIb2D z&F3CvXU)_Q&aJdo#aFH&oz>E(hIM05*R8ys%%Db|at0@!S-=X*MTm$qVL3jpFPL`W znVgw43JF6yy{MU%9rF67WoXGlu6WYf58n$!+%Z0U;D?~=_7N^O=x(AnS@)FA4$i*| z-xnczpYC8CG>=CtR$;8lnYU-da@iTH-#N}tUK)}x2Stt%R$ffm*bUw zwhQ8yp;kAK{en~`uJnhR)(Zu#h_{EUSWQ}%kxMOFnu+)Ql(HQ-{**U4c;0unh@13z z1Q{o8QZLRq4hXGk@BRPbxZk|&2YJx9GtTY_u?L z=TcvCPaenP=9__k9gh&fH;sUs?-uxCh%p~byU&@gfXB^O3x{hIBKUF$xcQnen7=jV z<2d7(?>rtiUkpwjF(HEQ9R%EbLm15CnU8OC!S^w2H{YjlMiCPt_&z|u%{K`$1u^F1 z+g|WpgU$1Z{oP=4ejE|z*YKYPck2l_Q4>=N`?n|H#9WLMHs5RBc}32R<_m>B`0t~-D{x=}r-=K%D7LCsQLWKRAgX11y2?BSnWZJ)s<0pY1 z)V3f}7lFeuT^7c$utusZH{e{uK>q%54cPUCpm_~qtuQH%gMn)iB250r<;GpYdUcUR HPMH4zcL4;4 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/lib737/USB_CDC/usbd_conf.o b/.pio/build/f722/lib737/USB_CDC/usbd_conf.o new file mode 100644 index 0000000000000000000000000000000000000000..f11579d7eda23e6beebea66a8f4f769210d3d667 GIT binary patch literal 7692 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 Mzi_@CDS*KJ1Hz}`p8x;= literal 0 HcmV?d00001 diff --git a/.pio/build/f722/lib737/USB_CDC/usbd_ioreq.o b/.pio/build/f722/lib737/USB_CDC/usbd_ioreq.o new file mode 100644 index 0000000000000000000000000000000000000000..70d3279f44370dd0c059b1aeb45bff3c51e50325 GIT binary patch literal 2332 zcma)7&1(};5T9+*8bd8LsUNLSwox#GS<^HUKQ7kTRIn{2RS^7WH_4N3X|i#5Q=$mH zh=_Rf=1mWtJrq1xtlbgW(u070gDDn z*o^=l_xeb0);CEw0*4`9=t&H2Y;C_tL<=ys^{sDW=jZPo&<8go8}S0=T5)7EUI?`- zx3+JNWA*m!@xN6^Ho^%wPQ1f~kpgo>HhTBSBKiTQ^Z5&Ua(eEDe%-cLUHzWz=#x%W zpQ@Hbr6MZ&yknPz>)MX1=Te#UcrJB6o2r^CwsT6)85v_-r)2tkI;$rgu_{bgoYHSi z7H7|hfFhMkl^nBHUe+D4X1SJK(=%t!X42U^Fqy%bn8GYspe51m&D)MAnyJ|w^c~nY zyT2zE9?}kJM?y!nVQoYk4JYKm`tyX2S%=}rPLTFZr~?HEL5~b$98%&i40L3|9Z?AS z6ueKtBMKf-@Th`E6}(@;`xSgZ!8^MR!JvW@s_Jc|0&GG!&!cx?tdyG$?6w4XqpE@7kVL zcL`6axd$^Z$5C}JB+g(w-C*bV6kHmlQMRj9ffF_GeKAbWbF5Os6Rtm+|N1zFRdhD_ z*0$c{-KG3Gj0JW4I;eHTL2?q6e!qX!rLjicm+l)2?|T{(`%y0iz&X4W#6N^e_k)z; zYp62c9LD}#K}*7X)9A~5mn1%#0rS<+m-*;U(@|q#z7WlfFp)d12!g#O# zo+y0t5+A*c%=bp&dyX;P7Z&dCH74Z#Zc2Rgk}}^X^yU6uVZ0aL7UpHXC5eyjCG&kn zU*>xkU}${d{=Q%&^DRq!G#}>sg+B4oxgmLvy6$_e55h=8_Ahy58WOVH q1I2Yrd`CTmJ}K=>`%`axmeGYJ3_g<+2=mc@hFn)if;fYSvHJ(cY&eww literal 0 HcmV?d00001 diff --git a/.pio/build/f722/lib737/libUSB_CDC.a b/.pio/build/f722/lib737/libUSB_CDC.a new file mode 100644 index 0000000000000000000000000000000000000000..e79f38b6a4671a770c9fac27475e06a6fcb2b3ab GIT binary patch literal 35470 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¨$_%D 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 literal 0 HcmV?d00001 diff --git a/.pio/build/f722/libFrameworkCMSISDevice.a b/.pio/build/f722/libFrameworkCMSISDevice.a new file mode 100644 index 0000000000000000000000000000000000000000..ed9304d585b3c3a28b6e74ff0608e4d33c4914b2 GIT binary patch literal 10346 zcmeHNeQaA-6+gC>xN$o6QOC}QlQ{Kkrwv=Tmlyk`_8P~T z?R4!l7!uPcY)F$pY=TK37*L@h4aUbnOq)iLDi~75hO`Y3MM4@vY%0qnhB~eM&hvZD zy(jB7?H?qR8$JK-@7#0mJ@=k_-~D*mew|s#6>ezh_Uj=SiG)IXBjLV~-``^=slR@I zs5cm{=a_CGqCC+hKV5zPSADSkWg`7KY%I*qAFy(@a-~XfYt~$xs~IEae16WVP}-_m z%WNWfLh@d-_y)G_LhU zEIJW1vQw&tElN*mt#D*o3v5{?HmK(1uH9>BhGY}TpfQjhGZ5LU>e>nL9HUm5osdlr z8?pUKJ5{UJPSqU>k=BRcTHk?deU=Etg2vzh)tI^{EkvP}S`cYknN&hE4_vclG80W_ zH4R&`Qb)6x`!Tr3(EEkQdUVdLlvFGCXNQfU%!)aHCilC&9@HwcQ=D$s>a-KoZrA$E zPSv|z8Ilpzq@koX#4_<@68)`AT9l;?5%ig6$t1c=tDFT|4wTSm#G_h0kZESXywF8v zq$}5~QuMVBQ{iyTj3C}^&=hoI(EEIu`>l$bBps2+`#D^_f-oI5hPkT+`5rEjWMu&}d-^82S-sx`AxTU;=zwNh_r7Q3%w#{%W_N#zA$wv)zo`x%L4=ddA?<|Wt^_?oZU3t6#CY{`R7@a zpM_z)lx6nzE6efK*#Bb>MEz)$X_+%c@_Yo*X3Vvkb*w8Hp*5{*lb3iQyLj+vqm;;p zKQ;KMNu@|_7CD-2jV%qWW?F~%Muqdx|AfLXL;Na*H=>C6Xf0i-3c%HQMBr-hp|)NK z`WwP#n>VP)?V}dzTTY~Qzbbh18ofQ61@9JoSa3t| zI|RR1@P`Edq2Rv}{I7y93GT%bp^m3^!FLGWD|k%sjNm!JtAgJr_``zJ&KixE%L}pc z!tuCSGwppc3xJ0k8{^y&XLoKJU>I}7nVi9u8fK+p9;cF7oTt@$EceFDzBN!!LM+gZJuJ`;u`JNe zUpRZN-eVDW%j!LrI+RxLu~zS~lzS=djz*Ddw^NE-zXaktQB8C89_s_%W8qN1=YmaS zpK-k%WS?!lIM8ljIgZ|qu3_9k)Wdj%Q}0fv-YcDY zuX5_$<<#5h)O$5iiu2)+o@LxkG{uNQ4>5KTO*5i#dB$#{0wXG$V+;~4Frv{lMjXhG zF@}lmX52&cSwyq@Trj5iQH%6KEu zNydFdk1M0ARAnCLX)2+?zl38FKMqeL$-juE}c zI8O8@#w5{M#tEXoG43b&J7bFIpNuyVonuTBy}^hJgf|(pL~k)p;s+a2?*aIg@gV%l zI0e5lehPkNycvFF#D&8a#zRDxGu}$%XS|JQC!;~s$v6$aGn()_;|%=Cn1eqV^YAC5 z1%EQm!k>(X;ZMc_{K<$5i~{5B@F(LD_>*xC{$wn{e~k0+A0sX}PB1ROe~fp)e~cCQ zkFg5BG1lN8#zpvt@hJSmcqjUm@fi9gP(5C%nKQszrH%zRRS`Rde`A` z>%|Zwv=t+(9`1t9c9#I%q8Z&fIr$Ng2iMl$ljw50yfz@W)$Kb(>6#Xz??cZGZh4$X z)$7MQ`ZKN)(ADb>_4?KDUf&3UeeeGp!CQ3$8s7*$jIRWIv%h(COXAA~-?`u;-h~&96Nkj( z^);Ip`=?g)34%-hSAtNoEcC=kS#lwhQ1Z%^3Yi3x3)RqJa1Ets6$mQzGmq-&;P&gTmL zigmPDEtco~p*?#-J>gp^8iF0pg?A^SD=xe@Hg$L|^=$TS@m%KF>e<$`!*w1vzzM3T ziT-uLl{2oq6IVwXr>i4{d6V`osE@wo68X+teOK^I%WQzWwD$xK_+|Z~; zIE}+DJnYl=(z^yavR=0?BsJc(QK8ol&SS_8JU%#J%Vv+teM}I-Fo4GryHH(cu(i?J z@ff&U2BM8PuhndyYt!S1b9ruX+xrCwRJ~`w)!E|eeZ$e~0dhEv=N>y&|6x6TPU3;- z3w0^cFoeA>0lMWey0&rh-4O5|tQB##liS27*Q4i<=`iGOaLbeHQ5;4*=_&zTz5fE# C!apGZ literal 0 HcmV?d00001 diff --git a/.pio/build/f722/src/balance.o b/.pio/build/f722/src/balance.o new file mode 100644 index 0000000000000000000000000000000000000000..212bc7ef77382545d36c448a79a9f4f3049e20a4 GIT binary patch literal 2392 zcma)6O-vnC6h6cIK`1C9r9T>+b}&4&Z+tu<{HQ69CznzSv`w3kSi{Wl2Hzv^&zYgY zE?WACx~MT-8yBVO(nON7FtO1{7cS_6m0cN#3Fz*z61ou2nRoB|85eq!JKy=v`R=(t zbMLt|dVxuj1foe0f(k=#y&DPix)6fr;8_3#PRF&n{Ia&L`Sd~|ZUoK;-Yw`;#haIx zjfC>EUS}+SoF4;d8Ugqv7XGt123>yE%v#tWYiEal{e1|b3!78p5!b%WAT+wUb^t(; zsiJX-aEYxQ_-i}`^aNec$T%qi>=L`D4ZAtIS%H5c zc4zBhxB0GmHXrRb-FtnO&r$t`zW%=HA>srkSj4AW?duQ|XT9Gr1?*3E)^ zTptVW0qf=pSnXpWH*&A=V0TA*ybC`*-q?6MtUP`5-1d#LTdFw%zkc-=z|%PP^?|j( zqMw=H4=01;v`3mPvZ-%Y zeID+IBQ+jB-F|!_qWOj4q7MQdeZbXEm)9Ba=<7ZDdRO0BR+S!~pgw5u=o>`HMISVJ z_z`#>Jv4m;dn@>%qe{_&cG$!50+k!Z&y^Vf@v9zgczDjkZ+iG0;4JiA06i3r2-d!b*m@XzE6J=7oGhcTCV7J&TF?`et-1Q??T+n<$-M;|l;U5w-!m zN_Z52?tNoB0G&PYcQ~Kq{0iq9Ar7ABJWqHG;5z3^96#asIU&aH6XJZ22#*77@c0vs zzY(HthY)r9geL&}_>X8^jf5C)=e&dS5FxHNLWufdLL7gd@MP(}kRMe0ql}{)h>lgl zq_FUTJD}nL>Yy674JtWQaft3uRk4!Py7`I!J3yygE9FP8&gL>1GmBGUF;aEMu~No@ zW7@d5|JPnb8Ey-LT;A&$CMwA(t`n8StD_v$y0AZk{l9c)P~)99f0V@WEaP4A1U6X|GO*RWU5`veKSNzp{UX>?TQyM_lu<0&6iFOe^c zc6B}~y`&LMoZm7!NGJB#gn?T^#A6iy3_G43Jps4fLERgIAd-d}p~y}ACnQC5Hly8& joz~Zao%SI91)A_327VxeH<6F(X|*na`~6ag5QXj^eh$hU literal 0 HcmV?d00001 diff --git a/.pio/build/f722/src/bmp280.o b/.pio/build/f722/src/bmp280.o new file mode 100644 index 0000000000000000000000000000000000000000..37b624da482f736297c1de60dd065cfa7fb2e342 GIT binary patch literal 4116 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 Zy6_1PmC0!fuSfp?H_t}!ij&ZC-XCL|)29Fc literal 0 HcmV?d00001 diff --git a/.pio/build/f722/src/icm42688.o b/.pio/build/f722/src/icm42688.o new file mode 100644 index 0000000000000000000000000000000000000000..eabb04e3032e651fe7fb56c0aeff558039a1e006 GIT binary patch literal 4000 zcma)8ZERE58Gi4Fo!|j+11(8N;U+e%Da3P}WC0kt$UvRq5C!wNg{{2R|k?(tgm;Z3<1+U6pC}8=ePP>q@jEN`p+!eko|&f%^{&ag`6>lQ7tfJ;g>!?3x(oRcGru(^U-DGsPaA7Uo$+5Yb94LSi^}TU zP}6w-q9nI1EDkm$e=*ZEE^ncra!H0wdRe;gF|@OV-ucVE6b%L@_G3;^MQ{R zlr9gR-s@ssf%u|-t#ax35bS^bXu;FPR&I~)d*Aq3@9a|i#Uq)(a;f7;g8QEsrO3cn z^QW&b{h6*W9qM?l=9r}1_O9L5&p#g~6t*u5{lOef=u@~ZfvR2zxiSfBs};>+`6Hx}e*r1dRm^|c!d-ufF0wH-W{ zniz$?JNGB;Gvns#j7u%!Vm(vh*%vcWRG?Ghsm3@i9s153$3AaRiE(ATPeksBH43e? zGzs0%veDAbmVZKMlieJNxqA0Be*E5@dqMS|=hU7~e_+kfQiAOl3?kNAtaj$w=Zild z40&fU{!6*VF*VhH`_|6b=eMW_HN zzI;~OlO5AjDLthP=W|KDP{`#AT6bGC(%#*6va>Cl_(3keRqGB%!|fUyBRe9US}3ni z=!t^9RXf&q_~18ni=wT&Z7iRdOs2KGemYag zMk}*{oo<%x{nR&Ju8CKJTU@3O!IhOgvKwxHA3$Cm212HdOgH&@L;2D@lUiEebWb zA@Un(&}HECA~V>xtac^mJZ7L3w_p3saeP%4AQC6wglSh)yK+kxc3g4fP!u z864glANgKBQ`CnulfrUjc<;zj+!lpwrg&IS>Y3BJu$ZN%9E zlmqj6BITr=(2FBt26z>*^YS+QbD%Hd_TiJb2?xX0d@_7E{7tOe;bV>e6J7^j)I39S zD`CgYxQDE`N31wLBkYecMo}HN^eAia{Ec-N(Z5-PPsRTD)}gTmuD5W5g*UNAc?4P4 z5OrGqM=gK9g@-IWY~jZ(J!CObScCsH)|lVx7XA>L-{(`-TZlBC zH`WJBCf0|~4ZjzkUG~qgMm(QQUT2Lp-}2$Y*=#W}23^dXI&JrG`4=giN)!_m9xD_m zj896KjbW6T1MF(6uyEZu22p_y6t(EUa(#$GTEQ;rW(B)bK|H^(S>2*rE^&d(Ds#G` z&Om|0|C7xO!aY&PDCQ&$1nD6|R5Aetf3gd{;mcf=%2R&^BKV zeK+4l;GJl;*nHzKxcNQ>p9UNA@psSW`w9APzIkB2-)*t^eh7n`Zy9_yVPii265D*Q zpzr2;2Zi)DY_`~ZFT>#G`w+l>UtVvU?@jdGd=n_JpiO4QF}#fC=353}9-d!4n$7n| z^fC2voxTLV6tFEE$MOkUb)0Ki#GE*8euX%9z1TTltPp391(%o~>#xx`C&B>2^E+pD z#gl#96g=RXvR!o`>#%_p!;oX`v&?um;z~&5^Uq`O9C*IGb}*Oa1KitxC?k`H;eBZC OI29kabv%eAcK5#)d8pg~ literal 0 HcmV?d00001 diff --git a/.pio/build/f722/src/main.o b/.pio/build/f722/src/main.o new file mode 100644 index 0000000000000000000000000000000000000000..0c477bddc73e7d750173de8740a1021e6c359274 GIT binary patch literal 3624 zcmaJ@YfKzf6h6x?6qeF%>C**qSZE6Z(`BIrYplS+lr7*QP#^WN&dv_(*xjA&%uvBb z#YdX>L(!~h)W)R#G3&pg##ECAqksHEqW?7U(Zs}ts0k|3wm-yk<^j`d>P_x^=R4=z zbI*Ouz4y6+VZr0^fKxos1RD&XSZP{HJ56YU0Bi-%;M(8+EW#qGNNQVNiGP1_@z41D z;-BjL{17yLac#8E;U|>7RfwDr9Uj<=ZPuvP3wH|DMUr-e>V-;EnnS79l%5^(>@V3D z%*0p9HwTJ+D|2JPR87XaGB;jPs5t-BP%z!M+S3<&q9z?Y=UwfI`V0Q^@zuGGrR9K* z=v`XgCB;|2(U+F@d{NO*Q=ooE7Xrn=xovMOEpMM*THZZCI#~GUDq(!pvwhRv+G1@X zz5>!+h4|`c*p@r!Z3q>hp~GzN6UcjOsH7pjdg1=6*D8w_g#E&g*NoS(zKeBXX}J<@ zbK^_PTedd~6gMP{#O|XRTN{ZDn>ZXhX5ygvB}>m=m%@Zp%gk1RBFVcxv1Wzjx2{3B zRA^a%hCuOUlu38@P;e%+0HHuJm?wVZlj1<>S4Ck=sC?gw&{DI##sBR)*LuQG-zs=o zHZNYjJ^|%sAFV?*Gx~?WphwHMz;}O5UJnb~-rQ6`pYY}Dt@$!@)D-#h^+Vy(*KlN~ ze1+QL@cakXDq>9T;~QsxZxY7qVihO)PV`bV z4@ckms~tksF^XyV{&W@h)NgPFx=VT>4?VQMZdC?tgIfLKVF0f8Oh}vw9p0O24T-Zh zK5gNYt)H^>Q?@>DnX?w?1kd>4Oi0!=TZW_2=wYtu=zYhz302ML+@z{;y;_zV$R_1f zN=|X3nkvbjd4irgU&#IA+VkU9`QZ08TWx~(rav9P3ngwdaxcSuP=1rf2Xs7a z=zKR>y-?<|k*SQamoxTqGv4re8XJ+Rp%?s2d+Ts=lwQ~jTaeJ0H)E{^A8?3H382v7 z5JckLSjnFPchtJ_zMhwmEmtQ{C$RBV)&N~|C-@HF#K1B-#|`l z{T;5?Huz($bbYT`>$`>FwG2PN@Ou~zSy9RH5;Pjnn1cAk(S$Ibh>hJpDCSZbS%bme z;lyaP->pjLr4)?M>Jy4|GU4`%yD52;b5pMQyP<}6y1=uXhzg^OBL;pCLDDvhqg&kk}cD?A!-Kb zhGXiIb#wi{Rupw^(>}mr)swu7c<7}u$aV*bqUhP z^<+Pu;m+W&;l>0^s(Brxl$5Y~PiXR~X<0W+m2P0(StU1RGR$q=iu;sKz>;dLh;`fW zL%0JVjOgD3K<_gDZ2(6IgJ7Otgkv^;kFW;dQyV`gtOfX)@OFS8{tx~-fJVYQ09pw- zj7wM#aF{TJ@d+CM1j0suV}yGFMhW);JV3Y~;BmqxfFxlvz-hue0nQS(0K7@q3h)tO z8~%rcI{~f`?gF6y&(8zwAv^%U6XIYy39;XP+x`$@Njt!!gm_UtL5PQYiV!CyO?VI> zLwE=vPgn(D*f>Mjg_FSRvspt-A{v^7X-C4#)&L&2hX{NUw=<7dI8RFczyI}yjs251 zEVz3#V>-{%5rM%}ifj_Cn?m_1za4SFBkJQH9FWtdTp);2XEp||sKym%0GKjJ}-bEzTp5jq1PP|E!-SPU7)1B=UCw3AQ?s%7w z3}QoyM{%8avnW$MdZSVK5@StRqWL8o)mLn!`Jqya6ZxDanqS9{-T`RJJErqU+;0`~ wqeAFP8@@unIjr>Vp?ReI2x$zcUN57Y07hI5op^Mlxc%q>_TG9ct3RUu0zt;sCjbBd literal 0 HcmV?d00001 diff --git a/.pio/build/f722/src/status.o b/.pio/build/f722/src/status.o new file mode 100644 index 0000000000000000000000000000000000000000..a6a8961d03507ce11902bd89ca19aa3a7add37ff GIT binary patch literal 1896 zcma)6O>Y}j6umQ^#7=0zm{b(EDz9!N98?dkNo9i&it{mXXi|p?R3s>2Y!9-V*b`-d(J)YzR&T^ znR!D|6q2S;nvM`re88^^jQb%?&(X6qdMUX)*;dueZhJOa-PlYnm-p$N*xi>et6*s~ zYn1ob=alcuZ7rt!m|RYlC)=8ute#q)c`|Z$%!stLNc6UPOZ`bX_h5HmTDx`l=Rb#I zM%H-n`0HMI|8Ez2EN&j`?fn)_l;*c7rKGs;m-mW~ zH*!B8Jl<0eUYM?)kN!$2?7lcu+S)1jy_D1+k80<_(fbdhkikW7`s@1HTSaj^F<+`@xihL%Qy^zm*HlAsk*KKD^ zK`@zpBRekAjCzY3!q;f_}bw3acVC$wd`u#9qgWpI` zl_)}LcNsX+hcz1RVKh1pe7nPGos5$R4fg2=ef@MtHQ31leXLI(^YyikD%QyYeeY@_ z^bEyO;62}gCrG2yh|;+BssxCP--5Hg1W#bS3y9LVeihF3Iy^y`-}Ovy&DEd|N| zgiDQ9!=qAhera}buDmqYgRVLa&suD>q_$$)-crS~R{a6f){1#Umey8lre|R)x&j}5 zp6KH+UJs+kF+ucI7&pSmC&4_gd3b~<8DbG)-Z$5?A$}Y246q3KkHR<^@}#>rnx0uf z^qe5pWrj!Sk&cy`q*q**bUbaHNoe_Sg41}4J=*tErEuSR)owPe7MkM|(M`{D8kIHA zar#RzPpX3}D@VW$utYPCQ?}l*!;1iJi{}PAu iyc~IL^3IUb4*>oL!vH4x;nV5St)s!Wz9RUMx_<#zS2@c7 literal 0 HcmV?d00001 diff --git a/.pio/build/project.checksum b/.pio/build/project.checksum new file mode 100644 index 0000000..384b04b --- /dev/null +++ b/.pio/build/project.checksum @@ -0,0 +1 @@ +ee8efb31f6b185f16e4d385971f1a0e3291fe5fd \ No newline at end of file diff --git a/flash.sh b/flash.sh new file mode 100755 index 0000000..c6ee599 --- /dev/null +++ b/flash.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Flash SaltyLab — auto-reboot to DFU if serial port exists +PORT=/dev/cu.usbmodemSALTY0011 +FW=.pio/build/f722/firmware.bin + +if [ -e "$PORT" ]; then + echo "Sending reboot-to-DFU..." + echo -n 'R' > "$PORT" + sleep 2 +fi + +echo "Flashing..." +/opt/homebrew/bin/dfu-util -a 0 -s 0x08000000:leave -D "$FW" diff --git a/include/balance.h b/include/balance.h new file mode 100644 index 0000000..ac30a20 --- /dev/null +++ b/include/balance.h @@ -0,0 +1,46 @@ +#ifndef BALANCE_H +#define BALANCE_H + +#include +#include "icm42688.h" + +/* + * SaltyLab Balance Controller + * + * Complementary filter (gyro + accel) → pitch angle + * PID controller → motor speed command + * Safety: tilt cutoff, arming, watchdog + */ + +typedef enum { + BALANCE_DISARMED = 0, /* Motors off, waiting for arm command */ + BALANCE_ARMED, /* Active balancing */ + BALANCE_TILT_FAULT, /* Tilt exceeded limit, motors killed */ +} balance_state_t; + +typedef struct { + /* State */ + balance_state_t state; + float pitch_deg; /* Current pitch angle (degrees) */ + float pitch_rate; /* Gyro pitch rate (deg/s) */ + + /* PID internals */ + float integral; + float prev_error; + int16_t motor_cmd; /* Output to ESC: -1000..+1000 */ + + /* Tuning */ + float kp, ki, kd; + float setpoint; /* Target pitch angle (degrees) — tune for COG offset */ + + /* Safety */ + float max_tilt; /* Cutoff angle (degrees) */ + int16_t max_speed; /* Speed limit */ +} balance_t; + +void balance_init(balance_t *b); +void balance_update(balance_t *b, const icm42688_data_t *imu, float dt); +void balance_arm(balance_t *b); +void balance_disarm(balance_t *b); + +#endif diff --git a/include/bmp280.h b/include/bmp280.h new file mode 100644 index 0000000..82519a1 --- /dev/null +++ b/include/bmp280.h @@ -0,0 +1,6 @@ +#ifndef BMP280_H +#define BMP280_H +#include +int bmp280_init(void); +void bmp280_read(int32_t *pressure_pa, int16_t *temp_x10); +#endif diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..28671cd --- /dev/null +++ b/include/config.h @@ -0,0 +1,143 @@ +#ifndef CONFIG_H +#define CONFIG_H + +// ============================================ +// SaltyLab Balance Bot — MAMBA F722S FC +// Pin assignments from Betaflight: DIAT-MAMBAF722_2022B +// ============================================ + +// --- IMU: MPU6000 (SPI1) --- +// SPI1: PA5=SCK, PA6=MISO, PA7=MOSI +// WHO_AM_I = 0x68 +#define MPU_SPI SPI1 +#define MPU_CS_PORT GPIOA +#define MPU_CS_PIN GPIO_PIN_4 // GYRO_CS 1 +#define MPU_EXTI_PORT GPIOC +#define MPU_EXTI_PIN GPIO_PIN_4 // GYRO_EXTI 1 (data ready IRQ) +#define GYRO_ALIGN CW270 // gyro_1_sensor_align = CW270 + +// --- Barometer: BMP280 or DPS310 (I2C1) --- +#define BARO_I2C I2C1 +#define BARO_SCL_PORT GPIOB +#define BARO_SCL_PIN GPIO_PIN_8 // I2C_SCL 1 +#define BARO_SDA_PORT GPIOB +#define BARO_SDA_PIN GPIO_PIN_9 // I2C_SDA 1 +// Magnetometer also on I2C1 (external, header only) + +// --- LEDs --- +#define LED1_PORT GPIOC +#define LED1_PIN GPIO_PIN_15 // LED 1 (active low) +#define LED2_PORT GPIOC +#define LED2_PIN GPIO_PIN_14 // LED 2 (active low) + +// --- Buzzer --- +#define BEEPER_PORT GPIOB +#define BEEPER_PIN GPIO_PIN_2 // BEEPER 1 +#define BEEPER_INVERTED 1 // beeper_inversion = ON +// beeper_od = OFF (push-pull) + +// --- Battery Monitoring (ADC3) --- +#define ADC_VBAT_PORT GPIOC +#define ADC_VBAT_PIN GPIO_PIN_1 // ADC_BATT 1 +#define ADC_CURR_PORT GPIOC +#define ADC_CURR_PIN GPIO_PIN_3 // ADC_CURR 1 +#define ADC_IBAT_SCALE 115 // ibata_scale + +// --- LED Strip (WS2812) --- +#define LED_STRIP_PORT GPIOB +#define LED_STRIP_PIN GPIO_PIN_3 // LED_STRIP 1 (TIM2_CH2) + +// --- OSD: MAX7456 (SPI2) --- +#define OSD_SPI SPI2 +#define OSD_CS_PORT GPIOB +#define OSD_CS_PIN GPIO_PIN_12 // OSD_CS 1 +// SPI2: PB13=SCK, PB14=MISO, PB15=MOSI + +// --- Blackbox Flash: M25P16 (SPI3) --- +#define FLASH_SPI SPI3 +#define FLASH_CS_PORT GPIOA +#define FLASH_CS_PIN GPIO_PIN_15 // FLASH_CS 1 +// SPI3: PC10=SCK, PC11=MISO, PB5=MOSI + +// --- Motor Outputs (PWM/DShot) --- +#define MOTOR1_PORT GPIOC +#define MOTOR1_PIN GPIO_PIN_8 // TIM8_CH3 +#define MOTOR2_PORT GPIOC +#define MOTOR2_PIN GPIO_PIN_9 // TIM8_CH4 +#define MOTOR3_PORT GPIOA +#define MOTOR3_PIN GPIO_PIN_8 // TIM1_CH1 +#define MOTOR4_PORT GPIOA +#define MOTOR4_PIN GPIO_PIN_9 // TIM1_CH2 +#define MOTOR5_PORT GPIOB +#define MOTOR5_PIN GPIO_PIN_0 // TIM3_CH3 +#define MOTOR6_PORT GPIOB +#define MOTOR6_PIN GPIO_PIN_1 // TIM3_CH4 +#define MOTOR7_PORT GPIOA +#define MOTOR7_PIN GPIO_PIN_10 // TIM1_CH3 +#define MOTOR8_PORT GPIOB +#define MOTOR8_PIN GPIO_PIN_4 // TIM3_CH1 + +// --- UARTs --- +// USART1: PB6=TX, PB7=RX (serial 0, SmartAudio/VTX) +#define UART1_TX_PORT GPIOB +#define UART1_TX_PIN GPIO_PIN_6 +#define UART1_RX_PORT GPIOB +#define UART1_RX_PIN GPIO_PIN_7 + +// USART2: PA2=TX, PA3=RX (serial 1) +#define UART2_TX_PORT GPIOA +#define UART2_TX_PIN GPIO_PIN_2 +#define UART2_RX_PORT GPIOA +#define UART2_RX_PIN GPIO_PIN_3 + +// USART3: PB10=TX, PB11=RX (serial 2, SBUS RX default) +#define UART3_TX_PORT GPIOB +#define UART3_TX_PIN GPIO_PIN_10 +#define UART3_RX_PORT GPIOB +#define UART3_RX_PIN GPIO_PIN_11 + +// UART4: PA0=TX, PA1=RX (serial 3) +#define UART4_TX_PORT GPIOA +#define UART4_TX_PIN GPIO_PIN_0 +#define UART4_RX_PORT GPIOA +#define UART4_RX_PIN GPIO_PIN_1 + +// UART5: PC12=TX, PD2=RX (serial 4) +#define UART5_TX_PORT GPIOC +#define UART5_TX_PIN GPIO_PIN_12 +#define UART5_RX_PORT GPIOD +#define UART5_RX_PIN GPIO_PIN_2 + +// USART6: PC6=TX, PC7=RX (serial 5) +#define UART6_TX_PORT GPIOC +#define UART6_TX_PIN GPIO_PIN_6 +#define UART6_RX_PORT GPIOC +#define UART6_RX_PIN GPIO_PIN_7 + +// --- PINIO (switchable outputs, e.g. VTX power) --- +#define PINIO1_PORT GPIOC +#define PINIO1_PIN GPIO_PIN_2 // pinio_config = 129 (USER1) +#define PINIO2_PORT GPIOC +#define PINIO2_PIN GPIO_PIN_0 // pinio_config = 129 (USER2) + +// --- SaltyLab Assignments --- +// Hoverboard ESC: USART2 (PA2=TX, PA3=RX) or USART3 +// ELRS Receiver: UART4 (PA0=TX, PA1=RX) — CRSF 420000 baud +// Jetson: USART6 (PC6=TX, PC7=RX) +// Debug: UART5 (PC12=TX, PD2=RX) + +// --- PID Tuning --- +#define PID_KP 35.0f +#define PID_KI 1.0f +#define PID_KD 1.0f +#define PID_INTEGRAL_MAX 500.0f +#define PID_LOOP_HZ 1000 + +// --- Safety --- +#define MAX_TILT_DEG 25.0f +#define RC_TIMEOUT_MS 500 +#define ARMING_HOLD_MS 3000 +#define MAX_SPEED_LIMIT 100 +#define WATCHDOG_TIMEOUT_MS 50 + +#endif // CONFIG_H diff --git a/include/crsf.h b/include/crsf.h new file mode 100644 index 0000000..36d495d --- /dev/null +++ b/include/crsf.h @@ -0,0 +1,19 @@ +#ifndef CRSF_H +#define CRSF_H + +#include +#include + +typedef struct { + uint16_t channels[16]; // Raw CRSF values (172-1811) + uint32_t last_rx_ms; // Timestamp of last valid frame + bool armed; // Arm switch state +} CRSFState; + +void crsf_init(void); +void crsf_parse_byte(uint8_t byte); +int16_t crsf_to_range(uint16_t val, int16_t min, int16_t max); + +extern volatile CRSFState crsf_state; + +#endif diff --git a/include/hoverboard.h b/include/hoverboard.h new file mode 100644 index 0000000..43836db --- /dev/null +++ b/include/hoverboard.h @@ -0,0 +1,29 @@ +#ifndef HOVERBOARD_H +#define HOVERBOARD_H + +#include + +/* + * Hoverboard ESC UART protocol (EFeru FOC firmware) + * USART2: PA2=TX, PA3=RX @ 115200 baud + * + * Packet: [0xABCD] [steer:i16] [speed:i16] [checksum:u16] + * Checksum = start ^ steer ^ speed + * Speed range: -1000 to +1000 + * Must send at >=50Hz or ESC times out (TIMEOUT=20 * DELAY_IN_MAIN_LOOP=5ms = 100ms) + */ + +#define HOVERBOARD_START_FRAME 0xABCD +#define HOVERBOARD_BAUD 115200 + +typedef struct __attribute__((packed)) { + uint16_t start; + int16_t steer; + int16_t speed; + uint16_t checksum; +} hoverboard_cmd_t; + +void hoverboard_init(void); +void hoverboard_send(int16_t speed, int16_t steer); + +#endif diff --git a/include/icm42688.h b/include/icm42688.h new file mode 100644 index 0000000..47e7463 --- /dev/null +++ b/include/icm42688.h @@ -0,0 +1,10 @@ +#ifndef ICM42688_H +#define ICM42688_H +#include +typedef struct { + int16_t ax, ay, az, gx, gy, gz, temp_x10; +} icm42688_data_t; +int icm42688_init(void); +void icm42688_read(icm42688_data_t *d); +void icm42688_get_trace(uint8_t *out, int *len); +#endif diff --git a/include/mpu6000.h b/include/mpu6000.h new file mode 100644 index 0000000..3f0bd4f --- /dev/null +++ b/include/mpu6000.h @@ -0,0 +1,17 @@ +#ifndef MPU6000_H +#define MPU6000_H + +#include +#include + +typedef struct { + float pitch; // degrees, filtered + float pitch_rate; // degrees/sec (raw gyro) + float accel_x; // g + float accel_z; // g +} IMUData; + +bool mpu6000_init(void); +void mpu6000_read(IMUData *data); + +#endif diff --git a/include/status.h b/include/status.h new file mode 100644 index 0000000..9badbb6 --- /dev/null +++ b/include/status.h @@ -0,0 +1,7 @@ +#ifndef STATUS_H +#define STATUS_H +#include +void status_init(void); +void status_boot_beep(void); +void status_update(uint32_t tick, int imu_ok, int baro_ok); +#endif diff --git a/lib/USB_CDC/include/usbd_cdc.h b/lib/USB_CDC/include/usbd_cdc.h new file mode 100644 index 0000000..1316976 --- /dev/null +++ b/lib/USB_CDC/include/usbd_cdc.h @@ -0,0 +1,184 @@ +/** + ****************************************************************************** + * @file usbd_cdc.h + * @author MCD Application Team + * @brief header file for the usbd_cdc.c file. + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup usbd_cdc + * @brief This file is the Header file for usbd_cdc.c + * @{ + */ + + +/** @defgroup usbd_cdc_Exported_Defines + * @{ + */ +#ifndef CDC_IN_EP +#define CDC_IN_EP 0x81U /* EP1 for data IN */ +#endif /* CDC_IN_EP */ +#ifndef CDC_OUT_EP +#define CDC_OUT_EP 0x01U /* EP1 for data OUT */ +#endif /* CDC_OUT_EP */ +#ifndef CDC_CMD_EP +#define CDC_CMD_EP 0x82U /* EP2 for CDC commands */ +#endif /* CDC_CMD_EP */ + +#ifndef CDC_HS_BINTERVAL +#define CDC_HS_BINTERVAL 0x10U +#endif /* CDC_HS_BINTERVAL */ + +#ifndef CDC_FS_BINTERVAL +#define CDC_FS_BINTERVAL 0x10U +#endif /* CDC_FS_BINTERVAL */ + +/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */ +#define CDC_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */ +#define CDC_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */ +#define CDC_CMD_PACKET_SIZE 8U /* Control Endpoint Packet size */ + +#define USB_CDC_CONFIG_DESC_SIZ 67U +#define CDC_DATA_HS_IN_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE +#define CDC_DATA_HS_OUT_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE + +#define CDC_DATA_FS_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE +#define CDC_DATA_FS_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE + +#define CDC_REQ_MAX_DATA_SIZE 0x7U +/*---------------------------------------------------------------------*/ +/* CDC definitions */ +/*---------------------------------------------------------------------*/ +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00U +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01U +#define CDC_SET_COMM_FEATURE 0x02U +#define CDC_GET_COMM_FEATURE 0x03U +#define CDC_CLEAR_COMM_FEATURE 0x04U +#define CDC_SET_LINE_CODING 0x20U +#define CDC_GET_LINE_CODING 0x21U +#define CDC_SET_CONTROL_LINE_STATE 0x22U +#define CDC_SEND_BREAK 0x23U + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + +/** + * @} + */ +typedef struct +{ + uint32_t bitrate; + uint8_t format; + uint8_t paritytype; + uint8_t datatype; +} USBD_CDC_LineCodingTypeDef; + +typedef struct _USBD_CDC_Itf +{ + int8_t (* Init)(void); + int8_t (* DeInit)(void); + int8_t (* Control)(uint8_t cmd, uint8_t *pbuf, uint16_t length); + int8_t (* Receive)(uint8_t *Buf, uint32_t *Len); + int8_t (* TransmitCplt)(uint8_t *Buf, uint32_t *Len, uint8_t epnum); +} USBD_CDC_ItfTypeDef; + + +typedef struct +{ + uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE / 4U]; /* Force 32-bit alignment */ + uint8_t CmdOpCode; + uint8_t CmdLength; + uint8_t *RxBuffer; + uint8_t *TxBuffer; + uint32_t RxLength; + uint32_t TxLength; + + __IO uint32_t TxState; + __IO uint32_t RxState; +} USBD_CDC_HandleTypeDef; + + + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_ClassTypeDef USBD_CDC; +#define USBD_CDC_CLASS &USBD_CDC +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_ItfTypeDef *fops); + +#ifdef USE_USBD_COMPOSITE +uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff, + uint32_t length, uint8_t ClassId); +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t ClassId); +#else +uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff, + uint32_t length); +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev); +#endif /* USE_USBD_COMPOSITE */ +uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff); +uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_CDC_H */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/lib/USB_CDC/include/usbd_cdc_if.h b/lib/USB_CDC/include/usbd_cdc_if.h new file mode 100644 index 0000000..19da466 --- /dev/null +++ b/lib/USB_CDC/include/usbd_cdc_if.h @@ -0,0 +1,14 @@ +#ifndef USBD_CDC_IF_H +#define USBD_CDC_IF_H + +#include "usbd_cdc.h" + +extern USBD_CDC_ItfTypeDef USBD_CDC_fops; + +// Send data over USB CDC +uint8_t CDC_Transmit(uint8_t *buf, uint16_t len); + + +/* Betaflight-style DFU reboot check — call early in main() */ +void checkForBootloader(void); +#endif diff --git a/lib/USB_CDC/include/usbd_conf.h b/lib/USB_CDC/include/usbd_conf.h new file mode 100644 index 0000000..b9f6d3a --- /dev/null +++ b/lib/USB_CDC/include/usbd_conf.h @@ -0,0 +1,27 @@ +#ifndef USBD_CONF_H +#define USBD_CONF_H + +/* Match Betaflight's usbd_conf.h exactly */ +#include "stm32f7xx_hal.h" +#include +#include +#include + +#define USBD_MAX_NUM_INTERFACES 3 +#define USBD_MAX_NUM_CONFIGURATION 1 +#define USBD_MAX_STR_DESC_SIZ 0x100 +#define USBD_SUPPORT_USER_STRING 0 +#define USBD_SELF_POWERED 1 +#define USBD_DEBUG_LEVEL 0 +#define USE_USB_FS + +#define USBD_malloc malloc +#define USBD_free free +#define USBD_memset memset +#define USBD_memcpy memcpy + +#define USBD_UsrLog(...) +#define USBD_ErrLog(...) +#define USBD_DbgLog(...) + +#endif diff --git a/lib/USB_CDC/include/usbd_core.h b/lib/USB_CDC/include/usbd_core.h new file mode 100644 index 0000000..5d8a284 --- /dev/null +++ b/lib/USB_CDC/include/usbd_core.h @@ -0,0 +1,175 @@ +/** + ****************************************************************************** + * @file usbd_core.h + * @author MCD Application Team + * @brief Header file for usbd_core.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_conf.h" +#include "usbd_def.h" +#include "usbd_ioreq.h" +#include "usbd_ctlreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_CORE + * @brief This file is the Header file for usbd_core.c file + * @{ + */ + + +/** @defgroup USBD_CORE_Exported_Defines + * @{ + */ +#ifndef USBD_DEBUG_LEVEL +#define USBD_DEBUG_LEVEL 0U +#endif /* USBD_DEBUG_LEVEL */ +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + + +/** + * @} + */ + + + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ +#define USBD_SOF USBD_LL_SOF +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_FunctionsPrototype + * @{ + */ +USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id); +USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass); +#if (USBD_USER_REGISTER_CALLBACK == 1U) +USBD_StatusTypeDef USBD_RegisterDevStateCallback(USBD_HandleTypeDef *pdev, USBD_DevStateCallbackTypeDef pUserCallback); +#endif /* USBD_USER_REGISTER_CALLBACK */ + +#ifdef USE_USBD_COMPOSITE +USBD_StatusTypeDef USBD_RegisterClassComposite(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass, + USBD_CompositeClassTypeDef classtype, uint8_t *EpAddr); + +USBD_StatusTypeDef USBD_UnRegisterClassComposite(USBD_HandleTypeDef *pdev); +uint8_t USBD_CoreGetEPAdd(USBD_HandleTypeDef *pdev, uint8_t ep_dir, uint8_t ep_type, uint8_t ClassId); +#endif /* USE_USBD_COMPOSITE */ + +uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index); +uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index); + +USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup); +USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *pdata); +USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *pdata); + +USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed); +USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev); + +USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); +USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); + +USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev); + +/* USBD Low Level Driver */ +USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev); + +USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, + uint8_t ep_type, uint16_t ep_mps); + +USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr); + +USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, + uint8_t *pbuf, uint32_t size); + +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, + uint8_t *pbuf, uint32_t size); + +#ifdef USBD_HS_TESTMODE_ENABLE +USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode); +#endif /* USBD_HS_TESTMODE_ENABLE */ + +uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr); +uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr); + +void USBD_LL_Delay(uint32_t Delay); + +void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr); +USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_CORE_H */ + +/** + * @} + */ + +/** + * @} + */ + + diff --git a/lib/USB_CDC/include/usbd_ctlreq.h b/lib/USB_CDC/include/usbd_ctlreq.h new file mode 100644 index 0000000..3c4eb16 --- /dev/null +++ b/lib/USB_CDC/include/usbd_ctlreq.h @@ -0,0 +1,101 @@ +/** + ****************************************************************************** + * @file usbd_req.h + * @author MCD Application Team + * @brief Header file for the usbd_req.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_REQUEST_H +#define __USB_REQUEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" + + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_REQ + * @brief header file for the usbd_req.c file + * @{ + */ + +/** @defgroup USBD_REQ_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Exported_Types + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBD_REQ_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_REQ_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_REQ_Exported_FunctionsPrototype + * @{ + */ + +USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +USBD_StatusTypeDef USBD_StdItfReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + +void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata); +void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_REQUEST_H */ + +/** + * @} + */ + +/** + * @} + */ + + diff --git a/lib/USB_CDC/include/usbd_def.h b/lib/USB_CDC/include/usbd_def.h new file mode 100644 index 0000000..52778b3 --- /dev/null +++ b/lib/USB_CDC/include/usbd_def.h @@ -0,0 +1,523 @@ +/** + ****************************************************************************** + * @file usbd_def.h + * @author MCD Application Team + * @brief General defines for the usb device library + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_DEF_H +#define __USBD_DEF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_conf.h" + +/** @addtogroup STM32_USBD_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USB_DEF + * @brief general defines for the usb device library file + * @{ + */ + +/** @defgroup USB_DEF_Exported_Defines + * @{ + */ + +#ifndef NULL +#define NULL 0U +#endif /* NULL */ + +#ifndef USBD_MAX_NUM_INTERFACES +#define USBD_MAX_NUM_INTERFACES 1U +#endif /* USBD_MAX_NUM_CONFIGURATION */ + +#ifndef USBD_MAX_NUM_CONFIGURATION +#define USBD_MAX_NUM_CONFIGURATION 1U +#endif /* USBD_MAX_NUM_CONFIGURATION */ + +#ifdef USE_USBD_COMPOSITE +#ifndef USBD_MAX_SUPPORTED_CLASS +#define USBD_MAX_SUPPORTED_CLASS 4U +#endif /* USBD_MAX_SUPPORTED_CLASS */ +#else +#ifndef USBD_MAX_SUPPORTED_CLASS +#define USBD_MAX_SUPPORTED_CLASS 1U +#endif /* USBD_MAX_SUPPORTED_CLASS */ +#endif /* USE_USBD_COMPOSITE */ + +#ifndef USBD_MAX_CLASS_ENDPOINTS +#define USBD_MAX_CLASS_ENDPOINTS 5U +#endif /* USBD_MAX_CLASS_ENDPOINTS */ + +#ifndef USBD_MAX_CLASS_INTERFACES +#define USBD_MAX_CLASS_INTERFACES 5U +#endif /* USBD_MAX_CLASS_INTERFACES */ + +#ifndef USBD_LPM_ENABLED +#define USBD_LPM_ENABLED 0U +#endif /* USBD_LPM_ENABLED */ + +#ifndef USBD_SELF_POWERED +#define USBD_SELF_POWERED 1U +#endif /*USBD_SELF_POWERED */ + +#ifndef USBD_MAX_POWER +#define USBD_MAX_POWER 0x32U /* 100 mA */ +#endif /* USBD_MAX_POWER */ + +#ifndef USBD_SUPPORT_USER_STRING_DESC +#define USBD_SUPPORT_USER_STRING_DESC 0U +#endif /* USBD_SUPPORT_USER_STRING_DESC */ + +#ifndef USBD_CLASS_USER_STRING_DESC +#define USBD_CLASS_USER_STRING_DESC 0U +#endif /* USBD_CLASS_USER_STRING_DESC */ + +#define USB_LEN_DEV_QUALIFIER_DESC 0x0AU +#define USB_LEN_DEV_DESC 0x12U +#define USB_LEN_CFG_DESC 0x09U +#define USB_LEN_IF_DESC 0x09U +#define USB_LEN_EP_DESC 0x07U +#define USB_LEN_OTG_DESC 0x03U +#define USB_LEN_LANGID_STR_DESC 0x04U +#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09U + +#define USBD_IDX_LANGID_STR 0x00U +#define USBD_IDX_MFC_STR 0x01U +#define USBD_IDX_PRODUCT_STR 0x02U +#define USBD_IDX_SERIAL_STR 0x03U +#define USBD_IDX_CONFIG_STR 0x04U +#define USBD_IDX_INTERFACE_STR 0x05U + +#define USB_REQ_TYPE_STANDARD 0x00U +#define USB_REQ_TYPE_CLASS 0x20U +#define USB_REQ_TYPE_VENDOR 0x40U +#define USB_REQ_TYPE_MASK 0x60U + +#define USB_REQ_RECIPIENT_DEVICE 0x00U +#define USB_REQ_RECIPIENT_INTERFACE 0x01U +#define USB_REQ_RECIPIENT_ENDPOINT 0x02U +#define USB_REQ_RECIPIENT_MASK 0x03U + +#define USB_REQ_GET_STATUS 0x00U +#define USB_REQ_CLEAR_FEATURE 0x01U +#define USB_REQ_SET_FEATURE 0x03U +#define USB_REQ_SET_ADDRESS 0x05U +#define USB_REQ_GET_DESCRIPTOR 0x06U +#define USB_REQ_SET_DESCRIPTOR 0x07U +#define USB_REQ_GET_CONFIGURATION 0x08U +#define USB_REQ_SET_CONFIGURATION 0x09U +#define USB_REQ_GET_INTERFACE 0x0AU +#define USB_REQ_SET_INTERFACE 0x0BU +#define USB_REQ_SYNCH_FRAME 0x0CU + +#define USB_DESC_TYPE_DEVICE 0x01U +#define USB_DESC_TYPE_CONFIGURATION 0x02U +#define USB_DESC_TYPE_STRING 0x03U +#define USB_DESC_TYPE_INTERFACE 0x04U +#define USB_DESC_TYPE_ENDPOINT 0x05U +#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06U +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07U +#define USB_DESC_TYPE_IAD 0x0BU +#define USB_DESC_TYPE_BOS 0x0FU + +#define USB_CONFIG_REMOTE_WAKEUP 0x02U +#define USB_CONFIG_SELF_POWERED 0x01U + +#define USB_FEATURE_EP_HALT 0x00U +#define USB_FEATURE_REMOTE_WAKEUP 0x01U +#define USB_FEATURE_TEST_MODE 0x02U + +#define USB_DEVICE_CAPABITY_TYPE 0x10U + +#define USB_CONF_DESC_SIZE 0x09U +#define USB_IF_DESC_SIZE 0x09U +#define USB_EP_DESC_SIZE 0x07U +#define USB_IAD_DESC_SIZE 0x08U + +#define USB_HS_MAX_PACKET_SIZE 512U +#define USB_FS_MAX_PACKET_SIZE 64U +#define USB_MAX_EP0_SIZE 64U + +/* Device Status */ +#define USBD_STATE_DEFAULT 0x01U +#define USBD_STATE_ADDRESSED 0x02U +#define USBD_STATE_CONFIGURED 0x03U +#define USBD_STATE_SUSPENDED 0x04U + + +/* EP0 State */ +#define USBD_EP0_IDLE 0x00U +#define USBD_EP0_SETUP 0x01U +#define USBD_EP0_DATA_IN 0x02U +#define USBD_EP0_DATA_OUT 0x03U +#define USBD_EP0_STATUS_IN 0x04U +#define USBD_EP0_STATUS_OUT 0x05U +#define USBD_EP0_STALL 0x06U + +#define USBD_EP_TYPE_CTRL 0x00U +#define USBD_EP_TYPE_ISOC 0x01U +#define USBD_EP_TYPE_BULK 0x02U +#define USBD_EP_TYPE_INTR 0x03U + +#ifdef USE_USBD_COMPOSITE +#define USBD_EP_IN 0x80U +#define USBD_EP_OUT 0x00U +#define USBD_FUNC_DESCRIPTOR_TYPE 0x24U +#define USBD_DESC_SUBTYPE_ACM 0x0FU +#define USBD_DESC_ECM_BCD_LOW 0x00U +#define USBD_DESC_ECM_BCD_HIGH 0x10U +#endif /* USE_USBD_COMPOSITE */ +/** + * @} + */ + + +/** @defgroup USBD_DEF_Exported_TypesDefinitions + * @{ + */ + +typedef struct usb_setup_req +{ + uint8_t bmRequest; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} USBD_SetupReqTypedef; + +typedef struct +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +} __PACKED USBD_ConfigDescTypeDef; + +typedef struct +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumDeviceCaps; +} USBD_BosDescTypeDef; + +typedef struct +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; +} __PACKED USBD_EpDescTypeDef; + +typedef struct +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; +} USBD_DescHeaderTypeDef; + +struct _USBD_HandleTypeDef; + +typedef struct _Device_cb +{ + uint8_t (*Init)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx); + uint8_t (*DeInit)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx); + /* Control Endpoints*/ + uint8_t (*Setup)(struct _USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + uint8_t (*EP0_TxSent)(struct _USBD_HandleTypeDef *pdev); + uint8_t (*EP0_RxReady)(struct _USBD_HandleTypeDef *pdev); + /* Class Specific Endpoints*/ + uint8_t (*DataIn)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum); + uint8_t (*DataOut)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum); + uint8_t (*SOF)(struct _USBD_HandleTypeDef *pdev); + uint8_t (*IsoINIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum); + uint8_t (*IsoOUTIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum); + + uint8_t *(*GetHSConfigDescriptor)(uint16_t *length); + uint8_t *(*GetFSConfigDescriptor)(uint16_t *length); + uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length); + uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length); +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) + uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length); +#endif /* USBD_SUPPORT_USER_STRING_DESC */ + +} USBD_ClassTypeDef; + +/* Following USB Device Speed */ +typedef enum +{ + USBD_SPEED_HIGH = 0U, + USBD_SPEED_FULL = 1U, + USBD_SPEED_LOW = 2U, +} USBD_SpeedTypeDef; + +/* Following USB Device status */ +typedef enum +{ + USBD_OK = 0U, + USBD_BUSY, + USBD_EMEM, + USBD_FAIL, +} USBD_StatusTypeDef; + +/* USB Device descriptors structure */ +typedef struct +{ + uint8_t *(*GetDeviceDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetLangIDStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetManufacturerStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetProductStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetSerialStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetConfigurationStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetInterfaceStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); +#if (USBD_CLASS_USER_STRING_DESC == 1) + uint8_t *(*GetUserStrDescriptor)(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length); +#endif /* USBD_CLASS_USER_STRING_DESC */ +#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1)) + uint8_t *(*GetBOSDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); +#endif /* (USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1) */ +} USBD_DescriptorsTypeDef; + +/* USB Device handle structure */ +typedef struct +{ + uint32_t status; + uint32_t total_length; + uint32_t rem_length; + uint32_t maxpacket; + uint16_t is_used; + uint16_t bInterval; +} USBD_EndpointTypeDef; + +#ifdef USE_USBD_COMPOSITE +typedef enum +{ + CLASS_TYPE_NONE = 0, + CLASS_TYPE_HID = 1, + CLASS_TYPE_CDC = 2, + CLASS_TYPE_MSC = 3, + CLASS_TYPE_DFU = 4, + CLASS_TYPE_CHID = 5, + CLASS_TYPE_AUDIO = 6, + CLASS_TYPE_ECM = 7, + CLASS_TYPE_RNDIS = 8, + CLASS_TYPE_MTP = 9, + CLASS_TYPE_VIDEO = 10, + CLASS_TYPE_PRINTER = 11, + CLASS_TYPE_CCID = 12, +} USBD_CompositeClassTypeDef; + + +/* USB Device handle structure */ +typedef struct +{ + uint8_t add; + uint8_t type; + uint8_t size; + uint8_t is_used; +} USBD_EPTypeDef; + +/* USB Device handle structure */ +typedef struct +{ + USBD_CompositeClassTypeDef ClassType; + uint32_t ClassId; + uint32_t Active; + uint32_t NumEps; + USBD_EPTypeDef Eps[USBD_MAX_CLASS_ENDPOINTS]; + uint8_t *EpAdd; + uint32_t NumIf; + uint8_t Ifs[USBD_MAX_CLASS_INTERFACES]; + uint32_t CurrPcktSze; +} USBD_CompositeElementTypeDef; +#endif /* USE_USBD_COMPOSITE */ + +/* USB Device handle structure */ +typedef struct _USBD_HandleTypeDef +{ + uint8_t id; + uint32_t dev_config; + uint32_t dev_default_config; + uint32_t dev_config_status; + USBD_SpeedTypeDef dev_speed; + USBD_EndpointTypeDef ep_in[16]; + USBD_EndpointTypeDef ep_out[16]; + __IO uint32_t ep0_state; + uint32_t ep0_data_len; + __IO uint8_t dev_state; + __IO uint8_t dev_old_state; + uint8_t dev_address; + uint8_t dev_connection_status; + uint8_t dev_test_mode; + uint32_t dev_remote_wakeup; + uint8_t ConfIdx; + + USBD_SetupReqTypedef request; + USBD_DescriptorsTypeDef *pDesc; + USBD_ClassTypeDef *pClass[USBD_MAX_SUPPORTED_CLASS]; + void *pClassData; + void *pClassDataCmsit[USBD_MAX_SUPPORTED_CLASS]; + void *pUserData[USBD_MAX_SUPPORTED_CLASS]; + void *pData; + void *pBosDesc; + void *pConfDesc; + uint32_t classId; + uint32_t NumClasses; +#ifdef USE_USBD_COMPOSITE + USBD_CompositeElementTypeDef tclasslist[USBD_MAX_SUPPORTED_CLASS]; +#endif /* USE_USBD_COMPOSITE */ +#if (USBD_USER_REGISTER_CALLBACK == 1U) + void (* DevStateCallback)(uint8_t dev_state, uint8_t cfgidx); /*!< User Notification callback */ +#endif /* USBD_USER_REGISTER_CALLBACK */ +} USBD_HandleTypeDef; + +#if (USBD_USER_REGISTER_CALLBACK == 1U) +typedef void (*USBD_DevStateCallbackTypeDef)(uint8_t dev_state, uint8_t cfgidx); /*!< pointer to User callback function */ +#endif /* USBD_USER_REGISTER_CALLBACK */ + +/* USB Device endpoint direction */ +typedef enum +{ + OUT = 0x00, + IN = 0x80, +} USBD_EPDirectionTypeDef; + +typedef enum +{ + NETWORK_CONNECTION = 0x00, + RESPONSE_AVAILABLE = 0x01, + CONNECTION_SPEED_CHANGE = 0x2A +} USBD_CDC_NotifCodeTypeDef; +/** + * @} + */ + + + +/** @defgroup USBD_DEF_Exported_Macros + * @{ + */ +__STATIC_INLINE uint16_t SWAPBYTE(uint8_t *addr) +{ + uint16_t _SwapVal; + uint16_t _Byte1; + uint16_t _Byte2; + uint8_t *_pbuff = addr; + + _Byte1 = *(uint8_t *)_pbuff; + _pbuff++; + _Byte2 = *(uint8_t *)_pbuff; + + _SwapVal = (_Byte2 << 8) | _Byte1; + + return _SwapVal; +} + +#ifndef LOBYTE +#define LOBYTE(x) ((uint8_t)((x) & 0x00FFU)) +#endif /* LOBYTE */ + +#ifndef HIBYTE +#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) +#endif /* HIBYTE */ + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif /* MIN */ + +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif /* MAX */ + +#if defined ( __GNUC__ ) +#ifndef __weak +#define __weak __attribute__((weak)) +#endif /* __weak */ +#ifndef __packed +#define __packed __attribute__((__packed__)) +#endif /* __packed */ +#endif /* __GNUC__ */ + + +/* In HS mode and when the DMA is used, all variables and data structures dealing + with the DMA during the transaction process should be 4-bytes aligned */ + +#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ +#ifndef __ALIGN_END +#define __ALIGN_END __attribute__ ((aligned (4U))) +#endif /* __ALIGN_END */ +#ifndef __ALIGN_BEGIN +#define __ALIGN_BEGIN +#endif /* __ALIGN_BEGIN */ +#else +#ifndef __ALIGN_END +#define __ALIGN_END +#endif /* __ALIGN_END */ +#ifndef __ALIGN_BEGIN +#if defined (__CC_ARM) /* ARM Compiler */ +#define __ALIGN_BEGIN __align(4U) +#elif defined (__ICCARM__) /* IAR Compiler */ +#define __ALIGN_BEGIN +#endif /* __CC_ARM */ +#endif /* __ALIGN_BEGIN */ +#endif /* __GNUC__ */ + + +/** + * @} + */ + +/** @defgroup USBD_DEF_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_DEF_Exported_FunctionsPrototype + * @{ + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_DEF_H */ + +/** + * @} + */ + +/** + * @} + */ + diff --git a/lib/USB_CDC/include/usbd_desc.h b/lib/USB_CDC/include/usbd_desc.h new file mode 100644 index 0000000..71bd41d --- /dev/null +++ b/lib/USB_CDC/include/usbd_desc.h @@ -0,0 +1,5 @@ +#ifndef USBD_DESC_H +#define USBD_DESC_H +#include "usbd_def.h" +extern USBD_DescriptorsTypeDef SaltyLab_Desc; +#endif diff --git a/lib/USB_CDC/include/usbd_ioreq.h b/lib/USB_CDC/include/usbd_ioreq.h new file mode 100644 index 0000000..bad1e36 --- /dev/null +++ b/lib/USB_CDC/include/usbd_ioreq.h @@ -0,0 +1,113 @@ +/** + ****************************************************************************** + * @file usbd_ioreq.h + * @author MCD Application Team + * @brief Header file for the usbd_ioreq.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_IOREQ_H +#define __USBD_IOREQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" +#include "usbd_core.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_IOREQ + * @brief header file for the usbd_ioreq.c file + * @{ + */ + +/** @defgroup USBD_IOREQ_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Exported_Types + * @{ + */ + + +/** + * @} + */ + + + +/** @defgroup USBD_IOREQ_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_IOREQ_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype + * @{ + */ + +USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev, + uint8_t *pbuf, uint32_t len); + +USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev, + uint8_t *pbuf, uint32_t len); + +USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev, + uint8_t *pbuf, uint32_t len); + +USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev, + uint8_t *pbuf, uint32_t len); + +USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev); + +uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_IOREQ_H */ + +/** + * @} + */ + +/** + * @} + */ + diff --git a/lib/USB_CDC/src/usbd_cdc.c b/lib/USB_CDC/src/usbd_cdc.c new file mode 100644 index 0000000..eb7f105 --- /dev/null +++ b/lib/USB_CDC/src/usbd_cdc.c @@ -0,0 +1,893 @@ +/** + ****************************************************************************** + * @file usbd_cdc.c + * @author MCD Application Team + * @brief This file provides the high layer firmware functions to manage the + * following functionalities of the USB CDC Class: + * - Initialization and Configuration of high and low layer + * - Enumeration as CDC Device (and enumeration for each implemented memory interface) + * - OUT/IN data transfer + * - Command IN transfer (class requests management) + * - Error management + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + * @verbatim + * + * =================================================================== + * CDC Class Driver Description + * =================================================================== + * This driver manages the "Universal Serial Bus Class Definitions for Communications Devices + * Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus + * Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007" + * This driver implements the following aspects of the specification: + * - Device descriptor management + * - Configuration descriptor management + * - Enumeration as CDC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN) + * - Requests management (as described in section 6.2 in specification) + * - Abstract Control Model compliant + * - Union Functional collection (using 1 IN endpoint for control) + * - Data interface class + * + * These aspects may be enriched or modified for a specific user application. + * + * This driver doesn't implement the following aspects of the specification + * (but it is possible to manage these features with some modifications on this driver): + * - Any class-specific aspect relative to communication classes should be managed by user application. + * - All communication classes other than PSTN are not managed + * + * @endverbatim + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc.h" +#include "usbd_ctlreq.h" + + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_CDC + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_CDC_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_CDC_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_CDC_Private_Macros + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_CDC_Private_FunctionPrototypes + * @{ + */ + +static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev); +#ifndef USE_USBD_COMPOSITE +static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length); +uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length); +#endif /* USE_USBD_COMPOSITE */ + +#ifndef USE_USBD_COMPOSITE +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = +{ + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, +}; +#endif /* USE_USBD_COMPOSITE */ +/** + * @} + */ + +/** @defgroup USBD_CDC_Private_Variables + * @{ + */ + + +/* CDC interface class callbacks structure */ +USBD_ClassTypeDef USBD_CDC = +{ + USBD_CDC_Init, + USBD_CDC_DeInit, + USBD_CDC_Setup, + NULL, /* EP0_TxSent */ + USBD_CDC_EP0_RxReady, + USBD_CDC_DataIn, + USBD_CDC_DataOut, + NULL, + NULL, + NULL, +#ifdef USE_USBD_COMPOSITE + NULL, + NULL, + NULL, + NULL, +#else + USBD_CDC_GetHSCfgDesc, + USBD_CDC_GetFSCfgDesc, + USBD_CDC_GetOtherSpeedCfgDesc, + USBD_CDC_GetDeviceQualifierDescriptor, +#endif /* USE_USBD_COMPOSITE */ +}; + +#ifndef USE_USBD_COMPOSITE +/* USB CDC device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_CfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + /* Configuration Descriptor */ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength */ + 0x00, + 0x02, /* bNumInterfaces: 2 interfaces */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor + describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif /* USBD_SELF_POWERED */ + USBD_MAX_POWER, /* MaxPower (mA) */ + + /*---------------------------------------------------------------------------*/ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoint used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + 0x01, /* bDataInterface */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + 0x00, /* bMasterInterface: Communication class interface */ + 0x01, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_FS_BINTERVAL, /* bInterval */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00 /* bInterval */ +}; +#endif /* USE_USBD_COMPOSITE */ + +static uint8_t CDCInEpAdd = CDC_IN_EP; +static uint8_t CDCOutEpAdd = CDC_OUT_EP; +static uint8_t CDCCmdEpAdd = CDC_CMD_EP; + +/** + * @} + */ + +/** @defgroup USBD_CDC_Private_Functions + * @{ + */ + +/** + * @brief USBD_CDC_Init + * Initialize the CDC interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + USBD_CDC_HandleTypeDef *hcdc; + + hcdc = (USBD_CDC_HandleTypeDef *)USBD_malloc(sizeof(USBD_CDC_HandleTypeDef)); + + if (hcdc == NULL) + { + pdev->pClassDataCmsit[pdev->classId] = NULL; + return (uint8_t)USBD_EMEM; + } + + (void)USBD_memset(hcdc, 0, sizeof(USBD_CDC_HandleTypeDef)); + + pdev->pClassDataCmsit[pdev->classId] = (void *)hcdc; + pdev->pClassData = pdev->pClassDataCmsit[pdev->classId]; + +#ifdef USE_USBD_COMPOSITE + /* Get the Endpoints addresses allocated for this class instance */ + CDCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId); + CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId); + CDCCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId); +#endif /* USE_USBD_COMPOSITE */ + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, CDCInEpAdd, USBD_EP_TYPE_BULK, + CDC_DATA_HS_IN_PACKET_SIZE); + + pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 1U; + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, CDCOutEpAdd, USBD_EP_TYPE_BULK, + CDC_DATA_HS_OUT_PACKET_SIZE); + + pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 1U; + + /* Set bInterval for CDC CMD Endpoint */ + pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = CDC_HS_BINTERVAL; + } + else + { + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, CDCInEpAdd, USBD_EP_TYPE_BULK, + CDC_DATA_FS_IN_PACKET_SIZE); + + pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 1U; + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, CDCOutEpAdd, USBD_EP_TYPE_BULK, + CDC_DATA_FS_OUT_PACKET_SIZE); + + pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 1U; + + /* Set bInterval for CMD Endpoint */ + pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = CDC_FS_BINTERVAL; + } + + /* Open Command IN EP */ + (void)USBD_LL_OpenEP(pdev, CDCCmdEpAdd, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE); + pdev->ep_in[CDCCmdEpAdd & 0xFU].is_used = 1U; + + hcdc->RxBuffer = NULL; + + /* Init physical Interface components */ + ((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Init(); + + /* Init Xfer states */ + hcdc->TxState = 0U; + hcdc->RxState = 0U; + + if (hcdc->RxBuffer == NULL) + { + return (uint8_t)USBD_EMEM; + } + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer, + CDC_DATA_HS_OUT_PACKET_SIZE); + } + else + { + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_Init + * DeInitialize the CDC layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + +#ifdef USE_USBD_COMPOSITE + /* Get the Endpoints addresses allocated for this CDC class instance */ + CDCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId); + CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId); + CDCCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, (uint8_t)pdev->classId); +#endif /* USE_USBD_COMPOSITE */ + + /* Close EP IN */ + (void)USBD_LL_CloseEP(pdev, CDCInEpAdd); + pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 0U; + + /* Close EP OUT */ + (void)USBD_LL_CloseEP(pdev, CDCOutEpAdd); + pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 0U; + + /* Close Command IN EP */ + (void)USBD_LL_CloseEP(pdev, CDCCmdEpAdd); + pdev->ep_in[CDCCmdEpAdd & 0xFU].is_used = 0U; + pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = 0U; + + /* DeInit physical Interface components */ + if (pdev->pClassDataCmsit[pdev->classId] != NULL) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->DeInit(); + (void)USBD_free(pdev->pClassDataCmsit[pdev->classId]); + pdev->pClassDataCmsit[pdev->classId] = NULL; + pdev->pClassData = NULL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_Setup + * Handle the CDC specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; + uint16_t len; + uint8_t ifalt = 0U; + uint16_t status_info = 0U; + USBD_StatusTypeDef ret = USBD_OK; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + if (req->wLength != 0U) + { + if ((req->bmRequest & 0x80U) != 0U) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Control(req->bRequest, + (uint8_t *)hcdc->data, + req->wLength); + + len = MIN(CDC_REQ_MAX_DATA_SIZE, req->wLength); + (void)USBD_CtlSendData(pdev, (uint8_t *)hcdc->data, len); + } + else + { + hcdc->CmdOpCode = req->bRequest; + hcdc->CmdLength = (uint8_t)MIN(req->wLength, USB_MAX_EP0_SIZE); + + (void)USBD_CtlPrepareRx(pdev, (uint8_t *)hcdc->data, hcdc->CmdLength); + } + } + else + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Control(req->bRequest, + (uint8_t *)req, 0U); + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, &ifalt, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state != USBD_STATE_CONFIGURED) + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_CDC_DataIn + * Data sent on non-control IN endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_HandleTypeDef *hcdc; + PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)pdev->pData; + + if (pdev->pClassDataCmsit[pdev->classId] == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; + + if ((pdev->ep_in[epnum & 0xFU].total_length > 0U) && + ((pdev->ep_in[epnum & 0xFU].total_length % hpcd->IN_ep[epnum & 0xFU].maxpacket) == 0U)) + { + /* Update the packet total length */ + pdev->ep_in[epnum & 0xFU].total_length = 0U; + + /* Send ZLP */ + (void)USBD_LL_Transmit(pdev, epnum, NULL, 0U); + } + else + { + hcdc->TxState = 0U; + + if (((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->TransmitCplt != NULL) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum); + } + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; + + if (pdev->pClassDataCmsit[pdev->classId] == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Get the received data length */ + hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum); + + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application Xfer */ + + ((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Receive(hcdc->RxBuffer, &hcdc->RxLength); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_EP0_RxReady + * Handle EP0 Rx Ready event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if ((pdev->pUserData[pdev->classId] != NULL) && (hcdc->CmdOpCode != 0xFFU)) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Control(hcdc->CmdOpCode, + (uint8_t *)hcdc->data, + (uint16_t)hcdc->CmdLength); + hcdc->CmdOpCode = 0xFFU; + } + + return (uint8_t)USBD_OK; +} +#ifndef USE_USBD_COMPOSITE +/** + * @brief USBD_CDC_GetFSCfgDesc + * Return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length) +{ + USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP); + USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP); + USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP); + + if (pEpCmdDesc != NULL) + { + pEpCmdDesc->bInterval = CDC_FS_BINTERVAL; + } + + if (pEpOutDesc != NULL) + { + pEpOutDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE; + } + + if (pEpInDesc != NULL) + { + pEpInDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE; + } + + *length = (uint16_t)sizeof(USBD_CDC_CfgDesc); + return USBD_CDC_CfgDesc; +} + +/** + * @brief USBD_CDC_GetHSCfgDesc + * Return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length) +{ + USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP); + USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP); + USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP); + + if (pEpCmdDesc != NULL) + { + pEpCmdDesc->bInterval = CDC_HS_BINTERVAL; + } + + if (pEpOutDesc != NULL) + { + pEpOutDesc->wMaxPacketSize = CDC_DATA_HS_MAX_PACKET_SIZE; + } + + if (pEpInDesc != NULL) + { + pEpInDesc->wMaxPacketSize = CDC_DATA_HS_MAX_PACKET_SIZE; + } + + *length = (uint16_t)sizeof(USBD_CDC_CfgDesc); + return USBD_CDC_CfgDesc; +} + +/** + * @brief USBD_CDC_GetOtherSpeedCfgDesc + * Return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length) +{ + USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP); + USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP); + USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP); + + if (pEpCmdDesc != NULL) + { + pEpCmdDesc->bInterval = CDC_FS_BINTERVAL; + } + + if (pEpOutDesc != NULL) + { + pEpOutDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE; + } + + if (pEpInDesc != NULL) + { + pEpInDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE; + } + + *length = (uint16_t)sizeof(USBD_CDC_CfgDesc); + return USBD_CDC_CfgDesc; +} + +/** + * @brief USBD_CDC_GetDeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CDC_DeviceQualifierDesc); + + return USBD_CDC_DeviceQualifierDesc; +} +#endif /* USE_USBD_COMPOSITE */ +/** + * @brief USBD_CDC_RegisterInterface + * @param pdev: device instance + * @param fops: CD Interface callback + * @retval status + */ +uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_ItfTypeDef *fops) +{ + if (fops == NULL) + { + return (uint8_t)USBD_FAIL; + } + + pdev->pUserData[pdev->classId] = fops; + + return (uint8_t)USBD_OK; +} + + +/** + * @brief USBD_CDC_SetTxBuffer + * @param pdev: device instance + * @param pbuff: Tx Buffer + * @param length: length of data to be sent + * @param ClassId: The Class ID + * @retval status + */ +#ifdef USE_USBD_COMPOSITE +uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, + uint8_t *pbuff, uint32_t length, uint8_t ClassId) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[ClassId]; +#else +uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, + uint8_t *pbuff, uint32_t length) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; +#endif /* USE_USBD_COMPOSITE */ + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc->TxBuffer = pbuff; + hcdc->TxLength = length; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_SetRxBuffer + * @param pdev: device instance + * @param pbuff: Rx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc->RxBuffer = pbuff; + + return (uint8_t)USBD_OK; +} + + +/** + * @brief USBD_CDC_TransmitPacket + * Transmit packet on IN endpoint + * @param pdev: device instance + * @param ClassId: The Class ID + * @retval status + */ +#ifdef USE_USBD_COMPOSITE +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t ClassId) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[ClassId]; +#else +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; +#endif /* USE_USBD_COMPOSITE */ + + USBD_StatusTypeDef ret = USBD_BUSY; + +#ifdef USE_USBD_COMPOSITE + /* Get the Endpoints addresses allocated for this class instance */ + CDCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, ClassId); +#endif /* USE_USBD_COMPOSITE */ + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (hcdc->TxState == 0U) + { + /* Tx Transfer in progress */ + hcdc->TxState = 1U; + + /* Update the packet total length */ + pdev->ep_in[CDCInEpAdd & 0xFU].total_length = hcdc->TxLength; + + /* Transmit next packet */ + (void)USBD_LL_Transmit(pdev, CDCInEpAdd, hcdc->TxBuffer, hcdc->TxLength); + + ret = USBD_OK; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_CDC_ReceivePacket + * prepare OUT Endpoint for reception + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; + +#ifdef USE_USBD_COMPOSITE + /* Get the Endpoints addresses allocated for this class instance */ + CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId); +#endif /* USE_USBD_COMPOSITE */ + + if (pdev->pClassDataCmsit[pdev->classId] == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer, + CDC_DATA_HS_OUT_PACKET_SIZE); + } + else + { + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + + return (uint8_t)USBD_OK; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + diff --git a/lib/USB_CDC/src/usbd_cdc_if.c b/lib/USB_CDC/src/usbd_cdc_if.c new file mode 100644 index 0000000..d138dff --- /dev/null +++ b/lib/USB_CDC/src/usbd_cdc_if.c @@ -0,0 +1,135 @@ +#include "usbd_cdc_if.h" +#include "stm32f7xx_hal.h" + +extern USBD_HandleTypeDef hUsbDevice; +volatile uint8_t cdc_streaming = 1; /* auto-stream */ +static volatile uint8_t cdc_port_open = 0; /* set when host asserts DTR */ +volatile uint8_t cdc_arm_request = 0; /* set by A command */ +volatile uint8_t cdc_disarm_request = 0; /* set by D command */ + + +static uint8_t UserRxBuffer[256]; +static uint8_t UserTxBuffer[256]; + +/* + * Betaflight-proven DFU reboot: + * 1. Write magic to RTC backup register (persists across soft reset) + * 2. NVIC_SystemReset() — clean hardware reset + * 3. Early startup checks magic, clears it, jumps to system bootloader + * + * The magic check happens in checkForBootloader() called from main.c + * before any peripheral init. + */ +#define BOOTLOADER_MAGIC 0xDEADBEEF + +static void request_bootloader(void) { + /* Betaflight-proven: write magic, disable IRQs, reset. + * checkForBootloader() runs on next boot before anything else. */ + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWR_EnableBkUpAccess(); + __HAL_RCC_RTC_ENABLE(); + + /* Write magic to RTC backup register 0 */ + RTC->BKP0R = BOOTLOADER_MAGIC; + + __disable_irq(); + NVIC_SystemReset(); +} + +/* + * Call this VERY early in main(), before HAL_Init(). + * Checks RTC backup register for magic value left by request_bootloader(). + * If found: clear magic, jump to STM32F7 system bootloader at 0x1FF00000. + */ +void checkForBootloader(void) { + /* + * Betaflight-proven bootloader jump for STM32F7. + * Called VERY early, before HAL_Init/caches/clocks. + * At this point only RCC PWR is needed to read RTC backup regs. + */ + + /* Enable backup domain access to read RTC backup register */ + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWR_EnableBkUpAccess(); + __HAL_RCC_RTC_ENABLE(); + + uint32_t magic = RTC->BKP0R; + + if (magic != BOOTLOADER_MAGIC) { + return; /* Normal boot */ + } + + /* Write POST marker (Betaflight does this so SystemInit can + * do a second reset if needed — we just clear it) */ + RTC->BKP0R = 0; + + /* Jump to STM32F7 system bootloader at 0x1FF00000. + * Exactly as Betaflight does it — no cache/VTOR/MEMRMP games needed + * because we run before any of that is configured. */ + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + __set_MSP(*(uint32_t *)0x1FF00000); + ((void (*)(void))(*(uint32_t *)0x1FF00004))(); + + while (1); +} + +static int8_t CDC_Init(void) { + USBD_CDC_SetTxBuffer(&hUsbDevice, UserTxBuffer, 0); + USBD_CDC_SetRxBuffer(&hUsbDevice, UserRxBuffer); + USBD_CDC_ReceivePacket(&hUsbDevice); + + /* Reset TxState so CDC_Transmit works after host (re)connects. + * Without this, if transmits happen before host opens port, + * TxState stays BUSY forever since host never ACKs. */ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)hUsbDevice.pClassData; + if (hcdc) hcdc->TxState = 0; + + return USBD_OK; +} + +static int8_t CDC_DeInit(void) { return USBD_OK; } + +static int8_t CDC_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length) { + (void)pbuf; (void)length; + if (cmd == 0x22) { /* CDC_SET_CONTROL_LINE_STATE — host opened port */ + cdc_port_open = 1; + cdc_streaming = 1; + } + return USBD_OK; +} + +static int8_t CDC_Receive(uint8_t *buf, uint32_t *len) { + if (*len >= 1 && buf[0] == 'S') { + cdc_streaming = !cdc_streaming; /* Toggle streaming */ + } + if (*len >= 1 && buf[0] == 'A') { + cdc_arm_request = 1; /* Arm balance — processed in main loop */ + } + if (*len >= 1 && buf[0] == 'D') { + cdc_disarm_request = 1; /* Disarm — processed in main loop */ + } + if (*len >= 1 && buf[0] == 'R') { + request_bootloader(); /* Sets magic + resets — never returns */ + } + USBD_CDC_SetRxBuffer(&hUsbDevice, UserRxBuffer); + USBD_CDC_ReceivePacket(&hUsbDevice); + return USBD_OK; +} + +USBD_CDC_ItfTypeDef USBD_CDC_fops = { CDC_Init, CDC_DeInit, CDC_Control, CDC_Receive }; + +uint8_t CDC_Transmit(uint8_t *buf, uint16_t len) { + + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)hUsbDevice.pClassData; + if (hcdc == NULL) return USBD_FAIL; + if (hcdc->TxState != 0) { + /* If stuck busy (no host ACK), force reset after a while */ + static uint32_t busy_count = 0; + if (++busy_count > 100) { hcdc->TxState = 0; busy_count = 0; } + return USBD_BUSY; + } + USBD_CDC_SetTxBuffer(&hUsbDevice, buf, len); + return USBD_CDC_TransmitPacket(&hUsbDevice); +} diff --git a/lib/USB_CDC/src/usbd_conf.c b/lib/USB_CDC/src/usbd_conf.c new file mode 100644 index 0000000..fbae848 --- /dev/null +++ b/lib/USB_CDC/src/usbd_conf.c @@ -0,0 +1,97 @@ +/* Taken directly from Betaflight: usbd_conf_stm32f7xx.c */ +#include "stm32f7xx_hal.h" +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_cdc.h" +#include "usbd_conf.h" + +PCD_HandleTypeDef hpcd; + +void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + if (hpcd->Instance == USB_OTG_FS) { + __HAL_RCC_GPIOA_CLK_ENABLE(); + + GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + HAL_NVIC_SetPriority(OTG_FS_IRQn, 6, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + } +} + +void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) +{ + if (hpcd->Instance == USB_OTG_FS) { + __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); + __HAL_RCC_SYSCFG_CLK_DISABLE(); + } +} + +void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_SetupStage(hpcd->pData, (uint8_t *)hpcd->Setup); } +void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { USBD_LL_DataOutStage(hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff); } +void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { USBD_LL_DataInStage(hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff); } +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_SOF(hpcd->pData); } +void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) { + USBD_LL_Reset(hpcd->pData); + USBD_LL_SetSpeed(hpcd->pData, USBD_SPEED_FULL); +} +void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_Suspend(hpcd->pData); } +void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_Resume(hpcd->pData); } +void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { USBD_LL_IsoOUTIncomplete(hpcd->pData, epnum); } +void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { USBD_LL_IsoINIncomplete(hpcd->pData, epnum); } +void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_DevConnected(hpcd->pData); } +void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_DevDisconnected(hpcd->pData); } + +USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) +{ + hpcd.Instance = USB_OTG_FS; + hpcd.Init.dev_endpoints = 4; + hpcd.Init.use_dedicated_ep1 = 0; + hpcd.Init.ep0_mps = 0x40; + hpcd.Init.dma_enable = 0; + hpcd.Init.low_power_enable = 0; + hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd.Init.Sof_enable = 0; + hpcd.Init.speed = PCD_SPEED_FULL; + hpcd.Init.vbus_sensing_enable = 0; + hpcd.Init.lpm_enable = 0; + + hpcd.pData = pdev; + pdev->pData = &hpcd; + + HAL_PCD_Init(&hpcd); + + HAL_PCDEx_SetRxFiFo(&hpcd, 0x80); + HAL_PCDEx_SetTxFiFo(&hpcd, 0, 0x40); + HAL_PCDEx_SetTxFiFo(&hpcd, 1, 0x80); + + return USBD_OK; +} + +USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) { HAL_PCD_DeInit(pdev->pData); return USBD_OK; } +USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) { HAL_PCD_Start(pdev->pData); return USBD_OK; } +USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) { HAL_PCD_Stop(pdev->pData); return USBD_OK; } +USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps) { HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type); return USBD_OK; } +USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_Close(pdev->pData, ep_addr); return USBD_OK; } +USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_Flush(pdev->pData, ep_addr); return USBD_OK; } +USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_SetStall(pdev->pData, ep_addr); return USBD_OK; } +USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); return USBD_OK; } +uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { + PCD_HandleTypeDef *hpcd = pdev->pData; + if ((ep_addr & 0x80) == 0x80) return hpcd->IN_ep[ep_addr & 0x7F].is_stall; + else return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; +} +USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) { HAL_PCD_SetAddress(pdev->pData, dev_addr); return USBD_OK; } +USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size) { HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); return USBD_OK; } +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size) { HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); return USBD_OK; } +uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { return HAL_PCD_EP_GetRxCount(pdev->pData, ep_addr); } +void USBD_LL_Delay(uint32_t Delay) { HAL_Delay(Delay); } diff --git a/lib/USB_CDC/src/usbd_core.c b/lib/USB_CDC/src/usbd_core.c new file mode 100644 index 0000000..ad4dd12 --- /dev/null +++ b/lib/USB_CDC/src/usbd_core.c @@ -0,0 +1,1215 @@ +/** + ****************************************************************************** + * @file usbd_core.c + * @author MCD Application Team + * @brief This file provides all the USBD core functions. + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" + +#ifdef USE_USBD_COMPOSITE +#include "usbd_composite_builder.h" +#endif /* USE_USBD_COMPOSITE */ + +/** @addtogroup STM32_USBD_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_CORE + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_CORE_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Private_Macros + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Private_Functions + * @{ + */ + +/** + * @brief USBD_Init + * Initialize the device stack and load the class driver + * @param pdev: device instance + * @param pdesc: Descriptor structure address + * @param id: Low level core index + * @retval status: USBD Status + */ +USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, + USBD_DescriptorsTypeDef *pdesc, uint8_t id) +{ + USBD_StatusTypeDef ret; + + /* Check whether the USB Host handle is valid */ + if (pdev == NULL) + { +#if (USBD_DEBUG_LEVEL > 1U) + USBD_ErrLog("Invalid Device handle"); +#endif /* (USBD_DEBUG_LEVEL > 1U) */ + return USBD_FAIL; + } + +#ifdef USE_USBD_COMPOSITE + /* Parse the table of classes in use */ + for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++) + { + /* Unlink previous class*/ + pdev->pClass[i] = NULL; + pdev->pUserData[i] = NULL; + + /* Set class as inactive */ + pdev->tclasslist[i].Active = 0; + pdev->NumClasses = 0; + pdev->classId = 0; + } +#else + /* Unlink previous class*/ + pdev->pClass[0] = NULL; + pdev->pUserData[0] = NULL; +#endif /* USE_USBD_COMPOSITE */ + + pdev->pConfDesc = NULL; + + /* Assign USBD Descriptors */ + if (pdesc != NULL) + { + pdev->pDesc = pdesc; + } + + /* Set Device initial State */ + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->id = id; + + /* Initialize low level driver */ + ret = USBD_LL_Init(pdev); + + return ret; +} + +/** + * @brief USBD_DeInit + * De-Initialize the device library + * @param pdev: device instance + * @retval status: USBD Status + */ +USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev) +{ + USBD_StatusTypeDef ret; + + /* Disconnect the USB Device */ + (void)USBD_LL_Stop(pdev); + + /* Set Default State */ + pdev->dev_state = USBD_STATE_DEFAULT; + +#ifdef USE_USBD_COMPOSITE + /* Parse the table of classes in use */ + for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++) + { + /* Check if current class is in use */ + if ((pdev->tclasslist[i].Active) == 1U) + { + if (pdev->pClass[i] != NULL) + { + pdev->classId = i; + /* Free Class Resources */ + pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config); + } + } + } +#else + /* Free Class Resources */ + if (pdev->pClass[0] != NULL) + { + pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config); + } + + pdev->pUserData[0] = NULL; + +#endif /* USE_USBD_COMPOSITE */ + + /* Free Device descriptors resources */ + pdev->pDesc = NULL; + pdev->pConfDesc = NULL; + + /* DeInitialize low level driver */ + ret = USBD_LL_DeInit(pdev); + + return ret; +} + +/** + * @brief USBD_RegisterClass + * Link class driver to Device Core. + * @param pdev: Device Handle + * @param pclass: Class handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass) +{ + uint16_t len = 0U; + + if (pclass == NULL) + { +#if (USBD_DEBUG_LEVEL > 1U) + USBD_ErrLog("Invalid Class handle"); +#endif /* (USBD_DEBUG_LEVEL > 1U) */ + return USBD_FAIL; + } + + /* link the class to the USB Device handle */ + pdev->pClass[0] = pclass; + + /* Get Device Configuration Descriptor */ +#ifdef USE_USB_HS + if (pdev->pClass[pdev->classId]->GetHSConfigDescriptor != NULL) + { + pdev->pConfDesc = (void *)pdev->pClass[pdev->classId]->GetHSConfigDescriptor(&len); + } +#else /* Default USE_USB_FS */ + if (pdev->pClass[pdev->classId]->GetFSConfigDescriptor != NULL) + { + pdev->pConfDesc = (void *)pdev->pClass[pdev->classId]->GetFSConfigDescriptor(&len); + } +#endif /* USE_USB_FS */ + + /* Increment the NumClasses */ + pdev->NumClasses++; + + return USBD_OK; +} + +#ifdef USE_USBD_COMPOSITE +/** + * @brief USBD_RegisterClassComposite + * Link class driver to Device Core. + * @param pdev : Device Handle + * @param pclass: Class handle + * @param classtype: Class type + * @param EpAddr: Endpoint Address handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_RegisterClassComposite(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass, + USBD_CompositeClassTypeDef classtype, uint8_t *EpAddr) +{ + USBD_StatusTypeDef ret = USBD_OK; + uint16_t len = 0U; + + if ((pdev->classId < USBD_MAX_SUPPORTED_CLASS) && (pdev->NumClasses < USBD_MAX_SUPPORTED_CLASS)) + { + if ((uint32_t)pclass != 0U) + { + /* Link the class to the USB Device handle */ + pdev->pClass[pdev->classId] = pclass; + ret = USBD_OK; + + pdev->tclasslist[pdev->classId].EpAdd = EpAddr; + + /* Call the composite class builder */ + (void)USBD_CMPSIT_AddClass(pdev, pclass, classtype, 0); + + /* Increment the ClassId for the next occurrence */ + pdev->classId ++; + pdev->NumClasses ++; + } + else + { +#if (USBD_DEBUG_LEVEL > 1U) + USBD_ErrLog("Invalid Class handle"); +#endif /* (USBD_DEBUG_LEVEL > 1U) */ + ret = USBD_FAIL; + } + } + + if (ret == USBD_OK) + { + /* Get Device Configuration Descriptor */ +#ifdef USE_USB_HS + pdev->pConfDesc = USBD_CMPSIT.GetHSConfigDescriptor(&len); +#else /* Default USE_USB_FS */ + pdev->pConfDesc = USBD_CMPSIT.GetFSConfigDescriptor(&len); +#endif /* USE_USB_FS */ + } + + return ret; +} + +/** + * @brief USBD_UnRegisterClassComposite + * UnLink all composite class drivers from Device Core. + * @param pdev: Device Handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_UnRegisterClassComposite(USBD_HandleTypeDef *pdev) +{ + USBD_StatusTypeDef ret = USBD_FAIL; + uint8_t idx1; + uint8_t idx2; + + /* Unroll all activated classes */ + for (idx1 = 0; idx1 < pdev->NumClasses; idx1++) + { + /* Check if the class correspond to the requested type and if it is active */ + if (pdev->tclasslist[idx1].Active == 1U) + { + /* Set the new class ID */ + pdev->classId = idx1; + + /* Free resources used by the selected class */ + if (pdev->pClass[pdev->classId] != NULL) + { + /* Free Class Resources */ + if (pdev->pClass[pdev->classId]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U) + { +#if (USBD_DEBUG_LEVEL > 1U) + USBD_ErrLog("Class DeInit didn't succeed!, can't unregister selected class"); +#endif /* (USBD_DEBUG_LEVEL > 1U) */ + + ret = USBD_FAIL; + } + } + + /* Free the class pointer */ + pdev->pClass[pdev->classId] = NULL; + + /* Free the class location in classes table and reset its parameters to zero */ + pdev->tclasslist[pdev->classId].ClassType = CLASS_TYPE_NONE; + pdev->tclasslist[pdev->classId].ClassId = 0U; + pdev->tclasslist[pdev->classId].Active = 0U; + pdev->tclasslist[pdev->classId].NumEps = 0U; + pdev->tclasslist[pdev->classId].NumIf = 0U; + pdev->tclasslist[pdev->classId].CurrPcktSze = 0U; + + for (idx2 = 0U; idx2 < USBD_MAX_CLASS_ENDPOINTS; idx2++) + { + pdev->tclasslist[pdev->classId].Eps[idx2].add = 0U; + pdev->tclasslist[pdev->classId].Eps[idx2].type = 0U; + pdev->tclasslist[pdev->classId].Eps[idx2].size = 0U; + pdev->tclasslist[pdev->classId].Eps[idx2].is_used = 0U; + } + + for (idx2 = 0U; idx2 < USBD_MAX_CLASS_INTERFACES; idx2++) + { + pdev->tclasslist[pdev->classId].Ifs[idx2] = 0U; + } + } + } + + /* Reset the configuration descriptor */ + (void)USBD_CMPST_ClearConfDesc(pdev); + + /* Reset the class ID and number of classes */ + pdev->classId = 0U; + pdev->NumClasses = 0U; + + return ret; +} +#endif /* USE_USBD_COMPOSITE */ + +#if (USBD_USER_REGISTER_CALLBACK == 1U) +/** + * @brief USBD_RegisterDevStateCallback + * @param pdev : Device Handle + * @param pUserCallback: User Callback + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_RegisterDevStateCallback(USBD_HandleTypeDef *pdev, USBD_DevStateCallbackTypeDef pUserCallback) +{ + pdev->DevStateCallback = pUserCallback; + + return USBD_OK; +} +#endif /* USBD_USER_REGISTER_CALLBACK */ + +/** + * @brief USBD_Start + * Start the USB Device Core. + * @param pdev: Device Handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev) +{ +#ifdef USE_USBD_COMPOSITE + pdev->classId = 0U; +#endif /* USE_USBD_COMPOSITE */ + + /* Start the low level driver */ + return USBD_LL_Start(pdev); +} + +/** + * @brief USBD_Stop + * Stop the USB Device Core. + * @param pdev: Device Handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev) +{ + /* Disconnect USB Device */ + (void)USBD_LL_Stop(pdev); + + /* Free Class Resources */ +#ifdef USE_USBD_COMPOSITE + /* Parse the table of classes in use */ + for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++) + { + /* Check if current class is in use */ + if ((pdev->tclasslist[i].Active) == 1U) + { + if (pdev->pClass[i] != NULL) + { + pdev->classId = i; + /* Free Class Resources */ + (void)pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config); + } + } + } + + /* Reset the class ID */ + pdev->classId = 0U; +#else + if (pdev->pClass[0] != NULL) + { + (void)pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config); + } +#endif /* USE_USBD_COMPOSITE */ + + return USBD_OK; +} + +/** + * @brief USBD_RunTestMode + * Launch test mode process + * @param pdev: device instance + * @retval status + */ +USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev) +{ +#ifdef USBD_HS_TESTMODE_ENABLE + USBD_StatusTypeDef ret; + + /* Run USB HS test mode */ + ret = USBD_LL_SetTestMode(pdev, pdev->dev_test_mode); + + return ret; +#else + /* Prevent unused argument compilation warning */ + UNUSED(pdev); + + return USBD_OK; +#endif /* USBD_HS_TESTMODE_ENABLE */ +} + +/** + * @brief USBD_SetClassConfig + * Configure device and start the interface + * @param pdev: device instance + * @param cfgidx: configuration index + * @retval status + */ + +USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + USBD_StatusTypeDef ret = USBD_OK; + +#ifdef USE_USBD_COMPOSITE + /* Parse the table of classes in use */ + for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++) + { + /* Check if current class is in use */ + if ((pdev->tclasslist[i].Active) == 1U) + { + if (pdev->pClass[i] != NULL) + { + pdev->classId = i; + /* Set configuration and Start the Class*/ + if (pdev->pClass[i]->Init(pdev, cfgidx) != 0U) + { + ret = USBD_FAIL; + } + } + } + } +#else + if (pdev->pClass[0] != NULL) + { + /* Set configuration and Start the Class */ + ret = (USBD_StatusTypeDef)pdev->pClass[0]->Init(pdev, cfgidx); + } +#endif /* USE_USBD_COMPOSITE */ + + return ret; +} + +/** + * @brief USBD_ClrClassConfig + * Clear current configuration + * @param pdev: device instance + * @param cfgidx: configuration index + * @retval status + */ +USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + USBD_StatusTypeDef ret = USBD_OK; + +#ifdef USE_USBD_COMPOSITE + /* Parse the table of classes in use */ + for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++) + { + /* Check if current class is in use */ + if ((pdev->tclasslist[i].Active) == 1U) + { + if (pdev->pClass[i] != NULL) + { + pdev->classId = i; + /* Clear configuration and De-initialize the Class process */ + if (pdev->pClass[i]->DeInit(pdev, cfgidx) != 0U) + { + ret = USBD_FAIL; + } + } + } + } +#else + /* Clear configuration and De-initialize the Class process */ + if (pdev->pClass[0]->DeInit(pdev, cfgidx) != 0U) + { + ret = USBD_FAIL; + } +#endif /* USE_USBD_COMPOSITE */ + + return ret; +} + + +/** + * @brief USBD_LL_SetupStage + * Handle the setup stage + * @param pdev: device instance + * @param psetup: setup packet buffer pointer + * @retval status + */ +USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup) +{ + USBD_StatusTypeDef ret; + + USBD_ParseSetupRequest(&pdev->request, psetup); + + pdev->ep0_state = USBD_EP0_SETUP; + + pdev->ep0_data_len = pdev->request.wLength; + + switch (pdev->request.bmRequest & 0x1FU) + { + case USB_REQ_RECIPIENT_DEVICE: + ret = USBD_StdDevReq(pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_INTERFACE: + ret = USBD_StdItfReq(pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_ENDPOINT: + ret = USBD_StdEPReq(pdev, &pdev->request); + break; + + default: + ret = USBD_LL_StallEP(pdev, (pdev->request.bmRequest & 0x80U)); + break; + } + + return ret; +} + +/** + * @brief USBD_LL_DataOutStage + * Handle data OUT stage + * @param pdev: device instance + * @param epnum: endpoint index + * @param pdata: data pointer + * @retval status + */ +USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev, + uint8_t epnum, uint8_t *pdata) +{ + USBD_EndpointTypeDef *pep; + USBD_StatusTypeDef ret = USBD_OK; + uint8_t idx; + + if (epnum == 0U) + { + pep = &pdev->ep_out[0]; + + if (pdev->ep0_state == USBD_EP0_DATA_OUT) + { + if (pep->rem_length > pep->maxpacket) + { + pep->rem_length -= pep->maxpacket; + + (void)USBD_CtlContinueRx(pdev, pdata, MIN(pep->rem_length, pep->maxpacket)); + } + else + { + /* Find the class ID relative to the current request */ + switch (pdev->request.bmRequest & 0x1FU) + { + case USB_REQ_RECIPIENT_DEVICE: + /* Device requests must be managed by the first instantiated class + (or duplicated by all classes for simplicity) */ + idx = 0U; + break; + + case USB_REQ_RECIPIENT_INTERFACE: + idx = USBD_CoreFindIF(pdev, LOBYTE(pdev->request.wIndex)); + break; + + case USB_REQ_RECIPIENT_ENDPOINT: + idx = USBD_CoreFindEP(pdev, LOBYTE(pdev->request.wIndex)); + break; + + default: + /* Back to the first class in case of doubt */ + idx = 0U; + break; + } + + if (idx < USBD_MAX_SUPPORTED_CLASS) + { + /* Setup the class ID and route the request to the relative class function */ + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if (pdev->pClass[idx]->EP0_RxReady != NULL) + { + pdev->classId = idx; + pdev->pClass[idx]->EP0_RxReady(pdev); + } + } + } + + (void)USBD_CtlSendStatus(pdev); + } + } + } + else + { + /* Get the class index relative to this interface */ + idx = USBD_CoreFindEP(pdev, (epnum & 0x7FU)); + + if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS)) + { + /* Call the class data out function to manage the request */ + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if (pdev->pClass[idx]->DataOut != NULL) + { + pdev->classId = idx; + ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataOut(pdev, epnum); + } + } + if (ret != USBD_OK) + { + return ret; + } + } + } + + return USBD_OK; +} + +/** + * @brief USBD_LL_DataInStage + * Handle data in stage + * @param pdev: device instance + * @param epnum: endpoint index + * @param pdata: data pointer + * @retval status + */ +USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev, + uint8_t epnum, uint8_t *pdata) +{ + USBD_EndpointTypeDef *pep; + USBD_StatusTypeDef ret; + uint8_t idx; + + if (epnum == 0U) + { + pep = &pdev->ep_in[0]; + + if (pdev->ep0_state == USBD_EP0_DATA_IN) + { + if (pep->rem_length > pep->maxpacket) + { + pep->rem_length -= pep->maxpacket; + + (void)USBD_CtlContinueSendData(pdev, pdata, pep->rem_length); + + /* Prepare endpoint for premature end of transfer */ + (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U); + } + else + { + /* last packet is MPS multiple, so send ZLP packet */ + if ((pep->maxpacket == pep->rem_length) && + (pep->total_length >= pep->maxpacket) && + (pep->total_length < pdev->ep0_data_len)) + { + (void)USBD_CtlContinueSendData(pdev, NULL, 0U); + pdev->ep0_data_len = 0U; + + /* Prepare endpoint for premature end of transfer */ + (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U); + } + else + { + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if (pdev->pClass[0]->EP0_TxSent != NULL) + { + pdev->classId = 0U; + pdev->pClass[0]->EP0_TxSent(pdev); + } + } + (void)USBD_LL_StallEP(pdev, 0x80U); + (void)USBD_CtlReceiveStatus(pdev); + } + } + } + + if (pdev->dev_test_mode != 0U) + { + (void)USBD_RunTestMode(pdev); + pdev->dev_test_mode = 0U; + } + } + else + { + /* Get the class index relative to this interface */ + idx = USBD_CoreFindEP(pdev, ((uint8_t)epnum | 0x80U)); + + if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS)) + { + /* Call the class data out function to manage the request */ + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if (pdev->pClass[idx]->DataIn != NULL) + { + pdev->classId = idx; + ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataIn(pdev, epnum); + + if (ret != USBD_OK) + { + return ret; + } + } + } + } + } + + return USBD_OK; +} + +/** + * @brief USBD_LL_Reset + * Handle Reset event + * @param pdev: device instance + * @retval status + */ +USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev) +{ + USBD_StatusTypeDef ret = USBD_OK; + + /* Upon Reset call user call back */ + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->ep0_state = USBD_EP0_IDLE; + pdev->dev_config = 0U; + pdev->dev_remote_wakeup = 0U; + pdev->dev_test_mode = 0U; + +#ifdef USE_USBD_COMPOSITE + /* Parse the table of classes in use */ + for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++) + { + /* Check if current class is in use */ + if ((pdev->tclasslist[i].Active) == 1U) + { + if (pdev->pClass[i] != NULL) + { + pdev->classId = i; + /* Clear configuration and De-initialize the Class process*/ + + if (pdev->pClass[i]->DeInit != NULL) + { + if (pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config) != USBD_OK) + { + ret = USBD_FAIL; + } + } + } + } + } +#else + + if (pdev->pClass[0] != NULL) + { + if (pdev->pClass[0]->DeInit != NULL) + { + if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != USBD_OK) + { + ret = USBD_FAIL; + } + } + } +#endif /* USE_USBD_COMPOSITE */ + + /* Open EP0 OUT */ + (void)USBD_LL_OpenEP(pdev, 0x00U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE); + pdev->ep_out[0x00U & 0xFU].is_used = 1U; + + pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE; + + /* Open EP0 IN */ + (void)USBD_LL_OpenEP(pdev, 0x80U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE); + pdev->ep_in[0x80U & 0xFU].is_used = 1U; + + pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE; + + return ret; +} + +/** + * @brief USBD_LL_SetSpeed + * Handle Reset event + * @param pdev: device instance + * @retval status + */ +USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, + USBD_SpeedTypeDef speed) +{ + pdev->dev_speed = speed; + + return USBD_OK; +} + +/** + * @brief USBD_LL_Suspend + * Handle Suspend event + * @param pdev: device instance + * @retval status + */ +USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev) +{ + if (pdev->dev_state != USBD_STATE_SUSPENDED) + { + pdev->dev_old_state = pdev->dev_state; + } + + pdev->dev_state = USBD_STATE_SUSPENDED; + + return USBD_OK; +} + +/** + * @brief USBD_LL_Resume + * Handle Resume event + * @param pdev: device instance + * @retval status + */ +USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev) +{ + if (pdev->dev_state == USBD_STATE_SUSPENDED) + { + pdev->dev_state = pdev->dev_old_state; + } + + return USBD_OK; +} + +/** + * @brief USBD_LL_SOF + * Handle SOF event + * @param pdev: device instance + * @retval status + */ +USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev) +{ + /* The SOF event can be distributed for all classes that support it */ + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { +#ifdef USE_USBD_COMPOSITE + /* Parse the table of classes in use */ + for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++) + { + /* Check if current class is in use */ + if ((pdev->tclasslist[i].Active) == 1U) + { + if (pdev->pClass[i] != NULL) + { + if (pdev->pClass[i]->SOF != NULL) + { + pdev->classId = i; + (void)pdev->pClass[i]->SOF(pdev); + } + } + } + } +#else + if (pdev->pClass[0] != NULL) + { + if (pdev->pClass[0]->SOF != NULL) + { + (void)pdev->pClass[0]->SOF(pdev); + } + } +#endif /* USE_USBD_COMPOSITE */ + } + + return USBD_OK; +} + +/** + * @brief USBD_LL_IsoINIncomplete + * Handle iso in incomplete event + * @param pdev: device instance + * @param epnum: Endpoint number + * @retval status + */ +USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, + uint8_t epnum) +{ + if (pdev->pClass[pdev->classId] == NULL) + { + return USBD_FAIL; + } + + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if (pdev->pClass[pdev->classId]->IsoINIncomplete != NULL) + { + (void)pdev->pClass[pdev->classId]->IsoINIncomplete(pdev, epnum); + } + } + + return USBD_OK; +} + +/** + * @brief USBD_LL_IsoOUTIncomplete + * Handle iso out incomplete event + * @param pdev: device instance + * @param epnum: Endpoint number + * @retval status + */ +USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, + uint8_t epnum) +{ + if (pdev->pClass[pdev->classId] == NULL) + { + return USBD_FAIL; + } + + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if (pdev->pClass[pdev->classId]->IsoOUTIncomplete != NULL) + { + (void)pdev->pClass[pdev->classId]->IsoOUTIncomplete(pdev, epnum); + } + } + + return USBD_OK; +} + +/** + * @brief USBD_LL_DevConnected + * Handle device connection event + * @param pdev: device instance + * @retval status + */ +USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev) +{ + /* Prevent unused argument compilation warning */ + UNUSED(pdev); + + return USBD_OK; +} + +/** + * @brief USBD_LL_DevDisconnected + * Handle device disconnection event + * @param pdev: device instance + * @retval status + */ +USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev) +{ + USBD_StatusTypeDef ret = USBD_OK; + + /* Free Class Resources */ + pdev->dev_state = USBD_STATE_DEFAULT; + +#ifdef USE_USBD_COMPOSITE + /* Parse the table of classes in use */ + for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++) + { + /* Check if current class is in use */ + if ((pdev->tclasslist[i].Active) == 1U) + { + if (pdev->pClass[i] != NULL) + { + pdev->classId = i; + /* Clear configuration and De-initialize the Class process*/ + if (pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U) + { + ret = USBD_FAIL; + } + } + } + } +#else + if (pdev->pClass[0] != NULL) + { + if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U) + { + ret = USBD_FAIL; + } + } +#endif /* USE_USBD_COMPOSITE */ + + return ret; +} + +/** + * @brief USBD_CoreFindIF + * return the class index relative to the selected interface + * @param pdev: device instance + * @param index : selected interface number + * @retval index of the class using the selected interface number. OxFF if no class found. + */ +uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index) +{ +#ifdef USE_USBD_COMPOSITE + /* Parse the table of classes in use */ + for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++) + { + /* Check if current class is in use */ + if ((pdev->tclasslist[i].Active) == 1U) + { + /* Parse all interfaces listed in the current class */ + for (uint32_t j = 0U; j < pdev->tclasslist[i].NumIf; j++) + { + /* Check if requested Interface matches the current class interface */ + if (pdev->tclasslist[i].Ifs[j] == index) + { + if (pdev->pClass[i]->Setup != NULL) + { + return (uint8_t)i; + } + } + } + } + } + + return 0xFFU; +#else + UNUSED(pdev); + UNUSED(index); + + return 0x00U; +#endif /* USE_USBD_COMPOSITE */ +} + +/** + * @brief USBD_CoreFindEP + * return the class index relative to the selected endpoint + * @param pdev: device instance + * @param index : selected endpoint number + * @retval index of the class using the selected endpoint number. 0xFF if no class found. + */ +uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index) +{ +#ifdef USE_USBD_COMPOSITE + /* Parse the table of classes in use */ + for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++) + { + /* Check if current class is in use */ + if ((pdev->tclasslist[i].Active) == 1U) + { + /* Parse all endpoints listed in the current class */ + for (uint32_t j = 0U; j < pdev->tclasslist[i].NumEps; j++) + { + /* Check if requested endpoint matches the current class endpoint */ + if (pdev->tclasslist[i].Eps[j].add == index) + { + if (pdev->pClass[i]->Setup != NULL) + { + return (uint8_t)i; + } + } + } + } + } + + return 0xFFU; +#else + UNUSED(pdev); + UNUSED(index); + + return 0x00U; +#endif /* USE_USBD_COMPOSITE */ +} + +#ifdef USE_USBD_COMPOSITE +/** + * @brief USBD_CoreGetEPAdd + * Get the endpoint address relative to a selected class + * @param pdev: device instance + * @param ep_dir: USBD_EP_IN or USBD_EP_OUT + * @param ep_type: USBD_EP_TYPE_CTRL, USBD_EP_TYPE_ISOC, USBD_EP_TYPE_BULK or USBD_EP_TYPE_INTR + * @param ClassId: The Class ID + * @retval Address of the selected endpoint or 0xFFU if no endpoint found. + */ +uint8_t USBD_CoreGetEPAdd(USBD_HandleTypeDef *pdev, uint8_t ep_dir, uint8_t ep_type, uint8_t ClassId) +{ + uint8_t idx; + + /* Find the EP address in the selected class table */ + for (idx = 0; idx < pdev->tclasslist[ClassId].NumEps; idx++) + { + if (((pdev->tclasslist[ClassId].Eps[idx].add & USBD_EP_IN) == ep_dir) && \ + (pdev->tclasslist[ClassId].Eps[idx].type == ep_type) && \ + (pdev->tclasslist[ClassId].Eps[idx].is_used != 0U)) + { + return (pdev->tclasslist[ClassId].Eps[idx].add); + } + } + + /* If reaching this point, then no endpoint was found */ + return 0xFFU; +} +#endif /* USE_USBD_COMPOSITE */ + +/** + * @brief USBD_GetEpDesc + * This function return the Endpoint descriptor + * @param pdev: device instance + * @param pConfDesc: pointer to Bos descriptor + * @param EpAddr: endpoint address + * @retval pointer to video endpoint descriptor + */ +void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr) +{ + USBD_DescHeaderTypeDef *pdesc = (USBD_DescHeaderTypeDef *)(void *)pConfDesc; + USBD_ConfigDescTypeDef *desc = (USBD_ConfigDescTypeDef *)(void *)pConfDesc; + USBD_EpDescTypeDef *pEpDesc = NULL; + uint16_t ptr; + + if (desc->wTotalLength > desc->bLength) + { + ptr = desc->bLength; + + while (ptr < desc->wTotalLength) + { + pdesc = USBD_GetNextDesc((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT) + { + pEpDesc = (USBD_EpDescTypeDef *)(void *)pdesc; + + if (pEpDesc->bEndpointAddress == EpAddr) + { + break; + } + else + { + pEpDesc = NULL; + } + } + } + } + + return (void *)pEpDesc; +} + +/** + * @brief USBD_GetNextDesc + * This function return the next descriptor header + * @param buf: Buffer where the descriptor is available + * @param ptr: data pointer inside the descriptor + * @retval next header + */ +USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr) +{ + USBD_DescHeaderTypeDef *pnext = (USBD_DescHeaderTypeDef *)(void *)pbuf; + + *ptr += pnext->bLength; + pnext = (USBD_DescHeaderTypeDef *)(void *)(pbuf + pnext->bLength); + + return (pnext); +} + +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + diff --git a/lib/USB_CDC/src/usbd_ctlreq.c b/lib/USB_CDC/src/usbd_ctlreq.c new file mode 100644 index 0000000..fa6ffcf --- /dev/null +++ b/lib/USB_CDC/src/usbd_ctlreq.c @@ -0,0 +1,1058 @@ +/** + ****************************************************************************** + * @file usbd_req.c + * @author MCD Application Team + * @brief This file provides the standard USB requests following chapter 9. + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ctlreq.h" +#include "usbd_ioreq.h" + +#ifdef USE_USBD_COMPOSITE +#include "usbd_composite_builder.h" +#endif /* USE_USBD_COMPOSITE */ + +/** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_REQ + * @brief USB standard requests module + * @{ + */ + +/** @defgroup USBD_REQ_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Defines + * @{ + */ +#ifndef USBD_MAX_STR_DESC_SIZ +#define USBD_MAX_STR_DESC_SIZ 64U +#endif /* USBD_MAX_STR_DESC_SIZ */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Macros + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_FunctionPrototypes + * @{ + */ +static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void USBD_SetAddress(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static USBD_StatusTypeDef USBD_SetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void USBD_SetFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void USBD_ClrFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static uint8_t USBD_GetLen(uint8_t *buf); + +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Functions + * @{ + */ + + +/** + * @brief USBD_StdDevReq + * Handle standard usb device requests + * @param pdev: device instance + * @param req: usb request + * @retval status + */ +USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_StatusTypeDef ret = USBD_OK; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + case USB_REQ_TYPE_VENDOR: + ret = (USBD_StatusTypeDef)pdev->pClass[pdev->classId]->Setup(pdev, req); + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_DESCRIPTOR: + USBD_GetDescriptor(pdev, req); + break; + + case USB_REQ_SET_ADDRESS: + USBD_SetAddress(pdev, req); + break; + + case USB_REQ_SET_CONFIGURATION: + ret = USBD_SetConfig(pdev, req); + break; + + case USB_REQ_GET_CONFIGURATION: + USBD_GetConfig(pdev, req); + break; + + case USB_REQ_GET_STATUS: + USBD_GetStatus(pdev, req); + break; + + case USB_REQ_SET_FEATURE: + USBD_SetFeature(pdev, req); + break; + + case USB_REQ_CLEAR_FEATURE: + USBD_ClrFeature(pdev, req); + break; + + default: + USBD_CtlError(pdev, req); + break; + } + break; + + default: + USBD_CtlError(pdev, req); + break; + } + + return ret; +} + +/** + * @brief USBD_StdItfReq + * Handle standard usb interface requests + * @param pdev: device instance + * @param req: usb request + * @retval status + */ +USBD_StatusTypeDef USBD_StdItfReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_StatusTypeDef ret = USBD_OK; + uint8_t idx; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + case USB_REQ_TYPE_VENDOR: + case USB_REQ_TYPE_STANDARD: + switch (pdev->dev_state) + { + case USBD_STATE_DEFAULT: + case USBD_STATE_ADDRESSED: + case USBD_STATE_CONFIGURED: + + if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES) + { + /* Get the class index relative to this interface */ + idx = USBD_CoreFindIF(pdev, LOBYTE(req->wIndex)); + if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS)) + { + /* Call the class data out function to manage the request */ + if (pdev->pClass[idx]->Setup != NULL) + { + pdev->classId = idx; + ret = (USBD_StatusTypeDef)(pdev->pClass[idx]->Setup(pdev, req)); + } + else + { + /* should never reach this condition */ + ret = USBD_FAIL; + } + } + else + { + /* No relative interface found */ + ret = USBD_FAIL; + } + + if ((req->wLength == 0U) && (ret == USBD_OK)) + { + (void)USBD_CtlSendStatus(pdev); + } + } + else + { + USBD_CtlError(pdev, req); + } + break; + + default: + USBD_CtlError(pdev, req); + break; + } + break; + + default: + USBD_CtlError(pdev, req); + break; + } + + return ret; +} + +/** + * @brief USBD_StdEPReq + * Handle standard usb endpoint requests + * @param pdev: device instance + * @param req: usb request + * @retval status + */ +USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_EndpointTypeDef *pep; + uint8_t ep_addr; + uint8_t idx; + USBD_StatusTypeDef ret = USBD_OK; + + ep_addr = LOBYTE(req->wIndex); + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + case USB_REQ_TYPE_VENDOR: + /* Get the class index relative to this endpoint */ + idx = USBD_CoreFindEP(pdev, ep_addr); + if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS)) + { + pdev->classId = idx; + /* Call the class data out function to manage the request */ + if (pdev->pClass[idx]->Setup != NULL) + { + ret = (USBD_StatusTypeDef)pdev->pClass[idx]->Setup(pdev, req); + } + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_SET_FEATURE: + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if ((ep_addr != 0x00U) && (ep_addr != 0x80U)) + { + (void)USBD_LL_StallEP(pdev, ep_addr); + (void)USBD_LL_StallEP(pdev, 0x80U); + } + else + { + USBD_CtlError(pdev, req); + } + break; + + case USBD_STATE_CONFIGURED: + if (req->wValue == USB_FEATURE_EP_HALT) + { + if ((ep_addr != 0x00U) && (ep_addr != 0x80U) && (req->wLength == 0x00U)) + { + (void)USBD_LL_StallEP(pdev, ep_addr); + } + } + (void)USBD_CtlSendStatus(pdev); + + break; + + default: + USBD_CtlError(pdev, req); + break; + } + break; + + case USB_REQ_CLEAR_FEATURE: + + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if ((ep_addr != 0x00U) && (ep_addr != 0x80U)) + { + (void)USBD_LL_StallEP(pdev, ep_addr); + (void)USBD_LL_StallEP(pdev, 0x80U); + } + else + { + USBD_CtlError(pdev, req); + } + break; + + case USBD_STATE_CONFIGURED: + if (req->wValue == USB_FEATURE_EP_HALT) + { + if ((ep_addr & 0x7FU) != 0x00U) + { + (void)USBD_LL_ClearStallEP(pdev, ep_addr); + } + (void)USBD_CtlSendStatus(pdev); + + /* Get the class index relative to this interface */ + idx = USBD_CoreFindEP(pdev, ep_addr); + if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS)) + { + pdev->classId = idx; + /* Call the class data out function to manage the request */ + if (pdev->pClass[idx]->Setup != NULL) + { + ret = (USBD_StatusTypeDef)(pdev->pClass[idx]->Setup(pdev, req)); + } + } + } + break; + + default: + USBD_CtlError(pdev, req); + break; + } + break; + + case USB_REQ_GET_STATUS: + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if ((ep_addr != 0x00U) && (ep_addr != 0x80U)) + { + USBD_CtlError(pdev, req); + break; + } + pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU] : \ + &pdev->ep_out[ep_addr & 0x7FU]; + + pep->status = 0x0000U; + + (void)USBD_CtlSendData(pdev, (uint8_t *)&pep->status, 2U); + break; + + case USBD_STATE_CONFIGURED: + if ((ep_addr & 0x80U) == 0x80U) + { + if (pdev->ep_in[ep_addr & 0xFU].is_used == 0U) + { + USBD_CtlError(pdev, req); + break; + } + } + else + { + if (pdev->ep_out[ep_addr & 0xFU].is_used == 0U) + { + USBD_CtlError(pdev, req); + break; + } + } + + pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU] : \ + &pdev->ep_out[ep_addr & 0x7FU]; + + if ((ep_addr == 0x00U) || (ep_addr == 0x80U)) + { + pep->status = 0x0000U; + } + else if (USBD_LL_IsStallEP(pdev, ep_addr) != 0U) + { + pep->status = 0x0001U; + } + else + { + pep->status = 0x0000U; + } + + (void)USBD_CtlSendData(pdev, (uint8_t *)&pep->status, 2U); + break; + + default: + USBD_CtlError(pdev, req); + break; + } + break; + + default: + USBD_CtlError(pdev, req); + break; + } + break; + + default: + USBD_CtlError(pdev, req); + break; + } + + return ret; +} + + +/** + * @brief USBD_GetDescriptor + * Handle Get Descriptor requests + * @param pdev: device instance + * @param req: usb request + * @retval None + */ +static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + uint16_t len = 0U; + uint8_t *pbuf = NULL; + uint8_t err = 0U; + + switch (req->wValue >> 8) + { +#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1U)) + case USB_DESC_TYPE_BOS: + if (pdev->pDesc->GetBOSDescriptor != NULL) + { + pbuf = pdev->pDesc->GetBOSDescriptor(pdev->dev_speed, &len); + } + else + { + USBD_CtlError(pdev, req); + err++; + } + break; +#endif /* (USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1U) */ + case USB_DESC_TYPE_DEVICE: + pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len); + break; + + case USB_DESC_TYPE_CONFIGURATION: + if (pdev->dev_speed == USBD_SPEED_HIGH) + { +#ifdef USE_USBD_COMPOSITE + if ((uint8_t)(pdev->NumClasses) > 0U) + { + pbuf = (uint8_t *)USBD_CMPSIT.GetHSConfigDescriptor(&len); + } + else +#endif /* USE_USBD_COMPOSITE */ + { + pbuf = (uint8_t *)pdev->pClass[0]->GetHSConfigDescriptor(&len); + } + pbuf[1] = USB_DESC_TYPE_CONFIGURATION; + } + else + { +#ifdef USE_USBD_COMPOSITE + if ((uint8_t)(pdev->NumClasses) > 0U) + { + pbuf = (uint8_t *)USBD_CMPSIT.GetFSConfigDescriptor(&len); + } + else +#endif /* USE_USBD_COMPOSITE */ + { + pbuf = (uint8_t *)pdev->pClass[0]->GetFSConfigDescriptor(&len); + } + pbuf[1] = USB_DESC_TYPE_CONFIGURATION; + } + break; + + case USB_DESC_TYPE_STRING: + switch ((uint8_t)(req->wValue)) + { + case USBD_IDX_LANGID_STR: + if (pdev->pDesc->GetLangIDStrDescriptor != NULL) + { + pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len); + } + else + { + USBD_CtlError(pdev, req); + err++; + } + break; + + case USBD_IDX_MFC_STR: + if (pdev->pDesc->GetManufacturerStrDescriptor != NULL) + { + pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len); + } + else + { + USBD_CtlError(pdev, req); + err++; + } + break; + + case USBD_IDX_PRODUCT_STR: + if (pdev->pDesc->GetProductStrDescriptor != NULL) + { + pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len); + } + else + { + USBD_CtlError(pdev, req); + err++; + } + break; + + case USBD_IDX_SERIAL_STR: + if (pdev->pDesc->GetSerialStrDescriptor != NULL) + { + pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len); + } + else + { + USBD_CtlError(pdev, req); + err++; + } + break; + + case USBD_IDX_CONFIG_STR: + if (pdev->pDesc->GetConfigurationStrDescriptor != NULL) + { + pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len); + } + else + { + USBD_CtlError(pdev, req); + err++; + } + break; + + case USBD_IDX_INTERFACE_STR: + if (pdev->pDesc->GetInterfaceStrDescriptor != NULL) + { + pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len); + } + else + { + USBD_CtlError(pdev, req); + err++; + } + break; + + default: +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) + pbuf = NULL; + + for (uint32_t idx = 0U; (idx < pdev->NumClasses); idx++) + { + if (pdev->pClass[idx]->GetUsrStrDescriptor != NULL) + { + pdev->classId = idx; + pbuf = pdev->pClass[idx]->GetUsrStrDescriptor(pdev, LOBYTE(req->wValue), &len); + + if (pbuf == NULL) /* This means that no class recognized the string index */ + { + continue; + } + else + { + break; + } + } + } +#endif /* USBD_SUPPORT_USER_STRING_DESC */ + +#if (USBD_CLASS_USER_STRING_DESC == 1U) + if (pdev->pDesc->GetUserStrDescriptor != NULL) + { + pbuf = pdev->pDesc->GetUserStrDescriptor(pdev->dev_speed, LOBYTE(req->wValue), &len); + } + else + { + USBD_CtlError(pdev, req); + err++; + } +#endif /* USBD_SUPPORT_USER_STRING_DESC */ + +#if ((USBD_CLASS_USER_STRING_DESC == 0U) && (USBD_SUPPORT_USER_STRING_DESC == 0U)) + USBD_CtlError(pdev, req); + err++; +#endif /* (USBD_CLASS_USER_STRING_DESC == 0U) && (USBD_SUPPORT_USER_STRING_DESC == 0U) */ + break; + } + break; + + case USB_DESC_TYPE_DEVICE_QUALIFIER: + if (pdev->dev_speed == USBD_SPEED_HIGH) + { +#ifdef USE_USBD_COMPOSITE + if ((uint8_t)(pdev->NumClasses) > 0U) + { + pbuf = (uint8_t *)USBD_CMPSIT.GetDeviceQualifierDescriptor(&len); + } + else +#endif /* USE_USBD_COMPOSITE */ + { + pbuf = (uint8_t *)pdev->pClass[0]->GetDeviceQualifierDescriptor(&len); + } + } + else + { + USBD_CtlError(pdev, req); + err++; + } + break; + + case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: + if (pdev->dev_speed == USBD_SPEED_HIGH) + { +#ifdef USE_USBD_COMPOSITE + if ((uint8_t)(pdev->NumClasses) > 0U) + { + pbuf = (uint8_t *)USBD_CMPSIT.GetOtherSpeedConfigDescriptor(&len); + } + else +#endif /* USE_USBD_COMPOSITE */ + { + pbuf = (uint8_t *)pdev->pClass[0]->GetOtherSpeedConfigDescriptor(&len); + } + pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION; + } + else + { + USBD_CtlError(pdev, req); + err++; + } + break; + + default: + USBD_CtlError(pdev, req); + err++; + break; + } + + if (err != 0U) + { + return; + } + + if (req->wLength != 0U) + { + if (len != 0U) + { + len = MIN(len, req->wLength); + (void)USBD_CtlSendData(pdev, pbuf, len); + } + else + { + USBD_CtlError(pdev, req); + } + } + else + { + (void)USBD_CtlSendStatus(pdev); + } +} + + +/** + * @brief USBD_SetAddress + * Set device address + * @param pdev: device instance + * @param req: usb request + * @retval None + */ +static void USBD_SetAddress(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + uint8_t dev_addr; + + if ((req->wIndex == 0U) && (req->wLength == 0U) && (req->wValue < 128U)) + { + dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + USBD_CtlError(pdev, req); + } + else + { + pdev->dev_address = dev_addr; + (void)USBD_LL_SetUSBAddress(pdev, dev_addr); + (void)USBD_CtlSendStatus(pdev); + + if (dev_addr != 0U) + { + pdev->dev_state = USBD_STATE_ADDRESSED; + } + else + { + pdev->dev_state = USBD_STATE_DEFAULT; + } + } + } + else + { + USBD_CtlError(pdev, req); + } +} + +/** + * @brief USBD_SetConfig + * Handle Set device configuration request + * @param pdev: device instance + * @param req: usb request + * @retval status + */ +static USBD_StatusTypeDef USBD_SetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_StatusTypeDef ret = USBD_OK; + static uint8_t cfgidx; + + cfgidx = (uint8_t)(req->wValue); + + if (cfgidx > USBD_MAX_NUM_CONFIGURATION) + { + USBD_CtlError(pdev, req); + return USBD_FAIL; + } + + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if (cfgidx != 0U) + { + pdev->dev_config = cfgidx; + + ret = USBD_SetClassConfig(pdev, cfgidx); + + if (ret != USBD_OK) + { + USBD_CtlError(pdev, req); + pdev->dev_state = USBD_STATE_ADDRESSED; + } + else + { + (void)USBD_CtlSendStatus(pdev); + pdev->dev_state = USBD_STATE_CONFIGURED; + +#if (USBD_USER_REGISTER_CALLBACK == 1U) + if (pdev->DevStateCallback != NULL) + { + pdev->DevStateCallback(USBD_STATE_CONFIGURED, cfgidx); + } +#endif /* USBD_USER_REGISTER_CALLBACK */ + } + } + else + { + (void)USBD_CtlSendStatus(pdev); + } + break; + + case USBD_STATE_CONFIGURED: + if (cfgidx == 0U) + { + pdev->dev_state = USBD_STATE_ADDRESSED; + pdev->dev_config = cfgidx; + (void)USBD_ClrClassConfig(pdev, cfgidx); + (void)USBD_CtlSendStatus(pdev); + } + else if (cfgidx != pdev->dev_config) + { + /* Clear old configuration */ + (void)USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config); + + /* set new configuration */ + pdev->dev_config = cfgidx; + + ret = USBD_SetClassConfig(pdev, cfgidx); + + if (ret != USBD_OK) + { + USBD_CtlError(pdev, req); + (void)USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config); + pdev->dev_state = USBD_STATE_ADDRESSED; + } + else + { + (void)USBD_CtlSendStatus(pdev); + } + } + else + { + (void)USBD_CtlSendStatus(pdev); + } + break; + + default: + USBD_CtlError(pdev, req); + (void)USBD_ClrClassConfig(pdev, cfgidx); + ret = USBD_FAIL; + break; + } + + return ret; +} + +/** + * @brief USBD_GetConfig + * Handle Get device configuration request + * @param pdev: device instance + * @param req: usb request + * @retval None + */ +static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + if (req->wLength != 1U) + { + USBD_CtlError(pdev, req); + } + else + { + switch (pdev->dev_state) + { + case USBD_STATE_DEFAULT: + case USBD_STATE_ADDRESSED: + pdev->dev_default_config = 0U; + (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_default_config, 1U); + break; + + case USBD_STATE_CONFIGURED: + (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_config, 1U); + break; + + default: + USBD_CtlError(pdev, req); + break; + } + } +} + +/** + * @brief USBD_GetStatus + * Handle Get Status request + * @param pdev: device instance + * @param req: usb request + * @retval None + */ +static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + switch (pdev->dev_state) + { + case USBD_STATE_DEFAULT: + case USBD_STATE_ADDRESSED: + case USBD_STATE_CONFIGURED: + if (req->wLength != 0x2U) + { + USBD_CtlError(pdev, req); + break; + } + +#if (USBD_SELF_POWERED == 1U) + pdev->dev_config_status = USB_CONFIG_SELF_POWERED; +#else + pdev->dev_config_status = 0U; +#endif /* USBD_SELF_POWERED */ + + if (pdev->dev_remote_wakeup != 0U) + { + pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP; + } + + (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_config_status, 2U); + break; + + default: + USBD_CtlError(pdev, req); + break; + } +} + + +/** + * @brief USBD_SetFeature + * Handle Set device feature request + * @param pdev: device instance + * @param req: usb request + * @retval None + */ +static void USBD_SetFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) + { + pdev->dev_remote_wakeup = 1U; + (void)USBD_CtlSendStatus(pdev); + } + else if (req->wValue == USB_FEATURE_TEST_MODE) + { + pdev->dev_test_mode = (uint8_t)(req->wIndex >> 8); + (void)USBD_CtlSendStatus(pdev); + } + else + { + USBD_CtlError(pdev, req); + } +} + + +/** + * @brief USBD_ClrFeature + * Handle clear device feature request + * @param pdev: device instance + * @param req: usb request + * @retval None + */ +static void USBD_ClrFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + switch (pdev->dev_state) + { + case USBD_STATE_DEFAULT: + case USBD_STATE_ADDRESSED: + case USBD_STATE_CONFIGURED: + if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) + { + pdev->dev_remote_wakeup = 0U; + (void)USBD_CtlSendStatus(pdev); + } + break; + + default: + USBD_CtlError(pdev, req); + break; + } +} + + +/** + * @brief USBD_ParseSetupRequest + * Copy buffer into setup structure + * @param req: usb request + * @param pdata: setup data pointer + * @retval None + */ +void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata) +{ + uint8_t *pbuff = pdata; + + req->bmRequest = *(uint8_t *)(pbuff); + + pbuff++; + req->bRequest = *(uint8_t *)(pbuff); + + pbuff++; + req->wValue = SWAPBYTE(pbuff); + + pbuff++; + pbuff++; + req->wIndex = SWAPBYTE(pbuff); + + pbuff++; + pbuff++; + req->wLength = SWAPBYTE(pbuff); +} + + +/** + * @brief USBD_CtlError + * Handle USB low level Error + * @param pdev: device instance + * @param req: usb request + * @retval None + */ +void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + UNUSED(req); + + (void)USBD_LL_StallEP(pdev, 0x80U); + (void)USBD_LL_StallEP(pdev, 0U); +} + + +/** + * @brief USBD_GetString + * Convert Ascii string into unicode one + * @param desc : descriptor buffer + * @param unicode : Formatted string buffer (unicode) + * @param len : descriptor length + * @retval None + */ +void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len) +{ + uint8_t idx = 0U; + uint8_t *pdesc; + + if (desc == NULL) + { + return; + } + + pdesc = desc; + *len = MIN(USBD_MAX_STR_DESC_SIZ, ((uint16_t)USBD_GetLen(pdesc) * 2U) + 2U); + + unicode[idx] = *(uint8_t *)len; + idx++; + unicode[idx] = USB_DESC_TYPE_STRING; + idx++; + + while (*pdesc != (uint8_t)'\0') + { + unicode[idx] = *pdesc; + pdesc++; + idx++; + + unicode[idx] = 0U; + idx++; + } +} + + +/** + * @brief USBD_GetLen + * return the string length + * @param buf : pointer to the ascii string buffer + * @retval string length + */ +static uint8_t USBD_GetLen(uint8_t *buf) +{ + uint8_t len = 0U; + uint8_t *pbuff = buf; + + while (*pbuff != (uint8_t)'\0') + { + len++; + pbuff++; + } + + return len; +} +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + diff --git a/lib/USB_CDC/src/usbd_desc.c b/lib/USB_CDC/src/usbd_desc.c new file mode 100644 index 0000000..3c467cd --- /dev/null +++ b/lib/USB_CDC/src/usbd_desc.c @@ -0,0 +1,63 @@ +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_conf.h" + +#define USBD_VID 0x0483 /* STMicroelectronics */ +#define USBD_PID_FS 0x5740 /* CDC Virtual COM Port */ +#define USBD_LANGID_STRING 0x0409 /* English US */ +#define USBD_MFR_STRING "SaltyLab" +#define USBD_PRODUCT_STRING "SaltyLab IMU" +#define USBD_SERIAL_STRING "SALTY001" + +static uint8_t *USBD_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); + +USBD_DescriptorsTypeDef SaltyLab_Desc = { + USBD_DeviceDescriptor, + USBD_LangIDStrDescriptor, + USBD_ManufacturerStrDescriptor, + USBD_ProductStrDescriptor, + USBD_SerialStrDescriptor, + USBD_ConfigStrDescriptor, + USBD_InterfaceStrDescriptor, +}; + +static uint8_t USBD_DeviceDesc[USB_LEN_DEV_DESC] = { + 0x12, USB_DESC_TYPE_DEVICE, 0x00, 0x02, 0x02, 0x02, 0x00, + 64, LOBYTE(USBD_VID), HIBYTE(USBD_VID), LOBYTE(USBD_PID_FS), HIBYTE(USBD_PID_FS), + 0x00, 0x02, 1, 2, 3, 1 +}; + +static uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] = { + USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), HIBYTE(USBD_LANGID_STRING) +}; + +static uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ]; + +static uint8_t *USBD_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + (void)speed; *length = sizeof(USBD_DeviceDesc); return USBD_DeviceDesc; +} +static uint8_t *USBD_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + (void)speed; *length = sizeof(USBD_LangIDDesc); return USBD_LangIDDesc; +} +static uint8_t *USBD_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString((uint8_t *)USBD_MFR_STRING, USBD_StrDesc, length); return USBD_StrDesc; +} +static uint8_t *USBD_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString((uint8_t *)USBD_PRODUCT_STRING, USBD_StrDesc, length); return USBD_StrDesc; +} +static uint8_t *USBD_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString((uint8_t *)USBD_SERIAL_STRING, USBD_StrDesc, length); return USBD_StrDesc; +} +static uint8_t *USBD_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString((uint8_t *)"CDC Config", USBD_StrDesc, length); return USBD_StrDesc; +} +static uint8_t *USBD_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString((uint8_t *)"CDC Interface", USBD_StrDesc, length); return USBD_StrDesc; +} diff --git a/lib/USB_CDC/src/usbd_ioreq.c b/lib/USB_CDC/src/usbd_ioreq.c new file mode 100644 index 0000000..e8a44db --- /dev/null +++ b/lib/USB_CDC/src/usbd_ioreq.c @@ -0,0 +1,224 @@ +/** + ****************************************************************************** + * @file usbd_ioreq.c + * @author MCD Application Team + * @brief This file provides the IO requests APIs for control endpoints. + ****************************************************************************** + * @attention + * + * Copyright (c) 2015 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_IOREQ + * @brief control I/O requests module + * @{ + */ + +/** @defgroup USBD_IOREQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Functions + * @{ + */ + +/** + * @brief USBD_CtlSendData + * send data on the ctl pipe + * @param pdev: device instance + * @param buff: pointer to data buffer + * @param len: length of data to be sent + * @retval status + */ +USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev, + uint8_t *pbuf, uint32_t len) +{ + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_DATA_IN; + pdev->ep_in[0].total_length = len; + +#ifdef USBD_AVOID_PACKET_SPLIT_MPS + pdev->ep_in[0].rem_length = 0U; +#else + pdev->ep_in[0].rem_length = len; +#endif /* USBD_AVOID_PACKET_SPLIT_MPS */ + + /* Start the transfer */ + (void)USBD_LL_Transmit(pdev, 0x00U, pbuf, len); + + return USBD_OK; +} + +/** + * @brief USBD_CtlContinueSendData + * continue sending data on the ctl pipe + * @param pdev: device instance + * @param buff: pointer to data buffer + * @param len: length of data to be sent + * @retval status + */ +USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev, + uint8_t *pbuf, uint32_t len) +{ + /* Start the next transfer */ + (void)USBD_LL_Transmit(pdev, 0x00U, pbuf, len); + + return USBD_OK; +} + +/** + * @brief USBD_CtlPrepareRx + * receive data on the ctl pipe + * @param pdev: device instance + * @param buff: pointer to data buffer + * @param len: length of data to be received + * @retval status + */ +USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev, + uint8_t *pbuf, uint32_t len) +{ + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_DATA_OUT; + pdev->ep_out[0].total_length = len; + +#ifdef USBD_AVOID_PACKET_SPLIT_MPS + pdev->ep_out[0].rem_length = 0U; +#else + pdev->ep_out[0].rem_length = len; +#endif /* USBD_AVOID_PACKET_SPLIT_MPS */ + + /* Start the transfer */ + (void)USBD_LL_PrepareReceive(pdev, 0U, pbuf, len); + + return USBD_OK; +} + +/** + * @brief USBD_CtlContinueRx + * continue receive data on the ctl pipe + * @param pdev: device instance + * @param buff: pointer to data buffer + * @param len: length of data to be received + * @retval status + */ +USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev, + uint8_t *pbuf, uint32_t len) +{ + (void)USBD_LL_PrepareReceive(pdev, 0U, pbuf, len); + + return USBD_OK; +} + +/** + * @brief USBD_CtlSendStatus + * send zero lzngth packet on the ctl pipe + * @param pdev: device instance + * @retval status + */ +USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev) +{ + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_STATUS_IN; + + /* Start the transfer */ + (void)USBD_LL_Transmit(pdev, 0x00U, NULL, 0U); + + return USBD_OK; +} + +/** + * @brief USBD_CtlReceiveStatus + * receive zero lzngth packet on the ctl pipe + * @param pdev: device instance + * @retval status + */ +USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev) +{ + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_STATUS_OUT; + + /* Start the transfer */ + (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U); + + return USBD_OK; +} + +/** + * @brief USBD_GetRxCount + * returns the received data length + * @param pdev: device instance + * @param ep_addr: endpoint address + * @retval Rx Data blength + */ +uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + return USBD_LL_GetRxDataSize(pdev, ep_addr); +} + +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..82ebd17 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,18 @@ +[env:f722] +platform = ststm32 +board = nucleo_f722ze +framework = stm32cube +upload_protocol = dfu +upload_command = /opt/homebrew/bin/dfu-util -a 0 -s 0x08000000:leave -D $SOURCE +monitor_speed = 115200 +board_build.mcu = stm32f722ret6 +board_build.f_cpu = 216000000L +build_flags = + -DSTM32F722xx + -DUSE_HAL_DRIVER + -DHSE_VALUE=8000000U + -DUSE_USB_FS + -I include + -Os + -Wl,--defsym,_Min_Heap_Size=0x2000 + -Wl,--defsym,_Min_Stack_Size=0x1000 diff --git a/src/balance.c b/src/balance.c new file mode 100644 index 0000000..8659c0b --- /dev/null +++ b/src/balance.c @@ -0,0 +1,113 @@ +#include "balance.h" +#include "config.h" +#include + +/* MPU6000 raw to physical units (default ±2g, ±250°/s) */ +#define ACCEL_SCALE (1.0f / 16384.0f) /* LSB to g (±2g range) */ +#define GYRO_SCALE (1.0f / 131.0f) /* LSB to °/s (±250°/s range) */ + +/* Complementary filter coefficient — 0.98 trusts gyro, 0.02 corrects with accel */ +#define COMP_ALPHA 0.98f + +void balance_init(balance_t *b) { + b->state = BALANCE_DISARMED; + b->pitch_deg = 0.0f; + b->pitch_rate = 0.0f; + b->integral = 0.0f; + b->prev_error = 0.0f; + b->motor_cmd = 0; + + /* Default PID — conservative starting point */ + b->kp = PID_KP; + b->ki = PID_KI; + b->kd = PID_KD; + b->setpoint = 0.0f; + + /* Safety defaults from config */ + b->max_tilt = MAX_TILT_DEG; + b->max_speed = MAX_SPEED_LIMIT; +} + +void balance_update(balance_t *b, const icm42688_data_t *imu, float dt) { + if (dt <= 0.0f || dt > 0.1f) return; /* Sanity check dt */ + + /* Convert raw IMU to physical units */ + float ax = imu->ax * ACCEL_SCALE; + float ay = imu->ay * ACCEL_SCALE; + float az = imu->az * ACCEL_SCALE; + + /* + * Gyro axis for pitch depends on mounting orientation. + * MPU6000 on MAMBA F722S with CW270 alignment: + * Pitch rate = gx axis (adjust sign if needed during testing) + */ + float gyro_pitch_rate = imu->gx * GYRO_SCALE; + b->pitch_rate = gyro_pitch_rate; + + /* Accelerometer pitch angle (atan2 of forward/down axes) + * With CW270: pitch = atan2(ax, az) + * Adjust axes based on actual mounting during testing */ + float accel_pitch = atan2f(ax, az) * (180.0f / 3.14159265f); + + /* Complementary filter */ + b->pitch_deg = COMP_ALPHA * (b->pitch_deg + gyro_pitch_rate * dt) + + (1.0f - COMP_ALPHA) * accel_pitch; + + /* Safety: tilt cutoff */ + if (b->state == BALANCE_ARMED) { + if (fabsf(b->pitch_deg) > b->max_tilt) { + b->state = BALANCE_TILT_FAULT; + b->motor_cmd = 0; + b->integral = 0.0f; + return; + } + } + + if (b->state != BALANCE_ARMED) { + b->motor_cmd = 0; + b->integral = 0.0f; + b->prev_error = 0.0f; + return; + } + + /* PID */ + float error = b->setpoint - b->pitch_deg; + + /* Proportional */ + float p_term = b->kp * error; + + /* Integral with anti-windup */ + b->integral += error * dt; + if (b->integral > PID_INTEGRAL_MAX) b->integral = PID_INTEGRAL_MAX; + if (b->integral < -PID_INTEGRAL_MAX) b->integral = -PID_INTEGRAL_MAX; + float i_term = b->ki * b->integral; + + /* Derivative (on measurement to avoid setpoint kick) */ + float d_term = b->kd * (-gyro_pitch_rate); /* Use gyro directly, cleaner than differencing */ + + /* Sum and clamp */ + float output = p_term + i_term + d_term; + if (output > (float)b->max_speed) output = (float)b->max_speed; + if (output < -(float)b->max_speed) output = -(float)b->max_speed; + + b->motor_cmd = (int16_t)output; + b->prev_error = error; +} + +void balance_arm(balance_t *b) { + if (b->state == BALANCE_DISARMED) { + /* Only arm if roughly upright */ + if (fabsf(b->pitch_deg) < 10.0f) { + b->integral = 0.0f; + b->prev_error = 0.0f; + b->motor_cmd = 0; + b->state = BALANCE_ARMED; + } + } +} + +void balance_disarm(balance_t *b) { + b->state = BALANCE_DISARMED; + b->motor_cmd = 0; + b->integral = 0.0f; +} diff --git a/src/bmp280.c b/src/bmp280.c new file mode 100644 index 0000000..3035147 --- /dev/null +++ b/src/bmp280.c @@ -0,0 +1,107 @@ +/* BMP280 barometer driver — I2C1 */ +#include "stm32f7xx_hal.h" +#include "bmp280.h" + +static I2C_HandleTypeDef hi2c1; +#define BMP280_ADDR (0x76 << 1) /* SDO to GND = 0x76, to VCC = 0x77 */ + +/* Calibration data */ +static uint16_t dig_T1; +static int16_t dig_T2, dig_T3; +static uint16_t dig_P1; +static int16_t dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9; +static int32_t t_fine; + +static uint8_t i2c_read(uint8_t reg) { + uint8_t val = 0; + HAL_I2C_Mem_Read(&hi2c1, BMP280_ADDR, reg, 1, &val, 1, 100); + return val; +} + +static void i2c_read_burst(uint8_t reg, uint8_t *buf, uint8_t len) { + HAL_I2C_Mem_Read(&hi2c1, BMP280_ADDR, reg, 1, buf, len, 100); +} + +static void i2c_write(uint8_t reg, uint8_t val) { + HAL_I2C_Mem_Write(&hi2c1, BMP280_ADDR, reg, 1, &val, 1, 100); +} + +int bmp280_init(void) { + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_I2C1_CLK_ENABLE(); + + GPIO_InitTypeDef gpio = {0}; + gpio.Pin = GPIO_PIN_8 | GPIO_PIN_9; /* PB8=SCL, PB9=SDA */ + gpio.Mode = GPIO_MODE_AF_OD; + gpio.Pull = GPIO_PULLUP; + gpio.Speed = GPIO_SPEED_FREQ_HIGH; + gpio.Alternate = GPIO_AF4_I2C1; + HAL_GPIO_Init(GPIOB, &gpio); + + hi2c1.Instance = I2C1; + hi2c1.Init.Timing = 0x20404768; /* 100kHz @ 54MHz APB1 */ + hi2c1.Init.OwnAddress1 = 0; + hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c1) != HAL_OK) return -1; + + HAL_Delay(10); + + /* Check chip ID */ + uint8_t id = i2c_read(0xD0); + if (id != 0x58 && id != 0x60) return -(int)id; /* 0x58=BMP280, 0x60=BME280 */ + + /* Read calibration */ + uint8_t cal[26]; + i2c_read_burst(0x88, cal, 26); + dig_T1 = (uint16_t)(cal[1] << 8 | cal[0]); + dig_T2 = (int16_t)(cal[3] << 8 | cal[2]); + dig_T3 = (int16_t)(cal[5] << 8 | cal[4]); + dig_P1 = (uint16_t)(cal[7] << 8 | cal[6]); + dig_P2 = (int16_t)(cal[9] << 8 | cal[8]); + dig_P3 = (int16_t)(cal[11] << 8 | cal[10]); + dig_P4 = (int16_t)(cal[13] << 8 | cal[12]); + dig_P5 = (int16_t)(cal[15] << 8 | cal[14]); + dig_P6 = (int16_t)(cal[17] << 8 | cal[16]); + dig_P7 = (int16_t)(cal[19] << 8 | cal[18]); + dig_P8 = (int16_t)(cal[21] << 8 | cal[20]); + dig_P9 = (int16_t)(cal[23] << 8 | cal[22]); + + /* Config: normal mode, 16x oversampling temp+press, 0.5ms standby */ + i2c_write(0xF5, 0x00); /* config: standby=0.5ms, filter=off */ + i2c_write(0xF4, 0xB7); /* ctrl_meas: osrs_t=x16, osrs_p=x16, normal mode */ + + HAL_Delay(50); + return (int)id; +} + +void bmp280_read(int32_t *pressure_pa, int16_t *temp_x10) { + uint8_t buf[6]; + i2c_read_burst(0xF7, buf, 6); + + int32_t adc_P = (int32_t)((buf[0] << 12) | (buf[1] << 4) | (buf[2] >> 4)); + int32_t adc_T = (int32_t)((buf[3] << 12) | (buf[4] << 4) | (buf[5] >> 4)); + + /* Temperature compensation (from BMP280 datasheet) */ + int32_t var1 = ((((adc_T >> 3) - ((int32_t)dig_T1 << 1))) * ((int32_t)dig_T2)) >> 11; + int32_t var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) * ((adc_T >> 4) - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14; + t_fine = var1 + var2; + *temp_x10 = (int16_t)((t_fine * 5 + 128) >> 8); /* 0.1°C units */ + + /* Pressure compensation */ + int64_t v1 = ((int64_t)t_fine) - 128000; + int64_t v2 = v1 * v1 * (int64_t)dig_P6; + v2 = v2 + ((v1 * (int64_t)dig_P5) << 17); + v2 = v2 + (((int64_t)dig_P4) << 35); + v1 = ((v1 * v1 * (int64_t)dig_P3) >> 8) + ((v1 * (int64_t)dig_P2) << 12); + v1 = (((((int64_t)1) << 47) + v1)) * ((int64_t)dig_P1) >> 33; + if (v1 == 0) { *pressure_pa = 0; return; } + int64_t p = 1048576 - adc_P; + p = (((p << 31) - v2) * 3125) / v1; + v1 = (((int64_t)dig_P9) * (p >> 13) * (p >> 13)) >> 25; + v2 = (((int64_t)dig_P8) * p) >> 19; + *pressure_pa = (int32_t)((p + v1 + v2) >> 8) + (((int64_t)dig_P7) << 4); + *pressure_pa /= 256; /* Pa */ +} diff --git a/src/hoverboard.c b/src/hoverboard.c new file mode 100644 index 0000000..572a3bc --- /dev/null +++ b/src/hoverboard.c @@ -0,0 +1,41 @@ +#include "hoverboard.h" +#include "config.h" +#include "stm32f7xx_hal.h" + +static UART_HandleTypeDef huart2; + +void hoverboard_init(void) { + /* Enable clocks */ + __HAL_RCC_USART2_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /* PA2=TX, PA3=RX, AF7 for USART2 */ + GPIO_InitTypeDef gpio = {0}; + gpio.Pin = GPIO_PIN_2 | GPIO_PIN_3; + gpio.Mode = GPIO_MODE_AF_PP; + gpio.Pull = GPIO_PULLUP; + gpio.Speed = GPIO_SPEED_FREQ_HIGH; + gpio.Alternate = GPIO_AF7_USART2; + HAL_GPIO_Init(GPIOA, &gpio); + + /* USART2 config */ + huart2.Instance = USART2; + huart2.Init.BaudRate = HOVERBOARD_BAUD; + huart2.Init.WordLength = UART_WORDLENGTH_8B; + huart2.Init.StopBits = UART_STOPBITS_1; + huart2.Init.Parity = UART_PARITY_NONE; + huart2.Init.Mode = UART_MODE_TX_RX; + huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart2.Init.OverSampling = UART_OVERSAMPLING_16; + HAL_UART_Init(&huart2); +} + +void hoverboard_send(int16_t speed, int16_t steer) { + hoverboard_cmd_t cmd; + cmd.start = HOVERBOARD_START_FRAME; + cmd.steer = steer; + cmd.speed = speed; + cmd.checksum = cmd.start ^ cmd.steer ^ cmd.speed; + + HAL_UART_Transmit(&huart2, (uint8_t *)&cmd, sizeof(cmd), 5); +} diff --git a/src/icm42688.c b/src/icm42688.c new file mode 100644 index 0000000..744d1b9 --- /dev/null +++ b/src/icm42688.c @@ -0,0 +1,175 @@ +/* MPU6000 + ICM-42688-P dual driver — auto-detects based on WHO_AM_I */ +#include "stm32f7xx_hal.h" +#include "config.h" +#include "icm42688.h" + +static SPI_HandleTypeDef hspi1; +static uint8_t imu_type = 0; /* 0=unknown, 1=MPU6000, 2=ICM42688 */ + +/* MPU6000 registers */ +#define MPU_REG_SMPLRT_DIV 0x19 +#define MPU_REG_CONFIG 0x1A +#define MPU_REG_GYRO_CONFIG 0x1B +#define MPU_REG_ACCEL_CONFIG 0x1C +#define MPU_REG_ACCEL_XOUT_H 0x3B +#define MPU_REG_PWR_MGMT_1 0x6B +#define MPU_REG_PWR_MGMT_2 0x6C +#define MPU_REG_WHO_AM_I 0x75 +#define MPU6000_WHO 0x68 + +/* ICM-42688-P registers */ +#define ICM_REG_DEVICE_CONFIG 0x11 +#define ICM_REG_TEMP_DATA1 0x1D +#define ICM_REG_PWR_MGMT0 0x4E +#define ICM_REG_GYRO_CONFIG0 0x4F +#define ICM_REG_ACCEL_CONFIG0 0x50 +#define ICM_REG_WHO_AM_I 0x75 +#define ICM_REG_BANK_SEL 0x76 +#define ICM42688_WHO 0x47 + +static void cs_low(void) { HAL_GPIO_WritePin(MPU_CS_PORT, MPU_CS_PIN, GPIO_PIN_RESET); } +static void cs_high(void) { HAL_GPIO_WritePin(MPU_CS_PORT, MPU_CS_PIN, GPIO_PIN_SET); } + +static void wreg(uint8_t reg, uint8_t val) { + uint8_t tx[2] = { reg & 0x7F, val }; + uint8_t rx[2]; + cs_low(); + HAL_SPI_TransmitReceive(&hspi1, tx, rx, 2, 100); + cs_high(); + HAL_Delay(1); +} + +static uint8_t rreg(uint8_t reg) { + uint8_t tx[2] = { reg | 0x80, 0x00 }; + uint8_t rx[2] = {0, 0}; + cs_low(); + HAL_SPI_TransmitReceive(&hspi1, tx, rx, 2, 100); + cs_high(); + return rx[1]; +} + +static uint8_t trace[16]; +static int trace_idx = 0; +static void tr(uint8_t v) { if (trace_idx < 16) trace[trace_idx++] = v; } + +static int init_mpu6000(void) { + /* Reset */ + wreg(MPU_REG_PWR_MGMT_1, 0x80); + HAL_Delay(100); + + /* Wake up, use PLL with X gyro ref */ + wreg(MPU_REG_PWR_MGMT_1, 0x01); + HAL_Delay(10); + + /* Sample rate = 1kHz (divider=0) */ + wreg(MPU_REG_SMPLRT_DIV, 0x00); + + /* DLPF = 42Hz (config=3) */ + wreg(MPU_REG_CONFIG, 0x03); + + /* Gyro: ±2000°/s (FS_SEL=3) */ + wreg(MPU_REG_GYRO_CONFIG, 0x18); + + /* Accel: ±16g (AFS_SEL=3) */ + wreg(MPU_REG_ACCEL_CONFIG, 0x18); + + /* Enable all axes */ + wreg(MPU_REG_PWR_MGMT_2, 0x00); + HAL_Delay(50); + + /* Verify */ + uint8_t pwr = rreg(MPU_REG_PWR_MGMT_1); + tr(pwr); /* Should be 0x01 */ + + return (pwr == 0x01) ? 0 : -200 - (int)pwr; +} + +int icm42688_init(void) { + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_SPI1_CLK_ENABLE(); + + GPIO_InitTypeDef gpio = {0}; + gpio.Pin = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; + gpio.Mode = GPIO_MODE_AF_PP; + gpio.Pull = GPIO_NOPULL; + gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + gpio.Alternate = GPIO_AF5_SPI1; + HAL_GPIO_Init(GPIOA, &gpio); + + /* CS on PA4 for MAMBA */ + gpio.Pin = MPU_CS_PIN; + gpio.Mode = GPIO_MODE_OUTPUT_PP; + gpio.Speed = GPIO_SPEED_FREQ_HIGH; + gpio.Pull = GPIO_PULLUP; + HAL_GPIO_Init(MPU_CS_PORT, &gpio); + cs_high(); + + SCB_DisableDCache(); /* Avoid SPI DCache issues on F7 */ + + hspi1.Instance = SPI1; + hspi1.Init.Mode = SPI_MODE_MASTER; + hspi1.Init.Direction = SPI_DIRECTION_2LINES; + hspi1.Init.DataSize = SPI_DATASIZE_8BIT; + hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH; + hspi1.Init.CLKPhase = SPI_PHASE_2EDGE; + hspi1.Init.NSS = SPI_NSS_SOFT; + hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; + hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; + hspi1.Init.TIMode = SPI_TIMODE_DISABLE; + hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + if (HAL_SPI_Init(&hspi1) != HAL_OK) return -1; + + HAL_Delay(200); + /* Wake from sleep first - MPU6000 needs this before WHO_AM_I */ + wreg(0x6B, 0x80); /* Reset */ + HAL_Delay(100); + wreg(0x6B, 0x01); /* Wake, PLL */ + HAL_Delay(50); + + uint8_t who = rreg(MPU_REG_WHO_AM_I); + tr(who); /* trace[0] */ + + int ret; + if (who == MPU6000_WHO) { + imu_type = 1; + ret = init_mpu6000(); + } else if (who == ICM42688_WHO) { + imu_type = 2; + ret = -99; /* TODO: ICM init */ + } else { + ret = -who; + } + + /* Speed up SPI for reads */ + hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; + HAL_SPI_Init(&hspi1); + + tr((uint8_t)imu_type); /* trace[last] */ + return ret; +} + +void icm42688_read(icm42688_data_t *d) { + if (imu_type == 1) { + /* MPU6000: ACCEL_XOUT_H (0x3B) → 14 bytes: accel(6)+temp(2)+gyro(6) */ + uint8_t tx[15], rx[15]; + tx[0] = MPU_REG_ACCEL_XOUT_H | 0x80; + for (int i = 1; i < 15; i++) tx[i] = 0x00; + cs_low(); + HAL_SPI_TransmitReceive(&hspi1, tx, rx, 15, 100); + cs_high(); + + d->ax = (int16_t)((rx[1] << 8) | rx[2]); + d->ay = (int16_t)((rx[3] << 8) | rx[4]); + d->az = (int16_t)((rx[5] << 8) | rx[6]); + int16_t temp_raw = (int16_t)((rx[7] << 8) | rx[8]); + d->temp_x10 = (int16_t)((temp_raw + 12421) / 34); /* MPU6000 formula */ + d->gx = (int16_t)((rx[9] << 8) | rx[10]); + d->gy = (int16_t)((rx[11] << 8) | rx[12]); + d->gz = (int16_t)((rx[13] << 8) | rx[14]); + } +} + +void icm42688_get_trace(uint8_t *out, int *len) { + *len = trace_idx; + for (int i = 0; i < trace_idx; i++) out[i] = trace[i]; +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..d359c20 --- /dev/null +++ b/src/main.c @@ -0,0 +1,141 @@ +#include "stm32f7xx_hal.h" +#include "usbd_core.h" +#include "usbd_cdc.h" +#include "usbd_cdc_if.h" +#include "usbd_desc.h" +#include "icm42688.h" +#include "bmp280.h" +#include "balance.h" +#include "hoverboard.h" +#include "config.h" +#include "status.h" +#include +#include + +extern volatile uint8_t cdc_streaming; /* set by S command in CDC RX */ +extern volatile uint8_t cdc_arm_request; /* set by A command */ +extern volatile uint8_t cdc_disarm_request; /* set by D command */ + +USBD_HandleTypeDef hUsbDevice; + +static void SystemClock_Config(void) { + RCC_OscInitTypeDef osc = {0}; + RCC_ClkInitTypeDef clk = {0}; + RCC_PeriphCLKInitTypeDef pclk = {0}; + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + osc.OscillatorType = RCC_OSCILLATORTYPE_HSE; + osc.HSEState = RCC_HSE_ON; + osc.PLL.PLLState = RCC_PLL_ON; + osc.PLL.PLLSource = RCC_PLLSOURCE_HSE; + osc.PLL.PLLM = 8; osc.PLL.PLLN = 432; osc.PLL.PLLP = 2; osc.PLL.PLLQ = 9; + if (HAL_RCC_OscConfig(&osc) != HAL_OK) { + osc.OscillatorType = RCC_OSCILLATORTYPE_HSI; + osc.HSIState = RCC_HSI_ON; osc.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + osc.HSEState = RCC_HSE_OFF; osc.PLL.PLLSource = RCC_PLLSOURCE_HSI; osc.PLL.PLLM = 16; + if (HAL_RCC_OscConfig(&osc) != HAL_OK) while (1); + } + HAL_PWREx_EnableOverDrive(); + pclk.PeriphClockSelection = RCC_PERIPHCLK_CLK48 | RCC_PERIPHCLK_I2C1; + pclk.Clk48ClockSelection = RCC_CLK48SOURCE_PLLSAIP; + pclk.PLLSAI.PLLSAIN = 384; pclk.PLLSAI.PLLSAIQ = 7; pclk.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV8; + pclk.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&pclk) != HAL_OK) while (1); + clk.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + clk.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + clk.AHBCLKDivider = RCC_SYSCLK_DIV1; + clk.APB1CLKDivider = RCC_HCLK_DIV4; clk.APB2CLKDivider = RCC_HCLK_DIV2; + HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_7); +} + +extern PCD_HandleTypeDef hpcd; +void OTG_FS_IRQHandler(void) { HAL_PCD_IRQHandler(&hpcd); } +void SysTick_Handler(void) { HAL_IncTick(); } + +int main(void) { + SCB_EnableICache(); + checkForBootloader(); /* Check RTC magic BEFORE HAL_Init — must be first thing */ + HAL_Init(); + SystemClock_Config(); + + /* USB CDC */ + USBD_Init(&hUsbDevice, &SaltyLab_Desc, 0); + USBD_RegisterClass(&hUsbDevice, &USBD_CDC); + USBD_CDC_RegisterInterface(&hUsbDevice, &USBD_CDC_fops); + USBD_Start(&hUsbDevice); + + status_init(); + HAL_Delay(3000); /* Wait for USB host to enumerate */ + + /* Init IMU */ + int imu_ret = icm42688_init(); + + /* Init hoverboard ESC UART */ + hoverboard_init(); + + /* Init balance controller */ + balance_t bal; + balance_init(&bal); + + char buf[256]; + int len; + + icm42688_data_t imu; + uint32_t send_tick = 0; + uint32_t balance_tick = 0; + uint32_t esc_tick = 0; + const float dt = 1.0f / PID_LOOP_HZ; /* 1ms at 1kHz */ + + while (1) { + if (imu_ret == 0) icm42688_read(&imu); + + uint32_t now = HAL_GetTick(); + + /* Handle arm/disarm requests from USB */ + if (cdc_arm_request) { + cdc_arm_request = 0; + balance_arm(&bal); + } + if (cdc_disarm_request) { + cdc_disarm_request = 0; + balance_disarm(&bal); + } + + /* Balance PID at 1kHz */ + if (imu_ret == 0 && now - balance_tick >= 1) { + balance_tick = now; + balance_update(&bal, &imu, dt); + } + + /* Send to hoverboard ESC at 50Hz (every 20ms) + * Both wheels get same speed for balance, steer=0 for now */ + if (now - esc_tick >= 20) { + esc_tick = now; + if (bal.state == BALANCE_ARMED) { + hoverboard_send(bal.motor_cmd, 0); + } else { + hoverboard_send(0, 0); /* Always send to prevent ESC timeout */ + } + } + + /* USB telemetry at 50Hz (only when streaming enabled via S command) */ + if (cdc_streaming && now - send_tick >= 20) { + send_tick = now; + if (imu_ret == 0) { + len = snprintf(buf, sizeof(buf), + "{\"ax\":%d,\"ay\":%d,\"az\":%d,\"gx\":%d,\"gy\":%d,\"gz\":%d," + "\"p\":%d,\"m\":%d,\"s\":%d}\n", + imu.ax, imu.ay, imu.az, imu.gx, imu.gy, imu.gz, + (int)(bal.pitch_deg * 10), /* pitch x10 for precision without %f */ + (int)bal.motor_cmd, + (int)bal.state); + } else { + len = snprintf(buf, sizeof(buf), "{\"err\":%d}\n", imu_ret); + } + CDC_Transmit((uint8_t *)buf, len); + } + + status_update(now, (imu_ret == 0), (bal.state == BALANCE_ARMED)); + HAL_Delay(1); + } +} diff --git a/src/main.c.bak b/src/main.c.bak new file mode 100644 index 0000000..5f66b9f --- /dev/null +++ b/src/main.c.bak @@ -0,0 +1,147 @@ +#include "stm32f7xx_hal.h" +#include "usbd_core.h" +#include "usbd_cdc.h" +#include "usbd_cdc_if.h" +#include "usbd_desc.h" +#include "icm42688.h" +#include "bmp280.h" +#include "balance.h" +#include "hoverboard.h" +#include "config.h" +#include "status.h" +#include +#include + +extern volatile uint8_t cdc_streaming; /* set by S command in CDC RX */ +extern volatile uint8_t cdc_arm_request; /* set by A command */ +extern volatile uint8_t cdc_disarm_request; /* set by D command */ + +USBD_HandleTypeDef hUsbDevice; + +static void SystemClock_Config(void) { + RCC_OscInitTypeDef osc = {0}; + RCC_ClkInitTypeDef clk = {0}; + RCC_PeriphCLKInitTypeDef pclk = {0}; + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + osc.OscillatorType = RCC_OSCILLATORTYPE_HSE; + osc.HSEState = RCC_HSE_ON; + osc.PLL.PLLState = RCC_PLL_ON; + osc.PLL.PLLSource = RCC_PLLSOURCE_HSE; + osc.PLL.PLLM = 8; osc.PLL.PLLN = 432; osc.PLL.PLLP = 2; osc.PLL.PLLQ = 9; + if (HAL_RCC_OscConfig(&osc) != HAL_OK) { + osc.OscillatorType = RCC_OSCILLATORTYPE_HSI; + osc.HSIState = RCC_HSI_ON; osc.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + osc.HSEState = RCC_HSE_OFF; osc.PLL.PLLSource = RCC_PLLSOURCE_HSI; osc.PLL.PLLM = 16; + if (HAL_RCC_OscConfig(&osc) != HAL_OK) while (1); + } + HAL_PWREx_EnableOverDrive(); + pclk.PeriphClockSelection = RCC_PERIPHCLK_CLK48 | RCC_PERIPHCLK_I2C1; + pclk.Clk48ClockSelection = RCC_CLK48SOURCE_PLLSAIP; + pclk.PLLSAI.PLLSAIN = 384; pclk.PLLSAI.PLLSAIQ = 7; pclk.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV8; + pclk.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&pclk) != HAL_OK) while (1); + clk.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + clk.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + clk.AHBCLKDivider = RCC_SYSCLK_DIV1; + clk.APB1CLKDivider = RCC_HCLK_DIV4; clk.APB2CLKDivider = RCC_HCLK_DIV2; + HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_7); +} + +extern PCD_HandleTypeDef hpcd; +void OTG_FS_IRQHandler(void) { HAL_PCD_IRQHandler(&hpcd); } +void SysTick_Handler(void) { HAL_IncTick(); } + +int main(void) { + SCB_EnableICache(); + checkForBootloader(); /* Check RTC magic BEFORE HAL_Init — must be first thing */ + HAL_Init(); + SystemClock_Config(); + + /* USB CDC */ + USBD_Init(&hUsbDevice, &SaltyLab_Desc, 0); + USBD_RegisterClass(&hUsbDevice, &USBD_CDC); + USBD_CDC_RegisterInterface(&hUsbDevice, &USBD_CDC_fops); + USBD_Start(&hUsbDevice); + + status_init(); + HAL_Delay(1000); + + /* Init IMU */ + int imu_ret = icm42688_init(); + + /* Init hoverboard ESC UART */ + hoverboard_init(); + + /* Init balance controller */ + balance_t bal; + balance_init(&bal); + + /* Send init status over USB */ + uint8_t tr[16]; int tlen; + icm42688_get_trace(tr, &tlen); + char buf[256]; + int len = snprintf(buf, sizeof(buf), + "{\"init\":1,\"imu\":%d,\"who\":%d}\n", + imu_ret, tr[0]); + CDC_Transmit((uint8_t *)buf, len); + + icm42688_data_t imu; + uint32_t send_tick = 0; + uint32_t balance_tick = 0; + uint32_t esc_tick = 0; + const float dt = 1.0f / PID_LOOP_HZ; /* 1ms at 1kHz */ + + while (1) { + if (imu_ret == 0) icm42688_read(&imu); + + uint32_t now = HAL_GetTick(); + + /* Handle arm/disarm requests from USB */ + if (cdc_arm_request) { + cdc_arm_request = 0; + balance_arm(&bal); + } + if (cdc_disarm_request) { + cdc_disarm_request = 0; + balance_disarm(&bal); + } + + /* Balance PID at 1kHz */ + if (imu_ret == 0 && now - balance_tick >= 1) { + balance_tick = now; + balance_update(&bal, &imu, dt); + } + + /* Send to hoverboard ESC at 50Hz (every 20ms) + * Both wheels get same speed for balance, steer=0 for now */ + if (now - esc_tick >= 20) { + esc_tick = now; + if (bal.state == BALANCE_ARMED) { + hoverboard_send(bal.motor_cmd, 0); + } else { + hoverboard_send(0, 0); /* Always send to prevent ESC timeout */ + } + } + + /* USB telemetry at 50Hz (only when streaming enabled via S command) */ + if (cdc_streaming && now - send_tick >= 20) { + send_tick = now; + if (imu_ret == 0) { + len = snprintf(buf, sizeof(buf), + "{\"ax\":%d,\"ay\":%d,\"az\":%d,\"gx\":%d,\"gy\":%d,\"gz\":%d," + "\"p\":%d,\"m\":%d,\"s\":%d}\n", + imu.ax, imu.ay, imu.az, imu.gx, imu.gy, imu.gz, + (int)(bal.pitch_deg * 10), /* pitch x10 for precision without %f */ + (int)bal.motor_cmd, + (int)bal.state); + } else { + len = snprintf(buf, sizeof(buf), "{\"err\":%d}\n", imu_ret); + } + CDC_Transmit((uint8_t *)buf, len); + } + + status_update(now, (imu_ret == 0), (bal.state == BALANCE_ARMED)); + HAL_Delay(1); + } +} diff --git a/src/status.c b/src/status.c new file mode 100644 index 0000000..58dd31b --- /dev/null +++ b/src/status.c @@ -0,0 +1,67 @@ +#include "stm32f7xx_hal.h" +#include "config.h" +#include "status.h" + +void status_init(void) { + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + + GPIO_InitTypeDef gpio = {0}; + gpio.Mode = GPIO_MODE_OUTPUT_PP; + gpio.Pull = GPIO_NOPULL; + gpio.Speed = GPIO_SPEED_FREQ_LOW; + + /* LED1 - PC15 */ + gpio.Pin = LED1_PIN; + HAL_GPIO_Init(LED1_PORT, &gpio); + + /* LED2 - PC14 */ + gpio.Pin = LED2_PIN; + HAL_GPIO_Init(LED2_PORT, &gpio); + + /* Buzzer - PB2 (inverted: HIGH = off) */ + gpio.Pin = BEEPER_PIN; + HAL_GPIO_Init(BEEPER_PORT, &gpio); + + /* Start with both LEDs ON (active low) */ + HAL_GPIO_WritePin(LED1_PORT, LED1_PIN, GPIO_PIN_RESET); + HAL_GPIO_WritePin(LED2_PORT, LED2_PIN, GPIO_PIN_RESET); + + /* Buzzer off */ + HAL_GPIO_WritePin(BEEPER_PORT, BEEPER_PIN, GPIO_PIN_RESET); +} + +void status_boot_beep(void) { + /* Two quick beeps */ + HAL_GPIO_WritePin(BEEPER_PORT, BEEPER_PIN, GPIO_PIN_SET); + HAL_Delay(80); + HAL_GPIO_WritePin(BEEPER_PORT, BEEPER_PIN, GPIO_PIN_RESET); + HAL_Delay(80); + HAL_GPIO_WritePin(BEEPER_PORT, BEEPER_PIN, GPIO_PIN_SET); + HAL_Delay(80); + HAL_GPIO_WritePin(BEEPER_PORT, BEEPER_PIN, GPIO_PIN_RESET); +} + +void status_update(uint32_t tick, int imu_ok, int baro_ok) { + if (imu_ok) { + /* Slow blink LED1 at 1Hz */ + if ((tick / 500) % 2) + HAL_GPIO_WritePin(LED1_PORT, LED1_PIN, GPIO_PIN_RESET); /* ON */ + else + HAL_GPIO_WritePin(LED1_PORT, LED1_PIN, GPIO_PIN_SET); /* OFF */ + + /* LED2: quick flash every 5s if baro OK */ + if (baro_ok && (tick % 5000) < 100) + HAL_GPIO_WritePin(LED2_PORT, LED2_PIN, GPIO_PIN_RESET); + else + HAL_GPIO_WritePin(LED2_PORT, LED2_PIN, GPIO_PIN_SET); + } else { + /* Fast blink LED1 at 5Hz = error */ + if ((tick / 100) % 2) + HAL_GPIO_WritePin(LED1_PORT, LED1_PIN, GPIO_PIN_RESET); + else + HAL_GPIO_WritePin(LED1_PORT, LED1_PIN, GPIO_PIN_SET); + /* LED2 solid ON */ + HAL_GPIO_WritePin(LED2_PORT, LED2_PIN, GPIO_PIN_RESET); + } +} diff --git a/ui/index.html b/ui/index.html new file mode 100644 index 0000000..83630c4 --- /dev/null +++ b/ui/index.html @@ -0,0 +1,375 @@ + + + + + +SaltyLab Balance Bot + + + +

+ +
+
+ PITCH + +
+
+ MOTOR + +
+
+ + + + +