[*** Just copy the following into a text editor and save as a60-lcd.c then
build by typing make a60-lcd from a terminal: ***]


#include <stdio.h>
#include <stdlib.h>
#include <linux/ioctl.h>
#include <linux/parport.h>
#include <linux/ppdev.h>
#include <fcntl.h>
#include <time.h>

int fd;
int data = 0x7f;

/*
* Linux tester for Siemens A60 LCD (A65, M55, C60, MC60, S55, etc)
*
* Connect signals to parallel port via ~10K resistors thus: -
*
* Parallel Port            A60-LCD
*   2   D0     <--10K->     1  CS
*   3   D1     <--10K->     2  Reset
*   4   D2     <--10K->     3  RS
*   5   D3     <--10K->     4  SCL
*   6   D4     <--10K->     5  SDA
*   7   D5     <-620R->     6  +2.9V *and* 8 A1
*   8   D6     <-620R->    10  A2
*  25   GND    <------>     7  GND   *and* 9 K
*
* LCD pad 1 is nearest the edge of the frame, pad 10 is nearest the
* middle of the assembly.
*
* By coincidence, Vf of the backlight LEDs is approx 2.9V, thus
* one can be used as a simple shunt regulator for the LCD supply.
*
* Remember, the series resistor limits the current in the shunt.
* The series resistors in the signal lines limit the current in
* the LCD's clamp diodes. Adjust values as necessary to suit the
* specific parallel port.
*
* Make sure you have your distro's ppdev package installed.
*/

void Send (X)
{
   int mask;

   /* clock a byte out serially to the LCD */

   for (mask = 0x80; mask; mask >>= 1)
   //for (mask = 0x01; mask & 0x100; mask <<= 1)
   {
       if (mask & X)
           data |= 0x10;
       else
           data &= ~0x10;
       data &= ~0x08;
       ioctl (fd, PPWDATA, &data);
       //ioctl (fd, PPWDATA, &data);

       data |= 0x08;
       ioctl (fd, PPWDATA, &data);
       //ioctl (fd, PPWDATA, &data);
   }
}

void Initialise (void)
{
   int i, flag;
   int Sequence [] =
   {
       0xf4, 0x90, 0xb3, 0xa0, 0xd0, -1,
       0xf0, 0xe2, 0xd4, 0x70, 0x66, 0xb2, 0xba, 0xa1, 0xa3, 0xab,
           0x94, 0x95, 0x95, 0x95, -1,
       0xf5, 0x90, -1,
       0xf1, 0x00, 0x10, 0x22, 0x30, 0x45, 0x50, 0x68, 0x70, 0x8a,
           0x90, 0xac, 0xb0, 0xce, 0xd0, -1,
       0xf2, 0x0f, 0x10, 0x20, 0x30, 0x43, 0x50, 0x66, 0x70, 0x89,
           0x90, 0xab, 0xb0, 0xcd, 0xd0, -1,
       0xf3, 0x0e, 0x10, 0x2f, 0x30, 0x40, 0x50, 0x64, 0x70, 0x87,
           0x90, 0xaa, 0xb0, 0xcb, 0xd0, -1,
       0xf4, 0x0d, 0x10, 0x2e, 0x30, 0x4f, 0x50, -1,
       0xf5, 0x91, -1,
       0xf1, 0x01, 0x11, 0x22, 0x31, 0x43, 0x51, 0x64, 0x71, 0x86,
           0x91, 0xa8, 0xb1, 0xcb, 0xd1, -1,
       0xf2, 0x0f, 0x11, 0x21, 0x31, 0x42, 0x51, 0x63, 0x71, 0x85,
           0x91, 0xa6, 0xb1, 0xc8, 0xd1, -1,
       0xf3, 0x0b, 0x11, 0x2f, 0x31, 0x41, 0x51, 0x62, 0x71, 0x83,
           0x91, 0xa4, 0xb1, 0xc6, 0xd1, -1,
       0xf4, 0x08, 0x11, 0x2b, 0x31, 0x4f, 0x51, -1,
       0x80, 0x94, -1,
       0xf5, 0xa2, -1,
       0xf4, 0x60, -1,
       0xf0, 0x40, 0x50, 0xc0, -1,
       0xf4, 0x70, -1, -1,
       0xf0, 0x81, -1,
       0xf4, 0xb3, 0xa0, -1,
       0xf0, 0x00 | 0x6, 0x10, 0x20, 0x30, -1,
       0xf5, 0x00 | 0xf, 0x10 | 0xc, 0x20 | 0xf, 0x30 | 0x4, -1,
       -1, -1
   };

   /* power off */
   data = 0;
   ioctl (fd, PPWDATA, &data);
   usleep (500000);

   /* power on, reset */
   data = 0x7d;
   ioctl (fd, PPWDATA, &data);
   usleep (10000);

   /* reset off */
   data |= 0x02;
   ioctl (fd, PPWDATA, &data);
   usleep (10000);

   /* send commands */
   i = 0;
   data &= ~0x01;
   data |=  0x04;
   ioctl (fd, PPWDATA, &data);

   flag = 1;
   do
   {
       Send (Sequence [i++]);

       if (Sequence [i] == -1)
       {
           data |= 0x01;
           ioctl (fd, PPWDATA, &data);
           usleep (1);

           data &= ~0x01;
           ioctl (fd, PPWDATA, &data);

           i++;
       }

       if (Sequence [i] == -1)
       {
           usleep (20000);
           i++;
       }
   } while (Sequence [i] != -1);

   /* select data register */
   data &= ~0x04;
   ioctl (fd, PPWDATA, &data);
   /* good to go! */
}

