summaryrefslogtreecommitdiffstats
path: root/stm32/app/oled.c
diff options
context:
space:
mode:
Diffstat (limited to 'stm32/app/oled.c')
-rw-r--r--stm32/app/oled.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/stm32/app/oled.c b/stm32/app/oled.c
new file mode 100644
index 0000000..983fe9a
--- /dev/null
+++ b/stm32/app/oled.c
@@ -0,0 +1,190 @@
+#include "project.h"
+
+
+int
+ssd1306_cmds (uint32_t i2c, uint8_t *buf, size_t len, int delay)
+{
+
+ int ret = -1;
+
+ while (i2c_lock());
+
+ do {
+
+ if (i2cp_start_transaction (i2c, SSD1306_I2C_ADDRESS, I2C_WRITE))
+ break;
+
+ if (i2cp_send (i2c, SSD1306_COMMAND))
+ break;
+
+ while (len--)
+ if (i2cp_send (i2c, * (buf++)))
+ break;
+
+ i2cp_stop (i2c);
+
+ if (delay)
+ delay_us (delay);
+
+ ret = 0;
+ } while (0);
+
+ i2c_unlock();
+
+
+ return ret;
+}
+
+int
+ssd1306_cmd (uint32_t i2c, uint8_t cmd, int delay)
+{
+ return ssd1306_cmds (i2c, &cmd, 1, delay);
+}
+
+
+
+void
+oled_generate_stream (uint8_t *vram)
+{
+ memset (vram, 0, DMA_BUF_SZ);
+ vram[0] = SSD1306_DATA_CONTINUE;
+}
+
+
+
+
+void
+oled_cls (uint8_t *vram)
+{
+ memset (vram + 1, 0, SSD1306_VRAM_SIZE);
+}
+
+
+void
+oled_on (uint32_t i2c)
+{
+ ssd1306_cmd (i2c, SSD1306_DISPLAY_ON, 0);
+
+}
+
+
+void
+oled_off (uint32_t i2c)
+{
+ ssd1306_cmd (i2c, SSD1306_DISPLAY_OFF, 0);
+}
+
+
+
+#if 0
+void
+oled_squirt (void)
+{
+ unsigned i;
+ uint8_t cmds[] = {
+ SSD1306_SET_PAGE_ADDR, 0, 0xff,
+ SSD1306_SET_COLUMN_ADDR, 0, SSD1306_WIDTH - 1
+ };
+
+ ssd1306_cmds (cmds, sizeof (cmds), 0);
+
+
+ while (i2c_lock());
+
+ i2cp_start_transaction (SSD1306_I2C_ADDRESS, I2C_WRITE);
+
+ for (i = 0; i < DMA_BUF_SZ; ++i)
+ i2cp_send (update_buf[i]);
+
+ i2cp_stop();
+
+ i2c_unlock();
+}
+#endif
+
+void
+oled_reset (uint32_t i2c)
+{
+ uint8_t init[] = {
+ SSD1306_DISPLAY_OFF,
+ SSD1306_SET_DISPLAY_CLOCK_DIV_RATIO, 0x80,
+ SSD1306_SET_MULTIPLEX_RATIO, SSD1306_HEIGHT - 1,
+ SSD1306_SET_DISPLAY_OFFSET, 0x0,
+ SSD1306_SET_START_LINE | 0x0,
+ SSD1306_CHARGE_PUMP, 0x14,
+ SSD1306_MEMORY_ADDR_MODE, 0x00,
+ SSD1306_SET_SEGMENT_REMAP | 0x1,
+ SSD1306_COM_SCAN_DIR_DEC,
+ //SSD1306_SET_COM_PINS, 0x12,
+ SSD1306_SET_COM_PINS, 0x02,
+ //SSD1306_SET_CONTRAST_CONTROL, 0xCF,
+ SSD1306_SET_CONTRAST_CONTROL, 0x8F,
+ SSD1306_SET_PRECHARGE_PERIOD, 0xF1,
+ SSD1306_SET_VCOM_DESELECT, 0x40,
+ SSD1306_DISPLAY_ALL_ON_RESUME,
+ SSD1306_NORMAL_DISPLAY,
+ SSD1306_DISPLAY_ON,
+ };
+
+ ssd1306_cmds (i2c, init, sizeof (init), 0);
+}
+
+
+void
+oled_const_strip (uint8_t *vram, int x, int xe, uint8_t and, uint8_t or)
+{
+ uint8_t r;
+
+ for (x++; x <= xe; ++x) {
+ r = vram[x] & and;
+ vram[x] = r | or;
+ }
+}
+
+
+void
+oled_blit_strip (uint8_t *vram, int x, int xe, uint8_t mask, int shift,
+ const uint8_t *src)
+{
+ uint8_t r, s;
+
+ while (x < 0) {
+ x++;
+ src++;
+ };
+
+ if (xe < 0) xe = 0;
+
+ if (x > SSD1306_VRAM_SIZE) xe = SSD1306_VRAM_SIZE;
+
+ if (xe > SSD1306_VRAM_SIZE) xe = SSD1306_VRAM_SIZE;
+
+
+ if (shift > 0) {
+ for (x++; x <= xe; ++x) {
+ s = * (src++);
+ s <<= shift;
+ s &= mask;
+ r = vram[x] & ~mask;
+ vram[x] = r | s;
+
+ }
+ } else if (shift < 0) {
+ shift = -shift;
+
+ for (x++; x <= xe; ++x) {
+ s = * (src++);
+ s >>= shift;
+ s &= mask;
+ r = vram[x] & ~mask;
+ vram[x] = r | s;
+ }
+ } else {
+ for (x++; x <= xe; ++x) {
+ s = * (src++);
+ s &= mask;
+ r = vram[x] & ~mask;
+ vram[x] = r | s;
+ }
+ }
+}