graphlcd-base/glcddrivers/picctl.c
changeset 5 37602e25a04a
child 8 5fa05abec614
equal deleted inserted replaced
4:df6a40031aa5 5:37602e25a04a
       
     1 /*
       
     2  * GraphLCD driver library
       
     3  *
       
     4  * picctl.c  -  PIC controlled LCD driver class
       
     5  *
       
     6  * This file is released under the GNU General Public License. Refer
       
     7  * to the COPYING file distributed with this package.
       
     8  *
       
     9  * Codebase by Andreas Regel <andreas.regel AT powarman.de>
       
    10  * (c) 2007 Carsten Presser
       
    11  */
       
    12 
       
    13 #include <stdint.h>
       
    14 #include <syslog.h>
       
    15 #include <math.h>
       
    16 
       
    17 #include "common.h"
       
    18 #include "config.h"
       
    19 #include "port.h"
       
    20 #include "picctl.h"
       
    21 
       
    22 
       
    23 
       
    24 namespace GLCD
       
    25 {
       
    26 
       
    27 /* command header:
       
    28 **  8 bits  sync byte (0xAA for sent commands, 0x55 for received commands)
       
    29 **  8 bits  command id
       
    30 ** 16 bits  command length (excluding header)
       
    31 */
       
    32 const unsigned char CMD_HDR_SYNC    = 0;
       
    33 const unsigned char CMD_HDR_COMMAND = 1;
       
    34 const unsigned char CMD_HDR_LENGTH  = 2;
       
    35 const unsigned char CMD_DATA_START  = 4;
       
    36 
       
    37 const unsigned char CMD_SYNC_SEND = 0xAA;
       
    38 const unsigned char CMD_SYNC_RECV = 0x55;
       
    39 
       
    40 
       
    41 const unsigned char CMD_SYS_SYNC =		0x00;
       
    42 const unsigned char CMD_SYS_ACK	=		0x01;
       
    43 const unsigned char CMD_SYS_NACK =		0x02;
       
    44 const unsigned char CMD_SYS_NIMP =		0xFF;
       
    45 const unsigned char CMD_SYS_IR =		0x10;
       
    46 
       
    47 const unsigned char CMD_DISP_CLEAR_SCREEN =	0x10;
       
    48 const unsigned char CMD_DISP_SET_ROW_DATA =  	0x14;
       
    49 const unsigned char CMD_DISP_SET_ADDRESS =	0x16;
       
    50 
       
    51 const unsigned char CMD_READ_CLOCK =		0x40;
       
    52 const unsigned char CMD_WRITE_CLOCK =		0x41;
       
    53 const unsigned char CMD_SET_PWM1 =		0x45;
       
    54 const unsigned char CMD_SET_PWM2 =		0x46;
       
    55 
       
    56 const unsigned char CMD_SET_MODE_MANAGED =	0x70;
       
    57 const unsigned char CMD_SET_MODE_UNMANAGED =	0x71;
       
    58 
       
    59 const unsigned char CMD_BOOT =			0x80;
       
    60 // singleton
       
    61 cDriverPICCtl* cDriverPICCtl::instance = 0;
       
    62 
       
    63 cDriverPICCtl* cDriverPICCtl::getInstance(cDriverConfig * config)
       
    64 {
       
    65     if (!instance)
       
    66         instance = new cDriverPICCtl(config);
       
    67     return instance;
       
    68 }
       
    69 // end singleton-pattern
       
    70 
       
    71 
       
    72 
       
    73 cDriverPICCtl::cDriverPICCtl(cDriverConfig * config)
       
    74 :   config(config)
       
    75 {
       
    76     oldConfig = new cDriverConfig(*config);
       
    77 
       
    78     port = new cSerialPort();
       
    79 
       
    80     //width = config->width;
       
    81     //height = config->height;
       
    82     refreshCounter = 0;
       
    83     ack_flag = false;
       
    84 }
       
    85 
       
    86 cDriverPICCtl::~cDriverPICCtl()
       
    87 {
       
    88     delete port;
       
    89     delete oldConfig;
       
    90 }
       
    91 
       
    92 void cDriverPICCtl::SignalHandler(int signal)
       
    93 {
       
    94     unsigned char buf[255];
       
    95     int numbytes,i;
       
    96 
       
    97     numbytes = instance->port->ReadData(buf,255);
       
    98 
       
    99 
       
   100     if ((buf[CMD_HDR_SYNC] == CMD_SYNC_RECV) && (buf[CMD_HDR_LENGTH+1] == (numbytes - CMD_DATA_START)))
       
   101     {
       
   102     	switch (buf[CMD_HDR_COMMAND])
       
   103 	{
       
   104 	  case CMD_SYS_ACK:	instance->ack_flag = true;
       
   105 	  			break;
       
   106 
       
   107 	  case CMD_SYS_IR:	printf(" Incoming Key-Event 0x%02x (Source 0x%02x)\n",buf[CMD_DATA_START+1],buf[CMD_DATA_START]);
       
   108 	  			break;
       
   109 
       
   110 	  default:		printf(" recieved Message 0x%x \n",buf[CMD_HDR_COMMAND]);
       
   111 	}
       
   112     }
       
   113     else
       
   114     {
       
   115         syslog(LOG_INFO, "PICCtl received a malformed packet.\n");
       
   116         for (i=0; i<numbytes; i++)
       
   117         {
       
   118             printf(" 0x%x",buf[i]);
       
   119         }
       
   120         printf("; recieved %d bytes2\n",numbytes);
       
   121     }
       
   122 
       
   123 }
       
   124 
       
   125 int cDriverPICCtl::Init()
       
   126 {
       
   127     int y;
       
   128 
       
   129     // fixed values so far...
       
   130     width = 240;
       
   131     height = 64;
       
   132 
       
   133     for (unsigned int i = 0; i < config->options.size(); i++)
       
   134     {
       
   135         if (config->options[i].name == "")
       
   136         {
       
   137         }
       
   138     }
       
   139 
       
   140     // setup lcd array (wanted state)
       
   141     newLCD = new unsigned char*[height];
       
   142     if (newLCD)
       
   143     {
       
   144         for (y = 0; y < height; y++)
       
   145         {
       
   146             newLCD[y] = new unsigned char[width/8];
       
   147             memset(newLCD[y], 0, (width/8));
       
   148         }
       
   149     }
       
   150     // setup lcd array (current state)
       
   151     oldLCD = new unsigned char*[height];
       
   152     if (oldLCD)
       
   153     {
       
   154         for (y = 0; y < height; y++)
       
   155         {
       
   156             oldLCD[y] = new unsigned char[width/8];
       
   157             memset(oldLCD[y], 0, (width/8));
       
   158         }
       
   159     }
       
   160 
       
   161     if (config->device == "")
       
   162     {
       
   163         return -1;
       
   164     }
       
   165     if (port->Open(config->device.c_str(), SignalHandler) != 0)
       
   166         return -1;
       
   167 
       
   168     *oldConfig = *config;
       
   169 
       
   170     // clear display
       
   171     Clear();
       
   172     CmdDispClearScreen();
       
   173     CmdDispSetManaged();
       
   174     CmdDispSetBrightness(100);
       
   175 
       
   176     syslog(LOG_INFO, "%s: PICCtl initialized.\n", config->name.c_str());
       
   177     return 0;
       
   178 }
       
   179 
       
   180 int cDriverPICCtl::DeInit()
       
   181 {
       
   182     int y;
       
   183     // free lcd array (wanted state)
       
   184     if (newLCD)
       
   185     {
       
   186         for (y = 0; y < height; y++)
       
   187         {
       
   188             delete[] newLCD[y];
       
   189         }
       
   190         delete[] newLCD;
       
   191     }
       
   192     // free lcd array (current state)
       
   193     if (oldLCD)
       
   194     {
       
   195         for (y = 0; y < height; y++)
       
   196         {
       
   197             delete[] oldLCD[y];
       
   198         }
       
   199         delete[] oldLCD;
       
   200     }
       
   201 
       
   202     CmdDispSetUnManaged();
       
   203     
       
   204     delete instance;
       
   205     instance = 0;
       
   206 
       
   207     if (port->Close() != 0)
       
   208         return -1;
       
   209     return 0;
       
   210 }
       
   211 
       
   212 int cDriverPICCtl::CheckSetup()
       
   213 {
       
   214     if (config->device != oldConfig->device ||
       
   215         config->width != oldConfig->width ||
       
   216         config->height != oldConfig->height)
       
   217     {
       
   218         DeInit();
       
   219         Init();
       
   220         return 0;
       
   221     }
       
   222 
       
   223     if (config->upsideDown != oldConfig->upsideDown ||
       
   224         config->invert != oldConfig->invert)
       
   225     {
       
   226         oldConfig->upsideDown = config->upsideDown;
       
   227         oldConfig->invert = config->invert;
       
   228         return 1;
       
   229     }
       
   230     return 0;
       
   231 }
       
   232 
       
   233 void cDriverPICCtl::Clear()
       
   234 {
       
   235     for (int y = 0; y < height; y++)
       
   236         memset(newLCD[y], 0, (width/8));
       
   237 }
       
   238 
       
   239 void cDriverPICCtl::Set8Pixels(int x, int y, unsigned char data)
       
   240 {
       
   241     if (x >= width || y >= height)
       
   242         return;
       
   243 
       
   244     if (!config->upsideDown)
       
   245     {
       
   246         newLCD[y][x/8] = data;
       
   247     }
       
   248     else
       
   249     {
       
   250         x = width - 1 - x;
       
   251         y = height - 1 - y;
       
   252         newLCD[y][x / 8] |= ReverseBits(data);
       
   253     }
       
   254 }
       
   255 
       
   256 void cDriverPICCtl::Refresh(bool refreshAll)
       
   257 {
       
   258     int y;
       
   259 
       
   260     if (CheckSetup() == 1)
       
   261         refreshAll = true;
       
   262 
       
   263     if (config->refreshDisplay > 0)
       
   264     {
       
   265         refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
       
   266         if (!refreshAll && !refreshCounter)
       
   267             refreshAll = true;
       
   268     }
       
   269 
       
   270 
       
   271     if (refreshAll)
       
   272     {
       
   273         // draw all
       
   274         // always draw a complete row! (30 bytes!)
       
   275         for (y = 0; y < height; y++)
       
   276         {
       
   277             CmdDispSetColData(y, 0, (width/8), newLCD[y]);
       
   278             memcpy(oldLCD[y], newLCD[y], (width/8));
       
   279         }
       
   280         // and reset RefreshCounter
       
   281         refreshCounter = 0;
       
   282     }
       
   283     else
       
   284     {
       
   285 	// for every line
       
   286 	for (y = 0; y< height; y++)
       
   287         {
       
   288             // did anysthing change? -> draw new line
       
   289 	    if (memcmp(newLCD[y],oldLCD[y],(width/8)) != 0)
       
   290             {
       
   291                  CmdDispSetColData(y, 0, (width/8), newLCD[y]);
       
   292                  memcpy(oldLCD[y], newLCD[y], (width/8));
       
   293             }
       
   294         }
       
   295     }
       
   296 }
       
   297 
       
   298 void cDriverPICCtl::SetBrightness(unsigned int percent)
       
   299 {
       
   300     CmdDispSetBrightness(percent);
       
   301 }
       
   302 
       
   303 void cDriverPICCtl::SetClock(unsigned int percent)
       
   304 {
       
   305     CmdDispSetBrightness(percent);
       
   306 }
       
   307 
       
   308 int cDriverPICCtl::WaitForAck(void)
       
   309 {
       
   310     int timeout;
       
   311 
       
   312     for (timeout=0; timeout<10000; timeout++)
       
   313     {
       
   314     	usleep(10);
       
   315 	if (ack_flag) return 1;
       
   316     }
       
   317     syslog(LOG_INFO, "PICCtl: missed a ACK packet!.\n");
       
   318     return 0;
       
   319 }
       
   320 
       
   321 void cDriverPICCtl::CmdDispClearScreen(void)
       
   322 {
       
   323     uint8_t cmd[4];
       
   324 
       
   325     cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
       
   326     cmd[CMD_HDR_COMMAND] = CMD_DISP_CLEAR_SCREEN;
       
   327     cmd[CMD_HDR_LENGTH] = 0;
       
   328     cmd[CMD_HDR_LENGTH+1] = 0;
       
   329 
       
   330     port->WriteData(cmd, 4);
       
   331     WaitForAck();
       
   332 }
       
   333 
       
   334 void cDriverPICCtl::CmdDispSetBrightness(uint8_t percent)
       
   335 {
       
   336     uint8_t cmd[5];
       
   337 
       
   338     cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
       
   339     cmd[CMD_HDR_COMMAND] = CMD_SET_PWM1;
       
   340     cmd[CMD_HDR_LENGTH] = 0;
       
   341     cmd[CMD_HDR_LENGTH+1] = 1;
       
   342     cmd[CMD_DATA_START] = (uint8_t) round(percent * 2.55);
       
   343 
       
   344     port->WriteData(cmd, 5);
       
   345     WaitForAck();
       
   346 }
       
   347 
       
   348 void cDriverPICCtl::CmdDispSetColData(uint8_t yoffset, uint8_t xoffset, uint8_t length, uint8_t * data)
       
   349 {
       
   350     uint8_t cmd[64];
       
   351     uint16_t address;
       
   352 
       
   353     address = 0x1E * yoffset + xoffset;
       
   354 
       
   355     cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
       
   356     cmd[CMD_HDR_COMMAND] = CMD_DISP_SET_ROW_DATA;
       
   357     cmd[CMD_HDR_LENGTH] = 0;
       
   358     cmd[CMD_HDR_LENGTH+1] = (length + 2);
       
   359     cmd[CMD_DATA_START] = (uint8_t)(address % 256);	// lower address
       
   360     cmd[CMD_DATA_START+1] = (uint8_t)(address / 256);	// upper address
       
   361     memcpy(&cmd[CMD_DATA_START+2], data, length);
       
   362 
       
   363     port->WriteData(cmd, length + 6);
       
   364     WaitForAck();
       
   365 
       
   366 //    for (address = 0; address < length+6; address ++) printf("0x%02x ",cmd[address]);
       
   367 //  printf("address=0x%x upper=0x%x lower=0x%x \n", address, (uint8_t)(address / 256), (uint8_t)(address % 256));
       
   368 //    printf("\n");
       
   369 }
       
   370 
       
   371 void cDriverPICCtl::CmdDispSetManaged(void)
       
   372 {
       
   373     uint8_t cmd[4];
       
   374 
       
   375     cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
       
   376     cmd[CMD_HDR_COMMAND] = CMD_SET_MODE_MANAGED;
       
   377     cmd[CMD_HDR_LENGTH] = 0;
       
   378     cmd[CMD_HDR_LENGTH+1] = 0;
       
   379 
       
   380     port->WriteData(cmd,4);
       
   381     WaitForAck();
       
   382 }
       
   383 
       
   384 void cDriverPICCtl::CmdDispSetUnManaged(void)
       
   385 {
       
   386     uint8_t cmd[4];
       
   387 
       
   388     cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
       
   389     cmd[CMD_HDR_COMMAND] = CMD_SET_MODE_UNMANAGED;
       
   390     cmd[CMD_HDR_LENGTH] = 0;
       
   391     cmd[CMD_HDR_LENGTH+1] = 0;
       
   392 
       
   393     port->WriteData(cmd,4);
       
   394     WaitForAck();
       
   395 }
       
   396 
       
   397 
       
   398 } // end NameSpace