LCD for 9XR board

Hardware Support for the 9XR
Post Reply
Romushock
Posts: 47
Joined: Thu Nov 08, 2012 8:35 am
Country: -
Location: North Italy

LCD for 9XR board

Post by Romushock »

Hi,guys,
Would like to know if anyone else can help solve my problem. I already asked for help on rcgroups.com and rcdesign.ru, but no one gave a clear answer . The fact is that I'm trying to hook up the display to 9XR motherboard. Turnkey solutions already exist
http://www.rcgroups.com/forums/showpost ... tcount=907,
but this display
http://www.ebay.com/itm/12864-128X64-Gr ... OC:DE:3160
is much smaller than the original . I found this one.
Image
Image
Image
But when it is connected to the board a strange thing happens - the image is divided horizontally into two parts and they change places - the bottom half is on top and the top - on the bottom.
ImageImageImageImageImageImage
I have 3 LCDs and 3 motherboards with different firmware (9XR, er9x and openTx), I've tried to connect them randomly , but the result is the same. Unfortunately , I'm not a programmer ( nobody is perfect ...). In the datasheet of the display http://www.egochina.net.cn/e-shop/ebay/ ... JHD756.pdf there is an initialization instruction, but I don't know where insert it into lcd.cpp file.
Here in the forum there are so many smart people - I hope they help... :cry:

User avatar
MikeB
9x Developer
Posts: 17990
Joined: Tue Dec 27, 2011 1:24 pm
Country: -
Location: Poole, Dorset, UK

Re: LCD for 9XR board

Post by MikeB »

If you can build er9x, try the following change:

Code: Select all

const static prog_uchar APM Lcdinit[] =
{
	0xe2, 0xae, 0xa1, 0xA6, 0xA4, 0xA2, 0xC0, 0x2F, 0x25, 0x81, 0x22, 0x40, 0xAF
} ;	


void lcd_init()
{
  // /home/thus/txt/datasheets/lcd/KS0713.pdf
  // ~/txt/flieger/ST7565RV17.pdf  from http://www.glyn.de/content.asp?wdid=132&sid=
	uint8_t i ;

	LcdLock = 1 ;						// Lock LCD data lines
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES);  //LCD_RES
  delay_2us();
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //  f524  sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21           1
  delay_1_5us(1500);
	for ( i = 0 ; i < 13 ; i += 1 )
0x40 added to init codes, 12 changed to 13 in the for instruction.

Mike.
erskyTx/er9x developer
The difficult we do immediately,
The impossible takes a little longer!
Romushock
Posts: 47
Joined: Thu Nov 08, 2012 8:35 am
Country: -
Location: North Italy

Re: LCD for 9XR board

Post by Romushock »

Hi Mike,
Sorry for the delay in replying . I haven't good news yet. I 've never really built the program, has always enjoyed the finished product . Well, everything in this life is ever done for the first time ...
So I tried to insert a block of your code in existing lcd.cpp file using avrstudio, like this

Code: Select all

/*
 * Author - Erez Raviv <[email protected]>
 *
 * Based on th9x -> http://code.google.com/p/th9x/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include "er9x.h"
#include <stdlib.h>

//#define LCD_2_CS		1

#define DBL_FONT_SMALL	1

#ifdef SIMU
bool lcd_refresh = true;
uint8_t lcd_buf[DISPLAY_W*DISPLAY_H/8];
#endif

uint8_t lcd_lastPos;

uint8_t displayBuf[DISPLAY_W*DISPLAY_H/8];
#define DISPLAY_END (displayBuf+sizeof(displayBuf))


const prog_uchar APM font[] = {
#include "font.lbm"
};

#define font_5x8_x20_x7f (font)

const prog_uchar APM font_dblsize[] = {
#include "font_dblsize.lbm"
};

#define font_10x16_x20_x7f (font_dblsize)


void lcd_clear()
{
  //for(unsigned i=0; i<sizeof(displayBuf); i++) displayBuf[i]=0;
  memset(displayBuf, 0, sizeof(displayBuf));
}


void lcd_img(uint8_t i_x,uint8_t i_y,const prog_uchar * imgdat,uint8_t idx/*,uint8_t mode*/)
{
  const prog_uchar  *q = imgdat;
  uint8_t w    = pgm_read_byte(q++);
  uint8_t hb   = (pgm_read_byte(q++)+7)/8;
  uint8_t sze1 = pgm_read_byte(q++);
  q += idx*sze1;
//  bool    inv  = (mode & INVERS) ? true : (mode & BLINK ? BLINK_ON_PHASE : false);
  for(uint8_t yb = 0; yb < hb; yb++){
    uint8_t   *p = &displayBuf[ (i_y / 8 + yb) * DISPLAY_W + i_x ];
    for(uint8_t x=0; x < w; x++){
      uint8_t b = pgm_read_byte(q++);
      *p++ = b;
      //*p++ = inv ? ~b : b;
    }
  }
}

uint8_t lcd_putc(uint8_t x,uint8_t y,const char c)
{
  return lcd_putcAtt(x,y,c,0);
}

/// invers: 0 no 1=yes 2=blink
uint8_t lcd_putcAtt(uint8_t x,uint8_t y,const char c,uint8_t mode)
{
    uint8_t *p    = &displayBuf[ y / 8 * DISPLAY_W + x ];
    //uint8_t *pmax = &displayBuf[ DISPLAY_H/8 * DISPLAY_W ];
		if ( c < 22 )		// Move to specific x position (c)*FW
		{
			x = c * FW ;
//  		if(mode&DBLSIZE)
//			{
//				x += x ;
//			}
			return x ;
		}
		x += FW ;
    const prog_uchar    *q = &font_5x8_x20_x7f[(c-0x20)*5];
    bool         inv = (mode & INVERS) ? true : (mode & BLINK ? BLINK_ON_PHASE : false);
    if(mode&DBLSIZE)
    {
			if ( (c!=0x2E)) x+=FW; //check for decimal point
	/* each letter consists of ten top bytes followed by
	 * five bottom by ten bottom bytes (20 bytes per 
	 * char) */

		  unsigned char c_mapped ;

#ifdef DBL_FONT_SMALL
			if ( c >= ',' && c <= ':' )
			{
				c_mapped = c - ',' + 1 ;		
			}
  		else if (c>='A' && c<='Z')
			{
				c_mapped = c - 'A' + 0x10 ;
			}
  		else if (c>='a' && c<='z')
			{
				c_mapped = c - 'a' + 0x2B ;
			}
  		else if (c=='_' )
			{
				c_mapped = 0x2A ;
			}
			else
			{
				c_mapped = 0 ;
			}
#else
			c_mapped = c - 0x20 ;
#endif
        q = &font_10x16_x20_x7f[(c_mapped)*20] ;// + ((c-0x20)/16)*160];
        for(char i=11; i>=0; i--){
	    /*top byte*/
            uint8_t b1 = i>1 ? pgm_read_byte(q) : 0;
	    /*bottom byte*/
            uint8_t b3 = i>1 ? pgm_read_byte(10+q) : 0;
	    /*top byte*/
//            uint8_t b2 = i>0 ? pgm_read_byte(++q) : 0;
	    /*bottom byte*/
//            uint8_t b4 = i>0 ? pgm_read_byte(10+q) : 0;
            q++;
            if(inv) {
                b1=~b1;
//                b2=~b2;
                b3=~b3;
//                b4=~b4;
            }

            if(&p[DISPLAY_W+1] < DISPLAY_END){
                p[0]=b1;
//                p[1]=b2;
                p[DISPLAY_W] = b3;
//                p[DISPLAY_W+1] = b4;
                p+=1;
            }
        }
//        q = &dbl_font[(c-0x20)*20];
//        for(char i=0; i<10; i++){
//            uint8_t b = pgm_read_byte(q++);
//            if((p+DISPLAY_W)<DISPLAY_END) *(p+DISPLAY_W) = inv ? ~b : b;
//            b = pgm_read_byte(q++);
//            if(p<DISPLAY_END) *p = inv ? ~b : b;
//            p++;
//        }
//        if(p<DISPLAY_END) *p = inv ? ~0 : 0;
//        if((p+DISPLAY_W)<DISPLAY_END) *(p+DISPLAY_W) = inv ? ~0 : 0;
    }
    else
    {
        uint8_t condense=0;

        if (mode & CONDENSED) {
            *p = inv ? ~0 : 0;
						p += 1 ;
            condense=1;
	    	x += FWNUM-FW ;
	}

        for(char i=5; i!=0; i--){
            uint8_t b = pgm_read_byte(q++);
    	    if (condense && i==4) {
                /*condense the letter by skipping column 4 */
                continue;
            }
            if(p<DISPLAY_END) {*p = inv ? ~b : b; p += 1 ; }
        }
        if(p<DISPLAY_END) *p++ = inv ? ~0 : 0;
    }
		return x ;
}

