Created
December 31, 2018 14:58
-
-
Save IndianBoy42/a22a782022b75672cae713a9f28a6813 to your computer and use it in GitHub Desktop.
STM32F4 LL OLED library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdarg.h> | |
#include "oled.h" | |
#define FONT_WIDTH 5 | |
#define FONT_HEIGHT 8 | |
#include "oled_font.h" | |
#define RES_128X64 | |
#ifdef RES_128X64 | |
#define WIDTH 128 | |
#define HEIGHT 64 | |
#define PAGES 8 | |
#define ROWS PAGES | |
#if FONT_WIDTH == 3 | |
#define COLS 42 | |
#endif | |
#if FONT_WIDTH == 5 | |
#define COLS 25 | |
#endif | |
#if FONT_WIDTH == 6 | |
#define COLS 21 | |
#endif | |
#if FONT_WIDTH == 8 | |
#define COLS 16 | |
#endif | |
#endif | |
uint8_t pixel_buf[PAGES][WIDTH] = {0}; | |
static void reset(void) { | |
gpio_set(OLED_RES); | |
delay(100); | |
gpio_reset(OLED_RES); | |
delay(100); | |
gpio_set(OLED_RES); | |
} | |
static void write_command(uint8_t command) { | |
#if 1 | |
gpio_reset(OLED_DC); | |
while (!(OLED_SPI->SR & SPI_SR_TXE)); | |
OLED_SPI->DR = command; | |
#else | |
while ((*((volatile uint16_t*)(&OLED_SPI->SR)) & SPI_SR_BSY)); | |
gpio_reset(OLED_DC); | |
*((volatile uint8_t *)(&OLED_SPI->DR)) = command; | |
while (!(*((volatile uint16_t*)(&OLED_SPI->SR)) & SPI_SR_BSY)); //Wait for transmission to start | |
while ((*((volatile uint16_t*)(&OLED_SPI->SR)) & SPI_SR_BSY)); //And then to end | |
gpio_set(OLED_DC); | |
#endif | |
} | |
static void write_data(uint8_t data) { | |
#if 1 | |
gpio_set(OLED_DC); | |
while (!(OLED_SPI->SR & SPI_SR_TXE)); | |
OLED_SPI->DR = data; | |
#else | |
while (!(*((volatile uint16_t*)(&OLED_SPI->SR)) & SPI_SR_BSY)); | |
*((volatile uint8_t *)(&OLED_SPI->DR)) = data; | |
#endif | |
} | |
void oled_init(void) { | |
LL_DMA_ConfigAddresses(DMA1, LL_DMA_STREAM_5, (uint32_t) &pixel_buf[0][0], (uint32_t) &OLED_SPI->DR, | |
LL_DMA_DIRECTION_MEMORY_TO_PERIPH); | |
LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_5, (uint32_t) WIDTH * PAGES); | |
// LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_5); | |
LL_SPI_EnableDMAReq_TX(OLED_SPI); | |
LL_SPI_Enable(OLED_SPI); | |
//gpio_reset(TFT_CS); | |
reset(); | |
write_command(0xAE); // Set display OFF | |
write_command(0xD5); // Set Display Clock Divide Ratio / OSC Frequency | |
write_command(0x80); // Display Clock Divide Ratio / OSC Frequency | |
write_command(0xA8); // Set Multiplex Ratio | |
write_command(0x3F); // Multiplex Ratio for 128x64 (64-1) | |
write_command(0xD3); // Set Display Offset | |
write_command(0x00); // Display Offset | |
write_command(0x40); // Set Display Start Line | |
write_command(0x8D); // Set Charge Pump | |
write_command(0x14); // Charge Pump (0x10 External, 0x14 Internal DC/DC) | |
write_command(0xA1); // Set Segment Re-Map | |
write_command(0xC8); // Set Com Output Scan Direction | |
write_command(0xDA); // Set COM Hardware Configuration | |
write_command(0x12); // COM Hardware Configuration | |
write_command(0x81); // Set Contrast | |
write_command(0xCF); // Contrast | |
write_command(0xD9); // Set Pre-Charge Period | |
write_command(0xF1); // Set Pre-Charge Period (0x22 External, 0xF1 Internal) | |
write_command(0xDB); // Set VCOMH Deselect Level | |
write_command(0x40); // VCOMH Deselect Level | |
write_command(0x20); //Set memory addressing mode | |
write_command(0x00); //Horizontal | |
// write_command(0x2E); | |
write_command(0xA4); // Set all pixels OFF | |
write_command(0xA6); // Set display not inverted | |
write_command(0xAF); // Set display On | |
delay(100); | |
oled_clear(); | |
} | |
static inline void set_region(uint8_t sx, uint8_t ex, uint8_t sy) { | |
write_command(0x21); | |
write_command(sx); | |
write_command(ex-1); | |
write_command(0x22); | |
write_command(sy); | |
write_command(PAGES - 1); | |
// write_command(HEIGHT); | |
} | |
static inline void set_cursor(uint8_t x, uint8_t y) { | |
write_command(0x21); | |
write_command(x); | |
write_command(WIDTH); | |
write_command(0x22); | |
write_command(y); | |
write_command(PAGES - 1); | |
// write_command(HEIGHT); | |
} | |
void oled_clear(void) { | |
set_region(0, WIDTH, 0); | |
// delay(1); | |
for (int i = WIDTH * PAGES; i; i--) { | |
write_data(0x00); | |
} | |
} | |
void oled_flash(void) { | |
set_region(0, WIDTH, 0); | |
for (int i = WIDTH * PAGES; i; i--) { | |
write_data(0xFF); | |
} | |
} | |
static inline void write_char(uint8_t ch) { | |
const uint8_t *cptr = CHAR_PTR(ch); | |
for (uint8_t i = FONT_WIDTH; i; i--) write_data(*cptr++); | |
} | |
void oled_write_char(uint8_t x, uint8_t y, uint8_t ch) { | |
set_region(x, x + FONT_WIDTH, y); | |
write_char(ch); | |
} | |
void oled_write_str(uint8_t x, uint8_t y, uint8_t wrapx, const char *pstr, ...) { | |
set_region(x, x + wrapx * FONT_WIDTH, y); | |
uint8_t buf[256]; | |
va_list arglist; | |
va_start(arglist, pstr); | |
vsprintf((char *) buf, (const char *) pstr, arglist); | |
va_end(arglist); | |
uint8_t * str = &buf[0]; | |
while (*str) { | |
write_char(*str++); | |
} | |
} | |
void oled_print_char(uint8_t x, uint8_t y, uint8_t ch) { | |
const uint8_t *cptr = CHAR_PTR(ch); | |
for (uint8_t i = 0; i < FONT_WIDTH; i++) { | |
pixel_buf[y][x+i] = *(cptr + i); | |
} | |
} | |
void oled_print_str(uint8_t x, uint8_t y, uint8_t wrapx, const char *pstr, ...) { | |
uint8_t wx = x + wrapx * FONT_WIDTH, ox = x; | |
uint8_t buf[256]; | |
va_list arglist; | |
va_start(arglist, pstr); | |
vsprintf((char *) buf, (const char *) pstr, arglist); | |
va_end(arglist); | |
uint8_t * str = &buf[0]; | |
while (*str) { | |
uint8_t ch = *str++; | |
const uint8_t *cptr = CHAR_PTR(ch); | |
for (uint8_t i = FONT_WIDTH; i; i--) pixel_buf[y][x++] = *cptr++; | |
if (x == wx) { | |
x = ox; | |
if (y++ == PAGES) y = 0; | |
} | |
} | |
} | |
void oled_update(void) { | |
set_region(0, WIDTH, 0); | |
//TODO: DMA Mode | |
gpio_set(OLED_DC); | |
LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_5); | |
// | |
// for (uint8_t i = 0; i<PAGES; i++) { | |
// for (uint8_t j = 0; j<WIDTH; j++) { | |
// write_data(pixel_buf[i][j]); | |
// } | |
// } | |
} | |
void DMA1_Stream5_IRQHandler() { | |
LL_DMA_ClearFlag_TC5(DMA1); | |
} | |
void oled_write_image(uint8_t x, uint8_t y, uint8_t w, uint8_t *lines, uint16_t len) { | |
set_region(x, x + w, y); | |
while (len--) { | |
write_data(*lines++); | |
} | |
} | |
void oled_scroll(OLEDScrollDirection dir, uint8_t start, uint8_t stop, OLEDScrollSpeed spd, uint8_t vertamt, uint8_t vfixed, | |
uint8_t vscroll) { | |
write_command(0x2E); //Disable scrolling | |
if (dir & 0x8) { | |
write_command(0xA3); | |
write_command(vfixed); | |
write_command(vscroll); | |
} | |
write_command(dir); //Setup scrolling | |
write_command(0); //dummy | |
write_command(start); | |
write_command(spd); //time interval | |
write_command(stop); | |
if (dir & 0x4) { | |
write_command(0); //dummy | |
write_command(0xFF); //dummy | |
} else { | |
write_command(vertamt); | |
} | |
write_command(0x2F); //Enable scrolling | |
} | |
void oled_stop_scroll(void) { | |
write_command(0x2E); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment