adc/microphone_adc - Read analog values from a microphone and plot the measured sound amplitude. i2c/bmp280_i2c - Read and convert temperature and pressure data from a BMP280 sensor, attached to an I2C bus. i2c/lis3dh_i2c - Read acceleration and temperature value from a LIS3DH sensor via I2C i2c/mcp9808_i2c - Read temperature, set limits and raise alerts when limits are surpassed. i2c/mma8451_i2c - Read acceleration from a MMA8451 accelerometer and set range and precision for the data. i2c/mpl3115a2_i2c - Interface with an MPL3115A2 altimeter, exploring interrupts and advanced board features, via I2C. i2c/oled_i2c - Convert and display a bitmap on a 128x32 SSD1306-driven OLED display i2c/pa1010d_i2c - Read GPS location data, parse and display data via I2C. i2c/pcf8523_i2c - Read time and date values from a real time clock. Set current time and alarms on it. uart/lcd_uart - Display text and symbols on a 16x02 RGB LCD display via UART
		
			
				
	
	
		
			82 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| 
 | |
| # Converts a grayscale image into a format able to be
 | |
| # displayed by the SSD1306 driver in horizontal addressing mode
 | |
| 
 | |
| # usage: python3 img_to_array.py <logo.bmp>
 | |
| 
 | |
| # depends on the Pillow library
 | |
| # `python3 -m pip install --upgrade Pillow`
 | |
| 
 | |
| from PIL import Image
 | |
| import sys
 | |
| from pathlib import Path
 | |
| 
 | |
| OLED_HEIGHT = 32
 | |
| OLED_WIDTH = 128
 | |
| OLED_PAGE_HEIGHT = 8
 | |
| 
 | |
| if len(sys.argv) < 2:
 | |
|     print("No image path provided.")
 | |
|     sys.exit()
 | |
| 
 | |
| img_path = sys.argv[1]
 | |
| 
 | |
| try:
 | |
|     im = Image.open(img_path)
 | |
| except OSError:
 | |
|     raise Exception("Oops! The image could not be opened.")
 | |
| 
 | |
| img_width = im.size[0]
 | |
| img_height = im.size[1]
 | |
| 
 | |
| if img_width > OLED_WIDTH or img_height > OLED_HEIGHT:
 | |
|     print(f'Your image is f{img_width} pixels wide and {img_height} pixels high, but...')
 | |
|     raise Exception(f"OLED display only {OLED_WIDTH} pixels wide and {OLED_HEIGHT} pixels high!")
 | |
| 
 | |
| if not (im.mode == "1" or im.mode == "L"):
 | |
|     raise Exception("Image must be grayscale only")
 | |
| 
 | |
| # black or white
 | |
| out = im.convert("1")
 | |
| 
 | |
| img_name = Path(im.filename).stem
 | |
| 
 | |
| # `pixels` is a flattened array with the top left pixel at index 0
 | |
| # and bottom right pixel at the width*height-1
 | |
| pixels = list(out.getdata())
 | |
| 
 | |
| # swap white for black and swap (255, 0) for (1, 0)
 | |
| pixels = [0 if x == 255 else 1 for x in pixels]
 | |
| 
 | |
| # our goal is to divide the image into 8-pixel high pages
 | |
| # and turn a pixel column into one byte, eg for one page:
 | |
| # 0 1 0 ....
 | |
| # 1 0 0
 | |
| # 1 1 1
 | |
| # 0 0 1
 | |
| # 1 1 0
 | |
| # 0 1 0
 | |
| # 1 1 1
 | |
| # 0 0 1 ....
 | |
| 
 | |
| # we get 0x6A, 0xAE, 0x33 ... and so on
 | |
| # as `pixels` is flattened, each bit in a column is IMG_WIDTH apart from the next
 | |
| 
 | |
| buffer = []
 | |
| for i in range(img_height // OLED_PAGE_HEIGHT):
 | |
|     start_index = i*img_width*OLED_PAGE_HEIGHT
 | |
|     for j in range(img_width):
 | |
|         out_byte = 0
 | |
|         for k in range(OLED_PAGE_HEIGHT):
 | |
|             out_byte |= pixels[k*img_width + start_index + j] << k
 | |
|         buffer.append(f'{out_byte:#04x}')
 | |
| 
 | |
| buffer = ", ".join(buffer)
 | |
| buffer_hex = f'static uint8_t {img_name}[] = {{{buffer}}}\n'
 | |
| 
 | |
| with open(f'{img_name}.h', 'wt') as file:
 | |
|     file.write(f'#define IMG_WIDTH {img_width}\n')
 | |
|     file.write(f'#define IMG_HEIGHT {img_height}\n\n')
 | |
|     file.write(buffer_hex)
 |