// Puts sub-string from string options
// First byte of string is sub-string length
// idx is index into string (in length units)
// Output length characters
void lcd_putsAttIdx(uint8_t x,uint8_t y,const prog_char * s,uint8_t idx,uint8_t att)
{
	uint8_t length ;
	length = pgm_read_byte(s++) ;

  lcd_putsnAtt(x,y,s+length*idx,length,att) ;
}


//uint8_t lcd_putsnAtt(uint8_t x,uint8_t y,const prog_char * s,uint8_t len,uint8_t mode)
void lcd_putsnAtt(uint8_t x,uint8_t y,const prog_char * s,uint8_t len,uint8_t mode)
{
	uint8_t source ;
//	uint8_t size ;
	source = mode & BSS ;
//	size = mode & DBLSIZE ;
  while(len!=0) {
    char c = (source) ? *s++ : pgm_read_byte(s++);
    x = lcd_putcAtt(x,y,c,mode);
//    x+=FW;
//		if ((size)&& (c!=0x2E)) x+=FW; //check for decimal point
    len--;
  }
}
void lcd_putsn_P(uint8_t x,uint8_t y,const prog_char * s,uint8_t len)
{
  lcd_putsnAtt( x,y,s,len,0);
}

//uint8_t lcd_puts2Att(uint8_t x,uint8_t y,const prog_char * s,const prog_char * t ,uint8_t mode)
//{
//	x = lcd_putsAtt( x, y, s, mode ) ;
//	return lcd_putsAtt( x, y, t, mode ) ;	
//}

uint8_t lcd_putsAtt(uint8_t x,uint8_t y,const prog_char * s,uint8_t mode)
{
	uint8_t source ;
//	uint8_t size ;
	source = mode & BSS ;
//	size = mode & DBLSIZE ;
  //while(char c=pgm_read_byte(s++)) {
  while(1) {
    char c = (source) ? *s++ : pgm_read_byte(s++);
    if(!c) break;
    x = lcd_putcAtt(x,y,c,mode);
//    x+=FW;
//		if ((size)&& (c!=0x2E)) x+=FW; //check for decimal point
  }
  return x;
}

void lcd_puts_Pleft(uint8_t y,const prog_char * s)
{
  lcd_putsAtt( 0, y, s, 0);
}

void lcd_puts_P(uint8_t x,uint8_t y,const prog_char * s)
{
  lcd_putsAtt( x, y, s, 0);
}
void lcd_outhex4(uint8_t x,uint8_t y,uint16_t val)
{
  x+=FWNUM*4;
  for(int i=0; i<4; i++)
  {
    x-=FWNUM;
    char c = val & 0xf;
    c = c>9 ? c+'A'-10 : c+'0';
    lcd_putcAtt(x,y,c,c>='A'?CONDENSED:0);
    val>>=4;
  }
}
void lcd_outdez(uint8_t x,uint8_t y,int16_t val)
{
  lcd_outdezAtt(x,y,val,0);
}

void lcd_outdezAtt(uint8_t x,uint8_t y,int16_t val,uint8_t mode)
{
  lcd_outdezNAtt( x,y,val,mode,5);
}

#define PREC(n) ((n&0x20) ? ((n&0x10) ? 2 : 1) : 0)
uint8_t lcd_outdezNAtt(uint8_t x,uint8_t y,int32_t val,uint8_t mode,int8_t len)
{
  uint8_t fw = FWNUM;
  uint8_t prec = PREC(mode);
	uint8_t negative = 0 ;
  uint8_t xn = 0;
  uint8_t ln = 2;
  char c;
  uint8_t xinc ;
	uint8_t fullwidth = 0 ;

	mode &= ~NO_UNIT ;
	if ( len < 0 )
	{
		fullwidth = 1 ;
		len = -len ;		
	}

  if ( val < 0 )
	{
		val = -val ;
		negative = 1 ;
	}

  if (mode & DBLSIZE)
  {
    fw += FWNUM ;
    xinc = 2*FWNUM;
    lcd_lastPos = 2*FW;
  }
  else
  {
    xinc = FWNUM ;
    lcd_lastPos = FW;
  }

  if (mode & LEFT) {
//    if (val >= 10000)
//      x += fw;
    if(negative)
    {
      x += fw;
    }
    if (val >= 1000)
      x += fw;
    if (val >= 100)
      x += fw;
    if (val >= 10)
      x += fw;
    if ( prec )
    {
      if ( prec == 2 )
      {
        if ( val < 100 )
        {
          x += fw;
        }
      }
      if ( val < 10 )
      {
        x+= fw;
      }
    }
  }
  else
  {
    x -= xinc;
  }
  lcd_lastPos += x ;

  if ( prec == 2 )
  {
    mode -= LEADING0;  // Can't have PREC2 and LEADING0
  }

  for (uint8_t i=1; i<=len; i++)
	{
		div_t qr ;
		qr = div( val, 10 ) ;
    c = (qr.rem) + '0';
    lcd_putcAtt(x, y, c, mode);
    if (prec==i) {
      if (mode & DBLSIZE) {
        xn = x;
        if( c<='3' && c>='1') ln++;
        uint8_t tn = (qr.quot) % 10;
        if(tn==2 || tn==4) {
          if (c=='4') {
            xn++;
          }
          else {
            xn--; ln++;
          }
        }
      }
      else {
        x -= 2;
        if (mode & INVERS)
          lcd_vline(x+1, y, 7);
        else
          lcd_plot(x+1, y+6);
      }
      if (qr.quot)
        prec = 0;
    }
    val = qr.quot ;
    if (!val)
    {
      if (prec)
      {
        if ( prec == 2 )
        {
          if ( i > 1 )
          {
            prec = 0 ;
          }
        }
        else
        {
          prec = 0 ;
        }
      }
      else if (mode & LEADING0)
			{
				if ( fullwidth == 0 )
				{
        	mode -= LEADING0;
				}
			}
      else
        break;
    }
    x-=fw;
  }
  if (xn) {
    lcd_hline(xn, y+2*FH-4, ln);
    lcd_hline(xn, y+2*FH-3, ln);
  }
  if(negative) lcd_putcAtt(x-fw,y,'-',mode);
	return 0 ;		// Stops compiler creating two sets of POPS, saves flash
}

void lcd_hbar( uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t percent )
{
	uint8_t solid ;
	if ( percent > 100 )
	{
		percent = 100 ;
	}
	solid = (w-2) * percent / 100 ;
	lcd_rect( x, y, w, h ) ;

	if ( solid )
	{
		w = y + h - 1 ;
		y += 1 ;
		x += 1 ;
		while ( y < w )
		{
 			lcd_hline(x, y, solid ) ;
			y += 1 ;			
		}
	}
}

// Reverse video 8 pixels high, w pixels wide
// Vertically on an 8 pixel high boundary
void lcd_char_inverse( uint8_t x, uint8_t y, uint8_t w, uint8_t blink )
{
	if ( blink && BLINK_ON_PHASE )
	{
		return ;
	}
	uint8_t end = x + w ;
  uint8_t *p = &displayBuf[ y / 8 * DISPLAY_W + x ];

	while ( x < end )
	{
		*p++ ^= 0xFF ;
		x += 1 ;
	}
}

void lcd_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h )
{
  lcd_vline(x, y, h ) ;
	if ( w > 1 )
	{
  	lcd_vline(x+w-1, y, h ) ;
	}
 	lcd_hline(x+1, y+h-1, w-2 ) ;
 	lcd_hline(x+1, y, w-2 ) ;
}

void lcd_plot(uint8_t x,uint8_t y)
{
  //  if(y>=64)  return;
  //  if(x>=128) return;
  //  displayBuf[ y / 8 * DISPLAY_W + x ] ^= BITMASK(y%8);
  uint8_t *p   = &displayBuf[ y / 8 * DISPLAY_W + x ];
  if(p<DISPLAY_END) *p ^= BITMASK(y%8);
}
void lcd_hlineStip(unsigned char x,unsigned char y, signed char w,uint8_t pat)
{
  if(w<0) {x+=w; w=-w;}
  uint8_t *p  = &displayBuf[ y / 8 * DISPLAY_W + x ];
  uint8_t msk = BITMASK(y%8);
  while(w){
    if ( p>=DISPLAY_END)
    {
      break ;			
    }
    if(pat&1) {
      //lcd_plot(x,y);
      *p ^= msk;
      pat = (pat >> 1) | 0x80;
    }else{
      pat = pat >> 1;
    }
    w--;
    p++;
  }
}

