SparkFun Forums 

Where electronics enthusiasts find answers.

Have questions about a SparkFun product or board? This is the place to be.
By mrtool
#60268
Random wrote:screen is designed for 2.8V and 5V is above what you really should use but works, 3.3V is a better match and will work fine.
Random wrote:Just to clarify, the comment about 5V refers to the input signals, I wouldn't want to try running the thing on 5V VCC. Your best bet is a 2.8V VCC and a logic level converter or a microchip running at 2.8V, but 3.3V works for VCC and 5V or below works for the input signals. The screen may be damaged over time by this, so if you can go for the closest to 2.8V.
Random wrote:the pins on that small LCD are numbered 1 to 33 going left to right with the screen facing you.

pin3 goes to the 3.3V on the arduino
pin 23 goes to CS which is arduino pin 10
pin 24 goes to MOSI which is arduino pin 11
pin 25 goes to SCK which is arduino pin 13
pin 31 and 32 go to ground
pin 27 is RESET and goes to 3.3V
pin 26 is dclk and goes to ground

you can check that you've got the pins the right way around as 31 and 32 will both be connected to the ground plane (continuous copper section) on the right hand side. the components on the flexible PCB should be facing upwards.
Random wrote: Heya,

I do have the sketch, this one makes a ball bounce around the screen some although it's pretty badly laid out - if you can't make sense of a part of it, just ask.
Code: Select all
#define INDEX 0x00
#define DATA 0x02
#define IDBYTE 0x74


unsigned short initcode[] = {
    0x00, 0x0001,

    0xFFFF, 20,

    0x08, 0x0303,
    0x02, 0x0500,
    0x01, 0x010B,
    0x0B, 0x4001,
    0x30, 0x0000,
    0x31, 0x0000,
    0x32, 0x0000,
    0x33, 0x0401,
    0x34, 0x0707,
    0x35, 0x0707,
    0x36, 0x0707,
    0x37, 0x0104,
    0x38, 0x0004,
    0x39, 0x0004,
    0x41, 0x0280,
    0x42, 0x8300,
    0x43, 0x9F9F,
    0x11, 0x0001,
    0x12, 0x0008,
    0x13, 0x100E,
    0x10, 0x0044,
    0x12, 0x0018,
    0x40, 0x0000,
    0x41, 0x0000,
    0x42, 0x5F00,

    0xFFFF, 40,

    0x13, 0x300C,

    0xFFFF, 60,

    0x10, 0x4340,

    0xFFFF, 100,

    0x21, 0x0004,
    0x44, 0x8304,
    0x45, 0x7F00,
    0x07, 0x0205,

    0xFFFF, 40,

    0x07, 0x0227,

    0xFFFF, 1,

    0x03, 0x1030,
    0x0D, 0x3336,
    0x07, 0x1237,

    0xFFFF, 0xFFFF,
};


void setup() {
  DDRB = (1<<PB3)|(1<<PB5)|(1<<PB2);
  SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0)|(0<<SPR1);
  SPSR = (1<<SPI2X);
}

void transmit( char data ) {
  SPDR = data;
  while(!(SPSR & (1<<SPIF))) ;
}

void write_reg( unsigned short index, unsigned short data ) {
    
    
   PORTB = PORTB & ~(1<<PB2);
   transmit(IDBYTE|INDEX);
   transmit(0x00);
   transmit(index);
   PORTB = PORTB | (1<<PB2);
   PORTB = PORTB & ~(1<<PB2);
   transmit(IDBYTE|DATA);
   transmit(data>>8);
   transmit(data);
   PORTB = PORTB | (1<<PB2);
}


