Moin.

Bin gerade dabei, einige Routinen in Eigenarbeit für ein LCD (128x64, Klassiker von Pollin mit KS0108-kompatiblem Controller) zu erstellen.
Es gibt zwar schon ein paar fertige Routinen, nur möcht ich das ganze selbst von Grund auf erstellen, um genau zu wissen, was ich da eigentlich mach.

Im Anhang ist der bisherige Stand.
Das Testprogramm in der main.c soll vom Prinzip her das gleiche machen, wie die Funktion TG12864B_Fill(), nur dass eben jedes Pixel gezielt angesprochen werden kann.
Problem ist nun hier, dass die Fläche nach dem Test nicht durchgehend weiss ist, sondern am linken Rand jedes "Treibers" dieses Muster hier aufweist:

Bild hier  

Wobei dieses "Muster" erst während des Aufbaus entsteht; d.h. die erste Zeile wird durchgehend gesetzt. Sobald die 2. Zeile beginnt, wird das erste Pixel wieder gelöscht. Beginnt die 3. Zeile, rutscht das gelöschte Pixel aus der ersten Zeile eins weiter ... usw, bis am Ende eben dieses Muster entsteht.
Der Fehler müsste entweder irgendwo in ~_SetPixel() oder ~_Goto() sein. Nur seh ich ihn nicht. Evtl jemand von euch?

Hier die Codes:
main.c
Code:
int main (void)
{
  ui8_t x=0;
  ui8_t y=0;

  TG12864B_Init();
  for (y = 0; y < 64  ; y++)
  for (x = 0; x < 128 ; x++)
  {
    {
      TG12864B_SetPixel(x,y,1);
//      _delay_ms(100);
    }
  }
  while(1)
  {
  
  }
  return(0);
}
tg12864b.c
Code:
#include "tg12864b.h"

stc_DisplayPosition DPos;
volatile ui8_t readdata = 0;


static inline void _delay4Cycles(ui16_t __count)
{
  if (__count == 0)
  {
    __asm__ __volatile__("rjmp 1f\n 1:");
  }
  else
  {
    __asm__ __volatile__ (
      "1: sbiw %0,1" "\n\t"
      "brne 1b"
      : "=w" (__count)
      : "0" (__count)
      );
  }
}

#define delay(us) _delay4Cycles(((F_CPU / 4000)*us)/1000)

void TG12864B_Init(void)
{
  // Prepare Timer 0, PWM Channel B
  //TCCR0A  = (1 << WGM00) | (1 << COM0B1);
  //TCCR0B = (1 << CS00) | (1 << CS01);
  //OCR0B = 0;

  // Set Ports & Pins as Output
  TG12864B_DATA_PORT = 0x00;
  TG12864B_DATA_DDR = 0xFF;
//  TG12864B_LIGHT_DDR |= (1 << TG12864B_LIGHT_PIN);
  TG12864B_EN_PORT &=~ (1 << TG12864B_EN_PIN);
  TG12864B_EN_DDR  |=  (1 << TG12864B_EN_PIN);
  TG12864B_RW_PORT &=~ (1 << TG12864B_RW_PIN);
  TG12864B_RW_DDR  |=  (1 << TG12864B_RW_PIN);
  TG12864B_DI_PORT &=~ (1 << TG12864B_DI_PIN);
  TG12864B_DI_DDR  |=  (1 << TG12864B_DI_PIN);
  TG12864B_CS1_PORT &=~ (1 << TG12864B_CS1_PIN);
  TG12864B_CS1_DDR  |=  (1 << TG12864B_CS1_PIN);
  TG12864B_CS2_PORT &=~ (1 << TG12864B_CS2_PIN);
  TG12864B_CS2_DDR  |=  (1 << TG12864B_CS2_PIN);
  TG12864B_RST_PORT &=~ (1 << TG12864B_RST_PIN);
  TG12864B_RST_DDR  |=  (1 << TG12864B_RST_PIN);

  _delay_ms(10);
  TG12864B_RST_PORT |= (1 << TG12864B_RST_PIN);
  _delay_ms(10);


  // Send commands for init
  DPos.x = 0;
  DPos.y = 0;
  DPos.page = 0;
  DPos.addr = 0;
  DPos.driver = 0;
  DPos.rel_y = 0;
  TG12864B_SendCmd(TG12864B_ON, 1);          // Power on both drivers
  TG12864B_SendCmd(TG12864B_ON, 2);          // Power on both drivers
  TG12864B_SendCmd(TG12864B_DISP_START, 1);  // Display start line = 0
  TG12864B_SendCmd(TG12864B_DISP_START, 2);  // Display start line = 0
  TG12864B_Fill(0x00);
}

