コード例 #1
0
static inline int ssd1289_hwinitialize(FAR struct ssd1289_dev_s *priv)
{
    FAR struct ssd1289_lcd_s *lcd  = priv->lcd;
#ifndef CONFIG_LCD_NOGETRUN
    uint16_t id;
#endif
    int ret;

    /* Select the LCD */

    lcd->select(lcd);

    /* Read the device ID.  Skip verification of the device ID is the LCD is
     * write-only. What choice do we have?
     */

#ifndef CONFIG_LCD_NOGETRUN
    id = ssd1289_readreg(lcd, SSD1289_DEVCODE);
    if (id != 0)
    {
        lcddbg("LCD ID: %04x\n", id);
    }

    /* If we could not get the ID, then let's just assume that this is an SSD1289.
     * Perhaps we have some early register access issues.  This seems to happen.
     * But then perhaps we should not even bother to read the device ID at all?
     */

    else
    {
        lcddbg("No LCD ID, assuming SSD1289\n");
        id = SSD1289_DEVCODE_VALUE;
    }

    /* Check if the ID is for the SSD1289 */

    if (id == SSD1289_DEVCODE_VALUE)
#endif
    {
        /* LCD controller configuration.  Many details of the controller initialization
         * must, unfortunately, vary from LCD to LCD.  I have looked at the spec and at
         * three different drivers for LCDs that have SSD1289 controllers.  I have tried
         * to summarize these differences as profiles (defined above).  Some other
         * alternatives are noted below.
         *
         * Most of the differences between LCDs are nothing more than a few minor bit
         * settings.  The most significant difference betwen LCD drivers in is the
         * manner in which the LCD is powered up and in how the power controls are set.
         * My suggestion is that if you have working LCD initialization code, you should
         * simply replace the following guesses with your working code.
         */

        /* Most drivers just enable the oscillator */

#ifdef SSD1289_USE_SIMPLE_INIT
        ssd1289_putreg(lcd, SSD1289_OSCSTART, SSD1289_OSCSTART_OSCEN);
#else
        /* But one goes through a more complex start-up sequence.  Something like the
         * following:
         *
         * First, put the display in INTERNAL operation:
         * D=INTERNAL(1) CM=0 DTE=0 GON=1 SPT=0 VLE=0 PT=0
         */

        ssd1289_putreg(lcd, SSD1289_DSPCTRL,
                       (SSD1289_DSPCTRL_INTERNAL | SSD1289_DSPCTRL_GON |
                        SSD1289_DSPCTRL_VLE(0)));

        /* Then enable the oscillator */

        ssd1289_putreg(lcd, SSD1289_OSCSTART, SSD1289_OSCSTART_OSCEN);

        /* Turn the display on:
         * D=ON(3) CM=0 DTE=0 GON=1 SPT=0 VLE=0 PT=0
         */

        ssd1289_putreg(lcd, SSD1289_DSPCTRL,
                       (SSD1289_DSPCTRL_ON | SSD1289_DSPCTRL_GON |
                        SSD1289_DSPCTRL_VLE(0)));

        /* Take the LCD out of sleep mode */

        ssd1289_putreg(lcd, SSD1289_SLEEP, 0);
        up_mdelay(30);

        /* Turn the display on:
         * D=INTERNAL(1) CM=0 DTE=1 GON=1 SPT=0 VLE=0 PT=0
         */

        ssd1289_putreg(lcd, SSD1289_DSPCTRL,
                       (SSD1289_DSPCTRL_ON | SSD1289_DSPCTRL_DTE |
                        SSD1289_DSPCTRL_GON | SSD1289_DSPCTRL_VLE(0)));
#endif

        /* Set up power control registers.  There is a lot of variability
         * from LCD-to-LCD in how the power registers are configured.
         */

        ssd1289_putreg(lcd, SSD1289_PWRCTRL1, PWRCTRL1_SETTING);
        ssd1289_putreg(lcd, SSD1289_PWRCTRL2, PWRCTRL2_SETTING);

        /* One driver adds a delay here.. I doubt that this is really necessary. */
        /* up_mdelay(15); */

        ssd1289_putreg(lcd, SSD1289_PWRCTRL3, PWRCTRL3_SETTING);
        ssd1289_putreg(lcd, SSD1289_PWRCTRL4, PWRCTRL4_SETTING);
        ssd1289_putreg(lcd, SSD1289_PWRCTRL5, PWRCTRL5_SETTING);

        /* One driver does an odd setting of the the driver output control.
         * No idea why.
         */
#if 0
        ssd1289_putreg(lcd, SSD1289_OUTCTRL,
                       (SSD1289_OUTCTRL_MUX(12) | SSD1289_OUTCTRL_TB |
                        SSD1289_OUTCTRL_BGR | SSD1289_OUTCTRL_CAD));

        /* The same driver does another small delay here */

        up_mdelay(15);
#endif

        /* After this point, the drivers differ only in some varying register
         * bit settings.
         */

        /* Set the driver output control.
         * PORTRAIT MODES:
         *    MUX=319, TB=1, SM=0, BGR=1, CAD=0, REV=1, RL=0
         * LANDSCAPE MODES:
         *    MUX=319, TB=0, SM=0, BGR=1, CAD=0, REV=1, RL=0
         */

#if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT)
        ssd1289_putreg(lcd, SSD1289_OUTCTRL,
                       (SSD1289_OUTCTRL_MUX(319) | SSD1289_OUTCTRL_TB |
                        SSD1289_OUTCTRL_BGR      | SSD1289_OUTCTRL_REV);
#else
        ssd1289_putreg(lcd, SSD1289_OUTCTRL,
                       (SSD1289_OUTCTRL_MUX(319) | SSD1289_OUTCTRL_BGR |
                        SSD1289_OUTCTRL_REV));
#endif

                       /* Set the LCD driving AC waveform
                        * NW=0, WSMD=0, EOR=1, BC=1, ENWD=0, FLD=0
                        */

                       ssd1289_putreg(lcd, SSD1289_ACCTRL,
                                      (SSD1289_ACCTRL_EOR | SSD1289_ACCTRL_BC));

                       /* Take the LCD out of sleep mode (isn't this redundant in the non-
                        * simple case?)
                        */

                       ssd1289_putreg(lcd, SSD1289_SLEEP, 0);

                       /* Set entry mode */

#if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT)
                       /* LG=0, AM=0, ID=3, TY=2, DMODE=0, WMODE=0, OEDEF=0, TRANS=0, DRM=3
                        * Alternative TY=2 (But TY only applies in 262K color mode anyway)
                        */

                       ssd1289_putreg(lcd, SSD1289_ENTRY,
                                      (SSD1289_ENTRY_ID_HINCVINC | SSD1289_ENTRY_TY_C |
                                       SSD1289_ENTRY_DMODE_RAM | SSD1289_ENTRY_DFM_65K));
#else
                       /* LG=0, AM=1, ID=3, TY=2, DMODE=0, WMODE=0, OEDEF=0, TRANS=0, DRM=3 */
                       /* Alternative TY=2 (But TY only applies in 262K color mode anyway) */

                       ssd1289_putreg(lcd, SSD1289_ENTRY,
                                      (SSD1289_ENTRY_AM | SSD1289_ENTRY_ID_HINCVINC |
                                       SSD1289_ENTRY_TY_C | SSD1289_ENTRY_DMODE_RAM |
                                       SSD1289_ENTRY_DFM_65K));
#endif

                       /* Clear compare registers */

                       ssd1289_putreg(lcd, SSD1289_CMP1, 0);
                       ssd1289_putreg(lcd, SSD1289_CMP2, 0);

                       /* One driver puts a huge, 100 millisecond delay here */
                       /* up_mdelay(100); */

                       /* Set Horizontal and vertical porch.
                        * Horizontal porch:  239 pixels per line, delay=28
                        * Vertical porch:    VBP=3, XFP=0
                        */

                       ssd1289_putreg(lcd, SSD1289_HPORCH,
                                      (28 << SSD1289_HPORCH_HBP_SHIFT) | (239 << SSD1289_HPORCH_XL_SHIFT));
                       ssd1289_putreg(lcd, SSD1289_VPORCH,
                                      (3 << SSD1289_VPORCH_VBP_SHIFT)  | (0 << SSD1289_VPORCH_XFP_SHIFT));

                       /* Set display control.
                        * D=ON(3), CM=0 (not 8-color), DTE=1, GON=1, SPT=0, VLE=1 PT=0
                        */

                       ssd1289_putreg(lcd, SSD1289_DSPCTRL,
                                      (SSD1289_DSPCTRL_ON  | SSD1289_DSPCTRL_DTE |
                                       SSD1289_DSPCTRL_GON | SSD1289_DSPCTRL_VLE(1)));

                       /* Frame cycle control.  Alternative: SSD1289_FCYCCTRL_DIV8 */

                       ssd1289_putreg(lcd, SSD1289_FCYCCTRL, 0);

                       /* Gate scan start position = 0 */

                       ssd1289_putreg(lcd, SSD1289_GSTART, 0);

                       /* Clear vertical scrolling */

                       ssd1289_putreg(lcd, SSD1289_VSCROLL1, 0);
                       ssd1289_putreg(lcd, SSD1289_VSCROLL2, 0);

                       /* Setup window 1 (0-319) */

                       ssd1289_putreg(lcd, SSD1289_W1START, 0);
                       ssd1289_putreg(lcd, SSD1289_W1END, 319);

                       /* Disable window 2 (0-0) */

                       ssd1289_putreg(lcd, SSD1289_W2START, 0);
                       ssd1289_putreg(lcd, SSD1289_W2END, 0);

                       /* Horizontal start and end (0-239) */

                       ssd1289_putreg(lcd, SSD1289_HADDR,
                                      (0 << SSD1289_HADDR_HSA_SHIFT) | (239 << SSD1289_HADDR_HEA_SHIFT));

                       /* Vertical start and end (0-319) */

                       ssd1289_putreg(lcd, SSD1289_VSTART, 0);
                       ssd1289_putreg(lcd, SSD1289_VEND, 319);

                       /* Gamma controls */

                       ssd1289_putreg(lcd, SSD1289_GAMMA1, 0x0707);
                       ssd1289_putreg(lcd, SSD1289_GAMMA2, 0x0204); /* Alternative: 0x0704 */
                       ssd1289_putreg(lcd, SSD1289_GAMMA3, 0x0204);
                       ssd1289_putreg(lcd, SSD1289_GAMMA4, 0x0502);
                       ssd1289_putreg(lcd, SSD1289_GAMMA5, 0x0507);
                       ssd1289_putreg(lcd, SSD1289_GAMMA6, 0x0204);
                       ssd1289_putreg(lcd, SSD1289_GAMMA7, 0x0204);
                       ssd1289_putreg(lcd, SSD1289_GAMMA8, 0x0502);
                       ssd1289_putreg(lcd, SSD1289_GAMMA9, 0x0302);
                       ssd1289_putreg(lcd, SSD1289_GAMMA10, 0x0302); /* Alternative: 0x1f00 */

                       /* Clear write mask */

                       ssd1289_putreg(lcd, SSD1289_WRMASK1, 0);
                       ssd1289_putreg(lcd, SSD1289_WRMASK2, 0);

                       /* Set frame frequency = 65Hz (This should not be necessary since this
                        * is the default POR value)
                        */

                       ssd1289_putreg(lcd, SSD1289_FFREQ, SSD1289_FFREQ_OSC_FF65);

                       /* Set the cursor at the home position and set the index register to
                        * the gram data register (I can't imagine these are necessary).
                        */

                       ssd1289_setcursor(lcd, 0, 0);
                       ssd1289_gramselect(lcd);

                       /* One driver has a 50 msec delay here */
                       /* up_mdelay(50); */

                       ret = OK;
    }
コード例 #2
0
static int ssd1289_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
                          size_t npixels)
{
#ifndef CONFIG_LCD_NOGETRUN
    FAR struct ssd1289_dev_s *priv = &g_lcddev;
    FAR struct ssd1289_lcd_s *lcd = priv->lcd;
    FAR uint16_t *dest = (FAR uint16_t*)buffer;
    uint16_t accum;
    int i;

    /* Buffer must be provided and aligned to a 16-bit address boundary */

    ssd1289_showrun(priv, row, col, npixels, false);
    DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);

    /* Select the LCD */

    lcd->select(lcd);

    /* Read the run from GRAM. */

#ifdef CONFIG_LCD_LANDSCAPE
    /* Convert coordinates -- Here the edge away from the row of buttons on
     * the STM3240G-EVAL is used as the top.
     */

    for (i = 0; i < npixels; i++)
    {
        /* Read the next pixel from this position */

        ssd1289_setcursor(lcd, row, col);
        ssd1289_gramselect(lcd);
        ssd1289_readsetup(lcd, &accum);
        *dest++ = ssd1289_gramread(lcd, &accum);

        /* Increment to the next column */

        col++;
    }
#elif defined(CONFIG_LCD_RLANDSCAPE)
    /* Convert coordinates -- Here the edge next to the row of buttons on
     * the STM3240G-EVAL is used as the top.
     */

    col = (SSD1289_XRES-1) - col;
    row = (SSD1289_YRES-1) - row;

    /* Set the cursor position */

    ssd1289_setcursor(lcd, col, row);

    /* Then read the GRAM data, auto-decrementing Y */

    ssd1289_gramselect(lcd);

    /* Prime the pump for unaligned read data */

    ssd1289_readsetup(lcd, &accum);

    for (i = 0; i < npixels; i++)
    {
        /* Read the next pixel from this position (autoincrements to the next row) */

        *dest++ = ssd1289_gramread(lcd, &accum);
    }
#elif defined(CONFIG_LCD_PORTRAIT)
    /* Convert coordinates.  In this configuration, the top of the display is to the left
     * of the buttons (if the board is held so that the buttons are at the botton of the
     * board).
     */

    col = (SSD1289_XRES-1) - col;

    /* Then read the GRAM data, manually incrementing Y (which is col) */

    for (i = 0; i < npixels; i++)
    {
        /* Read the next pixel from this position */

        ssd1289_setcursor(lcd, row, col);
        ssd1289_gramselect(lcd);
        ssd1289_readsetup(lcd, &accum);
        *dest++ = ssd1289_gramread(lcd, &accum);

        /* Increment to the next column */

        col--;
    }
#else /* CONFIG_LCD_RPORTRAIT */
    /* Convert coordinates.  In this configuration, the top of the display is to the right
     * of the buttons (if the board is held so that the buttons are at the botton of the
     * board).
     */

    row = (SSD1289_YRES-1) - row;

    /* Then write the GRAM data, manually incrementing Y (which is col) */

    for (i = 0; i < npixels; i++)
    {
        /* Write the next pixel to this position */

        ssd1289_setcursor(lcd, row, col);
        ssd1289_gramselect(lcd);
        ssd1289_readsetup(lcd, &accum);
        *dest++ = ssd1289_gramread(lcd, &accum);

        /* Decrement to the next column */

        col++;
    }
#endif

    /* De-select the LCD */

    lcd->deselect(lcd);
    return OK;
#else
    return -ENOSYS;
#endif
}
コード例 #3
0
ファイル: ssd1289.c プロジェクト: aqakulov/Firmware
static int ssd1289_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer,
                          size_t npixels)
{
  FAR struct ssd1289_dev_s *priv = &g_lcddev;
  FAR struct ssd1289_lcd_s *lcd = priv->lcd;
  FAR const uint16_t *src = (FAR const uint16_t*)buffer;
  int i;
 
  /* Buffer must be provided and aligned to a 16-bit address boundary */

  lcdvdbg("row: %d col: %d npixels: %d\n", row, col, npixels);
  DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);

  /* Select the LCD */

  lcd->select(lcd);

  /* Write the run to GRAM. */