void loop() {
  
      int i, x, y;
      long int pixel = 0;
      char out1, out2, pdata;
  
  for( i = 0;;i += 2 ) {
    if( initcode[i] == 0xFFFF && initcode[i+1] == 0xFFFF ) break;
    
    if( initcode[i] == 0xFFFF ) delay(initcode[i+1]);
    else write_reg( initcode[i], initcode[i+1] );
  }
  
  delay( 10 );
    
    write_reg(0x44, 0x7F00);
    write_reg(0x45, 0x5F00);
    
    write_reg(0x23, 0x0000);
    write_reg(0x24, 0x0000);
    write_reg(0x21, 0x0000);
    
    
      
    PORTB = PORTB & ~(1<<PB2);
    transmit( IDBYTE|INDEX );
    transmit( 0x00 );
    transmit( 0x22 );
    PORTB = PORTB | (1<<PB2);
    PORTB = PORTB & ~(1<<PB2);
    transmit( IDBYTE|DATA );
    int a,b,u,v,r,g,bl;
    a=50;
    b=30;
    u=3;
    v=2;
    randomSeed(analogRead(0));
    for(;;) {
      i=0;
      a+=u;
      b+=v;
          r=(int)random(0,32);
     g=(int)random(0,64);
     bl=(int)random(0,32);
     
            if( a<5 || a>121 ) u=-u;
      if( b<5 || b>89 ) v=-v;
    for( y = 0; y < 96; y++ ) {
      for( x = 0; x < 128; x++ ) {

      
      if( (x-a)*(x-a) + (y-b)*(y-b) < 49 ) {
        transmit((r<<3)|(g>>3));
        transmit((g<<5)|bl);
      } else {
        transmit(0);
        transmit(0);
      }
      }
    }
    }
    PORTB = PORTB | (1<<PB2);
  delay( 1000 );
  pinMode( 13, OUTPUT );
  digitalWrite( 13, HIGH );
  for(;;) {}
  pinMode( 13, OUTPUT );
  digitalWrite( 13, LOW );
}
Last edited by mrtool on Mon Dec 01, 2008 5:21 am, edited 1 time in total.
By Random
#60269
Just to clarify, the comment about 5V refers to the input signals, I wouldn't want to try running the thing on 5V VCC. Your best bet is a 2.8V VCC and a logic level converter or a microchip running at 2.8V, but 3.3V works for VCC and 5V or below works for the input signals. The screen may be damaged over time by this, so if you can go for the closest to 2.8V.
By mrtool
#60354
updated in case they don't read your comment
By asafpm
#62006
Is the code for the big screen or the small one? I tried it with the big one and couldn't get it to work yet.

I guess the code is for the small one. Could somebody give me some direction on where (in the code) to look to port it for the big screen?
By criznach
#62012
Yes, the code is for the small screen. I haven't actually tried the big one, but AFAIK, the big screen has no display memory of it's own - so using it is quite a bit harder.
By criznach
#62222
Here's a really terrible quality video of my progress with the small one...

http://www.youtube.com/watch?v=sENzSdIJjbQ

