From 7d1bd872093cb333c4ff716192b2b5ecc01027f2 Mon Sep 17 00:00:00 2001 From: arighi Date: Thu, 8 Apr 2010 16:54:40 +0000 Subject: [PATCH] lm3s1968: RIT128x96x4 OLED display driver. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3402 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/cortex-m3/drv/gpio_lm3s.c | 6 - bertos/cpu/cortex-m3/drv/gpio_lm3s.h | 6 + bertos/cpu/cortex-m3/drv/lcd_lm3s.c | 228 +++++++++++++++++++++++++++ bertos/cpu/cortex-m3/drv/lcd_lm3s.h | 49 ++++++ bertos/gfx/gfx.h | 2 +- 5 files changed, 284 insertions(+), 7 deletions(-) create mode 100644 bertos/cpu/cortex-m3/drv/lcd_lm3s.c create mode 100644 bertos/cpu/cortex-m3/drv/lcd_lm3s.h diff --git a/bertos/cpu/cortex-m3/drv/gpio_lm3s.c b/bertos/cpu/cortex-m3/drv/gpio_lm3s.c index 68af31ae..1c2549f2 100644 --- a/bertos/cpu/cortex-m3/drv/gpio_lm3s.c +++ b/bertos/cpu/cortex-m3/drv/gpio_lm3s.c @@ -40,12 +40,6 @@ #include "io/lm3s.h" #include "gpio_lm3s.h" -/* Write a value to the specified pin(s) */ -void lm3s_gpio_pin_write(uint32_t port, uint8_t pins, uint8_t val) -{ - HWREG(port + (GPIO_O_DATA + (pins << 2))) = val; -} - /** * Configure a GPIO pin * diff --git a/bertos/cpu/cortex-m3/drv/gpio_lm3s.h b/bertos/cpu/cortex-m3/drv/gpio_lm3s.h index 70179cfc..21afd327 100644 --- a/bertos/cpu/cortex-m3/drv/gpio_lm3s.h +++ b/bertos/cpu/cortex-m3/drv/gpio_lm3s.h @@ -68,6 +68,12 @@ #define GPIO_PIN_TYPE_ANALOG 0x00000000 //< Analog comparator /*\}*/ +/* Write a value to the specified pin(s) */ +INLINE void lm3s_gpio_pin_write(uint32_t port, uint8_t pins, uint8_t val) +{ + HWREG(port + (GPIO_O_DATA + (pins << 2))) = val; +} + int lm3s_gpio_pin_config(uint32_t port, uint8_t pins, uint32_t mode, uint32_t strength, uint32_t type); void lm3s_gpio_pin_write(uint32_t port, uint8_t pins, uint8_t val); diff --git a/bertos/cpu/cortex-m3/drv/lcd_lm3s.c b/bertos/cpu/cortex-m3/drv/lcd_lm3s.c new file mode 100644 index 00000000..2c98486f --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/lcd_lm3s.c @@ -0,0 +1,228 @@ +/** + * \file + * + * + * \brief LM3S1968 OLED display driver. + * + * \author Andrea Righi + */ + +#include +#include +#include "io/lm3s.h" +#include "clock_lm3s.h" +#include "ssi_lm3s.h" +#include "gpio_lm3s.h" +#include "lcd_lm3s.h" + +#define GPIO_OLEDDC_BASE GPIO_PORTH_BASE +#define GPIO_OLEDDC_PIN BV(2) +#define GPIO_OLEDEN_PIN BV(3) + +/* + * Hard-coded command initialization sequence. + * + * NOTE: the first byte is the size of the command. + */ +static const uint8_t init_cmd[] = +{ + /* Unlock commands */ + 3, 0xfd, 0x12, 0xe3, + /* Display off */ + 2, 0xae, 0xe3, + /* Icon off */ + 3, 0x94, 0, 0xe3, + /* Multiplex ratio */ + 3, 0xa8, 95, 0xe3, + /* Contrast */ + 3, 0x81, 0xb7, 0xe3, + /* Pre-charge current */ + 3, 0x82, 0x3f, 0xe3, + /* Display Re-map */ + 3, 0xa0, 0x52, 0xe3, + /* Display Start Line */ + 3, 0xa1, 0, 0xe3, + /* Display Offset */ + 3, 0xa2, 0x00, 0xe3, + /* Display Mode Normal */ + 2, 0xa4, 0xe3, + /* Phase Length */ + 3, 0xb1, 0x11, 0xe3, + /* Frame frequency */ + 3, 0xb2, 0x23, 0xe3, + /* Front Clock Divider */ + 3, 0xb3, 0xe2, 0xe3, + /* Set gray scale table */ + 17, 0xb8, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 19, 22, 26, 30, 0xe3, + /* Second pre-charge period */ + 3, 0xbb, 0x01, 0xe3, + /* Pre-charge voltage */ + 3, 0xbc, 0x3f, 0xe3, + /* Display ON */ + 2, 0xaf, 0xe3, +}; + +/* + * Hard-coded command shutdown sequence. + */ +static const uint8_t exit_cmd[] = +{ + /* Display OFF */ + 0xae, 0xe3 +}; + +/* + * Hard-coded horizontal increment command. + */ +static const uint8_t horizontal_inc[] = +{ + 0xa0, 0x52 +}; + +/** + * Write a sequence of data bytes to the LCD SSD1329 controller + */ +static void lcd_writeData(const uint8_t *buf, size_t count) +{ + while (count--) + lm3s_ssi_write_frame(SSI0_BASE, *buf++); +} + +/* Turn on the OLED display */ +void lm3s_lcd_on(void) +{ + unsigned int i; + + /* Loop through the SSD1329 controller initialization sequence */ + for (i = 0; i < sizeof(init_cmd); i += init_cmd[i] + 1) + { + lm3s_gpio_pin_write(GPIO_OLEDDC_BASE, GPIO_OLEDDC_PIN, 0); + lcd_writeData(init_cmd + i + 1, init_cmd[i] - 1); + } +} + +/* Turn off the OLED display */ +void lm3s_lcd_off(void) +{ + lm3s_gpio_pin_write(GPIO_OLEDDC_BASE, GPIO_OLEDDC_PIN, 0); + lcd_writeData(exit_cmd, sizeof(exit_cmd)); +} + +/* Refresh a bitmap on screen */ +void lm3s_lcd_blitBitmap(const Bitmap *bm) +{ + uint8_t lcd_row[bm->width / 2]; + uint8_t buffer[8]; + uint8_t mask; + int i, l; + + ASSERT(bm->width == LCD_WIDTH && bm->height == LCD_HEIGHT); + + /* Enter command mode */ + lm3s_gpio_pin_write(GPIO_OLEDDC_BASE, GPIO_OLEDDC_PIN, 0); + + buffer[0] = 0x15; + buffer[1] = 0; + buffer[2] = (bm->width - 2) / 2; + lcd_writeData(buffer, 3); + + buffer[0] = 0x75; + buffer[1] = 0; + buffer[2] = bm->height - 1; + lcd_writeData(buffer, 3); + lcd_writeData((const uint8_t *)&horizontal_inc, sizeof(horizontal_inc)); + + /* + * Enter data mode and send the encoded image data to the OLED display, + * over the SSI bus. + */ + lm3s_gpio_pin_write(GPIO_OLEDDC_BASE, GPIO_OLEDDC_PIN, GPIO_OLEDDC_PIN); + for (l = 0; l < bm->height / 8; l++) + { + for (mask = 1; mask; mask <<= 1) + { + for (i = 0; i < bm->width; i++) + { + if (bm->raster[l * bm->width + i] & mask) + lcd_row[i / 2] |= i & 1 ? 0x0f : 0xf0; + else + lcd_row[i / 2] &= i & 1 ? 0xf0 : 0x0f; + } + /* Write an entire row at once */ + lcd_writeData(lcd_row, sizeof(lcd_row)); + } + } +} + +/** + * Initialize the OLED display + * + * \param freq The SSI Clock Frequency + */ +void lm3s_lcd_init(unsigned long freq) +{ + uint32_t dummy; + + /* Enable the peripheral clock */ + SYSCTL_RCGC1_R |= SYSCTL_RCGC1_SSI0; + SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOA; + SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOH; + __delay(512); + + /* Configure the SSI0CLK and SSIOTX pins for SSI operation. */ + lm3s_gpio_pin_config(GPIO_PORTA_BASE, BV(2) | BV(3) | BV(5), + GPIO_DIR_MODE_HW, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPU); + /* + * Configure the GPIO port pin used as a D/Cn signal for OLED device, + * and the port pin used to enable power to the OLED panel. + */ + lm3s_gpio_pin_config(GPIO_OLEDDC_BASE, GPIO_OLEDDC_PIN | GPIO_OLEDEN_PIN, + GPIO_DIR_MODE_OUT, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD); + lm3s_gpio_pin_write(GPIO_OLEDDC_BASE, GPIO_OLEDDC_PIN | GPIO_OLEDEN_PIN, + GPIO_OLEDDC_PIN | GPIO_OLEDEN_PIN); + + /* Configure the SSI0 port for master mode */ + lm3s_ssi_init(SSI0_BASE, SSI_FRF_MOTO_MODE_2, SSI_MODE_MASTER, freq, 8); + /* + * Configure the GPIO port pin used as a D/Cn signal for OLED device, + * and the port pin used to enable power to the OLED panel. + */ + lm3s_gpio_pin_config(GPIO_PORTA_BASE, GPIO_OLEDEN_PIN, + GPIO_DIR_MODE_HW, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPU); + /* Enable the SSI port */ + lm3s_ssi_enable(SSI0_BASE); + + /* Drain the RX fifo */ + while (lm3s_ssi_read_frame_nonblocking(SSI0_BASE, &dummy)); + + /* Turn on the OLED display */ + lm3s_lcd_on(); +} diff --git a/bertos/cpu/cortex-m3/drv/lcd_lm3s.h b/bertos/cpu/cortex-m3/drv/lcd_lm3s.h new file mode 100644 index 00000000..72048615 --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/lcd_lm3s.h @@ -0,0 +1,49 @@ +/** + * \file + * + * + * \brief LM3S1968 OLED display driver. + */ + +#ifndef LCD_LM3S_H +#define LCD_LM3S_H + +#include /* Bitmap */ + +#define LCD_WIDTH 128 +#define LCD_HEIGHT 96 + +void lm3s_lcd_blitBitmap(const Bitmap *bm); +void lm3s_lcd_on(void); +void lm3s_lcd_off(void); +void lm3s_lcd_init(unsigned long freq); + +#endif /* LCD_LM3S_H */ diff --git a/bertos/gfx/gfx.h b/bertos/gfx/gfx.h index da10433d..eeef5bc7 100644 --- a/bertos/gfx/gfx.h +++ b/bertos/gfx/gfx.h @@ -154,7 +154,7 @@ typedef struct Image * Compute the size in bytes of a raster suitable for * holding a bitmap of \a width x \a height pixels. */ - #define RAST_SIZE(width, height) ( ((width) + 7 / 8) * (height) ) + #define RAST_SIZE(width, height) ( (((width) + 7) / 8) * (height) ) #elif CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_V_LSB /** -- 2.25.1