#ifdef CONFIG_LCD_LANDSCAPE
  /* Convert coordinates -- Here the edge away from the row of buttons on
   * the STM3240G-EVAL is used as the top.
   */

  /* Write the GRAM data, manually incrementing X */

  for (i = 0; i < npixels; i++)
    {
      /* Write the next pixel to this position */

      ssd1289_setcursor(lcd, col, row);
      ssd1289_gramselect(lcd);
      ssd1289_gramwrite(lcd, *src);

      /* Increment to next column */

      src++;
      col++;
    }
#elif defined(CONFIG_LCD_RLANDSCAPE)
  /* Convert coordinates -- Here the edge next to the row of buttons on
   * the STM3240G-EVAL is used as the top.
   */

  col = (SSD1289_XRES-1) - col;
  row = (SSD1289_YRES-1) - row;

  /* Set the cursor position */

  ssd1289_setcursor(lcd, col, row);

  /* Then write the GRAM data, auto-decrementing X */

  ssd1289_gramselect(lcd);
  for (i = 0; i < npixels; i++)
    {
      /* Write the next pixel to this position (auto-decrements to the next column) */

      ssd1289_gramwrite(lcd, *src);
      src++;
    }
#elif defined(CONFIG_LCD_PORTRAIT)
  /* Convert coordinates.  In this configuration, the top of the display is to the left
   * of the buttons (if the board is held so that the buttons are at the botton of the
   * board).
   */

  col = (SSD1289_XRES-1) - col;

  /* Then write the GRAM data, manually incrementing Y (which is col) */

  for (i = 0; i < npixels; i++)
    {
      /* Write the next pixel to this position */

      ssd1289_setcursor(lcd, row, col);
      ssd1289_gramselect(lcd);
      ssd1289_gramwrite(lcd, *src);

      /* Increment to next column */

      src++;
      col--;
    }
#else /* CONFIG_LCD_RPORTRAIT */
  /* Convert coordinates.  In this configuration, the top of the display is to the right
   * of the buttons (if the board is held so that the buttons are at the botton of the
   * board).
   */

  row = (SSD1289_YRES-1) - row;
  
  /* Then write the GRAM data, manually incrementing Y (which is col) */

  for (i = 0; i < npixels; i++)
    {
      /* Write the next pixel to this position */

      ssd1289_setcursor(lcd, row, col);
      ssd1289_gramselect(lcd);
      ssd1289_gramwrite(lcd, *src);

      /* Decrement to next column */

      src++;
      col++;
    }
#endif

  /* De-select the LCD */

  lcd->deselect(lcd);
  return OK;
}