void lcd_hline(uint8_t x,uint8_t y, int8_t w)
{
  lcd_hlineStip(x,y,w,0xff);
}

void lcd_vline(uint8_t x,uint8_t y, int8_t h)
{
//    while ((y+h)>=DISPLAY_H) h--;
		uint8_t y1 ;
    uint8_t *p  = &displayBuf[ y / 8 * DISPLAY_W + x ];
		y1 = y + h ;
    uint8_t *q  = &displayBuf[ y1 / 8 * DISPLAY_W + x ];
    *p ^= ~(BITMASK(y%8)-1);
    while(p<q){
        p  += DISPLAY_W;
        if ( p>=DISPLAY_END)
        {
          break ;			
        }
        *p ^= 0xff;
    }
    if(p<DISPLAY_END) *p ^= ~(BITMASK((y+h)%8)-1);
}



#if LCD_OTHER

// Supports 4W serial LCD interface and SSD1306 OLED controller
// - Hyun-Taek Chang ([email protected]), Feb 2013

// to select either stock LCD controller or SSD1306 OLED controller
 #define SSD1306         0       // Stock(ST7565/NT7532)=0, SSD1306=1

// controller independent options
 #define SERIAL_LCD      0       // parallel=0, 4W_serial=1
 #define ROTATE_SCREEN   0       // don't-rotate-screen=0, rotate-180-degree=1
 #define REVERSE_VIDEO   0       // don't-reverse-video=0, reverse-video=1

 #if (SSD1306 || ROTATE_SCREEN)
  #define COLUMN_START_LO 0x00
 #else  // ST7565
  #define COLUMN_START_LO 0x04        // skip first 4 columns
 #endif

 #if (SSD1306 || ROTATE_SCREEN)
 #define COLUMN_START_LO 0x00
 #else  // ST7565
 #define COLUMN_START_LO 0x04        // skip first 4 columns
 #endif

// force inline expansion
#define ALWAYS_INLINE   __attribute__((always_inline))

static void lcdSendByte(uint8_t val, uint8_t v0, uint8_t v1) ALWAYS_INLINE;
static void lcdEndSend() ALWAYS_INLINE;

static void lcdEndSend()
{
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1); // disable chip select
}

#if SERIAL_LCD
// Serial LCD module's SCLK(clock) and SI(data) must be connected
// to Atmega's PC4 and PC5, respectively.
#define OUT_C_LCD_SCL OUT_C_LCD_RnW     // PC4
#define OUT_C_LCD_SI  OUT_C_LCD_E       // PC5

static void lcdSendBit(uint8_t b, uint8_t v0, uint8_t v1) ALWAYS_INLINE;

// NOTE: ST7565 SCLK min period is 50ns (100ns?)
// single bit write takes 5 cycles = 312.5ns @16MHz clock
static void lcdSendBit(uint8_t b, uint8_t v0, uint8_t v1)
{
  PORTC_LCD_CTRL = v0;                  // out 0x15, r19  ; 1 cycle
  if (b != 0)                           // sbrc r24, 7    ; 1 cycle
    PORTC_LCD_CTRL = v1;                // out 0x15, r18  ; 1 cycle
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_SCL); // sbi 0x15, 4    ; 2 cycles
}

static void lcdSendByte(uint8_t val, uint8_t v0, uint8_t v1)
{
  lcdSendBit((val & 0x80), v0, v1);
  lcdSendBit((val & 0x40), v0, v1);
  lcdSendBit((val & 0x20), v0, v1);
  lcdSendBit((val & 0x10), v0, v1);
  lcdSendBit((val & 0x08), v0, v1);
  lcdSendBit((val & 0x04), v0, v1);
  lcdSendBit((val & 0x02), v0, v1);
  lcdSendBit((val & 0x01), v0, v1);
}

static void lcdSendCtl(uint8_t val)
{
  uint8_t v0c = 0xC5; // PC7=1,PC6=1,SI=0,SCL=0,A0=0,RES=1,CS1=0,PC0=1
  uint8_t v1c = 0xE5; // PC7=1,PC6=1,SI=1,SCL=0,A0=0,RES=1,CS1=0,PC0=1
  for (uint8_t n = 8; n > 0; n--) {
    lcdSendBit((val & 0x80), v0c, v1c);
    val <<= 1;
  }
  lcdEndSend();
}

#else    // PARALLEL_LCD

static void lcdStartSend() ALWAYS_INLINE;

static void lcdStartSend()
{
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);  // enable chip select
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);  // enable write 
}

static void lcdSendByte(uint8_t val, uint8_t = 0, uint8_t = 0)
{
  PORTA_LCD_DAT = val;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);    // rise enable
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);    // fall enable
}

static void lcdSendCtl(uint8_t val)
{
  lcdStartSend();
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);   // set to control mode
  lcdSendByte(val);
  lcdEndSend();
}
#endif

#define delay_1us() _delay_us(1)
#define delay_2us() _delay_us(2)
static void delay_1_5us(int ms)
{
  for(int i=0; i<ms; i++) delay_1us();
}

    const static prog_uchar APM Lcdinit[] =
    {
       0xe2, 0xae, 0xa1, 0xA6, 0xA4, 0xA2, 0xC0, 0x2F, 0x25, 0x81, 0x22, 0x40, 0xAF
    } ;   


    void lcd_init()
    {
      // /home/thus/txt/datasheets/lcd/KS0713.pdf
      // ~/txt/flieger/ST7565RV17.pdf  from http://www.glyn.de/content.asp?wdid=132&sid=
       uint8_t i ;

       LcdLock = 1 ;                  // Lock LCD data lines
      PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES);  //LCD_RES
      delay_2us();
      PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //  f524  sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21           1
      delay_1_5us(1500);
       for ( i = 0 ; i < 13 ; i += 1 )
     }

const static prog_uchar APM Lcdinit[] =
{
#if SSD1306
  0xAE,         // DON = 0: display OFF
  0xD5, 0x80,   // set display clock 100 frames/sec
  0xA8, 0x3F,   // set multiplex ratio 1/64 duty
  0xD3, 0x00,   // set display offset 0
# if EXTERNAL_VCC
  0x8D, 0x10,   // disable embedded DC/DC converter
  0xD9, 0x22,   // set precharge, discharge 2 clocks each
# else
  0x8D, 0x14,   // enable embedded DC/DC conveter
  0xD9, 0xF1,   // set precharge 15 clocks, discharge 1 clock
# endif
  0xDA, 0x12,   // set COM pins hardware configuration
  0xDB, 0x40,   // set VCOMH deselect level -undocumented
# if ROTATE_SCREEN
  0xA1,         // ADC = 1: reverse direction(SEG128->SEG1)
  0xC8,         // SHL = 1: reverse direction (COM64->COM1)
# else
  0xA0,         // ADC = 0: normal direction(SEG1->SEG128)
  0xC0,         // SHL = 0: normal direction (COM1->COM64)
# endif
#else  // !SSD1306 == ST7565 (stock LCD controller)
  0xE2,         // Initialize the internal functions
  0xAE,         // DON = 0: display OFF
  0xA4,         // Disable entire display-ON
  0xA2,         // Select LCD bias=0
  0x2F,         // Control power circuit operation VC=VR=VF=1
  0x25,         // Select int resistance ratio R2 R1 R0 =5
# if ROTATE_SCREEN
  0xA0,         // ADC = 0: normal direction(SEG1->SEG132/SEG128)
  0xC8,         // SHL = 1: reverse direction (COM64->COM1)
# else
  0xA1,         // ADC = 1: reverse direction(SEG132/SEG128->SEG1)
  0xC0,         // SHL = 0: normal direction (COM1->COM64)
# endif
#endif // SSD1306
#if REVERSE_VIDEO
  0xA7,         // REV = 1: reverse display
#else
  0xA6,         // REV = 0: non-reverse display
#endif // REVERSE_VIDEO
  0xAF          // DON = 1: display ON
};	


