1
0
Fork 0
stm32/Src/ssd1306.c

375 lines
9.5 KiB
C

#include"ssd1306.h"
static uint8_t SSD1306_Buffer[SSD1306_HEIGHT * SSD1306_WIDTH / 8];
// Een scherm-object om lokaal in te werken
static SSD1306_t SSD1306;
void startscrollright(uint8_t start, uint8_t stop){
ssd1306_WriteCommand(SSD1306_RIGHT_HORIZONTAL_SCROLL);
ssd1306_WriteCommand(0X00);
ssd1306_WriteCommand(start);
ssd1306_WriteCommand(0X00);
ssd1306_WriteCommand(stop);
ssd1306_WriteCommand(0X00);
ssd1306_WriteCommand(0XFF);
ssd1306_WriteCommand(SSD1306_ACTIVATE_SCROLL);
}
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1)
{
int16_t steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
_swap_int16_t(x0, y0);
_swap_int16_t(x1, y1);
}
if (x0 > x1) {
_swap_int16_t(x0, x1);
_swap_int16_t(y0, y1);
}
int16_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int16_t err = dx / 2;
int16_t ystep;
if (y0 < y1) {
ystep = 1;
} else {
ystep = -1;
}
for (; x0<=x1; x0++) {
if (steep) {
ssd1306_DrawPixel(y0, x0, White);
} else {
ssd1306_DrawPixel(x0, y0, White);
}
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
static int anim = 1;
static int x = 0;
void ssd1306_LoadImage(void) {
//memcpy(SSD1306_Buffer, image, 1024);
fastlz_decompress(image, 1024, SSD1306_Buffer, 1024);
}
void ssd1306_DrawSprite(SpriteDef *sprite, int8_t x, int8_t y) {
int spriteAddr = 0;
int currX, currY = 0;
for(int bank = y / 8; bank < sprite->height / 8; bank++) {
int start = (bank * sprite->width) + (bank * sprite->height) + (x);
currX = x;
int end = start + sprite->width;
for(int addr = start; addr < end; addr++) {
if (currX > 0 && currY > 0 && currX < SSD1306_WIDTH && currY < SSD1306_HEIGHT) {
SSD1306_Buffer[addr] = sprite->buffer[spriteAddr];
}
spriteAddr++;
currX++;
}
currY += 8;
}
}
void ssd1306_Anim(void) {
SpriteDef *sprite;
switch(anim) {
case 0:
sprite = &sprite_0;
break;
case 1:
sprite = &sprite_1;
break;
case 2:
sprite = &sprite_2;
break;
case 3:
sprite = &sprite_3;
break;
case 4:
sprite = &sprite_4;
break;
}
ssd1306_DrawSprite(sprite, x, 0);
anim++;
x += 15;
if (anim == 5) {
anim = 1;
}
if (x > SSD1306_WIDTH) {
x = -64;
}
}
/**
* [ssd1306_ScrollUp scrolls the whole LCD buffer up]
* @param pixels [How many pixels to scroll up]
* @param delay [Delay between refresh]
*/
//void ssd1306_ScrollUp(unsigned int pixels, unsigned int delay, )
void ssd1306_ScrollUp(unsigned int pixels, unsigned int delay, UART_HandleTypeDef uart)
{
static uint32_t end_addr = SSD1306_WIDTH * 8;
char lost_bit = 0;
//char buffer[64];
for(uint8_t times = 0; times < pixels; times++) {
for(uint32_t addr = 0; addr < end_addr; addr++) {
//char binary[33];
//itoa(SSD1306_Buffer[addr], binary, 2);
//sprintf(buffer, "addr: %x : %s\n\r", addr, binary);
//HAL_UART_Transmit(&uart, (uint8_t*)buffer, strlen(buffer), 0xFFFF);
// In the first bank we dont need to keep the lost bit
if (addr > 0x7f) {
lost_bit = SSD1306_Buffer[addr] & 0x01;
}
// Shift one pixel "up"
SSD1306_Buffer[addr] >>= 1;
// In the first bank we dont need to do this
if (addr > 0x7f) {
// Move the saved bit from the LSB to the MSB
lost_bit <<= 7;
// Add the saved bit to the bank above it
SSD1306_Buffer[addr - SSD1306_WIDTH] |= lost_bit;
}
}
ssd1306_UpdateScreen();
HAL_Delay(delay);
}
}
//
// Een byte sturen naar het commando register
// Kan niet gebruikt worden buiten deze file
//
void ssd1306_WriteCommand(uint8_t command)
{
HAL_I2C_Mem_Write(&hi2c1, SSD1306_I2C_ADDR, 0x00,1, &command, 1, 10);
}
//
// Het scherm initialiseren voor gebruik
//
uint8_t ssd1306_Init(void)
{
// Even wachten zodat het scherm zeker opgestart is
HAL_Delay(100);
ssd1306_WriteCommand(SSD1306_DISPLAYOFF); // 0xAE
ssd1306_WriteCommand(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
ssd1306_WriteCommand(0x80); // the suggested ratio 0x80
ssd1306_WriteCommand(SSD1306_SETMULTIPLEX); // 0xA8
ssd1306_WriteCommand(SSD1306_HEIGHT - 1);
ssd1306_WriteCommand(SSD1306_SETDISPLAYOFFSET); // 0xD3
ssd1306_WriteCommand(0x0); // no offset
ssd1306_WriteCommand(SSD1306_SETSTARTLINE | 0x0); // line #0
ssd1306_WriteCommand(SSD1306_CHARGEPUMP); // 0x8D
ssd1306_WriteCommand(0x14);
ssd1306_WriteCommand(SSD1306_MEMORYMODE); // 0x20
ssd1306_WriteCommand(0x00); // 0x0 act like ks0108
ssd1306_WriteCommand(SSD1306_SEGREMAP | 0x1);
ssd1306_WriteCommand(SSD1306_COMSCANDEC);
ssd1306_WriteCommand(SSD1306_SETCOMPINS); // 0xDA
ssd1306_WriteCommand(0x12);
ssd1306_WriteCommand(SSD1306_SETCONTRAST); // 0x81
ssd1306_WriteCommand(0xCF);
ssd1306_WriteCommand(SSD1306_SETPRECHARGE);
ssd1306_WriteCommand(0xF1);
ssd1306_WriteCommand(SSD1306_SETVCOMDETECT); // 0xDB
ssd1306_WriteCommand(0x40);
ssd1306_WriteCommand(SSD1306_DISPLAYALLON_RESUME); // 0xA4
ssd1306_WriteCommand(SSD1306_NORMALDISPLAY); // 0xA6
ssd1306_WriteCommand(SSD1306_DEACTIVATE_SCROLL);
ssd1306_WriteCommand(SSD1306_DISPLAYON);//--turn on oled panel
/* Clearen scherm */
ssd1306_Fill(Black);
/* Update screen */
ssd1306_UpdateScreen();
/* Set default values */
SSD1306.CurrentX = 0;
SSD1306.CurrentY = 0;
/* Initialized OK */
SSD1306.Initialized = 1;
/* Return OK */
return 1;
}
//
// We zetten de hele buffer op een bepaalde kleur
// color => de kleur waarin alles moet
//
void ssd1306_Fill(SSD1306_COLOR color)
{
/* Set memory */
uint32_t i;
for(i = 0; i < sizeof(SSD1306_Buffer); i++)
{
SSD1306_Buffer[i] = (color == Black) ? 0x00 : 0xFF;
}
}
//
// Alle weizigingen in de buffer naar het scherm sturen
//
void ssd1306_UpdateScreen(void)
{
uint8_t i;
for (i = 0; i < 8; i++) {
ssd1306_WriteCommand(0xB0 + i);
ssd1306_WriteCommand(0x00);
ssd1306_WriteCommand(0x10);
// We schrijven alles map per map weg
HAL_I2C_Mem_Write(&hi2c1,SSD1306_I2C_ADDR,0x40,1,&SSD1306_Buffer[SSD1306_WIDTH * i],SSD1306_WIDTH,100);
}
}
//
// 1 pixel op het scherm tekenen
// X => X coordinaat
// Y => Y coordinaat
// color => kleur die pixel moet krijgen
//
void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color)
{
if (x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT)
{
// We gaan niet buiten het scherm schrijven
return;
}
// Kijken of de pixel geinverteerd moet worden
if (SSD1306.Inverted)
{
color = (SSD1306_COLOR)!color;
}
// We zetten de juiste kleur voor de pixel
if (color == White)
{
SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8);
}
else
{
SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8));
}
}
//
// We willen 1 char naar het scherm sturen
// 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;
// Kijken of er nog plaats is op deze lijn
if (SSD1306_WIDTH <= (SSD1306.CurrentX + Font.FontWidth) ||
SSD1306_HEIGHT <= (SSD1306.CurrentY + Font.FontHeight))
{
// Er is geen plaats meer
return 0;
}
// We gaan door het font
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);
}
}
}
// De huidige positie is nu verplaatst
SSD1306.CurrentX += Font.FontWidth;
// We geven het geschreven char terug voor validatie
return ch;
}
//
// Functie voor het wegschrijven van een hele string
// str => string om op het scherm te schrijven
// Font => Het font dat gebruikt moet worden
// color => Black or White
//
char ssd1306_WriteString(char* str, FontDef Font, SSD1306_COLOR color)
{
// We schrijven alle char tot een nulbyte
while (*str)
{
if (ssd1306_WriteChar(*str, Font, color) != *str)
{
// Het karakter is niet juist weggeschreven
return *str;
}
// Volgende char
str++;
}
// Alles gelukt, we sturen dus 0 terug
return *str;
}
//
// Zet de cursor op een coordinaat
//
void ssd1306_SetCursor(uint8_t x, uint8_t y)
{
/* Set write pointers */
SSD1306.CurrentX = x;
SSD1306.CurrentY = y;
}