ATtiny85-PhoneChargeGuard icon indicating copy to clipboard operation
ATtiny85-PhoneChargeGuard copied to clipboard

How exactly are these fonts made?

Open parthbhat13 opened this issue 7 months ago • 3 comments

Hi, im so sorry to create a issue, i could not find any direct way to contact you. ive been a big fan of your projects and mainly how you play with the OLED displays and optimize the code. i was trying to use some fonts of yours in my code, but i saw that you have mostly stripped down a lot of things to save the memory. My most favouraite have been the 7 Segment style font. now i was wanting to use some letters like "I" , "A" or even in the big font. but i am so confused on how exactly have you made those fonts that i just was forced to contact you here as an issue. again sorry for that. but can you guide me how can i actually make more alphabets of the following fonts from your different codes.

// OLED 6x16 font
const uint8_t OLED_FONT_BIG[] = {
  0x7C, 0x1F, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x7C, 0x1F, //  0 0
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x1F, //  1 1
  0x00, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x00, //  2 2
  0x00, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, //  3 3
  0x7C, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x7C, 0x1F, //  4 4
  0x7C, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x00, 0x1F, //  5 5
  0x7C, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x00, 0x1F, //  6 6
  0x7C, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7C, 0x1F, //  7 7
  0x7C, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, //  8 8
  0x7C, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, //  9 9
  0x00, 0x00, 0xF0, 0x3F, 0x8C, 0x00, 0x82, 0x00, 0x8C, 0x00, 0xF0, 0x3F, // 10 A
  0x00, 0x00, 0xFE, 0x07, 0x00, 0x18, 0x00, 0x20, 0x00, 0x18, 0xFE, 0x07, // 11 V
  0x00, 0x00, 0xFE, 0x1F, 0x00, 0x20, 0x00, 0x1F, 0x00, 0x20, 0xFE, 0x1F, // 12 W
  0x00, 0x00, 0xFE, 0x3F, 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 0x00, 0x3F, // 13 h
  0x00, 0x00, 0x80, 0x3F, 0x80, 0x00, 0x80, 0x3F, 0x80, 0x00, 0x00, 0x3F, // 14 m
  0x00, 0x00, 0x00, 0x00, 0x30, 0x06, 0x30, 0x06, 0x00, 0x00, 0x00, 0x00, // 15 :
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 16 SPACE
};

another one is for the 7 segment style

// OLED 5x16 font 7 Segment
const uint8_t OLED_FONT[] = {
  0x7C, 0x1F, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x7C, 0x1F, // 0  0
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x1F, // 1  1
  0x00, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x00, // 2  2
  0x00, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, // 3  3
  0x7C, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x7C, 0x1F, // 4  4
  0x7C, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x00, 0x1F, // 5  5
  0x7C, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x00, 0x1F, // 6  6
  0x0C, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7C, 0x1F, // 7  7
  0x7C, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, // 8  8
  0x7C, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, // 9  9
  0xF0, 0x3F, 0x8C, 0x00, 0x82, 0x00, 0x8C, 0x00, 0xF0, 0x3F, // A 10
  0xFE, 0x07, 0x00, 0x18, 0x00, 0x20, 0x00, 0x18, 0xFE, 0x07, // V 11
  0x00, 0x00, 0x30, 0x06, 0x30, 0x06, 0x00, 0x00, 0x00, 0x00, // : 12
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //   13
  0x02, 0x00, 0x02, 0x00, 0x7E, 0x3F, 0x02, 0x00, 0x02, 0x00, // T 14
};

can you please give some guidance? or am i totally missing something? as well these fonts are taking from different projects of yours, im trying to implement this on STM32G030F6P6TR, i do have memory restrictions too. heres the C code attached.

/*
 * SSD1306.c
 *
 *  Created on: Dec 2, 2023
 *      Author: parthasus
 */


#include "stm32g0xx_hal.h"
#include "SSD1306.h"


// extern the i2c handler
extern I2C_HandleTypeDef hi2c2;
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))

// Oled definitions
#define OLED_CMD_MODE   0x00    // set command mode
#define OLED_DAT_MODE   0x40    // set data mode
#define OLED_INIT_LEN   11      // 9: no screen flip, 11: screen flip

// OLED init settings
const uint8_t OLED_INIT_CMD[] = {
  0xA8, 0x1F,                   // set multiplex for 128x32
  0x20, 0x01,                   // set vertical memory addressing mode
  0xDA, 0x02,                   // set COM pins hardware configuration to sequential
  0x8D, 0x14,                   // enable charge pump
  0xAF,                         // switch on OLED
  0xA1, 0xC8                    // flip the screen
};


// OLED current page
uint8_t OLED_page;

// OLED 5x8 font (adapted from Neven Boyanov and Stephen Denne)
const uint8_t OLED_FONT_SMALL[]  = {
  0x3E, 0x51, 0x49, 0x45, 0x3E, //  0 0
  0x00, 0x42, 0x7F, 0x40, 0x00, //  1 1
  0x42, 0x61, 0x51, 0x49, 0x46, //  2 2
  0x21, 0x41, 0x45, 0x4B, 0x31, //  3 3
  0x18, 0x14, 0x12, 0x7F, 0x10, //  4 4
  0x27, 0x45, 0x45, 0x45, 0x39, //  5 5
  0x3C, 0x4A, 0x49, 0x49, 0x30, //  6 6
  0x01, 0x71, 0x09, 0x05, 0x03, //  7 7
  0x36, 0x49, 0x49, 0x49, 0x36, //  8 8
  0x06, 0x49, 0x49, 0x29, 0x1E, //  9 9
  0x7C, 0x12, 0x11, 0x12, 0x7C, // 10 A
  0x1F, 0x20, 0x40, 0x20, 0x1F, // 11 V
  0x3F, 0x40, 0x38, 0x40, 0x3F, // 12 W
  0x7F, 0x08, 0x04, 0x04, 0x78, // 13 h
  0x7C, 0x04, 0x18, 0x04, 0x78, // 14 m
  0x00, 0x36, 0x36, 0x00, 0x00, // 15 :
  0x00, 0x00, 0x00, 0x00, 0x00, // 16 SPACE
  0x3E, 0x41, 0x41, 0x41, 0x22, // 17 C
  0x7F, 0x49, 0x49, 0x49, 0x41, // 18 E
  0x3E, 0x41, 0x49, 0x49, 0x7A, // 19 G
  0x7F, 0x08, 0x08, 0x08, 0x7F, // 20 H
  0x00, 0x41, 0x7F, 0x41, 0x00, // 21 I
  0x7F, 0x40, 0x40, 0x40, 0x40, // 22 L
  0x7F, 0x02, 0x0C, 0x02, 0x7F, // 23 M
  0x7F, 0x09, 0x09, 0x09, 0x06, // 24 P
  0x7F, 0x09, 0x19, 0x29, 0x46, // 25 R
  0x46, 0x49, 0x49, 0x49, 0x31, // 26 S
  0x01, 0x01, 0x7F, 0x01, 0x01, // 27 T
  0x3F, 0x40, 0x40, 0x40, 0x3F, // 28 U
  0x00, 0x44, 0x7D, 0x40, 0x00, // 29 i
  0x7C, 0x08, 0x04, 0x04, 0x78,  // 30 n
  0x7F, 0x41, 0x41, 0x22, 0x1C, // D 31
  0x00, 0x60, 0x60, 0x00, 0x00, // . 32
};
// OLED 6x16 font
const uint8_t OLED_FONT_BIG[] = {
  0x7C, 0x1F, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x7C, 0x1F, //  0 0
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x1F, //  1 1
  0x00, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x00, //  2 2
  0x00, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, //  3 3
  0x7C, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x7C, 0x1F, //  4 4
  0x7C, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x00, 0x1F, //  5 5
  0x7C, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x00, 0x1F, //  6 6
  0x7C, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7C, 0x1F, //  7 7
  0x7C, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, //  8 8
  0x7C, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, //  9 9
  0x00, 0x00, 0xF0, 0x3F, 0x8C, 0x00, 0x82, 0x00, 0x8C, 0x00, 0xF0, 0x3F, // 10 A
  0x00, 0x00, 0xFE, 0x07, 0x00, 0x18, 0x00, 0x20, 0x00, 0x18, 0xFE, 0x07, // 11 V
  0x00, 0x00, 0xFE, 0x1F, 0x00, 0x20, 0x00, 0x1F, 0x00, 0x20, 0xFE, 0x1F, // 12 W
  0x00, 0x00, 0xFE, 0x3F, 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 0x00, 0x3F, // 13 h
  0x00, 0x00, 0x80, 0x3F, 0x80, 0x00, 0x80, 0x3F, 0x80, 0x00, 0x00, 0x3F, // 14 m
  0x00, 0x00, 0x00, 0x00, 0x30, 0x06, 0x30, 0x06, 0x00, 0x00, 0x00, 0x00, // 15 :
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 16 SPACE

};

// OLED 5x16 font 7 Segment
const uint8_t OLED_FONT[] = {
  0x7C, 0x1F, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x7C, 0x1F, // 0  0
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x1F, // 1  1
  0x00, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x00, // 2  2
  0x00, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, // 3  3
  0x7C, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x7C, 0x1F, // 4  4
  0x7C, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x00, 0x1F, // 5  5
  0x7C, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x00, 0x1F, // 6  6
  0x0C, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7C, 0x1F, // 7  7
  0x7C, 0x1F, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, // 8  8
  0x7C, 0x00, 0x82, 0x20, 0x82, 0x20, 0x82, 0x20, 0x7C, 0x1F, // 9  9
  0xF0, 0x3F, 0x8C, 0x00, 0x82, 0x00, 0x8C, 0x00, 0xF0, 0x3F, // A 10
  0xFE, 0x07, 0x00, 0x18, 0x00, 0x20, 0x00, 0x18, 0xFE, 0x07, // V 11
  0x00, 0x00, 0x30, 0x06, 0x30, 0x06, 0x00, 0x00, 0x00, 0x00, // : 12
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //   13
  0x02, 0x00, 0x02, 0x00, 0x7E, 0x3F, 0x02, 0x00, 0x02, 0x00, // T 14
};

