Forum: Mikrocontroller und Digitale Elektronik T6963C-Display flackert


von Oyrer Andreas (Gast)


Lesenswert?

Hallo,

ich habe ein 240x128 Display mit T6963C-Controller angesteuert. Da ich
eine eigenen Schriftart verwende, kann ich den internen Zeichensatz
nicht verwenden. Die Schrift ist tlw. auch höher als 8 Zeilen. Um ein
Zeichen darzustellen, muss ich daher mehrere Adressen beschreiben (z.B.
2 untereinander). Damit die einzelnen Zeichen nicht immer erst bei den
nächsten 8 Bit einer Zeile beginnen, ver-odere ich die einzelnen
Zeichen. Die einzelnen Zeichen werden in einer Funktion beschrieben.
Damit das vorige Zeichen nicht tlw. gelöscht wird, lese ich zuert die
aktuelle Adresse aus, dann ver-odere ich dieses Datum mit den Daten des
aktuellen Zeichens und schreibe das Byte wieder raus.
Bisher funktioniert alles gut. Nun habe ich einen neuen
Display-Hersteller. Plötzlich flackert das Display, wenn ich das
aktuelle Datum auslese!!??!! Gebe ich diese Zeile weg, flackert es
nicht mehr, aber die Schrift ist auch nicht vollständig.

Hat vielleicht jemand eine Idee, woran das liegen könnte bzw. wie ich
mir abhelfen kann??

Das neue Display ist von Winstar (WG240128B).

Danke für eure Hilfe.

mfg
Andreas

von Michael (Gast)


Lesenswert?

1. Wie ist dein Code geschrieben bzgl. der Abfrage des Statusworts des
T6963C? Mit TimeOut oder richtige Abfrage vom Status?

2. Hat das Winstar einen kleineren RAM?

3. Sind die Konfigurationspins des T6963C richtig beschalten?

Ralf

von Oyrer Andreas (Gast)


Lesenswert?

Hallo Michael,

danke für deine Antwort, ich war die letzten Wochen auf Urlaub, deshalb
antworte ich etwas verspätet.

ad 1. Ich frage das Statusbyte ab, nicht mit Timeout
ad 2. das Winstar Display hat 8k RAM, das vorige Display 32k; aber ich
verwende nur den Grafikbereich, und der startet bei Adresse 0 => sollte
somit bei beiden Displays funktionieren (Auflösung 320 x 240).
ad 3. Die Konfigurationspins sind richtig beschaltet. Beide Displays
sind pinkompatibel (lt. Datenblatt).

Danke für die Hilfe
mfg Andreas

von Ralf (Gast)


Lesenswert?

Wenn ich eins von den Displays bekomme, verrat ich dir, woran es liegt
grins

Nein, quatsch, ernsthaft: also wenn ich folgende Rechnung vornehme:

320 * 240 / 8 = 9600 komme ich auf die benötigte Anzahl der Bytes, die
nötig sind, um über den vollen Display-Bereich Grafik darzustellen.

Bist du sicher dass das neue Display nur 8kB hat? Das könnte nämlich
dann den Fehler erklären :-)

Ralf

von Oyrer Andreas (Gast)


Lesenswert?

Uje, hier ist mir wohl ein Fehler passiert, das Display hat nämlich eine
Auflösung von 240x128 Pixel...

Danke für den Tipp.

mfg
Andreas

von Hauke Radtki (Gast)


Lesenswert?

Muss ein Fehler sein, da der t6963c kein 320x240 unterstützt :>

von Ralf (Gast)


Lesenswert?

Hi,

das dachte ich mir schon, dass es wohl nicht sein kann, dass
irgendjemand ein Grafikdisplay bastelt, dessen RAM nicht voll
ausreicht...

Okay, dann bleibt dir nur noch, hier mal den Code zu posten, vielleicht
kann man da was erkennen... Welchen Controller und welche
Programmiersprache verwendest du?

Ralf

von Oyrer Andreas (Gast)


Lesenswert?

Hallo Ralf,

den Code werde ich morgen posten. Danke für die Unterstützung. Ich
verwende einen ATmega128 und WinAVR.

mfg
Andreas

von Oyrer Andreas (Gast)


Lesenswert?

Hallo Ralf,

hier nun der Source (tlw.). Das Display flackert nicht, wenn die Zeile
DataLeft = LCD_ReadCmd_1_Data(LCD_DATA_RD); entfernt wird.

LCD_GraphicXY((_PosX / LCD_UNIT_WIDTH), _PosY + idx);

