├── 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
--------------------------------------------------------------------------------