void lcd_init()
{
  // /home/thus/txt/datasheets/lcd/KS0713.pdf
  // ~/txt/flieger/ST7565RV17.pdf  from http://www.glyn.de/content.asp?wdid=132&sid=

  LcdLock = 1 ;            // Lock LCD data lines
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES);  //LCD_RES
  delay_2us();
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //  f524  sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21           1
  delay_1_5us(1500);
  for (uint8_t i = 0; i < sizeof(Lcdinit); i++) {
    lcdSendCtl(pgm_read_byte(&Lcdinit[i]));
  }
  g_eeGeneral.contrast = lcd_nomContrast;
  LcdLock = 0 ;            // Free LCD data lines

}


void lcdSetContrast()
{
  lcdSetRefVolt(g_eeGeneral.contrast);
}

void lcdSetRefVolt(uint8_t val)
{
  LcdLock = 1 ;            // Lock LCD data lines
  lcdSendCtl(0x81);
  lcdSendCtl(val);
  LcdLock = 0 ;            // Free LCD data lines
}

volatile uint8_t LcdLock ;

void refreshDiplay()
{
#ifdef SIMU
  memcpy(lcd_buf, displayBuf, sizeof(displayBuf));
  lcd_refresh = true;

#else
  LcdLock = 1 ;             // Lock LCD data lines
  uint8_t *p=displayBuf;
#if SERIAL_LCD
  const uint8_t v0c = 0xC5; // PC7=1,PC6=1,SI=0,SCL=0,A0=0,RES=1,CS1=0,PC0=1
  const uint8_t v1c = 0xE5; // PC7=1,PC6=1,SI=1,SCL=0,A0=0,RES=1,CS1=0,PC0=1
  const uint8_t v0d = 0xCD; // PC7=1,PC6=1,SI=0,SCL=0,A0=1,RES=1,CS1=0,PC0=1
  const uint8_t v1d = 0xED; // PC7=1,PC6=1,SI=1,SCL=0,A0=1,RES=1,CS1=0,PC0=1
  for(uint8_t y=0xB0; y < 0xB8; y++) {
    lcdSendByte(COLUMN_START_LO, v0c, v1c);
    lcdSendByte(0x10, v0c, v1c);  //column addr 0
    lcdSendByte(y, v0c, v1c);     //page addr y

    for(uint8_t x=32; x>0; x--){
       lcdSendByte(*p++, v0d, v1d);
       lcdSendByte(*p++, v0d, v1d);
       lcdSendByte(*p++, v0d, v1d);
       lcdSendByte(*p++, v0d, v1d);
    }
  }
#else
  lcdStartSend();
  for(uint8_t y=0xB0; y < 0xB8; y++) {
    PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0); // switch to ctl send mode

    lcdSendByte(COLUMN_START_LO);
    lcdSendByte(0x10);  //column addr 0
    lcdSendByte(y);     //page addr y

    PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);  // switch to data send mode

    for(uint8_t x=32; x>0; x--){
       lcdSendByte(*p++);
       lcdSendByte(*p++);
       lcdSendByte(*p++);
       lcdSendByte(*p++);
    }
  }
#endif
  lcdEndSend();
  LcdLock = 0 ;            // Free LCD data lines
#endif
}


#else	// !defined(LCD_OTHER)


#ifndef LCD_2_CS
void lcdSendCtl(uint8_t val)
{
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
  PORTA_LCD_DAT = val;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_A0);
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS1);
}


#define delay_1us() _delay_us(1)
#define delay_2us() _delay_us(2)
static void delay_1_5us( uint16_t ms)
{
  for( uint16_t i=0; i<ms; i++) delay_1us();
}

const static prog_uchar APM Lcdinit[] =
{
	0xe2, 0xae, 0xa1, 0xA6, 0xA4, 0xA2, 0xC0, 0x2F, 0x25, 0x81, 0x22, 0xAF
} ;	


void lcd_init()
{
  // /home/thus/txt/datasheets/lcd/KS0713.pdf
  // ~/txt/flieger/ST7565RV17.pdf  from http://www.glyn.de/content.asp?wdid=132&sid=
	uint8_t i ;

	LcdLock = 1 ;						// Lock LCD data lines
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES);  //LCD_RES
  delay_2us();
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //  f524  sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21           1
  delay_1_5us(1500);
	for ( i = 0 ; i < 12 ; i += 1 )
	{
	  lcdSendCtl(pgm_read_byte(&Lcdinit[i]) ) ;
	}
  g_eeGeneral.contrast = lcd_nomContrast ;
	LcdLock = 0 ;						// Free LCD data lines

}


void lcdSetContrast()
{
	lcdSetRefVolt(g_eeGeneral.contrast);
}

void lcdSetRefVolt(uint8_t val)
{
	LcdLock = 1 ;						// Lock LCD data lines
  lcdSendCtl(0x81);
  lcdSendCtl(val);
	LcdLock = 0 ;						// Free LCD data lines
}

volatile uint8_t LcdLock ;
//volatile uint8_t LcdTrims ;
//uint8_t LcdTrimSwapped ;


void refreshDiplay()
{
#ifdef SIMU
  memcpy(lcd_buf, displayBuf, sizeof(displayBuf));
  lcd_refresh = true;
#else

	LcdLock = 1 ;						// Lock LCD data lines
  uint8_t *p=displayBuf;
  for(uint8_t y=0; y < 8; y++) {
    lcdSendCtl(0x04);
    lcdSendCtl(0x10); //column addr 0
    lcdSendCtl( y | 0xB0); //page addr y
    
		PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
    PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_A0);
    PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
		
    for(uint8_t x=32; x>0; x--){
//      lcdSendDat(*p);
      PORTA_LCD_DAT = *p++;
      PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);
      PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
      PORTA_LCD_DAT = *p++;
      PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);
      PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
      PORTA_LCD_DAT = *p++;
      PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);
      PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
      PORTA_LCD_DAT = *p++;
      PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);
      PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
//      p++;
    }
    PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_A0);
    PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS1);
  }
	LcdLock = 0 ;						// Free LCD data lines
#endif
}
#endif

#ifdef LCD_2_CS
uint8_t toggle_e()
{
  uint8_t value ;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E) ;
  asm("rjmp .+0") ;
  asm("rjmp .+0") ;
  asm("nop") ;
  value = PINA ;
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E) ;
  return value ;
}


#define delay_1us() _delay_us(1)
void delay_1_5us(int ms)
{
  for(int i=0; i<ms; i++) delay_1us();
}

#define OUT_C_LCD_CS2   0

static void lcdSendCtl(uint8_t val)
{
  uint8_t busy ;

  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);

  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RnW) ;    // read
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
  DDRA = 0 ;
  do
  {
    busy = toggle_e() ;
  } while ( busy & 0x80 ) ;
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
  DDRA = 0xFF ;
  PORTA_LCD_DAT = val;
  toggle_e() ;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS1);

  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS2);
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RnW) ;    // read
  DDRA = 0 ;
  do
  {
    busy = toggle_e() ;
  } while ( busy & 0x80 ) ;
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
  DDRA = 0xFF ;
  PORTA_LCD_DAT = val;
  toggle_e() ;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS2);

}


uint8_t Hpos ;

static void lcdSendDat(uint8_t val)
{
  uint8_t busy ;

  if ( Hpos )
  {
    PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1) ;
  }
  else
  {
    PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS2) ;
  }
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RnW) ;    // read
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
  DDRA = 0 ;
  do
  {
    busy = toggle_e() ;
  } while ( busy & 0x80 ) ;
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
  DDRA = 0xFF ;
  PORTA_LCD_DAT = val;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_A0);
  toggle_e() ;

  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS1);
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS2);
}


void lcd_init()
{
  // /home/thus/txt/datasheets/lcd/KS0713.pdf
  // ~/txt/flieger/ST7565RV17.pdf  from http://www.glyn.de/content.asp?wdid=132&sid=

  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS1);
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS2);
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_A0);
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES);  //LCD_RES
  delay_1us();
  delay_1us();//    f520  call  0xf4ce  delay_1us() ; 0x0xf4ce
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //  f524  sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21           1

  lcdSendCtl(0xC0); //
  lcdSendCtl(0x3F); //DON = 1: display ON

  g_eeGeneral.contrast = 0x22;
}

void lcdSetContrast()
{
	lcdSetRefVolt(g_eeGeneral.contrast);
}

void lcdSetRefVolt(uint8_t val)
{
	LcdLock = 1 ;						// Lock LCD data lines
  lcdSendCtl(0x81);
  lcdSendCtl(val);
	LcdLock = 0 ;						// Free LCD data lines
}