// Internal Function Prototype
void i2cWrite(uint8_t oledAddr, uint8_t oledReg, uint8_t oledData);


// global functions
uint8_t dispInit()
{
	if(HAL_I2C_IsDeviceReady(&hi2c2, OLED_ADDR, 2, 2000) != HAL_OK)
	{
		return 0;
	}

	for(uint8_t i = 0; i < OLED_INIT_LEN; i++)
	{
		i2cWrite(OLED_ADDR, OLED_CMD_MODE, OLED_INIT_CMD[i]);
	}

	return 1;
}

void dispSetCursor(uint8_t xPos, uint8_t yPos)
{
	i2cWrite(OLED_ADDR, OLED_CMD_MODE, 0x22);
	i2cWrite(OLED_ADDR, OLED_CMD_MODE, yPos);

	(yPos > 1) ? (i2cWrite(OLED_ADDR, OLED_CMD_MODE, 3)) : (i2cWrite(OLED_ADDR, OLED_CMD_MODE, yPos));

	i2cWrite(OLED_ADDR, OLED_CMD_MODE, xPos & 0x0F);
	i2cWrite(OLED_ADDR, OLED_CMD_MODE, 0x10 | (xPos >> 4));
	i2cWrite(OLED_ADDR, OLED_CMD_MODE, 0xB0 | (yPos));
	OLED_page = yPos;
}

void dispClearScreen(void)
{
	uint8_t i;
	dispSetCursor(0, 0);
	for(i = OLED_WIDTH; i; i--) i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00);

	dispSetCursor(0, 1);
	for(i = OLED_WIDTH; i; i--) i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x02);

	dispSetCursor(0, 2);
	do { i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00); } while (--i);
}

void dispPlotChar(uint8_t ch)
{
	if(OLED_page)
	{
		ch = (ch << 3) + (ch << 2);
		i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00);
		i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00);
		for(uint8_t i = 12; i; i--)
			i2cWrite(OLED_ADDR, OLED_DAT_MODE, pgm_read_byte(&OLED_FONT_BIG[ch++]));
		i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00);
		i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00);
	}
	else
	{
		ch += (ch << 2);
		i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00);
		for(uint8_t i = 5; i; i--)
			i2cWrite(OLED_ADDR, OLED_DAT_MODE, pgm_read_byte(&OLED_FONT_SMALL[ch++]));
		//i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00);
		//i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00);
	}
}

void dispPlotSevenSegment(uint8_t xPos, uint8_t yPos, uint8_t ch)
{
	i2cWrite(OLED_ADDR, OLED_CMD_MODE, 0x22);
	i2cWrite(OLED_ADDR, OLED_CMD_MODE, yPos);

	(yPos > 1) ? (i2cWrite(OLED_ADDR, OLED_CMD_MODE, 3)) : (i2cWrite(OLED_ADDR, OLED_CMD_MODE, yPos));

	i2cWrite(OLED_ADDR, OLED_CMD_MODE, xPos & 0x0F);
	i2cWrite(OLED_ADDR, OLED_CMD_MODE, 0x10 | (xPos >> 4));
	i2cWrite(OLED_ADDR, OLED_CMD_MODE, 0xB0 | (yPos));

	ch = (ch << 1) + (ch << 3);
	i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00);
	i2cWrite(OLED_ADDR, OLED_DAT_MODE, 0x00);
	for(uint8_t i = 10; i; i--)
		i2cWrite(OLED_ADDR, OLED_DAT_MODE, pgm_read_byte(&OLED_FONT[ch++]));
}


void dispPrintChar(uint8_t ch)
{
	dispPlotChar(ch);
}

void dispPrint(const uint8_t *p)
{
	uint8_t ch = pgm_read_byte(p);
	while(ch < 255)
	{
		dispPlotChar(ch);
		 ch = pgm_read_byte(++p);
	}
}


// internal functions
void i2cWrite(uint8_t oledAddr, uint8_t oledReg, uint8_t oledData)
{
	uint8_t data[2];
	data[0] = oledReg;
	data[1] = oledData;

	HAL_I2C_Master_Transmit(&hi2c2, oledAddr, data, 2, 20);
}

parthbhat13 avatar Dec 02 '23 14:12 parthbhat13