void PowerOff (void)
{
   data = 0;
   ioctl (fd, PPWDATA, &data);
}

void SetWindow (int x, int y, int sx, int sy)
{
   /* bounds checking */
   sx += x;
   if (x < 0) x = 0;
   if (x > 100) x = 100;
   if (sx <= x) sx = x + 1;
   if (sx > 101) sx = 101;

   sy += y;
   if (y < 0) y = 0;
   if (y > 79) y = 79;
   if (sy <= y) sy = y + 1;
   if (sy > 80) sy = 80;

   /* send command */
   x = 2 * (3 + x);
   sx = 2 * (3 + sx) + 1;
   data |=  0x04;
   data &= ~0x01;
   ioctl (fd, PPWDATA, &data);

   Send (0xf0);
   Send (0x00 | (x & 0x0f));
   Send (0x10 | (x >> 4));
   Send (0x20 | (y & 0x0f));
   Send (0x30 | (y >> 4));

   Send (0xf5);
   Send (0x00 | (sx & 0x0f));
   Send (0x10 | (sx >> 4));
   Send (0x20 | (sy & 0x0f));
   Send (0x30 | (sy >> 4));

   data &= ~0x04;
   data |=  0x01;
   ioctl (fd, PPWDATA, &data);
}

int main (int argc, char *argv[])
{
   int i, j, k, demo;

   /* open the parallel port driver */
   fd = open ("/dev/parport0", O_RDWR);
   if (fd == -1)
   {
       perror ("open");
       exit (1);
   }

   if (ioctl (fd, PPCLAIM))
   {
       perror ("PPCLAIM");
       close (fd);
       exit (1);
   }

/*  mode = IEEE1284_MODE_COMPAT;
   if (ioctl (fd, PPNEGOT, &mode))
   {
       perror ("PPNEGOT");
       close (fd);
       exit (1);
   } */

   if (argc > 1 && argv[1][0] == '0')
   {
       PowerOff ();
       close (fd);
       exit (0);
   }

   if (argc < 2 || argv[1][0] != 's')
   {
       Initialise ();
   }

   demo = (argc > 1 && argv[1][0] == 'd');
   k = 0;
   do
   {
       for (i = 0; i < 80; i++)
       {
           SetWindow (0, i, 101, 1);

           data &= ~0x01;
           ioctl (fd, PPWDATA, &data);
           for (j = 0; j < 101; j++)
           {
               if (demo)
               {
                   int x, c;
                   x = ((i + k) ^ (j - k)) & 0xFF;
                   c = ((x >> 4) % 7) + 1;
                   x &= 0x0F;

                   Send  ((c & 0x01)? x: 0);
                   Send (((c & 0x02)? x << 4: 0) |
                         ((c & 0x04)? x: 0));
               }
               else
               {
                   int r, g, b;
                   r = getchar ();
                   g = getchar ();
                   b = getchar ();
                   Send  ((r >> 4) & 0x0F);
                   Send (((b >> 4) & 0x0F) |
                          (g & 0xF0));
               }
           }
           data |=  0x01;
           ioctl (fd, PPWDATA, &data);
       }
       k++;
       usleep (100000);
   } while (demo);

   close (fd);
   return 0;
}