I've hooked up an ADXL330 accelerometer to control the bounce effect, and I do only partial screen updates. I've also switched to AVR GCC.
By mrtool
#63202
so any other people updating with this?
By criznach
#63213
Yeah, I posted some more source code and info for the small screen over the holidays, but my posts got caught by the spam filter, then never made it up here. So I'll have to find time to post it again some day.
By hellhammer
#65815
criznach, can you share your code? (is it the same as Random's or different?)

Also, can anyone point out how one is to solder the LCD to a PCB (one with appropriate pads)?
By criznach
#66083
hellhammer wrote:criznach, can you share your code? (is it the same as Random's or different?)

Also, can anyone point out how one is to solder the LCD to a PCB (one with appropriate pads)?
Below is my accelerometer controlled bouncing ball code. I'm using an adxl330. This is for an arduino, but using avr studio and without the boot loader. I did borrow a couple of pieces of code from the arduino sources.

I made a breakout board with .1" a header and soldered it by hand. It's pretty easy with an accurate PCB. Start by fluxing and tinning both the flexible connector and the PCB. A tiny amount of solder on each is plenty. Then apply more flux to both. Align the connector on the PCB so that a small amount of the tinned PCB traces are exposed and hold the display in place with tape. Then I used a straight screwdriver to push down a small amount of the flexible connector to contact the board, and applied just enough heat to the exposed PCB traces for the solder to flow. Work your way across with the heat and screwdriver.
Code: Select all
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>

#define INDEX 0x00
#define DATA 0x02
#define IDBYTE 0x74

// Coordinates of update rectangle
// Bouncing ball will be confined to this space
#define TOP 0
#define LEFT 0
#define BOTTOM 96
#define RIGHT 128
#define PITCH 256 // Width of the full display in unsigned chars
#define WIDTH (RIGHT-LEFT)
#define HEIGHT (BOTTOM-TOP)

#define ROLL_DAMP 0.995f
#define BOUNCE_DAMP 0.75f
#define ACCEL_SCALE 20.0f
#define MINACCEL 30.0f
#define MINSPEED 0.001f

#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// Ball size
#define RADIUS 16
#define RADIUS_SQUARED (RADIUS * RADIUS)
// Distance from center of ball to it's bounce
#define PADDING (RADIUS)

void lcd_setup();
void lcd_transmit( uint8_t data );
void lcd_write_reg( unsigned short index, unsigned short data );
void lcd_clear_black(void);
void update_ball(void);
void timer_setup(void);
unsigned long millis(void);
float mirror(float coord, float axis, float dampen);
void adc_init(void);      //Initializes converter and interrupt
void increment_adc_port(void);

#define FIRST_ADC_PORT 0
#define LAST_ADC_PORT 2
#define ADC_COUNT (LAST_ADC_PORT - FIRST_ADC_PORT + 1)

volatile uint8_t g_adc_port = FIRST_ADC_PORT;
volatile uint16_t g_adc[ADC_COUNT];

uint16_t g_x_avg;
uint16_t g_y_avg;

float x;
float y;
float x_last;
float y_last;
float dt;
float dt_last;
float dt_scalar;
float a_x;
float a_y;
float t_last;

volatile unsigned long timer0_clock_cycles = 0;
volatile unsigned long timer0_millis = 0;

unsigned short initcode[] PROGMEM = {
    
    // Oscillator start instruction
    0x00, 0x0001,

    // Pause
    0xFFFF, 20,
    
    // Front & back porch of 3 pixels
    0x08, 0x0303,
    
    // EOR = 1
    // 1 field
    0x02, 0x0500,
    
    // Set scan mode
    // Set 96 raster rows
    0x01, 0x010B,
    
    // Set frame cycle control
    // 4 clocks gate output time
    // 17 clocks raster row
    0x0B, 0x4001,
    
    // Gamma gradient adjustments. 
    0x30, 0x0000,
    0x31, 0x0000,
    0x32, 0x0000,
    0x33, 0x0401,
    0x34, 0x0707,
    0x35, 0x0707,
    0x36, 0x0707,
    0x37, 0x0104,
    0x38, 0x0004,
    0x39, 0x0004,
    
    // Vertical scroll control
    0x41, 0x0280,
    
    // 1st-Screen Drive Position (R42h)    
    0x42, 0x8300,
    // 2nd-Screen Drive Position (R43h)
    0x43, 0x9F9F,
    
    // Power control 2
    0x11, 0x0001,
    
    // Power control 3
    0x12, 0x0008,
    
    // Power control 4
    0x13, 0x100E,
    
    // Power control 1
    0x10, 0x0044,

    // Power control 3
    0x12, 0x0018,

    // Gate scan position
    0x40, 0x0000,

    // Vertical scroll control
    0x41, 0x0000,

    // 1st-Screen Drive Position (R42h)    
    0x42, 0x5F00,

    // Pause
    0xFFFF, 40,

    // Power control 4
    0x13, 0x300C,

    // Pause
    0xFFFF, 60,

    // Power control 1
    0x10, 0x4340,

    // Pause
    0xFFFF, 100,
    
    // Display control
    // Reverse display???
    0x07, 0x0205,

    0xFFFF, 40,

    0x07, 0x0227,

    0xFFFF, 1,

    // Entry mode
    // Set address auto-increment starting at top left
    // Physical display is 666 18 bit BGR?
    0x03, 0x1030,
    
    0x0D, 0x3336,
    0x07, 0x1237,

    // End of init
    0xFFFF, 0xFFFF,
};


void lcd_setup() {
  int i;

  // Configure arduino pins for SPI
  DDRB = (1<<PB3)|(1<<PB5)|(1<<PB2);
  SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0)|(0<<SPR1);
  SPSR = (1<<SPI2X);

  // Send init array defined above
  for( i = 0;;i += 2 ) {
    if( pgm_read_word(&initcode[i]) == 0xFFFF && pgm_read_word(&initcode[i+1]) == 0xFFFF ) break;
   
    if( pgm_read_word(&initcode[i]) == 0xFFFF ) _delay_ms(pgm_read_word(&initcode[i+1]));
    else lcd_write_reg( pgm_read_word(&initcode[i]), pgm_read_word(&initcode[i+1]) );
  }
 
  // Pause 10ms per the datasheet
  _delay_ms( 10 );
}

int main() {
  
  int xp, yp;

  long frames = 0;

  dt_last = 0.0;
  t_last = 0.0;
  dt = 0;
  
  a_x = 0;
  a_y = 0;

  x = (RIGHT-LEFT)/2;
  y = (BOTTOM-TOP)/2;
  x_last = x;
  y_last = y;

  timer_setup();

  adc_init();

  lcd_setup();

  lcd_clear_black();

  // Allow the ADC to get some samples
  _delay_ms(100);

  g_x_avg = g_adc[0];
  g_y_avg = g_adc[1];
   
  for(int i = 0; i < 10; i++) {
    g_x_avg = (float)g_x_avg * 0.9f + (float)g_adc[0] * 0.1f;
    g_y_avg = (float)g_y_avg * 0.9f + (float)g_adc[1] * 0.1f;
    _delay_ms(10);
  }

  t_last = (float)millis() / 1000;

  for(;;) {

    float t;
  
    t = (float)millis() / 1000;
  
    dt = t - t_last;
  
    if (dt_last == 0)
    {
      dt_scalar = 1;
    } else {
      dt_scalar = dt / dt_last;
    }
  
    a_x = ((float)g_x_avg - (float)g_adc[0]) * ACCEL_SCALE;
    a_y = ((float)g_y_avg - (float)g_adc[1]) * ACCEL_SCALE;

    if (a_x < MINACCEL && a_x > -MINACCEL) a_x = 0;
    if (a_y < MINACCEL && a_y > -MINACCEL) a_y = 0;

    update_ball();

    int ix = x;
    int iy = y;

    // Reverse direction at the edges with a buffer of PADDING pixels
    if( ix < LEFT + PADDING ) {
      x = mirror(x, LEFT + PADDING, BOUNCE_DAMP);
      x_last = mirror(x_last, LEFT + PADDING, BOUNCE_DAMP);
      ix = x;
    } else if (ix > RIGHT - PADDING ) {
      x = mirror(x, RIGHT - PADDING, BOUNCE_DAMP);
      x_last = mirror(x_last, RIGHT - PADDING, BOUNCE_DAMP);
      ix = x;
    }

    if( iy < TOP + PADDING ) {
      y = mirror(y, TOP + PADDING, BOUNCE_DAMP);
      y_last = mirror(y_last, TOP + PADDING, BOUNCE_DAMP);
      iy = y;
    } else if (iy > BOTTOM - PADDING ) {
      y = mirror(y, BOTTOM - PADDING, BOUNCE_DAMP);
      y_last = mirror(y_last, BOTTOM - PADDING, BOUNCE_DAMP);
      iy = y;
    }

    // Dampen any movement less than MINSPEED
    if( (x-x_last)*(x-x_last) + (y-y_last)*(y-y_last) < (MINSPEED * MINSPEED)) {
      x_last = x;
      y_last = y;
    }

    int ix_last = x_last;
    int iy_last = y_last;

    // Calculate the update rectangle
    int b_top, b_left, b_bottom, b_right;

    if (x > x_last) {
      // Ball moving right
      b_left = ix_last - PADDING;
      b_right = ix + PADDING;
    } else {
      // Ball moving left
      b_left = (ix - PADDING);
      b_right = ix_last + PADDING;
    }

    if (y > y_last) {
      // Ball moving down
      b_top = iy_last - PADDING;
      b_bottom = iy + PADDING;
    } else {
      // Ball moving up
      b_top = iy - PADDING;
      b_bottom = iy_last + PADDING;
    }

    // Set the horizontal display range that will be sent below
    lcd_write_reg(0x44, (b_right << 8) | b_left);

    // Set the vertical display range that will be sent below
    lcd_write_reg(0x45, (b_bottom << 8) | b_top);
 
    // Clear the RAM write data mask - all bits will be set
    // Determines what bits are committed to display RAM
    // The format is as follows...
    // xxGGGGGGxxBBBBBB
    // xxxxxxxxxxRRRRRR
    lcd_write_reg(0x23, 0b0000000000000000);
    lcd_write_reg(0x24, 0b0000000000000000);

    // Ram address set
    // These are 16 bit pixels, so I'm 
    // not sure why adding LEFT * 2 doesn't work
    lcd_write_reg(0x21, (b_top * PITCH + b_left));
   
    // Initiate a full-frame transfer by sending the first part of the write data command
    PORTB = PORTB & ~(1<<PB2);
    lcd_transmit( IDBYTE|INDEX );
    lcd_transmit( 0x00 );
    lcd_transmit( 0x22 );
    PORTB = PORTB | (1<<PB2);
    PORTB = PORTB & ~(1<<PB2);
    lcd_transmit( IDBYTE|DATA );

    for( yp = b_top; yp <= b_bottom; yp++ ) {
      for( xp = b_left; xp <= b_right; xp++ ) {

        // Is this pixel closer than RADIUS to the ball?
        if( (xp-ix)*(xp-ix) + (yp-iy)*(yp-iy) < (RADIUS_SQUARED)) {

          // Color bits seem to be as follows:
          // 0baRRRRaGG
          // 0bGGGaBBBB
          // 
          // I believe the a bits are alpha, but I don't think this
          // works in fast-write mode - so the a bits should be zero here 
          
          // Send ball color pixel
          lcd_transmit(0b01111000);
          lcd_transmit(0b00001111);
        } else {

          // Spiffy checkered background
          if (((xp >> 3) + (yp >> 3)) & 1) {
            // Send background color pixel
            lcd_transmit(0b00000000);
            lcd_transmit(0b00000000);
          } else {
            lcd_transmit(0b00000000);
            lcd_transmit(0b01100000);
          }
        }

      } // for xp
    } // for yp
    
    // Signal the end of this transmission
    PORTB = PORTB | (1<<PB2);

    t_last = t;
    dt_last = dt;

    frames++;

  } // forever
} 

// Send a byte
void lcd_transmit( uint8_t data ) {
  SPDR = data;
  while(!(SPSR & (1<<SPIF))) ;
}

// Parameters:
// index - register index from datasheet
// data  - data byte to put in the register
void lcd_write_reg( unsigned short index, unsigned short data ) {
   PORTB = PORTB & ~(1<<PB2);
   lcd_transmit(IDBYTE|INDEX);
   lcd_transmit(0x00);
   lcd_transmit(index);
   PORTB = PORTB | (1<<PB2);
   PORTB = PORTB & ~(1<<PB2);
   lcd_transmit(IDBYTE|DATA);
   lcd_transmit(data>>8);
   lcd_transmit(data);
   PORTB = PORTB | (1<<PB2);
}

// Use fast write mode to clear the screen with black pixels
// There might be a better way in hardware
void lcd_clear_black(void) {
  int x;
  int y;
  
  // Set the horizontal display range that will be sent below
  lcd_write_reg(0x44, (127 << 8) | 0);

  // Set the vertical display range that will be sent below
  lcd_write_reg(0x45, (95 << 8) | 0);
 
  // Clear the RAM write data mask - all bits will be set
  lcd_write_reg(0x23, 0x0000);
  lcd_write_reg(0x24, 0x0000);

  // Ram address set
  lcd_write_reg(0x21, 0x0000);
   
  // Initiate a full-frame transfer by sending the first part of the write data command
  PORTB = PORTB & ~(1<<PB2);
  lcd_transmit( IDBYTE|INDEX );
  lcd_transmit( 0x00 );
  lcd_transmit( 0x22 );
  PORTB = PORTB | (1<<PB2);
  PORTB = PORTB & ~(1<<PB2);
  lcd_transmit( IDBYTE|DATA );
    
  for( y = 0; y < 96; y++ ) {
    for( x = 0; x < 128; x++ ) {
      if (((x >> 3) + (y >> 3)) & 1) {
        // Send background color pixel
        lcd_transmit(0b00000000);
        lcd_transmit(0b00000000);
      } else {
        lcd_transmit(0b00000000);
        lcd_transmit(0b01100000);
      }
    } // for x
  } // for y
  // Signal the end of this transmission
  PORTB = PORTB | (1<<PB2);
}

void update_ball(void) {  
  float x_next;
  float y_next;

  // time-corrected verlet 
  x_next = x + ((x - x_last) * dt_scalar + a_x * dt * dt) * ROLL_DAMP;
  y_next = y + ((y - y_last) * dt_scalar + a_y * dt * dt) * ROLL_DAMP;

  y_last = y;
  x_last = x;

  x = x_next;
  y = y_next;
}

void timer_setup(void) {
	sei();
	
	// on the ATmega168, timer 0 is also used for fast hardware pwm
	// (using phase-correct PWM would mean that timer 0 overflowed half as often
	// resulting in different millis() behavior on the ATmega8 and ATmega168)
#if defined(__AVR_ATmega168__)
	sbi(TCCR0A, WGM01);
	sbi(TCCR0A, WGM00);
#endif  
	// set timer 0 prescale factor to 64
#if defined(__AVR_ATmega168__)
	sbi(TCCR0B, CS01);
	sbi(TCCR0B, CS00);
#else
	sbi(TCCR0, CS01);
	sbi(TCCR0, CS00);
#endif
	// enable timer 0 overflow interrupt
#if defined(__AVR_ATmega168__)
	sbi(TIMSK0, TOIE0);
#else
	sbi(TIMSK, TOIE0);
#endif
}

SIGNAL(SIG_OVERFLOW0)
{
	// timer 0 prescale factor is 64 and the timer overflows at 256
	timer0_clock_cycles += 64UL * 256UL;
	while (timer0_clock_cycles > clockCyclesPerMicrosecond() * 1000UL) {
		timer0_clock_cycles -= clockCyclesPerMicrosecond() * 1000UL;
		timer0_millis++;
	}
}

unsigned long millis(void)
{
	unsigned long m;
	uint8_t oldSREG = SREG;
	
	// disable interrupts while we read timer0_millis or we might get an
	// inconsistent value (e.g. in the middle of the timer0_millis++)
	cli();
	m = timer0_millis;
	SREG = oldSREG;
	
	return m;
}

float mirror(float coord, float axis, float dampen) {
  return axis + (axis - coord) * dampen;
}

void adc_init(void) {
	// Sampling frequency prescaler
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); 

	// Set reference voltage 
  ADMUX |= (1 << REFS0);   

  // Disable auto trigger
  ADCSRA &=~ (1 << ADATE); 

  // Select our initial input channel
  ADMUX |= FIRST_ADC_PORT; 

	// Enable ADC
	PRR &=~ (1 << PRADC);
	ADCSRA |= (1 << ADEN);

	// Enable interrupts
	ADCSRA |= (1 << ADIE);
		
	// Start sampling
	ADCSRA |= (1 << ADSC);  
}