subidx = 0;
while (1)
{
  if (subidx < CharWidthB)
  {
    if (subidx == 0)
      DataLeft = LCD_ReadCmd_1_Data(LCD_DATA_RD);

    Temp = pgm_read_byte(UsedFont.fontdata + Offset + subidx + idx *
CharWidthB);
    DisplayData = Temp >> (_PosX % LCD_UNIT_WIDTH);
    DisplayData |= DataLeft;
    DataLeft = (Temp << (LCD_UNIT_WIDTH - (_PosX % LCD_UNIT_WIDTH)));
  }
  else
  {
    if (DataLeft != 0)
      DisplayData = DataLeft;
    else
      break;
    DataLeft = 0;
  }
  subidx++;

  LCD_WriteCmd_1_Data(LCD_DATA_WR_INC, DisplayData);
}

//********************************************************************** 
*******
// read the status byte
//********************************************************************** 
*******
static unsigned char LCD_ReadStatus(void)
{
  CD_CMD;
  return LCD_ReadLow();
}

//********************************************************************** 
*******
// status check
//********************************************************************** 
*******
static void LCD_StatusCheck(unsigned char Status)
{
  while ((LCD_ReadStatus() & Status) != Status);
}

//********************************************************************** 
*******
// Read a data byte using auto write mode
//********************************************************************** 
*******
static unsigned char LCD_ReadDataAuto(void)
{
  LCD_StatusCheck(LCD_STATUS_AUTO_RD);
  CD_DATA;
  return LCD_ReadLow();
}

//********************************************************************** 
*******
// Read a data byte + a command byte
//********************************************************************** 
*******
static unsigned char LCD_ReadCmd_1_Data(unsigned char Cmd)
{
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  //CD_CMD;
  LCD_WriteLow(Cmd);

  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  return LCD_ReadLow();
}

//********************************************************************** 
*******
// Read a data byte
//********************************************************************** 
*******
static unsigned char LCD_ReadData(void)
{
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  return LCD_ReadLow();
}

//********************************************************************** 
*******
// read a byte
//********************************************************************** 
*******
static unsigned char LCD_ReadLow(void)
{
  unsigned char byte = 0;

  LCD_PORT_INPUT;
  // enable pullups to read data
  LCD_ENABLE_PU;

  CE_ENABLE;
  RD_ENABLE;

  // wait min. 150ns
  asm("nop");
  byte = LCD_PIN;

  CE_DISABLE;
  RD_DISABLE;

  LCD_PORT_OUTPUT;

  return byte;
}

//********************************************************************** 
*******
// Write a data byte + a command byte
//********************************************************************** 
*******
static void LCD_WriteCmd_1_Data(unsigned char Cmd, unsigned char data)
{
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  LCD_WriteLow(data);

  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  LCD_WriteLow(Cmd);
}

//********************************************************************** 
*******
// Write two data bytes + a command byte
//********************************************************************** 
*******
static void LCD_WriteCmd_2_Data(unsigned char Cmd, unsigned int data)
{
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  LCD_WriteLow((unsigned char)data);
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  LCD_WriteLow((unsigned char)(data >> 8));

  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  LCD_WriteLow(Cmd);
}

//********************************************************************** 
*******
// Write a byte
//********************************************************************** 
*******
static void LCD_WriteLow(unsigned char byte)
{
  CE_ENABLE;
  WR_ENABLE;

  LCD_PORT = byte;

  // wait min. 80ns
  //asm("nop");

  CE_DISABLE;
  WR_DISABLE;
}

von Ralf (Gast)


Lesenswert?

>> LCD_GraphicXY

Könntest du die Funktion wenigstens in groben Zügen mal beschreiben?
Ich werd aus deinen Variablennamen nicht schlau...

Wenn ich weiss, was da passiert bzw. passieren soll, wirds einfacher
für mich...

Ralf

von Oyrer Andreas (Gast)


Lesenswert?

Hallo,

am besten ich poste den gesamten Code.
Danke für die Hilfe.

#define LCD_PORT_OUTPUT  (LCD_PORT_DDR = 0xFF)
#define LCD_PORT_INPUT  (LCD_PORT_DDR = 0x00)
#define LCD_ENABLE_PU  (LCD_PORT = 0xFF)

#define WR_OUTPUT    sbi(DDRD, LCD_WR)
#define WR_ENABLE    cbi(PORTD, LCD_WR)
#define WR_DISABLE    sbi(PORTD, LCD_WR)

#define RD_OUTPUT    sbi(DDRD, LCD_RD)
#define RD_ENABLE    cbi(PORTD, LCD_RD)
#define RD_DISABLE    sbi(PORTD, LCD_RD)