volatile uint8_t LcdLock ;
//volatile uint8_t LcdTrims ;
//uint8_t LcdTrimSwapped ;


void refreshDiplay()
{
  uint8_t *p=displayBuf;

	LcdLock = 1 ;						// Lock LCD data lines

  for(uint8_t y=0; y < 8; y++) {
    lcdSendCtl(0xC0); //
    lcdSendCtl(0x40); //column addr 0
    lcdSendCtl( y | 0xB8); //page addr y

    for(uint8_t x=0; x<128; x++)
    {
      Hpos = x & 64 ;
      lcdSendDat(*p);
      p++;
    }
//    PORTA = 0xFF;  // Outputs high/pullups enabled
  }
	LcdLock = 0 ;						// Free LCD data lines
}
#endif

#endif  // LCD_OTHER



and replace the entire piece of initialize display, like this

Code: Select all

/*
 * Author - Erez Raviv <[email protected]>
 *
 * Based on th9x -> http://code.google.com/p/th9x/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include "er9x.h"
#include <stdlib.h>

//#define LCD_2_CS		1

#define DBL_FONT_SMALL	1

#ifdef SIMU
bool lcd_refresh = true;
uint8_t lcd_buf[DISPLAY_W*DISPLAY_H/8];
#endif

uint8_t lcd_lastPos;

uint8_t displayBuf[DISPLAY_W*DISPLAY_H/8];
#define DISPLAY_END (displayBuf+sizeof(displayBuf))


const prog_uchar APM font[] = {
#include "font.lbm"
};

#define font_5x8_x20_x7f (font)

const prog_uchar APM font_dblsize[] = {
#include "font_dblsize.lbm"
};

#define font_10x16_x20_x7f (font_dblsize)


void lcd_clear()
{
  //for(unsigned i=0; i<sizeof(displayBuf); i++) displayBuf[i]=0;
  memset(displayBuf, 0, sizeof(displayBuf));
}


void lcd_img(uint8_t i_x,uint8_t i_y,const prog_uchar * imgdat,uint8_t idx/*,uint8_t mode*/)
{
  const prog_uchar  *q = imgdat;
  uint8_t w    = pgm_read_byte(q++);
  uint8_t hb   = (pgm_read_byte(q++)+7)/8;
  uint8_t sze1 = pgm_read_byte(q++);
  q += idx*sze1;
//  bool    inv  = (mode & INVERS) ? true : (mode & BLINK ? BLINK_ON_PHASE : false);
  for(uint8_t yb = 0; yb < hb; yb++){
    uint8_t   *p = &displayBuf[ (i_y / 8 + yb) * DISPLAY_W + i_x ];
    for(uint8_t x=0; x < w; x++){
      uint8_t b = pgm_read_byte(q++);
      *p++ = b;
      //*p++ = inv ? ~b : b;
    }
  }
}

uint8_t lcd_putc(uint8_t x,uint8_t y,const char c)
{
  return lcd_putcAtt(x,y,c,0);
}

/// invers: 0 no 1=yes 2=blink
uint8_t lcd_putcAtt(uint8_t x,uint8_t y,const char c,uint8_t mode)
{
    uint8_t *p    = &displayBuf[ y / 8 * DISPLAY_W + x ];
    //uint8_t *pmax = &displayBuf[ DISPLAY_H/8 * DISPLAY_W ];
		if ( c < 22 )		// Move to specific x position (c)*FW
		{
			x = c * FW ;
//  		if(mode&DBLSIZE)
//			{
//				x += x ;
//			}
			return x ;
		}
		x += FW ;
    const prog_uchar    *q = &font_5x8_x20_x7f[(c-0x20)*5];
    bool         inv = (mode & INVERS) ? true : (mode & BLINK ? BLINK_ON_PHASE : false);
    if(mode&DBLSIZE)
    {
			if ( (c!=0x2E)) x+=FW; //check for decimal point
	/* each letter consists of ten top bytes followed by
	 * five bottom by ten bottom bytes (20 bytes per 
	 * char) */

		  unsigned char c_mapped ;

#ifdef DBL_FONT_SMALL
			if ( c >= ',' && c <= ':' )
			{
				c_mapped = c - ',' + 1 ;		
			}
  		else if (c>='A' && c<='Z')
			{
				c_mapped = c - 'A' + 0x10 ;
			}
  		else if (c>='a' && c<='z')
			{
				c_mapped = c - 'a' + 0x2B ;
			}
  		else if (c=='_' )
			{
				c_mapped = 0x2A ;
			}
			else
			{
				c_mapped = 0 ;
			}
#else
			c_mapped = c - 0x20 ;
#endif
        q = &font_10x16_x20_x7f[(c_mapped)*20] ;// + ((c-0x20)/16)*160];
        for(char i=11; i>=0; i--){
	    /*top byte*/
            uint8_t b1 = i>1 ? pgm_read_byte(q) : 0;
	    /*bottom byte*/
            uint8_t b3 = i>1 ? pgm_read_byte(10+q) : 0;
	    /*top byte*/
//            uint8_t b2 = i>0 ? pgm_read_byte(++q) : 0;
	    /*bottom byte*/
//            uint8_t b4 = i>0 ? pgm_read_byte(10+q) : 0;
            q++;
            if(inv) {
                b1=~b1;
//                b2=~b2;
                b3=~b3;
//                b4=~b4;
            }

            if(&p[DISPLAY_W+1] < DISPLAY_END){
                p[0]=b1;
//                p[1]=b2;
                p[DISPLAY_W] = b3;
//                p[DISPLAY_W+1] = b4;
                p+=1;
            }
        }
//        q = &dbl_font[(c-0x20)*20];
//        for(char i=0; i<10; i++){
//            uint8_t b = pgm_read_byte(q++);
//            if((p+DISPLAY_W)<DISPLAY_END) *(p+DISPLAY_W) = inv ? ~b : b;
//            b = pgm_read_byte(q++);
//            if(p<DISPLAY_END) *p = inv ? ~b : b;
//            p++;
//        }
//        if(p<DISPLAY_END) *p = inv ? ~0 : 0;
//        if((p+DISPLAY_W)<DISPLAY_END) *(p+DISPLAY_W) = inv ? ~0 : 0;
    }
    else
    {
        uint8_t condense=0;

        if (mode & CONDENSED) {
            *p = inv ? ~0 : 0;
						p += 1 ;
            condense=1;
	    	x += FWNUM-FW ;
	}

        for(char i=5; i!=0; i--){
            uint8_t b = pgm_read_byte(q++);
    	    if (condense && i==4) {
                /*condense the letter by skipping column 4 */
                continue;
            }
            if(p<DISPLAY_END) {*p = inv ? ~b : b; p += 1 ; }
        }
        if(p<DISPLAY_END) *p++ = inv ? ~0 : 0;
    }
		return x ;
}

// Puts sub-string from string options
// First byte of string is sub-string length
// idx is index into string (in length units)
// Output length characters
void lcd_putsAttIdx(uint8_t x,uint8_t y,const prog_char * s,uint8_t idx,uint8_t att)
{
	uint8_t length ;
	length = pgm_read_byte(s++) ;

  lcd_putsnAtt(x,y,s+length*idx,length,att) ;
}


//uint8_t lcd_putsnAtt(uint8_t x,uint8_t y,const prog_char * s,uint8_t len,uint8_t mode)
void lcd_putsnAtt(uint8_t x,uint8_t y,const prog_char * s,uint8_t len,uint8_t mode)
{
	uint8_t source ;
//	uint8_t size ;
	source = mode & BSS ;
//	size = mode & DBLSIZE ;
  while(len!=0) {
    char c = (source) ? *s++ : pgm_read_byte(s++);
    x = lcd_putcAtt(x,y,c,mode);
//    x+=FW;
//		if ((size)&& (c!=0x2E)) x+=FW; //check for decimal point
    len--;
  }
}
void lcd_putsn_P(uint8_t x,uint8_t y,const prog_char * s,uint8_t len)
{
  lcd_putsnAtt( x,y,s,len,0);
}

//uint8_t lcd_puts2Att(uint8_t x,uint8_t y,const prog_char * s,const prog_char * t ,uint8_t mode)
//{
//	x = lcd_putsAtt( x, y, s, mode ) ;
//	return lcd_putsAtt( x, y, t, mode ) ;	
//}