void increment_adc_port(void)
{
	if (g_adc_port >= LAST_ADC_PORT) {
		g_adc_port = FIRST_ADC_PORT;
	} 
	else {
		g_adc_port++;
	}
}

ISR(ADC_vect)
{
  // Code to be executed when ISR fires

  // Grab the current value
	g_adc[g_adc_port] = ADCL;
	g_adc[g_adc_port] |= ADCH << 8;

	// switch to next channel
    increment_adc_port();
    ADMUX &=~ 0b00001111;   
    ADMUX |= (1 << REFS0); 
    ADMUX |= (uint8_t)g_adc_port;

	// Disable ADC
 	ADCSRA &=~ (1 << ADEN);
	// Enable ADC
	PRR &=~ (1 << PRADC);
	ADCSRA |= (1 << ADEN);

	// Resume sampling
	ADCSRA |= (1 << ADSC);  
}

By mcarey42
#130132
Hello! I'm hoping this doesn't violate the non-commercial aspect of this forum, but I bought 150 of these assemblies in 2007 and they've been sitting in my basement since. I've posted them on e-bay for any who are interested.

I'm not trying to get much out of them, I just want them to go to a happy home where they will be used and loved :-).

http://cgi.ebay.com/ws/eBayISAPI.dll?Vi ... 500wt_1156