#define CE_OUTPUT    sbi(DDRA, LCD_CE)
#define CE_ENABLE    cbi(PORTA, LCD_CE)
#define CE_DISABLE    sbi(PORTA, LCD_CE)

#define CD_OUTPUT    sbi(DDRD, LCD_CD)
#define CD_DATA      cbi(PORTD, LCD_CD)
#define CD_CMD      sbi(PORTD, LCD_CD)

#define RST_OUTPUT    sbi(DDRA, LCD_RST)
#define RST_LOW      cbi(PORTA, LCD_RST)
#define RST_HIGH    sbi(PORTA, LCD_RST)

#define FS_OUTPUT    sbi(DDRA, LCD_FS)
#define FS_8x8      cbi(PORTA, LCD_FS)
#define FS_6x8      sbi(PORTA, LCD_FS)

#define MD2_OUTPUT    sbi(DDRA, LCD_FS)
#define MD2_40COL    cbi(PORTA, LCD_FS)
#define MD2_32COL    sbi(PORTA, LCD_FS)


//********************************************************************** 
*******
// global variables
//********************************************************************** 
*******
static Font_t UsedFont;
static unsigned char FontSet = 0;
static unsigned char Alignment = ALIGN_LEFT;

static unsigned char _PosX = 0;
static unsigned char _PosY = 0;

//********************************************************************** 
*******
// Init the display
//********************************************************************** 
*******
void LCD_Init(void)
{
  // init the IO-directions
  LCD_PORT_OUTPUT;

  WR_OUTPUT;
  RD_OUTPUT;
  CE_OUTPUT;
  CD_OUTPUT;
  RST_OUTPUT;
  FS_OUTPUT;
  MD2_OUTPUT;

  // init the IO-lines
  WR_DISABLE;
  RD_DISABLE;
  CE_DISABLE;

  if (LCD_UNIT_WIDTH == 6)
  {
    MD2_40COL;
    FS_6x8;
  }
  else
  {
    MD2_32COL;
    FS_8x8;
  }

  // reset LCD
  RST_LOW;
  Delay_ms(5);
  RST_HIGH;

  // init the display
  LCD_WriteCmd_2_Data(LCD_SET_TEXT_HOME_ADDR, LCD_TEXT_BASE);
  LCD_WriteCmd_2_Data(LCD_SET_GRA_HOME_ADDR, LCD_GRA_BASE);
  LCD_WriteCmd_2_Data(LCD_SET_TEXT_AREA, LCD_COLUMNS);
  LCD_WriteCmd_2_Data(LCD_SET_GRA_AREA, LCD_COLUMNS);
  LCD_WriteCmd(LCD_MODE_OR);

  // set offset register
  LCD_WriteCmd_2_Data(LCD_SET_OFFSET_REG, 0x1400);

  // clear the graphic ram
  LCD_ClearDisplay();

  // set address pointer to start of text ram
  //LCD_WriteCmd_2_Data(LCD_SET_ADDR_POINTER, LCD_TEXT_BASE);

  // set cursor 1 line
  //LCD_WriteCmd(LCD_1_LINE_CUR);
}

//********************************************************************** 
*******
// set display mode
//********************************************************************** 
*******
void LCD_DisplayMode(unsigned char Mode)
{
  LCD_WriteCmd(Mode);
}

//********************************************************************** 
*******
// Write a data byte using auto write mode
//********************************************************************** 
*******
static void LCD_WriteDataAuto(unsigned char data)
{
  LCD_StatusCheck(LCD_STATUS_AUTO_WR);
  CD_DATA;
  LCD_WriteLow(data);
}

//********************************************************************** 
*******
// Write a cmd byte
//********************************************************************** 
*******
static void LCD_WriteCmd(unsigned char cmd)
{
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  //CD_CMD;
  LCD_WriteLow(cmd);
}

//********************************************************************** 
*******
// Write a data byte
//********************************************************************** 
*******
static void LCD_WriteData(unsigned char data)
{
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  LCD_WriteLow(data);
}

//********************************************************************** 
*******
// Write a data byte + a command byte
//********************************************************************** 
*******
static void LCD_WriteCmd_1_Data(unsigned char Cmd, unsigned char data)
{
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  LCD_WriteLow(data);

  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  LCD_WriteLow(Cmd);
}

//********************************************************************** 
*******
// Write two data bytes + a command byte
//********************************************************************** 
*******
static void LCD_WriteCmd_2_Data(unsigned char Cmd, unsigned int data)
{
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  LCD_WriteLow((unsigned char)data);
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  LCD_WriteLow((unsigned char)(data >> 8));

  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  LCD_WriteLow(Cmd);
}