uint8_t lcd_putsAtt(uint8_t x,uint8_t y,const prog_char * s,uint8_t mode)
{
	uint8_t source ;
//	uint8_t size ;
	source = mode & BSS ;
//	size = mode & DBLSIZE ;
  //while(char c=pgm_read_byte(s++)) {
  while(1) {
    char c = (source) ? *s++ : pgm_read_byte(s++);
    if(!c) break;
    x = lcd_putcAtt(x,y,c,mode);
//    x+=FW;
//		if ((size)&& (c!=0x2E)) x+=FW; //check for decimal point
  }
  return x;
}

void lcd_puts_Pleft(uint8_t y,const prog_char * s)
{
  lcd_putsAtt( 0, y, s, 0);
}

void lcd_puts_P(uint8_t x,uint8_t y,const prog_char * s)
{
  lcd_putsAtt( x, y, s, 0);
}
void lcd_outhex4(uint8_t x,uint8_t y,uint16_t val)
{
  x+=FWNUM*4;
  for(int i=0; i<4; i++)
  {
    x-=FWNUM;
    char c = val & 0xf;
    c = c>9 ? c+'A'-10 : c+'0';
    lcd_putcAtt(x,y,c,c>='A'?CONDENSED:0);
    val>>=4;
  }
}
void lcd_outdez(uint8_t x,uint8_t y,int16_t val)
{
  lcd_outdezAtt(x,y,val,0);
}

void lcd_outdezAtt(uint8_t x,uint8_t y,int16_t val,uint8_t mode)
{
  lcd_outdezNAtt( x,y,val,mode,5);
}

#define PREC(n) ((n&0x20) ? ((n&0x10) ? 2 : 1) : 0)
uint8_t lcd_outdezNAtt(uint8_t x,uint8_t y,int32_t val,uint8_t mode,int8_t len)
{
  uint8_t fw = FWNUM;
  uint8_t prec = PREC(mode);
	uint8_t negative = 0 ;
  uint8_t xn = 0;
  uint8_t ln = 2;
  char c;
  uint8_t xinc ;
	uint8_t fullwidth = 0 ;

	mode &= ~NO_UNIT ;
	if ( len < 0 )
	{
		fullwidth = 1 ;
		len = -len ;		
	}

  if ( val < 0 )
	{
		val = -val ;
		negative = 1 ;
	}

  if (mode & DBLSIZE)
  {
    fw += FWNUM ;
    xinc = 2*FWNUM;
    lcd_lastPos = 2*FW;
  }
  else
  {
    xinc = FWNUM ;
    lcd_lastPos = FW;
  }

  if (mode & LEFT) {
//    if (val >= 10000)
//      x += fw;
    if(negative)
    {
      x += fw;
    }
    if (val >= 1000)
      x += fw;
    if (val >= 100)
      x += fw;
    if (val >= 10)
      x += fw;
    if ( prec )
    {
      if ( prec == 2 )
      {
        if ( val < 100 )
        {
          x += fw;
        }
      }
      if ( val < 10 )
      {
        x+= fw;
      }
    }
  }
  else
  {
    x -= xinc;
  }
  lcd_lastPos += x ;

  if ( prec == 2 )
  {
    mode -= LEADING0;  // Can't have PREC2 and LEADING0
  }

  for (uint8_t i=1; i<=len; i++)
	{
		div_t qr ;
		qr = div( val, 10 ) ;
    c = (qr.rem) + '0';
    lcd_putcAtt(x, y, c, mode);
    if (prec==i) {
      if (mode & DBLSIZE) {
        xn = x;
        if( c<='3' && c>='1') ln++;
        uint8_t tn = (qr.quot) % 10;
        if(tn==2 || tn==4) {
          if (c=='4') {
            xn++;
          }
          else {
            xn--; ln++;
          }
        }
      }
      else {
        x -= 2;
        if (mode & INVERS)
          lcd_vline(x+1, y, 7);
        else
          lcd_plot(x+1, y+6);
      }
      if (qr.quot)
        prec = 0;
    }
    val = qr.quot ;
    if (!val)
    {
      if (prec)
      {
        if ( prec == 2 )
        {
          if ( i > 1 )
          {
            prec = 0 ;
          }
        }
        else
        {
          prec = 0 ;
        }
      }
      else if (mode & LEADING0)
			{
				if ( fullwidth == 0 )
				{
        	mode -= LEADING0;
				}
			}
      else
        break;
    }
    x-=fw;
  }
  if (xn) {
    lcd_hline(xn, y+2*FH-4, ln);
    lcd_hline(xn, y+2*FH-3, ln);
  }
  if(negative) lcd_putcAtt(x-fw,y,'-',mode);
	return 0 ;		// Stops compiler creating two sets of POPS, saves flash
}

void lcd_hbar( uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t percent )
{
	uint8_t solid ;
	if ( percent > 100 )
	{
		percent = 100 ;
	}
	solid = (w-2) * percent / 100 ;
	lcd_rect( x, y, w, h ) ;

	if ( solid )
	{
		w = y + h - 1 ;
		y += 1 ;
		x += 1 ;
		while ( y < w )
		{
 			lcd_hline(x, y, solid ) ;
			y += 1 ;			
		}
	}
}

// Reverse video 8 pixels high, w pixels wide
// Vertically on an 8 pixel high boundary
void lcd_char_inverse( uint8_t x, uint8_t y, uint8_t w, uint8_t blink )
{
	if ( blink && BLINK_ON_PHASE )
	{
		return ;
	}
	uint8_t end = x + w ;
  uint8_t *p = &displayBuf[ y / 8 * DISPLAY_W + x ];

	while ( x < end )
	{
		*p++ ^= 0xFF ;
		x += 1 ;
	}
}

void lcd_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h )
{
  lcd_vline(x, y, h ) ;
	if ( w > 1 )
	{
  	lcd_vline(x+w-1, y, h ) ;
	}
 	lcd_hline(x+1, y+h-1, w-2 ) ;
 	lcd_hline(x+1, y, w-2 ) ;
}

void lcd_plot(uint8_t x,uint8_t y)
{
  //  if(y>=64)  return;
  //  if(x>=128) return;
  //  displayBuf[ y / 8 * DISPLAY_W + x ] ^= BITMASK(y%8);
  uint8_t *p   = &displayBuf[ y / 8 * DISPLAY_W + x ];
  if(p<DISPLAY_END) *p ^= BITMASK(y%8);
}
void lcd_hlineStip(unsigned char x,unsigned char y, signed char w,uint8_t pat)
{
  if(w<0) {x+=w; w=-w;}
  uint8_t *p  = &displayBuf[ y / 8 * DISPLAY_W + x ];
  uint8_t msk = BITMASK(y%8);
  while(w){
    if ( p>=DISPLAY_END)
    {
      break ;			
    }
    if(pat&1) {
      //lcd_plot(x,y);
      *p ^= msk;
      pat = (pat >> 1) | 0x80;
    }else{
      pat = pat >> 1;
    }
    w--;
    p++;
  }
}

void lcd_hline(uint8_t x,uint8_t y, int8_t w)
{
  lcd_hlineStip(x,y,w,0xff);
}

void lcd_vline(uint8_t x,uint8_t y, int8_t h)
{
//    while ((y+h)>=DISPLAY_H) h--;
		uint8_t y1 ;
    uint8_t *p  = &displayBuf[ y / 8 * DISPLAY_W + x ];
		y1 = y + h ;
    uint8_t *q  = &displayBuf[ y1 / 8 * DISPLAY_W + x ];
    *p ^= ~(BITMASK(y%8)-1);
    while(p<q){
        p  += DISPLAY_W;
        if ( p>=DISPLAY_END)
        {
          break ;			
        }
        *p ^= 0xff;
    }
    if(p<DISPLAY_END) *p ^= ~(BITMASK((y+h)%8)-1);
}



#if LCD_OTHER

// Supports 4W serial LCD interface and SSD1306 OLED controller
// - Hyun-Taek Chang ([email protected]), Feb 2013

// to select either stock LCD controller or SSD1306 OLED controller
 #define SSD1306         0       // Stock(ST7565/NT7532)=0, SSD1306=1

// controller independent options
 #define SERIAL_LCD      0       // parallel=0, 4W_serial=1
 #define ROTATE_SCREEN   0       // don't-rotate-screen=0, rotate-180-degree=1
 #define REVERSE_VIDEO   0       // don't-reverse-video=0, reverse-video=1

 #if (SSD1306 || ROTATE_SCREEN)
  #define COLUMN_START_LO 0x00
 #else  // ST7565
  #define COLUMN_START_LO 0x04        // skip first 4 columns
 #endif

 #if (SSD1306 || ROTATE_SCREEN)
 #define COLUMN_START_LO 0x00
 #else  // ST7565
 #define COLUMN_START_LO 0x04        // skip first 4 columns
 #endif