void TG12864B_SendCmd(ui8_t cmd, ui8_t driver)
{
  switch(driver)
  {
    case 1:
    TG12864B_CS2_PORT &=~ (1 << TG12864B_CS2_PIN);  // Driver 2 Off
    TG12864B_CS1_PORT |=  (1 << TG12864B_CS1_PIN);  // Driver 1 On
    break;
    case 2:
    TG12864B_CS2_PORT |=  (1 << TG12864B_CS2_PIN);  // Driver 2 On
    TG12864B_CS1_PORT &=~ (1 << TG12864B_CS1_PIN);  // Driver 1 Off
    break;
    case 3:
    TG12864B_CS1_PORT |=  (1 << TG12864B_CS1_PIN);  // Driver 1 On
    TG12864B_CS2_PORT |=  (1 << TG12864B_CS2_PIN);  // Driver 2 On 
    break;
    default:
    TG12864B_CS1_PORT &=~ (1 << TG12864B_CS1_PIN);  // Driver 1 Off
    TG12864B_CS2_PORT &=~ (1 << TG12864B_CS2_PIN);  // Driver 2 Off
    break;
  }
  TG12864B_DI_PORT &=~ (1 << TG12864B_DI_PIN);  // D/I = 0 = Instruction
  TG12864B_RW_PORT &=~ (1 << TG12864B_RW_PIN);  // R/W = 0 = Write   
  TG12864B_DATA_DDR = 0xFF;   // Port = Output
  TG12864B_DATA_PORT = cmd;   // Set data
  TG12864B_EN_Pulse();        // Enable Clock
  TG12864B_DATA_PORT = 0x00;  // Reset data port
}

void TG12864B_EN_Pulse(void)
{
  TG12864B_EN_PORT |=  (1 << TG12864B_EN_PIN);
  delay(4);
  TG12864B_EN_PORT &=~ (1 << TG12864B_EN_PIN);
  delay(4);
}

void TG12864B_Fill(ui8_t pattern)
{
  ui8_t add;
  ui8_t page;
  for (page = 0; page < 8 ; page++)
  {
    for (add = 0 ; add < 64 ; add++)
    {
      TG12864B_SendCmd(TG12864B_SET_ADD | add, 3);
      TG12864B_SendCmd(TG12864B_SET_PAGE | page, 3);
      TG12864B_SendDataRaw(pattern,3);
    }
  }
}

void TG12864B_SendDataRaw(ui8_t data, ui8_t driver)
{
  switch(driver)
  {
    case 1:
    TG12864B_CS2_PORT &=~ (1 << TG12864B_CS2_PIN);  // Driver 2 Off
    TG12864B_CS1_PORT |=  (1 << TG12864B_CS1_PIN);  // Driver 1 On
    break;
    case 2:
    TG12864B_CS2_PORT |=  (1 << TG12864B_CS2_PIN);  // Driver 2 On
    TG12864B_CS1_PORT &=~ (1 << TG12864B_CS1_PIN);  // Driver 1 Off
    break;
    case 3:
    TG12864B_CS1_PORT |=  (1 << TG12864B_CS1_PIN);  // Driver 1 On
    TG12864B_CS2_PORT |=  (1 << TG12864B_CS2_PIN);  // Driver 2 On 
    break;
    default:
    TG12864B_CS1_PORT &=~ (1 << TG12864B_CS1_PIN);  // Driver 1 Off
    TG12864B_CS2_PORT &=~ (1 << TG12864B_CS2_PIN);  // Driver 2 Off
    break;
  }
  TG12864B_DI_PORT |=  (1 << TG12864B_DI_PIN);  // D/I = 1 = Data
  TG12864B_RW_PORT &=~ (1 << TG12864B_RW_PIN);  // R/W = 0 = Write   
  TG12864B_DATA_DDR = 0xFF;   // Port = Output
  TG12864B_DATA_PORT = data;   // Set data
  TG12864B_EN_Pulse();        // Enable Clock
  TG12864B_DATA_PORT = 0x00;  // Reset data port

}

void TG12864B_Goto(ui8_t x, ui8_t y)
{
  DPos.x = x;
  DPos.y = y;

  // Check: coordinates are valid
  if (x > 127) { x = 127; }
  if (y > 63)  { y = 63;  }
  
  // Calculate Coordinates:
  // Get driver nr. & relative x coordinate (= address)
  if  ( x >= 128) 
  { 
    return;
  }

  if ( x <  64 )
  { 
    DPos.driver = 1;
    DPos.addr = x;
  }
  
  if (( x >=  64 ) && ( x < 128 )) 
  { 
    DPos.driver = 2; 
    DPos.addr = x - 64;
  }

  // Get Page:
  /*
  if               (y <  8)  {DPos.page = 0;}
  if ((y >=  8) && (y < 16)) {DPos.page = 1;}
  if ((y >= 16) && (y < 24)) {DPos.page = 2;}
  if ((y >= 24) && (y < 32)) {DPos.page = 3;}
  if ((y >= 32) && (y < 40)) {DPos.page = 4;}
  if ((y >= 40) && (y < 48)) {DPos.page = 5;}
  if ((y >= 48) && (y < 56)) {DPos.page = 6;}
  if ((y >= 56) && (y < 64)) {DPos.page = 7;}
  */
  DPos.page = floor(y / 8);
  DPos.rel_y = (y-DPos.page*8);
  //DPos.rel_y = y & 8;
}