Moderators, if this is a violation please forgive me. I know you aren't selling these anymore and figured there would be no harm in letting folks know they are available.
By DeniTCH
#138315
Hi, I know it is quite a while anyone has looked at these displays, but I am currently working with one of the QVGA ones for a university project and I have ran into trouble getting it to work.

I am implementing the display driver on a Xilinx Virtex-2 Pro FPGA development board. I am able to generate the needed signals including the SPI initialization sequence from Mikes site. However it seems to me that my timing (somehow) is wrong anyway. I have triedto follow the datasheet but I think it is a bit fuzzy on when exactly to start sending timing after the initialization sequence and the front- and backporch timings for the VSYNC and HSYNC signals. I try to drive the display in the following way:

1. Hold LCD_RESET low for 30ms, HSYNC, VSYNC kept high, DE kept low
2. Pull LCD_RESET high and wait for 30ms
4. Start the DOTCLOCK (5MHz) and the VSYNC and HSYNC signals
3. Send the 4 first initialization commands over SPI (Running at 3.33MHz)
4. Send the next 2 initialization commands
5. Wait 30ms
6. Send the rest of the initialization commands
7. Keep on driving the display with the RED color output to the data outputs and providing the DOTCLOCK, VSYNC, HSYNC and DE signals with the following timing:

Start of the frame:
VSYNC and HSYNC low at the same time, (DE kept high during the VSYNC period and its backporch which is 2 frames), HSYNC low for 3 DOTCLOCK cycles, VSYNC low for 324 lines. Each line is 256 DOTCLOCK cycles (3(HSYNC low) + 240 (px data) + 12 (hsync front porch))

During the normal data transfer:
HSYNC low for 3 DOTCLOCK cycles. DE low 1 cycle after the HSYNC high again. Wait for 240 clocks for pixel transfer, DE high. Wait 12 cycles for hsync front porch. Repeat process.

The display blinks between black and gray colors (so I assume that the initialization works), however no colors are displayed. As soon as I remove one (or more) of the DOTCLOCK, DE, or HSYNC, VSYNC lines, the displayed is filled with the color I am sending to it, as soon as i asser the line again, it starts blinking.

What am I doing wrong?

I will be very greatful for any suggestions or hints in the right direction. (Some of you folks have had much better results than me according to the pictures)

Best regards
Denis
  • 1
  • 3
  • 4
  • 5
  • 6
  • 7