// force inline expansion
#define ALWAYS_INLINE   __attribute__((always_inline))

static void lcdSendByte(uint8_t val, uint8_t v0, uint8_t v1) ALWAYS_INLINE;
static void lcdEndSend() ALWAYS_INLINE;

static void lcdEndSend()
{
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1); // disable chip select
}

#if SERIAL_LCD
// Serial LCD module's SCLK(clock) and SI(data) must be connected
// to Atmega's PC4 and PC5, respectively.
#define OUT_C_LCD_SCL OUT_C_LCD_RnW     // PC4
#define OUT_C_LCD_SI  OUT_C_LCD_E       // PC5

static void lcdSendBit(uint8_t b, uint8_t v0, uint8_t v1) ALWAYS_INLINE;

// NOTE: ST7565 SCLK min period is 50ns (100ns?)
// single bit write takes 5 cycles = 312.5ns @16MHz clock
static void lcdSendBit(uint8_t b, uint8_t v0, uint8_t v1)
{
  PORTC_LCD_CTRL = v0;                  // out 0x15, r19  ; 1 cycle
  if (b != 0)                           // sbrc r24, 7    ; 1 cycle
    PORTC_LCD_CTRL = v1;                // out 0x15, r18  ; 1 cycle
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_SCL); // sbi 0x15, 4    ; 2 cycles
}

static void lcdSendByte(uint8_t val, uint8_t v0, uint8_t v1)
{
  lcdSendBit((val & 0x80), v0, v1);
  lcdSendBit((val & 0x40), v0, v1);
  lcdSendBit((val & 0x20), v0, v1);
  lcdSendBit((val & 0x10), v0, v1);
  lcdSendBit((val & 0x08), v0, v1);
  lcdSendBit((val & 0x04), v0, v1);
  lcdSendBit((val & 0x02), v0, v1);
  lcdSendBit((val & 0x01), v0, v1);
}

static void lcdSendCtl(uint8_t val)
{
  uint8_t v0c = 0xC5; // PC7=1,PC6=1,SI=0,SCL=0,A0=0,RES=1,CS1=0,PC0=1
  uint8_t v1c = 0xE5; // PC7=1,PC6=1,SI=1,SCL=0,A0=0,RES=1,CS1=0,PC0=1
  for (uint8_t n = 8; n > 0; n--) {
    lcdSendBit((val & 0x80), v0c, v1c);
    val <<= 1;
  }
  lcdEndSend();
}

#else    // PARALLEL_LCD

static void lcdStartSend() ALWAYS_INLINE;

static void lcdStartSend()
{
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);  // enable chip select
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);  // enable write 
}

static void lcdSendByte(uint8_t val, uint8_t = 0, uint8_t = 0)
{
  PORTA_LCD_DAT = val;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);    // rise enable
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);    // fall enable
}

static void lcdSendCtl(uint8_t val)
{
  lcdStartSend();
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);   // set to control mode
  lcdSendByte(val);
  lcdEndSend();
}
#endif

#define delay_1us() _delay_us(1)
#define delay_2us() _delay_us(2)
static void delay_1_5us(int ms)
{
  for(int i=0; i<ms; i++) delay_1us();
}
const static prog_uchar APM Lcdinit[] =
{
  0xe2, 0xae, 0xa1, 0xA6, 0xA4, 0xA2, 0xC0, 0x2F, 0x25, 0x81, 0x22, 0x40, 0xAF
 } ;   


void lcd_init()
{
  // /home/thus/txt/datasheets/lcd/KS0713.pdf
  // ~/txt/flieger/ST7565RV17.pdf  from http://www.glyn.de/content.asp?wdid=132&sid=
   uint8_t i ;

 LcdLock = 1 ;                  // Lock LCD data lines
 PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES);  //LCD_RES
 delay_2us();
 PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //  f524  sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21           1
 delay_1_5us(1500);
  for ( i = 0 ; i < 13 ; i += 1 )
}



void lcdSetContrast()
{
  lcdSetRefVolt(g_eeGeneral.contrast);
}

void lcdSetRefVolt(uint8_t val)
{
  LcdLock = 1 ;            // Lock LCD data lines
  lcdSendCtl(0x81);
  lcdSendCtl(val);
  LcdLock = 0 ;            // Free LCD data lines
}

volatile uint8_t LcdLock ;

void refreshDiplay()
{
#ifdef SIMU
  memcpy(lcd_buf, displayBuf, sizeof(displayBuf));
  lcd_refresh = true;

#else
  LcdLock = 1 ;             // Lock LCD data lines
  uint8_t *p=displayBuf;
#if SERIAL_LCD
  const uint8_t v0c = 0xC5; // PC7=1,PC6=1,SI=0,SCL=0,A0=0,RES=1,CS1=0,PC0=1
  const uint8_t v1c = 0xE5; // PC7=1,PC6=1,SI=1,SCL=0,A0=0,RES=1,CS1=0,PC0=1
  const uint8_t v0d = 0xCD; // PC7=1,PC6=1,SI=0,SCL=0,A0=1,RES=1,CS1=0,PC0=1
  const uint8_t v1d = 0xED; // PC7=1,PC6=1,SI=1,SCL=0,A0=1,RES=1,CS1=0,PC0=1
  for(uint8_t y=0xB0; y < 0xB8; y++) {
    lcdSendByte(COLUMN_START_LO, v0c, v1c);
    lcdSendByte(0x10, v0c, v1c);  //column addr 0
    lcdSendByte(y, v0c, v1c);     //page addr y

    for(uint8_t x=32; x>0; x--){
       lcdSendByte(*p++, v0d, v1d);
       lcdSendByte(*p++, v0d, v1d);
       lcdSendByte(*p++, v0d, v1d);
       lcdSendByte(*p++, v0d, v1d);
    }
  }
#else
  lcdStartSend();
  for(uint8_t y=0xB0; y < 0xB8; y++) {
    PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0); // switch to ctl send mode

    lcdSendByte(COLUMN_START_LO);
    lcdSendByte(0x10);  //column addr 0
    lcdSendByte(y);     //page addr y

    PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);  // switch to data send mode

    for(uint8_t x=32; x>0; x--){
       lcdSendByte(*p++);
       lcdSendByte(*p++);
       lcdSendByte(*p++);
       lcdSendByte(*p++);
    }
  }
#endif
  lcdEndSend();
  LcdLock = 0 ;            // Free LCD data lines
#endif
}


#else	// !defined(LCD_OTHER)


#ifndef LCD_2_CS
void lcdSendCtl(uint8_t val)
{
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
  PORTA_LCD_DAT = val;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_A0);
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS1);
}


#define delay_1us() _delay_us(1)
#define delay_2us() _delay_us(2)
static void delay_1_5us( uint16_t ms)
{
  for( uint16_t i=0; i<ms; i++) delay_1us();
}

const static prog_uchar APM Lcdinit[] =
{
	0xe2, 0xae, 0xa1, 0xA6, 0xA4, 0xA2, 0xC0, 0x2F, 0x25, 0x81, 0x22, 0xAF
} ;	


void lcd_init()
{
  // /home/thus/txt/datasheets/lcd/KS0713.pdf
  // ~/txt/flieger/ST7565RV17.pdf  from http://www.glyn.de/content.asp?wdid=132&sid=
	uint8_t i ;

	LcdLock = 1 ;						// Lock LCD data lines
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES);  //LCD_RES
  delay_2us();
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //  f524  sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21           1
  delay_1_5us(1500);
	for ( i = 0 ; i < 12 ; i += 1 )
	{
	  lcdSendCtl(pgm_read_byte(&Lcdinit[i]) ) ;
	}
  g_eeGeneral.contrast = lcd_nomContrast ;
	LcdLock = 0 ;						// Free LCD data lines

}


void lcdSetContrast()
{
	lcdSetRefVolt(g_eeGeneral.contrast);
}

void lcdSetRefVolt(uint8_t val)
{
	LcdLock = 1 ;						// Lock LCD data lines
  lcdSendCtl(0x81);
  lcdSendCtl(val);
	LcdLock = 0 ;						// Free LCD data lines
}

volatile uint8_t LcdLock ;
//volatile uint8_t LcdTrims ;
//uint8_t LcdTrimSwapped ;