//********************************************************************** 
*******
// Write a byte
//********************************************************************** 
*******
static void LCD_WriteLow(unsigned char byte)
{
  CE_ENABLE;
  WR_ENABLE;

  LCD_PORT = byte;

  // wait min. 80ns
  //asm("nop");

  CE_DISABLE;
  WR_DISABLE;
}

//********************************************************************** 
*******
// read the status byte
//********************************************************************** 
*******
static unsigned char LCD_ReadStatus(void)
{
  CD_CMD;
  return LCD_ReadLow();
}

//********************************************************************** 
*******
// status check
//********************************************************************** 
*******
static void LCD_StatusCheck(unsigned char Status)
{
  while ((LCD_ReadStatus() & Status) != Status);
}

//********************************************************************** 
*******
// Read a data byte using auto write mode
//********************************************************************** 
*******
static unsigned char LCD_ReadDataAuto(void)
{
  LCD_StatusCheck(LCD_STATUS_AUTO_RD);
  CD_DATA;
  return LCD_ReadLow();
}

//********************************************************************** 
*******
// Read a data byte + a command byte
//********************************************************************** 
*******
static unsigned char LCD_ReadCmd_1_Data(unsigned char Cmd)
{
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  //CD_CMD;
  LCD_WriteLow(Cmd);

  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  return LCD_ReadLow();
}

//********************************************************************** 
*******
// Read a data byte
//********************************************************************** 
*******
static unsigned char LCD_ReadData(void)
{
  LCD_StatusCheck(LCD_STATUS_READ_WRITE);
  CD_DATA;
  return LCD_ReadLow();
}

//********************************************************************** 
*******
// read a byte
//********************************************************************** 
*******
static unsigned char LCD_ReadLow(void)
{
  unsigned char byte = 0;

  LCD_PORT_INPUT;
  // enable pullups to read data
  LCD_ENABLE_PU;

  CE_ENABLE;
  RD_ENABLE;

  // wait min. 150ns
  asm("nop");
  byte = LCD_PIN;

  CE_DISABLE;
  RD_DISABLE;

  LCD_PORT_OUTPUT;

  return byte;
}

//********************************************************************** 
*******
// set the address pointer to graphic area
//********************************************************************** 
*******
void LCD_GotoXY(unsigned char PosX, unsigned char PosY)
{
  _PosX = PosX;
  _PosY = PosY;

  LCD_SetAlign(ALIGN_LEFT);
}

//********************************************************************** 
*******
// set the address pointer to graphic area
//********************************************************************** 
*******
static void LCD_GraphicXY(unsigned char PosX, unsigned char PosY)
{
  LCD_WriteCmd_2_Data(LCD_SET_ADDR_POINTER, LCD_GRA_BASE + PosY *
LCD_COLUMNS + PosX);
}

//********************************************************************** 
*******
// Clear the whole graphic ram
//********************************************************************** 
*******
void LCD_ClearDisplay(void)
{
  unsigned int idx = 0;

  LCD_WriteCmd_2_Data(LCD_SET_ADDR_POINTER, LCD_GRA_BASE);
  LCD_WriteCmd(LCD_SET_DATA_AUTO_WR);

  for (idx = 0; idx < LCD_GRA_SIZE; idx++)
  {
    LCD_WriteDataAuto(0x00);
  }

  LCD_WriteCmd(LCD_AUTO_RESET);
}

//********************************************************************** 
*******
// Clear a specified range of the display ram
//********************************************************************** 
*******
void LCD_ClearRange(unsigned char StartX, unsigned char StartY,
unsigned char Width, unsigned char Height)
{
  unsigned char idx = 0;

  // clear line by line
  while (Height--)
  {
    // set the address pointer
    LCD_GraphicXY((StartX / LCD_UNIT_WIDTH), StartY++);

    LCD_WriteCmd(LCD_SET_DATA_AUTO_WR);

    for (idx = 0; idx < (Width / 8); idx++)
    {
      LCD_WriteDataAuto(0x00);
    }
    LCD_WriteCmd(LCD_AUTO_RESET);
  }
}

//********************************************************************** 
*******
// defines the font to use
//********************************************************************** 
*******
void LCD_SetFont(Font_t font)
{
  FontSet = 1;
  UsedFont = font;
}

//********************************************************************** 
*******
// set the alignment of the text
//********************************************************************** 
*******
void LCD_SetAlign(unsigned char Align)
{
  Alignment = Align;
}

