├── Doc ├── 320_240_demo.jpg ├── OLED_12864_SSD1306.pdf ├── OLED_demo.jpg ├── image_demo.jpg ├── mcu_pinout_image.gif ├── pin_out.jpg └── video_demo.jpg ├── README.md ├── mcu_prj ├── OLED_imageShow.7z ├── OLED_imageShow.bin ├── OLED_imageShow │ ├── Inc │ │ ├── dma.h │ │ ├── gpio.h │ │ ├── i2c.h │ │ ├── main.h │ │ ├── stm32f1xx_hal_conf.h │ │ ├── stm32f1xx_it.h │ │ └── usart.h │ ├── Src │ │ ├── dma.c │ │ ├── gpio.c │ │ ├── i2c.c │ │ ├── main.c │ │ ├── stm32f1xx_hal_msp.c │ │ ├── stm32f1xx_it.c │ │ ├── syscalls.c │ │ ├── sysmem.c │ │ ├── system_stm32f1xx.c │ │ └── usart.c │ ├── readme.txt │ └── ssd1306 │ │ ├── ssd1306.c │ │ ├── ssd1306.h │ │ ├── ssd1306_fonts.c │ │ ├── ssd1306_fonts.h │ │ ├── ssd1306_tests.c │ │ └── ssd1306_tests.h └── README.md └── python_gui ├── UI ├── TextViewer.py ├── TextViewer.ui ├── basic_ui.py ├── basic_ui.ui ├── image_export_ui.py ├── image_export_ui.ui ├── imgeModeWindow.py ├── imgeModeWindow.ui ├── main_ui.py ├── main_ui.ui ├── screenSampleWindow.py └── screenSampleWindow.ui ├── common └── Singleton.py ├── image_processing ├── BWImageToBytes.py ├── C_dll_source_code │ ├── build.bat │ ├── image_processing.c │ └── image_processing.h ├── Qt2CV.py ├── dithering.dll ├── image_processing.dll ├── image_processing_x64.dll └── image_translate.py ├── images ├── 0.jpg ├── 1.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg ├── 5.png ├── 7.jpg ├── demo_icon.png └── robot.jpg ├── main.py ├── screen.py ├── serial_port.py ├── test ├── dither_bayer_metrix_generator.py ├── iconDesignAutoUpload.py ├── read_image.py ├── read_video.py ├── tft_320_240.py └── tft_320_240_video.py ├── tools ├── environment_setup.py └── get-pip.py ├── video └── bad_apple.mp4 └── window ├── imageMode_Window.py ├── main_Window.py ├── screenMode_Window.py ├── screenSample_Window.py └── videoMode_Window.py /Doc/320_240_demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/Doc/320_240_demo.jpg -------------------------------------------------------------------------------- /Doc/OLED_12864_SSD1306.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/Doc/OLED_12864_SSD1306.pdf -------------------------------------------------------------------------------- /Doc/OLED_demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/Doc/OLED_demo.jpg -------------------------------------------------------------------------------- /Doc/image_demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/Doc/image_demo.jpg -------------------------------------------------------------------------------- /Doc/mcu_pinout_image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/Doc/mcu_pinout_image.gif -------------------------------------------------------------------------------- /Doc/pin_out.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/Doc/pin_out.jpg -------------------------------------------------------------------------------- /Doc/video_demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/Doc/video_demo.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Demo 2 | ## Image Mode 3 | - GUI 4 | 5 | 6 | 7 | - OLED 128\*64 8 | 9 | 10 | 11 | - TFT 320\*240 12 | 13 | 14 | 15 | ## Video Mode & Screen Mode 16 | 17 | Please watch the [demo video](https://www.bilibili.com/video/BV1v7411A7sF/ "OLED GUI Demo | 上位机工具"). 18 | 19 | # How it works 20 | 21 | Please referance to [this article](https://zhuanlan.zhihu.com/p/113066072 "OLED ToolBox, bad apple上位机 - Chang An的文章 - 知乎 22 | "). 23 | 24 | # Hardware: 25 | - STM32F103CET6 Blue Pill 26 | - OLED_12864_SSD1306 with IIC interface, or you could port to other screen interfaces. 27 | - USB to UART converter 28 | - ST-Link Debuger, any tools could the download program to the MCU. 29 | 30 | # 硬件: 31 | - STM32F103CET6 Blue Pill 32 | - OLED_12864_SSD1306 IIC 接口,或者你能移植到其它屏幕或接口 33 | - USB-UART 转换接口 34 | - ST-Link 调试器,任何能够下载程序到MCU的均可 35 | 36 | # IDE: 37 | - MCU: CubeMX_IDE, or you can port my source code to your IDE. 38 | - Python IDE: PyCharm, not required if you know how to run python in a terminal. 39 | 40 | # 集成开发环境: 41 | - 单片机:CubeMX_IDE,或者你可以移植源代码到你使用的IDE 42 | - Python:PyCharm,并不是必须的,可以在命令行中运行程序 43 | 44 | # Python Modules: 45 | - python 3.x 46 | 47 | > I wrote an environment setup script in \python_gui\tools\environment_setup.py, 48 | which could help you install modules below, 49 | but you must first install python 3.x to run this script. 50 | 51 | > 我写了一个环境建立的脚本在:\python_gui\tools\environment_setup.py, 52 | 它可以帮助你安装下面的模块, 53 | 但是首先你得安装Python 3.x来运行这个脚本 54 | 55 | - pyserial 56 | - numpy 57 | - opencv-python 58 | - PyQt5 59 | - pywin32 60 | 61 | # How to Run: 62 | 0, Make sure you have all the required hardware and software. 63 | 1, Download the MCU program and connect USB2UART module, then restart MCU. 64 | 2, Run GUI on a Windows PC: 65 | 0, Open the folder: \python_gui 66 | 1, Open a terminal enter and run cmd: python main.py 67 | Or Run main.py in PyCharm IDE. 68 | 2, Scan the serial port and select the right one to connect to the MCU. 69 | 3, Do whatever you want... 70 | # 怎样运行: 71 | 0,确认你具备需要的硬件与软件 72 | 1,下载单片机程序并连接串口到单片机,然后复位单片机 73 | 2,在Window电脑上运行图形用户界面: 74 | 0,打开文件夹:\python_gui 75 | 1,打开中端输入并运行:python main.py 76 | 或者在PyCharm中运行main.py 77 | 2,扫描串口并选择正确的连接到单片机 78 | 3,想干嘛干嘛 79 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/mcu_prj/OLED_imageShow.7z -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/mcu_prj/OLED_imageShow.bin -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Inc/dma.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * File Name : dma.h 4 | * Description : This file contains all the function prototypes for 5 | * the dma.c file 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* Define to prevent recursive inclusion -------------------------------------*/ 20 | #ifndef __dma_H 21 | #define __dma_H 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /* Includes ------------------------------------------------------------------*/ 28 | #include "main.h" 29 | 30 | /* DMA memory to memory transfer handles -------------------------------------*/ 31 | 32 | /* USER CODE BEGIN Includes */ 33 | 34 | /* USER CODE END Includes */ 35 | 36 | /* USER CODE BEGIN Private defines */ 37 | 38 | /* USER CODE END Private defines */ 39 | 40 | void MX_DMA_Init(void); 41 | 42 | /* USER CODE BEGIN Prototypes */ 43 | 44 | /* USER CODE END Prototypes */ 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif /* __dma_H */ 51 | 52 | /** 53 | * @} 54 | */ 55 | 56 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 57 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Inc/gpio.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * File Name : gpio.h 4 | * Description : This file contains all the functions prototypes for 5 | * the gpio 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef __gpio_H 22 | #define __gpio_H 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /* Includes ------------------------------------------------------------------*/ 28 | #include "main.h" 29 | 30 | /* USER CODE BEGIN Includes */ 31 | 32 | /* USER CODE END Includes */ 33 | 34 | /* USER CODE BEGIN Private defines */ 35 | 36 | /* USER CODE END Private defines */ 37 | 38 | void MX_GPIO_Init(void); 39 | 40 | /* USER CODE BEGIN Prototypes */ 41 | 42 | /* USER CODE END Prototypes */ 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | #endif /*__ pinoutConfig_H */ 48 | 49 | /** 50 | * @} 51 | */ 52 | 53 | /** 54 | * @} 55 | */ 56 | 57 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 58 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Inc/i2c.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * File Name : I2C.h 4 | * Description : This file provides code for the configuration 5 | * of the I2C instances. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* Define to prevent recursive inclusion -------------------------------------*/ 20 | #ifndef __i2c_H 21 | #define __i2c_H 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | /* Includes ------------------------------------------------------------------*/ 27 | #include "main.h" 28 | 29 | /* USER CODE BEGIN Includes */ 30 | 31 | /* USER CODE END Includes */ 32 | 33 | extern I2C_HandleTypeDef hi2c2; 34 | 35 | /* USER CODE BEGIN Private defines */ 36 | 37 | /* USER CODE END Private defines */ 38 | 39 | void MX_I2C2_Init(void); 40 | 41 | /* USER CODE BEGIN Prototypes */ 42 | 43 | /* USER CODE END Prototypes */ 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | #endif /*__ i2c_H */ 49 | 50 | /** 51 | * @} 52 | */ 53 | 54 | /** 55 | * @} 56 | */ 57 | 58 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 59 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Inc/main.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : main.h 5 | * @brief : Header for main.c file. 6 | * This file contains the common defines of the application. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | *

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

12 | * 13 | * This software component is licensed by ST under BSD 3-Clause license, 14 | * the "License"; You may not use this file except in compliance with the 15 | * License. You may obtain a copy of the License at: 16 | * opensource.org/licenses/BSD-3-Clause 17 | * 18 | ****************************************************************************** 19 | */ 20 | /* USER CODE END Header */ 21 | 22 | /* Define to prevent recursive inclusion -------------------------------------*/ 23 | #ifndef __MAIN_H 24 | #define __MAIN_H 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /* Includes ------------------------------------------------------------------*/ 31 | #include "stm32f1xx_hal.h" 32 | 33 | /* Private includes ----------------------------------------------------------*/ 34 | /* USER CODE BEGIN Includes */ 35 | 36 | /* USER CODE END Includes */ 37 | 38 | /* Exported types ------------------------------------------------------------*/ 39 | /* USER CODE BEGIN ET */ 40 | 41 | /* USER CODE END ET */ 42 | 43 | /* Exported constants --------------------------------------------------------*/ 44 | /* USER CODE BEGIN EC */ 45 | 46 | /* USER CODE END EC */ 47 | 48 | /* Exported macro ------------------------------------------------------------*/ 49 | /* USER CODE BEGIN EM */ 50 | 51 | /* USER CODE END EM */ 52 | 53 | /* Exported functions prototypes ---------------------------------------------*/ 54 | void Error_Handler(void); 55 | 56 | /* USER CODE BEGIN EFP */ 57 | 58 | /* USER CODE END EFP */ 59 | 60 | /* Private defines -----------------------------------------------------------*/ 61 | /* USER CODE BEGIN Private defines */ 62 | 63 | /* USER CODE END Private defines */ 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif /* __MAIN_H */ 70 | 71 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 72 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Inc/stm32f1xx_it.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32f1xx_it.h 5 | * @brief This file contains the headers of the interrupt handlers. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __STM32F1xx_IT_H 23 | #define __STM32F1xx_IT_H 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Private includes ----------------------------------------------------------*/ 30 | /* USER CODE BEGIN Includes */ 31 | 32 | /* USER CODE END Includes */ 33 | 34 | /* Exported types ------------------------------------------------------------*/ 35 | /* USER CODE BEGIN ET */ 36 | 37 | /* USER CODE END ET */ 38 | 39 | /* Exported constants --------------------------------------------------------*/ 40 | /* USER CODE BEGIN EC */ 41 | 42 | /* USER CODE END EC */ 43 | 44 | /* Exported macro ------------------------------------------------------------*/ 45 | /* USER CODE BEGIN EM */ 46 | 47 | /* USER CODE END EM */ 48 | 49 | /* Exported functions prototypes ---------------------------------------------*/ 50 | void NMI_Handler(void); 51 | void HardFault_Handler(void); 52 | void MemManage_Handler(void); 53 | void BusFault_Handler(void); 54 | void UsageFault_Handler(void); 55 | void SVC_Handler(void); 56 | void DebugMon_Handler(void); 57 | void PendSV_Handler(void); 58 | void SysTick_Handler(void); 59 | void DMA1_Channel4_IRQHandler(void); 60 | void DMA1_Channel6_IRQHandler(void); 61 | /* USER CODE BEGIN EFP */ 62 | 63 | /* USER CODE END EFP */ 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif /* __STM32F1xx_IT_H */ 70 | 71 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 72 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Inc/usart.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * File Name : USART.h 4 | * Description : This file provides code for the configuration 5 | * of the USART instances. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* Define to prevent recursive inclusion -------------------------------------*/ 20 | #ifndef __usart_H 21 | #define __usart_H 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | /* Includes ------------------------------------------------------------------*/ 27 | #include "main.h" 28 | 29 | /* USER CODE BEGIN Includes */ 30 | 31 | /* USER CODE END Includes */ 32 | 33 | extern UART_HandleTypeDef huart2; 34 | 35 | /* USER CODE BEGIN Private defines */ 36 | 37 | /* USER CODE END Private defines */ 38 | 39 | void MX_USART2_UART_Init(void); 40 | 41 | /* USER CODE BEGIN Prototypes */ 42 | 43 | /* USER CODE END Prototypes */ 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | #endif /*__ usart_H */ 49 | 50 | /** 51 | * @} 52 | */ 53 | 54 | /** 55 | * @} 56 | */ 57 | 58 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 59 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Src/dma.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * File Name : dma.c 4 | * Description : This file provides code for the configuration 5 | * of all the requested memory to memory DMA transfers. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Includes ------------------------------------------------------------------*/ 21 | #include "dma.h" 22 | 23 | /* USER CODE BEGIN 0 */ 24 | 25 | /* USER CODE END 0 */ 26 | 27 | /*----------------------------------------------------------------------------*/ 28 | /* Configure DMA */ 29 | /*----------------------------------------------------------------------------*/ 30 | 31 | /* USER CODE BEGIN 1 */ 32 | 33 | /* USER CODE END 1 */ 34 | 35 | /** 36 | * Enable DMA controller clock 37 | */ 38 | void MX_DMA_Init(void) 39 | { 40 | 41 | /* DMA controller clock enable */ 42 | __HAL_RCC_DMA1_CLK_ENABLE(); 43 | 44 | /* DMA interrupt init */ 45 | /* DMA1_Channel4_IRQn interrupt configuration */ 46 | HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0); 47 | HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn); 48 | /* DMA1_Channel6_IRQn interrupt configuration */ 49 | HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0); 50 | HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); 51 | 52 | } 53 | 54 | /* USER CODE BEGIN 2 */ 55 | 56 | /* USER CODE END 2 */ 57 | 58 | /** 59 | * @} 60 | */ 61 | 62 | /** 63 | * @} 64 | */ 65 | 66 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 67 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Src/gpio.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * File Name : gpio.c 4 | * Description : This file provides code for the configuration 5 | * of all used GPIO pins. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Includes ------------------------------------------------------------------*/ 21 | #include "gpio.h" 22 | /* USER CODE BEGIN 0 */ 23 | 24 | /* USER CODE END 0 */ 25 | 26 | /*----------------------------------------------------------------------------*/ 27 | /* Configure GPIO */ 28 | /*----------------------------------------------------------------------------*/ 29 | /* USER CODE BEGIN 1 */ 30 | 31 | /* USER CODE END 1 */ 32 | 33 | /** Configure pins as 34 | * Analog 35 | * Input 36 | * Output 37 | * EVENT_OUT 38 | * EXTI 39 | */ 40 | void MX_GPIO_Init(void) 41 | { 42 | 43 | /* GPIO Ports Clock Enable */ 44 | __HAL_RCC_GPIOD_CLK_ENABLE(); 45 | __HAL_RCC_GPIOA_CLK_ENABLE(); 46 | __HAL_RCC_GPIOB_CLK_ENABLE(); 47 | 48 | } 49 | 50 | /* USER CODE BEGIN 2 */ 51 | 52 | /* USER CODE END 2 */ 53 | 54 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 55 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Src/i2c.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * File Name : I2C.c 4 | * Description : This file provides code for the configuration 5 | * of the I2C instances. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Includes ------------------------------------------------------------------*/ 21 | #include "i2c.h" 22 | 23 | /* USER CODE BEGIN 0 */ 24 | 25 | /* USER CODE END 0 */ 26 | 27 | I2C_HandleTypeDef hi2c2; 28 | DMA_HandleTypeDef hdma_i2c2_tx; 29 | 30 | /* I2C2 init function */ 31 | void MX_I2C2_Init(void) 32 | { 33 | 34 | hi2c2.Instance = I2C2; 35 | hi2c2.Init.ClockSpeed = 400000; 36 | hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2; 37 | hi2c2.Init.OwnAddress1 = 0; 38 | hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; 39 | hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; 40 | hi2c2.Init.OwnAddress2 = 0; 41 | hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; 42 | hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; 43 | if (HAL_I2C_Init(&hi2c2) != HAL_OK) 44 | { 45 | Error_Handler(); 46 | } 47 | 48 | } 49 | 50 | void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) 51 | { 52 | 53 | GPIO_InitTypeDef GPIO_InitStruct = {0}; 54 | if(i2cHandle->Instance==I2C2) 55 | { 56 | /* USER CODE BEGIN I2C2_MspInit 0 */ 57 | 58 | /* USER CODE END I2C2_MspInit 0 */ 59 | 60 | __HAL_RCC_GPIOB_CLK_ENABLE(); 61 | /**I2C2 GPIO Configuration 62 | PB10 ------> I2C2_SCL 63 | PB11 ------> I2C2_SDA 64 | */ 65 | GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; 66 | GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; 67 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; 68 | HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 69 | 70 | /* I2C2 clock enable */ 71 | __HAL_RCC_I2C2_CLK_ENABLE(); 72 | 73 | /* I2C2 DMA Init */ 74 | /* I2C2_TX Init */ 75 | hdma_i2c2_tx.Instance = DMA1_Channel4; 76 | hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; 77 | hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE; 78 | hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE; 79 | hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; 80 | hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; 81 | hdma_i2c2_tx.Init.Mode = DMA_NORMAL; 82 | hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW; 83 | if (HAL_DMA_Init(&hdma_i2c2_tx) != HAL_OK) 84 | { 85 | Error_Handler(); 86 | } 87 | 88 | __HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c2_tx); 89 | 90 | /* USER CODE BEGIN I2C2_MspInit 1 */ 91 | 92 | /* USER CODE END I2C2_MspInit 1 */ 93 | } 94 | } 95 | 96 | void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle) 97 | { 98 | 99 | if(i2cHandle->Instance==I2C2) 100 | { 101 | /* USER CODE BEGIN I2C2_MspDeInit 0 */ 102 | 103 | /* USER CODE END I2C2_MspDeInit 0 */ 104 | /* Peripheral clock disable */ 105 | __HAL_RCC_I2C2_CLK_DISABLE(); 106 | 107 | /**I2C2 GPIO Configuration 108 | PB10 ------> I2C2_SCL 109 | PB11 ------> I2C2_SDA 110 | */ 111 | HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); 112 | 113 | /* I2C2 DMA DeInit */ 114 | HAL_DMA_DeInit(i2cHandle->hdmatx); 115 | /* USER CODE BEGIN I2C2_MspDeInit 1 */ 116 | 117 | /* USER CODE END I2C2_MspDeInit 1 */ 118 | } 119 | } 120 | 121 | /* USER CODE BEGIN 1 */ 122 | 123 | /* USER CODE END 1 */ 124 | 125 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 126 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Src/main.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : main.c 5 | * @brief : Main program body 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include "main.h" 23 | #include "dma.h" 24 | #include "i2c.h" 25 | #include "usart.h" 26 | #include "gpio.h" 27 | 28 | /* Private includes ----------------------------------------------------------*/ 29 | /* USER CODE BEGIN Includes */ 30 | #include 31 | #include 32 | #include "ssd1306.h" 33 | 34 | /* USER CODE END Includes */ 35 | 36 | /* Private typedef -----------------------------------------------------------*/ 37 | /* USER CODE BEGIN PTD */ 38 | 39 | /* USER CODE END PTD */ 40 | 41 | /* Private define ------------------------------------------------------------*/ 42 | /* USER CODE BEGIN PD */ 43 | 44 | /* USER CODE END PD */ 45 | 46 | /* Private macro -------------------------------------------------------------*/ 47 | /* USER CODE BEGIN PM */ 48 | 49 | /* USER CODE END PM */ 50 | 51 | /* Private variables ---------------------------------------------------------*/ 52 | 53 | /* USER CODE BEGIN PV */ 54 | 55 | /* USER CODE END PV */ 56 | 57 | /* Private function prototypes -----------------------------------------------*/ 58 | void SystemClock_Config(void); 59 | /* USER CODE BEGIN PFP */ 60 | 61 | /* USER CODE END PFP */ 62 | 63 | /* Private user code ---------------------------------------------------------*/ 64 | /* USER CODE BEGIN 0 */ 65 | uint8_t oled_icon_buff[] = { 66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 68 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 70 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 78 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 79 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 80 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 81 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 82 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 83 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 84 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 85 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 86 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 87 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 88 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 89 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 90 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 91 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3c, 0x23, 0x3c, 0xc0, 92 | 0x00, 0x08, 0xf8, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x7c, 0x82, 0x01, 0x01, 0x01, 0x87, 0x00, 0x00, 93 | 0xff, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x90, 0x48, 0x28, 0x28, 0xf0, 0x00, 0x08, 0xf8, 0x10, 94 | 0x08, 0x08, 0xf0, 0x00, 0x00, 0xb0, 0x48, 0x48, 0x38, 0x08, 0x00, 0x01, 0xff, 0x07, 0x38, 0xc1, 95 | 0xff, 0x01, 0x00, 0x08, 0x08, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x08, 0x08, 0x08, 0x98, 0x00, 96 | 0x00, 0xf0, 0x28, 0x28, 0x28, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 97 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 98 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 99 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 100 | 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 101 | 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 102 | 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x05, 0x05, 0x05, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 103 | 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 104 | 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 105 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 106 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 107 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 108 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 110 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 111 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 112 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 113 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 114 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 115 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 116 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 117 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 118 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 119 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 120 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 121 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 122 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 123 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 124 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 125 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 126 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 127 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 128 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 129 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 130 | }; 131 | 132 | uint8_t rx_buff[2][1024] = {0}; 133 | uint8_t rx_dma_complete = 0; 134 | uint8_t rx_dma_buffer_index = 0; 135 | uint8_t rx_display_buffer_index = 0; 136 | 137 | char uart_tx_buff[32]; 138 | 139 | /* USER CODE END 0 */ 140 | 141 | /** 142 | * @brief The application entry point. 143 | * @retval int 144 | */ 145 | int main(void) 146 | { 147 | /* USER CODE BEGIN 1 */ 148 | 149 | /* USER CODE END 1 */ 150 | 151 | 152 | /* MCU Configuration--------------------------------------------------------*/ 153 | 154 | /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ 155 | HAL_Init(); 156 | 157 | /* USER CODE BEGIN Init */ 158 | 159 | /* USER CODE END Init */ 160 | 161 | /* Configure the system clock */ 162 | SystemClock_Config(); 163 | 164 | /* USER CODE BEGIN SysInit */ 165 | 166 | /* USER CODE END SysInit */ 167 | 168 | /* Initialize all configured peripherals */ 169 | MX_GPIO_Init(); 170 | MX_DMA_Init(); 171 | MX_I2C2_Init(); 172 | MX_USART2_UART_Init(); 173 | /* USER CODE BEGIN 2 */ 174 | ssd1306_Init(); 175 | ssd1306_UpdateScreenWithBuffer(oled_icon_buff); 176 | 177 | HAL_UART_Receive_DMA(&huart2, (uint8_t *)rx_buff[rx_dma_buffer_index], sizeof(rx_buff[1])); 178 | 179 | /* USER CODE END 2 */ 180 | 181 | /* Infinite loop */ 182 | /* USER CODE BEGIN WHILE */ 183 | while (1) 184 | { 185 | /* USER CODE END WHILE */ 186 | 187 | /* USER CODE BEGIN 3 */ 188 | if(rx_dma_complete == 1) 189 | { 190 | // Send a info to PC 191 | sprintf(uart_tx_buff, "time : %ld ms\n", HAL_GetTick()); 192 | HAL_UART_Transmit(&huart2, (uint8_t *)uart_tx_buff, strlen(uart_tx_buff), 10); 193 | 194 | // Switch to another DMA rx_buffer 195 | rx_display_buffer_index = rx_dma_buffer_index; 196 | rx_dma_buffer_index = (1 == rx_dma_buffer_index) ? 0 : 1; 197 | 198 | // Restart DMA receiver 199 | rx_dma_complete = 0; 200 | HAL_UART_Receive_DMA(&huart2, (uint8_t *)rx_buff[rx_dma_buffer_index], sizeof(rx_buff[rx_dma_buffer_index])); 201 | 202 | // Update OLED 203 | ssd1306_UpdateScreenWithBuffer((uint8_t *)rx_buff[rx_display_buffer_index]); 204 | } 205 | } 206 | /* USER CODE END 3 */ 207 | } 208 | 209 | /** 210 | * @brief System Clock Configuration 211 | * @retval None 212 | */ 213 | void SystemClock_Config(void) 214 | { 215 | RCC_OscInitTypeDef RCC_OscInitStruct = {0}; 216 | RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; 217 | 218 | /** Initializes the CPU, AHB and APB busses clocks 219 | */ 220 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 221 | RCC_OscInitStruct.HSEState = RCC_HSE_ON; 222 | RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; 223 | RCC_OscInitStruct.HSIState = RCC_HSI_ON; 224 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 225 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 226 | RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; 227 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 228 | { 229 | Error_Handler(); 230 | } 231 | /** Initializes the CPU, AHB and APB busses clocks 232 | */ 233 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK 234 | |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; 235 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 236 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 237 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; 238 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 239 | 240 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) 241 | { 242 | Error_Handler(); 243 | } 244 | } 245 | 246 | /* USER CODE BEGIN 4 */ 247 | void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 248 | { 249 | rx_dma_complete = 1; 250 | } 251 | 252 | /* USER CODE END 4 */ 253 | 254 | /** 255 | * @brief This function is executed in case of error occurrence. 256 | * @retval None 257 | */ 258 | void Error_Handler(void) 259 | { 260 | /* USER CODE BEGIN Error_Handler_Debug */ 261 | /* User can add his own implementation to report the HAL error return state */ 262 | 263 | /* USER CODE END Error_Handler_Debug */ 264 | } 265 | 266 | #ifdef USE_FULL_ASSERT 267 | /** 268 | * @brief Reports the name of the source file and the source line number 269 | * where the assert_param error has occurred. 270 | * @param file: pointer to the source file name 271 | * @param line: assert_param error line source number 272 | * @retval None 273 | */ 274 | void assert_failed(uint8_t *file, uint32_t line) 275 | { 276 | /* USER CODE BEGIN 6 */ 277 | /* User can add his own implementation to report the file name and line number, 278 | tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ 279 | /* USER CODE END 6 */ 280 | } 281 | #endif /* USE_FULL_ASSERT */ 282 | 283 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 284 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Src/stm32f1xx_hal_msp.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * File Name : stm32f1xx_hal_msp.c 5 | * Description : This file provides code for the MSP Initialization 6 | * and de-Initialization codes. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | *

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

