From d85f3aeeeefd6926fe71ec8e066adb74f62dc1cc Mon Sep 17 00:00:00 2001 From: fishsoupisgood Date: Sat, 13 Jun 2020 21:05:45 +0100 Subject: fish --- app/oled.c | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 app/oled.c (limited to 'app/oled.c') diff --git a/app/oled.c b/app/oled.c new file mode 100644 index 0000000..51cfd9a --- /dev/null +++ b/app/oled.c @@ -0,0 +1,281 @@ +#include "project.h" + + +#define DMA_BUF_SZ (2 + (SSD1306_VRAM_SIZE)) + +uint8_t dma_buf[DMA_BUF_SZ]; +uint8_t update_buf[DMA_BUF_SZ]; +static int dma_in_progress = 0; +static int refresh_enabled = 0; +static uint32_t refresh_wdt = 0; + + +int +ssd1306_cmds (uint8_t * buf, size_t len, int delay) +{ + + while (i2c_lock ()); + + i2cp_start_transaction (SSD1306_I2C_ADDRESS, I2C_WRITE); + i2cp_send (SSD1306_COMMAND); + + while (len--) + i2cp_send (*(buf++)); + + i2cp_stop (); + + if (delay) + delay_us (delay); + i2c_unlock (); + + return 0; +} + +int +ssd1306_cmd (uint8_t cmd, int delay) +{ + return ssd1306_cmds (&cmd, 1, delay); +} + + + +static void +start_dma (void) +{ + uint8_t cmds[] = { + SSD1306_SET_PAGE_ADDR, 0, 0xff, + SSD1306_SET_COLUMN_ADDR, 0, SSD1306_WIDTH - 1 + }; + + if (dma_in_progress) + return; + + refresh_wdt = 0; + + dma_in_progress = 1; + + memcpy (dma_buf, update_buf, DMA_BUF_SZ); + + ssd1306_cmds (cmds, sizeof (cmds), 0); + + i2cp_start_transaction (SSD1306_I2C_ADDRESS, I2C_WRITE); + i2cp_start_dma (dma_buf, DMA_BUF_SZ); +} + + + +void +dma1_channel6_isr (void) +{ + if (dma_in_progress) + { + i2cp_stop_dma (); + + i2cp_stop (); + dma_in_progress = 0; + } + + if (refresh_enabled) + start_dma (); +} + +void +oled_refresh_wdt (void) +{ + if (!refresh_enabled) + return; + + refresh_wdt++; + + + if (refresh_wdt < 1000) + return; + + refresh_wdt = 0; + +/*No refresh for 1s, restart everything */ + + i2cp_stop_dma (); + i2cp_stop (); + dma_in_progress = 0; + + start_dma (); + +} + +static void +dma_generate_stream (void) +{ + memset (update_buf, 0, DMA_BUF_SZ); + update_buf[0] = SSD1306_DATA_CONTINUE; +} + + + +void +oled_enable_refresh (void) +{ + refresh_enabled = 1; + start_dma (); +} + + +void +oled_disable_refresh (void) +{ + refresh_enabled = 0; + while (dma_in_progress); +} + +void +oled_cls (void) +{ + memset (update_buf + 1, 0, SSD1306_VRAM_SIZE); +} + + +void +oled_on (void) +{ + ssd1306_cmd (SSD1306_DISPLAY_ON, 0); + +} + + +void +oled_off (void) +{ + ssd1306_cmd (SSD1306_DISPLAY_OFF, 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 (); +} + +void +oled_reset (void) +{ + 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 (init, sizeof (init), 0); +} + + +void +oled_const_strip (int x, int xe, uint8_t and, uint8_t or) +{ + uint8_t r; + + for (x++; x <= xe; ++x) + { + r = update_buf[x] & and; + update_buf[x] = r | or; + } +} + + +void +oled_blit_strip (int x, int xe, uint8_t mask, int shift, uint8_t * src) +{ + uint8_t r, s; + + + if (shift > 0) + { + for (x++; x <= xe; ++x) + { + s = *(src++); + s <<= shift; + s &= mask; + r = update_buf[x] & ~mask; + update_buf[x] = r | s; + + } + } + else if (shift < 0) + { + shift = -shift; + for (x++; x <= xe; ++x) + { + s = *(src++); + s >>= shift; + s &= mask; + r = update_buf[x] & ~mask; + update_buf[x] = r | s; + } + } + else + { + for (x++; x <= xe; ++x) + { + s = *(src++); + s &= mask; + r = update_buf[x] & ~mask; + update_buf[x] = r | s; + } + } +} + + + +void +oled_init () +{ + oled_reset (); + + delay_us (100); + + dma_generate_stream (); + + nvic_enable_irq (NVIC_DMA1_CHANNEL6_IRQ); + oled_enable_refresh (); +} + + +void +oled_shutdown (void) +{ + oled_disable_refresh (); + oled_off (); +} -- cgit v1.2.3