//********************************************************************** 
*******
// writes a char
//********************************************************************** 
*******
void LCD_PutChar(unsigned char str)
{
  unsigned char DataLeft = 0;
  unsigned int Offset = 0;
  unsigned char CharWidth = 0;
  unsigned char CharWidthB = 0;
  unsigned char idx = 0;
  unsigned char subidx = 0;

  // calculate the offset to read the font data
  idx = str - ' ';
  Offset = pgm_read_byte(UsedFont.fontoffset + idx*2);
  Offset += (pgm_read_byte(UsedFont.fontoffset + idx*2 + 1) << 8);

  CharWidth = pgm_read_byte(UsedFont.fontdata + Offset);
  CharWidthB = ((CharWidth - 1) / LCD_UNIT_WIDTH) + 1;
  Offset += 1;

  for (idx = 0; idx < UsedFont.Height; idx++)
  {
    unsigned char Temp = 0;
    unsigned char DisplayData;

    LCD_GraphicXY((_PosX / LCD_UNIT_WIDTH), _PosY + idx);

    subidx = 0;
    while (1)
    {
      if (subidx < CharWidthB)
      {
        if (subidx == 0)
          DataLeft = LCD_ReadCmd_1_Data(LCD_DATA_RD);

        Temp = pgm_read_byte(UsedFont.fontdata + Offset + subidx + idx *
CharWidthB);
        DisplayData = Temp >> (_PosX % LCD_UNIT_WIDTH);
        DisplayData |= DataLeft;
        DataLeft = (Temp << (LCD_UNIT_WIDTH - (_PosX % 
LCD_UNIT_WIDTH)));
      }
      else
      {
        if (DataLeft != 0)
          DisplayData = DataLeft;
        else
          break;
        DataLeft = 0;
      }
      subidx++;

      LCD_WriteCmd_1_Data(LCD_DATA_WR_INC, DisplayData);
    }
  }
  _PosX += CharWidth;
}

//********************************************************************** 
*******
// puts a hex character
//********************************************************************** 
*******
void LCD_PutHex(unsigned char data)
{
  unsigned char buf[5];
  sprintf(buf, "%02x", data);
  LCD_PutStr(buf);
}

//********************************************************************** 
*******
// Prints a long value
//********************************************************************** 
*******
void LCD_PutLong(unsigned long Value, BOOL ShowKomma)
{
  unsigned char Cnt = 0;
  unsigned char Buf[10];
  // umwandeln
  Cnt = 10;

  memset(Buf, 0x00, sizeof(Buf));

  do
  {
    Cnt--;
    Buf[Cnt] = Value % 10;
    Value /= 10;
  } while (Value > 0);

  // if the value is smaller than 1€, also show the komma and a leading
"0"
  if (Cnt >= 8 && ShowKomma)
    Cnt = 7;

  // nun ausgeben
  while (Cnt < 10)
  {
    LCD_PutChar(Buf[Cnt] + '0');
    Cnt++;
    if (ShowKomma && (Cnt == 8) )
      LCD_PutChar(',');
  }
}

//********************************************************************** 
*******
// writes text to the display at the specified position
//********************************************************************** 
*******
void LCD_PutStr(unsigned char * str)
{
  unsigned char PosX = _PosX;

  // if no font has been set, return
  if (FontSet == 0)
    return;

  if (Alignment != ALIGN_LEFT)
  {
    unsigned char * pstr = str;
    unsigned int Offset = 0;
    unsigned char idx = 0;
    unsigned char TextWidth = 0;

    while (*pstr >= ' ')
    {
      idx = *pstr - ' ';
      Offset = pgm_read_byte(UsedFont.fontoffset + idx*2);
      Offset += (pgm_read_byte(UsedFont.fontoffset + idx*2 + 1) << 8);

      TextWidth += pgm_read_byte(UsedFont.fontdata + Offset);
      pstr++;
    }
    if (Alignment == ALIGN_RIGHT)
      _PosX = (LCD_PIXELX - TextWidth);
    else
      _PosX = (LCD_PIXELX - TextWidth) / 2;
  }

  while (*str)
  {
    if (*str == '\n')
      _PosY += UsedFont.Height;
    else if (*str == '\r')
      _PosX = PosX;
    else
      LCD_PutChar(*str);
    str++;
  }
}

//********************************************************************** 
*******
// Write a small image
//********************************************************************** 
*******
void LCD_ShowImageSmall(unsigned char PosX, unsigned char Line,
unsigned char * image, unsigned char Len)
{
}

