From e394a4d293cb5419b09fad9cbb5df47dd27a91e2 Mon Sep 17 00:00:00 2001 From: angoosh Date: Thu, 1 Jul 2021 14:08:25 +0200 Subject: [PATCH] 1234 --- Hardware/DisplayBoard/MotorcycleMonitor.zip | Bin 0 -> 23814 bytes .../MotorcycleMonitoring-cache.lib | 316 + .../MotorcycleMonitoring.kicad_pcb | 1392 + .../MotorcycleMonitoring.kicad_pcb-bak | 1392 + .../DisplayBoard/MotorcycleMonitoring.net | 467 + .../DisplayBoard/MotorcycleMonitoring.pro | 248 + .../DisplayBoard/MotorcycleMonitoring.sch | 490 + .../DisplayBoard/MotorcycleMonitoring.sch-bak | 490 + Hardware/DisplayBoard/Project Log.txt | 24 + Hardware/DisplayBoard/README.md | 3 + Hardware/DisplayBoard/fp-info-cache | 82181 ++++++++++++++++ .../gerber/MotorcycleMonitoring-B_Cu.gbr | 3971 + .../gerber/MotorcycleMonitoring-B_Mask.gbr | 1544 + .../gerber/MotorcycleMonitoring-B_SilkS.gbr | 141 + .../gerber/MotorcycleMonitoring-Edge_Cuts.gbr | 26 + .../gerber/MotorcycleMonitoring-F_Cu.gbr | 1332 + .../gerber/MotorcycleMonitoring-F_Mask.gbr | 74 + .../gerber/MotorcycleMonitoring-F_SilkS.gbr | 31 + .../gerber/MotorcycleMonitoring-NPTH.drl | 13 + .../gerber/MotorcycleMonitoring-PTH.drl | 53 + .../gerber/MotorcycleMonitoring-job.gbrjob | 110 + Software/DisplayBoard/Core/Inc/fonts.h | 22 + Software/DisplayBoard/Core/Inc/main.h | 91 + Software/DisplayBoard/Core/Inc/ssd1306.h | 58 + .../Core/Inc/stm32f0xx_hal_conf.h | 322 + Software/DisplayBoard/Core/Inc/stm32f0xx_it.h | 73 + Software/DisplayBoard/Core/Src/fonts.c | 301 + Software/DisplayBoard/Core/Src/main.c | 854 + Software/DisplayBoard/Core/Src/ssd1306.c | 211 + .../DisplayBoard/Core/Src/stm32f0xx_hal_msp.c | 474 + Software/DisplayBoard/Core/Src/stm32f0xx_it.c | 268 + Software/DisplayBoard/Core/Src/syscalls.c | 159 + Software/DisplayBoard/Core/Src/sysmem.c | 80 + .../DisplayBoard/Core/Src/system_stm32f0xx.c | 247 + .../Core/Startup/startup_stm32f030c8tx.s | 273 + Software/DisplayBoard/DisplayBoard.ioc | 202 + 36 files changed, 97933 insertions(+) create mode 100644 Hardware/DisplayBoard/MotorcycleMonitor.zip create mode 100644 Hardware/DisplayBoard/MotorcycleMonitoring-cache.lib create mode 100644 Hardware/DisplayBoard/MotorcycleMonitoring.kicad_pcb create mode 100644 Hardware/DisplayBoard/MotorcycleMonitoring.kicad_pcb-bak create mode 100644 Hardware/DisplayBoard/MotorcycleMonitoring.net create mode 100644 Hardware/DisplayBoard/MotorcycleMonitoring.pro create mode 100644 Hardware/DisplayBoard/MotorcycleMonitoring.sch create mode 100644 Hardware/DisplayBoard/MotorcycleMonitoring.sch-bak create mode 100644 Hardware/DisplayBoard/Project Log.txt create mode 100644 Hardware/DisplayBoard/README.md create mode 100644 Hardware/DisplayBoard/fp-info-cache create mode 100644 Hardware/DisplayBoard/gerber/MotorcycleMonitoring-B_Cu.gbr create mode 100644 Hardware/DisplayBoard/gerber/MotorcycleMonitoring-B_Mask.gbr create mode 100644 Hardware/DisplayBoard/gerber/MotorcycleMonitoring-B_SilkS.gbr create mode 100644 Hardware/DisplayBoard/gerber/MotorcycleMonitoring-Edge_Cuts.gbr create mode 100644 Hardware/DisplayBoard/gerber/MotorcycleMonitoring-F_Cu.gbr create mode 100644 Hardware/DisplayBoard/gerber/MotorcycleMonitoring-F_Mask.gbr create mode 100644 Hardware/DisplayBoard/gerber/MotorcycleMonitoring-F_SilkS.gbr create mode 100644 Hardware/DisplayBoard/gerber/MotorcycleMonitoring-NPTH.drl create mode 100644 Hardware/DisplayBoard/gerber/MotorcycleMonitoring-PTH.drl create mode 100644 Hardware/DisplayBoard/gerber/MotorcycleMonitoring-job.gbrjob create mode 100644 Software/DisplayBoard/Core/Inc/fonts.h create mode 100644 Software/DisplayBoard/Core/Inc/main.h create mode 100644 Software/DisplayBoard/Core/Inc/ssd1306.h create mode 100644 Software/DisplayBoard/Core/Inc/stm32f0xx_hal_conf.h create mode 100644 Software/DisplayBoard/Core/Inc/stm32f0xx_it.h create mode 100644 Software/DisplayBoard/Core/Src/fonts.c create mode 100644 Software/DisplayBoard/Core/Src/main.c create mode 100644 Software/DisplayBoard/Core/Src/ssd1306.c create mode 100644 Software/DisplayBoard/Core/Src/stm32f0xx_hal_msp.c create mode 100644 Software/DisplayBoard/Core/Src/stm32f0xx_it.c create mode 100644 Software/DisplayBoard/Core/Src/syscalls.c create mode 100644 Software/DisplayBoard/Core/Src/sysmem.c create mode 100644 Software/DisplayBoard/Core/Src/system_stm32f0xx.c create mode 100644 Software/DisplayBoard/Core/Startup/startup_stm32f030c8tx.s create mode 100644 Software/DisplayBoard/DisplayBoard.ioc diff --git a/Hardware/DisplayBoard/MotorcycleMonitor.zip b/Hardware/DisplayBoard/MotorcycleMonitor.zip new file mode 100644 index 0000000000000000000000000000000000000000..7a696c4292446d1a2bc0d99c6aef91befa52a106 GIT binary patch literal 23814 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 G(f + +// +// Structure used to define fonts +// +typedef struct { + const uint8_t FontWidth; /* Font width in pixels */ + uint8_t FontHeight; /* Font height in pixels */ + const uint16_t *data; /* Pointer to data font data array */ +} FontDef; + +// +// Export the 3 available fonts +// +extern FontDef Font_7x10; +extern FontDef Font_11x18; +extern FontDef Font_16x26; + +#endif // _FONTS_H \ No newline at end of file diff --git a/Software/DisplayBoard/Core/Inc/main.h b/Software/DisplayBoard/Core/Inc/main.h new file mode 100644 index 0000000..4a0a995 --- /dev/null +++ b/Software/DisplayBoard/Core/Inc/main.h @@ -0,0 +1,91 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f0xx_hal.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ +#define TIRE_CIRC_M (float)1.906 +#define V_REF (float)3.3 +#define U_BATT_DIV_RATIO (float)11 +#define FUEL_DIV_RATIO (float)6.6 +#define MAX_FUEL_U (float)13 +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void Error_Handler(void); + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +#define GPInput1_Pin GPIO_PIN_1 +#define GPInput1_GPIO_Port GPIOA +#define GPInput1_EXTI_IRQn EXTI0_1_IRQn +#define GPInput2_Pin GPIO_PIN_2 +#define GPInput2_GPIO_Port GPIOA +#define GPInput2_EXTI_IRQn EXTI2_3_IRQn +#define FUEL_Pin GPIO_PIN_3 +#define FUEL_GPIO_Port GPIOA +#define SPEED_Pin GPIO_PIN_4 +#define SPEED_GPIO_Port GPIOA +#define U_BATT_Pin GPIO_PIN_5 +#define U_BATT_GPIO_Port GPIOA +#define RPM_Pin GPIO_PIN_6 +#define RPM_GPIO_Port GPIOA +#define LED_Pin GPIO_PIN_0 +#define LED_GPIO_Port GPIOB +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Software/DisplayBoard/Core/Inc/ssd1306.h b/Software/DisplayBoard/Core/Inc/ssd1306.h new file mode 100644 index 0000000..450113c --- /dev/null +++ b/Software/DisplayBoard/Core/Inc/ssd1306.h @@ -0,0 +1,58 @@ +/** + * This Library is written and optimized by Olivier Van den Eede(4ilo) in 2016 + * for Stm32 Uc and HAL-i2c lib's. + * + * To use this library with ssd1306 oled display you will need to customize the defines below. + * + * This library uses 2 extra files (fonts.c/h). + * In this files are 3 different fonts you can use: + * - Font_7x10 + * - Font_11x18 + * - Font_16x26 + * + */ + +#ifndef _SSD1306_H +#define _SSD1306_H + +#include "stm32f0xx_hal.h" +#include "fonts.h" + +// I2c address +#define SSD1306_I2C_ADDR 0x78 +// SSD1306 width in pixels +#define SSD1306_WIDTH 128 +// SSD1306 LCD height in pixels +#define SSD1306_HEIGHT 64 + + +// +// Enumeration for screen colors +// +typedef enum { + Black = 0x00, // Black color, no pixel + White = 0x01 //Pixel is set. Color depends on LCD +} SSD1306_COLOR; + +// +// Struct to store transformations +// +typedef struct { + uint16_t CurrentX; + uint16_t CurrentY; + uint8_t Inverted; + uint8_t Initialized; +} SSD1306_t; + +// +// Function definitions +// +uint8_t ssd1306_Init(I2C_HandleTypeDef *hi2c); +void ssd1306_UpdateScreen(I2C_HandleTypeDef *hi2c); +void ssd1306_Fill(SSD1306_COLOR color); +void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color); +char ssd1306_WriteChar(char ch, FontDef Font, SSD1306_COLOR color); +char ssd1306_WriteString(char* str, FontDef Font, SSD1306_COLOR color); +void ssd1306_SetCursor(uint8_t x, uint8_t y); + +#endif // _SSD1306_H diff --git a/Software/DisplayBoard/Core/Inc/stm32f0xx_hal_conf.h b/Software/DisplayBoard/Core/Inc/stm32f0xx_hal_conf.h new file mode 100644 index 0000000..bd9730e --- /dev/null +++ b/Software/DisplayBoard/Core/Inc/stm32f0xx_hal_conf.h @@ -0,0 +1,322 @@ +/** + ****************************************************************************** + * @file stm32f0xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2016 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F0xx_HAL_CONF_H +#define __STM32F0xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED + #define HAL_ADC_MODULE_ENABLED +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_CAN_MODULE_ENABLED */ +/*#define HAL_CEC_MODULE_ENABLED */ +/*#define HAL_COMP_MODULE_ENABLED */ +/*#define HAL_CRC_MODULE_ENABLED */ +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_TSC_MODULE_ENABLED */ +/*#define HAL_DAC_MODULE_ENABLED */ +/*#define HAL_I2S_MODULE_ENABLED */ +/*#define HAL_IWDG_MODULE_ENABLED */ +/*#define HAL_LCD_MODULE_ENABLED */ +/*#define HAL_LPTIM_MODULE_ENABLED */ +/*#define HAL_RNG_MODULE_ENABLED */ +/*#define HAL_RTC_MODULE_ENABLED */ +/*#define HAL_SPI_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +/*#define HAL_USART_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +/*#define HAL_SMARTCARD_MODULE_ENABLED */ +/*#define HAL_SMBUS_MODULE_ENABLED */ +/*#define HAL_WWDG_MODULE_ENABLED */ +/*#define HAL_PCD_MODULE_ENABLED */ +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +/** + * @brief In the following line adjust the External High Speed oscillator (HSE) Startup + * Timeout value + */ +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief In the following line adjust the Internal High Speed oscillator (HSI) Startup + * Timeout value + */ +#if !defined (HSI_STARTUP_TIMEOUT) + #define HSI_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSI start up */ +#endif /* HSI_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator for ADC (HSI14) value. + */ +#if !defined (HSI14_VALUE) +#define HSI14_VALUE ((uint32_t)14000000) /*!< Value of the Internal High Speed oscillator for ADC in Hz. + The real value may vary depending on the variations + in voltage and temperature. */ +#endif /* HSI14_VALUE */ + +/** + * @brief Internal High Speed oscillator for USB (HSI48) value. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE ((uint32_t)48000000) /*!< Value of the Internal High Speed oscillator for USB in Hz. + The real value may vary depending on the variations + in voltage and temperature. */ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)40000) +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ +/** + * @brief External Low Speed oscillator (LSI) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +/** + * @brief Time out for LSE start up value in ms. + */ +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0) /*!< tick interrupt priority (lowest by default) */ + /* Warning: Must be set to higher priority for HAL_Delay() */ + /* and HAL_GetTick() usage under interrupt context */ +#define USE_RTOS 0 +#define PREFETCH_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 0 +#define DATA_CACHE_ENABLE 0 +#define USE_SPI_CRC 0U + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_TSC_REGISTER_CALLBACKS 0U /* TSC register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f0xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f0xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f0xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f0xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f0xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f0xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f0xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f0xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED + #include "stm32f0xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f0xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f0xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f0xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f0xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f0xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f0xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f0xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f0xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f0xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f0xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f0xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32f0xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f0xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f0xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED + #include "stm32f0xx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f0xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f0xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f0xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F0xx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Software/DisplayBoard/Core/Inc/stm32f0xx_it.h b/Software/DisplayBoard/Core/Inc/stm32f0xx_it.h new file mode 100644 index 0000000..ad979ae --- /dev/null +++ b/Software/DisplayBoard/Core/Inc/stm32f0xx_it.h @@ -0,0 +1,73 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f0xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F0xx_IT_H +#define __STM32F0xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void NMI_Handler(void); +void HardFault_Handler(void); +void SVC_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +void EXTI0_1_IRQHandler(void); +void EXTI2_3_IRQHandler(void); +void DMA1_Channel2_3_IRQHandler(void); +void TIM3_IRQHandler(void); +void TIM6_IRQHandler(void); +void TIM14_IRQHandler(void); +void I2C1_IRQHandler(void); +void USART1_IRQHandler(void); +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F0xx_IT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Software/DisplayBoard/Core/Src/fonts.c b/Software/DisplayBoard/Core/Src/fonts.c new file mode 100644 index 0000000..81882d9 --- /dev/null +++ b/Software/DisplayBoard/Core/Src/fonts.c @@ -0,0 +1,301 @@ +#include "fonts.h" + +// Bitmaps for 3 different fonts + +static const uint16_t Font7x10 [] = { +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp +0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // ! +0x2800, 0x2800, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // " +0x2400, 0x2400, 0x7C00, 0x2400, 0x4800, 0x7C00, 0x4800, 0x4800, 0x0000, 0x0000, // # +0x3800, 0x5400, 0x5000, 0x3800, 0x1400, 0x5400, 0x5400, 0x3800, 0x1000, 0x0000, // $ +0x2000, 0x5400, 0x5800, 0x3000, 0x2800, 0x5400, 0x1400, 0x0800, 0x0000, 0x0000, // % +0x1000, 0x2800, 0x2800, 0x1000, 0x3400, 0x4800, 0x4800, 0x3400, 0x0000, 0x0000, // & +0x1000, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ' +0x0800, 0x1000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x1000, 0x0800, // ( +0x2000, 0x1000, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x1000, 0x2000, // ) +0x1000, 0x3800, 0x1000, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // * +0x0000, 0x0000, 0x1000, 0x1000, 0x7C00, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, // + +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // , +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3800, 0x0000, 0x0000, 0x0000, 0x0000, // - +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // . +0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x0000, 0x0000, // / +0x3800, 0x4400, 0x4400, 0x5400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 0 +0x1000, 0x3000, 0x5000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // 1 +0x3800, 0x4400, 0x4400, 0x0400, 0x0800, 0x1000, 0x2000, 0x7C00, 0x0000, 0x0000, // 2 +0x3800, 0x4400, 0x0400, 0x1800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 3 +0x0800, 0x1800, 0x2800, 0x2800, 0x4800, 0x7C00, 0x0800, 0x0800, 0x0000, 0x0000, // 4 +0x7C00, 0x4000, 0x4000, 0x7800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 5 +0x3800, 0x4400, 0x4000, 0x7800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 6 +0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x2000, 0x2000, 0x0000, 0x0000, // 7 +0x3800, 0x4400, 0x4400, 0x3800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 8 +0x3800, 0x4400, 0x4400, 0x4400, 0x3C00, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 9 +0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // : +0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // ; +0x0000, 0x0000, 0x0C00, 0x3000, 0x4000, 0x3000, 0x0C00, 0x0000, 0x0000, 0x0000, // < +0x0000, 0x0000, 0x0000, 0x7C00, 0x0000, 0x7C00, 0x0000, 0x0000, 0x0000, 0x0000, // = +0x0000, 0x0000, 0x6000, 0x1800, 0x0400, 0x1800, 0x6000, 0x0000, 0x0000, 0x0000, // > +0x3800, 0x4400, 0x0400, 0x0800, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // ? +0x3800, 0x4400, 0x4C00, 0x5400, 0x5C00, 0x4000, 0x4000, 0x3800, 0x0000, 0x0000, // @ +0x1000, 0x2800, 0x2800, 0x2800, 0x2800, 0x7C00, 0x4400, 0x4400, 0x0000, 0x0000, // A +0x7800, 0x4400, 0x4400, 0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x0000, 0x0000, // B +0x3800, 0x4400, 0x4000, 0x4000, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // C +0x7000, 0x4800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4800, 0x7000, 0x0000, 0x0000, // D +0x7C00, 0x4000, 0x4000, 0x7C00, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // E +0x7C00, 0x4000, 0x4000, 0x7800, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // F +0x3800, 0x4400, 0x4000, 0x4000, 0x5C00, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // G +0x4400, 0x4400, 0x4400, 0x7C00, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // H +0x3800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3800, 0x0000, 0x0000, // I +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // J +0x4400, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // K +0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // L +0x4400, 0x6C00, 0x6C00, 0x5400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // M +0x4400, 0x6400, 0x6400, 0x5400, 0x5400, 0x4C00, 0x4C00, 0x4400, 0x0000, 0x0000, // N +0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // O +0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // P +0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x5400, 0x3800, 0x0400, 0x0000, // Q +0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // R +0x3800, 0x4400, 0x4000, 0x3000, 0x0800, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // S +0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // T +0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // U +0x4400, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x1000, 0x0000, 0x0000, // V +0x4400, 0x4400, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // W +0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, // X +0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // Y +0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // Z +0x1800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1800, // [ +0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x0000, 0x0000, /* \ */ +0x3000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3000, // ] +0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^ +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFE00, // _ +0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ` +0x0000, 0x0000, 0x3800, 0x4400, 0x3C00, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // a +0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x0000, 0x0000, // b +0x0000, 0x0000, 0x3800, 0x4400, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // c +0x0400, 0x0400, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // d +0x0000, 0x0000, 0x3800, 0x4400, 0x7C00, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // e +0x0C00, 0x1000, 0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // f +0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x7800, // g +0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // h +0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // i +0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0xE000, // j +0x4000, 0x4000, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4400, 0x0000, 0x0000, // k +0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // l +0x0000, 0x0000, 0x7800, 0x5400, 0x5400, 0x5400, 0x5400, 0x5400, 0x0000, 0x0000, // m +0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // n +0x0000, 0x0000, 0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // o +0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x4000, 0x4000, // p +0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x0400, // q +0x0000, 0x0000, 0x5800, 0x6400, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // r +0x0000, 0x0000, 0x3800, 0x4400, 0x3000, 0x0800, 0x4400, 0x3800, 0x0000, 0x0000, // s +0x2000, 0x2000, 0x7800, 0x2000, 0x2000, 0x2000, 0x2000, 0x1800, 0x0000, 0x0000, // t +0x0000, 0x0000, 0x4400, 0x4400, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // u +0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x0000, 0x0000, // v +0x0000, 0x0000, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // w +0x0000, 0x0000, 0x4400, 0x2800, 0x1000, 0x1000, 0x2800, 0x4400, 0x0000, 0x0000, // x +0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x6000, // y +0x0000, 0x0000, 0x7C00, 0x0800, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // z +0x1800, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1800, // { +0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, // | +0x3000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x3000, // } +0x0000, 0x0000, 0x0000, 0x7400, 0x4C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~ +}; + +static const uint16_t Font11x18 [] = { +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp +0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // ! +0x0000, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // " +0x0000, 0x1980, 0x1980, 0x1980, 0x1980, 0x7FC0, 0x7FC0, 0x1980, 0x3300, 0x7FC0, 0x7FC0, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, 0x0000, // # +0x0000, 0x1E00, 0x3F00, 0x7580, 0x6580, 0x7400, 0x3C00, 0x1E00, 0x0700, 0x0580, 0x6580, 0x6580, 0x7580, 0x3F00, 0x1E00, 0x0400, 0x0400, 0x0000, // $ +0x0000, 0x7000, 0xD800, 0xD840, 0xD8C0, 0xD980, 0x7300, 0x0600, 0x0C00, 0x1B80, 0x36C0, 0x66C0, 0x46C0, 0x06C0, 0x0380, 0x0000, 0x0000, 0x0000, // % +0x0000, 0x1E00, 0x3F00, 0x3300, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x3CC0, 0x66C0, 0x6380, 0x6180, 0x6380, 0x3EC0, 0x1C80, 0x0000, 0x0000, 0x0000, // & +0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ' +0x0080, 0x0100, 0x0300, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0300, 0x0100, 0x0080, // ( +0x2000, 0x1000, 0x1800, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x1800, 0x1000, 0x2000, // ) +0x0000, 0x0C00, 0x2D00, 0x3F00, 0x1E00, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // * +0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // + +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // , +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x1E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // - +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // . +0x0000, 0x0300, 0x0300, 0x0300, 0x0600, 0x0600, 0x0600, 0x0600, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // / +0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6D80, 0x6D80, 0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 0 +0x0000, 0x0600, 0x0E00, 0x1E00, 0x3600, 0x2600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 1 +0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x0180, 0x0300, 0x0600, 0x0C00, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // 2 +0x0000, 0x1C00, 0x3E00, 0x6300, 0x6300, 0x0300, 0x0E00, 0x0E00, 0x0300, 0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 3 +0x0000, 0x0600, 0x0E00, 0x0E00, 0x1E00, 0x1E00, 0x1600, 0x3600, 0x3600, 0x6600, 0x7F80, 0x7F80, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 4 +0x0000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x6380, 0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 5 +0x0000, 0x1E00, 0x3F00, 0x3380, 0x6180, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x3380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 6 +0x0000, 0x7F80, 0x7F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0600, 0x0C00, 0x0C00, 0x0C00, 0x0800, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // 7 +0x0000, 0x1E00, 0x3F00, 0x6380, 0x6180, 0x6180, 0x2100, 0x1E00, 0x3F00, 0x6180, 0x6180, 0x6180, 0x6180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 8 +0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6180, 0x7300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 9 +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // : +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // ; +0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0380, 0x0E00, 0x3800, 0x6000, 0x3800, 0x0E00, 0x0380, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // < +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // = +0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x7000, 0x1C00, 0x0700, 0x0180, 0x0700, 0x1C00, 0x7000, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // > +0x0000, 0x1F00, 0x3F80, 0x71C0, 0x60C0, 0x00C0, 0x01C0, 0x0380, 0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // ? +0x0000, 0x1E00, 0x3F00, 0x3180, 0x7180, 0x6380, 0x6F80, 0x6D80, 0x6D80, 0x6F80, 0x6780, 0x6000, 0x3200, 0x3E00, 0x1C00, 0x0000, 0x0000, 0x0000, // @ +0x0000, 0x0E00, 0x0E00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x3180, 0x3180, 0x3F80, 0x3F80, 0x3180, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // A +0x0000, 0x7C00, 0x7E00, 0x6300, 0x6300, 0x6300, 0x6300, 0x7E00, 0x7E00, 0x6300, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x0000, 0x0000, 0x0000, // B +0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // C +0x0000, 0x7C00, 0x7F00, 0x6300, 0x6380, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6300, 0x6300, 0x7E00, 0x7C00, 0x0000, 0x0000, 0x0000, // D +0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // E +0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // F +0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6380, 0x6380, 0x6180, 0x6180, 0x3180, 0x3F80, 0x1E00, 0x0000, 0x0000, 0x0000, // G +0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7F80, 0x7F80, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // H +0x0000, 0x3F00, 0x3F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3F00, 0x3F00, 0x0000, 0x0000, 0x0000, // I +0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // J +0x0000, 0x60C0, 0x6180, 0x6300, 0x6600, 0x6600, 0x6C00, 0x7800, 0x7C00, 0x6600, 0x6600, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // K +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // L +0x0000, 0x71C0, 0x71C0, 0x7BC0, 0x7AC0, 0x6AC0, 0x6AC0, 0x6EC0, 0x64C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // M +0x0000, 0x7180, 0x7180, 0x7980, 0x7980, 0x7980, 0x6D80, 0x6D80, 0x6D80, 0x6580, 0x6780, 0x6780, 0x6780, 0x6380, 0x6380, 0x0000, 0x0000, 0x0000, // N +0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // O +0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // P +0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6580, 0x6780, 0x3300, 0x3F80, 0x1E40, 0x0000, 0x0000, 0x0000, // Q +0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x6600, 0x6300, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // R +0x0000, 0x0E00, 0x1F00, 0x3180, 0x3180, 0x3000, 0x3800, 0x1E00, 0x0700, 0x0380, 0x6180, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // S +0x0000, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // T +0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // U +0x0000, 0x60C0, 0x60C0, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x0400, 0x0000, 0x0000, 0x0000, // V +0x0000, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xCCC0, 0x4C80, 0x4C80, 0x5E80, 0x5280, 0x5280, 0x7380, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // W +0x0000, 0xC0C0, 0x6080, 0x6180, 0x3300, 0x3B00, 0x1E00, 0x0C00, 0x0C00, 0x1E00, 0x1F00, 0x3B00, 0x7180, 0x6180, 0xC0C0, 0x0000, 0x0000, 0x0000, // X +0x0000, 0xC0C0, 0x6180, 0x6180, 0x3300, 0x3300, 0x1E00, 0x1E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // Y +0x0000, 0x3F80, 0x3F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // Z +0x0F00, 0x0F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0F00, 0x0F00, // [ +0x0000, 0x1800, 0x1800, 0x1800, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0300, 0x0300, 0x0300, 0x0000, 0x0000, 0x0000, /* \ */ +0x1E00, 0x1E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x1E00, 0x1E00, // ] +0x0000, 0x0C00, 0x0C00, 0x1E00, 0x1200, 0x3300, 0x3300, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^ +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFE0, 0x0000, // _ +0x0000, 0x3800, 0x1800, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ` +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F00, 0x3F80, 0x6180, 0x0180, 0x1F80, 0x3F80, 0x6180, 0x6380, 0x7F80, 0x38C0, 0x0000, 0x0000, 0x0000, // a +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x0000, 0x0000, 0x0000, // b +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6000, 0x6000, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // c +0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0000, 0x0000, 0x0000, // d +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x7F80, 0x7F80, 0x6000, 0x7180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // e +0x0000, 0x07C0, 0x0FC0, 0x0C00, 0x0C00, 0x7F80, 0x7F80, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // f +0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6380, 0x7F00, 0x3E00, // g +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6F00, 0x7F80, 0x7180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // h +0x0000, 0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // i +0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x4600, 0x7E00, 0x3C00, // j +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x6300, 0x6600, 0x6C00, 0x7C00, 0x7600, 0x6300, 0x6300, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // k +0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // l +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xFFC0, 0xCEC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0x0000, 0x0000, 0x0000, // m +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6F00, 0x7F80, 0x7180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // n +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // o +0x0000, 0x0000, 0x0000, 0x0000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x6000, 0x6000, 0x6000, 0x6000, // p +0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x0180, 0x0180, 0x0180, // q +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6700, 0x3F80, 0x3900, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, // r +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F80, 0x6180, 0x6000, 0x7F00, 0x3F80, 0x0180, 0x6180, 0x7F00, 0x1E00, 0x0000, 0x0000, 0x0000, // s +0x0000, 0x0000, 0x0800, 0x1800, 0x1800, 0x7F00, 0x7F00, 0x1800, 0x1800, 0x1800, 0x1800, 0x1800, 0x1800, 0x1F80, 0x0F80, 0x0000, 0x0000, 0x0000, // t +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F80, 0x3D80, 0x0000, 0x0000, 0x0000, // u +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0600, 0x0000, 0x0000, 0x0000, // v +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xDD80, 0xDD80, 0x5500, 0x5500, 0x5500, 0x7700, 0x7700, 0x2200, 0x2200, 0x0000, 0x0000, 0x0000, // w +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x0C00, 0x1E00, 0x3300, 0x3300, 0x6180, 0x0000, 0x0000, 0x0000, // x +0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x3180, 0x3300, 0x3300, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x1C00, 0x7C00, 0x7000, // y +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FC0, 0x0180, 0x0300, 0x0600, 0x0C00, 0x1800, 0x3000, 0x7FC0, 0x7FC0, 0x0000, 0x0000, 0x0000, // z +0x0380, 0x0780, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0E00, 0x1C00, 0x1C00, 0x0E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0780, 0x0380, // { +0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, // | +0x3800, 0x3C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0E00, 0x0700, 0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3C00, 0x3800, // } +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3880, 0x7F80, 0x4700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~ +}; + +static const uint16_t Font16x26 [] = { +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [ ] +0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03C0,0x03C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [!] +0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = ["] +0x01CE,0x03CE,0x03DE,0x039E,0x039C,0x079C,0x3FFF,0x7FFF,0x0738,0x0F38,0x0F78,0x0F78,0x0E78,0xFFFF,0xFFFF,0x1EF0,0x1CF0,0x1CE0,0x3CE0,0x3DE0,0x39E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [#] +0x03FC,0x0FFE,0x1FEE,0x1EE0,0x1EE0,0x1EE0,0x1EE0,0x1FE0,0x0FE0,0x07E0,0x03F0,0x01FC,0x01FE,0x01FE,0x01FE,0x01FE,0x01FE,0x01FE,0x3DFE,0x3FFC,0x0FF0,0x01E0,0x01E0,0x0000,0x0000,0x0000, // Ascii = [$] +0x3E03,0xF707,0xE78F,0xE78E,0xE39E,0xE3BC,0xE7B8,0xE7F8,0xF7F0,0x3FE0,0x01C0,0x03FF,0x07FF,0x07F3,0x0FF3,0x1EF3,0x3CF3,0x38F3,0x78F3,0xF07F,0xE03F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [%] +0x07E0,0x0FF8,0x0F78,0x1F78,0x1F78,0x1F78,0x0F78,0x0FF0,0x0FE0,0x1F80,0x7FC3,0xFBC3,0xF3E7,0xF1F7,0xF0F7,0xF0FF,0xF07F,0xF83E,0x7C7F,0x3FFF,0x1FEF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [&] +0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03C0,0x01C0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = ['] +0x003F,0x007C,0x01F0,0x01E0,0x03C0,0x07C0,0x0780,0x0780,0x0F80,0x0F00,0x0F00,0x0F00,0x0F00,0x0F00,0x0F00,0x0F80,0x0780,0x0780,0x07C0,0x03C0,0x01E0,0x01F0,0x007C,0x003F,0x000F,0x0000, // Ascii = [(] +0x7E00,0x1F00,0x07C0,0x03C0,0x01E0,0x01F0,0x00F0,0x00F0,0x00F8,0x0078,0x0078,0x0078,0x0078,0x0078,0x0078,0x00F8,0x00F0,0x00F0,0x01F0,0x01E0,0x03C0,0x07C0,0x1F00,0x7E00,0x7800,0x0000, // Ascii = [)] +0x03E0,0x03C0,0x01C0,0x39CE,0x3FFF,0x3F7F,0x0320,0x0370,0x07F8,0x0F78,0x1F3C,0x0638,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [*] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0xFFFF,0xFFFF,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [+] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x01E0,0x01E0,0x01E0,0x01C0,0x0380, // Ascii = [,] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FFE,0x3FFE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [-] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [.] +0x000F,0x000F,0x001E,0x001E,0x003C,0x003C,0x0078,0x0078,0x00F0,0x00F0,0x01E0,0x01E0,0x03C0,0x03C0,0x0780,0x0780,0x0F00,0x0F00,0x1E00,0x1E00,0x3C00,0x3C00,0x7800,0x7800,0xF000,0x0000, // Ascii = [/] +0x07F0,0x0FF8,0x1F7C,0x3E3E,0x3C1E,0x7C1F,0x7C1F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x7C1F,0x7C1F,0x3C1E,0x3E3E,0x1F7C,0x0FF8,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [0] +0x00F0,0x07F0,0x3FF0,0x3FF0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [1] +0x0FE0,0x3FF8,0x3C7C,0x003C,0x003E,0x003E,0x003E,0x003C,0x003C,0x007C,0x00F8,0x01F0,0x03E0,0x07C0,0x0780,0x0F00,0x1E00,0x3E00,0x3C00,0x3FFE,0x3FFE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [2] +0x0FF0,0x1FF8,0x1C7C,0x003E,0x003E,0x003E,0x003C,0x003C,0x00F8,0x0FF0,0x0FF8,0x007C,0x003E,0x001E,0x001E,0x001E,0x001E,0x003E,0x1C7C,0x1FF8,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [3] +0x0078,0x00F8,0x00F8,0x01F8,0x03F8,0x07F8,0x07F8,0x0F78,0x1E78,0x1E78,0x3C78,0x7878,0x7878,0xFFFF,0xFFFF,0x0078,0x0078,0x0078,0x0078,0x0078,0x0078,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [4] +0x1FFC,0x1FFC,0x1FFC,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1FE0,0x1FF8,0x00FC,0x007C,0x003E,0x003E,0x001E,0x003E,0x003E,0x003C,0x1C7C,0x1FF8,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [5] +0x01FC,0x07FE,0x0F8E,0x1F00,0x1E00,0x3E00,0x3C00,0x3C00,0x3DF8,0x3FFC,0x7F3E,0x7E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3E0F,0x1E1F,0x1F3E,0x0FFC,0x03F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [6] +0x3FFF,0x3FFF,0x3FFF,0x000F,0x001E,0x001E,0x003C,0x0038,0x0078,0x00F0,0x00F0,0x01E0,0x01E0,0x03C0,0x03C0,0x0780,0x0F80,0x0F80,0x0F00,0x1F00,0x1F00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [7] +0x07F8,0x0FFC,0x1F3E,0x1E1E,0x3E1E,0x3E1E,0x1E1E,0x1F3C,0x0FF8,0x07F0,0x0FF8,0x1EFC,0x3E3E,0x3C1F,0x7C1F,0x7C0F,0x7C0F,0x3C1F,0x3F3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [8] +0x07F0,0x0FF8,0x1E7C,0x3C3E,0x3C1E,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x3C1F,0x3E3F,0x1FFF,0x07EF,0x001F,0x001E,0x001E,0x003E,0x003C,0x38F8,0x3FF0,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [9] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [:] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x01E0,0x01E0,0x01E0,0x03C0,0x0380, // Ascii = [;] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0x000F,0x003F,0x00FC,0x03F0,0x0FC0,0x3F00,0xFE00,0x3F00,0x0FC0,0x03F0,0x00FC,0x003F,0x000F,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [<] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [=] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xE000,0xF800,0x7E00,0x1F80,0x07E0,0x01F8,0x007E,0x001F,0x007E,0x01F8,0x07E0,0x1F80,0x7E00,0xF800,0xE000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [>] +0x1FF0,0x3FFC,0x383E,0x381F,0x381F,0x001E,0x001E,0x003C,0x0078,0x00F0,0x01E0,0x03C0,0x03C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x07C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [?] +0x03F8,0x0FFE,0x1F1E,0x3E0F,0x3C7F,0x78FF,0x79EF,0x73C7,0xF3C7,0xF38F,0xF38F,0xF38F,0xF39F,0xF39F,0x73FF,0x7BFF,0x79F7,0x3C00,0x1F1C,0x0FFC,0x03F8,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [@] +0x0000,0x0000,0x0000,0x03E0,0x03E0,0x07F0,0x07F0,0x07F0,0x0F78,0x0F78,0x0E7C,0x1E3C,0x1E3C,0x3C3E,0x3FFE,0x3FFF,0x781F,0x780F,0xF00F,0xF007,0xF007,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [A] +0x0000,0x0000,0x0000,0x3FF8,0x3FFC,0x3C3E,0x3C1E,0x3C1E,0x3C1E,0x3C3E,0x3C7C,0x3FF0,0x3FF8,0x3C7E,0x3C1F,0x3C1F,0x3C0F,0x3C0F,0x3C1F,0x3FFE,0x3FF8,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [B] +0x0000,0x0000,0x0000,0x01FF,0x07FF,0x1F87,0x3E00,0x3C00,0x7C00,0x7800,0x7800,0x7800,0x7800,0x7800,0x7C00,0x7C00,0x3E00,0x3F00,0x1F83,0x07FF,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [C] +0x0000,0x0000,0x0000,0x7FF0,0x7FFC,0x787E,0x781F,0x781F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x781F,0x781E,0x787E,0x7FF8,0x7FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [D] +0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFE,0x3FFE,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [E] +0x0000,0x0000,0x0000,0x1FFF,0x1FFF,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1FFF,0x1FFF,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [F] +0x0000,0x0000,0x0000,0x03FE,0x0FFF,0x1F87,0x3E00,0x7C00,0x7C00,0x7800,0xF800,0xF800,0xF87F,0xF87F,0x780F,0x7C0F,0x7C0F,0x3E0F,0x1F8F,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [G] +0x0000,0x0000,0x0000,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7FFF,0x7FFF,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [H] +0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [I] +0x0000,0x0000,0x0000,0x1FFC,0x1FFC,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x0078,0x0078,0x38F8,0x3FF0,0x3FC0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [J] +0x0000,0x0000,0x0000,0x3C1F,0x3C1E,0x3C3C,0x3C78,0x3CF0,0x3DE0,0x3FE0,0x3FC0,0x3F80,0x3FC0,0x3FE0,0x3DF0,0x3CF0,0x3C78,0x3C7C,0x3C3E,0x3C1F,0x3C0F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [K] +0x0000,0x0000,0x0000,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [L] +0x0000,0x0000,0x0000,0xF81F,0xFC1F,0xFC1F,0xFE3F,0xFE3F,0xFE3F,0xFF7F,0xFF77,0xFF77,0xF7F7,0xF7E7,0xF3E7,0xF3E7,0xF3C7,0xF007,0xF007,0xF007,0xF007,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [M] +0x0000,0x0000,0x0000,0x7C0F,0x7C0F,0x7E0F,0x7F0F,0x7F0F,0x7F8F,0x7F8F,0x7FCF,0x7BEF,0x79EF,0x79FF,0x78FF,0x78FF,0x787F,0x783F,0x783F,0x781F,0x781F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [N] +0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x7C1F,0x780F,0x780F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0x780F,0x780F,0x7C1F,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [O] +0x0000,0x0000,0x0000,0x3FFC,0x3FFF,0x3E1F,0x3E0F,0x3E0F,0x3E0F,0x3E0F,0x3E1F,0x3E3F,0x3FFC,0x3FF0,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [P] +0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x7C1F,0x780F,0x780F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0x780F,0x780F,0x7C1F,0x3E3E,0x1FFC,0x07F8,0x007C,0x003F,0x000F,0x0003,0x0000, // Ascii = [Q] +0x0000,0x0000,0x0000,0x3FF0,0x3FFC,0x3C7E,0x3C3E,0x3C1E,0x3C1E,0x3C3E,0x3C3C,0x3CFC,0x3FF0,0x3FE0,0x3DF0,0x3CF8,0x3C7C,0x3C3E,0x3C1E,0x3C1F,0x3C0F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [R] +0x0000,0x0000,0x0000,0x07FC,0x1FFE,0x3E0E,0x3C00,0x3C00,0x3C00,0x3E00,0x1FC0,0x0FF8,0x03FE,0x007F,0x001F,0x000F,0x000F,0x201F,0x3C3E,0x3FFC,0x1FF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [S] +0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [T] +0x0000,0x0000,0x0000,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x3C1E,0x3C1E,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [U] +0x0000,0x0000,0x0000,0xF007,0xF007,0xF807,0x780F,0x7C0F,0x3C1E,0x3C1E,0x3E1E,0x1E3C,0x1F3C,0x1F78,0x0F78,0x0FF8,0x07F0,0x07F0,0x07F0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [V] +0x0000,0x0000,0x0000,0xE003,0xF003,0xF003,0xF007,0xF3E7,0xF3E7,0xF3E7,0x73E7,0x7BF7,0x7FF7,0x7FFF,0x7F7F,0x7F7F,0x7F7E,0x3F7E,0x3E3E,0x3E3E,0x3E3E,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [W] +0x0000,0x0000,0x0000,0xF807,0x7C0F,0x3E1E,0x3E3E,0x1F3C,0x0FF8,0x07F0,0x07E0,0x03E0,0x03E0,0x07F0,0x0FF8,0x0F7C,0x1E7C,0x3C3E,0x781F,0x780F,0xF00F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [X] +0x0000,0x0000,0x0000,0xF807,0x7807,0x7C0F,0x3C1E,0x3E1E,0x1F3C,0x0F78,0x0FF8,0x07F0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [Y] +0x0000,0x0000,0x0000,0x7FFF,0x7FFF,0x000F,0x001F,0x003E,0x007C,0x00F8,0x00F0,0x01E0,0x03E0,0x07C0,0x0F80,0x0F00,0x1E00,0x3E00,0x7C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [Z] +0x07FF,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x07FF,0x07FF,0x0000, // Ascii = [[] +0x7800,0x7800,0x3C00,0x3C00,0x1E00,0x1E00,0x0F00,0x0F00,0x0780,0x0780,0x03C0,0x03C0,0x01E0,0x01E0,0x00F0,0x00F0,0x0078,0x0078,0x003C,0x003C,0x001E,0x001E,0x000F,0x000F,0x0007,0x0000, // Ascii = [\] +0x7FF0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x7FF0,0x7FF0,0x0000, // Ascii = []] +0x00C0,0x01C0,0x01C0,0x03E0,0x03E0,0x07F0,0x07F0,0x0778,0x0F78,0x0F38,0x1E3C,0x1E3C,0x3C1E,0x3C1E,0x380F,0x780F,0x7807,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [^] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000, // Ascii = [_] +0x00F0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [`] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0FF8,0x3FFC,0x3C7C,0x003E,0x003E,0x003E,0x07FE,0x1FFE,0x3E3E,0x7C3E,0x783E,0x7C3E,0x7C7E,0x3FFF,0x1FCF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [a] +0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3DF8,0x3FFE,0x3F3E,0x3E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C1F,0x3C1E,0x3F3E,0x3FFC,0x3BF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [b] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03FE,0x0FFF,0x1F87,0x3E00,0x3E00,0x3C00,0x7C00,0x7C00,0x7C00,0x3C00,0x3E00,0x3E00,0x1F87,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [c] +0x001F,0x001F,0x001F,0x001F,0x001F,0x001F,0x07FF,0x1FFF,0x3E3F,0x3C1F,0x7C1F,0x7C1F,0x7C1F,0x781F,0x781F,0x7C1F,0x7C1F,0x3C3F,0x3E7F,0x1FFF,0x0FDF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [d] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03F8,0x0FFC,0x1F3E,0x3E1E,0x3C1F,0x7C1F,0x7FFF,0x7FFF,0x7C00,0x7C00,0x3C00,0x3E00,0x1F07,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [e] +0x01FF,0x03E1,0x03C0,0x07C0,0x07C0,0x07C0,0x7FFF,0x7FFF,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [f] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07EF,0x1FFF,0x3E7F,0x3C1F,0x7C1F,0x7C1F,0x781F,0x781F,0x781F,0x7C1F,0x7C1F,0x3C3F,0x3E7F,0x1FFF,0x0FDF,0x001E,0x001E,0x001E,0x387C,0x3FF8, // Ascii = [g] +0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3DFC,0x3FFE,0x3F9E,0x3F1F,0x3E1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [h] +0x01F0,0x01F0,0x0000,0x0000,0x0000,0x0000,0x7FE0,0x7FE0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [i] +0x00F8,0x00F8,0x0000,0x0000,0x0000,0x0000,0x3FF8,0x3FF8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F0,0x71F0,0x7FE0, // Ascii = [j] +0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C1F,0x3C3E,0x3C7C,0x3CF8,0x3DF0,0x3DE0,0x3FC0,0x3FC0,0x3FE0,0x3DF0,0x3CF8,0x3C7C,0x3C3E,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [k] +0x7FF0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [l] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF79E,0xFFFF,0xFFFF,0xFFFF,0xFBE7,0xF9E7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [m] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3DFC,0x3FFE,0x3F9E,0x3F1F,0x3E1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [n] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x3C1F,0x7C1F,0x780F,0x780F,0x780F,0x780F,0x780F,0x7C1F,0x3C1F,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [o] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3DF8,0x3FFE,0x3F3E,0x3E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C1F,0x3E1E,0x3F3E,0x3FFC,0x3FF8,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00, // Ascii = [p] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07EE,0x1FFE,0x3E7E,0x3C1E,0x7C1E,0x781E,0x781E,0x781E,0x781E,0x781E,0x7C1E,0x7C3E,0x3E7E,0x1FFE,0x0FDE,0x001E,0x001E,0x001E,0x001E,0x001E, // Ascii = [q] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1F7F,0x1FFF,0x1FE7,0x1FC7,0x1F87,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [r] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07FC,0x1FFE,0x1E0E,0x3E00,0x3E00,0x3F00,0x1FE0,0x07FC,0x00FE,0x003E,0x001E,0x001E,0x3C3E,0x3FFC,0x1FF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [s] +0x0000,0x0000,0x0000,0x0780,0x0780,0x0780,0x7FFF,0x7FFF,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x07C0,0x03FF,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [t] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C3E,0x3C7E,0x3EFE,0x1FFE,0x0FDE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [u] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF007,0x780F,0x780F,0x3C1E,0x3C1E,0x3E1E,0x1E3C,0x1E3C,0x0F78,0x0F78,0x0FF0,0x07F0,0x07F0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [v] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF003,0xF1E3,0xF3E3,0xF3E7,0xF3F7,0xF3F7,0x7FF7,0x7F77,0x7F7F,0x7F7F,0x7F7F,0x3E3E,0x3E3E,0x3E3E,0x3E3E,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [w] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7C0F,0x3E1E,0x3E3C,0x1F3C,0x0FF8,0x07F0,0x07F0,0x03E0,0x07F0,0x07F8,0x0FF8,0x1E7C,0x3E3E,0x3C1F,0x781F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [x] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF807,0x780F,0x7C0F,0x3C1E,0x3C1E,0x1E3C,0x1E3C,0x1F3C,0x0F78,0x0FF8,0x07F0,0x07F0,0x03E0,0x03E0,0x03C0,0x03C0,0x03C0,0x0780,0x0F80,0x7F00, // Ascii = [y] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x001F,0x003E,0x007C,0x00F8,0x01F0,0x03E0,0x07C0,0x0F80,0x1F00,0x1E00,0x3C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [z] +0x01FE,0x03E0,0x03C0,0x03C0,0x03C0,0x03C0,0x01E0,0x01E0,0x01E0,0x01C0,0x03C0,0x3F80,0x3F80,0x03C0,0x01C0,0x01E0,0x01E0,0x01E0,0x03C0,0x03C0,0x03C0,0x03C0,0x03E0,0x01FE,0x007E,0x0000, // Ascii = [{] +0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000, // Ascii = [|] +0x3FC0,0x03E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01C0,0x03C0,0x03C0,0x01C0,0x01E0,0x00FE,0x00FE,0x01E0,0x01C0,0x03C0,0x03C0,0x01C0,0x01E0,0x01E0,0x01E0,0x01E0,0x03E0,0x3FC0,0x3F00,0x0000, // Ascii = [}] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3F07,0x7FC7,0x73E7,0xF1FF,0xF07E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [~] +}; + +FontDef Font_7x10 = {7,10,Font7x10}; +FontDef Font_11x18 = {11,18,Font11x18}; +FontDef Font_16x26 = {16,26,Font16x26}; \ No newline at end of file diff --git a/Software/DisplayBoard/Core/Src/main.c b/Software/DisplayBoard/Core/Src/main.c new file mode 100644 index 0000000..177624a --- /dev/null +++ b/Software/DisplayBoard/Core/Src/main.c @@ -0,0 +1,854 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "ssd1306.h" +#include "fonts.h" +#include +#include +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +ADC_HandleTypeDef hadc; + +I2C_HandleTypeDef hi2c1; +DMA_HandleTypeDef hdma_i2c1_tx; + +TIM_HandleTypeDef htim3; +TIM_HandleTypeDef htim6; +TIM_HandleTypeDef htim14; + +UART_HandleTypeDef huart1; +DMA_HandleTypeDef hdma_usart1_rx; + +/* USER CODE BEGIN PV */ +int lastFuelGaugeCount = 5; +int tstCnt = 0; +int cnt = 1; +int resetTimer = 0; +uint32_t lastRpmPulseTimCnt = 0; +uint32_t lastSpdPulseTimCnt = 0; +int rpm, speed; +float trip = 0; +float all_kms = 0; +float battVoltage = 0; +float fuelLevel = 0; +int battVoltageADC = 0; +int fuelLevelADC = 0; +uint32_t avgRpmTime = 0; +uint32_t avgSpdTime = 0; +uint32_t rpmSamples[60]; +int rpmSamplesIndex = 0; +uint32_t spdSamples[60]; +int spdSamplesIndex = 0; +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +static void MX_DMA_Init(void); +static void MX_I2C1_Init(void); +static void MX_ADC_Init(void); +static void MX_TIM3_Init(void); +static void MX_TIM14_Init(void); +static void MX_USART1_UART_Init(void); +static void MX_TIM6_Init(void); +/* USER CODE BEGIN PFP */ +void FuelGauge(int); +void MultiChannelADC(ADC_HandleTypeDef*, uint32_t*, uint8_t); +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* USER CODE BEGIN Init */ + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + MX_I2C1_Init(); + MX_ADC_Init(); + MX_TIM3_Init(); + MX_TIM14_Init(); + MX_USART1_UART_Init(); + MX_TIM6_Init(); + /* USER CODE BEGIN 2 */ + TIM6->DIER |= 1 << 0; + + if (ssd1306_Init(&hi2c1) != 0) { + Error_Handler(); + } + + ssd1306_Fill(Black); + ssd1306_UpdateScreen(&hi2c1); + + ssd1306_SetCursor(0, 23); + ssd1306_WriteString("Motorcycle Monitor", Font_7x10, White); + ssd1306_SetCursor(23, 45); + ssd1306_WriteString("Ver: 1.0.0", Font_7x10, White); + ssd1306_UpdateScreen(&hi2c1); + HAL_Delay(1000); + HAL_TIM_Base_Start_IT(&htim6); + ssd1306_Fill(Black); + + /* USER CODE END 2 */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + uint32_t ADCReadArr[2]; + + MultiChannelADC(&hadc, ADCReadArr, 2); + + fuelLevelADC = ADCReadArr[0]; + battVoltageADC = ADCReadArr[1]; + + battVoltage = battVoltageADC*(V_REF/4096)*U_BATT_DIV_RATIO; + fuelLevel = fuelLevelADC*(V_REF/4096)*FUEL_DIV_RATIO; + + int fuelLevelStep = MAX_FUEL_U/5; + if(fuelLevel < fuelLevelStep){ + FuelGauge(0); + } + else if(fuelLevel < fuelLevelStep*2){ + FuelGauge(1); + } + else if(fuelLevel < fuelLevelStep*3){ + FuelGauge(2); + } + else if(fuelLevel < fuelLevelStep*4){ + FuelGauge(3); + } + else{ + FuelGauge(4); + } + + if(resetTimer > 5){ + resetTimer = 0; + ssd1306_SetCursor(0, 0); + ssd1306_WriteString("0", Font_16x26, White); + ssd1306_SetCursor(78, 0); + ssd1306_WriteString("0", Font_16x26, White); + ssd1306_UpdateScreen(&hi2c1); + } + + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + } + /* USER CODE END 3 */ +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI14; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSI14State = RCC_HSI14_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.HSI14CalibrationValue = 16; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12; + RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) + { + Error_Handler(); + } + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1; + PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1; + PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { + Error_Handler(); + } + HAL_RCC_MCOConfig(RCC_MCO, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_1); +} + +/** + * @brief ADC Initialization Function + * @param None + * @retval None + */ +static void MX_ADC_Init(void) +{ + + /* USER CODE BEGIN ADC_Init 0 */ + + /* USER CODE END ADC_Init 0 */ + + ADC_ChannelConfTypeDef sConfig = {0}; + + /* USER CODE BEGIN ADC_Init 1 */ + + /* USER CODE END ADC_Init 1 */ + /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) + */ + hadc.Instance = ADC1; + hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; + hadc.Init.Resolution = ADC_RESOLUTION_12B; + hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD; + hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; + hadc.Init.LowPowerAutoWait = DISABLE; + hadc.Init.LowPowerAutoPowerOff = DISABLE; + hadc.Init.ContinuousConvMode = DISABLE; + hadc.Init.DiscontinuousConvMode = DISABLE; + hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; + hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc.Init.DMAContinuousRequests = DISABLE; + hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED; + if (HAL_ADC_Init(&hadc) != HAL_OK) + { + Error_Handler(); + } + /** Configure for the selected ADC regular channel to be converted. + */ + sConfig.Channel = ADC_CHANNEL_3; + sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; + sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; + if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) + { + Error_Handler(); + } + /** Configure for the selected ADC regular channel to be converted. + */ + sConfig.Channel = ADC_CHANNEL_5; + if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN ADC_Init 2 */ + + /* USER CODE END ADC_Init 2 */ + +} + +/** + * @brief I2C1 Initialization Function + * @param None + * @retval None + */ +static void MX_I2C1_Init(void) +{ + + /* USER CODE BEGIN I2C1_Init 0 */ + + /* USER CODE END I2C1_Init 0 */ + + /* USER CODE BEGIN I2C1_Init 1 */ + + /* USER CODE END I2C1_Init 1 */ + hi2c1.Instance = I2C1; + hi2c1.Init.Timing = 0x0000020B; + hi2c1.Init.OwnAddress1 = 0; + hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c1.Init.OwnAddress2 = 0; + hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c1) != HAL_OK) + { + Error_Handler(); + } + /** Configure Analogue filter + */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) + { + Error_Handler(); + } + /** Configure Digital filter + */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN I2C1_Init 2 */ + + /* USER CODE END I2C1_Init 2 */ + +} + +/** + * @brief TIM3 Initialization Function + * @param None + * @retval None + */ +static void MX_TIM3_Init(void) +{ + + /* USER CODE BEGIN TIM3_Init 0 */ + + /* USER CODE END TIM3_Init 0 */ + + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_IC_InitTypeDef sConfigIC = {0}; + + /* USER CODE BEGIN TIM3_Init 1 */ + + /* USER CODE END TIM3_Init 1 */ + htim3.Instance = TIM3; + htim3.Init.Prescaler = 4799; + htim3.Init.CounterMode = TIM_COUNTERMODE_UP; + htim3.Init.Period = 10000; + htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&htim3) != HAL_OK) + { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_IC_Init(&htim3) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK) + { + Error_Handler(); + } + sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; + sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; + sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; + sConfigIC.ICFilter = 0; + if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM3_Init 2 */ + + /* USER CODE END TIM3_Init 2 */ + +} + +/** + * @brief TIM6 Initialization Function + * @param None + * @retval None + */ +static void MX_TIM6_Init(void) +{ + + /* USER CODE BEGIN TIM6_Init 0 */ + + /* USER CODE END TIM6_Init 0 */ + + /* USER CODE BEGIN TIM6_Init 1 */ + + /* USER CODE END TIM6_Init 1 */ + htim6.Instance = TIM6; + htim6.Init.Prescaler = 47999; + htim6.Init.CounterMode = TIM_COUNTERMODE_UP; + htim6.Init.Period = 1000; + htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&htim6) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM6_Init 2 */ + + /* USER CODE END TIM6_Init 2 */ + +} + +/** + * @brief TIM14 Initialization Function + * @param None + * @retval None + */ +static void MX_TIM14_Init(void) +{ + + /* USER CODE BEGIN TIM14_Init 0 */ + + /* USER CODE END TIM14_Init 0 */ + + TIM_IC_InitTypeDef sConfigIC = {0}; + + /* USER CODE BEGIN TIM14_Init 1 */ + + /* USER CODE END TIM14_Init 1 */ + htim14.Instance = TIM14; + htim14.Init.Prescaler = 4799; + htim14.Init.CounterMode = TIM_COUNTERMODE_UP; + htim14.Init.Period = 10000; + htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&htim14) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_IC_Init(&htim14) != HAL_OK) + { + Error_Handler(); + } + sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; + sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; + sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; + sConfigIC.ICFilter = 0; + if (HAL_TIM_IC_ConfigChannel(&htim14, &sConfigIC, TIM_CHANNEL_1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM14_Init 2 */ + + /* USER CODE END TIM14_Init 2 */ + +} + +/** + * @brief USART1 Initialization Function + * @param None + * @retval None + */ +static void MX_USART1_UART_Init(void) +{ + + /* USER CODE BEGIN USART1_Init 0 */ + + /* USER CODE END USART1_Init 0 */ + + /* USER CODE BEGIN USART1_Init 1 */ + + /* USER CODE END USART1_Init 1 */ + huart1.Instance = USART1; + huart1.Init.BaudRate = 38400; + huart1.Init.WordLength = UART_WORDLENGTH_8B; + huart1.Init.StopBits = UART_STOPBITS_1; + huart1.Init.Parity = UART_PARITY_NONE; + huart1.Init.Mode = UART_MODE_TX_RX; + huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart1.Init.OverSampling = UART_OVERSAMPLING_16; + huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; + huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; + if (HAL_UART_Init(&huart1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USART1_Init 2 */ + + /* USER CODE END USART1_Init 2 */ + +} + +/** + * Enable DMA controller clock + */ +static void MX_DMA_Init(void) +{ + + /* DMA controller clock enable */ + __HAL_RCC_DMA1_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA1_Channel2_3_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); + +} + +/** + * @brief GPIO Initialization Function + * @param None + * @retval None + */ +static void MX_GPIO_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pins : GPInput1_Pin GPInput2_Pin */ + GPIO_InitStruct.Pin = GPInput1_Pin|GPInput2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /*Configure GPIO pin : LED_Pin */ + GPIO_InitStruct.Pin = LED_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct); + + /* EXTI interrupt init*/ + HAL_NVIC_SetPriority(EXTI0_1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(EXTI0_1_IRQn); + + HAL_NVIC_SetPriority(EXTI2_3_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(EXTI2_3_IRQn); + +} + +/* USER CODE BEGIN 4 */ +void FuelGauge(int barCount){ + int width = 64; + int height = 32; + + if(lastFuelGaugeCount != barCount){ + lastFuelGaugeCount = barCount; + if(barCount == 0){ + for(int i = 0; i= 1){ + for(int i = 0; i= 2){ + for(int i = width/4+1; i= 3){ + for(int i = width/2+1; i= 4){ + for(int i = width-width/4+1; i Instance == TIM3){ + uint32_t rpmTime; + uint32_t RpmPulseTime = TIM3->CNT; + + resetTimer = 0; + + if(RpmPulseTime < lastRpmPulseTimCnt){ + rpmTime = (65535 + RpmPulseTime) - lastRpmPulseTimCnt; + } + else{ + rpmTime = RpmPulseTime - lastRpmPulseTimCnt; + } + rpmSamples[rpmSamplesIndex] = rpmTime; + rpmSamplesIndex++; + + if(rpmSamplesIndex == 60){ + rpmSamplesIndex = 0; + + for(int i = 0; i < (sizeof(rpmSamples)/sizeof(rpmSamples[0])); i++){ + avgRpmTime += rpmSamples[i]; + } + avgRpmTime /= (sizeof(rpmSamples)/sizeof(rpmSamples[0])); + rpm = ((float)TIM3->ARR/(float)avgRpmTime)*60; + char msg[4]; + sprintf(msg, "%d", rpm); + + for(int i = 0; i<104; i++){ + for(int j = 0; j < 27; j++){ + ssd1306_DrawPixel(i,j, Black); + } + } + + ssd1306_SetCursor(0, 0); + ssd1306_WriteString(msg, Font_16x26, White); + ssd1306_UpdateScreen(&hi2c1); + } + } + //SPEED - pulse = 100ns + if(htim -> Instance == TIM14){ + uint32_t spdTime; + uint32_t SpdPulseTime = TIM14->CNT; + + resetTimer = 0; + trip += TIRE_CIRC_M/1000; + all_kms += TIRE_CIRC_M/1000; + + if(SpdPulseTime < lastSpdPulseTimCnt){ + spdTime = (65535 + SpdPulseTime) - lastSpdPulseTimCnt; + } + else{ + spdTime = SpdPulseTime - lastSpdPulseTimCnt; + } + spdSamples[spdSamplesIndex] = spdTime; + spdSamplesIndex++; + + if(spdSamplesIndex == 60){ + spdSamplesIndex = 0; + + for(int i = 0; i < (sizeof(spdSamples)/sizeof(spdSamples[0])); i++){ + avgSpdTime += spdSamples[i]; + } + avgSpdTime /= (sizeof(spdSamples)/sizeof(spdSamples[0])); + speed = (TIRE_CIRC_M/1000)*(float)(((float)TIM14->ARR/(float)spdTime)*3600); + char msg[4]; + sprintf(msg, "%d", rpm); + + for(int i = 104; i<128; i++){ + for(int j = 0; j < 27; j++){ + ssd1306_DrawPixel(i,j, Black); + } + } + + ssd1306_SetCursor(78, 0); + ssd1306_WriteString(msg, Font_16x26, White); + ssd1306_UpdateScreen(&hi2c1); + } + } +} + +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ + if(htim -> Instance == TIM6){ + char voltage[4]; + char trp[6]; + char km[6]; + + resetTimer++; + sprintf(voltage, "%.1f", battVoltage); + sprintf(trp, "%.1f", trip); + sprintf(km, "%.1f", all_kms); + + for(int i = 70; i<128; i++){ + for(int j = 27; j < 63; j++){ + ssd1306_DrawPixel(i,j, Black); + } + } + ssd1306_SetCursor(70, 27); + ssd1306_WriteString("U: ", Font_7x10, White); + ssd1306_WriteString(voltage, Font_7x10, White); + ssd1306_SetCursor(70+7*7, 27); + ssd1306_WriteString("V", Font_7x10, White); + ssd1306_SetCursor(70, 39); + ssd1306_WriteString(km, Font_7x10, White); + ssd1306_SetCursor(70, 51); + ssd1306_WriteString(trp, Font_7x10, White); + ssd1306_UpdateScreen(&hi2c1); + } +} + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + + /* USER CODE END Error_Handler_Debug */ +} + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Software/DisplayBoard/Core/Src/ssd1306.c b/Software/DisplayBoard/Core/Src/ssd1306.c new file mode 100644 index 0000000..7880a16 --- /dev/null +++ b/Software/DisplayBoard/Core/Src/ssd1306.c @@ -0,0 +1,211 @@ +#include "ssd1306.h" + + +// Screenbuffer +static uint8_t SSD1306_Buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8]; + +// Screen object +static SSD1306_t SSD1306; + + +// +// Send a byte to the command register +// +static uint8_t ssd1306_WriteCommand(I2C_HandleTypeDef *hi2c, uint8_t command) +{ + return HAL_I2C_Mem_Write(hi2c, SSD1306_I2C_ADDR, 0x00, 1, &command, 1, 10); +} + + +// +// Initialize the oled screen +// +uint8_t ssd1306_Init(I2C_HandleTypeDef *hi2c) +{ + // Wait for the screen to boot + HAL_Delay(100); + int status = 0; + + // Init LCD + status += ssd1306_WriteCommand(hi2c, 0xAE); // Display off + status += ssd1306_WriteCommand(hi2c, 0x20); // Set Memory Addressing Mode + status += ssd1306_WriteCommand(hi2c, 0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid + status += ssd1306_WriteCommand(hi2c, 0xB0); // Set Page Start Address for Page Addressing Mode,0-7 + status += ssd1306_WriteCommand(hi2c, 0xC8); // Set COM Output Scan Direction + status += ssd1306_WriteCommand(hi2c, 0x00); // Set low column address + status += ssd1306_WriteCommand(hi2c, 0x10); // Set high column address + status += ssd1306_WriteCommand(hi2c, 0x40); // Set start line address + status += ssd1306_WriteCommand(hi2c, 0x81); // set contrast control register + status += ssd1306_WriteCommand(hi2c, 0xFF); + status += ssd1306_WriteCommand(hi2c, 0xA1); // Set segment re-map 0 to 127 + status += ssd1306_WriteCommand(hi2c, 0xA6); // Set normal display + status += ssd1306_WriteCommand(hi2c, 0xA8); // Set multiplex ratio(1 to 64) + status += ssd1306_WriteCommand(hi2c, 0x3F); + status += ssd1306_WriteCommand(hi2c, 0xA4); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content + status += ssd1306_WriteCommand(hi2c, 0xD3); // Set display offset + status += ssd1306_WriteCommand(hi2c, 0x00); // No offset + status += ssd1306_WriteCommand(hi2c, 0xD5); // Set display clock divide ratio/oscillator frequency + status += ssd1306_WriteCommand(hi2c, 0xF0); // Set divide ratio + status += ssd1306_WriteCommand(hi2c, 0xD9); // Set pre-charge period + status += ssd1306_WriteCommand(hi2c, 0x22); + status += ssd1306_WriteCommand(hi2c, 0xDA); // Set com pins hardware configuration + status += ssd1306_WriteCommand(hi2c, 0x12); + status += ssd1306_WriteCommand(hi2c, 0xDB); // Set vcomh + status += ssd1306_WriteCommand(hi2c, 0x20); // 0x20,0.77xVcc + status += ssd1306_WriteCommand(hi2c, 0x8D); // Set DC-DC enable + status += ssd1306_WriteCommand(hi2c, 0x14); // + status += ssd1306_WriteCommand(hi2c, 0xAF); // Turn on SSD1306 panel + + if (status != 0) { + return 1; + } + + // Clear screen + ssd1306_Fill(Black); + + // Flush buffer to screen + ssd1306_UpdateScreen(hi2c); + + // Set default values for screen object + SSD1306.CurrentX = 0; + SSD1306.CurrentY = 0; + + SSD1306.Initialized = 1; + + return 0; +} + +// +// Fill the whole screen with the given color +// +void ssd1306_Fill(SSD1306_COLOR color) +{ + // Fill screenbuffer with a constant value (color) + uint32_t i; + + for(i = 0; i < sizeof(SSD1306_Buffer); i++) + { + SSD1306_Buffer[i] = (color == Black) ? 0x00 : 0xFF; + } +} + +// +// Write the screenbuffer with changed to the screen +// +void ssd1306_UpdateScreen(I2C_HandleTypeDef *hi2c) +{ + uint8_t i; + + for (i = 0; i < 8; i++) { + ssd1306_WriteCommand(hi2c, 0xB0 + i); + ssd1306_WriteCommand(hi2c, 0x00); + ssd1306_WriteCommand(hi2c, 0x10); + + HAL_I2C_Mem_Write(hi2c, SSD1306_I2C_ADDR, 0x40, 1, &SSD1306_Buffer[SSD1306_WIDTH * i], SSD1306_WIDTH, 100); + } +} + +// +// Draw one pixel in the screenbuffer +// X => X Coordinate +// Y => Y Coordinate +// color => Pixel color +// +void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color) +{ + if (x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT) + { + // Don't write outside the buffer + return; + } + + // Check if pixel should be inverted + if (SSD1306.Inverted) + { + color = (SSD1306_COLOR)!color; + } + + // Draw in the correct color + if (color == White) + { + SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8); + } + else + { + SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8)); + } +} + + +// +// Draw 1 char to the screen buffer +// ch => Character to write +// Font => Font to use +// color => Black or White +// +char ssd1306_WriteChar(char ch, FontDef Font, SSD1306_COLOR color) +{ + uint32_t i, b, j; + + // Check remaining space on current line + if (SSD1306_WIDTH <= (SSD1306.CurrentX + Font.FontWidth) || + SSD1306_HEIGHT <= (SSD1306.CurrentY + Font.FontHeight)) + { + // Not enough space on current line + return 0; + } + + // Translate font to screenbuffer + for (i = 0; i < Font.FontHeight; i++) + { + b = Font.data[(ch - 32) * Font.FontHeight + i]; + for (j = 0; j < Font.FontWidth; j++) + { + if ((b << j) & 0x8000) + { + ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) color); + } + else + { + ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR)!color); + } + } + } + + // The current space is now taken + SSD1306.CurrentX += Font.FontWidth; + + // Return written char for validation + return ch; +} + +// +// Write full string to screenbuffer +// +char ssd1306_WriteString(char* str, FontDef Font, SSD1306_COLOR color) +{ + // Write until null-byte + while (*str) + { + if (ssd1306_WriteChar(*str, Font, color) != *str) + { + // Char could not be written + return *str; + } + + // Next char + str++; + } + + // Everything ok + return *str; +} + +// +// Set cursor position +// +void ssd1306_SetCursor(uint8_t x, uint8_t y) +{ + SSD1306.CurrentX = x; + SSD1306.CurrentY = y; +} \ No newline at end of file diff --git a/Software/DisplayBoard/Core/Src/stm32f0xx_hal_msp.c b/Software/DisplayBoard/Core/Src/stm32f0xx_hal_msp.c new file mode 100644 index 0000000..8ad74e8 --- /dev/null +++ b/Software/DisplayBoard/Core/Src/stm32f0xx_hal_msp.c @@ -0,0 +1,474 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : stm32f0xx_hal_msp.c + * Description : This file provides code for the MSP Initialization + * and de-Initialization codes. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ +extern DMA_HandleTypeDef hdma_i2c1_tx; + +extern DMA_HandleTypeDef hdma_usart1_rx; + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN Define */ + +/* USER CODE END Define */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN Macro */ + +/* USER CODE END Macro */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* External functions --------------------------------------------------------*/ +/* USER CODE BEGIN ExternalFunctions */ + +/* USER CODE END ExternalFunctions */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ +/** + * Initializes the Global MSP. + */ +void HAL_MspInit(void) +{ + /* USER CODE BEGIN MspInit 0 */ + + /* USER CODE END MspInit 0 */ + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + /* System interrupt init*/ + + /* USER CODE BEGIN MspInit 1 */ + + /* USER CODE END MspInit 1 */ +} + +/** +* @brief ADC MSP Initialization +* This function configures the hardware resources used in this example +* @param hadc: ADC handle pointer +* @retval None +*/ +void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(hadc->Instance==ADC1) + { + /* USER CODE BEGIN ADC1_MspInit 0 */ + + /* USER CODE END ADC1_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_ADC1_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**ADC GPIO Configuration + PA3 ------> ADC_IN3 + PA5 ------> ADC_IN5 + */ + GPIO_InitStruct.Pin = FUEL_Pin|U_BATT_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USER CODE BEGIN ADC1_MspInit 1 */ + + /* USER CODE END ADC1_MspInit 1 */ + } + +} + +/** +* @brief ADC MSP De-Initialization +* This function freeze the hardware resources used in this example +* @param hadc: ADC handle pointer +* @retval None +*/ +void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) +{ + if(hadc->Instance==ADC1) + { + /* USER CODE BEGIN ADC1_MspDeInit 0 */ + + /* USER CODE END ADC1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_ADC1_CLK_DISABLE(); + + /**ADC GPIO Configuration + PA3 ------> ADC_IN3 + PA5 ------> ADC_IN5 + */ + HAL_GPIO_DeInit(GPIOA, FUEL_Pin|U_BATT_Pin); + + /* USER CODE BEGIN ADC1_MspDeInit 1 */ + + /* USER CODE END ADC1_MspDeInit 1 */ + } + +} + +/** +* @brief I2C MSP Initialization +* This function configures the hardware resources used in this example +* @param hi2c: I2C handle pointer +* @retval None +*/ +void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(hi2c->Instance==I2C1) + { + /* USER CODE BEGIN I2C1_MspInit 0 */ + + /* USER CODE END I2C1_MspInit 0 */ + + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**I2C1 GPIO Configuration + PB6 ------> I2C1_SCL + PB7 ------> I2C1_SDA + */ + GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF1_I2C1; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_I2C1_CLK_ENABLE(); + + /* I2C1 DMA Init */ + /* I2C1_TX Init */ + hdma_i2c1_tx.Instance = DMA1_Channel2; + hdma_i2c1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_i2c1_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_i2c1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_i2c1_tx.Init.Mode = DMA_NORMAL; + hdma_i2c1_tx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_i2c1_tx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(hi2c,hdmatx,hdma_i2c1_tx); + + /* I2C1 interrupt Init */ + HAL_NVIC_SetPriority(I2C1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(I2C1_IRQn); + /* USER CODE BEGIN I2C1_MspInit 1 */ + + /* USER CODE END I2C1_MspInit 1 */ + } + +} + +/** +* @brief I2C MSP De-Initialization +* This function freeze the hardware resources used in this example +* @param hi2c: I2C handle pointer +* @retval None +*/ +void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) +{ + if(hi2c->Instance==I2C1) + { + /* USER CODE BEGIN I2C1_MspDeInit 0 */ + + /* USER CODE END I2C1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_I2C1_CLK_DISABLE(); + + /**I2C1 GPIO Configuration + PB6 ------> I2C1_SCL + PB7 ------> I2C1_SDA + */ + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6); + + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7); + + /* I2C1 DMA DeInit */ + HAL_DMA_DeInit(hi2c->hdmatx); + + /* I2C1 interrupt DeInit */ + HAL_NVIC_DisableIRQ(I2C1_IRQn); + /* USER CODE BEGIN I2C1_MspDeInit 1 */ + + /* USER CODE END I2C1_MspDeInit 1 */ + } + +} + +/** +* @brief TIM_Base MSP Initialization +* This function configures the hardware resources used in this example +* @param htim_base: TIM_Base handle pointer +* @retval None +*/ +void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(htim_base->Instance==TIM3) + { + /* USER CODE BEGIN TIM3_MspInit 0 */ + + /* USER CODE END TIM3_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_TIM3_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**TIM3 GPIO Configuration + PA6 ------> TIM3_CH1 + */ + GPIO_InitStruct.Pin = RPM_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF1_TIM3; + HAL_GPIO_Init(RPM_GPIO_Port, &GPIO_InitStruct); + + /* TIM3 interrupt Init */ + HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TIM3_IRQn); + /* USER CODE BEGIN TIM3_MspInit 1 */ + + /* USER CODE END TIM3_MspInit 1 */ + } + else if(htim_base->Instance==TIM6) + { + /* USER CODE BEGIN TIM6_MspInit 0 */ + + /* USER CODE END TIM6_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_TIM6_CLK_ENABLE(); + /* TIM6 interrupt Init */ + HAL_NVIC_SetPriority(TIM6_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TIM6_IRQn); + /* USER CODE BEGIN TIM6_MspInit 1 */ + + /* USER CODE END TIM6_MspInit 1 */ + } + else if(htim_base->Instance==TIM14) + { + /* USER CODE BEGIN TIM14_MspInit 0 */ + + /* USER CODE END TIM14_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_TIM14_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**TIM14 GPIO Configuration + PA4 ------> TIM14_CH1 + */ + GPIO_InitStruct.Pin = SPEED_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF4_TIM14; + HAL_GPIO_Init(SPEED_GPIO_Port, &GPIO_InitStruct); + + /* TIM14 interrupt Init */ + HAL_NVIC_SetPriority(TIM14_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TIM14_IRQn); + /* USER CODE BEGIN TIM14_MspInit 1 */ + + /* USER CODE END TIM14_MspInit 1 */ + } + +} + +/** +* @brief TIM_Base MSP De-Initialization +* This function freeze the hardware resources used in this example +* @param htim_base: TIM_Base handle pointer +* @retval None +*/ +void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) +{ + if(htim_base->Instance==TIM3) + { + /* USER CODE BEGIN TIM3_MspDeInit 0 */ + + /* USER CODE END TIM3_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM3_CLK_DISABLE(); + + /**TIM3 GPIO Configuration + PA6 ------> TIM3_CH1 + */ + HAL_GPIO_DeInit(RPM_GPIO_Port, RPM_Pin); + + /* TIM3 interrupt DeInit */ + HAL_NVIC_DisableIRQ(TIM3_IRQn); + /* USER CODE BEGIN TIM3_MspDeInit 1 */ + + /* USER CODE END TIM3_MspDeInit 1 */ + } + else if(htim_base->Instance==TIM6) + { + /* USER CODE BEGIN TIM6_MspDeInit 0 */ + + /* USER CODE END TIM6_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM6_CLK_DISABLE(); + + /* TIM6 interrupt DeInit */ + HAL_NVIC_DisableIRQ(TIM6_IRQn); + /* USER CODE BEGIN TIM6_MspDeInit 1 */ + + /* USER CODE END TIM6_MspDeInit 1 */ + } + else if(htim_base->Instance==TIM14) + { + /* USER CODE BEGIN TIM14_MspDeInit 0 */ + + /* USER CODE END TIM14_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM14_CLK_DISABLE(); + + /**TIM14 GPIO Configuration + PA4 ------> TIM14_CH1 + */ + HAL_GPIO_DeInit(SPEED_GPIO_Port, SPEED_Pin); + + /* TIM14 interrupt DeInit */ + HAL_NVIC_DisableIRQ(TIM14_IRQn); + /* USER CODE BEGIN TIM14_MspDeInit 1 */ + + /* USER CODE END TIM14_MspDeInit 1 */ + } + +} + +/** +* @brief UART MSP Initialization +* This function configures the hardware resources used in this example +* @param huart: UART handle pointer +* @retval None +*/ +void HAL_UART_MspInit(UART_HandleTypeDef* huart) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(huart->Instance==USART1) + { + /* USER CODE BEGIN USART1_MspInit 0 */ + + /* USER CODE END USART1_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_USART1_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USART1 GPIO Configuration + PA9 ------> USART1_TX + PA10 ------> USART1_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF1_USART1; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USART1 DMA Init */ + /* USART1_RX Init */ + hdma_usart1_rx.Instance = DMA1_Channel3; + hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_usart1_rx.Init.Mode = DMA_CIRCULAR; + hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx); + + /* USART1 interrupt Init */ + HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USART1_IRQn); + /* USER CODE BEGIN USART1_MspInit 1 */ + + /* USER CODE END USART1_MspInit 1 */ + } + +} + +/** +* @brief UART MSP De-Initialization +* This function freeze the hardware resources used in this example +* @param huart: UART handle pointer +* @retval None +*/ +void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) +{ + if(huart->Instance==USART1) + { + /* USER CODE BEGIN USART1_MspDeInit 0 */ + + /* USER CODE END USART1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART1_CLK_DISABLE(); + + /**USART1 GPIO Configuration + PA9 ------> USART1_TX + PA10 ------> USART1_RX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); + + /* USART1 DMA DeInit */ + HAL_DMA_DeInit(huart->hdmarx); + + /* USART1 interrupt DeInit */ + HAL_NVIC_DisableIRQ(USART1_IRQn); + /* USER CODE BEGIN USART1_MspDeInit 1 */ + + /* USER CODE END USART1_MspDeInit 1 */ + } + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Software/DisplayBoard/Core/Src/stm32f0xx_it.c b/Software/DisplayBoard/Core/Src/stm32f0xx_it.c new file mode 100644 index 0000000..ce41f1d --- /dev/null +++ b/Software/DisplayBoard/Core/Src/stm32f0xx_it.c @@ -0,0 +1,268 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f0xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "stm32f0xx_it.h" +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* External variables --------------------------------------------------------*/ +extern DMA_HandleTypeDef hdma_i2c1_tx; +extern I2C_HandleTypeDef hi2c1; +extern TIM_HandleTypeDef htim3; +extern TIM_HandleTypeDef htim6; +extern TIM_HandleTypeDef htim14; +extern DMA_HandleTypeDef hdma_usart1_rx; +extern UART_HandleTypeDef huart1; +/* USER CODE BEGIN EV */ + +/* USER CODE END EV */ + +/******************************************************************************/ +/* Cortex-M0 Processor Interruption and Exception Handlers */ +/******************************************************************************/ +/** + * @brief This function handles Non maskable interrupt. + */ +void NMI_Handler(void) +{ + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ + + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ + + /* USER CODE END NonMaskableInt_IRQn 1 */ +} + +/** + * @brief This function handles Hard fault interrupt. + */ +void HardFault_Handler(void) +{ + /* USER CODE BEGIN HardFault_IRQn 0 */ + + /* USER CODE END HardFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_HardFault_IRQn 0 */ + /* USER CODE END W1_HardFault_IRQn 0 */ + } +} + +/** + * @brief This function handles System service call via SWI instruction. + */ +void SVC_Handler(void) +{ + /* USER CODE BEGIN SVC_IRQn 0 */ + + /* USER CODE END SVC_IRQn 0 */ + /* USER CODE BEGIN SVC_IRQn 1 */ + + /* USER CODE END SVC_IRQn 1 */ +} + +/** + * @brief This function handles Pendable request for system service. + */ +void PendSV_Handler(void) +{ + /* USER CODE BEGIN PendSV_IRQn 0 */ + + /* USER CODE END PendSV_IRQn 0 */ + /* USER CODE BEGIN PendSV_IRQn 1 */ + + /* USER CODE END PendSV_IRQn 1 */ +} + +/** + * @brief This function handles System tick timer. + */ +void SysTick_Handler(void) +{ + /* USER CODE BEGIN SysTick_IRQn 0 */ + + /* USER CODE END SysTick_IRQn 0 */ + HAL_IncTick(); + /* USER CODE BEGIN SysTick_IRQn 1 */ + + /* USER CODE END SysTick_IRQn 1 */ +} + +/******************************************************************************/ +/* STM32F0xx Peripheral Interrupt Handlers */ +/* Add here the Interrupt Handlers for the used peripherals. */ +/* For the available peripheral interrupt handler names, */ +/* please refer to the startup file (startup_stm32f0xx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles EXTI line 0 and 1 interrupts. + */ +void EXTI0_1_IRQHandler(void) +{ + /* USER CODE BEGIN EXTI0_1_IRQn 0 */ + + /* USER CODE END EXTI0_1_IRQn 0 */ + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); + /* USER CODE BEGIN EXTI0_1_IRQn 1 */ + + /* USER CODE END EXTI0_1_IRQn 1 */ +} + +/** + * @brief This function handles EXTI line 2 and 3 interrupts. + */ +void EXTI2_3_IRQHandler(void) +{ + /* USER CODE BEGIN EXTI2_3_IRQn 0 */ + + /* USER CODE END EXTI2_3_IRQn 0 */ + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); + /* USER CODE BEGIN EXTI2_3_IRQn 1 */ + + /* USER CODE END EXTI2_3_IRQn 1 */ +} + +/** + * @brief This function handles DMA1 channel 2 and 3 interrupts. + */ +void DMA1_Channel2_3_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel2_3_IRQn 0 */ + + /* USER CODE END DMA1_Channel2_3_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_i2c1_tx); + HAL_DMA_IRQHandler(&hdma_usart1_rx); + /* USER CODE BEGIN DMA1_Channel2_3_IRQn 1 */ + + /* USER CODE END DMA1_Channel2_3_IRQn 1 */ +} + +/** + * @brief This function handles TIM3 global interrupt. + */ +void TIM3_IRQHandler(void) +{ + /* USER CODE BEGIN TIM3_IRQn 0 */ + + /* USER CODE END TIM3_IRQn 0 */ + HAL_TIM_IRQHandler(&htim3); + /* USER CODE BEGIN TIM3_IRQn 1 */ + + /* USER CODE END TIM3_IRQn 1 */ +} + +/** + * @brief This function handles TIM6 global interrupt. + */ +void TIM6_IRQHandler(void) +{ + /* USER CODE BEGIN TIM6_IRQn 0 */ + + /* USER CODE END TIM6_IRQn 0 */ + HAL_TIM_IRQHandler(&htim6); + /* USER CODE BEGIN TIM6_IRQn 1 */ + + /* USER CODE END TIM6_IRQn 1 */ +} + +/** + * @brief This function handles TIM14 global interrupt. + */ +void TIM14_IRQHandler(void) +{ + /* USER CODE BEGIN TIM14_IRQn 0 */ + + /* USER CODE END TIM14_IRQn 0 */ + HAL_TIM_IRQHandler(&htim14); + /* USER CODE BEGIN TIM14_IRQn 1 */ + + /* USER CODE END TIM14_IRQn 1 */ +} + +/** + * @brief This function handles I2C1 global interrupt. + */ +void I2C1_IRQHandler(void) +{ + /* USER CODE BEGIN I2C1_IRQn 0 */ + + /* USER CODE END I2C1_IRQn 0 */ + if (hi2c1.Instance->ISR & (I2C_FLAG_BERR | I2C_FLAG_ARLO | I2C_FLAG_OVR)) { + HAL_I2C_ER_IRQHandler(&hi2c1); + } else { + HAL_I2C_EV_IRQHandler(&hi2c1); + } + /* USER CODE BEGIN I2C1_IRQn 1 */ + + /* USER CODE END I2C1_IRQn 1 */ +} + +/** + * @brief This function handles USART1 global interrupt. + */ +void USART1_IRQHandler(void) +{ + /* USER CODE BEGIN USART1_IRQn 0 */ + + /* USER CODE END USART1_IRQn 0 */ + HAL_UART_IRQHandler(&huart1); + /* USER CODE BEGIN USART1_IRQn 1 */ + + /* USER CODE END USART1_IRQn 1 */ +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Software/DisplayBoard/Core/Src/syscalls.c b/Software/DisplayBoard/Core/Src/syscalls.c new file mode 100644 index 0000000..4ec9584 --- /dev/null +++ b/Software/DisplayBoard/Core/Src/syscalls.c @@ -0,0 +1,159 @@ +/** + ****************************************************************************** + * @file syscalls.c + * @author Auto-generated by STM32CubeIDE + * @brief STM32CubeIDE Minimal System calls file + * + * For more information about which c-functions + * need which of these lowlevel functions + * please consult the Newlib libc-manual + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Variables */ +//#undef errno +extern int errno; +extern int __io_putchar(int ch) __attribute__((weak)); +extern int __io_getchar(void) __attribute__((weak)); + +register char * stack_ptr asm("sp"); + +char *__env[1] = { 0 }; +char **environ = __env; + + +/* Functions */ +void initialise_monitor_handles() +{ +} + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + errno = EINVAL; + return -1; +} + +void _exit (int status) +{ + _kill(status, -1); + while (1) {} /* Make sure we hang here */ +} + +__attribute__((weak)) int _read(int file, char *ptr, int len) +{ + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + *ptr++ = __io_getchar(); + } + +return len; +} + +__attribute__((weak)) int _write(int file, char *ptr, int len) +{ + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + __io_putchar(*ptr++); + } + return len; +} + +int _close(int file) +{ + return -1; +} + + +int _fstat(int file, struct stat *st) +{ + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + return 0; +} + +int _open(char *path, int flags, ...) +{ + /* Pretend like we always fail */ + return -1; +} + +int _wait(int *status) +{ + errno = ECHILD; + return -1; +} + +int _unlink(char *name) +{ + errno = ENOENT; + return -1; +} + +int _times(struct tms *buf) +{ + return -1; +} + +int _stat(char *file, struct stat *st) +{ + st->st_mode = S_IFCHR; + return 0; +} + +int _link(char *old, char *new) +{ + errno = EMLINK; + return -1; +} + +int _fork(void) +{ + errno = EAGAIN; + return -1; +} + +int _execve(char *name, char **argv, char **env) +{ + errno = ENOMEM; + return -1; +} diff --git a/Software/DisplayBoard/Core/Src/sysmem.c b/Software/DisplayBoard/Core/Src/sysmem.c new file mode 100644 index 0000000..23180b6 --- /dev/null +++ b/Software/DisplayBoard/Core/Src/sysmem.c @@ -0,0 +1,80 @@ +/** + ****************************************************************************** + * @file sysmem.c + * @author Generated by STM32CubeIDE + * @brief STM32CubeIDE System Memory calls file + * + * For more information about which C functions + * need which of these lowlevel functions + * please consult the newlib libc manual + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include + +/** + * Pointer to the current high watermark of the heap usage + */ +static uint8_t *__sbrk_heap_end = NULL; + +/** + * @brief _sbrk() allocates memory to the newlib heap and is used by malloc + * and others from the C library + * + * @verbatim + * ############################################################################ + * # .data # .bss # newlib heap # MSP stack # + * # # # # Reserved by _Min_Stack_Size # + * ############################################################################ + * ^-- RAM start ^-- _end _estack, RAM end --^ + * @endverbatim + * + * This implementation starts allocating at the '_end' linker symbol + * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack + * The implementation considers '_estack' linker symbol to be RAM end + * NOTE: If the MSP stack, at any point during execution, grows larger than the + * reserved size, please increase the '_Min_Stack_Size'. + * + * @param incr Memory size + * @return Pointer to allocated memory + */ +void *_sbrk(ptrdiff_t incr) +{ + extern uint8_t _end; /* Symbol defined in the linker script */ + extern uint8_t _estack; /* Symbol defined in the linker script */ + extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ + const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; + const uint8_t *max_heap = (uint8_t *)stack_limit; + uint8_t *prev_heap_end; + + /* Initalize heap end at first call */ + if (NULL == __sbrk_heap_end) + { + __sbrk_heap_end = &_end; + } + + /* Protect heap from growing into the reserved MSP stack */ + if (__sbrk_heap_end + incr > max_heap) + { + errno = ENOMEM; + return (void *)-1; + } + + prev_heap_end = __sbrk_heap_end; + __sbrk_heap_end += incr; + + return (void *)prev_heap_end; +} diff --git a/Software/DisplayBoard/Core/Src/system_stm32f0xx.c b/Software/DisplayBoard/Core/Src/system_stm32f0xx.c new file mode 100644 index 0000000..4761a85 --- /dev/null +++ b/Software/DisplayBoard/Core/Src/system_stm32f0xx.c @@ -0,0 +1,247 @@ +/** + ****************************************************************************** + * @file system_stm32f0xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M0 Device Peripheral Access Layer System Source File. + * + * 1. This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f0xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2016 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f0xx_system + * @{ + */ + +/** @addtogroup STM32F0xx_System_Private_Includes + * @{ + */ + +#include "stm32f0xx.h" + +/** + * @} + */ + +/** @addtogroup STM32F0xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F0xx_System_Private_Defines + * @{ + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000) /*!< Default value of the External oscillator in Hz. + This value can be provided and adapted by the user application. */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)8000000) /*!< Default value of the Internal oscillator in Hz. + This value can be provided and adapted by the user application. */ +#endif /* HSI_VALUE */ + +#if !defined (HSI48_VALUE) +#define HSI48_VALUE ((uint32_t)48000000) /*!< Default value of the HSI48 Internal oscillator in Hz. + This value can be provided and adapted by the user application. */ +#endif /* HSI48_VALUE */ +/** + * @} + */ + +/** @addtogroup STM32F0xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F0xx_System_Private_Variables + * @{ + */ + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ +uint32_t SystemCoreClock = 8000000; + +const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + +/** + * @} + */ + +/** @addtogroup STM32F0xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F0xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * @param None + * @retval None + */ +void SystemInit(void) +{ + /* NOTE :SystemInit(): This function is called at startup just after reset and + before branch to main program. This call is made inside + the "startup_stm32f0xx.s" file. + User can setups the default system clock (System clock source, PLL Multiplier + and Divider factors, AHB/APBx prescalers and Flash settings). + */ +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f0xx_hal_conf.h file (default value + * 8 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f0xx_hal_conf.h file (its value + * depends on the application requirements), user has to ensure that HSE_VALUE + * is same as the real frequency of the crystal used. Otherwise, this function + * may have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate (void) +{ + uint32_t tmp = 0, pllmull = 0, pllsource = 0, predivfactor = 0; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case RCC_CFGR_SWS_HSI: /* HSI used as system clock */ + SystemCoreClock = HSI_VALUE; + break; + case RCC_CFGR_SWS_HSE: /* HSE used as system clock */ + SystemCoreClock = HSE_VALUE; + break; + case RCC_CFGR_SWS_PLL: /* PLL used as system clock */ + /* Get PLL clock source and multiplication factor ----------------------*/ + pllmull = RCC->CFGR & RCC_CFGR_PLLMUL; + pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; + pllmull = ( pllmull >> 18) + 2; + predivfactor = (RCC->CFGR2 & RCC_CFGR2_PREDIV) + 1; + + if (pllsource == RCC_CFGR_PLLSRC_HSE_PREDIV) + { + /* HSE used as PLL clock source : SystemCoreClock = HSE/PREDIV * PLLMUL */ + SystemCoreClock = (HSE_VALUE/predivfactor) * pllmull; + } +#if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F072xB) || defined(STM32F078xx) || defined(STM32F091xC) || defined(STM32F098xx) + else if (pllsource == RCC_CFGR_PLLSRC_HSI48_PREDIV) + { + /* HSI48 used as PLL clock source : SystemCoreClock = HSI48/PREDIV * PLLMUL */ + SystemCoreClock = (HSI48_VALUE/predivfactor) * pllmull; + } +#endif /* STM32F042x6 || STM32F048xx || STM32F072xB || STM32F078xx || STM32F091xC || STM32F098xx */ + else + { +#if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F070x6) \ + || defined(STM32F078xx) || defined(STM32F071xB) || defined(STM32F072xB) \ + || defined(STM32F070xB) || defined(STM32F091xC) || defined(STM32F098xx) || defined(STM32F030xC) + /* HSI used as PLL clock source : SystemCoreClock = HSI/PREDIV * PLLMUL */ + SystemCoreClock = (HSI_VALUE/predivfactor) * pllmull; +#else + /* HSI used as PLL clock source : SystemCoreClock = HSI/2 * PLLMUL */ + SystemCoreClock = (HSI_VALUE >> 1) * pllmull; +#endif /* STM32F042x6 || STM32F048xx || STM32F070x6 || + STM32F071xB || STM32F072xB || STM32F078xx || STM32F070xB || + STM32F091xC || STM32F098xx || STM32F030xC */ + } + break; + default: /* HSI used as system clock */ + SystemCoreClock = HSI_VALUE; + break; + } + /* Compute HCLK clock frequency ----------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Software/DisplayBoard/Core/Startup/startup_stm32f030c8tx.s b/Software/DisplayBoard/Core/Startup/startup_stm32f030c8tx.s new file mode 100644 index 0000000..ff3496e --- /dev/null +++ b/Software/DisplayBoard/Core/Startup/startup_stm32f030c8tx.s @@ -0,0 +1,273 @@ +/** + ****************************************************************************** + * @file startup_stm32f030x8.s + * @author MCD Application Team + * @brief STM32F030x8 devices vector table for GCC toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M0 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2016 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m0 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r0, =_estack + mov sp, r0 /* set stack pointer */ + +/* Copy the data segment initializers from flash to SRAM */ + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + movs r3, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyDataInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit + +/* Zero fill the bss segment. */ + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b LoopFillZerobss + +FillZerobss: + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + cmp r2, r4 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + +LoopForever: + b LoopForever + + +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M0. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word 0 + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler /* Window WatchDog */ + .word 0 /* Reserved */ + .word RTC_IRQHandler /* RTC through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */ + .word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */ + .word EXTI4_15_IRQHandler /* EXTI Line 4 to 15 */ + .word 0 /* Reserved */ + .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ + .word DMA1_Channel2_3_IRQHandler /* DMA1 Channel 2 and Channel 3 */ + .word DMA1_Channel4_5_IRQHandler /* DMA1 Channel 4 and Channel 5 */ + .word ADC1_IRQHandler /* ADC1 */ + .word TIM1_BRK_UP_TRG_COM_IRQHandler /* TIM1 Break, Update, Trigger and Commutation */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word 0 /* Reserved */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM6_IRQHandler /* TIM6 */ + .word 0 /* Reserved */ + .word TIM14_IRQHandler /* TIM14 */ + .word TIM15_IRQHandler /* TIM15 */ + .word TIM16_IRQHandler /* TIM16 */ + .word TIM17_IRQHandler /* TIM17 */ + .word I2C1_IRQHandler /* I2C1 */ + .word I2C2_IRQHandler /* I2C2 */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_1_IRQHandler + .thumb_set EXTI0_1_IRQHandler,Default_Handler + + .weak EXTI2_3_IRQHandler + .thumb_set EXTI2_3_IRQHandler,Default_Handler + + .weak EXTI4_15_IRQHandler + .thumb_set EXTI4_15_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_3_IRQHandler + .thumb_set DMA1_Channel2_3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_5_IRQHandler + .thumb_set DMA1_Channel4_5_IRQHandler,Default_Handler + + .weak ADC1_IRQHandler + .thumb_set ADC1_IRQHandler,Default_Handler + + .weak TIM1_BRK_UP_TRG_COM_IRQHandler + .thumb_set TIM1_BRK_UP_TRG_COM_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM6_IRQHandler + .thumb_set TIM6_IRQHandler,Default_Handler + + .weak TIM14_IRQHandler + .thumb_set TIM14_IRQHandler,Default_Handler + + .weak TIM15_IRQHandler + .thumb_set TIM15_IRQHandler,Default_Handler + + .weak TIM16_IRQHandler + .thumb_set TIM16_IRQHandler,Default_Handler + + .weak TIM17_IRQHandler + .thumb_set TIM17_IRQHandler,Default_Handler + + .weak I2C1_IRQHandler + .thumb_set I2C1_IRQHandler,Default_Handler + + .weak I2C2_IRQHandler + .thumb_set I2C2_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/Software/DisplayBoard/DisplayBoard.ioc b/Software/DisplayBoard/DisplayBoard.ioc new file mode 100644 index 0000000..163e8df --- /dev/null +++ b/Software/DisplayBoard/DisplayBoard.ioc @@ -0,0 +1,202 @@ +#MicroXplorer Configuration settings - do not modify +ADC.IPParameters=SamplingTime +ADC.SamplingTime=ADC_SAMPLETIME_239CYCLES_5 +Dma.I2C1_TX.0.Direction=DMA_MEMORY_TO_PERIPH +Dma.I2C1_TX.0.Instance=DMA1_Channel2 +Dma.I2C1_TX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.I2C1_TX.0.MemInc=DMA_MINC_ENABLE +Dma.I2C1_TX.0.Mode=DMA_NORMAL +Dma.I2C1_TX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.I2C1_TX.0.PeriphInc=DMA_PINC_DISABLE +Dma.I2C1_TX.0.Priority=DMA_PRIORITY_LOW +Dma.I2C1_TX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.Request0=I2C1_TX +Dma.Request1=USART1_RX +Dma.RequestsNb=2 +Dma.USART1_RX.1.Direction=DMA_PERIPH_TO_MEMORY +Dma.USART1_RX.1.Instance=DMA1_Channel3 +Dma.USART1_RX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.USART1_RX.1.MemInc=DMA_MINC_ENABLE +Dma.USART1_RX.1.Mode=DMA_CIRCULAR +Dma.USART1_RX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.USART1_RX.1.PeriphInc=DMA_PINC_DISABLE +Dma.USART1_RX.1.Priority=DMA_PRIORITY_LOW +Dma.USART1_RX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +File.Version=6 +GPIO.groupedBy=Group By Peripherals +I2C1.I2C_Speed_Mode=I2C_Fast +I2C1.IPParameters=I2C_Speed_Mode,Timing +I2C1.Timing=0x0000020B +KeepUserPlacement=false +Mcu.Family=STM32F0 +Mcu.IP0=ADC +Mcu.IP1=DMA +Mcu.IP2=I2C1 +Mcu.IP3=NVIC +Mcu.IP4=RCC +Mcu.IP5=SYS +Mcu.IP6=TIM3 +Mcu.IP7=TIM6 +Mcu.IP8=TIM14 +Mcu.IP9=USART1 +Mcu.IPNb=10 +Mcu.Name=STM32F030C8Tx +Mcu.Package=LQFP48 +Mcu.Pin0=PA1 +Mcu.Pin1=PA2 +Mcu.Pin10=PA14 +Mcu.Pin11=PB6 +Mcu.Pin12=PB7 +Mcu.Pin13=VP_SYS_VS_Systick +Mcu.Pin14=VP_TIM3_VS_ClockSourceINT +Mcu.Pin15=VP_TIM6_VS_ClockSourceINT +Mcu.Pin16=VP_TIM14_VS_ClockSourceINT +Mcu.Pin2=PA3 +Mcu.Pin3=PA4 +Mcu.Pin4=PA5 +Mcu.Pin5=PA6 +Mcu.Pin6=PB0 +Mcu.Pin7=PA9 +Mcu.Pin8=PA10 +Mcu.Pin9=PA13 +Mcu.PinsNb=17 +Mcu.ThirdPartyNb=0 +Mcu.UserConstants= +Mcu.UserName=STM32F030C8Tx +MxCube.Version=6.1.1 +MxDb.Version=DB.6.0.10 +NVIC.DMA1_Channel2_3_IRQn=true\:0\:0\:false\:false\:true\:false\:true +NVIC.EXTI0_1_IRQn=true\:0\:0\:false\:false\:true\:true\:true +NVIC.EXTI2_3_IRQn=true\:0\:0\:false\:false\:true\:true\:true +NVIC.ForceEnableDMAVector=true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.I2C1_IRQn=true\:0\:0\:false\:false\:true\:true\:true +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.SVC_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true +NVIC.TIM14_IRQn=true\:0\:0\:false\:false\:true\:true\:true +NVIC.TIM3_IRQn=true\:0\:0\:false\:false\:true\:true\:true +NVIC.TIM6_IRQn=true\:0\:0\:false\:false\:true\:true\:true +NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true\:true +PA1.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI +PA1.GPIO_Label=GPInput1 +PA1.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING +PA1.GPIO_PuPd=GPIO_PULLUP +PA1.Locked=true +PA1.Signal=GPXTI1 +PA10.Mode=Asynchronous +PA10.Signal=USART1_RX +PA13.Mode=Serial_Wire +PA13.Signal=SYS_SWDIO +PA14.Mode=Serial_Wire +PA14.Signal=SYS_SWCLK +PA2.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI +PA2.GPIO_Label=GPInput2 +PA2.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING +PA2.GPIO_PuPd=GPIO_PULLUP +PA2.Locked=true +PA2.Signal=GPXTI2 +PA3.GPIOParameters=GPIO_Label +PA3.GPIO_Label=FUEL +PA3.Locked=true +PA3.Mode=IN3 +PA3.Signal=ADC_IN3 +PA4.GPIOParameters=GPIO_Label +PA4.GPIO_Label=SPEED +PA4.Locked=true +PA4.Signal=S_TIM14_CH1 +PA5.GPIOParameters=GPIO_Label +PA5.GPIO_Label=U_BATT +PA5.Locked=true +PA5.Mode=IN5 +PA5.Signal=ADC_IN5 +PA6.GPIOParameters=GPIO_Label +PA6.GPIO_Label=RPM +PA6.Locked=true +PA6.Signal=S_TIM3_CH1 +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PB0.GPIOParameters=GPIO_Label +PB0.GPIO_Label=LED +PB0.Locked=true +PB0.Signal=GPIO_Output +PB6.Mode=I2C +PB6.Signal=I2C1_SCL +PB7.Mode=I2C +PB7.Signal=I2C1_SDA +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerOptimize=6 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=false +ProjectManager.CustomerFirmwarePackage= +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32F030C8Tx +ProjectManager.FirmwarePackage=STM32Cube FW_F0 V1.11.2 +ProjectManager.FreePins=false +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x200 +ProjectManager.KeepUserCode=true +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=1 +ProjectManager.MainLocation=Core/Src +ProjectManager.NoMain=false +ProjectManager.PreviousToolchain=STM32CubeIDE +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=DisplayBoard.ioc +ProjectManager.ProjectName=DisplayBoard +ProjectManager.RegisterCallBack= +ProjectManager.StackSize=0x400 +ProjectManager.TargetToolchain=STM32CubeIDE +ProjectManager.ToolChainLocation= +ProjectManager.UnderRoot=true +ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-MX_DMA_Init-DMA-false-HAL-true,3-SystemClock_Config-RCC-false-HAL-false,4-MX_I2C1_Init-I2C1-false-HAL-true,5-MX_ADC_Init-ADC-false-HAL-true,6-MX_TIM3_Init-TIM3-false-HAL-true,7-MX_TIM14_Init-TIM14-false-HAL-true,8-MX_USART1_UART_Init-USART1-false-HAL-true +RCC.AHBFreq_Value=48000000 +RCC.APB1Freq_Value=48000000 +RCC.APB1TimFreq_Value=48000000 +RCC.FCLKCortexFreq_Value=48000000 +RCC.FamilyName=M +RCC.HCLKFreq_Value=48000000 +RCC.IPParameters=AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLMCOFreq_Value,PLLMUL,SYSCLKFreq_VALUE,SYSCLKSource,TimSysFreq_Value,USART1Freq_Value +RCC.MCOFreq_Value=48000000 +RCC.PLLCLKFreq_Value=48000000 +RCC.PLLMCOFreq_Value=24000000 +RCC.PLLMUL=RCC_PLL_MUL12 +RCC.SYSCLKFreq_VALUE=48000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.TimSysFreq_Value=48000000 +RCC.USART1Freq_Value=48000000 +SH.GPXTI1.0=GPIO_EXTI1 +SH.GPXTI1.ConfNb=1 +SH.GPXTI2.0=GPIO_EXTI2 +SH.GPXTI2.ConfNb=1 +SH.S_TIM14_CH1.0=TIM14_CH1,Input_Capture1_from_TI1 +SH.S_TIM14_CH1.ConfNb=1 +SH.S_TIM3_CH1.0=TIM3_CH1,Input_Capture1_from_TI1 +SH.S_TIM3_CH1.ConfNb=1 +TIM14.Channel=TIM_CHANNEL_1 +TIM14.IPParameters=Channel,Prescaler,Period +TIM14.Period=10000 +TIM14.Prescaler=4799 +TIM3.Channel-Input_Capture1_from_TI1=TIM_CHANNEL_1 +TIM3.IPParameters=Channel-Input_Capture1_from_TI1,Prescaler,Period +TIM3.Period=10000 +TIM3.Prescaler=4799 +TIM6.IPParameters=Prescaler,Period +TIM6.Period=1000 +TIM6.Prescaler=47999 +USART1.IPParameters=VirtualMode-Asynchronous +USART1.VirtualMode-Asynchronous=VM_ASYNC +VP_SYS_VS_Systick.Mode=SysTick +VP_SYS_VS_Systick.Signal=SYS_VS_Systick +VP_TIM14_VS_ClockSourceINT.Mode=Enable_Timer +VP_TIM14_VS_ClockSourceINT.Signal=TIM14_VS_ClockSourceINT +VP_TIM3_VS_ClockSourceINT.Mode=Internal +VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT +VP_TIM6_VS_ClockSourceINT.Mode=Enable_Timer +VP_TIM6_VS_ClockSourceINT.Signal=TIM6_VS_ClockSourceINT +board=custom +isbadioc=false