void refreshDiplay()
{
#ifdef SIMU
  memcpy(lcd_buf, displayBuf, sizeof(displayBuf));
  lcd_refresh = true;
#else

	LcdLock = 1 ;						// Lock LCD data lines
  uint8_t *p=displayBuf;
  for(uint8_t y=0; y < 8; y++) {
    lcdSendCtl(0x04);
    lcdSendCtl(0x10); //column addr 0
    lcdSendCtl( y | 0xB0); //page addr y
    
		PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
    PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_A0);
    PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
		
    for(uint8_t x=32; x>0; x--){
//      lcdSendDat(*p);
      PORTA_LCD_DAT = *p++;
      PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);
      PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
      PORTA_LCD_DAT = *p++;
      PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);
      PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
      PORTA_LCD_DAT = *p++;
      PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);
      PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
      PORTA_LCD_DAT = *p++;
      PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E);
      PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
//      p++;
    }
    PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_A0);
    PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS1);
  }
	LcdLock = 0 ;						// Free LCD data lines
#endif
}
#endif

#ifdef LCD_2_CS
uint8_t toggle_e()
{
  uint8_t value ;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_E) ;
  asm("rjmp .+0") ;
  asm("rjmp .+0") ;
  asm("nop") ;
  value = PINA ;
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E) ;
  return value ;
}


#define delay_1us() _delay_us(1)
void delay_1_5us(int ms)
{
  for(int i=0; i<ms; i++) delay_1us();
}

#define OUT_C_LCD_CS2   0

static void lcdSendCtl(uint8_t val)
{
  uint8_t busy ;

  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);

  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RnW) ;    // read
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
  DDRA = 0 ;
  do
  {
    busy = toggle_e() ;
  } while ( busy & 0x80 ) ;
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
  DDRA = 0xFF ;
  PORTA_LCD_DAT = val;
  toggle_e() ;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS1);

  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS2);
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RnW) ;    // read
  DDRA = 0 ;
  do
  {
    busy = toggle_e() ;
  } while ( busy & 0x80 ) ;
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
  DDRA = 0xFF ;
  PORTA_LCD_DAT = val;
  toggle_e() ;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS2);

}


uint8_t Hpos ;

static void lcdSendDat(uint8_t val)
{
  uint8_t busy ;

  if ( Hpos )
  {
    PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1) ;
  }
  else
  {
    PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS2) ;
  }
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RnW) ;    // read
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
  DDRA = 0 ;
  do
  {
    busy = toggle_e() ;
  } while ( busy & 0x80 ) ;
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
  DDRA = 0xFF ;
  PORTA_LCD_DAT = val;
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_A0);
  toggle_e() ;

  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS1);
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS2);
}


void lcd_init()
{
  // /home/thus/txt/datasheets/lcd/KS0713.pdf
  // ~/txt/flieger/ST7565RV17.pdf  from http://www.glyn.de/content.asp?wdid=132&sid=

  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS1);
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_CS2);
  PORTC_LCD_CTRL |=  (1<<OUT_C_LCD_A0);
  PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES);  //LCD_RES
  delay_1us();
  delay_1us();//    f520  call  0xf4ce  delay_1us() ; 0x0xf4ce
  PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //  f524  sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21           1

  lcdSendCtl(0xC0); //
  lcdSendCtl(0x3F); //DON = 1: display ON

  g_eeGeneral.contrast = 0x22;
}

void lcdSetContrast()
{
	lcdSetRefVolt(g_eeGeneral.contrast);
}

void lcdSetRefVolt(uint8_t val)
{
	LcdLock = 1 ;						// Lock LCD data lines
  lcdSendCtl(0x81);
  lcdSendCtl(val);
	LcdLock = 0 ;						// Free LCD data lines
}

volatile uint8_t LcdLock ;
//volatile uint8_t LcdTrims ;
//uint8_t LcdTrimSwapped ;


void refreshDiplay()
{
  uint8_t *p=displayBuf;

	LcdLock = 1 ;						// Lock LCD data lines

  for(uint8_t y=0; y < 8; y++) {
    lcdSendCtl(0xC0); //
    lcdSendCtl(0x40); //column addr 0
    lcdSendCtl( y | 0xB8); //page addr y

    for(uint8_t x=0; x<128; x++)
    {
      Hpos = x & 64 ;
      lcdSendDat(*p);
      p++;
    }
//    PORTA = 0xFF;  // Outputs high/pullups enabled
  }
	LcdLock = 0 ;						// Free LCD data lines
}
#endif

#endif  // LCD_OTHER



then built er9.hex by clicking er9x-builder ( right?) it seems the program is compiled
1.JPG
and flash transmitter .

Nothing changes , the image remains divided into two halves.
DSCF7470.jpg
Yesterday arrived small displays, and they work out of the box.
DSCF7467.jpg
DSCF7468.jpg
DSCF7471.jpg
What drive me wild is that they are completely identical to the parameters , but small ones works and big ones - no.
What can I do , Mike?
User avatar
MikeB
9x Developer
Posts: 17990
Joined: Tue Dec 27, 2011 1:24 pm
Country: -
Location: Poole, Dorset, UK

Re: LCD for 9XR board

Post by MikeB »

You changed the wrong piece of code. That is some new code for handling a serial LCD.
Further down the file is the code you need to change.
Search down for:

Code: Select all

const static prog_uchar APM Lcdinit[] =
{
	0xe2, 0xae, 0xa1, 0xA6, 0xA4, 0xA2, 0xC0, 0x2F, 0x25, 0x81, 0x22, 0xAF
} ;	
already in the file. This is the area to change.

Mike.
erskyTx/er9x developer
The difficult we do immediately,
The impossible takes a little longer!
Romushock
Posts: 47
Joined: Thu Nov 08, 2012 8:35 am
Country: -
Location: North Italy

Re: LCD for 9XR board

Post by Romushock »

Don't work... Nothing changed... My new lcd.cpp here below.
lcd.rar
(6.36 KiB) Downloaded 442 times
:oops: :oops: :oops:

User avatar
MikeB
9x Developer
Posts: 17990
Joined: Tue Dec 27, 2011 1:24 pm
Country: -
Location: Poole, Dorset, UK

Re: LCD for 9XR board

Post by MikeB »

In void refreshDiplay()
try changing:
lcdSendCtl( y | 0xB0); //page addr y
to
lcdSendCtl( (y ^ 0x04) | 0xB0); //page addr y

This should fix the display, buit the code will be specific to that display.

Mike.
erskyTx/er9x developer
The difficult we do immediately,
The impossible takes a little longer!
Romushock
Posts: 47
Joined: Thu Nov 08, 2012 8:35 am
Country: -
Location: North Italy

Re: LCD for 9XR board

Post by Romushock »

Hi Mike, nothing helps... I tried to replace only y to (y ^ 0x04), compilling and flash it and make all of changes proposed by You. Situation has not changed. Small display continues to work with any lcd.cpp file changes.
lcd.rar
(6.32 KiB) Downloaded 466 times
l c d.rar
(6.32 KiB) Downloaded 421 times
Romushock
Posts: 47
Joined: Thu Nov 08, 2012 8:35 am
Country: -
Location: North Italy

Re: LCD for 9XR board

Post by Romushock »

I feel so lonely... :( :( :(
User avatar
MikeB
9x Developer
Posts: 17990
Joined: Tue Dec 27, 2011 1:24 pm
Country: -
Location: Poole, Dorset, UK

Re: LCD for 9XR board

Post by MikeB »

Sorry, I'll try to look at this today, I've been rather busy. The change I suggsted should have worked, and messed up other displays.

Mike.
erskyTx/er9x developer
The difficult we do immediately,
The impossible takes a little longer!
User avatar
MikeB
9x Developer
Posts: 17990
Joined: Tue Dec 27, 2011 1:24 pm
Country: -
Location: Poole, Dorset, UK

Re: LCD for 9XR board

Post by MikeB »

The code has got THREE copies of refreshDiplay() in it, for different displays now.
You need to add the ^4 to THIS one:

for(uint8_t y=0; y < 8; y++) {
lcdSendCtl(0x04);
lcdSendCtl(0x10); //column addr 0
lcdSendCtl( (y^4) | 0xB0); //page addr y

PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);

Mike.
erskyTx/er9x developer
The difficult we do immediately,
The impossible takes a little longer!
kbadra
Posts: 31
Joined: Mon Jan 04, 2016 11:57 am
Country: Brazil
Location: Belo Horizonte

Re: LCD for 9XR board

Post by kbadra »

Did it work?
Satisfação

Post Reply

Return to “Turnigy 9XR radio”