//********************************************************************** 
*******
// Write a full screen display
// image is located in flash memory
//********************************************************************** 
*******
void LCD_ShowImage(PGM_P pimage)
{
}

//********************************************************************** 
*******
// Set a pixel
//********************************************************************** 
*******
void LCD_SetPixel(unsigned char PosX, unsigned char PosY)
{
  // set address pointer
  LCD_WriteCmd_2_Data(LCD_SET_ADDR_POINTER, LCD_GRA_BASE + PosY *
LCD_COLUMNS + PosX / LCD_UNIT_WIDTH);
  LCD_WriteCmd(LCD_BIT_SET | (LCD_UNIT_WIDTH - 1 - (PosX %
LCD_UNIT_WIDTH)));
}

//********************************************************************** 
*******
// reset a pixel
//********************************************************************** 
*******
void LCD_ResetPixel(unsigned char PosX, unsigned char PosY)
{
  LCD_WriteCmd_2_Data(LCD_SET_ADDR_POINTER, LCD_GRA_BASE + PosY *
LCD_COLUMNS + PosX / LCD_UNIT_WIDTH);
  LCD_WriteCmd(LCD_BIT_RESET | (LCD_UNIT_WIDTH - 1 - (PosX %
LCD_UNIT_WIDTH)));
}

//********************************************************************** 
*******
// draw a line
//********************************************************************** 
*******
void LCD_DrawLine(unsigned char X1, unsigned char Y1, unsigned char X2,
unsigned char Y2)
{
  unsigned char XStep, YStep, XStart, YStart;
  unsigned int Tmp;

  if (X1 > X2)
  {
    XStep = X1 - X2;
    XStart = X2;
  }
  else
  {
    XStep = X2 - X1;
    XStart = X1;
  }
  if (Y1 > Y2)
  {
    YStep = Y1 - Y2;
    YStart = Y2;
  }
  else
  {
    YStep = Y2 - Y1;
    YStart = Y1;
  }

  if (XStep > YStep)
  {
    for (unsigned char x = 0; x <= XStep; x++)
    {
      Tmp = (YStep * 100) / XStep;
      LCD_SetPixel(x + XStart, Tmp * x / 100 + YStart);
    }
  }
  else
  {
    for (unsigned char y = 0; y <= YStep; y++)
    {
      Tmp = (XStep * 100) / YStep;
      LCD_SetPixel(Tmp * y / 100 + XStart, y + YStart);
    }
  }
}

//********************************************************************** 
*******
// draw a rectangle
//********************************************************************** 
*******
void LCD_DrawRect(unsigned char X1, unsigned char Y1, unsigned char X2,
unsigned char Y2)
{
  LCD_DrawLine(X1, Y1, X2, Y1);
  LCD_DrawLine(X2, Y1, X2, Y2);
  LCD_DrawLine(X2, Y2, X1, Y2);
  LCD_DrawLine(X1, Y2, X1, Y1);
}

//********************************************************************** 
*******
// draw a circle
//********************************************************************** 
*******
void LCD_DrawCircle(unsigned char PosX, unsigned char PosY, unsigned
char Radius)
{
  int tswitch, y, x = 0;

  y = Radius;
  tswitch = 3 - 2 * Radius;
  while (x <= y)
  {
    LCD_SetPixel(PosX + x, PosY + y);
    LCD_SetPixel(PosX + x, PosY - y);
    LCD_SetPixel(PosX - x, PosY + y);
    LCD_SetPixel(PosX - x, PosY - y);
    LCD_SetPixel(PosX + y, PosY + x);
    LCD_SetPixel(PosX + y, PosY - x);
    LCD_SetPixel(PosX - y, PosY + x);
    LCD_SetPixel(PosX - y, PosY - x);

    if (tswitch < 0)
      tswitch += (4 * x + 6);
    else
    {
      tswitch += (4 * (x - y) + 10);
      y--;
    }
    x++;
  }
}

//********************************************************************** 
*******
// draw a box
//********************************************************************** 
*******
void LCD_DrawBox(unsigned char PosX, unsigned char PosY, unsigned char
Width, unsigned char Height)
{
  if (Width < 17) Width = 17;
  if (Height < 17) Height = 17;

  Width -= 17;
  Height -= 17;

  LCD_DrawArc(PosX + 8, PosY + 8, 8, 0);
  LCD_DrawLine(PosX + 8, PosY, PosX + 8 + Width, PosY);
  LCD_DrawArc(PosX + 8 + Width, PosY + 8, 8, 1);
  LCD_DrawLine(PosX + 16 + Width, PosY + 8, PosX + 16 + Width, PosY + 8
+ Height);
  LCD_DrawArc(PosX + 8 + Width, PosY + 8 + Height, 8, 2);
  LCD_DrawLine(PosX + 8, PosY + 16 + Height, PosX + 8 + Width, PosY + 16
+ Height);
  LCD_DrawArc(PosX + 8, PosY + 8 + Height, 8, 3);
  LCD_DrawLine(PosX, PosY + 8, PosX, PosY + 8 + Height);
}

