graphlcd-base/glcddrivers/picctl.c
author cpresser@rika
Thu, 07 Feb 2008 00:18:02 +0000
changeset 10 9798f65f2f35
parent 9 63442d0b7eca
child 14 ccaf76b245ec
permissions -rw-r--r--
thx @arghgra. defined variable != declared variable
     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 const unsigned char CMD_ESCAPE_BYTE = 0x42;
    40 
    41 
    42 const unsigned char CMD_SYS_SYNC =		0x00;
    43 const unsigned char CMD_SYS_ACK	=		0x01;
    44 const unsigned char CMD_SYS_NACK =		0x02;
    45 const unsigned char CMD_SYS_NIMP =		0xFF;
    46 const unsigned char CMD_SYS_IR =		0x10;
    47 
    48 const unsigned char CMD_DISP_CLEAR_SCREEN =	0x10;
    49 const unsigned char CMD_DISP_SET_ROW_DATA =  	0x14;
    50 const unsigned char CMD_DISP_SET_ADDRESS =	0x16;
    51 
    52 const unsigned char CMD_READ_CLOCK =		0x40;
    53 const unsigned char CMD_WRITE_CLOCK =		0x41;
    54 const unsigned char CMD_SET_PWM1 =		0x45;
    55 const unsigned char CMD_SET_PWM2 =		0x46;
    56 
    57 const unsigned char CMD_SET_MODE_MANAGED =	0x70;
    58 const unsigned char CMD_SET_MODE_UNMANAGED =	0x71;
    59 
    60 const unsigned char CMD_BOOT =			0x80;
    61 
    62 
    63 // globals...
    64 uint8_t cDriverPICCtl::buf[255];
    65 uint8_t cDriverPICCtl::buf_pos;
    66 uint8_t cDriverPICCtl::buf_cmd_start;
    67 bool cDriverPICCtl::buf_flag_escape;
    68 
    69 // singleton
    70 cDriverPICCtl* cDriverPICCtl::instance = 0;
    71 
    72 cDriverPICCtl* cDriverPICCtl::getInstance(cDriverConfig * config)
    73 {
    74     if (!instance)
    75         instance = new cDriverPICCtl(config);
    76     return instance;
    77 }
    78 // end singleton-pattern
    79 
    80 
    81 
    82 cDriverPICCtl::cDriverPICCtl(cDriverConfig * config)
    83 :   config(config)
    84 {
    85     oldConfig = new cDriverConfig(*config);
    86 
    87     port = new cSerialPort();
    88 
    89     //width = config->width;
    90     //height = config->height;
    91     refreshCounter = 0;
    92     ack_flag = false;
    93     
    94     buf_pos = 1;
    95     buf_cmd_start = 255;
    96     buf_flag_escape = false;
    97 }
    98 
    99 cDriverPICCtl::~cDriverPICCtl()
   100 {
   101     delete port;
   102     delete oldConfig;
   103 }
   104 
   105 void cDriverPICCtl::SignalHandler(int signal)
   106 {
   107     // read all available data
   108     while (instance->port->ReadData(&buf[buf_pos]))
   109     {
   110         // search for SYNC byte
   111         if ((buf[buf_pos] == CMD_SYNC_RECV) && (!buf_flag_escape))
   112 	{
   113 	    if (buf_cmd_start != 255)
   114 	    {
   115 	        // bytes = buf_cmd_start - buf_pos
   116                 syslog(LOG_INFO, "PICCtl received a malformed packet. Scrapped xxx bytes\n");
   117 		buf_cmd_start = 0;
   118 		buf_pos = 0;
   119 		buf[buf_pos] = CMD_SYNC_RECV;
   120 	    }
   121  	    buf_cmd_start = buf_pos;
   122 	}
   123 
   124 
   125         if ((buf[buf_pos] == CMD_ESCAPE_BYTE) && (!buf_flag_escape))
   126 	{
   127 	    buf_flag_escape = true;
   128 	    buf_pos--; // should do!!! better would be something like next();
   129 	    // set flag...
   130 	    // next;
   131 	} 
   132 	else
   133 	{
   134 	    buf_flag_escape = false;
   135 	}
   136 
   137         // we need to check for a valid packet...
   138 	if (buf_pos >=CMD_DATA_START)
   139 	{
   140             // if we recieved a valid packet: start decoding
   141 	    if (buf[CMD_HDR_LENGTH+1] == (buf_pos - CMD_DATA_START))
   142 	    {
   143 	        instance->DecodeCmd(&buf[buf_cmd_start],(buf_pos-1));
   144 		buf_pos = 0;
   145 		buf_cmd_start = 0;
   146 	    }
   147 	}
   148 
   149         buf_pos++;
   150 
   151     }
   152 }
   153 
   154 
   155 void cDriverPICCtl::DecodeCmd(uint8_t * cmd, uint8_t len)
   156 {
   157     switch (cmd[CMD_HDR_COMMAND])
   158     {
   159         case CMD_SYS_ACK:	instance->ack_flag = true;
   160 	 			break;
   161 
   162 	case CMD_SYS_IR:	printf(" Incoming Key-Event 0x%02x (Source 0x%02x)\n",cmd[CMD_DATA_START+1],cmd[CMD_DATA_START]);
   163 	  			break;
   164 
   165 	default:		printf(" recieved Message 0x%x \n",cmd[CMD_HDR_COMMAND]);
   166     }
   167 
   168 }
   169 
   170 int cDriverPICCtl::Init()
   171 {
   172     int y;
   173 
   174     // fixed values so far...
   175     width = 240;
   176     height = 64;
   177 
   178     for (unsigned int i = 0; i < config->options.size(); i++)
   179     {
   180         if (config->options[i].name == "")
   181         {
   182         }
   183     }
   184 
   185     // setup lcd array (wanted state)
   186     newLCD = new unsigned char*[height];
   187     if (newLCD)
   188     {
   189         for (y = 0; y < height; y++)
   190         {
   191             newLCD[y] = new unsigned char[width/8];
   192             memset(newLCD[y], 0, (width/8));
   193         }
   194     }
   195     // setup lcd array (current state)
   196     oldLCD = new unsigned char*[height];
   197     if (oldLCD)
   198     {
   199         for (y = 0; y < height; y++)
   200         {
   201             oldLCD[y] = new unsigned char[width/8];
   202             memset(oldLCD[y], 0, (width/8));
   203         }
   204     }
   205 
   206     if (config->device == "")
   207     {
   208         return -1;
   209     }
   210     if (port->Open(config->device.c_str(), SignalHandler) != 0)
   211         return -1;
   212 
   213     *oldConfig = *config;
   214 
   215     // clear display
   216     Clear();
   217     CmdDispClearScreen();
   218     CmdDispSetManaged();
   219 
   220     syslog(LOG_INFO, "%s: PICCtl initialized.\n", config->name.c_str());
   221     return 0;
   222 }
   223 
   224 int cDriverPICCtl::DeInit()
   225 {
   226     int y;
   227     // free lcd array (wanted state)
   228     if (newLCD)
   229     {
   230         for (y = 0; y < height; y++)
   231         {
   232             delete[] newLCD[y];
   233         }
   234         delete[] newLCD;
   235     }
   236     // free lcd array (current state)
   237     if (oldLCD)
   238     {
   239         for (y = 0; y < height; y++)
   240         {
   241             delete[] oldLCD[y];
   242         }
   243         delete[] oldLCD;
   244     }
   245 
   246     CmdDispSetUnManaged();
   247     
   248     delete instance;
   249     instance = 0;
   250 
   251     if (port->Close() != 0)
   252         return -1;
   253     return 0;
   254 }
   255 
   256 int cDriverPICCtl::CheckSetup()
   257 {
   258     if (config->device != oldConfig->device ||
   259         config->width != oldConfig->width ||
   260         config->height != oldConfig->height)
   261     {
   262         DeInit();
   263         Init();
   264         return 0;
   265     }
   266 
   267     if (config->upsideDown != oldConfig->upsideDown ||
   268         config->invert != oldConfig->invert)
   269     {
   270         oldConfig->upsideDown = config->upsideDown;
   271         oldConfig->invert = config->invert;
   272         return 1;
   273     }
   274     return 0;
   275 }
   276 
   277 void cDriverPICCtl::Clear()
   278 {
   279     for (int y = 0; y < height; y++)
   280         memset(newLCD[y], 0, (width/8));
   281 }
   282 
   283 void cDriverPICCtl::Set8Pixels(int x, int y, unsigned char data)
   284 {
   285     if (x >= width || y >= height)
   286         return;
   287 
   288     if (!config->upsideDown)
   289     {
   290         newLCD[y][x/8] = data;
   291     }
   292     else
   293     {
   294         x = width - 1 - x;
   295         y = height - 1 - y;
   296         newLCD[y][x / 8] |= ReverseBits(data);
   297     }
   298 }
   299 
   300 void cDriverPICCtl::Refresh(bool refreshAll)
   301 {
   302     int y;
   303 
   304     if (CheckSetup() == 1)
   305         refreshAll = true;
   306 
   307     if (config->refreshDisplay > 0)
   308     {
   309         refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
   310         if (!refreshAll && !refreshCounter)
   311             refreshAll = true;
   312     }
   313 
   314 
   315     if (refreshAll)
   316     {
   317         // draw all
   318         // always draw a complete row! (30 bytes!)
   319         for (y = 0; y < height; y++)
   320         {
   321             CmdDispSetColData(y, 0, (width/8), newLCD[y]);
   322             memcpy(oldLCD[y], newLCD[y], (width/8));
   323         }
   324         // and reset RefreshCounter
   325         refreshCounter = 0;
   326     }
   327     else
   328     {
   329 	// for every line
   330 	for (y = 0; y< height; y++)
   331         {
   332             // did anysthing change? -> draw new line
   333 	    if (memcmp(newLCD[y],oldLCD[y],(width/8)) != 0)
   334             {
   335                  CmdDispSetColData(y, 0, (width/8), newLCD[y]);
   336                  memcpy(oldLCD[y], newLCD[y], (width/8));
   337             }
   338         }
   339     }
   340 }
   341 
   342 void cDriverPICCtl::SetBrightness(unsigned int percent)
   343 {
   344     CmdDispSetBrightness(percent);
   345 }
   346 
   347 void cDriverPICCtl::SetClock(unsigned int percent)
   348 {
   349     CmdDispSetBrightness(percent);
   350 }
   351 
   352 int cDriverPICCtl::WaitForAck(void)
   353 {
   354     int timeout;
   355 
   356     for (timeout=0; timeout<10000; timeout++)
   357     {
   358     	usleep(10);
   359 	if (ack_flag) return 1;
   360     }
   361     syslog(LOG_INFO, "PICCtl: missed a ACK packet!.\n");
   362     return 0;
   363 }
   364 
   365 void cDriverPICCtl::CmdDispClearScreen(void)
   366 {
   367     uint8_t cmd[4];
   368 
   369     cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
   370     cmd[CMD_HDR_COMMAND] = CMD_DISP_CLEAR_SCREEN;
   371     cmd[CMD_HDR_LENGTH] = 0;
   372     cmd[CMD_HDR_LENGTH+1] = 0;
   373 
   374     port->WriteData(cmd, 4);
   375     WaitForAck();
   376 }
   377 
   378 void cDriverPICCtl::CmdDispSetBrightness(uint8_t percent)
   379 {
   380     uint8_t cmd[5];
   381 
   382     cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
   383     cmd[CMD_HDR_COMMAND] = CMD_SET_PWM1;
   384     cmd[CMD_HDR_LENGTH] = 0;
   385     cmd[CMD_HDR_LENGTH+1] = 1;
   386     cmd[CMD_DATA_START] = (uint8_t) round(percent * 2.55);
   387 
   388     port->WriteData(cmd, 5);
   389     WaitForAck();
   390 }
   391 
   392 void cDriverPICCtl::CmdDispSetColData(uint8_t yoffset, uint8_t xoffset, uint8_t length, uint8_t * data)
   393 {
   394     uint8_t cmd[64];
   395     uint16_t address;
   396 
   397     address = 0x1E * yoffset + xoffset;
   398 
   399     cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
   400     cmd[CMD_HDR_COMMAND] = CMD_DISP_SET_ROW_DATA;
   401     cmd[CMD_HDR_LENGTH] = 0;
   402     cmd[CMD_HDR_LENGTH+1] = (length + 2);
   403     cmd[CMD_DATA_START] = (uint8_t)(address % 256);	// lower address
   404     cmd[CMD_DATA_START+1] = (uint8_t)(address / 256);	// upper address
   405     memcpy(&cmd[CMD_DATA_START+2], data, length);
   406 
   407     port->WriteData(cmd, length + 6);
   408     WaitForAck();
   409 
   410 //    for (address = 0; address < length+6; address ++) printf("0x%02x ",cmd[address]);
   411 //  printf("address=0x%x upper=0x%x lower=0x%x \n", address, (uint8_t)(address / 256), (uint8_t)(address % 256));
   412 //    printf("\n");
   413 }
   414 
   415 void cDriverPICCtl::CmdDispSetManaged(void)
   416 {
   417     uint8_t cmd[4];
   418 
   419     cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
   420     cmd[CMD_HDR_COMMAND] = CMD_SET_MODE_MANAGED;
   421     cmd[CMD_HDR_LENGTH] = 0;
   422     cmd[CMD_HDR_LENGTH+1] = 0;
   423 
   424     port->WriteData(cmd,4);
   425     WaitForAck();
   426 }
   427 
   428 void cDriverPICCtl::CmdDispSetUnManaged(void)
   429 {
   430     uint8_t cmd[4];
   431 
   432     cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
   433     cmd[CMD_HDR_COMMAND] = CMD_SET_MODE_UNMANAGED;
   434     cmd[CMD_HDR_LENGTH] = 0;
   435     cmd[CMD_HDR_LENGTH+1] = 0;
   436 
   437     port->WriteData(cmd,4);
   438     WaitForAck();
   439 }
   440 
   441 
   442 } // end NameSpace