1
0
Fork 0
stm32/Src/ssd1306.c

391 lines
10 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 uint8_t anim = 1;
static int16_t x = -64;
/**
* [ssd1306_Decompress description]
* @param input [description]
* @param output [description]
* @param output_size [description]
*/
void ssd1306_Decompress(uint8_t *input, uint8_t *output, uint16_t output_size) {
z_stream infstream;
infstream.zalloc = Z_NULL;
infstream.zfree = Z_NULL;
infstream.opaque = Z_NULL;
infstream.avail_in = 0;
infstream.next_in = Z_NULL;
infstream.next_in = (Bytef *)input;
infstream.avail_in = output_size;
infstream.avail_out = (uInt)output_size;
infstream.next_out = (Bytef *)output;
inflateInit(&infstream);
inflate(&infstream, Z_FINISH);
inflateEnd(&infstream);
}
void ssd1306_LoadImage(void) {
//memcpy(SSD1306_Buffer, image, 1024);
ssd1306_Decompress(image, SSD1306_Buffer, sizeof(SSD1306_Buffer));
}
void ssd1306_DrawSprite(SpriteDef sprite, int16_t x, int16_t y) {
uint16_t spriteAddr = 0;
int16_t currX, currY = y;
for(int16_t bank = currY / 8; bank < sprite.height / 8; bank++) {
currX = x;
int16_t start = (bank * sprite.width) + (bank * sprite.height) + x;
int16_t end = start + sprite.width;
for(int16_t addr = start; addr < end; addr++) {
if (spriteAddr < (sprite.height * sprite.width / 8) ) {
for(uint8_t bit = 0; bit < 8; bit++) {
if ((sprite.buffer[spriteAddr] >> bit) & 0x01) {
uint8_t newY = bit + currY;
if (currX >= 0 && newY >= 0 && currX < SSD1306_WIDTH && newY < SSD1306_HEIGHT) {
ssd1306_DrawPixel(currX, newY, White);
}
}
}
}
spriteAddr++;
currX++;
}
currY += 8;
}
}
void ssd1306_Anim(void) {
SpriteDef dstSprite;
uint16_t dstSize;
dstSize = animation.height * animation.width / 8;
dstSprite.width = animation.width;
dstSprite.height = animation.height;
dstSprite.buffer = malloc(sizeof(uint8_t) * (dstSize));
ssd1306_Decompress(animation.buffer[anim], dstSprite.buffer, dstSize);
ssd1306_DrawSprite(dstSprite, x, 0);
free(dstSprite.buffer);
anim++;
x++;
if (anim == animation.frames) {
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(uint8_t pixels, uint8_t delay)
{
uint32_t end_addr = SSD1306_WIDTH * 8;
char lost_bit = 0;
for(uint8_t times = 0; times < pixels; times++) {
for(uint16_t addr = 0; addr < end_addr; addr++) {
// 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;
}