//********************************************************************** 
*******
// draw a arc
//********************************************************************** 
*******
void LCD_DrawArc(unsigned char PosX, unsigned char PosY, unsigned char
Radius, unsigned char Dir)
{
  int tswitch, y, x = 0;

  y = Radius;
  tswitch = 3 - 2 * Radius;
  while (x <= y)
  {
    switch (Dir)
    {
    case 0:
      // arc left upper
      LCD_SetPixel(PosX - x, PosY - y);
      LCD_SetPixel(PosX - y, PosY - x);
      break;
    case 1:
      // arc right upper
      LCD_SetPixel(PosX + x, PosY - y);
      LCD_SetPixel(PosX + y, PosY - x);
      break;
    case 2:
      // arc right lower
      LCD_SetPixel(PosX + x, PosY + y);
      LCD_SetPixel(PosX + y, PosY + x);
      break;
    case 3:
      // arc left lower
      LCD_SetPixel(PosX - x, PosY + y);
      LCD_SetPixel(PosX - y, PosY + x);
      break;
    }

    if (tswitch < 0)
      tswitch += (4 * x + 6);
    else
    {
      tswitch += (4 * (x - y) + 10);
      y--;
    }
    x++;
  }
}

von Ralf (Gast)


Lesenswert?

Das hilft nur bedingt. Ich brauch ne Beschreibung, was das Programm bzw.
einzelne Funktionen machen (sollen). Ich werd aus dem Code allein nicht
schlau. Jede gute Software ist dokumentiert.

Ralf

von Oyrer Andreas (Gast)


Lesenswert?

Hallo,

Doku ist sicher nicht schlecht, aber wie immer ist das, was am
wenigsten Priorität hat und auch bei diesem Projekt war so gut wie
keine Zeit dafür...

Prinzipieller Ablauf:
LCD_Init() => Initialisieren des Displays + IO-Leitungen
LCD_ClearDisplay() => Display-RAM löschen
LCD_GotoXY() => Position am Display setzen
LCD_PutStr() => String ausgeben mit eingestellter Schriftart (nicht die
eingebaute Schriftart, sondern selbst definierter Schriftsatz)
LCD_PutStr ruft LCD_PutChar() auf.
LCD_PutChar() => Ausgabe eines einzelnen Zeichens auf das Display. Das
Zeichen wird Zeile für Zeile je 8Bit ausgegeben. Ist das Zeichen z.B.
23 Pixel hoch, so wird die Schleife 23x durchlaufen. Pro Schreibzyklus
können nur 8 Bit in einer Zeile geschrieben werden. Ist das Zeichen
z.B. 11 Pixel breit, so muss man 2x schreiben, um eine Zeile des
Zeichens richtig anzuzeigen. Das erste Zeichen ist eigentlich kein
Problem. Schreibt man aber einen String raus, so schreibe ich nach dem
ersten Zeichen das weitere hinten dran. Nehmen wir an, die Zeichen
werden durch 2 Leerspalten getrennt. Dann sollte das 2. Zeichen ab
Pixel 13 stehen. Da das aber in der Mitte eines Bytes ist, muss ich das
Zeichen auslesen, welches an der Adresse steht (hier steht ein Teil des
ersten Zeichens). Dann muss ich das aktuelle Zeichen entsprechend
verschieben, um die ersten 3 Pixel ((16 - 13) % 8) anzuzeigen. Diese
Daten muss ich mit dem Inhalt des Display-RAMs verodern, um das alte
Zeichen (2. Teil des ersten Zeichens) nicht zu löschen. Danach wird das
Byte wieder geschrieben. usw.

Ist die Beschreibung so ok?

von thkais (Gast)


Lesenswert?

Kleiner Tipp am Rande: Man kann sich viel Datenverkehr sparen, wenn man
den String im RAM des µC vorbereitet.
Ich schreibe eine ganze Zeile (1 Pixel breit) in den RAM (der ist so
breit wie das Display, also 32 Bytes) und muss dann nur links und
rechts  die beiden End-Bytes verodern. Alles andere wird überschrieben
- dadurch kann man auch Texte überschreiben, ohne gleich alles löschen
zu müssen.

