816 lines
24 KiB
C
816 lines
24 KiB
C
#include "ssd1306.h"
|
||
#include <math.h>
|
||
#include <stdlib.h>
|
||
#include <string.h> // For memcpy
|
||
#include "my.h" // For memcpy
|
||
#include "OLED_Fonts.h"
|
||
|
||
|
||
extern __IO bool por;
|
||
extern __IO bool clbr;
|
||
const char SERIAL[] ={'0','2','3'};
|
||
extern __IO UserData_TypeDef currentData, pardata_old;
|
||
|
||
__IO uint8_t DMA_Ready = 0;
|
||
|
||
const uint8_t SAVE_LOGO[8] =
|
||
{
|
||
0x10, 0x30, 0x7F, 0xFF, 0xFF, 0x7F, 0x30, 0x10,
|
||
};
|
||
|
||
|
||
const uint8_t logo_new[64 * 3] = {
|
||
0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0x00, 0x00, 0x00, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00,
|
||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00,
|
||
0x3E, 0xFF, 0xFF, 0xFF, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01,
|
||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
|
||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xFF, 0xFF, 0xFF, 0x3E, 0x00,
|
||
0x00, 0x30, 0x71, 0x7B, 0xFB, 0xF3, 0xF3, 0xF3, 0xF3, 0x7F, 0x7F, 0x3F, 0x1F, 0x00, 0x00, 0x00,
|
||
0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03,
|
||
0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00,
|
||
0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00
|
||
};
|
||
|
||
|
||
const uint8_t Logo128x24[128 * 3] = {
|
||
0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC, 0x7E, 0x3E, 0x3E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
|
||
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00,
|
||
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0x1F,
|
||
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0xE0, 0xF8, 0xFC, 0xFC, 0xFE, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E,
|
||
0x3E, 0x7E, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0xFE, 0xFC, 0xFC, 0xF8, 0xE0,
|
||
0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x7F, 0x7E, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0,
|
||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00,
|
||
0x00, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||
0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F
|
||
};
|
||
|
||
|
||
const uint8_t LOGO[] = {
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F,
|
||
0x0F, 0x0F, 0x07, 0x07, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x0F, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
|
||
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
|
||
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0,
|
||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F,
|
||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
|
||
0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
|
||
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
|
||
0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF8, 0xF8,
|
||
0xF0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||
};
|
||
|
||
|
||
|
||
uint8_t logo[16*64] = {0};
|
||
uint8_t rx[SSD1306_BUFFER_SIZE];
|
||
|
||
extern const char SERIAL[];
|
||
|
||
#if defined(SSD1306_USE_I2C)
|
||
|
||
void ssd1306_Reset(void) {
|
||
/* for I2C - do nothing */
|
||
}
|
||
|
||
// Send a byte to the command register
|
||
void ssd1306_WriteCommand(uint8_t byte) {
|
||
HAL_I2C_Mem_Write(&SSD1306_I2C_PORT, SSD1306_I2C_ADDR, 0x00, 1, &byte, 1, HAL_MAX_DELAY);
|
||
}
|
||
|
||
// Send data
|
||
void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) {
|
||
HAL_I2C_Mem_Write(&SSD1306_I2C_PORT, SSD1306_I2C_ADDR, 0x40, 1, buffer, buff_size, HAL_MAX_DELAY);
|
||
}
|
||
|
||
#elif defined(SSD1306_USE_SPI)
|
||
|
||
void ssd1306_Reset(void) {
|
||
// CS = High (not selected)
|
||
HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET);
|
||
|
||
// Reset the OLED
|
||
HAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_RESET);
|
||
HAL_Delay(10);
|
||
HAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_SET);
|
||
HAL_Delay(10);
|
||
}
|
||
|
||
// Send a byte to the command register
|
||
void ssd1306_WriteCommand(uint8_t byte) {
|
||
uint8_t rx;
|
||
HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLED
|
||
HAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_RESET); // command
|
||
//HAL_SPI_TransmitReceive(&hspi2, &byte, &rx, 1, 100);
|
||
HAL_SPI_Transmit(&SSD1306_SPI_PORT, (uint8_t *) &byte, 1, HAL_MAX_DELAY); //TODO
|
||
HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED
|
||
}
|
||
|
||
// Send data
|
||
void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) {
|
||
|
||
uint32_t i;
|
||
|
||
HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLED
|
||
HAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_SET); // data
|
||
|
||
//HAL_SPI_Transmit(&hspi2, buffer, buff_size, 10000);
|
||
|
||
|
||
/* for(i = 0; i < buff_size; i++) {
|
||
SPI_WrRd(buffer[i]);
|
||
}*/
|
||
HAL_SPI_Transmit(&SSD1306_SPI_PORT, buffer, buff_size, HAL_MAX_DELAY);
|
||
HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED
|
||
}
|
||
|
||
#else
|
||
#error "You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro"
|
||
#endif
|
||
|
||
|
||
// Screenbuffer
|
||
static uint8_t SSD1306_Buffer[SSD1306_BUFFER_SIZE];
|
||
|
||
|
||
SSD1306_t SSD1306;
|
||
|
||
/* Fills the Screenbuffer with values from a given buffer of a fixed length */
|
||
SSD1306_Error_t ssd1306_FillBuffer(uint8_t* buf, uint32_t len) {
|
||
SSD1306_Error_t ret = SSD1306_ERR;
|
||
if (len <= SSD1306_BUFFER_SIZE) {
|
||
memcpy(SSD1306_Buffer,buf,len);
|
||
ret = SSD1306_OK;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
void DrawSaving(void)
|
||
{
|
||
memcpy(&SSD1306_Buffer[120], &SAVE_LOGO[0], 8);
|
||
}
|
||
|
||
|
||
void DrawLogo(void)
|
||
{
|
||
char str[10];
|
||
|
||
|
||
/*memcpy(&SSD1306_Buffer[2 + 390], &Logo128x24[0], 128);
|
||
memcpy(&SSD1306_Buffer[132 + 390], &Logo128x24[128], 128);
|
||
memcpy(&SSD1306_Buffer[262 + 390], &Logo128x24[256], 128);*/
|
||
|
||
memcpy(&SSD1306_Buffer[2 + 32 + 390], &logo_new[0], 64);
|
||
memcpy(&SSD1306_Buffer[132 + 32 + 390], &logo_new[64], 64);
|
||
memcpy(&SSD1306_Buffer[262 + 32 + 390], &logo_new[128], 64);
|
||
|
||
|
||
FontSet(Segoe_UI_Rus_8);
|
||
#ifdef A621
|
||
OLED_DrawStr("Db,hjrjynhjkkth F621", CENTER, 0, White);
|
||
#endif
|
||
#ifdef A631
|
||
OLED_DrawStr("Db,hjrjynhjkkth F631", CENTER, 0, White);
|
||
#endif
|
||
#ifdef A632
|
||
OLED_DrawStr("Db,hjrjynhjkkth F632", CENTER, 0, White);
|
||
#endif
|
||
#ifdef A633
|
||
OLED_DrawStr("Db,hjrjynhjkkth F633", CENTER, 0, White);
|
||
#endif
|
||
#ifdef A634
|
||
OLED_DrawStr("Db,hjrjynhjkkth F634", CENTER, 0, White);
|
||
#endif
|
||
#ifdef A635
|
||
OLED_DrawStr("Db,hjrjynhjkkth F635", CENTER, 0, White);
|
||
#endif
|
||
#ifdef A636
|
||
OLED_DrawStr("Db,hjrjynhjkkth F636", CENTER, 0, White);
|
||
#endif
|
||
#ifdef A637
|
||
OLED_DrawStr("Db,hjrjynhjkkth F637", CENTER, 0, White);
|
||
#endif
|
||
#ifdef A638
|
||
OLED_DrawStr("Db,hjrjynhjkkth F638", CENTER, 0, White);
|
||
#endif
|
||
#ifdef A639
|
||
OLED_DrawStr("Db,hjrjynhjkkth F639", CENTER, 0, White);
|
||
#endif
|
||
|
||
|
||
ssd1306_SetCursor(76, 52);
|
||
ssd1306_WriteString((char *) SERIAL, Font_6x8, White);
|
||
|
||
|
||
strcpy(str, "Flhtc "); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
if(currentData.OWN < 10)
|
||
{
|
||
str[6] = (char) (currentData.OWN + 48);
|
||
str[7] = 0;
|
||
}
|
||
else
|
||
if(currentData.OWN < 100)
|
||
{
|
||
str[6] = (char) ((currentData.OWN / 10) + 48);
|
||
str[7] = (char) ((currentData.OWN % 10) + 48);
|
||
str[8] = 0;
|
||
}
|
||
else
|
||
{
|
||
str[6] = (char) ((currentData.OWN / 100) + 48);
|
||
str[7] = (char) ((currentData.OWN % 100 / 10) + 48);
|
||
str[8] = (char) ((currentData.OWN % 100 % 10) + 48);
|
||
str[9] = 0;
|
||
}
|
||
OLED_DrawStr(str, 2, 51, White);
|
||
|
||
|
||
ssd1306_UpdateScreen();
|
||
}
|
||
|
||
|
||
// Initialize the oled screen
|
||
void ssd1306_Init(void)
|
||
{
|
||
char str[10];
|
||
|
||
// Reset OLED
|
||
ssd1306_Reset();
|
||
|
||
// Wait for the screen to boot
|
||
HAL_Delay(100);
|
||
|
||
|
||
/* ssd1306_SetDisplayOn(1); //--turn on SSD1306 panel
|
||
while(1)
|
||
{
|
||
ssd1306_Fill(Black);
|
||
ssd1306_UpdateScreen();
|
||
HAL_Delay(100);
|
||
}*/
|
||
|
||
|
||
// Init OLED
|
||
ssd1306_SetDisplayOn(0); //display off
|
||
|
||
ssd1306_WriteCommand(0x20); //Set Memory Addressing Mode
|
||
ssd1306_WriteCommand(0x00); // 00b,Horizontal Addressing Mode; 01b,Vertical Addressing Mode;
|
||
// 10b,Page Addressing Mode (RESET); 11b,Invalid
|
||
|
||
ssd1306_WriteCommand(0xB0); //Set Page Start Address for Page Addressing Mode,0-7
|
||
|
||
#ifdef SSD1306_MIRROR_VERT
|
||
ssd1306_WriteCommand(0xC0); // Mirror vertically
|
||
#else
|
||
ssd1306_WriteCommand(0xC8); //Set COM Output Scan Direction
|
||
#endif
|
||
|
||
ssd1306_WriteCommand(0x00); //---set low column address
|
||
ssd1306_WriteCommand(0x10); //---set high column address
|
||
|
||
ssd1306_WriteCommand(0x40); //--set start line address - CHECK
|
||
|
||
ssd1306_SetContrast(0xCF);
|
||
|
||
#ifdef SSD1306_MIRROR_HORIZ
|
||
ssd1306_WriteCommand(0xA0); // Mirror horizontally
|
||
#else
|
||
ssd1306_WriteCommand(0xA1); //--set segment re-map 0 to 127 - CHECK
|
||
#endif
|
||
|
||
#ifdef SSD1306_INVERSE_COLOR
|
||
ssd1306_WriteCommand(0xA7); //--set inverse color
|
||
#else
|
||
ssd1306_WriteCommand(0xA6); //--set normal color
|
||
#endif
|
||
|
||
// Set multiplex ratio.
|
||
#if (SSD1306_HEIGHT == 128)
|
||
// Found in the Luma Python lib for SH1106.
|
||
ssd1306_WriteCommand(0x7F);
|
||
#else
|
||
ssd1306_WriteCommand(0xA8); //--set multiplex ratio(1 to 64) - CHECK
|
||
#endif
|
||
|
||
#if (SSD1306_HEIGHT == 32)
|
||
ssd1306_WriteCommand(0x1F); //
|
||
#elif (SSD1306_HEIGHT == 64)
|
||
ssd1306_WriteCommand(0x3F); //
|
||
#elif (SSD1306_HEIGHT == 128)
|
||
ssd1306_WriteCommand(0x3F); // Seems to work for 128px high displays too.
|
||
#else
|
||
#error "Only 32, 64, or 128 lines of height are supported!"
|
||
#endif
|
||
|
||
ssd1306_WriteCommand(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
|
||
|
||
//ssd1306_WriteCommand(0xD3); //-set display offset - CHECK
|
||
//ssd1306_WriteCommand(0x00); //-not offset
|
||
|
||
ssd1306_WriteCommand(0xD5); //--set display clock divide ratio/oscillator frequency
|
||
ssd1306_WriteCommand(0xF0); //--set divide ratio
|
||
|
||
ssd1306_WriteCommand(0xD9); //--set pre-charge period
|
||
ssd1306_WriteCommand(0x22); //
|
||
|
||
ssd1306_WriteCommand(0xDA); //--set com pins hardware configuration - CHECK
|
||
#if (SSD1306_HEIGHT == 32)
|
||
ssd1306_WriteCommand(0x02);
|
||
#elif (SSD1306_HEIGHT == 64)
|
||
ssd1306_WriteCommand(0x12);
|
||
#elif (SSD1306_HEIGHT == 128)
|
||
ssd1306_WriteCommand(0x12);
|
||
#else
|
||
#error "Only 32, 64, or 128 lines of height are supported!"
|
||
#endif
|
||
|
||
ssd1306_WriteCommand(0xDB); //--set vcomh
|
||
ssd1306_WriteCommand(0x20); //0x20,0.77xVcc
|
||
|
||
ssd1306_WriteCommand(0x8D); //--set DC-DC enable
|
||
ssd1306_WriteCommand(0x14); //
|
||
ssd1306_SetDisplayOn(1); //--turn on SSD1306 panel
|
||
|
||
SSD1306.CurrentX = 0;
|
||
SSD1306.CurrentY = 0;
|
||
SSD1306.Initialized = 1;
|
||
|
||
ssd1306_Fill(Black);
|
||
ssd1306_UpdateScreen();
|
||
|
||
|
||
DrawLogo();
|
||
HAL_Delay(LOGO_TIME_MS);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
// Fill the whole screen with the given color
|
||
void ssd1306_Fill(SSD1306_COLOR color)
|
||
{
|
||
uint32_t i;
|
||
|
||
for(i = 0; i < sizeof(SSD1306_Buffer); i++) {
|
||
SSD1306_Buffer[i] = (color == Black) ? 0x00 : 0xFF;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
void OLED_DrawPixelStatus(uint8_t pos_x, uint8_t pos_y, uint8_t mode)
|
||
{
|
||
if (pos_x >= SSD1306_WIDTH || pos_y >= SSD1306_HEIGHT) return;
|
||
|
||
if (mode) SSD1306_Buffer[pos_x + (pos_y / 8) * SSD1306_WIDTH] |= (1 << (pos_y & 7));
|
||
else SSD1306_Buffer[pos_x + (pos_y / 8) * SSD1306_WIDTH] &= ~(1 << (pos_y & 7));
|
||
}
|
||
|
||
|
||
uint8_t OLED_GetWidthStr(const char* str)
|
||
{
|
||
uint8_t stl = strlen(str);
|
||
uint8_t len = 0;
|
||
|
||
for (uint8_t i = 0; i < stl; i++, *str++)
|
||
{
|
||
len += fontbyte(Font.numchars * (*str - Font.offset) + 4);
|
||
}
|
||
|
||
return len;
|
||
}
|
||
|
||
uint8_t OLED_GetWidthNum(int16_t num)
|
||
{
|
||
char buf[15];
|
||
sprintf(buf, "%d", num);
|
||
|
||
return OLED_GetWidthStr(buf);
|
||
}
|
||
|
||
|
||
void OLED_DrawChar(char c, uint8_t ix, uint8_t iy, uint8_t mode)
|
||
{
|
||
const uint8_t* symbol = &fontbyte(Font.numchars * (c - Font.offset) + 4);
|
||
|
||
for (uint8_t x = 0; x < symbol[0]; x++)
|
||
{
|
||
for (uint8_t y = 0; y < Font.height; y++)
|
||
{
|
||
if (symbol[1 + y / 8 + x * (Font.numchars - 1) / Font.width] & (0x01 << (y % 8)))
|
||
OLED_DrawPixelStatus(ix + x, iy + y, (mode) ? 1 : 0);
|
||
else
|
||
OLED_DrawPixelStatus(ix + x, iy + y, (mode) ? 0 : 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
void OLED_DrawNum(int16_t num, uint8_t x, uint8_t y, uint8_t mode)
|
||
{
|
||
char buf[15];
|
||
sprintf(buf, "%d", num);
|
||
|
||
OLED_DrawStr(buf, x, y, mode);
|
||
}
|
||
|
||
void OLED_DrawStr(char *str, uint8_t x, uint8_t y, uint8_t mode)
|
||
{
|
||
uint8_t stl = strlen(str);
|
||
uint8_t pos = x;
|
||
|
||
if (pos == RIGHT) pos = 130 - OLED_GetWidthStr(str) - 1;
|
||
if (pos == CENTER) pos = (SSD1306_WIDTH - OLED_GetWidthStr(str) - 1) / 2;
|
||
if (y == CENTER) y = (SSD1306_HEIGHT - Font.height) / 2;
|
||
|
||
for (uint8_t cnt = 0; cnt < stl; cnt++, *str++)
|
||
{
|
||
OLED_DrawChar(*str, pos, y, mode);
|
||
pos += fontbyte(Font.numchars * (*str - Font.offset) + 4);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// Write the screenbuffer with changed to the screen
|
||
void ssd1306_UpdateScreen(void) {
|
||
// Write data to each page of RAM. Number of pages
|
||
// depends on the screen height:
|
||
//
|
||
// * 32px == 4 pages
|
||
// * 64px == 8 pages
|
||
// * 128px == 16 pages
|
||
for(uint8_t i = 0; i < SSD1306_HEIGHT/8; i++) {
|
||
ssd1306_WriteCommand(0xB0 + i); // Set the current RAM page address.
|
||
ssd1306_WriteCommand(0x00);
|
||
ssd1306_WriteCommand(0x10);
|
||
|
||
//HAL_SPI_Transmit_DMA(&hspi, uint8_t *pData, uint16_t Size);
|
||
ssd1306_WriteData(&SSD1306_Buffer[SSD1306_WIDTH*i],SSD1306_WIDTH);
|
||
}
|
||
}
|
||
|
||
// Draw one pixel in the screenbuffer
|
||
// X => X Coordinate
|
||
// Y => Y Coordinate
|
||
// color => Pixel color
|
||
void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color) {
|
||
if(x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT) {
|
||
// Don't write outside the buffer
|
||
return;
|
||
}
|
||
|
||
// Check if pixel should be inverted
|
||
if(SSD1306.Inverted) {
|
||
color = (SSD1306_COLOR)!color;
|
||
}
|
||
|
||
// Draw in the right color
|
||
if(color == White) {
|
||
SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8);
|
||
} else {
|
||
SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8));
|
||
}
|
||
}
|
||
|
||
// Draw 1 char to the screen buffer
|
||
// ch => char om weg te schrijven
|
||
// Font => Font waarmee we gaan schrijven
|
||
// color => Black or White
|
||
char ssd1306_WriteChar(char ch, FontDef Font, SSD1306_COLOR color) {
|
||
uint32_t i, b, j;
|
||
|
||
// Check if character is valid
|
||
if (ch < 32 || ch > 126)
|
||
return 0;
|
||
|
||
// Check remaining space on current line
|
||
if (SSD1306_WIDTH < (SSD1306.CurrentX + Font.FontWidth) ||
|
||
SSD1306_HEIGHT < (SSD1306.CurrentY + Font.FontHeight))
|
||
{
|
||
// Not enough space on current line
|
||
return 0;
|
||
}
|
||
|
||
// Use the font to write
|
||
for(i = 0; i < Font.FontHeight; i++) {
|
||
b = Font.data[(ch - 32) * Font.FontHeight + i];
|
||
for(j = 0; j < Font.FontWidth; j++) {
|
||
if((b << j) & 0x8000) {
|
||
ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) color);
|
||
} else {
|
||
ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR)!color);
|
||
}
|
||
}
|
||
}
|
||
|
||
// The current space is now taken
|
||
SSD1306.CurrentX += Font.FontWidth;
|
||
|
||
// Return written char for validation
|
||
return ch;
|
||
}
|
||
|
||
// Write full string to screenbuffer
|
||
char ssd1306_WriteString(char* str, FontDef Font, SSD1306_COLOR color) {
|
||
// Write until null-byte
|
||
while (*str) {
|
||
if (ssd1306_WriteChar(*str, Font, color) != *str) {
|
||
// Char could not be written
|
||
return *str;
|
||
}
|
||
|
||
// Next char
|
||
str++;
|
||
}
|
||
|
||
// Everything ok
|
||
return *str;
|
||
}
|
||
|
||
// Position the cursor
|
||
void ssd1306_SetCursor(uint8_t x, uint8_t y) {
|
||
SSD1306.CurrentX = x;
|
||
SSD1306.CurrentY = y;
|
||
}
|
||
|
||
// Draw line by Bresenhem's algorithm
|
||
void ssd1306_Line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) {
|
||
int32_t deltaX = abs(x2 - x1);
|
||
int32_t deltaY = abs(y2 - y1);
|
||
int32_t signX = ((x1 < x2) ? 1 : -1);
|
||
int32_t signY = ((y1 < y2) ? 1 : -1);
|
||
int32_t error = deltaX - deltaY;
|
||
int32_t error2;
|
||
|
||
ssd1306_DrawPixel(x2, y2, color);
|
||
while((x1 != x2) || (y1 != y2))
|
||
{
|
||
ssd1306_DrawPixel(x1, y1, color);
|
||
error2 = error * 2;
|
||
if(error2 > -deltaY)
|
||
{
|
||
error -= deltaY;
|
||
x1 += signX;
|
||
}
|
||
else
|
||
{
|
||
/*nothing to do*/
|
||
}
|
||
|
||
if(error2 < deltaX)
|
||
{
|
||
error += deltaX;
|
||
y1 += signY;
|
||
}
|
||
else
|
||
{
|
||
/*nothing to do*/
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
//Draw polyline
|
||
void ssd1306_Polyline(const SSD1306_VERTEX *par_vertex, uint16_t par_size, SSD1306_COLOR color) {
|
||
uint16_t i;
|
||
if(par_vertex != 0){
|
||
for(i = 1; i < par_size; i++){
|
||
ssd1306_Line(par_vertex[i - 1].x, par_vertex[i - 1].y, par_vertex[i].x, par_vertex[i].y, color);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*nothing to do*/
|
||
}
|
||
return;
|
||
}
|
||
/*Convert Degrees to Radians*/
|
||
static float ssd1306_DegToRad(float par_deg) {
|
||
return par_deg * 3.14 / 180.0;
|
||
}
|
||
/*Normalize degree to [0;360]*/
|
||
static uint16_t ssd1306_NormalizeTo0_360(uint16_t par_deg) {
|
||
uint16_t loc_angle;
|
||
if(par_deg <= 360)
|
||
{
|
||
loc_angle = par_deg;
|
||
}
|
||
else
|
||
{
|
||
loc_angle = par_deg % 360;
|
||
loc_angle = ((par_deg != 0)?par_deg:360);
|
||
}
|
||
return loc_angle;
|
||
}
|
||
/*DrawArc. Draw angle is beginning from 4 quart of trigonometric circle (3pi/2)
|
||
* start_angle in degree
|
||
* sweep in degree
|
||
*/
|
||
void ssd1306_DrawArc(uint8_t x, uint8_t y, uint8_t radius, uint16_t start_angle, uint16_t sweep, SSD1306_COLOR color) {
|
||
#define CIRCLE_APPROXIMATION_SEGMENTS 36
|
||
float approx_degree;
|
||
uint32_t approx_segments;
|
||
uint8_t xp1,xp2;
|
||
uint8_t yp1,yp2;
|
||
uint32_t count = 0;
|
||
uint32_t loc_sweep = 0;
|
||
float rad;
|
||
|
||
loc_sweep = ssd1306_NormalizeTo0_360(sweep);
|
||
|
||
count = (ssd1306_NormalizeTo0_360(start_angle) * CIRCLE_APPROXIMATION_SEGMENTS) / 360;
|
||
approx_segments = (loc_sweep * CIRCLE_APPROXIMATION_SEGMENTS) / 360;
|
||
approx_degree = loc_sweep / (float)approx_segments;
|
||
while(count < approx_segments)
|
||
{
|
||
rad = ssd1306_DegToRad(count*approx_degree);
|
||
xp1 = x + (int8_t)(sin(rad)*radius);
|
||
yp1 = y + (int8_t)(cos(rad)*radius);
|
||
count++;
|
||
if(count != approx_segments)
|
||
{
|
||
rad = ssd1306_DegToRad(count*approx_degree);
|
||
}
|
||
else
|
||
{
|
||
rad = ssd1306_DegToRad(loc_sweep);
|
||
}
|
||
xp2 = x + (int8_t)(sin(rad)*radius);
|
||
yp2 = y + (int8_t)(cos(rad)*radius);
|
||
ssd1306_Line(xp1,yp1,xp2,yp2,color);
|
||
}
|
||
|
||
return;
|
||
}
|
||
//Draw circle by Bresenhem's algorithm
|
||
void ssd1306_DrawCircle(uint8_t par_x,uint8_t par_y,uint8_t par_r,SSD1306_COLOR par_color) {
|
||
int32_t x = -par_r;
|
||
int32_t y = 0;
|
||
int32_t err = 2 - 2 * par_r;
|
||
int32_t e2;
|
||
|
||
if (par_x >= SSD1306_WIDTH || par_y >= SSD1306_HEIGHT) {
|
||
return;
|
||
}
|
||
|
||
do {
|
||
ssd1306_DrawPixel(par_x - x, par_y + y, par_color);
|
||
ssd1306_DrawPixel(par_x + x, par_y + y, par_color);
|
||
ssd1306_DrawPixel(par_x + x, par_y - y, par_color);
|
||
ssd1306_DrawPixel(par_x - x, par_y - y, par_color);
|
||
e2 = err;
|
||
if (e2 <= y) {
|
||
y++;
|
||
err = err + (y * 2 + 1);
|
||
if(-x == y && e2 <= x) {
|
||
e2 = 0;
|
||
}
|
||
else
|
||
{
|
||
/*nothing to do*/
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*nothing to do*/
|
||
}
|
||
if(e2 > x) {
|
||
x++;
|
||
err = err + (x * 2 + 1);
|
||
}
|
||
else
|
||
{
|
||
/*nothing to do*/
|
||
}
|
||
} while(x <= 0);
|
||
|
||
return;
|
||
}
|
||
|
||
//Draw rectangle
|
||
void ssd1306_DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) {
|
||
ssd1306_Line(x1,y1,x2,y1,color);
|
||
ssd1306_Line(x2,y1,x2,y2,color);
|
||
ssd1306_Line(x2,y2,x1,y2,color);
|
||
ssd1306_Line(x1,y2,x1,y1,color);
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
void ssd1306_DrawFillRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color)
|
||
{
|
||
uint8_t l, h, i;
|
||
|
||
if(x2 >= x1)
|
||
{
|
||
l = x2 - x1 + 1;
|
||
if(y2 >= y1)
|
||
h = y2 - y1 + 1;
|
||
else h = y1 - y2 + 1;
|
||
}
|
||
else
|
||
{
|
||
l = x1 - x2 + 1;
|
||
if(y2 >= y1)
|
||
h = y2 - y1 + 1;
|
||
else h = y1 - y2 + 1;
|
||
}
|
||
|
||
|
||
for(i = 0; i < h; i++) {
|
||
ssd1306_Line(x1, y1 + i, x2, y1 + i, color);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
void ssd1306_SetContrast(const uint8_t value) {
|
||
const uint8_t kSetContrastControlRegister = 0x81;
|
||
ssd1306_WriteCommand(kSetContrastControlRegister);
|
||
ssd1306_WriteCommand(value);
|
||
}
|
||
|
||
void ssd1306_SetDisplayOn(const uint8_t on) {
|
||
uint8_t value;
|
||
if (on) {
|
||
value = 0xAF; // Display on
|
||
SSD1306.DisplayOn = 1;
|
||
} else {
|
||
value = 0xAE; // Display off
|
||
SSD1306.DisplayOn = 0;
|
||
}
|
||
ssd1306_WriteCommand(value);
|
||
}
|
||
|
||
uint8_t ssd1306_GetDisplayOn() {
|
||
return SSD1306.DisplayOn;
|
||
}
|