diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2015-09-07 17:06:05 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2015-09-07 17:06:05 +0900 |
commit | 014dbf25f628a3befb930d23ee0c24d4e9b8f929 (patch) | |
tree | 31b25440aa30c411e98571efcaa3a7d15cd9d181 /example-primer2/lcd.c | |
parent | 41610443d4d53d229d83509464f73f2bd52d98e2 (diff) |
Add example-primer2
Diffstat (limited to 'example-primer2/lcd.c')
-rw-r--r-- | example-primer2/lcd.c | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/example-primer2/lcd.c b/example-primer2/lcd.c new file mode 100644 index 0000000..effbe24 --- /dev/null +++ b/example-primer2/lcd.c @@ -0,0 +1,388 @@ +#include <stdint.h> +#include <stdlib.h> +#include <chopstx.h> +#include "sys.h" /* for set_led */ +#include "st7732.h" +#include "board.h" + +#define PERIPH_BASE 0x40000000 +#define APBPERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) + +struct GPIO { + volatile uint32_t CRL; + volatile uint32_t CRH; + volatile uint32_t IDR; + volatile uint32_t ODR; + volatile uint32_t BSRR; + volatile uint32_t BRR; + volatile uint32_t LCKR; +}; + +#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) +#define GPIOA ((struct GPIO *) GPIOA_BASE) +#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) +#define GPIOB ((struct GPIO *) GPIOB_BASE) +#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) +#define GPIOC ((struct GPIO *) GPIOC_BASE) +#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400) +#define GPIOD ((struct GPIO *) GPIOD_BASE) +#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800) +#define GPIOE ((struct GPIO *) GPIOE_BASE) + +static struct GPIO *const GPIO_LCD = ((struct GPIO *const) GPIO_LED_BASE); +static struct GPIO *const GPIO_LCD_CTRL = ((struct GPIO *const) GPIO_USB_BASE); + +#define GPIO_LCD_RD 4 +#define GPIO_LCD_WR 5 +#define GPIO_LCD_RST 6 +#define GPIO_LCD_CS 7 +#define GPIO_LCD_RS 11 +/* PE7:LCD_D0 - PE14:LCD_D7 */ +#define GPIO_DATA_SHIFT 7 +#define GPIO_DATA_MASK (0xff << GPIO_DATA_SHIFT) + +static void +lcd_command_common (st7732_cmd_t cmd) +{ + /* Set command. */ + GPIO_LCD->BRR = GPIO_DATA_MASK & ~(cmd << GPIO_DATA_SHIFT); + GPIO_LCD->BSRR = GPIO_DATA_MASK & (cmd << GPIO_DATA_SHIFT); + /* Set CMD mode. */ + GPIO_LCD_CTRL->BRR = (1 << GPIO_LCD_RS); + /* Asert /CS. */ + GPIO_LCD_CTRL->BRR = (1<< GPIO_LCD_CS); + /* Asert /WR. */ + GPIO_LCD_CTRL->BRR = (1<< GPIO_LCD_WR); + // chopstx_usec_wait (1); + /* Negate /WR. */ + GPIO_LCD_CTRL->BSRR = (1<< GPIO_LCD_WR); + + /* Return DATA mode. */ + GPIO_LCD_CTRL->BSRR = (1 << GPIO_LCD_RS); +} + +/* Issue command with no data read/write. */ +void +lcd_command_no (st7732_cmd_t cmd) +{ + lcd_command_common (cmd); + + /* Negate /CS. */ + GPIO_LCD_CTRL->BSRR = (1<< GPIO_LCD_CS); +} + +#if 0 +void +lcd_command_readn (st7732_cmd_t cmd, uint8_t *data, size_t n) +{ + volatile int dummy __attribute__ ((unused)); + + lcd_command_common (cmd); + + /* Set GPIO_LCD to input mode. */ + GPIO_LCD->CRH = 0x88888888; + GPIO_LCD->CRL = 0x88888833; + + /* Assert /RD. */ + GPIO_LCD_CTRL->BRR = (1<< GPIO_LCD_RD); + // chopstx_usec_wait (1); + /* Dummy read. */ + dummy = GPIO_LCD->IDR; + /* Negate /RD. */ + GPIO_LCD_CTRL->BSRR = (1<< GPIO_LCD_RD); + + /* Read loop. */ + while (n-- > 0) + { + /* Assert /RD. */ + GPIO_LCD_CTRL->BRR = (1<< GPIO_LCD_RD); + // chopstx_usec_wait (1); + /* Negate /RD. */ + GPIO_LCD_CTRL->BSRR = (1<< GPIO_LCD_RD); + *data++ = GPIO_LCD->IDR >> GPIO_DATA_SHIFT; + } + + /* Negate /CS. */ + GPIO_LCD_CTRL->BSRR = (1<< GPIO_LCD_CS); + + /* Set GPIO_LCD to output mode. */ + GPIO_LCD->CRH = 0x83333333; + GPIO_LCD->CRL = 0x38888833; +} +#endif + +/* Issue command with N data write. */ +void +lcd_command_writen (st7732_cmd_t cmd, uint8_t *data, size_t n) +{ + lcd_command_common (cmd); + + /* Write loop. */ + while (n-- > 0) + { + uint8_t b = *data++; + + GPIO_LCD->BRR = GPIO_DATA_MASK & ~(b << GPIO_DATA_SHIFT); + GPIO_LCD->BSRR = GPIO_DATA_MASK & (b << GPIO_DATA_SHIFT); + /* Assert /WR. */ + GPIO_LCD_CTRL->BRR = (1<< GPIO_LCD_WR); + // chopstx_usec_wait (1); + /* Negate /WR. */ + GPIO_LCD_CTRL->BSRR = (1<< GPIO_LCD_WR); + } + + /* Negate /CS. */ + GPIO_LCD_CTRL->BSRR = (1<< GPIO_LCD_CS); +} + +/* Issue command with N same data write. */ +void +lcd_command_filln (st7732_cmd_t cmd, uint8_t b, size_t n) +{ + lcd_command_common (cmd); + + /* Write loop. */ + while (n-- > 0) + { + GPIO_LCD->BRR = GPIO_DATA_MASK & ~(b << GPIO_DATA_SHIFT); + GPIO_LCD->BSRR = GPIO_DATA_MASK & (b << GPIO_DATA_SHIFT); + /* Assert /WR. */ + GPIO_LCD_CTRL->BRR = (1<< GPIO_LCD_WR); + // chopstx_usec_wait (1); + /* Negate /WR. */ + GPIO_LCD_CTRL->BSRR = (1<< GPIO_LCD_WR); + } + + /* Negate /CS. */ + GPIO_LCD_CTRL->BSRR = (1<< GPIO_LCD_CS); +} + +static chopstx_mutex_t lcd_mtx; +static chopstx_cond_t lcd_cnd0; +static chopstx_cond_t lcd_cnd1; + +/* Process for initializing ST7732. */ +static void * +lcd_initializer (void *arg __attribute__((unused))) +{ + uint8_t args[16]; + + chopstx_mutex_lock (&lcd_mtx); + chopstx_cond_wait (&lcd_cnd0, &lcd_mtx); + chopstx_mutex_unlock (&lcd_mtx); + + /* Set GPIO_LCD to write mode. */ + GPIO_LCD->CRH = 0x83333333; + GPIO_LCD->CRL = 0x38888833; + + /* Set GPIO_LCD_CTRL IO mode. */ + GPIO_LCD_CTRL->CRH = 0x88883888; + GPIO_LCD_CTRL->CRL = 0x33333888; + + /* Restart ST7732. */ + /* Hard reset. */ + chopstx_usec_wait (100000); + GPIO_LCD_CTRL->BRR = (1 << GPIO_LCD_RST); + chopstx_usec_wait (100000); + GPIO_LCD_CTRL->BSRR = (1 << GPIO_LCD_RST); + chopstx_usec_wait (100000); + + /* Software reset. */ + lcd_command_no (SWRESET); + chopstx_usec_wait (150000); + + /* Sleep in. */ + lcd_command_no (SLPIN); + chopstx_usec_wait (100000); + + /* Sleep out. */ + lcd_command_no (SLPOUT); + chopstx_usec_wait (100000); + + /* Configure ST7732. Set display mode, pixel mode, etc. */ + /* FRMCTR1, 6, 3, 2 */ + args[0] = 0x06; args[1] = 0x03; args[2] = 0x02; + lcd_command_writen (FRMCTR1, args, 3); + /* INVCTR, 3 */ + args[0] = 0x03; + lcd_command_writen (INVCTR, args, 1); + /* DISSET5, 2, eh */ + args[0] = 0x02; args[1] = 0x0e; + lcd_command_writen (DISSET5, args, 2); + /* DISPCTRL, 1ah */ + args[0] = 0x1a; + lcd_command_writen (DISPCTRL, args, 1); + /* PWCTR1, 2, 0 */ + args[0] = 0x02; args[1] = 0x00; + lcd_command_writen (PWCTR1, args, 2); + /* PWCTR2, 5 */ + args[0] = 0x05; + lcd_command_writen (PWCTR2, args, 1); + /* PWCTR3, 2, 2 */ + args[0] = 0x02; args[1] = 0x02; + lcd_command_writen (PWCTR3, args, 2); + /* PWCTR4, 1, 2 */ + args[0] = 0x01; args[1] = 0x00; + lcd_command_writen (PWCTR4, args, 2); + /* PWCTR5, 1, 2 */ + args[0] = 0x01; args[1] = 0x00; + lcd_command_writen (PWCTR5, args, 2); + /* VMCTR1, 47h, 2ah */ + args[0] = 0x47; args[1] = 0x2a; + lcd_command_writen (VMCTR1, args, 2); + /* OSCADJ, 4ch */ + args[0] = 0x4c; + lcd_command_writen (OSCADJ, args, 1); + /* DEFADJ, 6 */ + args[0] = 0x06; + lcd_command_writen (DEFADJ, args, 1); + + /* gamma adjust */ + + /* MADCTL, c0h MY=1, MX=1 */ + args[0] = 0xc0; + lcd_command_writen (MADCTL, args, 1); + + /* Set RA and CA. */ + /* RASET, 0, 0, 0, 159 */ + args[0] = 0x00; args[1] = 0x00; args[2] = 0x00; args[3] = LCD_ROW-1; + lcd_command_writen (RASET, args, 4); + /* CASET, 0, 0, 0, 127 */ + args[0] = 0x00; args[1] = 0x00; args[2] = 0x00; args[3] = LCD_COLUMN-1; + lcd_command_writen (CASET, args, 4); + + /* 0x06: RGB 6-6-6-bit. */ + args[0] = 0x06; + lcd_command_writen (COLMOD, args, 1); + + args[0] = 0; + lcd_command_writen (TEON, args, 1); + + lcd_command_no (DISPON); + + /* Wait 20ms. */ + chopstx_usec_wait (20000); + + chopstx_mutex_lock (&lcd_mtx); + chopstx_cond_signal (&lcd_cnd1); + chopstx_mutex_unlock (&lcd_mtx); + + return NULL; +} + +/* Plot a point with rgb color. 2 LSBs of rgb values will be ignored. */ +void +lcd_draw_point (int x, int y, int r, int g, int b) +{ + uint8_t args[4]; + + /* Set RA and CA. */ + /* RASET, 0, y, 0, y */ + args[0] = 0x00; args[1] = y; args[2] = 0x00; args[3] = y; + lcd_command_writen (RASET, args, 4); + /* CASET, 0, x, 0, x */ + args[0] = 0x00; args[1] = x; args[2] = 0x00; args[3] = x; + lcd_command_writen (CASET, args, 4); + + args[0] = r; args[1] = g; args[2] = b; + lcd_command_writen (RAMWR, args, 3); +} + +static uint8_t hexfont5x8[16*5] = { + 0x7e, 0x89, 0x91, 0xa1, 0x7e, /* 0 */ + 0x00, 0x41, 0xff, 0x01, 0x00, /* 1 */ + 0x43, 0x85, 0x89, 0x91, 0x61, /* 2 */ + 0x42, 0x81, 0x91, 0x91, 0x6e, /* 3 */ + 0x18, 0x28, 0x48, 0xff, 0x08, /* 4 */ + 0xf2, 0x91, 0x91, 0x91, 0x8e, /* 5 */ + 0x1e, 0x29, 0x49, 0x89, 0x86, /* 6 */ + 0x80, 0x8f, 0x90, 0xa0, 0xc0, /* 7 */ + 0x6e, 0x91, 0x91, 0x91, 0x6e, /* 8 */ + 0x70, 0x89, 0x89, 0x8a, 0x7c, /* 9 */ + 0x7f, 0x88, 0x88, 0x88, 0x7f, /* A */ + 0xff, 0x91, 0x91, 0x91, 0x6e, /* B */ + 0x7e, 0x81, 0x81, 0x81, 0x42, /* C */ + 0xff, 0x81, 0x81, 0x42, 0x3c, /* D */ + 0xff, 0x91, 0x91, 0x91, 0x81, /* E */ + 0xff, 0x90, 0x90, 0x90, 0x80, /* F */ +}; + +/* Draw hex number with rgb color. */ +void +lcd_draw_hexfont5x8 (uint32_t hex, int x, int y, int r, int g, int b, int bg) +{ + int i, j; + uint8_t *p; + uint8_t args[5*8*3]; + + p = &hexfont5x8[(hex & 0xf)*5]; + + /* Set RA and CA. */ + /* RASET, 0, y, 0, y+8-1 */ + args[0] = 0x00; args[1] = y; args[2] = 0x00; args[3] = y+7; + lcd_command_writen (RASET, args, 4); + /* CASET, 0, x, 0, x+5-1 */ + args[0] = 0x00; args[1] = x; args[2] = 0x00; args[3] = x+4; + lcd_command_writen (CASET, args, 4); + + for (i = 0; i < 5; i++) + { + uint8_t rb = *p++; + for (j = 0; j < 8; j++) + { + int k = (5*j+i)*3; + if (rb & (0x80 >> j)) + { + args[k] = r; args[k+1] = g; args[k+2] = b; + } + else + { + args[k] = bg; args[k+1] = bg; args[k+2] = bg; + } + } + } + + lcd_command_writen (RAMWR, args, 5*8*3); +} + +void +lcd_printhex (uint32_t hex, int x, int y, int r, int g, int b, int bg) +{ + int i; + + if (y < 0 || y >= LCD_ROW - 8) + return; + for (i = 7; i >= 0; i--) + { + lcd_draw_hexfont5x8 ((hex >> 4*i)&0xf, x, y, r, g, b, bg); + x += 5; + if (x >= LCD_COLUMN - 5) + break; + } +} + +#define PRIO_LCD 3 + +extern uint8_t __process1_stack_base__, __process1_stack_size__; +const uint32_t __stackaddr_lcd = (uint32_t)&__process1_stack_base__; +const size_t __stacksize_lcd = (size_t)&__process1_stack_size__; + +/* Initialize LCD. */ +void +lcd_init (void) +{ + chopstx_mutex_init (&lcd_mtx); + chopstx_cond_init (&lcd_cnd0); + chopstx_cond_init (&lcd_cnd1); + + chopstx_create (PRIO_LCD, __stackaddr_lcd, __stacksize_lcd, + lcd_initializer, NULL); + + chopstx_usec_wait (200*1000); + + chopstx_mutex_lock (&lcd_mtx); + chopstx_cond_signal (&lcd_cnd0); + chopstx_cond_wait (&lcd_cnd1, &lcd_mtx); + chopstx_mutex_unlock (&lcd_mtx); +} |