Zu Deinem Problem: Ich vermute ein Timing-Problem. Ich würde
spaßeshalber in jede Subroutine, die mit dem Display auf Hardwareebene
kommuniziert, mit ein paar eingestreuten NOPs verlangsamen. Vielleicht
ist irgendwo ein Signal einen Tick zu schnell. Bedingt durch
unterschiedliche Layouts könnte es bei einem Display gerade so
hinhauen, beim anderen eben nicht...

von Oyrer Andreas (Gast)


Lesenswert?

Danke für den Tipp. Teilweise habe ich schon nops eingefügt, aber ich
werde das noch mal erweitern. Wenn ich dadurch den Fehler nicht
verhindert kann, muss ich mir auch die Daten vor dem Schreiben im RAM
speichern.

mfg
Andreas

von thkais (Gast)


Lesenswert?

Man könnte das mit dem Verlangsamen auch auf die Spitze treiben: Nach
jedem Programmschritt per serieller Schnittstelle den aktuellen Status
senden und auf eine Quittierung warten - also eine Art "single-step".
Dann sollte man eigentlich den Übeltäter ganz exakt finden.

von Oyrer Andreas (Gast)


Lesenswert?

Hallo,

ich habe jetzt die gesamte SW umgeworfen. Nun gebe ich einen String wie
thkais gemeint hat Zeile für Zeile aus. Dadurch kann ich die Daten im
RAM zwischenspeichern und muss das Display-RAM nicht mehr auslesen.
Allerdings flackert das Display jetzt auch ab und zu, aber weit nicht
so extrem wie vorher...

Danke für eure Hilfe.

mfg
Andreas

von Ralf (Gast)


Lesenswert?

Noch n Tip meinerseits, sorry erstmal dass ich erst jetzt schreibe.

Ich habe auch mal einen eigenen Schriftsatz implementiert, und bin
dabei so vorgegangen:

Jeder Buchstabe war über eine Tabelle im Code hinterlegt (wird bei dir
wohl auch so sein).
Die ersten beiden Einträge der Tabelle haben die Größe des Buchstabens
in X und in Y angegeben. Alle weiteren Einträge waren die Pixel, die
den Buchstaben bilden, pro 8 Pixel also ein Byte.
Hatte ich z.B. eine Breite von 14 Pixeln, so habe ich das erste Byte
komplett und vom zweiten eben die höchstwertigen 6 Bits ausgegeben -->
mittels PUTPIXEL.
Ich musste aber nicht auslesen, so wie du es machst, sondern habe nur
die gesetzten Pixel eingetragen.
Wollte ich sicherstellen, dass ein evtl. bereits vorhandener Buchstabe
überschrieben wird, so hab ich natürlich auch die nicht gesetzten Pixel
ausgegeben...

Schließlich hat der T6963C ja eine Pixelfunktion, warum also die nicht
nutzen???
Vielleicht kannst du das auch so machen...
Ob es allerdings mit byteweisem Schreiben schneller geht, müsste ich
mal probieren, dann wäre das ganze nämlich ein Tip von dir an mich ;-)

Ralf

von Oyrer Andreas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Ralf,

danke für den Tipp. Das hatte ich mir auch schon mal überlegt gehabt.
Ich dachte mir aber, dass das vielleicht zu langsam werden könnte, da
man immer nur 1 Pixel setzen kann.

Anbei habe ich den neuen Code, falls es dich interessiert.

Auch ich habe mir einige Schriftarten definiert. Mit einem speziellen
Tool kann ich Systemfonts umwandeln und gleich als font-Datei
speichern. Die Höhe eines Zeichens einer Schriftart ist immer gleich,
die Breite des Zeichens steht, wie bei dir, vor den eigentlichen
Daten.

mfg
Andreas

von Ralf (Gast)


Lesenswert?

Okay, ich hab demnächst Urlaub, vielleicht probier ich mal die
1-Byte-auf-einmal-Variante...
Wie heisst dein Tool bzw. wo kann ich das herunterladen?

Ralf

von Oyrer Andreas (Gast)


Angehängte Dateien:

Lesenswert?

Naja, das Tool zum konvertieren habe ich im Zuge eines Projektes in der
Arbeit geschrieben...

Das Tool zum Umwandeln der Systemfonts findest du anbei. Etwas
komisches Programm, aber es funktioniert und wandelt dir die Fonts in
Binäre Daten um. Diese sind aber spaltenweise und müssen erst noch (mit
meinem Tool) umgewandelt werden.

Andreas

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.