|
|
@ -3,6 +3,7 @@ |
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
|
|
|
|
#include "ufb/framebuffer.h" |
|
|
|
#include "ufb/framebuffer.h" |
|
|
|
#include "gpio.h" |
|
|
|
#include "gpio.h" |
|
|
@ -12,27 +13,32 @@ |
|
|
|
|
|
|
|
|
|
|
|
#define SSD1309_HEIGHT 64 |
|
|
|
#define SSD1309_HEIGHT 64 |
|
|
|
|
|
|
|
|
|
|
|
static inline void cs_select() { |
|
|
|
static inline void cs_select() |
|
|
|
|
|
|
|
{ |
|
|
|
asm volatile("nop \n nop \n nop"); |
|
|
|
asm volatile("nop \n nop \n nop"); |
|
|
|
HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, 0); // Active low
|
|
|
|
HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, 0); // Active low
|
|
|
|
asm volatile("nop \n nop \n nop"); |
|
|
|
asm volatile("nop \n nop \n nop"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void cs_deselect() { |
|
|
|
static inline void cs_deselect() |
|
|
|
|
|
|
|
{ |
|
|
|
asm volatile("nop \n nop \n nop"); |
|
|
|
asm volatile("nop \n nop \n nop"); |
|
|
|
HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, 1); |
|
|
|
HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, 1); |
|
|
|
asm volatile("nop \n nop \n nop"); |
|
|
|
asm volatile("nop \n nop \n nop"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void dc_command() { |
|
|
|
static inline void dc_command() |
|
|
|
|
|
|
|
{ |
|
|
|
HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, 0); |
|
|
|
HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void dc_data() { |
|
|
|
static inline void dc_data() |
|
|
|
|
|
|
|
{ |
|
|
|
HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, 1); |
|
|
|
HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void oled_command16(uint8_t cmd, uint8_t arg) { |
|
|
|
void oled_command16(uint8_t cmd, uint8_t arg) |
|
|
|
|
|
|
|
{ |
|
|
|
uint8_t buf[2]; |
|
|
|
uint8_t buf[2]; |
|
|
|
buf[0] = cmd; |
|
|
|
buf[0] = cmd; |
|
|
|
buf[1] = arg; |
|
|
|
buf[1] = arg; |
|
|
@ -42,14 +48,16 @@ void oled_command16(uint8_t cmd, uint8_t arg) { |
|
|
|
cs_deselect(); |
|
|
|
cs_deselect(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void oled_command(uint8_t cmd) { |
|
|
|
void oled_command(uint8_t cmd) |
|
|
|
|
|
|
|
{ |
|
|
|
dc_command(); |
|
|
|
dc_command(); |
|
|
|
cs_select(); |
|
|
|
cs_select(); |
|
|
|
HAL_SPI_Transmit(&OLED_HSPI, &cmd, 1, 1000); |
|
|
|
HAL_SPI_Transmit(&OLED_HSPI, &cmd, 1, 1000); |
|
|
|
cs_deselect(); |
|
|
|
cs_deselect(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void oled_reset() { |
|
|
|
void oled_reset() |
|
|
|
|
|
|
|
{ |
|
|
|
// Issue a display reset
|
|
|
|
// Issue a display reset
|
|
|
|
HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, 0); |
|
|
|
HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, 0); |
|
|
|
HAL_Delay(1); |
|
|
|
HAL_Delay(1); |
|
|
@ -57,7 +65,8 @@ void oled_reset() { |
|
|
|
HAL_Delay(1); |
|
|
|
HAL_Delay(1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void oled_invert(bool invert) { |
|
|
|
void oled_invert(bool invert) |
|
|
|
|
|
|
|
{ |
|
|
|
if (invert) { |
|
|
|
if (invert) { |
|
|
|
oled_command(0xA6); |
|
|
|
oled_command(0xA6); |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -65,7 +74,8 @@ void oled_invert(bool invert) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void oled_init() { |
|
|
|
void oled_init() |
|
|
|
|
|
|
|
{ |
|
|
|
oled_reset(); |
|
|
|
oled_reset(); |
|
|
|
|
|
|
|
|
|
|
|
// simplified display init
|
|
|
|
// simplified display init
|
|
|
@ -160,13 +170,75 @@ void oled_init() { |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void oled_data(uint8_t *data, size_t len) { |
|
|
|
static void transpose8_and_reverse(const uint8_t *a, uint8_t *b) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
uint32_t x, y, t; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Load the array and pack it into x and y.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]; |
|
|
|
|
|
|
|
y = (a[4] << 24) | (a[5] << 16) | (a[6] << 8) | a[7]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
t = (x ^ (x >> 7)) & 0x00AA00AA; |
|
|
|
|
|
|
|
x = x ^ t ^ (t << 7); |
|
|
|
|
|
|
|
t = (y ^ (y >> 7)) & 0x00AA00AA; |
|
|
|
|
|
|
|
y = y ^ t ^ (t << 7); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
t = (x ^ (x >> 14)) & 0x0000CCCC; |
|
|
|
|
|
|
|
x = x ^ t ^ (t << 14); |
|
|
|
|
|
|
|
t = (y ^ (y >> 14)) & 0x0000CCCC; |
|
|
|
|
|
|
|
y = y ^ t ^ (t << 14); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
t = (x & 0xF0F0F0F0) | ((y >> 4) & 0x0F0F0F0F); |
|
|
|
|
|
|
|
y = ((x << 4) & 0xF0F0F0F0) | (y & 0x0F0F0F0F); |
|
|
|
|
|
|
|
x = t; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// a[0] = x >> 24;
|
|
|
|
|
|
|
|
// a[1] = x >> 16;
|
|
|
|
|
|
|
|
// a[2] = x >> 8;
|
|
|
|
|
|
|
|
// a[3] = x;
|
|
|
|
|
|
|
|
// a[4] = y >> 24;
|
|
|
|
|
|
|
|
// a[5] = y >> 16;
|
|
|
|
|
|
|
|
// a[6] = y >> 8;
|
|
|
|
|
|
|
|
// a[7] = y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
b[7] = x >> 24; |
|
|
|
|
|
|
|
b[6] = x >> 16; |
|
|
|
|
|
|
|
b[5] = x >> 8; |
|
|
|
|
|
|
|
b[4] = x; |
|
|
|
|
|
|
|
b[3] = y >> 24; |
|
|
|
|
|
|
|
b[2] = y >> 16; |
|
|
|
|
|
|
|
b[1] = y >> 8; |
|
|
|
|
|
|
|
b[0] = y; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void oled_data(uint8_t *data, size_t len) |
|
|
|
|
|
|
|
{ |
|
|
|
dc_data(); |
|
|
|
dc_data(); |
|
|
|
cs_select(); |
|
|
|
cs_select(); |
|
|
|
HAL_SPI_Transmit(&OLED_HSPI, data, len, 1000); |
|
|
|
HAL_SPI_Transmit(&OLED_HSPI, data, len, 1000); |
|
|
|
cs_deselect(); |
|
|
|
cs_deselect(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void fb_blit() { |
|
|
|
void fb_blit() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
#if 0 |
|
|
|
oled_data(fb, FB_LEN); |
|
|
|
oled_data(fb, FB_LEN); |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
dc_data(); |
|
|
|
|
|
|
|
cs_select(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 90deg
|
|
|
|
|
|
|
|
uint8_t buf[8]; |
|
|
|
|
|
|
|
for (int j = FBW / 8 - 1; j >= 0; j--) { |
|
|
|
|
|
|
|
for (int i = 0; i < FBH / 8; i++) { |
|
|
|
|
|
|
|
// i, j are "square coords" (8x8)
|
|
|
|
|
|
|
|
transpose8_and_reverse(&fb[i * FBW + j * 8], buf); |
|
|
|
|
|
|
|
HAL_SPI_Transmit(&OLED_HSPI, buf, 8, 100); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cs_deselect(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|