12 | * 13 | * This software component is licensed by ST under BSD 3-Clause license, 14 | * the "License"; You may not use this file except in compliance with the 15 | * License. You may obtain a copy of the License at: 16 | * opensource.org/licenses/BSD-3-Clause 17 | * 18 | ****************************************************************************** 19 | */ 20 | /* USER CODE END Header */ 21 | 22 | /* Includes ------------------------------------------------------------------*/ 23 | #include "main.h" 24 | /* USER CODE BEGIN Includes */ 25 | 26 | /* USER CODE END Includes */ 27 | 28 | /* Private typedef -----------------------------------------------------------*/ 29 | /* USER CODE BEGIN TD */ 30 | 31 | /* USER CODE END TD */ 32 | 33 | /* Private define ------------------------------------------------------------*/ 34 | /* USER CODE BEGIN Define */ 35 | 36 | /* USER CODE END Define */ 37 | 38 | /* Private macro -------------------------------------------------------------*/ 39 | /* USER CODE BEGIN Macro */ 40 | 41 | /* USER CODE END Macro */ 42 | 43 | /* Private variables ---------------------------------------------------------*/ 44 | /* USER CODE BEGIN PV */ 45 | 46 | /* USER CODE END PV */ 47 | 48 | /* Private function prototypes -----------------------------------------------*/ 49 | /* USER CODE BEGIN PFP */ 50 | 51 | /* USER CODE END PFP */ 52 | 53 | /* External functions --------------------------------------------------------*/ 54 | /* USER CODE BEGIN ExternalFunctions */ 55 | 56 | /* USER CODE END ExternalFunctions */ 57 | 58 | /* USER CODE BEGIN 0 */ 59 | 60 | /* USER CODE END 0 */ 61 | /** 62 | * Initializes the Global MSP. 63 | */ 64 | void HAL_MspInit(void) 65 | { 66 | /* USER CODE BEGIN MspInit 0 */ 67 | 68 | /* USER CODE END MspInit 0 */ 69 | 70 | __HAL_RCC_AFIO_CLK_ENABLE(); 71 | __HAL_RCC_PWR_CLK_ENABLE(); 72 | 73 | /* System interrupt init*/ 74 | 75 | /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled 76 | */ 77 | __HAL_AFIO_REMAP_SWJ_NOJTAG(); 78 | 79 | /* USER CODE BEGIN MspInit 1 */ 80 | 81 | /* USER CODE END MspInit 1 */ 82 | } 83 | 84 | /* USER CODE BEGIN 1 */ 85 | 86 | /* USER CODE END 1 */ 87 | 88 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 89 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Src/stm32f1xx_it.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32f1xx_it.c 5 | * @brief Interrupt Service Routines. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include "main.h" 23 | #include "stm32f1xx_it.h" 24 | /* Private includes ----------------------------------------------------------*/ 25 | /* USER CODE BEGIN Includes */ 26 | /* USER CODE END Includes */ 27 | 28 | /* Private typedef -----------------------------------------------------------*/ 29 | /* USER CODE BEGIN TD */ 30 | 31 | /* USER CODE END TD */ 32 | 33 | /* Private define ------------------------------------------------------------*/ 34 | /* USER CODE BEGIN PD */ 35 | 36 | /* USER CODE END PD */ 37 | 38 | /* Private macro -------------------------------------------------------------*/ 39 | /* USER CODE BEGIN PM */ 40 | 41 | /* USER CODE END PM */ 42 | 43 | /* Private variables ---------------------------------------------------------*/ 44 | /* USER CODE BEGIN PV */ 45 | 46 | /* USER CODE END PV */ 47 | 48 | /* Private function prototypes -----------------------------------------------*/ 49 | /* USER CODE BEGIN PFP */ 50 | 51 | /* USER CODE END PFP */ 52 | 53 | /* Private user code ---------------------------------------------------------*/ 54 | /* USER CODE BEGIN 0 */ 55 | 56 | /* USER CODE END 0 */ 57 | 58 | /* External variables --------------------------------------------------------*/ 59 | extern DMA_HandleTypeDef hdma_i2c2_tx; 60 | extern DMA_HandleTypeDef hdma_usart2_rx; 61 | /* USER CODE BEGIN EV */ 62 | 63 | /* USER CODE END EV */ 64 | 65 | /******************************************************************************/ 66 | /* Cortex-M3 Processor Interruption and Exception Handlers */ 67 | /******************************************************************************/ 68 | /** 69 | * @brief This function handles Non maskable interrupt. 70 | */ 71 | void NMI_Handler(void) 72 | { 73 | /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ 74 | 75 | /* USER CODE END NonMaskableInt_IRQn 0 */ 76 | /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ 77 | 78 | /* USER CODE END NonMaskableInt_IRQn 1 */ 79 | } 80 | 81 | /** 82 | * @brief This function handles Hard fault interrupt. 83 | */ 84 | void HardFault_Handler(void) 85 | { 86 | /* USER CODE BEGIN HardFault_IRQn 0 */ 87 | 88 | /* USER CODE END HardFault_IRQn 0 */ 89 | while (1) 90 | { 91 | /* USER CODE BEGIN W1_HardFault_IRQn 0 */ 92 | /* USER CODE END W1_HardFault_IRQn 0 */ 93 | } 94 | } 95 | 96 | /** 97 | * @brief This function handles Memory management fault. 98 | */ 99 | void MemManage_Handler(void) 100 | { 101 | /* USER CODE BEGIN MemoryManagement_IRQn 0 */ 102 | 103 | /* USER CODE END MemoryManagement_IRQn 0 */ 104 | while (1) 105 | { 106 | /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ 107 | /* USER CODE END W1_MemoryManagement_IRQn 0 */ 108 | } 109 | } 110 | 111 | /** 112 | * @brief This function handles Prefetch fault, memory access fault. 113 | */ 114 | void BusFault_Handler(void) 115 | { 116 | /* USER CODE BEGIN BusFault_IRQn 0 */ 117 | 118 | /* USER CODE END BusFault_IRQn 0 */ 119 | while (1) 120 | { 121 | /* USER CODE BEGIN W1_BusFault_IRQn 0 */ 122 | /* USER CODE END W1_BusFault_IRQn 0 */ 123 | } 124 | } 125 | 126 | /** 127 | * @brief This function handles Undefined instruction or illegal state. 128 | */ 129 | void UsageFault_Handler(void) 130 | { 131 | /* USER CODE BEGIN UsageFault_IRQn 0 */ 132 | 133 | /* USER CODE END UsageFault_IRQn 0 */ 134 | while (1) 135 | { 136 | /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ 137 | /* USER CODE END W1_UsageFault_IRQn 0 */ 138 | } 139 | } 140 | 141 | /** 142 | * @brief This function handles System service call via SWI instruction. 143 | */ 144 | void SVC_Handler(void) 145 | { 146 | /* USER CODE BEGIN SVCall_IRQn 0 */ 147 | 148 | /* USER CODE END SVCall_IRQn 0 */ 149 | /* USER CODE BEGIN SVCall_IRQn 1 */ 150 | 151 | /* USER CODE END SVCall_IRQn 1 */ 152 | } 153 | 154 | /** 155 | * @brief This function handles Debug monitor. 156 | */ 157 | void DebugMon_Handler(void) 158 | { 159 | /* USER CODE BEGIN DebugMonitor_IRQn 0 */ 160 | 161 | /* USER CODE END DebugMonitor_IRQn 0 */ 162 | /* USER CODE BEGIN DebugMonitor_IRQn 1 */ 163 | 164 | /* USER CODE END DebugMonitor_IRQn 1 */ 165 | } 166 | 167 | /** 168 | * @brief This function handles Pendable request for system service. 169 | */ 170 | void PendSV_Handler(void) 171 | { 172 | /* USER CODE BEGIN PendSV_IRQn 0 */ 173 | 174 | /* USER CODE END PendSV_IRQn 0 */ 175 | /* USER CODE BEGIN PendSV_IRQn 1 */ 176 | 177 | /* USER CODE END PendSV_IRQn 1 */ 178 | } 179 | 180 | /** 181 | * @brief This function handles System tick timer. 182 | */ 183 | void SysTick_Handler(void) 184 | { 185 | /* USER CODE BEGIN SysTick_IRQn 0 */ 186 | 187 | /* USER CODE END SysTick_IRQn 0 */ 188 | HAL_IncTick(); 189 | /* USER CODE BEGIN SysTick_IRQn 1 */ 190 | 191 | /* USER CODE END SysTick_IRQn 1 */ 192 | } 193 | 194 | /******************************************************************************/ 195 | /* STM32F1xx Peripheral Interrupt Handlers */ 196 | /* Add here the Interrupt Handlers for the used peripherals. */ 197 | /* For the available peripheral interrupt handler names, */ 198 | /* please refer to the startup file (startup_stm32f1xx.s). */ 199 | /******************************************************************************/ 200 | 201 | /** 202 | * @brief This function handles DMA1 channel4 global interrupt. 203 | */ 204 | void DMA1_Channel4_IRQHandler(void) 205 | { 206 | /* USER CODE BEGIN DMA1_Channel4_IRQn 0 */ 207 | 208 | /* USER CODE END DMA1_Channel4_IRQn 0 */ 209 | HAL_DMA_IRQHandler(&hdma_i2c2_tx); 210 | /* USER CODE BEGIN DMA1_Channel4_IRQn 1 */ 211 | 212 | /* USER CODE END DMA1_Channel4_IRQn 1 */ 213 | } 214 | 215 | /** 216 | * @brief This function handles DMA1 channel6 global interrupt. 217 | */ 218 | void DMA1_Channel6_IRQHandler(void) 219 | { 220 | /* USER CODE BEGIN DMA1_Channel6_IRQn 0 */ 221 | 222 | /* USER CODE END DMA1_Channel6_IRQn 0 */ 223 | HAL_DMA_IRQHandler(&hdma_usart2_rx); 224 | /* USER CODE BEGIN DMA1_Channel6_IRQn 1 */ 225 | 226 | /* USER CODE END DMA1_Channel6_IRQn 1 */ 227 | } 228 | 229 | /* USER CODE BEGIN 1 */ 230 | 231 | /* USER CODE END 1 */ 232 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 233 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Src/syscalls.c: -------------------------------------------------------------------------------- 1 | /** 2 | ***************************************************************************** 3 | ** 4 | ** File : syscalls.c 5 | ** 6 | ** Author : Auto-generated by STM32CubeIDE 7 | ** 8 | ** Abstract : STM32CubeIDE Minimal System calls file 9 | ** 10 | ** For more information about which c-functions 11 | ** need which of these lowlevel functions 12 | ** please consult the Newlib libc-manual 13 | ** 14 | ** Environment : STM32CubeIDE MCU 15 | ** 16 | ** Distribution: The file is distributed as is, without any warranty 17 | ** of any kind. 18 | ** 19 | ***************************************************************************** 20 | ** 21 | **

© COPYRIGHT(c) 2018 STMicroelectronics

22 | ** 23 | ** Redistribution and use in source and binary forms, with or without modification, 24 | ** are permitted provided that the following conditions are met: 25 | ** 1. Redistributions of source code must retain the above copyright notice, 26 | ** this list of conditions and the following disclaimer. 27 | ** 2. Redistributions in binary form must reproduce the above copyright notice, 28 | ** this list of conditions and the following disclaimer in the documentation 29 | ** and/or other materials provided with the distribution. 30 | ** 3. Neither the name of STMicroelectronics nor the names of its contributors 31 | ** may be used to endorse or promote products derived from this software 32 | ** without specific prior written permission. 33 | ** 34 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 35 | ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 37 | ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 38 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 40 | ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 41 | ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 42 | ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 43 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 | ** 45 | ** 46 | ***************************************************************************** 47 | */ 48 | 49 | /* Includes */ 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | 59 | 60 | /* Variables */ 61 | //#undef errno 62 | extern int errno; 63 | extern int __io_putchar(int ch) __attribute__((weak)); 64 | extern int __io_getchar(void) __attribute__((weak)); 65 | 66 | register char * stack_ptr asm("sp"); 67 | 68 | char *__env[1] = { 0 }; 69 | char **environ = __env; 70 | 71 | 72 | /* Functions */ 73 | void initialise_monitor_handles() 74 | { 75 | } 76 | 77 | int _getpid(void) 78 | { 79 | return 1; 80 | } 81 | 82 | int _kill(int pid, int sig) 83 | { 84 | errno = EINVAL; 85 | return -1; 86 | } 87 | 88 | void _exit (int status) 89 | { 90 | _kill(status, -1); 91 | while (1) {} /* Make sure we hang here */ 92 | } 93 | 94 | __attribute__((weak)) int _read(int file, char *ptr, int len) 95 | { 96 | int DataIdx; 97 | 98 | for (DataIdx = 0; DataIdx < len; DataIdx++) 99 | { 100 | *ptr++ = __io_getchar(); 101 | } 102 | 103 | return len; 104 | } 105 | 106 | __attribute__((weak)) int _write(int file, char *ptr, int len) 107 | { 108 | int DataIdx; 109 | 110 | for (DataIdx = 0; DataIdx < len; DataIdx++) 111 | { 112 | __io_putchar(*ptr++); 113 | } 114 | return len; 115 | } 116 | 117 | int _close(int file) 118 | { 119 | return -1; 120 | } 121 | 122 | 123 | int _fstat(int file, struct stat *st) 124 | { 125 | st->st_mode = S_IFCHR; 126 | return 0; 127 | } 128 | 129 | int _isatty(int file) 130 | { 131 | return 1; 132 | } 133 | 134 | int _lseek(int file, int ptr, int dir) 135 | { 136 | return 0; 137 | } 138 | 139 | int _open(char *path, int flags, ...) 140 | { 141 | /* Pretend like we always fail */ 142 | return -1; 143 | } 144 | 145 | int _wait(int *status) 146 | { 147 | errno = ECHILD; 148 | return -1; 149 | } 150 | 151 | int _unlink(char *name) 152 | { 153 | errno = ENOENT; 154 | return -1; 155 | } 156 | 157 | int _times(struct tms *buf) 158 | { 159 | return -1; 160 | } 161 | 162 | int _stat(char *file, struct stat *st) 163 | { 164 | st->st_mode = S_IFCHR; 165 | return 0; 166 | } 167 | 168 | int _link(char *old, char *new) 169 | { 170 | errno = EMLINK; 171 | return -1; 172 | } 173 | 174 | int _fork(void) 175 | { 176 | errno = EAGAIN; 177 | return -1; 178 | } 179 | 180 | int _execve(char *name, char **argv, char **env) 181 | { 182 | errno = ENOMEM; 183 | return -1; 184 | } 185 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Src/sysmem.c: -------------------------------------------------------------------------------- 1 | /** 2 | ***************************************************************************** 3 | ** 4 | ** File : sysmem.c 5 | ** 6 | ** Author : Auto-generated by STM32CubeIDE 7 | ** 8 | ** Abstract : STM32CubeIDE Minimal System Memory calls file 9 | ** 10 | ** For more information about which c-functions 11 | ** need which of these lowlevel functions 12 | ** please consult the Newlib libc-manual 13 | ** 14 | ** Environment : STM32CubeIDE MCU 15 | ** 16 | ** Distribution: The file is distributed as is, without any warranty 17 | ** of any kind. 18 | ** 19 | ***************************************************************************** 20 | ** 21 | **

© COPYRIGHT(c) 2018 STMicroelectronics

22 | ** 23 | ** Redistribution and use in source and binary forms, with or without modification, 24 | ** are permitted provided that the following conditions are met: 25 | ** 1. Redistributions of source code must retain the above copyright notice, 26 | ** this list of conditions and the following disclaimer. 27 | ** 2. Redistributions in binary form must reproduce the above copyright notice, 28 | ** this list of conditions and the following disclaimer in the documentation 29 | ** and/or other materials provided with the distribution. 30 | ** 3. Neither the name of STMicroelectronics nor the names of its contributors 31 | ** may be used to endorse or promote products derived from this software 32 | ** without specific prior written permission. 33 | ** 34 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 35 | ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 37 | ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 38 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 40 | ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 41 | ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 42 | ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 43 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 | ** 45 | ** 46 | ***************************************************************************** 47 | */ 48 | 49 | /* Includes */ 50 | #include 51 | #include 52 | 53 | /* Variables */ 54 | extern int errno; 55 | register char * stack_ptr asm("sp"); 56 | 57 | /* Functions */ 58 | 59 | /** 60 | _sbrk 61 | Increase program data space. Malloc and related functions depend on this 62 | **/ 63 | caddr_t _sbrk(int incr) 64 | { 65 | extern char end asm("end"); 66 | static char *heap_end; 67 | char *prev_heap_end; 68 | 69 | if (heap_end == 0) 70 | heap_end = &end; 71 | 72 | prev_heap_end = heap_end; 73 | if (heap_end + incr > stack_ptr) 74 | { 75 | errno = ENOMEM; 76 | return (caddr_t) -1; 77 | } 78 | 79 | heap_end += incr; 80 | 81 | return (caddr_t) prev_heap_end; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Src/system_stm32f1xx.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f1xx.c 4 | * @author MCD Application Team 5 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File. 6 | * 7 | * 1. This file provides two functions and one global variable to be called from 8 | * user application: 9 | * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier 10 | * factors, AHB/APBx prescalers and Flash settings). 11 | * This function is called at startup just after reset and 12 | * before branch to main program. This call is made inside 13 | * the "startup_stm32f1xx_xx.s" file. 14 | * 15 | * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used 16 | * by the user application to setup the SysTick 17 | * timer or configure other parameters. 18 | * 19 | * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must 20 | * be called whenever the core clock is changed 21 | * during program execution. 22 | * 23 | * 2. After each device reset the HSI (8 MHz) is used as system clock source. 24 | * Then SystemInit() function is called, in "startup_stm32f1xx_xx.s" file, to 25 | * configure the system clock before to branch to main program. 26 | * 27 | * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depending on 28 | * the product used), refer to "HSE_VALUE". 29 | * When HSE is used as system clock source, directly or through PLL, and you 30 | * are using different crystal you have to adapt the HSE value to your own 31 | * configuration. 32 | * 33 | ****************************************************************************** 34 | * @attention 35 | * 36 | *

© Copyright (c) 2017 STMicroelectronics. 37 | * All rights reserved.

38 | * 39 | * This software component is licensed by ST under BSD 3-Clause license, 40 | * the "License"; You may not use this file except in compliance with the 41 | * License. You may obtain a copy of the License at: 42 | * opensource.org/licenses/BSD-3-Clause 43 | * 44 | ****************************************************************************** 45 | */ 46 | 47 | /** @addtogroup CMSIS 48 | * @{ 49 | */ 50 | 51 | /** @addtogroup stm32f1xx_system 52 | * @{ 53 | */ 54 | 55 | /** @addtogroup STM32F1xx_System_Private_Includes 56 | * @{ 57 | */ 58 | 59 | #include "stm32f1xx.h" 60 | 61 | /** 62 | * @} 63 | */ 64 | 65 | /** @addtogroup STM32F1xx_System_Private_TypesDefinitions 66 | * @{ 67 | */ 68 | 69 | /** 70 | * @} 71 | */ 72 | 73 | /** @addtogroup STM32F1xx_System_Private_Defines 74 | * @{ 75 | */ 76 | 77 | #if !defined (HSE_VALUE) 78 | #define HSE_VALUE 8000000U /*!< Default value of the External oscillator in Hz. 79 | This value can be provided and adapted by the user application. */ 80 | #endif /* HSE_VALUE */ 81 | 82 | #if !defined (HSI_VALUE) 83 | #define HSI_VALUE 8000000U /*!< Default value of the Internal oscillator in Hz. 84 | This value can be provided and adapted by the user application. */ 85 | #endif /* HSI_VALUE */ 86 | 87 | /*!< Uncomment the following line if you need to use external SRAM */ 88 | #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) 89 | /* #define DATA_IN_ExtSRAM */ 90 | #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ 91 | 92 | /*!< Uncomment the following line if you need to relocate your vector Table in 93 | Internal SRAM. */ 94 | /* #define VECT_TAB_SRAM */ 95 | #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field. 96 | This value must be a multiple of 0x200. */ 97 | 98 | 99 | /** 100 | * @} 101 | */ 102 | 103 | /** @addtogroup STM32F1xx_System_Private_Macros 104 | * @{ 105 | */ 106 | 107 | /** 108 | * @} 109 | */ 110 | 111 | /** @addtogroup STM32F1xx_System_Private_Variables 112 | * @{ 113 | */ 114 | 115 | /* This variable is updated in three ways: 116 | 1) by calling CMSIS function SystemCoreClockUpdate() 117 | 2) by calling HAL API function HAL_RCC_GetHCLKFreq() 118 | 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency 119 | Note: If you use this function to configure the system clock; then there 120 | is no need to call the 2 first functions listed above, since SystemCoreClock 121 | variable is updated automatically. 122 | */ 123 | uint32_t SystemCoreClock = 16000000; 124 | const uint8_t AHBPrescTable[16U] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; 125 | const uint8_t APBPrescTable[8U] = {0, 0, 0, 0, 1, 2, 3, 4}; 126 | 127 | /** 128 | * @} 129 | */ 130 | 131 | /** @addtogroup STM32F1xx_System_Private_FunctionPrototypes 132 | * @{ 133 | */ 134 | 135 | #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) 136 | #ifdef DATA_IN_ExtSRAM 137 | static void SystemInit_ExtMemCtl(void); 138 | #endif /* DATA_IN_ExtSRAM */ 139 | #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ 140 | 141 | /** 142 | * @} 143 | */ 144 | 145 | /** @addtogroup STM32F1xx_System_Private_Functions 146 | * @{ 147 | */ 148 | 149 | /** 150 | * @brief Setup the microcontroller system 151 | * Initialize the Embedded Flash Interface, the PLL and update the 152 | * SystemCoreClock variable. 153 | * @note This function should be used only after reset. 154 | * @param None 155 | * @retval None 156 | */ 157 | void SystemInit (void) 158 | { 159 | /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ 160 | /* Set HSION bit */ 161 | RCC->CR |= 0x00000001U; 162 | 163 | /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ 164 | #if !defined(STM32F105xC) && !defined(STM32F107xC) 165 | RCC->CFGR &= 0xF8FF0000U; 166 | #else 167 | RCC->CFGR &= 0xF0FF0000U; 168 | #endif /* STM32F105xC */ 169 | 170 | /* Reset HSEON, CSSON and PLLON bits */ 171 | RCC->CR &= 0xFEF6FFFFU; 172 | 173 | /* Reset HSEBYP bit */ 174 | RCC->CR &= 0xFFFBFFFFU; 175 | 176 | /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ 177 | RCC->CFGR &= 0xFF80FFFFU; 178 | 179 | #if defined(STM32F105xC) || defined(STM32F107xC) 180 | /* Reset PLL2ON and PLL3ON bits */ 181 | RCC->CR &= 0xEBFFFFFFU; 182 | 183 | /* Disable all interrupts and clear pending bits */ 184 | RCC->CIR = 0x00FF0000U; 185 | 186 | /* Reset CFGR2 register */ 187 | RCC->CFGR2 = 0x00000000U; 188 | #elif defined(STM32F100xB) || defined(STM32F100xE) 189 | /* Disable all interrupts and clear pending bits */ 190 | RCC->CIR = 0x009F0000U; 191 | 192 | /* Reset CFGR2 register */ 193 | RCC->CFGR2 = 0x00000000U; 194 | #else 195 | /* Disable all interrupts and clear pending bits */ 196 | RCC->CIR = 0x009F0000U; 197 | #endif /* STM32F105xC */ 198 | 199 | #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) 200 | #ifdef DATA_IN_ExtSRAM 201 | SystemInit_ExtMemCtl(); 202 | #endif /* DATA_IN_ExtSRAM */ 203 | #endif 204 | 205 | #ifdef VECT_TAB_SRAM 206 | SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ 207 | #else 208 | SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ 209 | #endif 210 | } 211 | 212 | /** 213 | * @brief Update SystemCoreClock variable according to Clock Register Values. 214 | * The SystemCoreClock variable contains the core clock (HCLK), it can 215 | * be used by the user application to setup the SysTick timer or configure 216 | * other parameters. 217 | * 218 | * @note Each time the core clock (HCLK) changes, this function must be called 219 | * to update SystemCoreClock variable value. Otherwise, any configuration 220 | * based on this variable will be incorrect. 221 | * 222 | * @note - The system frequency computed by this function is not the real 223 | * frequency in the chip. It is calculated based on the predefined 224 | * constant and the selected clock source: 225 | * 226 | * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) 227 | * 228 | * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) 229 | * 230 | * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) 231 | * or HSI_VALUE(*) multiplied by the PLL factors. 232 | * 233 | * (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value 234 | * 8 MHz) but the real value may vary depending on the variations 235 | * in voltage and temperature. 236 | * 237 | * (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value 238 | * 8 MHz or 25 MHz, depending on the product used), user has to ensure 239 | * that HSE_VALUE is same as the real frequency of the crystal used. 240 | * Otherwise, this function may have wrong result. 241 | * 242 | * - The result of this function could be not correct when using fractional 243 | * value for HSE crystal. 244 | * @param None 245 | * @retval None 246 | */ 247 | void SystemCoreClockUpdate (void) 248 | { 249 | uint32_t tmp = 0U, pllmull = 0U, pllsource = 0U; 250 | 251 | #if defined(STM32F105xC) || defined(STM32F107xC) 252 | uint32_t prediv1source = 0U, prediv1factor = 0U, prediv2factor = 0U, pll2mull = 0U; 253 | #endif /* STM32F105xC */ 254 | 255 | #if defined(STM32F100xB) || defined(STM32F100xE) 256 | uint32_t prediv1factor = 0U; 257 | #endif /* STM32F100xB or STM32F100xE */ 258 | 259 | /* Get SYSCLK source -------------------------------------------------------*/ 260 | tmp = RCC->CFGR & RCC_CFGR_SWS; 261 | 262 | switch (tmp) 263 | { 264 | case 0x00U: /* HSI used as system clock */ 265 | SystemCoreClock = HSI_VALUE; 266 | break; 267 | case 0x04U: /* HSE used as system clock */ 268 | SystemCoreClock = HSE_VALUE; 269 | break; 270 | case 0x08U: /* PLL used as system clock */ 271 | 272 | /* Get PLL clock source and multiplication factor ----------------------*/ 273 | pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; 274 | pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; 275 | 276 | #if !defined(STM32F105xC) && !defined(STM32F107xC) 277 | pllmull = ( pllmull >> 18U) + 2U; 278 | 279 | if (pllsource == 0x00U) 280 | { 281 | /* HSI oscillator clock divided by 2 selected as PLL clock entry */ 282 | SystemCoreClock = (HSI_VALUE >> 1U) * pllmull; 283 | } 284 | else 285 | { 286 | #if defined(STM32F100xB) || defined(STM32F100xE) 287 | prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U; 288 | /* HSE oscillator clock selected as PREDIV1 clock entry */ 289 | SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; 290 | #else 291 | /* HSE selected as PLL clock entry */ 292 | if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET) 293 | {/* HSE oscillator clock divided by 2 */ 294 | SystemCoreClock = (HSE_VALUE >> 1U) * pllmull; 295 | } 296 | else 297 | { 298 | SystemCoreClock = HSE_VALUE * pllmull; 299 | } 300 | #endif 301 | } 302 | #else 303 | pllmull = pllmull >> 18U; 304 | 305 | if (pllmull != 0x0DU) 306 | { 307 | pllmull += 2U; 308 | } 309 | else 310 | { /* PLL multiplication factor = PLL input clock * 6.5 */ 311 | pllmull = 13U / 2U; 312 | } 313 | 314 | if (pllsource == 0x00U) 315 | { 316 | /* HSI oscillator clock divided by 2 selected as PLL clock entry */ 317 | SystemCoreClock = (HSI_VALUE >> 1U) * pllmull; 318 | } 319 | else 320 | {/* PREDIV1 selected as PLL clock entry */ 321 | 322 | /* Get PREDIV1 clock source and division factor */ 323 | prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC; 324 | prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U; 325 | 326 | if (prediv1source == 0U) 327 | { 328 | /* HSE oscillator clock selected as PREDIV1 clock entry */ 329 | SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; 330 | } 331 | else 332 | {/* PLL2 clock selected as PREDIV1 clock entry */ 333 | 334 | /* Get PREDIV2 division factor and PLL2 multiplication factor */ 335 | prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4U) + 1U; 336 | pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8U) + 2U; 337 | SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull; 338 | } 339 | } 340 | #endif /* STM32F105xC */ 341 | break; 342 | 343 | default: 344 | SystemCoreClock = HSI_VALUE; 345 | break; 346 | } 347 | 348 | /* Compute HCLK clock frequency ----------------*/ 349 | /* Get HCLK prescaler */ 350 | tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)]; 351 | /* HCLK clock frequency */ 352 | SystemCoreClock >>= tmp; 353 | } 354 | 355 | #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) 356 | /** 357 | * @brief Setup the external memory controller. Called in startup_stm32f1xx.s 358 | * before jump to __main 359 | * @param None 360 | * @retval None 361 | */ 362 | #ifdef DATA_IN_ExtSRAM 363 | /** 364 | * @brief Setup the external memory controller. 365 | * Called in startup_stm32f1xx_xx.s/.c before jump to main. 366 | * This function configures the external SRAM mounted on STM3210E-EVAL 367 | * board (STM32 High density devices). This SRAM will be used as program 368 | * data memory (including heap and stack). 369 | * @param None 370 | * @retval None 371 | */ 372 | void SystemInit_ExtMemCtl(void) 373 | { 374 | __IO uint32_t tmpreg; 375 | /*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is 376 | required, then adjust the Register Addresses */ 377 | 378 | /* Enable FSMC clock */ 379 | RCC->AHBENR = 0x00000114U; 380 | 381 | /* Delay after an RCC peripheral clock enabling */ 382 | tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_FSMCEN); 383 | 384 | /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */ 385 | RCC->APB2ENR = 0x000001E0U; 386 | 387 | /* Delay after an RCC peripheral clock enabling */ 388 | tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPDEN); 389 | 390 | (void)(tmpreg); 391 | 392 | /* --------------- SRAM Data lines, NOE and NWE configuration ---------------*/ 393 | /*---------------- SRAM Address lines configuration -------------------------*/ 394 | /*---------------- NOE and NWE configuration --------------------------------*/ 395 | /*---------------- NE3 configuration ----------------------------------------*/ 396 | /*---------------- NBL0, NBL1 configuration ---------------------------------*/ 397 | 398 | GPIOD->CRL = 0x44BB44BBU; 399 | GPIOD->CRH = 0xBBBBBBBBU; 400 | 401 | GPIOE->CRL = 0xB44444BBU; 402 | GPIOE->CRH = 0xBBBBBBBBU; 403 | 404 | GPIOF->CRL = 0x44BBBBBBU; 405 | GPIOF->CRH = 0xBBBB4444U; 406 | 407 | GPIOG->CRL = 0x44BBBBBBU; 408 | GPIOG->CRH = 0x444B4B44U; 409 | 410 | /*---------------- FSMC Configuration ---------------------------------------*/ 411 | /*---------------- Enable FSMC Bank1_SRAM Bank ------------------------------*/ 412 | 413 | FSMC_Bank1->BTCR[4U] = 0x00001091U; 414 | FSMC_Bank1->BTCR[5U] = 0x00110212U; 415 | } 416 | #endif /* DATA_IN_ExtSRAM */ 417 | #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ 418 | 419 | /** 420 | * @} 421 | */ 422 | 423 | /** 424 | * @} 425 | */ 426 | 427 | /** 428 | * @} 429 | */ 430 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 431 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/Src/usart.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * File Name : USART.c 4 | * Description : This file provides code for the configuration 5 | * of the USART instances. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Includes ------------------------------------------------------------------*/ 21 | #include "usart.h" 22 | 23 | /* USER CODE BEGIN 0 */ 24 | 25 | /* USER CODE END 0 */ 26 | 27 | UART_HandleTypeDef huart2; 28 | DMA_HandleTypeDef hdma_usart2_rx; 29 | 30 | /* USART2 init function */ 31 | 32 | void MX_USART2_UART_Init(void) 33 | { 34 | 35 | huart2.Instance = USART2; 36 | huart2.Init.BaudRate = 1000000; 37 | huart2.Init.WordLength = UART_WORDLENGTH_8B; 38 | huart2.Init.StopBits = UART_STOPBITS_1; 39 | huart2.Init.Parity = UART_PARITY_NONE; 40 | huart2.Init.Mode = UART_MODE_TX_RX; 41 | huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; 42 | huart2.Init.OverSampling = UART_OVERSAMPLING_16; 43 | if (HAL_UART_Init(&huart2) != HAL_OK) 44 | { 45 | Error_Handler(); 46 | } 47 | 48 | } 49 | 50 | void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) 51 | { 52 | 53 | GPIO_InitTypeDef GPIO_InitStruct = {0}; 54 | if(uartHandle->Instance==USART2) 55 | { 56 | /* USER CODE BEGIN USART2_MspInit 0 */ 57 | 58 | /* USER CODE END USART2_MspInit 0 */ 59 | /* USART2 clock enable */ 60 | __HAL_RCC_USART2_CLK_ENABLE(); 61 | 62 | __HAL_RCC_GPIOA_CLK_ENABLE(); 63 | /**USART2 GPIO Configuration 64 | PA2 ------> USART2_TX 65 | PA3 ------> USART2_RX 66 | */ 67 | GPIO_InitStruct.Pin = GPIO_PIN_2; 68 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 69 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; 70 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 71 | 72 | GPIO_InitStruct.Pin = GPIO_PIN_3; 73 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 74 | GPIO_InitStruct.Pull = GPIO_NOPULL; 75 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 76 | 77 | /* USART2 DMA Init */ 78 | /* USART2_RX Init */ 79 | hdma_usart2_rx.Instance = DMA1_Channel6; 80 | hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 81 | hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE; 82 | hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE; 83 | hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; 84 | hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; 85 | hdma_usart2_rx.Init.Mode = DMA_NORMAL; 86 | hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW; 87 | if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK) 88 | { 89 | Error_Handler(); 90 | } 91 | 92 | __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx); 93 | 94 | /* USER CODE BEGIN USART2_MspInit 1 */ 95 | 96 | /* USER CODE END USART2_MspInit 1 */ 97 | } 98 | } 99 | 100 | void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) 101 | { 102 | 103 | if(uartHandle->Instance==USART2) 104 | { 105 | /* USER CODE BEGIN USART2_MspDeInit 0 */ 106 | 107 | /* USER CODE END USART2_MspDeInit 0 */ 108 | /* Peripheral clock disable */ 109 | __HAL_RCC_USART2_CLK_DISABLE(); 110 | 111 | /**USART2 GPIO Configuration 112 | PA2 ------> USART2_TX 113 | PA3 ------> USART2_RX 114 | */ 115 | HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); 116 | 117 | /* USART2 DMA DeInit */ 118 | HAL_DMA_DeInit(uartHandle->hdmarx); 119 | /* USER CODE BEGIN USART2_MspDeInit 1 */ 120 | 121 | /* USER CODE END USART2_MspDeInit 1 */ 122 | } 123 | } 124 | 125 | /* USER CODE BEGIN 1 */ 126 | 127 | /* USER CODE END 1 */ 128 | 129 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 130 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/readme.txt: -------------------------------------------------------------------------------- 1 | This file include some source code. 2 | The whole project please download OLED_imageShow.7z 3 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/ssd1306/ssd1306.c: -------------------------------------------------------------------------------- 1 | #include "ssd1306.h" 2 | 3 | #if defined(SSD1306_USE_I2C) 4 | 5 | void ssd1306_Reset(void) { 6 | /* for I2C - do nothing */ 7 | } 8 | 9 | // Send a byte to the command register 10 | void ssd1306_WriteCommand(uint8_t byte) { 11 | HAL_I2C_Mem_Write(&SSD1306_I2C_PORT, SSD1306_I2C_ADDR, 0x00, 1, &byte, 1, HAL_MAX_DELAY); 12 | } 13 | 14 | // Send data 15 | void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) { 16 | HAL_I2C_Mem_Write(&SSD1306_I2C_PORT, SSD1306_I2C_ADDR, 0x40, 1, buffer, buff_size, HAL_MAX_DELAY); 17 | } 18 | 19 | void ssd1306_WriteDataDMA(uint8_t* buffer, size_t buff_size) { 20 | HAL_I2C_Mem_Write_DMA(&SSD1306_I2C_PORT, SSD1306_I2C_ADDR, 0x40, 1, buffer, buff_size); 21 | } 22 | 23 | #elif defined(SSD1306_USE_SPI) 24 | 25 | void ssd1306_Reset(void) { 26 | // CS = High (not selected) 27 | HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); 28 | 29 | // Reset the OLED 30 | HAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_RESET); 31 | HAL_Delay(10); 32 | HAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_SET); 33 | HAL_Delay(10); 34 | } 35 | 36 | // Send a byte to the command register 37 | void ssd1306_WriteCommand(uint8_t byte) { 38 | HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLED 39 | HAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_RESET); // command 40 | HAL_SPI_Transmit(&SSD1306_SPI_PORT, (uint8_t *) &byte, 1, HAL_MAX_DELAY); 41 | HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED 42 | } 43 | 44 | // Send data 45 | void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) { 46 | HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLED 47 | HAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_SET); // data 48 | HAL_SPI_Transmit(&SSD1306_SPI_PORT, buffer, buff_size, HAL_MAX_DELAY); 49 | HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED 50 | } 51 | 52 | #else 53 | #error "You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro" 54 | #endif 55 | 56 | 57 | // Screenbuffer 58 | static uint8_t SSD1306_Buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8]; 59 | 60 | // Screen object 61 | static SSD1306_t SSD1306; 62 | 63 | // Initialize the oled screen 64 | void ssd1306_Init(void) { 65 | // Reset OLED 66 | ssd1306_Reset(); 67 | 68 | // Wait for the screen to boot 69 | HAL_Delay(100); 70 | 71 | // Init OLED 72 | ssd1306_WriteCommand(0xAE); //display off 73 | 74 | ssd1306_WriteCommand(0x20); //Set Memory Addressing Mode 75 | ssd1306_WriteCommand(0x00); // 00b,Horizontal Addressing Mode; 01b,Vertical Addressing Mode; 76 | // 10b,Page Addressing Mode (RESET); 11b,Invalid 77 | 78 | ssd1306_WriteCommand(0xB0); //Set Page Start Address for Page Addressing Mode,0-7 79 | 80 | #ifdef SSD1306_MIRROR_VERT 81 | ssd1306_WriteCommand(0xC0); // Mirror vertically 82 | #else 83 | ssd1306_WriteCommand(0xC8); //Set COM Output Scan Direction 84 | #endif 85 | 86 | ssd1306_WriteCommand(0x00); //---set low column address 87 | ssd1306_WriteCommand(0x10); //---set high column address 88 | 89 | ssd1306_WriteCommand(0x40); //--set start line address - CHECK 90 | 91 | ssd1306_WriteCommand(0x81); //--set contrast control register - CHECK 92 | ssd1306_WriteCommand(0xFF); 93 | 94 | #ifdef SSD1306_MIRROR_HORIZ 95 | ssd1306_WriteCommand(0xA0); // Mirror horizontally 96 | #else 97 | ssd1306_WriteCommand(0xA1); //--set segment re-map 0 to 127 - CHECK 98 | #endif 99 | 100 | #ifdef SSD1306_INVERSE_COLOR 101 | ssd1306_WriteCommand(0xA7); //--set inverse color 102 | #else 103 | ssd1306_WriteCommand(0xA6); //--set normal color 104 | #endif 105 | 106 | ssd1306_WriteCommand(0xA8); //--set multiplex ratio(1 to 64) - CHECK 107 | ssd1306_WriteCommand(0x3F); // 108 | 109 | ssd1306_WriteCommand(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content 110 | 111 | ssd1306_WriteCommand(0xD3); //-set display offset - CHECK 112 | ssd1306_WriteCommand(0x00); //-not offset 113 | 114 | ssd1306_WriteCommand(0xD5); //--set display clock divide ratio/oscillator frequency 115 | ssd1306_WriteCommand(0xF0); //--set divide ratio 116 | 117 | ssd1306_WriteCommand(0xD9); //--set pre-charge period 118 | ssd1306_WriteCommand(0x22); // 119 | 120 | ssd1306_WriteCommand(0xDA); //--set com pins hardware configuration - CHECK 121 | ssd1306_WriteCommand(0x12); 122 | 123 | ssd1306_WriteCommand(0xDB); //--set vcomh 124 | ssd1306_WriteCommand(0x20); //0x20,0.77xVcc 125 | 126 | ssd1306_WriteCommand(0x8D); //--set DC-DC enable 127 | ssd1306_WriteCommand(0x14); // 128 | ssd1306_WriteCommand(0xAF); //--turn on SSD1306 panel 129 | 130 | // Clear screen 131 | ssd1306_Fill(Black); 132 | 133 | // Flush buffer to screen 134 | ssd1306_UpdateScreen(); 135 | 136 | // Set default values for screen object 137 | SSD1306.CurrentX = 0; 138 | SSD1306.CurrentY = 0; 139 | 140 | SSD1306.Initialized = 1; 141 | } 142 | 143 | // Fill the whole screen with the given color 144 | void ssd1306_Fill(SSD1306_COLOR color) { 145 | /* Set memory */ 146 | uint32_t i; 147 | 148 | for(i = 0; i < sizeof(SSD1306_Buffer); i++) { 149 | SSD1306_Buffer[i] = (color == Black) ? 0x00 : 0xFF; 150 | } 151 | } 152 | 153 | // Write the screenbuffer with changed to the screen 154 | void ssd1306_UpdateScreen(void) { 155 | uint8_t i; 156 | for(i = 0; i < 8; i++) { 157 | ssd1306_WriteCommand(0xB0 + i); 158 | ssd1306_WriteCommand(0x00); 159 | ssd1306_WriteCommand(0x10); 160 | ssd1306_WriteData(&SSD1306_Buffer[SSD1306_WIDTH*i],SSD1306_WIDTH); 161 | } 162 | } 163 | 164 | // Write the screenbuffer with user defined buffer 165 | void ssd1306_UpdateScreenWithBuffer(uint8_t *buffer) 166 | { 167 | ssd1306_WriteCommand(0x21); 168 | ssd1306_WriteCommand(0x00); 169 | ssd1306_WriteCommand(0x7f); 170 | 171 | ssd1306_WriteCommand(0x22); 172 | ssd1306_WriteCommand(0x00); 173 | ssd1306_WriteCommand(0x07); 174 | 175 | ssd1306_WriteData(buffer, SSD1306_WIDTH*SSD1306_HEIGHT/8); 176 | } 177 | 178 | // Draw one pixel in the screenbuffer 179 | // X => X Coordinate 180 | // Y => Y Coordinate 181 | // color => Pixel color 182 | void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color) { 183 | if(x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT) { 184 | // Don't write outside the buffer 185 | return; 186 | } 187 | 188 | // Check if pixel should be inverted 189 | if(SSD1306.Inverted) { 190 | color = (SSD1306_COLOR)!color; 191 | } 192 | 193 | // Draw in the right color 194 | if(color == White) { 195 | SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8); 196 | } else { 197 | SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8)); 198 | } 199 | } 200 | 201 | // Draw 1 char to the screen buffer 202 | // ch => char om weg te schrijven 203 | // Font => Font waarmee we gaan schrijven 204 | // color => Black or White 205 | char ssd1306_WriteChar(char ch, FontDef Font, SSD1306_COLOR color) { 206 | uint32_t i, b, j; 207 | 208 | // Check if character is valid 209 | if (ch < 32 || ch > 126) 210 | return 0; 211 | 212 | // Check remaining space on current line 213 | if (SSD1306_WIDTH < (SSD1306.CurrentX + Font.FontWidth) || 214 | SSD1306_HEIGHT < (SSD1306.CurrentY + Font.FontHeight)) 215 | { 216 | // Not enough space on current line 217 | return 0; 218 | } 219 | 220 | // Use the font to write 221 | for(i = 0; i < Font.FontHeight; i++) { 222 | b = Font.data[(ch - 32) * Font.FontHeight + i]; 223 | for(j = 0; j < Font.FontWidth; j++) { 224 | if((b << j) & 0x8000) { 225 | ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) color); 226 | } else { 227 | ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR)!color); 228 | } 229 | } 230 | } 231 | 232 | // The current space is now taken 233 | SSD1306.CurrentX += Font.FontWidth; 234 | 235 | // Return written char for validation 236 | return ch; 237 | } 238 | 239 | // Write full string to screenbuffer 240 | char ssd1306_WriteString(char* str, FontDef Font, SSD1306_COLOR color) { 241 | // Write until null-byte 242 | while (*str) { 243 | if (ssd1306_WriteChar(*str, Font, color) != *str) { 244 | // Char could not be written 245 | return *str; 246 | } 247 | 248 | // Next char 249 | str++; 250 | } 251 | 252 | // Everything ok 253 | return *str; 254 | } 255 | 256 | // Position the cursor 257 | void ssd1306_SetCursor(uint8_t x, uint8_t y) { 258 | SSD1306.CurrentX = x; 259 | SSD1306.CurrentY = y; 260 | } 261 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/ssd1306/ssd1306.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This Library was originally written by Olivier Van den Eede (4ilo) in 2016. 3 | * Some refactoring was done and SPI support was added by Aleksander Alekseev (afiskon) in 2018. 4 | * 5 | * https://github.com/afiskon/stm32-ssd1306 6 | */ 7 | 8 | #ifndef __SSD1306_H__ 9 | #define __SSD1306_H__ 10 | 11 | #include 12 | 13 | #if defined(STM32F1) 14 | #include "stm32f1xx_hal.h" 15 | #elif defined(STM32F4) 16 | #include "stm32f4xx_hal.h" 17 | #elif defined(STM32L0) 18 | #include "stm32l0xx_hal.h" 19 | #elif defined(STM32L4) 20 | #include "stm32l4xx_hal.h" 21 | #elif defined(STM32F3) 22 | #include "stm32f3xx_hal.h" 23 | #elif defined(STM32H7) 24 | #include "stm32h7xx_hal.h" 25 | #else 26 | #error "SSD1306 library was tested only on STM32F1, STM32F3, STM32F4, STM32L0, STM32L4, STM32H7 MCU families. Please modify ssd1306.h if you know what you are doing. Also please send a pull request if it turns out the library works on other MCU's as well!" 27 | #endif 28 | 29 | #include "ssd1306_fonts.h" 30 | 31 | /* vvv I2C config vvv */ 32 | 33 | #ifndef SSD1306_I2C_PORT 34 | #define SSD1306_I2C_PORT hi2c1 35 | #endif 36 | 37 | #ifndef SSD1306_I2C_ADDR 38 | #define SSD1306_I2C_ADDR (0x3C << 1) 39 | #endif 40 | 41 | /* ^^^ I2C config ^^^ */ 42 | 43 | /* vvv SPI config vvv */ 44 | 45 | #ifndef SSD1306_SPI_PORT 46 | #define SSD1306_SPI_PORT hspi2 47 | #endif 48 | 49 | #ifndef SSD1306_CS_Port 50 | #define SSD1306_CS_Port GPIOB 51 | #endif 52 | #ifndef SSD1306_CS_Pin 53 | #define SSD1306_CS_Pin GPIO_PIN_12 54 | #endif 55 | 56 | #ifndef SSD1306_DC_Port 57 | #define SSD1306_DC_Port GPIOB 58 | #endif 59 | #ifndef SSD1306_DC_Pin 60 | #define SSD1306_DC_Pin GPIO_PIN_14 61 | #endif 62 | 63 | #ifndef SSD1306_Reset_Port 64 | #define SSD1306_Reset_Port GPIOA 65 | #endif 66 | #ifndef SSD1306_Reset_Pin 67 | #define SSD1306_Reset_Pin GPIO_PIN_8 68 | #endif 69 | 70 | /* ^^^ SPI config ^^^ */ 71 | 72 | #if defined(SSD1306_USE_I2C) 73 | extern I2C_HandleTypeDef SSD1306_I2C_PORT; 74 | #elif defined(SSD1306_USE_SPI) 75 | extern SPI_HandleTypeDef SSD1306_SPI_PORT; 76 | #else 77 | #error "You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro!" 78 | #endif 79 | 80 | // SSD1306 OLED height in pixels 81 | #ifndef SSD1306_HEIGHT 82 | #define SSD1306_HEIGHT 64 83 | #endif 84 | 85 | // SSD1306 width in pixels 86 | #ifndef SSD1306_WIDTH 87 | #define SSD1306_WIDTH 128 88 | #endif 89 | 90 | // some LEDs don't display anything in first two columns 91 | // #define SSD1306_WIDTH 130 92 | 93 | // Enumeration for screen colors 94 | typedef enum { 95 | Black = 0x00, // Black color, no pixel 96 | White = 0x01 // Pixel is set. Color depends on OLED 97 | } SSD1306_COLOR; 98 | 99 | // Struct to store transformations 100 | typedef struct { 101 | uint16_t CurrentX; 102 | uint16_t CurrentY; 103 | uint8_t Inverted; 104 | uint8_t Initialized; 105 | } SSD1306_t; 106 | 107 | // Procedure definitions 108 | void ssd1306_Init(void); 109 | void ssd1306_Fill(SSD1306_COLOR color); 110 | void ssd1306_UpdateScreen(void); 111 | void ssd1306_UpdateScreenWithBuffer(uint8_t *buffer); 112 | void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color); 113 | char ssd1306_WriteChar(char ch, FontDef Font, SSD1306_COLOR color); 114 | char ssd1306_WriteString(char* str, FontDef Font, SSD1306_COLOR color); 115 | void ssd1306_SetCursor(uint8_t x, uint8_t y); 116 | 117 | // Low-level procedures 118 | void ssd1306_Reset(void); 119 | void ssd1306_WriteCommand(uint8_t byte); 120 | void ssd1306_WriteData(uint8_t* buffer, size_t buff_size); 121 | void ssd1306_WriteDataDMA(uint8_t* buffer, size_t buff_size); 122 | 123 | #endif // __SSD1306_H__ 124 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/ssd1306/ssd1306_fonts.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef __SSD1306_FONTS_H__ 4 | #define __SSD1306_FONTS_H__ 5 | 6 | typedef struct { 7 | const uint8_t FontWidth; /*!< Font width in pixels */ 8 | uint8_t FontHeight; /*!< Font height in pixels */ 9 | const uint16_t *data; /*!< Pointer to data font data array */ 10 | } FontDef; 11 | 12 | 13 | extern FontDef Font_6x8; 14 | extern FontDef Font_7x10; 15 | extern FontDef Font_11x18; 16 | extern FontDef Font_16x26; 17 | 18 | #endif // __SSD1306_FONTS_H__ 19 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/ssd1306/ssd1306_tests.c: -------------------------------------------------------------------------------- 1 | #include "ssd1306.h" 2 | #include 3 | #include 4 | 5 | void ssd1306_TestBorder() { 6 | ssd1306_Fill(Black); 7 | 8 | uint32_t start = HAL_GetTick(); 9 | uint32_t end = start; 10 | uint8_t x = 0; 11 | uint8_t y = 0; 12 | do { 13 | ssd1306_DrawPixel(x, y, Black); 14 | 15 | if((y == 0) && (x < 127)) 16 | x++; 17 | else if((x == 127) && (y < 63)) 18 | y++; 19 | else if((y == 63) && (x > 0)) 20 | x--; 21 | else 22 | y--; 23 | 24 | ssd1306_DrawPixel(x, y, White); 25 | ssd1306_UpdateScreen(); 26 | 27 | //HAL_Delay(5); 28 | end = HAL_GetTick(); 29 | } while((end - start) < 8000); 30 | 31 | HAL_Delay(1000); 32 | } 33 | 34 | void ssd1306_TestFonts() { 35 | ssd1306_Fill(Black); 36 | ssd1306_SetCursor(2, 0); 37 | ssd1306_WriteString("Font 16x26", Font_16x26, White); 38 | ssd1306_SetCursor(2, 26); 39 | ssd1306_WriteString("Font 11x18", Font_11x18, White); 40 | ssd1306_SetCursor(2, 26+18); 41 | ssd1306_WriteString("Font 7x10", Font_7x10, White); 42 | ssd1306_SetCursor(2, 26+18+10); 43 | ssd1306_WriteString("Font 6x8", Font_6x8, White); 44 | ssd1306_UpdateScreen(); 45 | } 46 | 47 | void ssd1306_TestFPS() { 48 | ssd1306_Fill(White); 49 | 50 | uint32_t start = HAL_GetTick(); 51 | uint32_t end = start; 52 | int fps = 0; 53 | char message[] = "ABCDEFGHIJK"; 54 | 55 | ssd1306_SetCursor(2,0); 56 | ssd1306_WriteString("Testing...", Font_11x18, Black); 57 | 58 | do { 59 | ssd1306_SetCursor(2, 18); 60 | ssd1306_WriteString(message, Font_11x18, Black); 61 | ssd1306_UpdateScreen(); 62 | 63 | char ch = message[0]; 64 | memmove(message, message+1, sizeof(message)-2); 65 | message[sizeof(message)-2] = ch; 66 | 67 | fps++; 68 | end = HAL_GetTick(); 69 | } while((end - start) < 5000); 70 | 71 | HAL_Delay(1000); 72 | 73 | char buff[64]; 74 | fps = (float)fps / ((end - start) / 1000.0); 75 | snprintf(buff, sizeof(buff), "~%d FPS", fps); 76 | 77 | ssd1306_Fill(White); 78 | ssd1306_SetCursor(2, 18); 79 | ssd1306_WriteString(buff, Font_11x18, Black); 80 | ssd1306_UpdateScreen(); 81 | } 82 | 83 | void ssd1306_TestAll() { 84 | ssd1306_Init(); 85 | ssd1306_TestFPS(); 86 | HAL_Delay(3000); 87 | ssd1306_TestBorder(); 88 | ssd1306_TestFonts(); 89 | } 90 | -------------------------------------------------------------------------------- /mcu_prj/OLED_imageShow/ssd1306/ssd1306_tests.h: -------------------------------------------------------------------------------- 1 | #ifndef __SSD1306_TEST_H__ 2 | #define __SSD1306_TEST_H__ 3 | 4 | void ssd1306_TestBorder(); 5 | void ssd1306_TestFonts(); 6 | void ssd1306_TestFPS(); 7 | void ssd1306_TestAll(); 8 | 9 | #endif // __SSD1306_TEST_H__ 10 | -------------------------------------------------------------------------------- /mcu_prj/README.md: -------------------------------------------------------------------------------- 1 | # OLED_imageShow 2 | > folder include some main source code. 3 | 4 | # OLED_imageShow.7z 5 | > include all the project files. 6 | 7 | # OLED_imageShow.bin 8 | > is the img that could download to your MCU directly, if you don't need the source code. 9 | -------------------------------------------------------------------------------- /python_gui/UI/TextViewer.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'TextViewer.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.13.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | 10 | from PyQt5 import QtCore, QtGui, QtWidgets 11 | 12 | 13 | class Ui_Dialog_TextViewer(object): 14 | def setupUi(self, Dialog_TextViewer): 15 | Dialog_TextViewer.setObjectName("Dialog_TextViewer") 16 | Dialog_TextViewer.resize(554, 699) 17 | self.buttonBox = QtWidgets.QDialogButtonBox(Dialog_TextViewer) 18 | self.buttonBox.setGeometry(QtCore.QRect(20, 630, 521, 41)) 19 | self.buttonBox.setOrientation(QtCore.Qt.Horizontal) 20 | self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) 21 | self.buttonBox.setObjectName("buttonBox") 22 | self.textBrowser_OutputCArray = QtWidgets.QTextBrowser(Dialog_TextViewer) 23 | self.textBrowser_OutputCArray.setGeometry(QtCore.QRect(10, 10, 531, 611)) 24 | self.textBrowser_OutputCArray.setObjectName("textBrowser_OutputCArray") 25 | 26 | self.retranslateUi(Dialog_TextViewer) 27 | self.buttonBox.accepted.connect(Dialog_TextViewer.accept) 28 | self.buttonBox.rejected.connect(Dialog_TextViewer.reject) 29 | QtCore.QMetaObject.connectSlotsByName(Dialog_TextViewer) 30 | 31 | def retranslateUi(self, Dialog_TextViewer): 32 | _translate = QtCore.QCoreApplication.translate 33 | Dialog_TextViewer.setWindowTitle(_translate("Dialog_TextViewer", "Text Viewer")) 34 | -------------------------------------------------------------------------------- /python_gui/UI/TextViewer.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog_TextViewer 4 | 5 | 6 | 7 | 0 8 | 0 9 | 603 10 | 694 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Text Viewer 21 | 22 | 23 | 24 | 25 | 20 26 | 630 27 | 521 28 | 41 29 | 30 | 31 | 32 | Qt::Horizontal 33 | 34 | 35 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 36 | 37 | 38 | 39 | 40 | 41 | 10 42 | 9 43 | 581 44 | 611 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 579 53 | 0 54 | 55 | 56 | 57 | Qt::ScrollBarAlwaysOn 58 | 59 | 60 | QTextEdit::NoWrap 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | buttonBox 71 | accepted() 72 | Dialog_TextViewer 73 | accept() 74 | 75 | 76 | 238 77 | 644 78 | 79 | 80 | 157 81 | 274 82 | 83 | 84 | 85 | 86 | buttonBox 87 | rejected() 88 | Dialog_TextViewer 89 | reject() 90 | 91 | 92 | 306 93 | 650 94 | 95 | 96 | 286 97 | 274 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /python_gui/UI/basic_ui.py: -------------------------------------------------------------------------------- 1 | 2 | from PyQt5 import QtCore, QtWidgets 3 | 4 | class Ui_Form(object): 5 | def setupUi(self, Form): 6 | Form.setObjectName("Form") 7 | self.pushButton = QtWidgets.QPushButton(Form) 8 | self.pushButton.setGeometry(QtCore.QRect(460, 330, 93, 28)) 9 | self.pushButton.setObjectName("pushButton") 10 | 11 | self.retranslateUi(Form) 12 | self.pushButton.clicked.connect(self.button_click) 13 | QtCore.QMetaObject.connectSlotsByName(Form) 14 | 15 | def retranslateUi(self, Form): 16 | _translate = QtCore.QCoreApplication.translate 17 | Form.setWindowTitle(_translate("Form", "Form")) 18 | self.pushButton.setText(_translate("Form", "PushButton")) 19 | 20 | def button_click(self): 21 | print('Push button clicked!') 22 | 23 | 24 | if __name__ == "__main__": 25 | from PyQt5.QtWidgets import QApplication, QWidget 26 | import sys 27 | 28 | # Make a Qt Framework 29 | app = QApplication(sys.argv) 30 | 31 | # Make a from 32 | w = QWidget() 33 | 34 | # add item 35 | ui = Ui_Form() 36 | ui.setupUi(w) 37 | 38 | # Show a form 39 | w.show() 40 | 41 | # run Framework and wait for exit 42 | app.exec_() 43 | 44 | -------------------------------------------------------------------------------- /python_gui/UI/basic_ui.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Form 4 | 5 | 6 | 7 | 0 8 | 0 9 | 601 10 | 401 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 460 20 | 330 21 | 93 22 | 28 23 | 24 | 25 | 26 | PushButton 27 | 28 | 29 | 30 | 31 | 32 | 33 | pushButton 34 | clicked() 35 | Form 36 | close() 37 | 38 | 39 | 535 40 | 348 41 | 42 | 43 | 572 44 | 353 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /python_gui/UI/image_export_ui.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'image_export_ui.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.13.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtWidgets 10 | 11 | class Ui_imageExportWindow(object): 12 | def setupUi(self, imageExportWindow): 13 | imageExportWindow.setObjectName("imageExportWindow") 14 | imageExportWindow.resize(800, 400) 15 | self.widget = QtWidgets.QWidget(imageExportWindow) 16 | self.widget.setGeometry(QtCore.QRect(0, 0, 800, 400)) 17 | self.widget.setObjectName("widget") 18 | self.verticalLayout = QtWidgets.QVBoxLayout(self.widget) 19 | self.verticalLayout.setContentsMargins(0, 0, 0, 0) 20 | self.verticalLayout.setObjectName("verticalLayout") 21 | self.textEdit_eportEditor = QtWidgets.QTextEdit(self.widget) 22 | self.textEdit_eportEditor.setObjectName("textEdit_eportEditor") 23 | self.verticalLayout.addWidget(self.textEdit_eportEditor) 24 | 25 | self.retranslateUi(imageExportWindow) 26 | QtCore.QMetaObject.connectSlotsByName(imageExportWindow) 27 | 28 | def retranslateUi(self, imageExportWindow): 29 | _translate = QtCore.QCoreApplication.translate 30 | imageExportWindow.setWindowTitle(_translate("imageExportWindow", "Export Window")) 31 | -------------------------------------------------------------------------------- /python_gui/UI/image_export_ui.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | imageExportWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 800 10 | 400 11 | 12 | 13 | 14 | Export Window 15 | 16 | 17 | 18 | 19 | 0 20 | 0 21 | 800 22 | 400 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /python_gui/UI/imgeModeWindow.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'imgeModeWindow.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.13.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | 10 | from PyQt5 import QtCore, QtGui, QtWidgets 11 | 12 | 13 | class Ui_Form(object): 14 | def setupUi(self, Form): 15 | Form.setObjectName("Form") 16 | Form.setEnabled(True) 17 | Form.resize(875, 695) 18 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 19 | sizePolicy.setHorizontalStretch(0) 20 | sizePolicy.setVerticalStretch(0) 21 | sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth()) 22 | Form.setSizePolicy(sizePolicy) 23 | self.groupBox = QtWidgets.QGroupBox(Form) 24 | self.groupBox.setGeometry(QtCore.QRect(350, 20, 511, 411)) 25 | self.groupBox.setObjectName("groupBox") 26 | self.horizontalLayoutWidget = QtWidgets.QWidget(self.groupBox) 27 | self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 20, 481, 41)) 28 | self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") 29 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget) 30 | self.horizontalLayout.setContentsMargins(0, 0, 0, 0) 31 | self.horizontalLayout.setObjectName("horizontalLayout") 32 | self.radioButton_ImagePreviewRaw = QtWidgets.QRadioButton(self.horizontalLayoutWidget) 33 | self.radioButton_ImagePreviewRaw.setObjectName("radioButton_ImagePreviewRaw") 34 | self.horizontalLayout.addWidget(self.radioButton_ImagePreviewRaw) 35 | self.radioButton_ImagePreviewGray = QtWidgets.QRadioButton(self.horizontalLayoutWidget) 36 | self.radioButton_ImagePreviewGray.setObjectName("radioButton_ImagePreviewGray") 37 | self.horizontalLayout.addWidget(self.radioButton_ImagePreviewGray) 38 | self.radioButton_ImagePreviewBW = QtWidgets.QRadioButton(self.horizontalLayoutWidget) 39 | self.radioButton_ImagePreviewBW.setObjectName("radioButton_ImagePreviewBW") 40 | self.horizontalLayout.addWidget(self.radioButton_ImagePreviewBW) 41 | self.label_ImagePreview = QtWidgets.QLabel(self.groupBox) 42 | self.label_ImagePreview.setGeometry(QtCore.QRect(10, 80, 480, 320)) 43 | self.label_ImagePreview.setFrameShape(QtWidgets.QFrame.Box) 44 | self.label_ImagePreview.setAlignment(QtCore.Qt.AlignCenter) 45 | self.label_ImagePreview.setObjectName("label_ImagePreview") 46 | self.groupBox_2 = QtWidgets.QGroupBox(Form) 47 | self.groupBox_2.setGeometry(QtCore.QRect(20, 20, 301, 211)) 48 | self.groupBox_2.setObjectName("groupBox_2") 49 | self.pushButton_OpenImage = QtWidgets.QPushButton(self.groupBox_2) 50 | self.pushButton_OpenImage.setGeometry(QtCore.QRect(20, 30, 251, 61)) 51 | self.pushButton_OpenImage.setObjectName("pushButton_OpenImage") 52 | self.textEdit_ShowImageName = QtWidgets.QTextEdit(self.groupBox_2) 53 | self.textEdit_ShowImageName.setGeometry(QtCore.QRect(20, 106, 251, 81)) 54 | self.textEdit_ShowImageName.setObjectName("textEdit_ShowImageName") 55 | self.groupBox_3 = QtWidgets.QGroupBox(Form) 56 | self.groupBox_3.setGeometry(QtCore.QRect(20, 250, 301, 261)) 57 | self.groupBox_3.setObjectName("groupBox_3") 58 | self.label_HistogramView = QtWidgets.QLabel(self.groupBox_3) 59 | self.label_HistogramView.setGeometry(QtCore.QRect(20, 30, 256, 128)) 60 | self.label_HistogramView.setFrameShape(QtWidgets.QFrame.Box) 61 | self.label_HistogramView.setAlignment(QtCore.Qt.AlignCenter) 62 | self.label_HistogramView.setObjectName("label_HistogramView") 63 | self.horizontalSlider_HistogramThresholdValue = QtWidgets.QSlider(self.groupBox_3) 64 | self.horizontalSlider_HistogramThresholdValue.setGeometry(QtCore.QRect(14, 160, 270, 21)) 65 | self.horizontalSlider_HistogramThresholdValue.setMinimum(1) 66 | self.horizontalSlider_HistogramThresholdValue.setMaximum(254) 67 | self.horizontalSlider_HistogramThresholdValue.setOrientation(QtCore.Qt.Horizontal) 68 | self.horizontalSlider_HistogramThresholdValue.setTickPosition(QtWidgets.QSlider.TicksAbove) 69 | self.horizontalSlider_HistogramThresholdValue.setObjectName("horizontalSlider_HistogramThresholdValue") 70 | self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.groupBox_3) 71 | self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(20, 190, 261, 51)) 72 | self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2") 73 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2) 74 | self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) 75 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 76 | self.label_3 = QtWidgets.QLabel(self.horizontalLayoutWidget_2) 77 | self.label_3.setObjectName("label_3") 78 | self.horizontalLayout_2.addWidget(self.label_3) 79 | self.spinBox_HistogramThresholdValue = QtWidgets.QSpinBox(self.horizontalLayoutWidget_2) 80 | self.spinBox_HistogramThresholdValue.setWrapping(True) 81 | self.spinBox_HistogramThresholdValue.setSuffix("") 82 | self.spinBox_HistogramThresholdValue.setMinimum(1) 83 | self.spinBox_HistogramThresholdValue.setMaximum(254) 84 | self.spinBox_HistogramThresholdValue.setStepType(QtWidgets.QAbstractSpinBox.DefaultStepType) 85 | self.spinBox_HistogramThresholdValue.setObjectName("spinBox_HistogramThresholdValue") 86 | self.horizontalLayout_2.addWidget(self.spinBox_HistogramThresholdValue) 87 | self.groupBox_4 = QtWidgets.QGroupBox(Form) 88 | self.groupBox_4.setGeometry(QtCore.QRect(350, 450, 511, 231)) 89 | self.groupBox_4.setObjectName("groupBox_4") 90 | self.label_OutputImagePreview = QtWidgets.QLabel(self.groupBox_4) 91 | self.label_OutputImagePreview.setGeometry(QtCore.QRect(40, 50, 256, 128)) 92 | self.label_OutputImagePreview.setFrameShape(QtWidgets.QFrame.Box) 93 | self.label_OutputImagePreview.setAlignment(QtCore.Qt.AlignCenter) 94 | self.label_OutputImagePreview.setObjectName("label_OutputImagePreview") 95 | self.checkBox_invertBW = QtWidgets.QCheckBox(self.groupBox_4) 96 | self.checkBox_invertBW.setGeometry(QtCore.QRect(320, 60, 101, 19)) 97 | self.checkBox_invertBW.setObjectName("checkBox_invertBW") 98 | self.groupBox_5 = QtWidgets.QGroupBox(Form) 99 | self.groupBox_5.setGeometry(QtCore.QRect(20, 530, 301, 151)) 100 | self.groupBox_5.setObjectName("groupBox_5") 101 | self.pushButton_OutputBWImageToCArray = QtWidgets.QPushButton(self.groupBox_5) 102 | self.pushButton_OutputBWImageToCArray.setGeometry(QtCore.QRect(30, 30, 231, 91)) 103 | self.pushButton_OutputBWImageToCArray.setObjectName("pushButton_OutputBWImageToCArray") 104 | 105 | self.retranslateUi(Form) 106 | QtCore.QMetaObject.connectSlotsByName(Form) 107 | 108 | def retranslateUi(self, Form): 109 | _translate = QtCore.QCoreApplication.translate 110 | Form.setWindowTitle(_translate("Form", "Image")) 111 | self.groupBox.setTitle(_translate("Form", "PreView Selection")) 112 | self.radioButton_ImagePreviewRaw.setText(_translate("Form", "Raw")) 113 | self.radioButton_ImagePreviewGray.setText(_translate("Form", "Gray")) 114 | self.radioButton_ImagePreviewBW.setText(_translate("Form", "BlackAndWhite")) 115 | self.label_ImagePreview.setText(_translate("Form", "