ui8_t TG12864B_ReadData(void)
{
  ui8_t data;
  TG12864B_DATA_PORT = 0x00;  // Data = 0
  TG12864B_DATA_DDR = 0x00;   // Data = Input

  if (DPos.driver == 1)
  {
    TG12864B_CS2_PORT &=~ (1 << TG12864B_CS2_PIN);  // Driver 2 Off
    TG12864B_CS1_PORT |=  (1 << TG12864B_CS1_PIN);  // Driver 1 On
  }
  if (DPos.driver == 2)
  {
    TG12864B_CS1_PORT &=~ (1 << TG12864B_CS1_PIN);  // Driver 1 Off
    TG12864B_CS2_PORT |=  (1 << TG12864B_CS2_PIN);  // Driver 2 On 
  }

  TG12864B_DI_PORT |=  (1 << TG12864B_DI_PIN);  // D/I = 1 = Data       
  TG12864B_RW_PORT |=  (1 << TG12864B_RW_PIN);  // R/W = 1 = Read    

  TG12864B_EN_PORT |=  (1 << TG12864B_EN_PIN);
  delay(10);
  data = TG12864B_DATA_INPUT;
  delay(10);
  TG12864B_EN_PORT &=~ (1 << TG12864B_EN_PIN);
  delay(10);
  TG12864B_DATA_DDR = 0xFF;   // Data = Output
  return (data);
}

void TG12864B_SetPixel(ui8_t x, ui8_t y, ui8_t value)
{
  TG12864B_Goto(x, y);
  TG12864B_SendCmd(TG12864B_SET_ADD | DPos.addr, DPos.driver);
  TG12864B_SendCmd(TG12864B_SET_PAGE | DPos.page, DPos.driver);
  readdata = TG12864B_ReadData();
  if (value == 0)
  {
    readdata &=~ (1 << DPos.rel_y);
  }
  else
  {
    readdata |= (1 << DPos.rel_y);
  }
  TG12864B_SendCmd(TG12864B_SET_ADD | DPos.addr, DPos.driver);
  TG12864B_SendCmd(TG12864B_SET_PAGE | DPos.page, DPos.driver);
  TG12864B_SendDataRaw(readdata, DPos.driver)  ;
  
}
tg12864b.h
Code:
#ifndef _TG12864B_H_
#define _TG12864B_H_

#include <math.h>
#include <avr/io.h>
#include <util/delay.h>
#include "glob_defs.h"
#include "glob_type.h"

#define TG12864B_DATA_PORT     PORTA
#define TG12864B_DATA_DDR      DDRA
#define TG12864B_DATA_INPUT    PINA

#define TG12864B_EN_PORT       PORTD
#define TG12864B_EN_DDR        DDRD
#define TG12864B_EN_PIN        4

#define TG12864B_RW_PORT       PORTD
#define TG12864B_RW_DDR        DDRD
#define TG12864B_RW_PIN        5

#define TG12864B_DI_PORT       PORTD
#define TG12864B_DI_DDR        DDRD
#define TG12864B_DI_PIN        6

#define TG12864B_CS1_PORT      PORTB
#define TG12864B_CS1_DDR       DDRB
#define TG12864B_CS1_PIN       2

#define TG12864B_CS2_PORT      PORTB
#define TG12864B_CS2_DDR       DDRB
#define TG12864B_CS2_PIN       3

#define TG12864B_RST_PORT      PORTD
#define TG12864B_RST_DDR       DDRD
#define TG12864B_RST_PIN       3

// Commands
#define TG12864B_ON				    0x3F
#define TG12864B_OFF				  0x3E
#define TG12864B_SET_ADD			0x40
#define TG12864B_SET_PAGE		  0xB8
#define TG12864B_DISP_START		0xC0
#define INCREMENT_X			         0
#define NO_INCREMENT_X		       1



void TG12864B_Init(void);
void TG12864B_SendCmd(ui8_t cmd, ui8_t driver);
void TG12864B_SendDataRaw(ui8_t data, ui8_t driver);
void TG12864B_EN_Pulse(void);
void TG12864B_Fill(ui8_t pattern);
void TG12864B_Goto(ui8_t x, ui8_t y);
ui8_t TG12864B_ReadData(void);
void TG12864B_SetPixel(ui8_t x, ui8_t y, ui8_t value);


typedef struct {
	ui8_t x;
	ui8_t y;
	ui8_t driver;
  ui8_t addr;
  ui8_t page;
  ui8_t rel_y;
} stc_DisplayPosition;


#endif
mfG