Image PreView

")) 116 | self.groupBox_2.setTitle(_translate("Form", "File Import")) 117 | self.pushButton_OpenImage.setText(_translate("Form", "Open Image")) 118 | self.groupBox_3.setTitle(_translate("Form", "Gray Histogram and BW threshold")) 119 | self.label_HistogramView.setText(_translate("Form", "

Histogram

")) 120 | self.label_3.setText(_translate("Form", "Threshold Value")) 121 | self.groupBox_4.setTitle(_translate("Form", "Output Image")) 122 | self.label_OutputImagePreview.setText(_translate("Form", "

Output Image

")) 123 | self.checkBox_invertBW.setText(_translate("Form", "Invert BW")) 124 | self.groupBox_5.setTitle(_translate("Form", "GroupBox")) 125 | self.pushButton_OutputBWImageToCArray.setText(_translate("Form", "Output BW image to C array")) 126 | -------------------------------------------------------------------------------- /python_gui/UI/imgeModeWindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Form 4 | 5 | 6 | true 7 | 8 | 9 | 10 | 0 11 | 0 12 | 875 13 | 695 14 | 15 | 16 | 17 | 18 | 0 19 | 0 20 | 21 | 22 | 23 | Image 24 | 25 | 26 | 27 | 28 | 350 29 | 20 30 | 511 31 | 411 32 | 33 | 34 | 35 | PreView Selection 36 | 37 | 38 | 39 | 40 | 10 41 | 20 42 | 481 43 | 41 44 | 45 | 46 | 47 | 48 | 49 | 50 | Raw 51 | 52 | 53 | 54 | 55 | 56 | 57 | Gray 58 | 59 | 60 | 61 | 62 | 63 | 64 | BlackAndWhite 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 10 74 | 80 75 | 480 76 | 320 77 | 78 | 79 | 80 | QFrame::Box 81 | 82 | 83 | <html><head/><body><p><span style=" font-size:16pt; font-weight:600;">Image PreView</span></p></body></html> 84 | 85 | 86 | Qt::AlignCenter 87 | 88 | 89 | 90 | 91 | 92 | 93 | 20 94 | 20 95 | 301 96 | 211 97 | 98 | 99 | 100 | File Import 101 | 102 | 103 | 104 | 105 | 20 106 | 30 107 | 251 108 | 61 109 | 110 | 111 | 112 | Open Image 113 | 114 | 115 | 116 | 117 | 118 | 20 119 | 106 120 | 251 121 | 81 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 20 130 | 250 131 | 301 132 | 261 133 | 134 | 135 | 136 | Gray Histogram and BW threshold 137 | 138 | 139 | 140 | 141 | 20 142 | 30 143 | 256 144 | 128 145 | 146 | 147 | 148 | QFrame::Box 149 | 150 | 151 | <html><head/><body><p><span style=" font-weight:600;">Histogram</span></p></body></html> 152 | 153 | 154 | Qt::AlignCenter 155 | 156 | 157 | 158 | 159 | 160 | 14 161 | 160 162 | 270 163 | 21 164 | 165 | 166 | 167 | 1 168 | 169 | 170 | 254 171 | 172 | 173 | Qt::Horizontal 174 | 175 | 176 | QSlider::TicksAbove 177 | 178 | 179 | 180 | 181 | 182 | 20 183 | 190 184 | 261 185 | 51 186 | 187 | 188 | 189 | 190 | 191 | 192 | Threshold Value 193 | 194 | 195 | 196 | 197 | 198 | 199 | true 200 | 201 | 202 | 203 | 204 | 205 | 1 206 | 207 | 208 | 254 209 | 210 | 211 | QAbstractSpinBox::DefaultStepType 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 350 222 | 450 223 | 511 224 | 231 225 | 226 | 227 | 228 | Output Image 229 | 230 | 231 | 232 | 233 | 40 234 | 50 235 | 256 236 | 128 237 | 238 | 239 | 240 | QFrame::Box 241 | 242 | 243 | <html><head/><body><p><span style=" font-weight:600;">Output Image</span></p></body></html> 244 | 245 | 246 | Qt::AlignCenter 247 | 248 | 249 | 250 | 251 | 252 | 320 253 | 60 254 | 101 255 | 19 256 | 257 | 258 | 259 | Invert BW 260 | 261 | 262 | 263 | 264 | 265 | 266 | 20 267 | 530 268 | 301 269 | 151 270 | 271 | 272 | 273 | GroupBox 274 | 275 | 276 | 277 | 278 | 30 279 | 30 280 | 231 281 | 91 282 | 283 | 284 | 285 | Output BW image to C array 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | -------------------------------------------------------------------------------- /python_gui/UI/screenSampleWindow.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'screenSampleWindow.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.13.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | 10 | from PyQt5 import QtCore, QtGui, QtWidgets 11 | 12 | 13 | class Ui_Form_screenSampleWindow(object): 14 | def setupUi(self, Form_screenSampleWindow): 15 | Form_screenSampleWindow.setObjectName("Form_screenSampleWindow") 16 | Form_screenSampleWindow.resize(256, 128) 17 | 18 | self.retranslateUi(Form_screenSampleWindow) 19 | QtCore.QMetaObject.connectSlotsByName(Form_screenSampleWindow) 20 | 21 | def retranslateUi(self, Form_screenSampleWindow): 22 | _translate = QtCore.QCoreApplication.translate 23 | Form_screenSampleWindow.setWindowTitle(_translate("Form_screenSampleWindow", "Form")) 24 | -------------------------------------------------------------------------------- /python_gui/UI/screenSampleWindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Form_screenSampleWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 256 10 | 128 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /python_gui/common/Singleton.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def Singleton(cls): 4 | """ 5 | Singleton class 6 | """ 7 | _instance = {} 8 | 9 | def _singleton(*args, **kargs): 10 | if cls not in _instance: 11 | _instance[cls] = cls(*args, **kargs) 12 | return _instance[cls] 13 | 14 | return _singleton -------------------------------------------------------------------------------- /python_gui/image_processing/BWImageToBytes.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | from common.Singleton import Singleton 4 | 5 | from ctypes import CDLL, c_uint8, c_int, Structure 6 | import platform 7 | 8 | @Singleton 9 | class BWImageToBytes(object): 10 | """ 11 | image_flip_h: True, False 12 | image_flip_v: True, False 13 | scan_dir: H, V 14 | byte_dir: H, V 15 | sign_bit: LSB, MSB 16 | """ 17 | def __init__(self, image_flip_h=False, image_flip_v=False, scan_dir='H', byte_dir='H', sign_bit='LSB'): 18 | self.image_flip_h = image_flip_h 19 | self.image_flip_v = image_flip_v 20 | self.scan_dir = scan_dir 21 | self.byte_dir = byte_dir 22 | self.sign_bit = sign_bit 23 | 24 | # init dll 25 | self.bw2bytes_config = self.BW2BYTES_CONFIG() 26 | self.update_bw_config() 27 | self.bw2bytes_func = None 28 | self.load_dll() 29 | 30 | class BW2BYTES_CONFIG(Structure): 31 | _fields_ = [ 32 | ("flip_h", c_int), 33 | ("flip_v", c_int), 34 | ("scan_dir", c_int), 35 | ("byte_dir", c_int), 36 | ("sign_bit", c_int)] 37 | 38 | def load_dll(self): 39 | if platform.architecture()[0] == "64bit": 40 | dll_lib = CDLL("./image_processing/image_processing_x64.dll") 41 | else: 42 | dll_lib = CDLL("./image_processing/image_processing.dll") 43 | self.bw2bytes_func = dll_lib.bw2Bytes 44 | 45 | # set args type 46 | self.bw2bytes_func.argtypes = [np.ctypeslib.ndpointer(c_uint8), 47 | np.ctypeslib.ndpointer(c_uint8, 1), 48 | c_int, 49 | c_int, 50 | self.BW2BYTES_CONFIG] 51 | self.bw2bytes_func.restype = c_int 52 | 53 | def update_bw_config(self): 54 | if self.image_flip_h == True: 55 | self.bw2bytes_config.flip_h = 1 56 | else: 57 | self.bw2bytes_config.flip_h = 0 58 | 59 | if self.image_flip_v == True: 60 | self.bw2bytes_config.flip_v = 1 61 | else: 62 | self.bw2bytes_config.flip_v = 0 63 | 64 | if self.scan_dir == 'H': 65 | self.bw2bytes_config.scan_dir = 0 66 | else: 67 | self.bw2bytes_config.scan_dir = 1 68 | 69 | if self.byte_dir == 'H': 70 | self.bw2bytes_config.byte_dir = 0 71 | else: 72 | self.bw2bytes_config.byte_dir = 1 73 | 74 | if self.sign_bit == 'MSB': 75 | self.bw2bytes_config.sign_bit = 0 76 | else: 77 | self.bw2bytes_config.sign_bit = 1 78 | 79 | def setHorizontalFlip(self, enable): 80 | if type(enable) is bool: 81 | self.image_flip_h = enable 82 | else: 83 | raise Exception('param: should be True/False !') 84 | 85 | def setVerticalFlip(self, enable): 86 | if type(enable) is bool: 87 | self.image_flip_v = enable 88 | else: 89 | raise Exception('param: should be True/False !') 90 | 91 | def setScanDirection(self, direction): 92 | if direction == 'H' or direction == 'h': 93 | self.scan_dir = 'H' 94 | elif direction == 'V' or direction == 'v': 95 | self.scan_dir = 'V' 96 | else: 97 | raise Exception('direction: should be H/v !') 98 | 99 | def setByteDirection(self, direction): 100 | if direction == 'H' or direction == 'h': 101 | self.byte_dir = 'H' 102 | elif direction == 'V' or direction == 'v': 103 | self.byte_dir = 'V' 104 | else: 105 | raise Exception('direction: should be H/v !') 106 | 107 | def setSignBit(self, sign_bit): 108 | if sign_bit == 'LSB': 109 | self.sign_bit = 'LSB' 110 | elif sign_bit == 'MSB': 111 | self.sign_bit = 'MSB' 112 | else: 113 | raise Exception('sign_bit: should be LSB/MSB !') 114 | 115 | def convert(self, image): 116 | """ 117 | :param image: numpy 2D BW image array 0-black, 1-light 118 | :return: numpy 1D array 119 | """ 120 | h, w = image.shape 121 | # update config 122 | self.update_bw_config() 123 | # malloc a new array 124 | data_bytes = np.zeros(h * w // 8, dtype='uint8') 125 | 126 | if self.bw2bytes_func(image.copy(), data_bytes, w, h, self.bw2bytes_config) != 0: 127 | return None 128 | else: 129 | return data_bytes 130 | 131 | # # force image data to 0 and 1 132 | # if image.max() > 1: 133 | # image = (image > 1) * np.uint8(1) 134 | # 135 | # if (self.byte_dir == 'H') and (w % 8 != 0): 136 | # raise Exception("Error: byte_dir not fit or image width not aligned with 8\n") 137 | # if (self.byte_dir == 'V') and (h % 8 != 0): 138 | # raise Exception("Error: byte_dir not fit or image height not aligned with 8\n") 139 | # 140 | # # step 1, flip 141 | # if self.image_flip_h: 142 | # image = image[:, ::-1] 143 | # 144 | # if self.image_flip_v: 145 | # image = image[::-1, :] 146 | # 147 | # # step 2, scan_dir and byte_dir 148 | # output_bytes = w * h // 8 149 | # new_image_array = np.zeros((output_bytes, 8), dtype='uint8') 150 | # 151 | # i = 0 152 | # if self.scan_dir == 'H': 153 | # if self.byte_dir == 'H': 154 | # for row in range(h): 155 | # for col in range(0, w, 8): 156 | # new_image_array[i, :] = image[row, col:col+8] 157 | # i += 1 158 | # else: 159 | # for row in range(0, h, 8): 160 | # for col in range(w): 161 | # new_image_array[i, :] = image[row:row+8, col] 162 | # i += 1 163 | # else: 164 | # if self.byte_dir == 'H': 165 | # for col in range(0, w, 8): 166 | # for row in range(h): 167 | # new_image_array[i, :] = image[row, col:col+8] 168 | # i += 1 169 | # else: 170 | # for col in range(w): 171 | # for row in range(0, h, 8): 172 | # new_image_array[i, :] = image[row:row+8, col] 173 | # i += 1 174 | # if i != output_bytes: 175 | # print('Error: sample bytes length error!\n') 176 | # 177 | # # step 3, sign_bit 178 | # if self.sign_bit == 'MSB': 179 | # new_image_array = new_image_array[:, ::-1] 180 | # elif self.sign_bit == 'LSB': 181 | # pass 182 | # else: 183 | # raise Exception('sign_bit setting must be LSB/MSB\n') 184 | # 185 | # # step 4, output to bytes 1D array 186 | # data_bytes = np.zeros(output_bytes, dtype='uint8') 187 | # for i in range(output_bytes): 188 | # bits = new_image_array[i, :] 189 | # bits_str = ''.join([str(x) for x in bits]) 190 | # data_bytes[i] = np.int(bits_str, 2) 191 | # 192 | # return data_bytes 193 | 194 | 195 | if __name__ == '__main__': 196 | image = np.zeros((64, 128), dtype='uint8') 197 | 198 | image[0, 0:8] = np.array([1, 1, 1, 1, 0, 0, 0, 0]) 199 | 200 | image_processor = BWImageToBytes(sign_bit='MSB', scan_dir='V', byte_dir='V') 201 | image_processor.set_sign_bit('1') 202 | image_processor.set_scan_dir('v') 203 | image_processor.set_byte_direction('v') 204 | 205 | result = image_processor.convert(image) 206 | 207 | print(result[0:2]) 208 | 209 | -------------------------------------------------------------------------------- /python_gui/image_processing/C_dll_source_code/build.bat: -------------------------------------------------------------------------------- 1 | ECHO using MinGW to build x86 dll 2 | gcc -shared -Os -s -o image_processing.dll image_processing.c 3 | copy ./image_processing.dll ./../image_processing.dll 4 | 5 | ECHO using MinGW-w64 to build x64 dll 6 | ECHO gcc -shared -Os -s -o image_processing_x64.dll image_processing.c 7 | ECHO copy ./image_processing_x64.dll ./../image_processing_x64.dll -------------------------------------------------------------------------------- /python_gui/image_processing/C_dll_source_code/image_processing.c: -------------------------------------------------------------------------------- 1 | 2 | #include "image_processing.h" 3 | 4 | #include 5 | 6 | // Macro 7 | #define XY(x, y, w) (x + (y) * w) 8 | #define ARRAY_GET_XY(pointer, x, y, w) (*(pointer + XY(x, y, w))) 9 | #define ARRAY_GET(pointer, i) (*(pointer + i)) 10 | 11 | // Dithering 12 | static const uint8_t bayer_metrix_4x4[4][4] = { 13 | {0, 12, 3, 15}, 14 | {8, 4, 11, 7}, 15 | {2, 14, 1, 13}, 16 | {10, 6, 9, 5} 17 | }; 18 | 19 | static const uint8_t bayer_metrix_8x8[8][8] = { 20 | { 0, 32, 8, 40, 2, 34, 10, 42}, 21 | {48, 16, 56, 24, 50, 18, 58, 26}, 22 | {12, 44, 4, 36, 14, 46, 6, 38}, 23 | {60, 28, 52, 20, 62, 30, 54, 22}, 24 | { 3, 35, 11, 43, 1, 33, 9, 41}, 25 | {51, 19, 59, 27, 49, 17, 57, 25}, 26 | {15, 47, 7, 39, 13, 45, 5, 37}, 27 | {63, 31, 55, 23, 61, 29, 53, 21} 28 | }; 29 | 30 | static const uint8_t bayer_metrix_16x16[16][16] = { 31 | { 0, 128, 32, 160, 8, 136, 40, 168, 2, 130, 34, 162, 10, 138, 42, 170}, 32 | {192, 64, 224, 96, 200, 72, 232, 104, 194, 66, 226, 98, 202, 74, 234, 106}, 33 | { 48, 176, 16, 144, 56, 184, 24, 152, 50, 178, 18, 146, 58, 186, 26, 154}, 34 | {240, 112, 208, 80, 248, 120, 216, 88, 242, 114, 210, 82, 250, 122, 218, 90}, 35 | { 12, 140, 44, 172, 4, 132, 36, 164, 14, 142, 46, 174, 6, 134, 38, 166}, 36 | {204, 76, 236, 108, 196, 68, 228, 100, 206, 78, 238, 110, 198, 70, 230, 102}, 37 | { 60, 188, 28, 156, 52, 180, 20, 148, 62, 190, 30, 158, 54, 182, 22, 150}, 38 | {252, 124, 220, 92, 244, 116, 212, 84, 254, 126, 222, 94, 246, 118, 214, 86}, 39 | { 3, 131, 35, 163, 11, 139, 43, 171, 1, 129, 33, 161, 9, 137, 41, 169}, 40 | {195, 67, 227, 99, 203, 75, 235, 107, 193, 65, 225, 97, 201, 73, 233, 105}, 41 | { 51, 179, 19, 147, 59, 187, 27, 155, 49, 177, 17, 145, 57, 185, 25, 153}, 42 | {243, 115, 211, 83, 251, 123, 219, 91, 241, 113, 209, 81, 249, 121, 217, 89}, 43 | { 15, 143, 47, 175, 7, 135, 39, 167, 13, 141, 45, 173, 5, 133, 37, 165}, 44 | {207, 79, 239, 111, 199, 71, 231, 103, 205, 77, 237, 109, 197, 69, 229, 101}, 45 | { 63, 191, 31, 159, 55, 183, 23, 151, 61, 189, 29, 157, 53, 181, 21, 149}, 46 | {255, 127, 223, 95, 247, 119, 215, 87, 253, 125, 221, 93, 245, 117, 213, 85} 47 | }; 48 | 49 | int dithering(uint8_t* image, int w, int h, int bayer_size) 50 | { 51 | uint8_t level_div = 256 / (bayer_size * bayer_size); 52 | int data_bytes = w * h; 53 | int N = bayer_size; 54 | 55 | uint8_t* bayer_p; 56 | 57 | // gray level to bayer matrix level 58 | for (int i = 0; i < data_bytes; i++) 59 | ARRAY_GET(image, i) /= level_div; 60 | 61 | // chose bayer matrix 62 | switch (bayer_size) 63 | { 64 | case 4: bayer_p = (uint8_t *)bayer_metrix_4x4; break; 65 | case 8: bayer_p = (uint8_t *)bayer_metrix_8x8; break; 66 | case 16: bayer_p = (uint8_t *)bayer_metrix_16x16; break; 67 | default: return -1; 68 | } 69 | 70 | // start dither process 71 | for (int y = 0; y < h; y++) 72 | { 73 | for (int x = 0; x < w; x++) 74 | { 75 | if (ARRAY_GET_XY(image, x, y, w) > ARRAY_GET_XY(bayer_p, x % N, y % N, N)) 76 | { 77 | ARRAY_GET_XY(image, x, y, w) = 255; 78 | } 79 | else 80 | { 81 | ARRAY_GET_XY(image, x, y, w) = 0; 82 | } 83 | } 84 | } 85 | 86 | return 0; 87 | } 88 | 89 | // Error diffusion 90 | int error_diffusion(uint8_t* image, int w, int h) 91 | { 92 | int old_v, new_v, error; 93 | int data_bytes = w * h; 94 | 95 | int* image_p = malloc(w * h * sizeof(int)); 96 | 97 | if (image_p == NULL) 98 | return -1; 99 | 100 | for (int i = 0; i < data_bytes; i++) 101 | { 102 | ARRAY_GET(image_p, i) = (int)ARRAY_GET(image, i); 103 | } 104 | 105 | for (int y = 0; y < h; y++) 106 | { 107 | for (int x = 0; x < w; x++) 108 | { 109 | old_v = ARRAY_GET_XY(image_p, x, y, w); 110 | new_v = (old_v > 127) ? 255 : 0; 111 | ARRAY_GET_XY(image_p, x, y, w) = new_v; 112 | error = old_v - new_v; 113 | 114 | if ((0 <= x + 1) && (x + 1 < w) && (0 <= y) && (y < h)) 115 | ARRAY_GET_XY(image_p, x + 1, y, w) += (error * 7 / 16); 116 | 117 | if ((0 <= x + 1) && (x + 1 < w) && (0 <= y + 1) && (y + 1 < h)) 118 | ARRAY_GET_XY(image_p, x + 1, y + 1, w) += (error * 1 / 16); 119 | 120 | if ((0 <= x) && (x < w) && (0 <= y + 1) && (y + 1 < h)) 121 | ARRAY_GET_XY(image_p, x, y + 1, w) += (error * 5 / 16); 122 | 123 | if ((0 <= x - 1) && (x - 1 < w) && (0 <= y + 1) && (y + 1 < h)) 124 | ARRAY_GET_XY(image_p, x - 1, y + 1, w) += (error * 3 / 16); 125 | } 126 | } 127 | 128 | for (int i = 0; i < data_bytes; i++) 129 | { 130 | ARRAY_GET(image, i) = (uint8_t)ARRAY_GET(image_p, i); 131 | } 132 | 133 | free(image_p); 134 | 135 | return 0; 136 | } 137 | 138 | // Black White image to bytes 139 | int bw2Bytes(uint8_t* image, uint8_t* bytes, int w, int h, bw2bytes_config_t config) 140 | { 141 | int image_bytes = w * h; 142 | int out_bytes = image_bytes / 8; 143 | uint8_t temp; 144 | 145 | // Check if h, w is aligned with byte direction 146 | if ((config.byte_dir == 0) && (w % 8 != 0)) 147 | return -1; 148 | if ((config.byte_dir == 1) && (h % 8 != 0)) 149 | return -1; 150 | 151 | // all value to 0 or 1 152 | for (int i = 0; i < image_bytes; i++) 153 | ARRAY_GET(image, i) = (ARRAY_GET(image, i) >= 1) ? (uint8_t)1 : (uint8_t)0; 154 | 155 | // horizontal flip 156 | if (config.flip_h == 1) 157 | { 158 | for (int y = 0; y < h; y++) 159 | { 160 | for (int x = 0; x < w / 2; x++) 161 | { 162 | temp = ARRAY_GET_XY(image, x, y, w); 163 | ARRAY_GET_XY(image, x, y, w) = ARRAY_GET_XY(image, w - x - 1, y, w); 164 | ARRAY_GET_XY(image, w - x - 1, y, w) = temp; 165 | } 166 | } 167 | } 168 | 169 | // vertical flip 170 | if (config.flip_v == 1) 171 | { 172 | for (int x = 0; x < w; x++) 173 | { 174 | for (int y = 0; y < h / 2; y++) 175 | { 176 | temp = ARRAY_GET_XY(image, x, y, w); 177 | ARRAY_GET_XY(image, x, y, w) = ARRAY_GET_XY(image, x, h - y - 1, w); 178 | ARRAY_GET_XY(image, x, h - y - 1, w) = temp; 179 | } 180 | } 181 | } 182 | 183 | // scan 184 | int i = 0; 185 | // Horizontal Scan 186 | if (config.scan_dir == 0) 187 | { 188 | // byte_dir horizontal 189 | if (config.byte_dir == 0) 190 | { 191 | for (int y = 0; y < h; y++) 192 | { 193 | for (int x = 0; x < w; x += 8) 194 | { 195 | // sign bit MSB 196 | if (config.sign_bit == 0) 197 | { 198 | for (int bits = 0; bits < 8; bits++) 199 | { 200 | ARRAY_GET(bytes, i) |= (ARRAY_GET_XY(image, x + bits, y, w)) << (7 - bits); 201 | } 202 | } 203 | // sign bit LSB 204 | else 205 | { 206 | for (int bits = 0; bits < 8; bits++) 207 | { 208 | ARRAY_GET(bytes, i) |= (ARRAY_GET_XY(image, x + bits, y, w)) << (bits); 209 | } 210 | } 211 | 212 | i++; 213 | } 214 | } 215 | } 216 | // byte_dir vertical 217 | else 218 | { 219 | for (int y = 0; y < h; y += 8) 220 | { 221 | for (int x = 0; x < w; x++) 222 | { 223 | // sign bit MSB 224 | if (config.sign_bit == 0) 225 | { 226 | for (int bits = 0; bits < 8; bits++) 227 | { 228 | ARRAY_GET(bytes, i) |= (ARRAY_GET_XY(image, x, y + bits, w)) << (7 - bits); 229 | } 230 | } 231 | // sign bit LSB 232 | else 233 | { 234 | for (int bits = 0; bits < 8; bits++) 235 | { 236 | ARRAY_GET(bytes, i) |= (ARRAY_GET_XY(image, x, y + bits, w)) << (bits); 237 | } 238 | } 239 | 240 | i++; 241 | } 242 | } 243 | } 244 | } 245 | // Vertical Scan 246 | else 247 | { 248 | // byte_dir horizontal 249 | if (config.byte_dir == 0) 250 | { 251 | for (int x = 0; x < w; x += 8) 252 | { 253 | for (int y = 0; y < h; y++) 254 | { 255 | // sign bit MSB 256 | if (config.sign_bit == 0) 257 | { 258 | for (int bits = 0; bits < 8; bits++) 259 | { 260 | ARRAY_GET(bytes, i) |= (ARRAY_GET_XY(image, x + bits, y, w)) << (7 - bits); 261 | } 262 | } 263 | // sign bit LSB 264 | else 265 | { 266 | for (int bits = 0; bits < 8; bits++) 267 | { 268 | ARRAY_GET(bytes, i) |= (ARRAY_GET_XY(image, x + bits, y, w)) << (bits); 269 | } 270 | } 271 | 272 | i++; 273 | } 274 | } 275 | } 276 | // byte_dir vertical 277 | else 278 | { 279 | for (int x = 0; x < w; x++) 280 | { 281 | for (int y = 0; y < h; y += 8) 282 | { 283 | // sign bit MSB 284 | if (config.sign_bit == 0) 285 | { 286 | for (int bits = 0; bits < 8; bits++) 287 | { 288 | ARRAY_GET(bytes, i) |= (ARRAY_GET_XY(image, x, y + bits, w)) << (7 - bits); 289 | } 290 | } 291 | // sign bit LSB 292 | else 293 | { 294 | for (int bits = 0; bits < 8; bits++) 295 | { 296 | ARRAY_GET(bytes, i) |= (ARRAY_GET_XY(image, x, y + bits, w)) << (bits); 297 | } 298 | } 299 | 300 | i++; 301 | } 302 | } 303 | } 304 | } 305 | 306 | return 0; 307 | } 308 | 309 | -------------------------------------------------------------------------------- /python_gui/image_processing/C_dll_source_code/image_processing.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | 6 | 7 | 8 | // Dither 9 | extern __declspec(dllexport) int dithering(uint8_t* image, int w, int h, int bayer_size); 10 | 11 | // Error diffusion 12 | extern __declspec(dllexport) int error_diffusion(uint8_t* image, int w, int h); 13 | 14 | // BW to bytes 15 | typedef struct BW2BYTES_CONFIG_Type 16 | { 17 | int flip_h; // 0-not flip, 1-flip 18 | int flip_v; // 0-not flip, 1-flip 19 | int scan_dir; // 0-Horizontal, 1-Vertical 20 | int byte_dir; // 0-Horizontal, 1-Vertical 21 | int sign_bit; // 0-MSB, 1-LSB 22 | }bw2bytes_config_t; 23 | 24 | extern __declspec(dllexport) int bw2Bytes(uint8_t* image, uint8_t* bytes, int w, int h, bw2bytes_config_t config); 25 | -------------------------------------------------------------------------------- /python_gui/image_processing/Qt2CV.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtGui import QImage 2 | 3 | import numpy as np 4 | 5 | def OpenCVImage2QPixMap(cvImage): 6 | if len(cvImage.shape) == 3: 7 | height, width, channel = cvImage.shape 8 | bytesPerLine = 3 * width 9 | return QImage(cvImage.data, width, height, bytesPerLine, QImage.Format_RGB888) 10 | elif len(cvImage.shape) == 2: 11 | height, width = cvImage.shape 12 | bytesPerLine = 1 * width 13 | return QImage(cvImage.data, width, height, bytesPerLine, QImage.Format_Grayscale8) 14 | else: 15 | print("OpenCVImage2QPixMap: image type not covered!") 16 | return None 17 | 18 | def QPixmap2OpenCVImage(qimage): 19 | # convert to 24bits image 20 | image = qimage.convertToFormat(QImage.Format_RGB888) 21 | 22 | # get image info 23 | width = image.width() 24 | height = image.height() 25 | # check if its width is fit 4 bytes aligned 26 | is4bytesAligned = True 27 | if width * 3 != image.bytesPerLine(): 28 | is4bytesAligned = False 29 | 30 | # reshape to opencv image 31 | ptr = image.bits() 32 | ptr.setsize(image.byteCount()) 33 | if not is4bytesAligned: 34 | arr_temp = np.array(ptr).reshape(height, image.bytesPerLine()) 35 | arr_temp = arr_temp[:, 0:(3*width)] 36 | arr = np.array(arr_temp).reshape(height, width, 3) 37 | else: 38 | arr = np.array(ptr).reshape(height, width, 3) # Copies the data 39 | return arr -------------------------------------------------------------------------------- /python_gui/image_processing/dithering.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/image_processing/dithering.dll -------------------------------------------------------------------------------- /python_gui/image_processing/image_processing.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/image_processing/image_processing.dll -------------------------------------------------------------------------------- /python_gui/image_processing/image_processing_x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/image_processing/image_processing_x64.dll -------------------------------------------------------------------------------- /python_gui/image_processing/image_translate.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import queue 3 | import cv2 as cv 4 | import numpy as np 5 | 6 | from image_processing.BWImageToBytes import BWImageToBytes 7 | from common.Singleton import Singleton 8 | 9 | from ctypes import CDLL, c_uint8, c_int 10 | import platform 11 | 12 | class OutputImagesStructure(object): 13 | def __init__(self): 14 | # images for preview 15 | self.raw = None 16 | self.gray = None 17 | self.bw = None 18 | # images for output 19 | self.output_bw = None 20 | self.output_bw2x = None 21 | # output bw image bytes 22 | self.bytes = None 23 | 24 | # bayer4 = np.array( 25 | # [[0, 12, 3, 15], 26 | # [8, 4, 11, 7], 27 | # [2, 14, 1, 13], 28 | # [10, 6, 9, 5]], dtype='uint8') 29 | # 30 | # bayer8 = np.array( 31 | # [[ 0, 32, 8, 40, 2, 34, 10, 42], 32 | # [48, 16, 56, 24, 50, 18, 58, 26], 33 | # [12, 44, 4, 36, 14, 46, 6, 38], 34 | # [60, 28, 52, 20, 62, 30, 54, 22], 35 | # [ 3, 35, 11, 43, 1, 33, 9, 41], 36 | # [51, 19, 59, 27, 49, 17, 57, 25], 37 | # [15, 47, 7, 39, 13, 45, 5, 37], 38 | # [63, 31, 55, 23, 61, 29, 53, 21]], dtype='uint8' 39 | # ) 40 | # 41 | # bayer16 = np.array( 42 | # [[ 0, 128, 32, 160, 8, 136, 40, 168, 2, 130, 34, 162, 10, 138, 42, 170], 43 | # [192, 64, 224, 96, 200, 72, 232, 104, 194, 66, 226, 98, 202, 74, 234, 106], 44 | # [ 48, 176, 16, 144, 56, 184, 24, 152, 50, 178, 18, 146, 58, 186, 26, 154], 45 | # [240, 112, 208, 80, 248, 120, 216, 88, 242, 114, 210, 82, 250, 122, 218, 90], 46 | # [ 12, 140, 44, 172, 4, 132, 36, 164, 14, 142, 46, 174, 6, 134, 38, 166], 47 | # [204, 76, 236, 108, 196, 68, 228, 100, 206, 78, 238, 110, 198, 70, 230, 102], 48 | # [ 60, 188, 28, 156, 52, 180, 20, 148, 62, 190, 30, 158, 54, 182, 22, 150], 49 | # [252, 124, 220, 92, 244, 116, 212, 84, 254, 126, 222, 94, 246, 118, 214, 86], 50 | # [ 3, 131, 35, 163, 11, 139, 43, 171, 1, 129, 33, 161, 9, 137, 41, 169], 51 | # [195, 67, 227, 99, 203, 75, 235, 107, 193, 65, 225, 97, 201, 73, 233, 105], 52 | # [ 51, 179, 19, 147, 59, 187, 27, 155, 49, 177, 17, 145, 57, 185, 25, 153], 53 | # [243, 115, 211, 83, 251, 123, 219, 91, 241, 113, 209, 81, 249, 121, 217, 89], 54 | # [ 15, 143, 47, 175, 7, 135, 39, 167, 13, 141, 45, 173, 5, 133, 37, 165], 55 | # [207, 79, 239, 111, 199, 71, 231, 103, 205, 77, 237, 109, 197, 69, 229, 101], 56 | # [ 63, 191, 31, 159, 55, 183, 23, 151, 61, 189, 29, 157, 53, 181, 21, 149], 57 | # [255, 127, 223, 95, 247, 119, 215, 87, 253, 125, 221, 93, 245, 117, 213, 85]], dtype='uint8' 58 | # ) 59 | # 60 | # 61 | # def dither(gray_image, bayer_size): 62 | # 63 | # h, w = gray_image.shape 64 | # gray_image = gray_image // (256 // (bayer_size ** 2)) 65 | # 66 | # if bayer_size == 4: 67 | # bayer = bayer4 68 | # elif bayer_size == 8: 69 | # bayer = bayer8 70 | # elif bayer_size == 16: 71 | # bayer = bayer16 72 | # else: 73 | # return None 74 | # 75 | # for x in range(h): 76 | # for y in range(w): 77 | # if gray_image[x, y] > bayer[x % bayer_size, y % bayer_size]: 78 | # gray_image[x, y] = 255 79 | # else: 80 | # gray_image[x, y] = 0 81 | # 82 | # return gray_image 83 | 84 | 85 | @Singleton 86 | class ImageTranslate(object): 87 | 88 | def __init__(self): 89 | self.thread = threading.Thread(target=self.process_threading) 90 | self.thread_run = False 91 | self.lock = threading.Lock() 92 | 93 | self.input_queue = queue.Queue(10) 94 | self.output_queue = queue.Queue(10) 95 | 96 | self.output_images = OutputImagesStructure() 97 | 98 | self.complete_callback = None 99 | 100 | self.image_to_bw = BWImageToBytes() 101 | 102 | self.preview_image_width = 128 103 | self.preview_image_height = 64 104 | 105 | self.preview_image_width_temp = 128 106 | self.preview_image_height_temp = 64 107 | 108 | self.output_image_width = 128 109 | self.output_image_height = 64 110 | 111 | self.output_image_width_temp = 128 112 | self.output_image_height_temp = 64 113 | 114 | self.bw_threshold = 127 115 | self.bw_threshold_temp = 127 116 | self.bw_invert = False 117 | self.bw_invert_temp = False 118 | 119 | self.dither_size = 0 120 | self.dither_size_temp = 0 121 | self.binarization_mode = 'threshold' 122 | self.binarization_mode_temp = 'threshold' 123 | 124 | self.binarization_equalizeHist = False 125 | self.binarization_equalizeHist_temp = False 126 | 127 | # init dll 128 | self.dithering = None 129 | self.error_diffusion = None 130 | self.load_dll() 131 | 132 | 133 | def start(self): 134 | if self.thread_run: 135 | return None 136 | self.thread_run = True 137 | self.thread.start() 138 | 139 | def stop(self): 140 | self.thread_run = False 141 | self.thread.join() 142 | 143 | def load_dll(self): 144 | if platform.architecture()[0] == "64bit": 145 | dll_lib = CDLL("./image_processing/image_processing_x64.dll") 146 | else: 147 | dll_lib = CDLL("./image_processing/image_processing.dll") 148 | self.dithering = dll_lib.dithering 149 | self.error_diffusion = dll_lib.error_diffusion 150 | 151 | # set args type 152 | self.dithering.argtypes = [np.ctypeslib.ndpointer(c_uint8), 153 | c_int, 154 | c_int, 155 | c_int] 156 | self.dithering.restype = c_int 157 | 158 | self.error_diffusion.argtypes = [np.ctypeslib.ndpointer(c_uint8), 159 | c_int, 160 | c_int] 161 | self.error_diffusion.restype = c_int 162 | 163 | def set_threshold(self, value): 164 | if self.lock.acquire(blocking=True, timeout=0.1): 165 | if value != 0: 166 | self.bw_threshold_temp = value 167 | 168 | self.lock.release() 169 | 170 | def set_dither_size(self, size): 171 | if self.lock.acquire(blocking=True, timeout=0.1): 172 | self.dither_size_temp = size 173 | 174 | self.lock.release() 175 | 176 | def set_binarization_mode(self, mode): 177 | if self.lock.acquire(blocking=True, timeout=0.1): 178 | self.binarization_mode_temp = mode 179 | 180 | self.lock.release() 181 | 182 | def set_invert(self, enable): 183 | if self.lock.acquire(blocking=True, timeout=0.1): 184 | if type(enable) == bool: 185 | self.bw_invert_temp = enable 186 | 187 | self.lock.release() 188 | 189 | def set_equalizrHist(self, enable): 190 | if self.lock.acquire(blocking=True, timeout=0.1): 191 | if type(enable) == bool: 192 | self.binarization_equalizeHist_temp = enable 193 | 194 | self.lock.release() 195 | 196 | def set_preview_size(self, width, height): 197 | if self.lock.acquire(blocking=True, timeout=0.1): 198 | self.preview_image_width_temp = width 199 | self.preview_image_height_temp = height 200 | 201 | self.lock.release() 202 | 203 | def set_output_size(self, width, height): 204 | if self.lock.acquire(blocking=True, timeout=0.1): 205 | self.output_image_width_temp = width 206 | self.output_image_height_temp = height 207 | 208 | self.lock.release() 209 | 210 | def update_parameters(self): 211 | if self.lock.acquire(blocking=True, timeout=0.1): 212 | self.bw_threshold = self.bw_threshold_temp 213 | self.bw_invert = self.bw_invert_temp 214 | 215 | self.dither_size = self.dither_size_temp 216 | self.binarization_mode = self.binarization_mode_temp 217 | self.binarization_equalizeHist = self.binarization_equalizeHist_temp 218 | 219 | self.preview_image_width = self.preview_image_width_temp 220 | self.preview_image_height = self.preview_image_height_temp 221 | 222 | self.output_image_width = self.output_image_width_temp 223 | self.output_image_height = self.output_image_height_temp 224 | 225 | self.lock.release() 226 | 227 | def input_image(self, image): 228 | self.input_queue.put(image, timeout=0.1) 229 | 230 | def output_clean(self): 231 | while self.output_queue.qsize() > 0: 232 | self.output_queue.get() 233 | 234 | def read_images(self): 235 | try: 236 | return self.output_queue.get(timeout=0.1) 237 | except: 238 | print("read_images failed!") 239 | return None 240 | 241 | def install_complete_callback(self, callback): 242 | if callback != None: 243 | self.complete_callback = callback 244 | 245 | def remove_complete_callback(self): 246 | self.complete_callback = None 247 | 248 | def image_translate(self, image): 249 | # s1 = time.perf_counter() 250 | w = self.preview_image_width 251 | h = self.preview_image_height 252 | 253 | image_raw = cv.resize(image, (w, h)) 254 | image_gray = cv.cvtColor(image_raw, cv.COLOR_BGR2GRAY) 255 | 256 | if self.binarization_equalizeHist: 257 | image_gray = cv.equalizeHist(image_gray) 258 | 259 | image_out_gray_2x = cv.resize(image_gray, (2 * self.output_image_width, 2 * self.output_image_height)) 260 | image_out_gray_1x = cv.resize(image_gray, (self.output_image_width, self.output_image_height)) 261 | 262 | if self.binarization_mode == 'threshold': 263 | if not self.bw_invert: 264 | ret, image_bw = cv.threshold(image_gray, self.bw_threshold, 255, cv.THRESH_BINARY) 265 | ret, image_out_bw2x = cv.threshold(image_out_gray_2x, self.bw_threshold, 255, cv.THRESH_BINARY) 266 | ret, image_out_bw = cv.threshold(image_out_gray_1x, self.bw_threshold, 255, cv.THRESH_BINARY) 267 | else: 268 | ret, image_bw = cv.threshold(image_gray, self.bw_threshold, 255, cv.THRESH_BINARY_INV) 269 | ret, image_out_bw2x = cv.threshold(image_out_gray_2x, self.bw_threshold, 255, cv.THRESH_BINARY_INV) 270 | ret, image_out_bw = cv.threshold(image_out_gray_1x, self.bw_threshold, 255, cv.THRESH_BINARY_INV) 271 | elif self.binarization_mode == 'dithering': 272 | image_bw = image_gray.copy() 273 | self.dithering(image_bw, w, h, self.dither_size) 274 | 275 | image_out_bw2x = image_out_gray_2x 276 | self.dithering(image_out_bw2x, 2 * self.output_image_width, 2 * self.output_image_height, self.dither_size) 277 | 278 | image_out_bw = image_out_gray_1x 279 | self.dithering(image_out_bw, self.output_image_width, self.output_image_height, self.dither_size) 280 | elif self.binarization_mode == 'error_diff': 281 | image_bw = image_gray.copy() 282 | self.error_diffusion(image_bw, w, h) 283 | 284 | image_out_bw2x = image_out_gray_2x 285 | self.error_diffusion(image_out_bw2x, 2 * self.output_image_width, 2 * self.output_image_height) 286 | 287 | image_out_bw = image_out_gray_1x 288 | self.error_diffusion(image_out_bw, self.output_image_width, self.output_image_height) 289 | else: 290 | return None 291 | # s1 = time.perf_counter() 292 | image_out_bw_bytes = self.image_to_bw.convert(image_out_bw) 293 | # s2 = time.perf_counter() 294 | # dt = s2-s1 295 | # print('dt: %.6f, fps: %.3f' % (dt, 1/dt)) 296 | 297 | self.output_images.raw = image_raw 298 | self.output_images.gray = image_gray 299 | self.output_images.bw = image_bw 300 | self.output_images.output_bw = image_out_bw 301 | self.output_images.output_bw2x = image_out_bw2x 302 | self.output_images.bytes = image_out_bw_bytes 303 | 304 | def output_images_to_queue(self): 305 | self.output_queue.put(self.output_images, timeout=0.1) 306 | 307 | def process_threading(self): 308 | while self.thread_run: 309 | try: 310 | image = self.input_queue.get(timeout=0.1) 311 | self.update_parameters() 312 | self.image_translate(image) 313 | self.output_images_to_queue() 314 | if self.complete_callback != None: 315 | self.complete_callback(self.output_queue) 316 | except: 317 | pass 318 | -------------------------------------------------------------------------------- /python_gui/images/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/images/0.jpg -------------------------------------------------------------------------------- /python_gui/images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/images/1.jpg -------------------------------------------------------------------------------- /python_gui/images/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/images/2.jpg -------------------------------------------------------------------------------- /python_gui/images/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/images/3.jpg -------------------------------------------------------------------------------- /python_gui/images/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/images/4.jpg -------------------------------------------------------------------------------- /python_gui/images/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/images/5.jpg -------------------------------------------------------------------------------- /python_gui/images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/images/5.png -------------------------------------------------------------------------------- /python_gui/images/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/images/7.jpg -------------------------------------------------------------------------------- /python_gui/images/demo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/images/demo_icon.png -------------------------------------------------------------------------------- /python_gui/images/robot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/images/robot.jpg -------------------------------------------------------------------------------- /python_gui/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import os 4 | os.environ['CUDA_VISIBLE_DEVICES'] = '0' 5 | 6 | from PyQt5.QtWidgets import QApplication 7 | 8 | from window.main_Window import MainWindow 9 | 10 | if __name__ == '__main__': 11 | 12 | app = QApplication(sys.argv) 13 | 14 | window = MainWindow() 15 | 16 | res = app.exec_() 17 | 18 | window.exit() 19 | 20 | sys.exit(res) -------------------------------------------------------------------------------- /python_gui/screen.py: -------------------------------------------------------------------------------- 1 | import win32gui 2 | import win32con 3 | import win32api 4 | 5 | from PyQt5.QtWidgets import QApplication 6 | import sys 7 | import threading 8 | import queue 9 | import time 10 | 11 | class ScreenDraw(object): 12 | 13 | def __init__(self): 14 | self.hwnd = 0 # 窗口的编号,0号表示当前活跃窗口 15 | self.hwndDC = win32gui.GetWindowDC(self.hwnd) 16 | 17 | def drawRect(self, x, y, w, h): 18 | win32gui.FlashWindow(self.hwnd, 0) 19 | self.prebrush = win32gui.SelectObject(self.hwndDC, self.hbrush) 20 | win32gui.Rectangle(self.hwndDC, x - 1, y - 1, x + w + 2, y + h + 2) # 左上到右下的坐标 21 | 22 | def setPenColor(self, r, g, b): 23 | self.hbrush = win32gui.GetStockObject(win32con.NULL_BRUSH) # 定义透明画刷,这个很重要!! 24 | self.hPen = win32gui.CreatePen(win32con.PS_SOLID, 2, win32api.RGB(r, g, b)) # 定义框颜色 25 | win32gui.SelectObject(self.hwndDC, self.hPen) 26 | self.prebrush = win32gui.SelectObject(self.hwndDC, self.hbrush) 27 | win32gui.SelectObject(self.hwndDC, self.prebrush) 28 | 29 | def close(self): 30 | win32gui.DeleteObject(self.hPen) 31 | win32gui.DeleteObject(self.hbrush) 32 | win32gui.DeleteObject(self.prebrush) 33 | win32gui.ReleaseDC(self.hwnd, self.hwndDC) 34 | 35 | class ScreenGet(object): 36 | 37 | def __init__(self): 38 | self.hwnd = 0 39 | self.app = QApplication(sys.argv) 40 | self.screen = self.app.primaryScreen() 41 | 42 | self.thread = threading.Thread(target=self.thread) 43 | self.running = False 44 | 45 | self.image = None 46 | self.image_out_q = queue.Queue(2) 47 | 48 | self.image_x = 0 49 | self.image_y = 0 50 | self.image_w = 480 51 | self.image_h = 320 52 | self.image_x_temp = 0 53 | self.image_y_temp = 0 54 | self.image_w_temp = 480 55 | self.image_h_temp = 320 56 | 57 | def start(self): 58 | self.running = True 59 | self.thread.start() 60 | 61 | def stop(self): 62 | self.running = False 63 | self.thread.join() 64 | 65 | def getScreen(self, x, y, w, h): 66 | if self.image_out_q.qsize() > 0: 67 | image = self.image_out_q.get() 68 | self.setScreenArea(x, y, w, h) 69 | return image 70 | else: 71 | # screen = self.app.primaryScreen() 72 | image = self.screen.grabWindow(self.hwnd, x, y, w, h) 73 | return image 74 | 75 | def setScreenArea(self, x, y, w, h): 76 | self.image_x_temp = x 77 | self.image_y_temp = y 78 | self.image_w_temp = w 79 | self.image_h_temp = h 80 | 81 | def screenAreaParamUpdate(self): 82 | self.image_x = self.image_x_temp 83 | self.image_y = self.image_y_temp 84 | self.image_w = self.image_w_temp 85 | self.image_h = self.image_h_temp 86 | 87 | def thread(self): 88 | while self.running: 89 | if self.image_out_q.qsize() < 2: 90 | self.screenAreaParamUpdate() 91 | image = self.screen.grabWindow(self.hwnd, self.image_x, self.image_y,self.image_w, self.image_h) 92 | self.image_out_q.put(image) 93 | else: 94 | time.sleep(0.01) 95 | -------------------------------------------------------------------------------- /python_gui/serial_port.py: -------------------------------------------------------------------------------- 1 | import serial 2 | import serial.tools.list_ports 3 | 4 | 5 | class SerialPort(object): 6 | 7 | def __init__(self, port, baudrate): 8 | try: 9 | self.serial = serial.Serial(port, baudrate) 10 | except Exception: 11 | print("Serial Port '%s' Open False!" % (port)) 12 | 13 | @classmethod 14 | def getDeviceList(self): 15 | deviceNames = [] 16 | portList = list(serial.tools.list_ports.comports()) 17 | for port in portList: 18 | deviceNames.append((port.description, port.device)) 19 | return deviceNames 20 | 21 | def open(self, port, baudrate): 22 | try: 23 | # self.serial = serial.Serial(port, baudrate, write_timeout=0) 24 | self.serial = serial.Serial(port, baudrate) 25 | except Exception: 26 | print("Serial Port '%s' Open False!" % (port)) 27 | 28 | def close(self): 29 | if not self.serial.closed: 30 | self.serial.close() 31 | 32 | def send(self, data): 33 | self.serial.write(data) 34 | 35 | 36 | if __name__ == '__main__': 37 | portList = SerialPort.getDeviceList() 38 | for port in portList: 39 | print(port) -------------------------------------------------------------------------------- /python_gui/test/dither_bayer_metrix_generator.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def bayer_recursive(Mn): 5 | n, _ = Mn.shape 6 | Mn2 = np.zeros((2*n, 2*n), dtype='uint8') 7 | 8 | Mn2[:n, :n] = 4 * Mn 9 | Mn2[:n, n:] = 4 * Mn + 2 10 | Mn2[n:, :n] = 4 * Mn + 3 11 | Mn2[n:, n:] = 4 * Mn + 1 12 | 13 | return Mn2 14 | 15 | M2 = np.array([[0, 2], [3, 1]]) 16 | 17 | M4 = bayer_recursive(M2) 18 | print(M4) 19 | 20 | M8 = bayer_recursive(M4) 21 | print(M8) 22 | 23 | M16 = bayer_recursive(M8) 24 | print(M16) -------------------------------------------------------------------------------- /python_gui/test/iconDesignAutoUpload.py: -------------------------------------------------------------------------------- 1 | import cv2 as cv 2 | import numpy as np 3 | 4 | import time 5 | 6 | def gray2bw(imageArray): 7 | hight, width = imageArray.shape 8 | 9 | bw_image_array = np.zeros((hight, width), int) 10 | 11 | for i in range(hight): 12 | for j in range(width): 13 | bw_image_array[i][j] = 1 if imageArray[i][j] > 128 else 0 14 | return bw_image_array 15 | 16 | def bw2bytes(bw_image): 17 | hight, width = bw_image.shape 18 | rows = hight / 8 19 | 20 | array_list = [] 21 | 22 | for row_index in range(rows): 23 | row = row_index * 8 24 | for col in range(width): 25 | bytes_array = [] 26 | for i in range(8): 27 | bytes_array.append(bw_image[row+i][col]) 28 | array_list.append(bytes_array) 29 | 30 | return array_list 31 | 32 | def bytes_array_to_byte(bytes_array): 33 | byte_list = [] 34 | for nums in bytes_array: 35 | num_byte = 0 36 | index = 0 37 | for num in nums: 38 | num_byte |= num << index 39 | index += 1 40 | byte_list.append(num_byte) 41 | 42 | return byte_list 43 | 44 | def readImageAndConvertToBytes(file_path): 45 | image = cv.imread(file_path) 46 | image = cv.cvtColor(image, cv.COLOR_BGR2GRAY) 47 | image = cv.resize(image, (128, 64)) 48 | 49 | bw_image = gray2bw(image) 50 | bw_image_bytes_list = bw2bytes(bw_image) 51 | byte_list = bytes_array_to_byte(bw_image_bytes_list) 52 | 53 | return byte_list 54 | 55 | import serial 56 | oled = serial.Serial('COM6', 1000000) 57 | 58 | while True: 59 | try: 60 | time.sleep(1) 61 | bytes_stream = readImageAndConvertToBytes('../images/demo_icon.png') 62 | oled.write(bytes_stream) 63 | print("Send complete!") 64 | except: 65 | print("Send Error, closed!") 66 | oled.close() 67 | break -------------------------------------------------------------------------------- /python_gui/test/read_image.py: -------------------------------------------------------------------------------- 1 | import cv2 as cv 2 | import numpy as np 3 | 4 | import serial 5 | import time 6 | 7 | def gray2bw(imageArray): 8 | return (imageArray > 127) * np.uint8(1) 9 | 10 | def bw2bytes(bw_image): 11 | hight, width = bw_image.shape 12 | rows = hight / 8 13 | 14 | image_raw_bw = np.zeros((8, 128*(64/8)), dtype='uint8') 15 | for row_index in range(0,8): 16 | row = row_index * 8 17 | for col in range(0, 128): 18 | image_raw_bw[0:, row_index * 128 + col] = bw_image[row:row+8, col] 19 | 20 | return image_raw_bw 21 | 22 | def bytes_array_to_byte(bytes_array): 23 | # into byte 24 | image_raw_bytes = np.zeros((1024), dtype='uint8') 25 | for col in range(0, 1024): 26 | one_byte_array = bytes_array[0:8, col] 27 | byte_str = ''.join([str(x) for x in one_byte_array]) 28 | byte_str = byte_str[::-1] 29 | image_raw_bytes[col] = np.int(byte_str, 2) 30 | 31 | return image_raw_bytes 32 | 33 | def readImageAndConvertToBytes(file_path): 34 | image = cv.imread(file_path) 35 | image = cv.cvtColor(image, cv.COLOR_BGR2GRAY) 36 | image = cv.resize(image, (128, 64)) 37 | 38 | bw_image = gray2bw(image) 39 | cv.imwrite('bw_image.png', bw_image) 40 | bw_image_bytes_list = bw2bytes(bw_image) 41 | cv.imwrite('bw_image_bytes_list.png', bw_image_bytes_list) 42 | byte_list = bytes_array_to_byte(bw_image_bytes_list) 43 | 44 | return byte_list 45 | 46 | display = serial.Serial('COM6', 1000000) 47 | 48 | rx_buffer = '' 49 | 50 | send_flag = False 51 | 52 | 53 | s1 = time.clock() 54 | image_name = "images/demo_icon.png" 55 | bytes_stream = readImageAndConvertToBytes(image_name) 56 | s2 = time.clock() 57 | if send_flag == True: 58 | # wait for ack 59 | rx_buffer = display.read_until('\n') 60 | print(rx_buffer) 61 | print(s2-s1) 62 | send_flag = True 63 | display.write(bytes_stream) 64 | 65 | 66 | display.close() -------------------------------------------------------------------------------- /python_gui/test/read_video.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 as cv 3 | 4 | import serial 5 | import time 6 | 7 | 8 | # re-sample image 9 | def re_sample(gray_image): 10 | # binary 11 | image_bw = (gray_image > 127) * np.uint8(1) 12 | # re-sample 13 | image_raw_bw = np.zeros((8, int(128*(64/8))), dtype='uint8') 14 | for row_index in range(0,8): 15 | row = row_index * 8 16 | for col in range(0, 128): 17 | image_raw_bw[0:, row_index * 128 + col] = image_bw[row:row+8, col] 18 | 19 | # into byte 20 | image_raw_bytes = np.zeros(1024, dtype='uint8') 21 | for col in range(0, 1024): 22 | one_byte_array = image_raw_bw[0:8, col] 23 | byte_str = ''.join([str(x) for x in one_byte_array]) 24 | byte_str = byte_str[::-1] 25 | image_raw_bytes[col] = np.int(byte_str, 2) 26 | 27 | return image_raw_bytes 28 | 29 | 30 | display = serial.Serial('COM6', 1000000, write_timeout=0) 31 | 32 | frame_index = 0 33 | 34 | last_time_stamp = 0 35 | 36 | average_dt = 0 37 | 38 | if __name__ == '__main__': 39 | 40 | try: 41 | # open video 42 | cap = cv.VideoCapture('video/bad_apple.mp4') 43 | 44 | while True: 45 | # read one frame image 46 | ret, frame = cap.read() 47 | image = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) 48 | image = cv.resize(image, (128, 64)) 49 | 50 | # cv.imshow('input_image', frame) 51 | cv.imshow('output_image', image) 52 | 53 | # re-sample image 54 | bytes_stream = re_sample(image) 55 | 56 | # wait for response 57 | if frame_index != 0: 58 | display.read_until(b'\n') 59 | display.read_all() 60 | 61 | # send one frame data 62 | display.write(bytes_stream) 63 | 64 | # update frame index 65 | frame_index += 1 66 | 67 | # break 68 | cv.waitKey(1) 69 | 70 | # update time stamp 71 | new_time_stamp = time.process_time() 72 | dt = new_time_stamp - last_time_stamp 73 | last_time_stamp = new_time_stamp 74 | 75 | average_dt = dt * 0.05 + 0.95 * average_dt 76 | 77 | print('index: %d, fps: %.1f' % (frame_index, 1/average_dt)) 78 | 79 | except 'Exception': 80 | display.close() 81 | cap.release() 82 | cv.destroyAllWindows() 83 | -------------------------------------------------------------------------------- /python_gui/test/tft_320_240.py: -------------------------------------------------------------------------------- 1 | import cv2 as cv 2 | import numpy as np 3 | 4 | import serial 5 | 6 | def re_sample(gray_image, width, height): 7 | # binary 8 | image_bw = (gray_image > 127) * np.uint8(1) 9 | # re-sample 10 | image_raw_bw = np.zeros((8, int(width*(height/8))), dtype='uint8') 11 | for col in range(0, width): 12 | for row_index in range(0, int(height/8)): 13 | row = row_index * 8 14 | image_raw_bw[0:, col * int(height/8) + row_index] = image_bw[row:row+8, col] 15 | # into byte 16 | num_bytes = int(width * height / 8) 17 | image_raw_bytes = np.zeros(num_bytes, dtype='uint8') 18 | for col in range(0, num_bytes): 19 | one_byte_array = image_raw_bw[0:8, col] 20 | byte_str = ''.join([str(x) for x in one_byte_array]) 21 | # byte_str = byte_str[::-1] 22 | image_raw_bytes[col] = np.int(byte_str, 2) 23 | 24 | return image_raw_bytes 25 | 26 | 27 | port = serial.Serial('COM9', 1000000) 28 | 29 | if __name__ == '__main__': 30 | image = cv.imread('../images/5.jpg') 31 | image = cv.cvtColor(image, cv.COLOR_BGR2GRAY) 32 | image = cv.resize(image, (320, 240)) 33 | 34 | image = cv.flip(image, 1) 35 | 36 | cv.imshow('image', image) 37 | 38 | image_bw_bytes = re_sample(image, 320, 240) 39 | 40 | # bw_image = (image // 8) * np.uint8(1) 41 | # bw_image_raw_data = bw_image.reshape((1, 240*120))[0] 42 | col = 16 43 | index = 0 44 | out_str = '' 45 | for i in range(col): 46 | for j in range(int(320*240/8/col)): 47 | out_str += '%02x ' % (image_bw_bytes[index]) 48 | index += 1 49 | out_str += '\n' 50 | print(out_str) 51 | port.write(image_bw_bytes) 52 | cv.waitKey(2000) 53 | cv.destroyWindow('image') 54 | 55 | port.close() -------------------------------------------------------------------------------- /python_gui/test/tft_320_240_video.py: -------------------------------------------------------------------------------- 1 | import cv2 as cv 2 | import numpy as np 3 | 4 | import serial 5 | 6 | import time 7 | 8 | def re_sample(gray_image, width, height): 9 | # binary 10 | image_bw = (gray_image < 127) * np.uint8(1) 11 | # re-sample 12 | image_raw_bw = np.zeros((8, int(width*(height/8))), dtype='uint8') 13 | for col in range(0, width): 14 | for row_index in range(0, int(height/8)): 15 | row = row_index * 8 16 | image_raw_bw[0:, col * int(height/8) + row_index] = image_bw[row:row+8, col] 17 | # into byte 18 | num_bytes = int(width * height / 8) 19 | image_raw_bytes = np.zeros(num_bytes, dtype='uint8') 20 | for col in range(0, num_bytes): 21 | one_byte_array = image_raw_bw[0:8, col] 22 | byte_str = ''.join([str(x) for x in one_byte_array]) 23 | # byte_str = byte_str[::-1] 24 | image_raw_bytes[col] = np.int(byte_str, 2) 25 | 26 | return image_raw_bytes 27 | 28 | 29 | display = serial.Serial('COM9', 1000000, write_timeout=0) 30 | 31 | frame_index = 0 32 | 33 | last_time_stamp = 0 34 | 35 | average_dt = 0 36 | 37 | if __name__ == '__main__': 38 | 39 | try: 40 | # open video 41 | cap = cv.VideoCapture('../video/bad_apple.mp4') 42 | 43 | while True: 44 | # read one frame image 45 | ret, frame = cap.read() 46 | image = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) 47 | image = cv.resize(image, (240, 120)) 48 | 49 | # cv.imshow('input_image', frame) 50 | cv.imshow('output_image', image) 51 | 52 | image = cv.flip(image, 1) 53 | 54 | # re-sample image 55 | bytes_stream = re_sample(image, 240, 120) 56 | 57 | # wait for response 58 | if frame_index != 0: 59 | display.read_until(b'\n') 60 | display.read_all() 61 | 62 | # send one frame data 63 | display.write(bytes_stream) 64 | 65 | # update frame index 66 | frame_index += 1 67 | 68 | # break 69 | cv.waitKey(1) 70 | 71 | # update time stamp 72 | new_time_stamp = time.process_time() 73 | dt = new_time_stamp - last_time_stamp 74 | last_time_stamp = new_time_stamp 75 | 76 | average_dt = dt * 0.05 + 0.95 * average_dt 77 | 78 | print('index: %d, fps: %.1f' % (frame_index, 1 / average_dt)) 79 | 80 | except 'Exception': 81 | display.close() 82 | cap.release() 83 | cv.destroyAllWindows() -------------------------------------------------------------------------------- /python_gui/tools/environment_setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import platform 4 | 5 | # Third-party module 6 | modules_needed = [ 7 | 'pyserial', 8 | 'numpy', 9 | 'opencv-python', 10 | 'PyQt5', 11 | 'pywin32', 12 | ] 13 | 14 | def install_pip(): 15 | global system 16 | if system == 'Windows': 17 | print('Install process:') 18 | print('\t1.Download get-pip.py to a folder on your computer.') 19 | print('\t2.Open a command prompt and navigate to the folder containing get-pip.py.') 20 | print('\t3.Run the following command:') 21 | print('\t python get-pip.py') 22 | # Auto install process 23 | result = os.system('python get-pip.py') 24 | if result != 0: 25 | result = os.system('python tools/get-pip.py') 26 | if result == 0: 27 | print('\t4.Pip is now installed!') 28 | else: 29 | print("\t4.Pip install failed!, please install by yourself!") 30 | sys.exit() 31 | 32 | if 0 != os.system('pip -V'): 33 | print('\t5.Check if C:\Python27\Scripts is in your system path. Otherwise, pip will not recognized.') 34 | sys.exit() 35 | 36 | print('\nPip installed!\n') 37 | else: 38 | print('Not support yet.') 39 | sys.exit() 40 | 41 | if __name__ == "__main__": 42 | # 0, check if pyhton 3.x is installed 43 | print("0, check if pyhton 3x is installed") 44 | if sys.version_info.major == 3: 45 | print('\tCheck OK!') 46 | else: 47 | print('\tPlesse make sure you have installed python 3.x correctly!') 48 | sys.exit() 49 | 50 | # 1, check the operating system 51 | print("1, check the operating system") 52 | system = platform.system() 53 | print("\tYour system is '%s'." % (system)) 54 | 55 | # 2, check if python pip is installed 56 | print("2, check if python pip is installed") 57 | result = os.system('pip -V') 58 | if result != 0: 59 | install_pip() 60 | else: 61 | print('\tPython pip is installed!') 62 | 63 | # 3, check/install third-party module is installed 64 | print("3, check/install third-party module is installed") 65 | print('Third-party modules: {}'.format(modules_needed)) 66 | modules_uninstall = [] 67 | for name in modules_needed: 68 | # check if this module is installed 69 | result = os.system('pip show %s' % (name)) 70 | if result == 0: 71 | print("\nInstalled '%s', skip to next!\n" % (name)) 72 | continue 73 | 74 | # install 75 | result = os.system('pip install %s' % (name)) 76 | if result == 0: 77 | print("\nInstall '%s' sucess!\n" % (name)) 78 | else: 79 | modules_uninstall.append(name) 80 | print("Install false, please install '%s' manually!" % (name)) 81 | print("The cmd is: pip install %s" % (name)) 82 | 83 | if modules_uninstall != []: 84 | print("\nPlease install these modules manually again:") 85 | for name in modules_uninstall: 86 | print(name) 87 | else: 88 | print("\nAll resuired modules are installed!\n") -------------------------------------------------------------------------------- /python_gui/video/bad_apple.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnChangNice/oled_display_gui/b3593ad7352fc1470b8da366c6b4168984fbb2d7/python_gui/video/bad_apple.mp4 -------------------------------------------------------------------------------- /python_gui/window/imageMode_Window.py: -------------------------------------------------------------------------------- 1 | 2 | from PyQt5.QtWidgets import QFileDialog, QWidget 3 | from PyQt5.QtGui import QPixmap 4 | 5 | from os import path 6 | import cv2 as cv 7 | import numpy as np 8 | from image_processing.Qt2CV import OpenCVImage2QPixMap 9 | from UI.image_export_ui import Ui_imageExportWindow 10 | from image_processing.image_translate import ImageTranslate, OutputImagesStructure 11 | 12 | import threading 13 | 14 | 15 | class ImageModeWindow(object): 16 | 17 | def __init__(self, window, main_ui): 18 | self.main_ui = main_ui 19 | self.window = window 20 | 21 | # export window 22 | self.export_window = QWidget() 23 | self.init_export_window(self.export_window) 24 | 25 | # init image translator 26 | self.image_translator = ImageTranslate() 27 | self.image_translator.start() 28 | self.images = OutputImagesStructure() 29 | 30 | # init signal and slot 31 | self.init_signal() 32 | 33 | self.sendMethod = None 34 | 35 | self.lock = threading.Lock() 36 | 37 | def init_export_window(self, window): 38 | self.imageExport_ui = Ui_imageExportWindow() 39 | self.imageExport_ui.setupUi(window) 40 | self.imageExport_ui.retranslateUi(window) 41 | 42 | def init_signal(self): 43 | # connect signal and slot 44 | # tab widget 45 | self.main_ui.tabWidget.currentChanged.connect(self.tab_changed) 46 | # Threshold value 47 | self.main_ui.spinBox_BWThreshold.valueChanged['int'].connect(self.main_ui.horizontalSlider_BWThreshold.setValue) 48 | self.main_ui.horizontalSlider_BWThreshold.valueChanged['int'].connect(self.main_ui.spinBox_BWThreshold.setValue) 49 | self.main_ui.horizontalSlider_BWThreshold.valueChanged.connect(self.BWThresholdValueUpdate) 50 | self.previewBWSize = '2X' 51 | self.main_ui.checkBox_previewBW2x.clicked.connect(self.previewBWSizeUpdate) 52 | # import image 53 | self.main_ui.pbt_openImageFile.clicked.connect(self.openImage) 54 | self.lastFolderPath = '' 55 | # BM invert 56 | self.main_ui.checkBox_BWInvert.clicked.connect(self.BWInvertUpdate) 57 | self.BWInvert = False 58 | # preview mode 59 | self.main_ui.radioButton_previewRaw.clicked.connect(self.previewModeUpdate) 60 | self.main_ui.radioButton_previewGray.clicked.connect(self.previewModeUpdate) 61 | self.main_ui.radioButton_previewBW.clicked.connect(self.previewModeUpdate) 62 | self.previewMode = 'raw' 63 | # export mode 64 | self.main_ui.radioButton_exportHexCArray.clicked.connect(self.exportModeUpdate) 65 | self.main_ui.radioButton_exportHexValue.clicked.connect(self.exportModeUpdate) 66 | self.exportMode = 'HexCArray' 67 | self.main_ui.pbt_exportImage.clicked.connect(self.exportImage) 68 | # send to OLED 69 | self.main_ui.radioButton_SendImageAuto.clicked.connect(self.imageSendModeUpdate) 70 | self.main_ui.radioButton_sendImageManually.clicked.connect(self.imageSendModeUpdate) 71 | self.imageSendMode = 'Manually' 72 | self.main_ui.pbt_sendImage.clicked.connect(self.sendManually) 73 | 74 | # disable 75 | self.setImageWidgetEnable(False) 76 | 77 | # init tab and install image mode callback for image translator 78 | self.tab_changed() 79 | 80 | """ 81 | There only one image translator instance, so we must install the current callback when mode is changed. 82 | """ 83 | def tab_changed(self): 84 | index = self.main_ui.tabWidget.currentIndex() 85 | tab_name = self.main_ui.tabWidget.tabText(index) 86 | if tab_name == 'Image': 87 | self.image_translator.output_clean() 88 | self.image_translator.install_complete_callback(self.image_translate_complete) 89 | 90 | def setImageWidgetEnable(self, enable): 91 | self.main_ui.radioButton_previewRaw.setEnabled(enable) 92 | self.main_ui.radioButton_previewGray.setEnabled(enable) 93 | self.main_ui.radioButton_previewBW.setEnabled(enable) 94 | 95 | self.main_ui.spinBox_BWThreshold.setEnabled(enable) 96 | self.main_ui.horizontalSlider_BWThreshold.setEnabled(enable) 97 | 98 | self.main_ui.checkBox_BWInvert.setEnabled(enable) 99 | self.main_ui.checkBox_previewBW2x.setEnabled(enable) 100 | self.main_ui.pbt_exportImage.setEnabled(enable) 101 | 102 | self.main_ui.radioButton_SendImageAuto.setEnabled(enable) 103 | self.main_ui.pbt_sendImage.setEnabled(enable) 104 | 105 | def openImage(self): 106 | filename, filetype = QFileDialog.getOpenFileName(self.window, 'Select a image file', self.lastFolderPath) 107 | if filename != '': 108 | self.lastFolderPath = path.dirname(filename) 109 | self.main_ui.lineEdit_imageFileName.setText(filename) 110 | self.image_raw = cv.imread(filename) 111 | try: 112 | h, w, n = self.image_raw.shape 113 | except: 114 | return 115 | self.setImageWidgetEnable(True) 116 | k = w / h 117 | height = self.main_ui.label_previewWindow.height() 118 | width = int(k * height) - 1 119 | self.image_translator.set_preview_size(width, height) 120 | self.image_translator.input_image(self.image_raw) 121 | 122 | def imageSendModeUpdate(self): 123 | if self.main_ui.radioButton_sendImageManually.isChecked(): 124 | self.imageSendMode = 'Manually' 125 | else: 126 | self.imageSendMode = 'Auto' 127 | 128 | def BWThresholdValueUpdate(self): 129 | if self.lock.acquire(blocking=True, timeout=0.1): 130 | thresholdValue = self.main_ui.spinBox_BWThreshold.value() 131 | self.image_translator.set_threshold(thresholdValue) 132 | self.image_translator.input_image(self.image_raw) 133 | self.lock.release() 134 | 135 | def previewBWSizeUpdate(self): 136 | if self.main_ui.checkBox_previewBW2x.isChecked(): 137 | self.previewBWSize = '2X' 138 | else: 139 | self.previewBWSize = '1X' 140 | self.updateBWPreview() 141 | 142 | def exportModeUpdate(self): 143 | if self.main_ui.radioButton_exportHexCArray.isChecked(): 144 | self.exportMode = 'HexCArray' 145 | else: 146 | self.exportMode = 'HexValue' 147 | 148 | def exportImage(self): 149 | image_bytes = self.images.bytes 150 | # export 151 | out_str = '' 152 | if self.exportMode == 'HexCArray': 153 | out_str += 'uint8_t bitmap[] = {\n' 154 | out_hex_nums = ['0x%02x' % x for x in image_bytes] 155 | numbers_per_line = 32 156 | for i in range(int(1024 / numbers_per_line)): 157 | index = i * numbers_per_line 158 | out_str += ' %s,\n' % (', '.join(out_hex_nums[index:(index + numbers_per_line)])) 159 | out_str += '};\n' 160 | else: 161 | out_hex_nums = ['%02x' % x for x in image_bytes] 162 | out_str += ' '.join(out_hex_nums) 163 | 164 | self.imageExport_ui.textEdit_eportEditor.setText(out_str) 165 | self.export_window.show() 166 | 167 | 168 | def BWInvertUpdate(self): 169 | if self.main_ui.checkBox_BWInvert.isChecked(): 170 | self.BWInvert = True 171 | else: 172 | self.BWInvert = False 173 | self.image_translator.set_invert(self.BWInvert) 174 | self.image_translator.input_image(self.image_raw) 175 | 176 | def previewModeUpdate(self): 177 | if self.main_ui.radioButton_previewRaw.isChecked(): 178 | self.previewMode = 'raw' 179 | elif self.main_ui.radioButton_previewGray.isChecked(): 180 | self.previewMode = 'gray' 181 | else: 182 | self.previewMode = 'bw' 183 | self.updatePreview() 184 | 185 | def updatePreview(self): 186 | # update preview 187 | if self.previewMode == 'raw': 188 | image = self.images.raw 189 | elif self.previewMode == 'gray': 190 | image = self.images.gray 191 | else: 192 | image = self.images.bw 193 | 194 | image_pix = OpenCVImage2QPixMap(image) 195 | self.main_ui.label_previewWindow.setPixmap(QPixmap.fromImage(image_pix)) 196 | 197 | def updateBWPreview(self): 198 | # update BW preview 199 | if self.previewBWSize == '2X': 200 | image = self.images.output_bw2x 201 | else: 202 | image = self.images.output_bw 203 | 204 | image_pix = OpenCVImage2QPixMap(image) 205 | self.main_ui.label_previewOutputBW.setPixmap(QPixmap.fromImage(image_pix)) 206 | 207 | # send to display 208 | if self.imageSendMode == 'Auto': 209 | self.send(self.images.bytes) 210 | 211 | def sendManually(self): 212 | self.send(self.images.bytes) 213 | 214 | def addSendMethod(self, sendMethod): 215 | self.sendMethod = sendMethod 216 | 217 | def image_translate_complete(self, images_queue): 218 | count = images_queue.qsize() 219 | for i in range(count): 220 | self.images = images_queue.get() 221 | 222 | self.updatePreview() 223 | self.updateBWPreview() 224 | 225 | def send(self, data): 226 | if self.sendMethod != None: 227 | self.sendMethod.send(data) 228 | 229 | def exit(self): 230 | pass -------------------------------------------------------------------------------- /python_gui/window/main_Window.py: -------------------------------------------------------------------------------- 1 | 2 | from UI.main_ui import Ui_mainWindow 3 | from window.imageMode_Window import ImageModeWindow 4 | from window.videoMode_Window import VideoModeWindow 5 | from window.screenMode_Window import ScreenModeWindow 6 | from PyQt5.QtWidgets import QMainWindow 7 | 8 | from serial_port import SerialPort 9 | from image_processing.BWImageToBytes import BWImageToBytes 10 | from image_processing.image_translate import ImageTranslate 11 | 12 | 13 | class MainWindow(object): 14 | def __init__(self): 15 | # setup window 16 | self.window = QMainWindow() 17 | self.main_ui = Ui_mainWindow() 18 | self.main_ui.setupUi(self.window) 19 | self.main_ui.retranslateUi(self.window) 20 | 21 | self.imageModeWindow = ImageModeWindow(self.window, self.main_ui) 22 | self.videoModeWindow = VideoModeWindow(self.window, self.main_ui) 23 | self.screenModeWindow = ScreenModeWindow(self.window, self.main_ui) 24 | 25 | # BW image to bytes instance 26 | self.image_to_bw = BWImageToBytes() 27 | 28 | # image processing 29 | self.image_translator = ImageTranslate() 30 | self.image_translator.start() 31 | 32 | self.connectSignal() 33 | 34 | # show window 35 | self.window.show() 36 | 37 | def connectSignal(self): 38 | # connect serial port widgets 39 | self.main_ui.pbt_scanSerialPort.clicked.connect(self.portScan) 40 | self.main_ui.combox_serialPortList.activated.connect(self.portSelect) 41 | self.main_ui.pbt_serialOpen.clicked.connect(self.portOpen) 42 | self.portOpened = False 43 | # connect display setting 44 | self.main_ui.spinBox_displayRow.valueChanged.connect(self.displayColumnRowSetting) 45 | self.main_ui.spinBox_displayCol.valueChanged.connect(self.displayColumnRowSetting) 46 | self.main_ui.checkBox_displayFlipH.clicked.connect(self.displayFlipModeSetting) 47 | self.main_ui.checkBox_displayFlipV.clicked.connect(self.displayFlipModeSetting) 48 | self.main_ui.comboBox_displayScanDirection.activated.connect(self.displayScanDirectionSetting) 49 | self.main_ui.comboBox_displayByteDirection.activated.connect(self.displayByteDirectionSetting) 50 | self.main_ui.comboBox_displaySignBit.activated.connect(self.displaySignBitSetting) 51 | self.displaySettingInit() 52 | # connect binarization setting 53 | self.main_ui.radioButton_binarizationThreshold.clicked.connect(self.binarizationSetting) 54 | self.main_ui.radioButton_binarizationDither.clicked.connect(self.binarizationSetting) 55 | self.main_ui.radioButton_binarizationErrorDiffusion.clicked.connect(self.binarizationSetting) 56 | self.main_ui.checkBox_binarizationEqualizeHist.clicked.connect(self.binarizationSetting) 57 | self.main_ui.comboBox_ditherBayerSize.activated.connect(self.binarizationSetting) 58 | self.binarizationSetting() 59 | 60 | def portScan(self): 61 | portList = SerialPort.getDeviceList() 62 | self.main_ui.combox_serialPortList.clear() 63 | for portInfo, port in portList: 64 | self.main_ui.combox_serialPortList.addItem(portInfo, port) 65 | # default select the first one 66 | self.port = self.main_ui.combox_serialPortList.currentData() 67 | self.baudrate = self.main_ui.spinBox_baudrate.value() 68 | 69 | def portSelect(self): 70 | self.port = self.main_ui.combox_serialPortList.currentData() 71 | self.baudrate = self.main_ui.spinBox_baudrate.value() 72 | 73 | def portOpen(self): 74 | if self.portOpened == False: 75 | try: 76 | self.serial = SerialPort(self.port, self.baudrate) 77 | self.portOpened = True 78 | self.main_ui.pbt_serialOpen.setText('Close') 79 | self.imageModeWindow.addSendMethod(self.serial) 80 | self.videoModeWindow.addSendMethod(self.serial) 81 | self.screenModeWindow.addSendMethod(self.serial) 82 | except Exception: 83 | print('Serial port open false.') 84 | else: 85 | try: 86 | self.serial.close() 87 | self.serial = None 88 | self.portOpened = False 89 | self.main_ui.pbt_serialOpen.setText('Open') 90 | self.imageModeWindow.addSendMethod(None) 91 | except Exception: 92 | print('Serial port close false.') 93 | 94 | def binarizationSetting(self): 95 | if self.main_ui.checkBox_binarizationEqualizeHist.isChecked(): 96 | self.image_translator.set_equalizrHist(True) 97 | else: 98 | self.image_translator.set_equalizrHist(False) 99 | 100 | if self.main_ui.radioButton_binarizationThreshold.isChecked(): 101 | self.image_translator.set_binarization_mode('threshold') 102 | elif self.main_ui.radioButton_binarizationDither.isChecked(): 103 | self.image_translator.set_binarization_mode('dithering') 104 | size_str = self.main_ui.comboBox_ditherBayerSize.currentText() 105 | size = int(size_str[:-1]) 106 | self.image_translator.set_dither_size(size) 107 | elif self.main_ui.radioButton_binarizationErrorDiffusion.isChecked(): 108 | self.image_translator.set_binarization_mode('error_diff') 109 | else: 110 | pass 111 | 112 | def displaySettingInit(self): 113 | self.displayColumnRowSetting() 114 | self.displayFlipModeSetting() 115 | self.displayScanDirectionSetting() 116 | self.displayByteDirectionSetting() 117 | self.displaySignBitSetting() 118 | 119 | def displayColumnRowSetting(self): 120 | col = self.main_ui.spinBox_displayCol.value() 121 | row = self.main_ui.spinBox_displayRow.value() 122 | self.image_translator.set_output_size(col, row) 123 | 124 | def displayFlipModeSetting(self): 125 | flip_h = self.main_ui.checkBox_displayFlipH.isChecked() 126 | flip_v = self.main_ui.checkBox_displayFlipV.isChecked() 127 | self.image_to_bw.setHorizontalFlip(flip_h) 128 | self.image_to_bw.setVerticalFlip(flip_v) 129 | 130 | def displayScanDirectionSetting(self): 131 | scan_direction = self.main_ui.comboBox_displayScanDirection.currentText() 132 | if scan_direction == 'Horizontal': 133 | dir = 'H' 134 | else: 135 | dir = 'V' 136 | self.image_to_bw.setScanDirection(dir) 137 | 138 | def displayByteDirectionSetting(self): 139 | byte_direction = self.main_ui.comboBox_displayByteDirection.currentText() 140 | if byte_direction == 'Horizontal': 141 | dir = 'H' 142 | else: 143 | dir = 'V' 144 | self.image_to_bw.setByteDirection(dir) 145 | 146 | def displaySignBitSetting(self): 147 | sign_bit = self.main_ui.comboBox_displaySignBit.currentText() 148 | self.image_to_bw.setSignBit(sign_bit) 149 | 150 | def exit(self): 151 | if self.portOpened: 152 | self.serial.close() 153 | self.imageModeWindow.exit() 154 | self.videoModeWindow.exit() 155 | self.screenModeWindow.exit() 156 | self.image_translator.stop() 157 | 158 | 159 | if __name__ == '__main__': 160 | import sys 161 | from PyQt5.QtWidgets import QApplication 162 | 163 | app = QApplication(sys.argv) 164 | 165 | window = MainWindow() 166 | 167 | sys.exit(app.exec_()) 168 | 169 | window.exit() 170 | -------------------------------------------------------------------------------- /python_gui/window/screenMode_Window.py: -------------------------------------------------------------------------------- 1 | 2 | from PyQt5.QtGui import QPixmap 3 | from PyQt5.QtCore import QTimer 4 | from PyQt5 import QtCore 5 | 6 | from image_processing.Qt2CV import OpenCVImage2QPixMap 7 | from window.screenSample_Window import ScreenSampleWindow 8 | from image_processing.image_translate import ImageTranslate, OutputImagesStructure 9 | 10 | 11 | class ScreenModeWindow(object): 12 | 13 | def __init__(self, window, main_ui): 14 | self.main_ui = main_ui 15 | self.window = window 16 | 17 | # sample window 18 | self.sample_window = ScreenSampleWindow() 19 | self.sample_window.setWindowOpacity(0.01) 20 | self.sample_window.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) 21 | self.sample_window.resize(800, 600) 22 | 23 | # init image translator 24 | self.image_translator = ImageTranslate() 25 | self.images = OutputImagesStructure() 26 | self.screen_image = None 27 | h = self.main_ui.label_screenPreviewWindow.height() 28 | w = self.main_ui.label_screenPreviewWindow.width() 29 | self.image_translator.set_preview_size(w, h) 30 | self.image_translator.start() 31 | 32 | # init signal and slot 33 | self.init_signal() 34 | 35 | # serial send method 36 | self.sendMethod = None 37 | 38 | # timer 39 | self.drawRectTimer = QTimer(self.window) 40 | self.drawRectTimer.setTimerType(0) 41 | self.drawRectTimer.timeout.connect(self.sampleWindowUpdate) 42 | 43 | self.screenShotTimer = QTimer(self.window) 44 | self.screenShotTimer.setTimerType(0) 45 | self.screenShotTimer.timeout.connect(self.screenImageGet) 46 | 47 | def init_signal(self): 48 | # connect signal and slot 49 | # tab widget 50 | self.main_ui.tabWidget.currentChanged.connect(self.tab_changed) 51 | # pop sample button 52 | self.main_ui.pbt_screenSampleWindow.clicked.connect(self.openSampleWindow) 53 | self.main_ui.checkBox_sampleWindowShowOnTop.clicked.connect(self.sampleWindowShowMode) 54 | # Threshold value 55 | self.main_ui.spinBox_screenBWThreshold.valueChanged['int'].connect(self.main_ui.horizontalSlider_screenBWThreshold.setValue) 56 | self.main_ui.horizontalSlider_screenBWThreshold.valueChanged['int'].connect(self.main_ui.spinBox_screenBWThreshold.setValue) 57 | self.videoBWThresholdValue = 127 58 | self.main_ui.spinBox_screenBWThreshold.valueChanged.connect(self.BWThresholdValueUpdate) 59 | self.previewBWSize = '2X' 60 | self.main_ui.checkBox_screenPreviewBW2x.clicked.connect(self.previewBWSizeUpdate) 61 | 62 | # BM invert 63 | self.main_ui.checkBox_screenBWInvert.clicked.connect(self.BWInvertUpdate) 64 | self.screenBWInvert = False 65 | 66 | # preview mode 67 | self.main_ui.radioButton_screenPreviewRaw.clicked.connect(self.previewModeUpdate) 68 | self.main_ui.radioButton_screenPreviewGray.clicked.connect(self.previewModeUpdate) 69 | self.main_ui.radioButton_screenPreviewBW.clicked.connect(self.previewModeUpdate) 70 | self.previewMode = 'raw' 71 | 72 | # send frame signal 73 | self.main_ui.pbt_screenStartSending.clicked.connect(self.sendModeUpdate) 74 | self.screenSending = False 75 | 76 | self.setScreenWidgetEnable(False) 77 | 78 | # init tab and install image mode callback for image translator 79 | self.tab_changed() 80 | 81 | """ 82 | There only one image translator instance, so we must install the current callback when mode is changed. 83 | """ 84 | def tab_changed(self): 85 | index = self.main_ui.tabWidget.currentIndex() 86 | tab_name = self.main_ui.tabWidget.tabText(index) 87 | print(tab_name) 88 | if tab_name == 'Screen': 89 | self.image_translator.output_clean() 90 | self.image_translator.install_complete_callback(self.image_translate_complete) 91 | 92 | def setScreenWidgetEnable(self, enable): 93 | self.main_ui.spinBox_screenBWThreshold.setEnabled(enable) 94 | self.main_ui.horizontalSlider_screenBWThreshold.setEnabled(enable) 95 | self.main_ui.checkBox_screenBWInvert.setEnabled(enable) 96 | self.main_ui.checkBox_screenPreviewBW2x.setEnabled(enable) 97 | 98 | self.main_ui.radioButton_screenPreviewRaw.setEnabled(enable) 99 | self.main_ui.radioButton_screenPreviewGray.setEnabled(enable) 100 | self.main_ui.radioButton_screenPreviewBW.setEnabled(enable) 101 | 102 | self.main_ui.pbt_screenStartSending.setEnabled(enable) 103 | 104 | if enable == True: 105 | self.main_ui.pbt_screenSampleWindow.setText('Close Sample Window') 106 | else: 107 | self.main_ui.pbt_screenSampleWindow.setText('Open Sample Window') 108 | 109 | def openSampleWindow(self): 110 | if self.sample_window.isHidden(): 111 | self.setScreenWidgetEnable(True) 112 | self.main_ui.checkBox_sampleWindowShowOnTop.setEnabled(False) 113 | self.sample_window.show() 114 | self.drawRectTimer.start(30) 115 | self.screenShotTimer.start(10) 116 | else: 117 | self.setScreenWidgetEnable(False) 118 | self.main_ui.checkBox_sampleWindowShowOnTop.setEnabled(True) 119 | if self.screenSending: 120 | self.sendModeUpdate() 121 | self.sample_window.hide() 122 | self.drawRectTimer.stop() 123 | self.screenShotTimer.stop() 124 | 125 | def sampleWindowShowMode(self): 126 | if self.main_ui.checkBox_sampleWindowShowOnTop.isChecked(): 127 | self.sample_window.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) 128 | else: 129 | self.sample_window.setWindowFlags(QtCore.Qt.Widget) 130 | 131 | def sampleWindowUpdate(self): 132 | if self.sample_window.isHidden(): 133 | self.drawRectTimer.stop() 134 | return None 135 | self.sample_window.draw_rect() 136 | 137 | def screenImageGet(self): 138 | self.screen_image = self.sample_window.get_window_image() 139 | self.image_translator.input_image(self.screen_image) 140 | if self.screenSending: 141 | self.updatePreview() 142 | self.updateBWPreview() 143 | self.send(self.images.bytes) 144 | 145 | def BWThresholdValueUpdate(self): 146 | threshold = self.main_ui.spinBox_screenBWThreshold.value() 147 | self.image_translator.set_threshold(threshold) 148 | if not self.screenSending: 149 | self.image_translator.input_image(self.screen_image) 150 | 151 | def previewBWSizeUpdate(self): 152 | if self.main_ui.checkBox_screenPreviewBW2x.isChecked(): 153 | self.previewBWSize = '2X' 154 | else: 155 | self.previewBWSize = '1X' 156 | 157 | self.updateBWPreview() 158 | 159 | def BWInvertUpdate(self): 160 | if self.main_ui.checkBox_screenBWInvert.isChecked(): 161 | self.image_translator.set_invert(True) 162 | else: 163 | self.image_translator.set_invert(False) 164 | 165 | if not self.screenSending: 166 | self.image_translator.input_image(self.screen_image) 167 | 168 | def previewModeUpdate(self): 169 | if self.main_ui.radioButton_screenPreviewRaw.isChecked(): 170 | self.previewMode = 'raw' 171 | elif self.main_ui.radioButton_screenPreviewGray.isChecked(): 172 | self.previewMode = 'gray' 173 | else: 174 | self.previewMode = 'bw' 175 | 176 | self.updatePreview() 177 | 178 | def updatePreview(self): 179 | # update preview 180 | if self.previewMode == 'raw': 181 | image = self.images.raw 182 | elif self.previewMode == 'gray': 183 | image = self.images.gray 184 | else: 185 | image = self.images.bw 186 | 187 | image_pix = OpenCVImage2QPixMap(image) 188 | self.main_ui.label_screenPreviewWindow.setPixmap(QPixmap.fromImage(image_pix)) 189 | 190 | def updateBWPreview(self): 191 | if self.previewBWSize == '2X': 192 | image = self.images.output_bw2x 193 | else: 194 | image = self.images.output_bw 195 | 196 | image_pix = OpenCVImage2QPixMap(image) 197 | self.main_ui.label_screenPreviewOutputBW.setPixmap(QPixmap.fromImage(image_pix)) 198 | 199 | def image_translate_complete(self, images_queue): 200 | count = images_queue.qsize() 201 | for i in range(count): 202 | self.images = images_queue.get() 203 | 204 | if not self.screenSending: 205 | self.updatePreview() 206 | self.updateBWPreview() 207 | 208 | def sendModeUpdate(self): 209 | if self.screenSending: 210 | self.screenSending = False 211 | self.main_ui.pbt_screenStartSending.setText('Start Sending') 212 | self.screenShotTimer.setInterval(10) 213 | else: 214 | self.screenSending = True 215 | self.main_ui.pbt_screenStartSending.setText('Stop Sending') 216 | fps = self.main_ui.spinBox_screenSendFramerate.value() 217 | self.screenShotTimer.setInterval(int(1000/fps)) 218 | 219 | def addSendMethod(self, sendMethod): 220 | self.sendMethod = sendMethod 221 | 222 | def send(self, data): 223 | if self.sendMethod != None: 224 | self.sendMethod.send(data) 225 | 226 | def exit(self): 227 | self.sample_window.stop() 228 | # self.sample_window.destroy() 229 | self.screenShotTimer.stop() 230 | self.drawRectTimer.stop() -------------------------------------------------------------------------------- /python_gui/window/screenSample_Window.py: -------------------------------------------------------------------------------- 1 | 2 | from PyQt5.QtWidgets import QWidget 3 | from PyQt5.QtCore import Qt 4 | 5 | from UI.screenSampleWindow import Ui_Form_screenSampleWindow 6 | 7 | from screen import ScreenDraw, ScreenGet 8 | from image_processing.Qt2CV import QPixmap2OpenCVImage 9 | 10 | import time 11 | 12 | 13 | class ScreenSampleWindow(QWidget): 14 | 15 | def __init__(self): 16 | super(ScreenSampleWindow, self).__init__() 17 | 18 | # mouse tracking 19 | self.setMouseTracking(True) 20 | self.mouse_button_pressed = False 21 | self.last_mouse_track_time = 0 22 | 23 | # connect window ui and Widget 24 | self.window_ui = Ui_Form_screenSampleWindow() 25 | self.window_ui.setupUi(self) 26 | self.window_ui.retranslateUi(self) 27 | 28 | # draw screen 29 | self.screen = ScreenDraw() 30 | self.screen.setPenColor(255, 0, 0) 31 | self.setWindowFlags(Qt.WindowMinimizeButtonHint) 32 | 33 | # screen shot 34 | self.screenShot = ScreenGet() 35 | self.screenShot.start() 36 | 37 | self.show() 38 | 39 | def draw_rect(self): 40 | result = self.geometry() 41 | x, y, w, h = result.x(), result.y(), result.width(), result.height() 42 | 43 | self.screen.drawRect(x, y, w, h) 44 | 45 | def get_window_image(self): 46 | result = self.geometry() 47 | x, y, w, h = result.x(), result.y(), result.width(), result.height() 48 | pixmap = self.screenShot.getScreen(x, y, w, h) 49 | image = pixmap.toImage() 50 | return QPixmap2OpenCVImage(image) 51 | 52 | def mousePressEvent(self, event): 53 | if event.buttons() == Qt.LeftButton: 54 | if not self.mouse_button_pressed: 55 | self.mouse_button_pressed = True 56 | self.dx = event.globalX() - self.x() 57 | self.dy = event.globalY() - self.y() 58 | event.accept() 59 | else: 60 | if self.mouse_button_pressed: 61 | self.mouse_button_pressed = False 62 | event.accept() 63 | 64 | def mouseMoveEvent(self, event): 65 | # mouse move tracking don't need too fast, otherwise it will crash 66 | current_time = time.time() 67 | if current_time < self.last_mouse_track_time + 0.1: 68 | return None 69 | self.last_mouse_track_time = current_time 70 | 71 | if self.mouse_button_pressed: 72 | x = event.globalX() 73 | y = event.globalY() 74 | self.move(x - self.dx, y - self.dy) 75 | 76 | def stop(self): 77 | self.screenShot.stop() 78 | 79 | 80 | -------------------------------------------------------------------------------- /python_gui/window/videoMode_Window.py: -------------------------------------------------------------------------------- 1 | 2 | from PyQt5.QtWidgets import QFileDialog 3 | from PyQt5.QtGui import QPixmap 4 | from PyQt5.QtCore import QTimer 5 | 6 | from os import path 7 | import time 8 | from image_processing.Qt2CV import OpenCVImage2QPixMap 9 | import cv2 as cv 10 | from image_processing.image_translate import ImageTranslate, OutputImagesStructure 11 | 12 | class VideoModeWindow(object): 13 | 14 | def __init__(self, window, main_ui): 15 | self.main_ui = main_ui 16 | self.window = window 17 | 18 | # init image translator 19 | self.image_translator = ImageTranslate() 20 | self.image_translator.start() 21 | self.images = OutputImagesStructure() 22 | self.video = None 23 | self.video_frame = None 24 | self.video_frame_index = 0 25 | self.video_frames = 0 26 | 27 | # init signal and slot 28 | self.init_signal() 29 | 30 | # send method 31 | self.sendMethod = None 32 | 33 | # timer 34 | self.timer = QTimer(self.window) 35 | self.timer.setTimerType(0) # Precise timers try to keep millisecond accuracy 36 | self.timer.timeout.connect(self.videoSendProcess) 37 | 38 | # remember last slider 39 | self.lastSliderTime = 0 40 | 41 | def init_signal(self): 42 | # connect signal and slot 43 | # tab widget 44 | self.main_ui.tabWidget.currentChanged.connect(self.tab_changed) 45 | # Threshold value 46 | self.main_ui.spinBox_videoBWThreshold.valueChanged['int'].connect(self.main_ui.horizontalSlider_videoBWThreshold.setValue) 47 | self.main_ui.horizontalSlider_videoBWThreshold.valueChanged['int'].connect(self.main_ui.spinBox_videoBWThreshold.setValue) 48 | self.videoBWThresholdValue = 127 49 | self.main_ui.spinBox_videoBWThreshold.valueChanged.connect(self.videoBWThresholdValueUpdate) 50 | self.videoPreviewBWSize = '2X' 51 | self.main_ui.checkBox_videoPreviewBW2x.clicked.connect(self.previewBWSizeUpdate) 52 | # import image 53 | self.main_ui.pbt_videoOpenFile.clicked.connect(self.openVideo) 54 | self.lastFolderPath = '' 55 | # BM invert 56 | self.main_ui.checkBox_videoBWInvert.clicked.connect(self.BWInvertUpdate) 57 | self.videoBWInvert = False 58 | # preview mode 59 | self.main_ui.radioButton_videoPreviewRaw.clicked.connect(self.previewModeUpdate) 60 | self.main_ui.radioButton_videoPreviewGray.clicked.connect(self.previewModeUpdate) 61 | self.main_ui.radioButton_videoPreviewBW.clicked.connect(self.previewModeUpdate) 62 | self.previewMode = 'raw' 63 | self.main_ui.horizontalSlider_videoPreviewFrameOffset.valueChanged.connect(self.previewSilderUpdate) 64 | self.main_ui.horizontalSlider_videoPreviewFrameOffset.valueChanged['int'].connect(self.main_ui.spinBox_videoFrameOffset.setValue) 65 | self.main_ui.spinBox_videoFrameOffset.valueChanged['int'].connect(self.main_ui.horizontalSlider_videoPreviewFrameOffset.setValue) 66 | 67 | # send to OLED 68 | self.main_ui.pbt_videoStartSending.clicked.connect(self.videoSendStateUpdate) 69 | self.videoSendFramerate = 1 70 | self.videoSending = False 71 | 72 | # disable widget before import video file 73 | self.setPreviewSliderAndSpinboxEnable(False) 74 | self.setVideoWidgetEnable(False) 75 | 76 | # init tab and install image mode callback for image translator 77 | self.tab_changed() 78 | 79 | """ 80 | There only one image translator instance, so we must install the current callback when mode is changed. 81 | """ 82 | def tab_changed(self): 83 | index = self.main_ui.tabWidget.currentIndex() 84 | tab_name = self.main_ui.tabWidget.tabText(index) 85 | print(tab_name) 86 | if tab_name == 'Video': 87 | self.image_translator.output_clean() 88 | self.image_translator.install_complete_callback(self.image_translate_complete) 89 | 90 | def setPreviewSliderAndSpinboxEnable(self, enable): 91 | self.main_ui.horizontalSlider_videoPreviewFrameOffset.setEnabled(enable) 92 | self.main_ui.spinBox_videoFrameOffset.setEnabled(enable) 93 | self.main_ui.spinBox_videoSendFramerate.setEnabled(enable) 94 | 95 | def setVideoWidgetEnable(self, enable): 96 | self.main_ui.spinBox_videoBWThreshold.setEnabled(enable) 97 | self.main_ui.horizontalSlider_videoBWThreshold.setEnabled(enable) 98 | self.main_ui.checkBox_videoBWInvert.setEnabled(enable) 99 | self.main_ui.checkBox_videoPreviewBW2x.setEnabled(enable) 100 | 101 | self.main_ui.radioButton_videoPreviewRaw.setEnabled(enable) 102 | self.main_ui.radioButton_videoPreviewGray.setEnabled(enable) 103 | self.main_ui.radioButton_videoPreviewBW.setEnabled(enable) 104 | 105 | self.main_ui.pbt_videoStartSending.setEnabled(enable) 106 | 107 | def openVideo(self): 108 | filename, filetype = QFileDialog.getOpenFileName(self.window, 'Select a video file', self.lastFolderPath) 109 | if filename != '': 110 | self.lastFolderPath = path.dirname(filename) 111 | self.main_ui.lineEdit_videoFileName.setText(filename) 112 | # self.video.open(filename) 113 | self.video = cv.VideoCapture(filename) 114 | 115 | # get video info 116 | fps = int(self.video.get(cv.CAP_PROP_FPS)) 117 | self.video_frames = int(self.video.get(cv.CAP_PROP_FRAME_COUNT)) 118 | # update ui 119 | self.main_ui.lineEdit_videoInfoFramerate.setText('%d' % fps) 120 | self.main_ui.lineEdit_videoInfoDuration.setText('%d|%.1f' % (self.video_frames, self.video_frames / fps)) 121 | self.main_ui.horizontalSlider_videoPreviewFrameOffset.setMinimum(0) 122 | self.main_ui.horizontalSlider_videoPreviewFrameOffset.setMaximum(self.video_frames-1) 123 | self.main_ui.spinBox_videoFrameOffset.setMinimum(0) 124 | self.main_ui.spinBox_videoFrameOffset.setMaximum(self.video_frames-1) 125 | self.main_ui.horizontalSlider_videoPreviewFrameOffset.setSliderPosition(0) 126 | 127 | self.setPreviewSliderAndSpinboxEnable(True) 128 | self.setVideoWidgetEnable(True) 129 | 130 | # translate first frame 131 | ret, self.video_frame = self.video.read() 132 | h, w, n = self.video_frame.shape 133 | k = w / h 134 | height = self.main_ui.label_videoPreviewWindow.height() 135 | width = int(k * height) - 1 136 | self.image_translator.set_preview_size(width, height) 137 | self.image_translator.input_image(self.video_frame) 138 | 139 | def videoBWThresholdValueUpdate(self): 140 | threshold = self.main_ui.spinBox_videoBWThreshold.value() 141 | 142 | self.image_translator.set_threshold(threshold) 143 | if not self.videoSending: 144 | self.image_translator.input_image(self.video_frame) 145 | 146 | def previewBWSizeUpdate(self): 147 | if self.main_ui.checkBox_videoPreviewBW2x.isChecked(): 148 | self.videoPreviewBWSize = '2X' 149 | else: 150 | self.videoPreviewBWSize = '1X' 151 | 152 | self.updateBWPreview() 153 | 154 | def BWInvertUpdate(self): 155 | if self.main_ui.checkBox_videoBWInvert.isChecked(): 156 | self.image_translator.set_invert(True) 157 | else: 158 | self.image_translator.set_invert(False) 159 | 160 | if not self.videoSending: 161 | self.image_translator.input_image(self.video_frame) 162 | 163 | def previewModeUpdate(self): 164 | if self.main_ui.radioButton_videoPreviewRaw.isChecked(): 165 | self.previewMode = 'raw' 166 | elif self.main_ui.radioButton_videoPreviewGray.isChecked(): 167 | self.previewMode = 'gray' 168 | else: 169 | self.previewMode = 'BW' 170 | 171 | self.updatePreview() 172 | 173 | def previewSilderUpdate(self): 174 | if self.videoSending: 175 | return None 176 | # the slider don't need response too fast, and this will save some cpu time. 177 | current_time = time.time() 178 | if current_time < self.lastSliderTime + 0.1: 179 | return None 180 | self.lastSliderTime = current_time 181 | # get current slider value 182 | index = self.main_ui.horizontalSlider_videoPreviewFrameOffset.value() 183 | # read frame specified 184 | self.video.set(cv.CAP_PROP_POS_FRAMES, index) 185 | ret, self.video_frame = self.video.read() 186 | self.image_translator.input_image(self.video_frame) 187 | 188 | def updatePreview(self): 189 | # update preview 190 | if self.previewMode == 'raw': 191 | image = self.images.raw 192 | elif self.previewMode == 'gray': 193 | image = self.images.gray 194 | else: 195 | image = self.images.bw 196 | image_pix = OpenCVImage2QPixMap(image) 197 | self.main_ui.label_videoPreviewWindow.setPixmap(QPixmap.fromImage(image_pix)) 198 | 199 | def updateBWPreview(self): 200 | if self.videoPreviewBWSize == '2X': 201 | image = self.images.output_bw2x 202 | else: 203 | image = self.images.output_bw 204 | image_pix = OpenCVImage2QPixMap(image) 205 | self.main_ui.label_videoPreviewOutputBW.setPixmap(QPixmap.fromImage(image_pix)) 206 | 207 | def videoSendStateUpdate(self): 208 | if self.videoSending: 209 | self.videoSending = False 210 | self.setPreviewSliderAndSpinboxEnable(True) 211 | self.main_ui.pbt_videoStartSending.setText('Start Sending') 212 | self.timer.stop() 213 | self.image_translator.output_clean() 214 | 215 | else: 216 | self.videoSending = True 217 | self.setPreviewSliderAndSpinboxEnable(False) 218 | self.main_ui.pbt_videoStartSending.setText('Stop Sending') 219 | fps = self.main_ui.spinBox_videoSendFramerate.value() 220 | self.timer.start(int(1000/fps)) 221 | 222 | def videoSendProcess(self): 223 | # read next frame 224 | ret, self.video_frame = self.video.read() 225 | self.image_translator.input_image(self.video_frame) 226 | # update last frame 227 | self.updatePreview() 228 | self.updateBWPreview() 229 | # send to serial 230 | self.send(self.images.bytes) 231 | # update frame index ui 232 | index = int(self.video.get(cv.CAP_PROP_POS_FRAMES)) 233 | self.main_ui.spinBox_videoFrameOffset.setValue(index) 234 | # check if video reach the end 235 | if index >= self.video_frames-1: 236 | self.videoSendStateUpdate() 237 | 238 | def image_translate_complete(self, images_queue): 239 | count = images_queue.qsize() 240 | for i in range(count): 241 | self.images = images_queue.get() 242 | # self.images = images_queue.get() 243 | 244 | if not self.videoSending: 245 | self.updatePreview() 246 | self.updateBWPreview() 247 | 248 | def addSendMethod(self, sendMethod): 249 | self.sendMethod = sendMethod 250 | 251 | def send(self, data): 252 | if self.sendMethod != None: 253 | self.sendMethod.send(data) 254 | 255 | def exit(self): 256 | pass --------------------------------------------------------------------------------