PageRenderTime 156ms CodeModel.GetById 29ms app.highlight 53ms RepoModel.GetById 17ms app.codeStats 3ms

/Minestation.pde

https://github.com/radikalbytes/minestation
Processing | 1704 lines | 1021 code | 143 blank | 540 comment | 147 complexity | 532c12e540de077e1b025a5fd0e391bd MD5 | raw file
   1#include <TimerOne.h>
   2// Compatiblity with Arduino IDE 1.0
   3// Arduino API used in v.22 libraries
   4// is WProgram.h
   5// and in v1.0 it's renamed to Arduino.h
   6
   7 #if defined(ARDUINO) && ARDUINO >= 100
   8  #include "Arduino.h"
   9  #else
  10  #include "WProgram.h"
  11  #endif
  12/****************************************************/
  13/* Example Program For LCD6610 (NPX)                */
  14/* MCU      : Arduino Nano                          */
  15/* By       : Gravitech                             */
  16/* Function : Demo Interface LCD6610                */
  17/*            (Philips controller)                  */ 
  18/****************************************************/
  19/* Interface LCD6610 to Arduino Nano                */
  20/*    Nano  --> LCD6610                             */
  21/*    D2    --> BL                                  */
  22/*    D3    --> #CS                                 */
  23/*    D4    --> SCLK                                */
  24/*    D5    --> SDATA                               */
  25/*    D6    --> #RESEET                             */
  26/*    +5V   --> VCC,VBL                             */
  27/*    GND   --> GND                                 */
  28/****************************************************/
  29
  30#include <avr/pgmspace.h>
  31#include "foto.h"
  32#include "fonts.h"
  33#include <TimerOne.h>
  34
  35/* Define LCD6610 PinIO interface */
  36//#define BL    2      // Digital 2 --> BL
  37#define CS    10 //3     // Digital 3 --> #CS
  38#define CLK   13 // 4      // Digital 4 --> SCLK
  39#define SDA   11 // 5      // Digital 5 --> SDATA
  40#define RESET 9 // 6      // Digital 6 --> #RESET
  41
  42/* Start of Define Philips(NXP):PCF8833 Header */ 
  43#define NOP 0x00 	// nop
  44#define SWRESET  0x01 	// software reset
  45#define BSTROFF  0x02 	// booster voltage OFF
  46#define BSTRON   0x03 	// booster voltage ON
  47#define RDDIDIF  0x04 	// read display identification
  48#define RDDST    0x09 	// read display status
  49#define SLEEPIN  0x10 	// sleep in
  50#define SLEEPOUT 0x11 	// sleep out
  51#define PTLON    0x12 	// partial display mode
  52#define NORON    0x13 	// display normal mode
  53#define INVOFF   0x20 	// inversion OFF
  54#define INVON    0x21 	// inversion ON
  55#define DALO     0x22 	// all pixel OFF
  56#define DAL      0x23 	// all pixel ON
  57#define SETCON   0x25 	// write contrast
  58#define DISPOFF  0x28 	// display OFF
  59#define DISPON   0x29 	// display ON
  60#define CASET    0x2A 	// column address set
  61#define PASET    0x2B 	// page address set
  62#define RAMWR    0x2C 	// memory write
  63#define RGBSET   0x2D 	// colour set
  64#define PTLAR    0x30 	// partial area
  65#define VSCRDEF  0x33 	// vertical scrolling definition
  66#define TEOFF    0x34 	// test mode
  67#define TEON     0x35 	// test mode
  68#define MADCTL   0x36 	// memory access control
  69#define SEP      0x37 	// vertical scrolling start address
  70#define IDMOFF   0x38 	// idle mode OFF
  71#define IDMON    0x39 	// idle mode ON
  72#define COLMOD   0x3A 	// interface pixel format
  73#define SETVOP   0xB0 	// set Vop
  74#define BRS      0xB4 	// bottom row swap
  75#define TRS      0xB6 	// top row swap
  76#define DISCTR   0xB9 	// display control
  77//#define DAOR   0xBA 	// data order(DOR)
  78#define TCDFE    0xBD 	// enable/disable DF temperature compensation
  79#define TCVOPE   0xBF 	// enable/disable Vop temp comp
  80#define EC       0xC0 	// internal or external oscillator
  81#define SETMUL   0xC2 	// set multiplication factor
  82#define TCVOPAB  0xC3 	// set TCVOP slopes A and B
  83#define TCVOPCD  0xC4 	// set TCVOP slopes c and d
  84#define TCDF     0xC5 	// set divider frequency
  85#define DF8COLOR 0xC6 	// set divider frequency 8-color mode
  86#define SETBS    0xC7 	// set bias system
  87#define RDTEMP   0xC8 	// temperature read back
  88#define NLI      0xC9 	// n-line inversion
  89#define RDID1    0xDA 	// read ID1
  90#define RDID2    0xDB 	// read ID2
  91#define RDID3    0xDC 	// read ID3
  92
  93#ifdef PB1
  94#define LCD_CS(x)           PORTB= (x)? (PORTB|(1<<PB2)) : (PORTB&~(1<<PB2))
  95#define LCD_CLK(x)          PORTB= (x)? (PORTB|(1<<PB5)) : (PORTB&~(1<<PB5))
  96#define LCD_DATA(x)         PORTB= (x)? (PORTB|(1<<PB3)) : (PORTB&~(1<<PB3))
  97#define LCD_RESET(x)        PORTB= (x)? (PORTB|(1<<PB1)) : (PORTB&~(1<<PB1))
  98#define LCD_levelLight(x)    PORTB= (x)? (PORTB|(1<<PB0)) : (PORTB&~(1<<PB0))
  99#else
 100#define LCD_CS(x)           PORTB= (x)? (PORTB|(1<<PORTB2)) : (PORTB&~(1<<PORTB2))
 101#define LCD_CLK(x)          PORTB= (x)? (PORTB|(1<<PORTB5)) : (PORTB&~(1<<PORTB5))
 102#define LCD_DATA(x)         PORTB= (x)? (PORTB|(1<<PORTB3)) : (PORTB&~(1<<PORTB3))
 103#define LCD_RESET(x)        PORTB= (x)? (PORTB|(1<<PORTB1)) : (PORTB&~(1<<PORTB1))
 104#define LCD_levelLight(x)    PORTB= (x)? (PORTB|(1<<PORTB0)) : (PORTB&~(1<<PORTB0))
 105#endif
 106
 107#define LCDCommand      0
 108#define LCDData         1
 109
 110// Font sizes
 111#define SMALL 0
 112#define MEDIUM 1
 113#define LARGE 2
 114
 115// Booleans
 116#define NOFILL 0
 117#define FILL 1
 118
 119// 12-bit color definitions
 120// Mode color BGR 多?多 I don't know but works
 121#define WHITE 0xFFF
 122#define BLACK 0x000
 123#define RED 0x00F //0xF00
 124#define GREEN 0x0F0
 125#define BLUE 0xF00 //0x00F
 126#define CYAN2 0xF70
 127#define CYAN 0xFF0 //0x0FF
 128#define MAGENTA 0xF0F
 129#define YELLOW 0x0FF //0xFF0
 130#define BROWN 0x22B //0xB22
 131#define ORANGE 0x0AF //0xFA0
 132#define PINK 0xA6F //0xF6A
 133#define GREY 0xCCC
 134
 135#define cbi(reg, bit) (reg&=~(1<<bit))
 136#define sbi(reg, bit) (reg|= (1<<bit))
 137
 138#define CS0 cbi(PORTD,CS);
 139#define CS1 sbi(PORTD,CS);
 140#define CLK0 cbi(PORTD,CLK);
 141#define CLK1 sbi(PORTD,CLK);
 142#define SDA0 cbi(PORTD,SDA);
 143#define SDA1 sbi(PORTD,SDA);
 144#define RESET0 cbi(PORTD,RESET);
 145#define RESET1 sbi(PORTD,RESET);
 146#define BL0 cbi(PORTD,BL);
 147#define BL1 sbi(PORTD,BL);
 148/* End of Define Philips(NXP):PCF8833 Header */ 
 149
 150
 151// constants will don't change
 152const int contrastplus = 2;     // the number of the pushbutton contrastplus pin
 153const int contrastminus = 3;    // the number of the pushbutton contrastminus pin
 154
 155// variables will change:
 156int contrastplusState = 0;      // variable for reading the pushbutton contrastplus
 157int contrastminusState = 0;     // variable for reading the pushbutton contrastminus
 158int contrast_value;          // contrast LCD value
 159
 160#define long_buffer 128
 161#define inicio_trama '@'
 162#define fin_trama '#'
 163#define BOUNCE_DURATION 50
 164volatile unsigned long bounceTime=0;
 165char buffer[long_buffer+1]; // Allocate some space for the string
 166char inChar=-1; // Where to store the character read
 167byte index = 0; // Index into array; where to store the character
 168char Time_str[10]={"00:00"};
 169char Rain_time_str[10]={0,0,0,0,0,0,0,0,0,0};
 170char Thunder_time_str[10]={0,0,0,0,0,0,0,0,0,0};
 171char dist_to_spawn_str[10]={0,0,0,0,0,0,0,0,0,0};
 172char PosX_str[8]={"0.000"};
 173char PosY_str[8]={"0.000"};
 174char PosZ_str[8]={"0.000"};
 175char Hour_str[3]={0,0,0};
 176char Minute_str[3]={0,0,0};
 177char Day_str[3]={0,0,0};
 178char Month_str[3]={0,0,0};
 179char Year_str[5]={0,0,0,0,0};
 180char  Thundering_str=0x00;
 181char  Raining_str=0x00;
 182char  World_name[16]={"Minestation 1.0"};
 183double Time=0;
 184double Rain_time=0;
 185double Thunder_time=0;
 186short  Thundering=0;
 187short  Raining=0;
 188short  Sun=0;
 189short  Moon=0;
 190//float PosX=0.0;
 191//float PosY=0.0;
 192//float PosZ=0.0;
 193float dist_to_spawn=0.0;
 194int   Hour=0;
 195int   Minute=0;
 196int   Day=1;
 197int   Month=1;
 198int   Year=0;
 199int   modo=0;
 200int   stringLen=15;
 201int   PosXSun=64;
 202int   PosYSun=15;
 203int   hourTmp;
 204int   minuteTmp;
 205int   dayTmp;
 206int   levelLight=5;
 207int   inByte;
 208
 209
 210/*************************************************************/
 211/*            Function prototypes                            */
 212/*************************************************************/
 213void sendCMD(byte);
 214void sendData(byte);
 215void shiftBits(byte);
 216void lcd_init();
 217void draw_color_bar();
 218void lcd_clear(uint16_t, byte, byte, byte, byte);
 219void LCDPutStr(char*, int, int, int, int, int);
 220void LCDPutChar(char, int, int, int, int, int);
 221void LCDSetLine(int, int, int, int, int);
 222void LCDSetRect(int, int, int, int, unsigned char fill, int);
 223void LCDSetCircle(int, int, int, int);
 224void LCDSetPixel(byte, byte, int);
 225void LCDSetXY(byte, byte);
 226void calculatePositionSun();
 227void drawStormIcon(byte,byte);
 228void drawRainIcon(byte, byte);
 229void calculateTime(long);
 230void drawCloud1(int,int);
 231void drawCloud2(int,int);
 232void drawSunMoon(int,int,int);
 233void calculatePosSunMoon();
 234void putBackground();
 235
 236/*************************************************************/
 237/*            Main Code Start here                           */
 238/*************************************************************/
 239void setup() 
 240{ 
 241  contrast_value=56;  
 242  // initialize the pushbutton pins as inputs:
 243  pinMode(contrastplus, INPUT);
 244  pinMode(contrastminus, INPUT);
 245  DDRB=0x2F;
 246  DDRB=0x2F;
 247 // DDRD |= B01111100;   // Set SPI pins as output 
 248 // PORTD |= B01111100;  // Set SPI pins HIGH
 249 Serial.begin(9600);
 250 Serial.write("Minestation Arduino v0.0.1");
 251  
 252  lcd_init();
 253  delay(500);
 254  lcd_contrast(contrast_value);
 255  attachInterrupt(0, contrastPlus, RISING);
 256  attachInterrupt(1, contrastMinus, RISING);
 257  Timer1.initialize(100000);
 258  draw_color_bar(); 
 259 delay(500);
 260// lcd_clear(BLACK,0,0,131,131);
 261/* 
 262 LCDPutStr("Probando...",            5, 40, LARGE,  YELLOW,  BLACK);
 263 LCDPutStr("132X132",           20, 40, LARGE,  CYAN,    BLACK);
 264 LCDPutStr("Color Graphic LCD", 37, 17, SMALL,  CYAN,    BLACK);
 265 LCDPutStr("WWW.GRAVITECH.US",  50,  2, LARGE,  RED,     WHITE);
 266 LCDPutStr("SMALL GREEN",       70, 37, SMALL,  GREEN,   BLACK);
 267 LCDPutStr("MEDIUM BLUE",       81, 25, MEDIUM, BLUE,    BLACK);
 268 LCDPutStr("LARGE PINK",        90, 27, LARGE,  PINK,    BLACK);
 269 LCDPutStr("MEDIUM MAGENTA",   107, 12, MEDIUM, MAGENTA, BLACK);
 270 LCDPutStr("SMALL ORANGE",     119, 30, SMALL,  ORANGE,  BLACK);
 271
 272 delay(500);
 273 lcd_clear(BLUE,0,0,131,131);
 274 
 275 LCDSetLine(120, 10, 120, 50, YELLOW);     // Draw Line Create Rectangle
 276 LCDSetLine(120, 50, 80, 50, YELLOW);
 277 LCDSetLine(80, 50, 80, 10, YELLOW);
 278 LCDSetLine(80, 10, 120, 10, YELLOW);
 279 LCDSetLine(120, 85, 80, 105, YELLOW);     // Draw Line Create X
 280 LCDSetLine(80, 85, 120, 105, YELLOW);    
 281 LCDSetCircle(62, 65, 20, RED);            // Draw Circle 
 282 LCDSetRect(5, 5, 125, 125, NOFILL, BLUE); // Draw box with no fill
 283 LCDSetRect(10, 10, 40, 40, FILL, PINK);   // Draw box with fill
 284 LCDSetRect(10, 90, 40, 120, FILL, GREEN);
 285 
 286 delay(2000);
 287 lcd_clear(BLUE,0,0,131,131);
 288 delay(2000);*/
 289   lcd_clear(BLACK,0,0,131,131);
 290   lcd_clear(WHITE,116,0,131,131);
 291  
 292  LCDSetLine(0, 65,115, 65, WHITE); // Vertical division screen
 293  LCDSetLine(0, 66,115, 66, WHITE); 
 294  LCDSetLine(17,65,17, 131, WHITE); // Clock division
 295  LCDSetLine(18,65,18, 131, WHITE); 
 296  LCDSetLine(37,65,37, 131, WHITE); // Date division
 297  LCDSetLine(38,65,38, 131, WHITE); 
 298  // Draw Atrezzo clock
 299  LCDSetCircle(8, 77, 7, GREEN);            // Draw Circle 
 300  LCDSetCircle(8, 77, 6, GREEN);            
 301  LCDSetLine(8, 77, 5, 77, GREEN);   // Draw hands clock
 302  LCDSetLine(8, 78, 5, 78, GREEN); 
 303  LCDSetLine(8, 77, 9, 80, GREEN); 
 304  LCDSetLine(8, 78, 9, 81, GREEN);
 305  //Draw Atrezzo calendar
 306  LCDSetRect(34, 69, 20, 86, NOFILL, RED);   // Draw box 
 307  LCDSetRect(35, 70, 21, 87, NOFILL, RED);   // Draw box  
 308  LCDSetPixel(35,87,BLACK);
 309  LCDSetPixel(20,69,BLACK);
 310  LCDSetLine(19, 75, 23, 75, RED);
 311  LCDSetLine(19, 74, 23, 74, RED);
 312  LCDSetLine(19, 80, 23, 80, RED);
 313  LCDSetLine(19, 81, 23, 81, RED);
 314  
 315  
 316   
 317  LCDSetLine(73,65,73, 131, WHITE); // Position division
 318  LCDSetLine(74,65,74, 131, WHITE); 
 319   
 320  LCDSetLine(0,130,130, 130, WHITE); // Date division
 321  LCDSetLine(0,129,130,129, WHITE); 
 322  
 323  putBackground();
 324} 
 325 
 326void loop() 
 327{
 328  int  px,py;
 329  int  dd,ee;
 330  char  str_tmp[16];
 331  int xxx,yyy;
 332
 333  
 334  //Put World Name centered
 335  px=(132-(stringLen*8))/2;
 336  lcd_clear(WHITE,116,0,131,131);
 337  LCDPutStr(World_name,       116, px, LARGE,  BLACK,  WHITE);
 338  
 339  //Put Time
 340  if (Hour==24) Hour=0;
 341  sprintf(str_tmp,"%02d:%02d",Hour,Minute);
 342  LCDPutStr(str_tmp, 5, 95, SMALL,WHITE,BLACK);
 343  
 344  //Put Date 
 345  sprintf(str_tmp,"%02d", Day);
 346  LCDPutStr(str_tmp, 25,73,SMALL,RED,BLACK);  
 347  sprintf(str_tmp,"%02d/%02d", Month,Year);
 348  LCDPutStr(str_tmp, 25,95,SMALL,WHITE,BLACK);  
 349  
 350  //Put coordenates
 351  LCDPutStr("X: ",            43, 73, SMALL,  WHITE,  BLACK);
 352  LCDPutStr(PosX_str,         43, 86, SMALL,  WHITE,  BLACK);
 353  LCDPutStr("Y: ",            53, 73, SMALL, WHITE,  BLACK);
 354  LCDPutStr(PosY_str,         53, 86, SMALL,  WHITE,  BLACK);
 355  LCDPutStr("Z: ",            63, 73, SMALL, WHITE,  BLACK);
 356  LCDPutStr(PosZ_str,         63, 86, SMALL,  WHITE,  BLACK);  //  LCDPutStr("6x8  How'r'u?",            24, 1, SMALL,  GREEN,  BLACK);
 357  
 358  xxx=PosXSun;
 359  yyy=PosYSun;
 360  calculatePosSunMoon();
 361  if ((xxx!=PosXSun) | (yyy!=PosYSun)){
 362    if ((Hour<21) & (Hour>6)) drawSunMoon(PosXSun,PosYSun,YELLOW);
 363    else drawSunMoon(PosXSun,PosYSun,WHITE);
 364  }
 365 // drawCloud1(-3,12);
 366 // drawCloud2(23,35);
 367  drawStormIcon(68,77);
 368  if (Raining==1) {
 369     lcd_clear(BLACK,96,68,110,83);
 370     drawRainIcon(68,96);
 371  }
 372  else {
 373     lcd_clear(BLACK,96,68,110,83);
 374     lcd_clear(YELLOW,99,71,109,81);
 375  }
 376  //Put Rain time
 377  calculateTime(Rain_time);
 378  if(dayTmp>0)  sprintf(str_tmp,"%d days",dayTmp);
 379  else {
 380     if (hourTmp==24) hourTmp=0;  
 381     sprintf(str_tmp,"%02d:%02d  ",hourTmp,minuteTmp);
 382  }
 383  LCDPutStr(str_tmp, 102, 86, SMALL,WHITE,BLACK);
 384  //Put thunder time
 385  calculateTime(Thunder_time);
 386  if(dayTmp>0)  sprintf(str_tmp,"%d days",dayTmp);
 387  else {
 388     if (hourTmp==24) hourTmp=0;  
 389     sprintf(str_tmp,"%02d:%02d  ",hourTmp,minuteTmp);
 390  }
 391  if(Raining==1)
 392     LCDPutStr(str_tmp, 82, 86, SMALL,WHITE,BLACK);
 393  else 
 394     LCDPutStr(" Clear ", 82, 86, SMALL,WHITE,BLACK);
 395  inByte=Serial.read();
 396  
 397  if(inByte=='@'){
 398     recibe_trama();
 399     command_process();
 400  }
 401 
 402} 
 403
 404
 405
 406
 407/*************************************************************/
 408/*            Function definitions                           */
 409/*************************************************************/
 410void putBackground(){
 411  lcd_clear(0xF30,0,0,114,64);
 412  bitmap(1,54,0);  //Put world
 413}
 414
 415void calculatePositionSun(){
 416  PosXSun=0;
 417  PosYSun=0;
 418  
 419}
 420
 421void Inicia_buffer(){
 422   memset(buffer, '\0', 128);
 423}
 424
 425void contrastPlus(){
 426   long dd,ddd;
 427   static long lasttime;
 428   if (millis()<lasttime) lasttime=millis();
 429   if((lasttime+BOUNCE_DURATION)>millis()) return;
 430   lasttime=millis();
 431   contrast_value++;
 432   lcd_contrast(contrast_value); 
 433}
 434
 435void contrastMinus(){
 436   long dd,ddd;
 437   static long lasttime;
 438   if (millis()<lasttime) lasttime=millis();
 439   if((lasttime+BOUNCE_DURATION)>millis()) return;
 440   lasttime=millis();
 441   contrast_value--;
 442   lcd_contrast(contrast_value); 
 443}
 444
 445void drawSunMoon(int pX, int pY,int color){
 446   int backColor=0xF30;
 447   switch (levelLight){
 448      case 0:
 449        backColor=0xF30;
 450      break;
 451      case 1:
 452        backColor=0xE20;
 453      break;
 454      case 2:
 455        backColor=0xD10;
 456      break;
 457      case 3:
 458        backColor=0xC00;
 459      break;
 460      case 4:
 461        backColor=0xB00;
 462      break;
 463      case 5:
 464        backColor=0xA00;
 465      break;  
 466   }
 467   lcd_clear(backColor,0,0,53,64);
 468   if (pX<55) LCDSetRect(pY, pX, pY+10, pX+10, FILL, color);   // Draw sun  
 469   else LCDSetRect(pY, pX, pY+10, pX+64-pX, FILL, color);   
 470}
 471
 472void drawCloud1(int pX,int pY){
 473  // Part white in cloud1
 474   unsigned char linW [64] PROGMEM ={ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9,
 475                                      2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
 476  //Part grey in cloud1           
 477   unsigned char linG [64] PROGMEM ={ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7,
 478                                      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 8};  
 479   byte fin=32;    
 480   if((pX+32)>64) fin=64-pX;
 481   for (int o=0 ; o<fin ; o++){
 482      LCDSetLine(pY+linW[o],pX,pY+linW[o+32], pX, WHITE); 
 483      LCDSetLine(pY+linG[o],pX,pY+linG[o+32], pX, GREY); 
 484      if(o==10){
 485         LCDSetLine(pY+7,pX,pY+9, pX, WHITE);   
 486         LCDSetPixel(pY+6,pX,GREY);
 487      }
 488      if(o==11){
 489         LCDSetLine(pY+8,pX,pY+9, pX, WHITE);   
 490         LCDSetLine(pY+6,pX,pY+7, pX, GREY);   
 491      }
 492      if(o==12){
 493         LCDSetPixel(pY+9,pX,WHITE);
 494         LCDSetLine(pY+7,pX,pY+8, pX, GREY);   
 495      }
 496      pX++;
 497   } 
 498}
 499
 500void drawCloud2(int pX,int pY){
 501  // Part white in cloud1
 502   unsigned char linW [88] PROGMEM ={ 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
 503                                      2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15};
 504  //Part grey in cloud1           
 505   unsigned char linG [88] PROGMEM ={ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,
 506                                      1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14};  
 507   byte fin=44;    
 508   if((pX+44)>64) fin=64-pX;
 509   for (int o=0 ; o<fin ; o++){
 510      LCDSetLine(pY+linW[o],pX,pY+linW[o+44], pX, WHITE); 
 511      LCDSetLine(pY+linG[o],pX,pY+linG[o+44], pX, GREY); 
 512      if(o==24){
 513         LCDSetPixel(pY+2,pX,WHITE);
 514         LCDSetPixel(pY+1,pX,GREY);
 515      }
 516      if(o==25){
 517         LCDSetLine(pY+2,pX,pY+3, pX, WHITE);   
 518         LCDSetLine(pY+0,pX,pY+1, pX, GREY);   
 519      }
 520      if(o==26){
 521         LCDSetLine(pY+2,pX,pY+4, pX, WHITE);   
 522         LCDSetLine(pY+0,pX,pY+1, pX, GREY);   
 523      }
 524      if(o==27){
 525         LCDSetLine(pY+2,pX,pY+5, pX, WHITE);   
 526         LCDSetLine(pY+0,pX,pY+1, pX, GREY);   
 527      }
 528      if(o==28){
 529         LCDSetLine(pY+2,pX,pY+6, pX, WHITE);   
 530         LCDSetLine(pY+0,pX,pY+1, pX, GREY);   
 531      }
 532      if(o==29){
 533         LCDSetLine(pY+2,pX,pY+7, pX, WHITE);   
 534         LCDSetLine(pY+0,pX,pY+1, pX, GREY);   
 535      }
 536      pX++;
 537   } 
 538}
 539
 540void calculatePosSunMoon(){
 541   int www;
 542    www=(Hour*60)+Minute;
 543    //Sunshine
 544    if ((www>420) & (www<480)) {
 545       PosXSun=((www-420)/6)-10; 
 546       PosYSun=22-((www-420)/8); 
 547       if (levelLight!=5-((www-420)/12)){
 548         levelLight=5-((www-420)/12);
 549         putBackground();
 550       }  
 551    }  
 552    //sunrising
 553    else if ((www>1200) & (www<1260)) {
 554       PosXSun=54+((www-1200)/6);
 555       PosYSun=15+((www-1200)/8);
 556       if (((www-1200)/12)!=levelLight){
 557         levelLight=((www-1200)/12);
 558         putBackground();
 559       }       
 560    }
 561    
 562    else if ((www>480) & (www<1200)) {
 563       PosXSun=(www-480)/13; 
 564       PosYSun=15;
 565       if (levelLight!=0){
 566          levelLight=0;
 567          putBackground();         
 568       } 
 569    }
 570    //Moon down
 571    else if ((www>360)&(www<=420)){
 572       PosXSun=54+((www-360)/6);
 573       PosYSun=15+((www-360)/8);
 574    }
 575    //Moon up
 576    else if ((www>=1260)&(www<1320)){   
 577       PosXSun=((www-1260)/6)-10;
 578       PosYSun=22-((www-1260)/8);  
 579       if (levelLight<5){
 580          levelLight=5;
 581          putBackground();         
 582       }      
 583    }
 584    else if ((www>=1320)&(www<=1440)){
 585       PosXSun=((www-1320)/11);
 586       PosYSun=15;         
 587    }
 588    else if ((www>=0)&(www<=360)){
 589       PosXSun=11+(www/11);
 590       PosYSun=15;         
 591    }
 592    
 593}
 594
 595void drawStormIcon(byte pX,byte pY){
 596    LCDSetLine(0+pY,7+pX,7+pY,14+pX, YELLOW);
 597    LCDSetLine(7+pY,14+pX,4+pY,3+pX,YELLOW);
 598    LCDSetLine(4+pY,3+pX,15+pY,10+pX,YELLOW);
 599    LCDSetLine(15+pY,10+pX,13+pY,6+pX,YELLOW);
 600    LCDSetLine(15+pY,10+pX,11+pY,10+pX,YELLOW);    
 601}
 602
 603void drawRainIcon(byte pX, byte pY){
 604    LCDSetLine(2+pY,3+pX,4+pY,3+pX,BLUE);
 605    LCDSetLine(3+pY,2+pX,3+pY,4+pX,BLUE);
 606    
 607    LCDSetRect(2+pY,12+pX,3+pY,13+pX, NOFILL, BLUE);   // Draw box 
 608    LCDSetRect(3+pY,9+pX,4+pY,10+pX, NOFILL, BLUE);   // Draw box 
 609    LCDSetRect(4+pY,11+pX,5+pY,12+pX, NOFILL, BLUE);   // Draw box 
 610    LCDSetRect(6+pY,10+pX,7+pY,11+pX, NOFILL, CYAN);   // Draw box 
 611    LCDSetRect(5+pY,13+pX,6+pY,14+pX, NOFILL, CYAN);   // Draw box 
 612    
 613    LCDSetRect(8+pY,5+pX,9+pY,6+pX, NOFILL, CYAN2);   // Draw box
 614    LCDSetRect(9+pY,4+pX,10+pY,5+pX, NOFILL, CYAN2);   // Draw box
 615    LCDSetRect(9+pY,1+pX,10+pY,2+pX, NOFILL, CYAN2);   // Draw box
 616    LCDSetRect(10+pY,2+pX,11+pY,3+pX, NOFILL, CYAN2);   // Draw box
 617    LCDSetRect(11+pY,5+pX,12+pY,6+pX, NOFILL, CYAN);   // Draw box
 618    LCDSetRect(12+pY,3+pX,13+pY,4+pX, NOFILL, CYAN);   // Draw box
 619    LCDSetRect(12+pY,6+pX,13+pY,7+pX, NOFILL, CYAN);   // Draw box
 620    LCDSetRect(13+pY,2+pX,14+pY,3+pX, NOFILL, CYAN);   // Draw box 
 621}
 622
 623void calculateTime(long ttt){
 624
 625  hourTmp=0;
 626  minuteTmp=0;
 627  dayTmp=0;
 628  minuteTmp=ttt/16.6666667;
 629
 630  
 631  if(minuteTmp>1440) {
 632     dayTmp=minuteTmp/1440;
 633     minuteTmp=0;
 634  }
 635  else {
 636     minuteTmp+=Minute;
 637     if (minuteTmp>59) {
 638        hourTmp+=(minuteTmp/60);
 639        minuteTmp=minuteTmp%60;
 640     }
 641     hourTmp+=Hour;
 642     if (hourTmp>24){
 643        dayTmp+=hourTmp/24; 
 644     }
 645  }
 646}
 647
 648void recibe_trama(){
 649 /* byte inByte = '\0';
 650   while(inByte != inicio_trama) {
 651    while(!Serial.available());            // wait for input
 652    inByte = Serial.read(); // Wait for the start of the message
 653   }*/ 
 654   
 655    detachInterrupt(0);    //Save from resets by overflow
 656    detachInterrupt(1);    //Save from resets by overflow
 657    Inicia_buffer();
 658    index=0;
 659    do{
 660      while(!Serial.available());            // wait for input
 661      buffer[index] = Serial.read();       // get it
 662     // Serial.print(buffer[index]);
 663      if (buffer [index] == fin_trama) break;
 664    } while (++index < long_buffer);
 665       
 666    buffer[index] = 0;                     // null terminate the string*/
 667
 668  //Restore external interrupts
 669  attachInterrupt(0, contrastPlus, RISING);
 670  attachInterrupt(1, contrastMinus, RISING);
 671   
 672}
 673
 674///////////////////////////////////////
 675//  Limpiar variables de string
 676///////////////////////////////////////
 677void limpia_strings(){
 678 int f;
 679 for(f=0;f<16;f++){
 680   if (f<3){
 681      Hour_str[f]=0x00;
 682      Minute_str[f]=0x00;
 683      Day_str[f]=0x00;
 684      Month_str[f]=0x00;      
 685   }
 686   if (f<5) Year_str[f]=0x00;
 687   if (f<8){ 
 688      PosX_str[f]=0x00;
 689      PosY_str[f]=0x00;
 690      PosZ_str[f]=0x00;
 691   }
 692   if (f<10){ 
 693      dist_to_spawn_str[f]=0x00;
 694      Time_str[f]=0x00;
 695      Rain_time_str[f]=0x00;
 696      Thunder_time_str[f]=0x00;
 697   }
 698
 699   World_name[f]=0x00;
 700 }
 701
 702}
 703
 704/***************************************************************
 705** Parser del Buffer
 706**
 707**  String data format
 708**
 709**  @           //Start character
 710**  int <time> 
 711**  int <min>
 712**  int <hour>
 713**  int <day>
 714**  int <month>
 715**  int <year>
 716**  bool <sun?>
 717**  bool <moon?>
 718**  int <raining time left>
 719**  int <thundering time left>
 720**  bool <raining?>
 721**  bool <thundering?>
 722**  float <pos_x>
 723**  float <pos_y>
 724**  float <pos_z>
 725**  float <distance to spawn from player>
 726**  char* <name of world>
 727**  #          //End character
 728**
 729**
 730**  Data string sample:
 731**  @1232144,55,21,18,9,1974,1,0,12500,20000,0,0,12.6584,24.6854,-2.2359,145875,Twin Peaks#
 732**
 733****************************************************************/
 734void command_process(){
 735
 736  int i,j;
 737  limpia_strings();                 //Limpiar todas las cadenas
 738  i=0;
 739   //Tiempo
 740   j=0;
 741   while (buffer[i]!=','){
 742      Time_str[j++]=buffer[i];
 743      i++;
 744   }
 745   Time=atol(Time_str);
 746
 747   i++;
 748   //Minutos
 749   j=0;
 750   while (buffer[i]!=','){
 751      Minute_str[j++]=buffer[i];
 752      i++;
 753   }
 754   Minute=atoi(Minute_str);
 755   i++;
 756   //Horas
 757   j=0;
 758   while (buffer[i]!=','){
 759      Hour_str[j++]=buffer[i];
 760      i++;
 761   }
 762   Hour=atoi(Hour_str); 
 763   i++;
 764   //Dia
 765   j=0;
 766   while (buffer[i]!=','){
 767      Day_str[j++]=buffer[i];
 768      i++;
 769   }
 770   Day=atoi(Day_str);
 771   i++;
 772   //Mes
 773   j=0;
 774   while (buffer[i]!=','){
 775      Month_str[j++]=buffer[i];
 776      i++;
 777   }
 778   Month=atoi(Month_str);
 779   i++ ;  
 780   //A単o
 781   j=0;
 782   while (buffer[i]!=','){
 783      Year_str[j++]=buffer[i];
 784      i++;
 785   }
 786   Year=atoi(Year_str);
 787   i++;
 788   //Sun FLag
 789   if(buffer[i]=='1') Sun=1;
 790   else Sun=0;
 791   i+=2;
 792   //Moon FLag
 793   if(buffer[i]=='1') Moon=1;
 794   else Moon=0;
 795   i+=2;
 796   //Rain Time
 797   j=0;
 798   while (buffer[i]!=','){
 799      Rain_time_str[j++]=buffer[i];
 800      i++;
 801   }
 802   Rain_time=atol(Rain_time_str);
 803   i++;
 804   //Thundering Time
 805   j=0;
 806   while (buffer[i]!=','){
 807      Thunder_time_str[j++]=buffer[i];
 808      i++;
 809   }
 810   Thunder_time=atol(Thunder_time_str);
 811   
 812   i++;
 813   //Raining FLag
 814   if(buffer[i]=='1') Raining=1;
 815   else Raining=0;
 816   i+=2;
 817   //Thundering flag
 818   if(buffer[i]=='1') Thundering=1;
 819   else Thundering=0;
 820   i+=2;
 821   //PosX
 822   j=0;
 823   while (buffer[i]!=','){
 824      if (j<7) PosX_str[j++]=buffer[i];
 825      i++;
 826   }
 827   //PosX=atof(PosX_str);
 828   i++;
 829   //PosY
 830   j=0;
 831   while (buffer[i]!=','){
 832      if (j<7) PosY_str[j++]=buffer[i];
 833      i++;
 834   }
 835   //PosY=atof(PosY_str);
 836   i++;
 837   //PosZ
 838   j=0;
 839   while (buffer[i]!=','){
 840      if (j<7) PosZ_str[j++]=buffer[i];
 841      i++;
 842   }
 843   //PosZ=atof(PosZ_str);
 844   i++;
 845   //Distance to Spawn
 846   j=0;
 847   while (buffer[i]!=','){
 848      dist_to_spawn_str[j++]=buffer[i];
 849      i++;
 850   }
 851   dist_to_spawn=atof(dist_to_spawn_str);
 852   i++;   
 853    //World Name
 854   j=0;
 855   stringLen=0;
 856   while (buffer[i]!='\0'){
 857      World_name[j++]=buffer[i];
 858      i++;
 859      stringLen++;
 860   }
 861   Inicia_buffer(); // Borro buffer.
 862}
 863
 864/**************************************/
 865/*   Change LCD contrast              */
 866/**************************************/
 867void lcd_contrast(int value){
 868   sendCMD(SETCON);  // Set Contrast
 869   sendData(value); 
 870   Serial.print("contraste:");
 871 
 872   Serial.println(value);
 873   
 874   delay(80); 
 875}
 876
 877/**************************************/
 878/*        Sending command             */
 879/**************************************/
 880void sendCMD(byte data) 
 881{
 882     byte i;
 883
 884    LCD_DATA(0);                     // set up first bit as command or data 
 885    LCD_CS(0);                     // Enable device CS
 886
 887    LCD_CLK(0);                     // Pull Clock LOW
 888    LCD_CLK(1);                     // Pul Clock HIGH
 889    
 890    if(data == 0x0){        // spi cannot transfer zero??
 891      LCD_DATA(0);
 892      for(i=0; i<8; i++){
 893      
 894        LCD_CLK(0);                     // Pull Clock LOW
 895        LCD_CLK(1);   
 896      }
 897    }
 898    else{
 899    SPCR |=0x50;                  // Enable Hardware SPI
 900    SPSR |= 0x1;
 901    SPDR = data;                   // send data
 902    
 903    while(!(SPSR & 0x80));            // wait until send complete
 904
 905    }
 906
 907    SPCR &=~0x50;                  // Disable Hardware SPI, this releases the SPI pins
 908                              // for general IO use. which is used to send the 1'st 
 909      LCD_CS(1);                     // disable device CS                           // bit out
 910 /* CS1
 911  CLK0
 912  CS0
 913  SDA0
 914  CLK1
 915  CLK0
 916
 917  shiftBits(data);
 918  CLK0
 919  CS1*/
 920}
 921/**************************************/
 922/*        Sending data                */
 923/**************************************/
 924void sendData(byte data) {
 925   byte i;
 926
 927    LCD_DATA(1);                     // set up first bit as command or data 
 928    LCD_CS(0);                     // Enable device CS
 929
 930    LCD_CLK(0);                     // Pull Clock LOW
 931    LCD_CLK(1);                     // Pul Clock HIGH
 932    
 933    if(data == 0x0){        // spi cannot transfer zero??
 934      LCD_DATA(0);
 935      for(i=0; i<8; i++){
 936      
 937        LCD_CLK(0);                     // Pull Clock LOW
 938        LCD_CLK(1);   
 939      }
 940    }
 941    else{
 942    SPCR |=0x50;                  // Enable Hardware SPI
 943    SPSR |= 0x1;
 944    SPDR = data;                   // send data
 945    
 946    while(!(SPSR & 0x80));            // wait until send complete
 947
 948    }
 949
 950    SPCR &=~0x50;                  // Disable Hardware SPI, this releases the SPI pins
 951                              // for general IO use. which is used to send the 1'st 
 952      LCD_CS(1);                     // disable device CS                           // bit out  
 953/*  CS1
 954  CLK0
 955  CS0
 956  SDA1
 957  CLK1
 958  CLK0
 959
 960  shiftBits(data);
 961  CLK0
 962  CS1*/
 963}
 964/**************************************/
 965/*        Shifting SPI bit out        */
 966/**************************************/
 967void shiftBits(byte data) 
 968{
 969  byte Bit;
 970  
 971  for (Bit = 0; Bit < 8; Bit++)     // 8 Bit Write
 972  {
 973    CLK0          // Standby SCLK
 974    if((data&0x80)>>7)
 975    {
 976      SDA1
 977    }
 978    else
 979    {
 980      SDA0
 981    }
 982    CLK1          // Strobe signal bit 
 983    data <<= 1;   // Next bit data
 984  }  
 985}
 986/**************************************/
 987/*        Initialize LCD              */
 988/**************************************/
 989void lcd_init()
 990{
 991  /* // Initial state
 992  CLK0
 993  CS1
 994  SDA1
 995  
 996  // Hardware Reset LCD
 997  RESET0
 998  delay(100);
 999  RESET1
1000  delay(100);*/
1001    LCD_CS(1);
1002    LCD_CLK(0);
1003    LCD_DATA(0);
1004
1005    LCD_RESET(1);
1006    delay(50);
1007    LCD_RESET(0);
1008    delay(50);
1009    LCD_RESET(1);
1010    delay(50);
1011
1012    LCD_CS(1);
1013    LCD_CLK(1);
1014    LCD_DATA(1);
1015    delay(10);
1016  // Sleep out (commmand 0x11)
1017  sendCMD(SLEEPOUT);
1018  
1019  // Inversion on (command 0x20)
1020  //sendCMD(INVON);    // seems to be required for this controller
1021  sendCMD(INVOFF); 
1022  
1023  // Color Interface Pixel Format (command 0x3A)
1024  sendCMD(COLMOD);
1025  sendData(0x03);    // 0x03 = 12 bits-per-pixel
1026  
1027  // Memory access controler (command 0x36)
1028  sendCMD(MADCTL);
1029  sendData(0b11010110); //C8); // 0xC0 = mirror x and y, reverse rgb
1030  
1031  // Write contrast (command 0x25)
1032  sendCMD(SETCON);
1033  sendData(0x3C); // contrast 0x30
1034  delay(1000);
1035
1036  // Display On (command 0x29)
1037  sendCMD(DISPON);
1038}
1039/**************************************/
1040/*       Draw a demo color bar        */
1041/**************************************/
1042void draw_color_bar()
1043{
1044  lcd_clear(RED,0,0,131,33);
1045  lcd_clear(GREEN,0,34,131,66);
1046  lcd_clear(BLUE,0,67,131,99);
1047  lcd_clear(WHITE,0,100,131,131);
1048}
1049/**************************************/
1050/* Clear LCD from (x0,y0) to (x1,y1)  */
1051/**************************************/
1052void lcd_clear(uint16_t color, byte x0, byte y0, byte x1, byte y1)
1053{
1054  uint16_t xmin, xmax, ymin, ymax;
1055  uint16_t i;
1056  
1057  // best way to create a filled rectangle is to define a drawing box
1058  // and loop two pixels at a time
1059  // calculate the min and max for x and y directions
1060  xmin = (x0 <= x1) ? x0 : x1;
1061  xmax = (x0 > x1) ? x0 : x1;
1062  ymin = (y0 <= y1) ? y0 : y1;
1063  ymax = (y0 > y1) ? y0 : y1;
1064
1065  // specify the controller drawing box according to those limits
1066  // Row address set (command 0x2B)
1067  sendCMD(PASET);
1068  sendData(xmin);
1069  sendData(xmax);
1070
1071  // Column address set (command 0x2A)
1072  sendCMD(CASET);
1073  sendData(ymin);
1074  sendData(ymax);
1075
1076  // WRITE MEMORY
1077  sendCMD(RAMWR);
1078
1079  // loop on total number of pixels / 2
1080  for (i = 0; i < ((((xmax - xmin + 1) * (ymax - ymin + 1)) / 2) + 1); i++) 
1081  {
1082    // use the color value to output three data bytes covering two pixels
1083    // For some reason, it has to send blue first then green and red
1084    sendData((color << 4) | ((color & 0xF0) >> 4));
1085    sendData(((color >> 4) & 0xF0) | (color & 0x0F));
1086    sendData((color & 0xF0) | (color >> 8));
1087  }
1088}
1089// *************************************************************************************************
1090// LCDPutStr.c
1091//
1092// Draws a null-terminates character string at the specified (x,y) address, size and color
1093//
1094// Inputs: pString = pointer to character string to be displayed
1095// x = row address (0 .. 131)
1096// y = column address (0 .. 131)
1097// Size = font pitch (SMALL, MEDIUM, LARGE)
1098// fColor = 12-bit foreground color value rrrrggggbbbb
1099// bColor = 12-bit background color value rrrrggggbbbb
1100//
1101//
1102// Returns: nothing
1103//
1104// Notes: Here's an example to display "Hello World!" at address (20,20)
1105//
1106// LCDPutChar("Hello World!", 20, 20, LARGE, WHITE, BLACK);
1107//
1108//
1109// Author: James P Lynch July 7, 2007
1110// *************************************************************************************************
1111void LCDPutStr(char *pString, int x, int y, int Size, int fColor, int bColor)
1112{
1113  // loop until null-terminator is seen
1114  while (*pString != 0x00) 
1115  {
1116    // draw the character
1117    LCDPutChar(*pString++, x, y, Size, fColor, bColor);
1118
1119    // advance the y position
1120    if (Size == SMALL)
1121    y = y + 6;
1122
1123    else if (Size == MEDIUM)
1124    y = y + 8;
1125
1126    else
1127    y = y + 8;
1128
1129    // bail out if y exceeds 131
1130    if (y > 131) break;
1131  }
1132}
1133// *****************************************************************************
1134// LCDPutChar.c
1135//
1136// Draws an ASCII character at the specified (x,y) address and color
1137//
1138// Inputs: c = character to be displayed
1139// x = row address (0 .. 131)
1140// y = column address (0 .. 131)
1141// size = font pitch (SMALL, MEDIUM, LARGE)
1142// fcolor = 12-bit foreground color value rrrrggggbbbb
1143// bcolor = 12-bit background color value rrrrggggbbbb
1144//
1145//
1146// Returns: nothing
1147//
1148//
1149// Notes: Here's an example to display "E" at address (20,20)
1150//
1151// LCDPutChar('E', 20, 20, MEDIUM, WHITE, BLACK);
1152//
1153// (27,20) (27,27)
1154// | |
1155// | |
1156// ^ V V
1157// : _ # # # # # # # 0x7F
1158// : _ _ # # _ _ _ # 0x31
1159// : _ _ # # _ # _ _ 0x34
1160// x _ _ # # # # _ _ 0x3C
1161// : _ _ # # _ # _ _ 0x34
1162// : _ _ # # _ _ _ # 0x31
1163// : _ # # # # # # # 0x7F
1164// : _ _ _ _ _ _ _ _ 0x00
1165//
1166// ------y------->
1167// ^ ^
1168// | |
1169// | |
1170// (20,20) (20,27)
1171//
1172//
1173// The most efficient way to display a character is to make use of the "wrap-around" feature
1174// of the Philips PCF8833 LCD controller chip.
1175//
1176// Assume that we position the character at (20, 20) that's a (row, col) specification.
1177// With the row and column address set commands, you can specify an 8x8 box for the SMALL and MEDIUM
1178// characters or a 16x8 box for the LARGE characters.
1179//
1180// WriteSpiCommand(PASET); // set the row drawing limits
1181// WriteSpiData(20); //
1182// WriteSpiData(27); // limit rows to (20, 27)
1183//
1184// WriteSpiCommand(CASET); // set the column drawing limits
1185// WriteSpiData(20); //
1186// WriteSpiData(27); // limit columns to (20,27)
1187//
1188// When the algorithm completes col 27, the column address wraps back to 20
1189// At the same time, the row address increases by one (this is done by the controller)
1190//
1191// We walk through each row, two pixels at a time. The purpose is to create three
1192// data bytes representing these two pixels in the following format (as specified by Philips
1193// for RGB 4 : 4 : 4 format (see page 62 of PCF8833 controller manual).
1194//
1195// Data for pixel 0: RRRRGGGGBBBB
1196// Data for Pixel 1: RRRRGGGGBBBB
1197//
1198// WriteSpiCommand(RAMWR); // start a memory write (96 data bytes to follow)
1199//
1200// WriteSpiData(RRRRGGGG); // first pixel, red and green data
1201// WriteSpiData(BBBBRRRR); // first pixel, blue data; second pixel, red data
1202// WriteSpiData(GGGGBBBB); // second pixel, green and blue data
1203// :
1204// and so on until all pixels displayed!
1205// :
1206// WriteSpiCommand(NOP); // this will terminate the RAMWR command
1207//
1208//
1209// Author: James P Lynch July 7, 2007
1210// *****************************************************************************
1211void LCDPutChar(char c, int x, int y, int size, int fColor, int bColor) 
1212{
1213  int i,j;
1214  unsigned int  nCols;
1215  unsigned int  nRows;
1216  unsigned int  nBytes;
1217  unsigned char PixelRow;
1218  unsigned char Mask;
1219  unsigned int  Word0;
1220  unsigned int  Word1;
1221  unsigned char *pFont;
1222  unsigned char *pChar;
1223  unsigned char *FontTable[] = {(unsigned char *)FONT6x8,
1224                                (unsigned char *)FONT6x8,
1225                                //(unsigned char *)FONT8x8,
1226                                (unsigned char *)FONT8x16};
1227
1228  // get pointer to the beginning of the selected font table
1229  pFont = (unsigned char *)FontTable[size];
1230
1231  /* get the nColumns, nRows and nBytes */
1232  //nCols = *pFont;
1233  nCols  = pgm_read_byte(&*pFont);         // Array Flash
1234  //nRows = *(pFont + 1);
1235  nRows  = pgm_read_byte(&*(pFont + 1));   // Array Flash
1236  //nBytes = *(pFont + 2);
1237  nBytes = pgm_read_byte(&*(pFont + 2));   // Array Flash
1238
1239  /* get pointer to the last byte of the desired character */
1240  //pChar = pFont + (nBytes * (c - 0x1F)) + nBytes - 1;
1241  pChar = pFont + (nBytes * (c - 0x1F));
1242  // Row address set (command 0x2B)
1243  sendCMD(PASET);
1244  sendData(x);
1245  sendData(x + nRows - 1);
1246
1247  // Column address set (command 0x2A)
1248  sendCMD(CASET);
1249  sendData(y);
1250  sendData(y + nCols - 1);
1251
1252  // WRITE MEMORY
1253  sendCMD(RAMWR);
1254  // loop on each row, working backwards from the bottom to the top
1255  for (i = nRows - 1; i >= 0; i--) 
1256  {
1257    /* copy pixel row from font table and then decrement row */
1258    //PixelRow = pgm_read_byte(&*pChar--);  // Array Flash
1259    //PixelRow = *pChar--;
1260    PixelRow = pgm_read_byte(&*pChar++);  // Array Flash
1261
1262    // loop on each pixel in the row (left to right)
1263    // Note: we do two pixels each loop
1264    Mask = 0x80;
1265    for (j = 0; j < nCols; j += 2) 
1266	{
1267      // if pixel bit set, use foreground color; else use the background color
1268      // now get the pixel color for two successive pixels
1269      if ((PixelRow & Mask) == 0)
1270        Word0 = bColor;
1271      else
1272        Word0 = fColor;
1273      Mask = Mask >> 1;
1274
1275      if ((PixelRow & Mask) == 0)
1276        Word1 = bColor;
1277      else
1278        Word1 = fColor;
1279      Mask = Mask >> 1;
1280      
1281      // use this information to output three data bytes
1282      // For some reason, it has to send blue first then green and red
1283      
1284      sendData((Word0 << 4) | ((Word0 & 0xF0) >> 4));
1285      sendData(((Word0 >> 4) & 0xF0) | (Word1 & 0x0F));
1286      sendData((Word1 & 0xF0) | (Word1 >> 8));
1287      
1288    }
1289  }
1290
1291  // terminate the Write Memory command
1292  sendCMD(NOP);
1293}
1294// *************************************************************************************************
1295// LCDSetLine.c
1296//
1297// Draws a line in the specified color from (x0,y0) to (x1,y1)
1298//
1299// Inputs: x = row address (0 .. 131)
1300// y = column address (0 .. 131)
1301// color = 12-bit color value rrrrggggbbbb
1302// rrrr = 1111 full red
1303// :
1304// 0000 red is off
1305//
1306// gggg = 1111 full green
1307// :
1308// 0000 green is off
1309//
1310// bbbb = 1111 full blue
1311// :
1312// 0000 blue is off
1313//
1314// Returns: nothing
1315//
1316// Note: good write-up on this algorithm in Wikipedia (search for Bresenham's line algorithm)
1317// see lcd.h for some sample color settings
1318//
1319// Authors: Dr. Leonard McMillan, Associate Professor UNC
1320// Jack Bresenham IBM, Winthrop University (Father of this algorithm, 1962)
1321//
1322// Note: taken verbatim from Professor McMillan's presentation:
1323// http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
1324//
1325// *************************************************************************************************
1326void LCDSetLine(int x0, int y0, int x1, int y1, int color) 
1327{
1328  int dy = y1 - y0;
1329  int dx = x1 - x0;
1330  int stepx, stepy;
1331  if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
1332  if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
1333  dy <<= 1; // dy is now 2*dy
1334  dx <<= 1; // dx is now 2*dx
1335  LCDSetPixel(x0, y0, color);
1336  if (dx > dy) 
1337  {
1338    int fraction = dy - (dx >> 1); // same as 2*dy - dx
1339    while (x0 != x1) 
1340    {
1341      if (fraction >= 0) 
1342      {
1343        y0 += stepy;
1344        fraction -= dx; // same as fraction -= 2*dx
1345      }
1346      x0 += stepx;
1347      fraction += dy; // same as fraction -= 2*dy
1348      LCDSetPixel(x0, y0, color);
1349    }
1350  } 
1351  else 
1352  {
1353    int fraction = dx - (dy >> 1);
1354    while (y0 != y1) 
1355	{
1356      if (fraction >= 0) 
1357	  {
1358        x0 += stepx;
1359        fraction -= dy;
1360      }
1361      y0 += stepy;
1362      fraction += dx;
1363      LCDSetPixel(x0, y0, color);
1364    }
1365  }
1366}
1367// *****************************************************************************************
1368// LCDSetRect.c
1369//
1370// Draws a rectangle in the specified color from (x1,y1) to (x2,y2)
1371// Rectangle can be filled with a color if desired
1372//
1373// Inputs: x = row address (0 .. 131)
1374// y = column address (0 .. 131)
1375// fill = 0=no fill, 1-fill entire rectangle
1376// color = 12-bit color value for lines rrrrggggbbbb
1377// rrrr = 1111 full red
1378// :
1379// 0000 red is off
1380//
1381// gggg = 1111 full green
1382// :
1383// 0000 green is off
1384//
1385// bbbb = 1111 full blue
1386// :
1387// 0000 blue is off
1388// Returns: nothing
1389//
1390// Notes:
1391//
1392// The best way to fill a rectangle is to take advantage of the "wrap-around" featute
1393// built into the Philips PCF8833 controller. By defining a drawing box, the memory can
1394// be simply filled by successive memory writes until all pixels have been illuminated.
1395//
1396// 1. Given the coordinates of two opposing corners (x0, y0) (x1, y1)
1397// calculate the minimums and maximums of the coordinates
1398//
1399// xmin = (x0 <= x1) ? x0 : x1;
1400// xmax = (x0 > x1) ? x0 : x1;
1401// ymin = (y0 <= y1) ? y0 : y1;
1402// ymax = (y0 > y1) ? y0 : y1;
1403//
1404// 2. Now set up the drawing box to be the desired rectangle
1405//
1406// WriteSpiCommand(PASET); // set the row boundaries
1407// WriteSpiData(xmin);
1408// WriteSpiData(xmax);
1409// WriteSpiCommand(CASET); // set the column boundaries
1410// WriteSpiData(ymin);
1411// WriteSpiData(ymax);
1412//
1413// 3. Calculate the number of pixels to be written divided by 2
1414//
1415// NumPixels = ((((xmax - xmin + 1) * (ymax - ymin + 1)) / 2) + 1)
1416//
1417// You may notice that I added one pixel to the formula.
1418// This covers the case where the number of pixels is odd and we
1419// would lose one pixel due to rounding error. In the case of
1420// odd pixels, the number of pixels is exact.
1421// in the case of even pixels, we have one more pixel than
1422// needed, but it cannot be displayed because it is outside
1423// the drawing box.
1424//
1425// We divide by 2 because two pixels are represented by three bytes.
1426// So we work through the rectangle two pixels at a time.
1427//
1428// 4. Now a simple memory write loop will fill the rectangle
1429//
1430// for (i = 0; i < ((((xmax - xmin + 1) * (ymax - ymin + 1)) / 2) + 1); i++) {
1431// WriteSpiData((color >> 4) & 0xFF);
1432// WriteSpiData(((color & 0xF) << 4) | ((color >> 8) & 0xF));
1433// WriteSpiData(color & 0xFF);
1434// }
1435//
1436// In the case of an unfilled rectangle, drawing four lines with the Bresenham line
1437// drawing algorithm is reasonably efficient.
1438//
1439// Author: James P Lynch July 7, 2007
1440// *****************************************************************************************
1441void LCDSetRect(int x0, int y0, int x1, int y1, unsigned char fill, int color) 
1442{
1443  int xmin, xmax, ymin, ymax;
1444  int i;
1445
1446  // check if the rectangle is to be filled
1447  if (fill == FILL) 
1448  {
1449    // best way to create a filled rectangle is to define a drawing box
1450    // and loop two pixels at a time
1451    // calculate the min and max for x and y directions
1452    xmin = (x0 <= x1) ? x0 : x1;
1453    xmax = (x0 > x1) ? x0 : x1;
1454    ymin = (y0 <= y1) ? y0 : y1;
1455    ymax = (y0 > y1) ? y0 : y1;
1456
1457    // specify the controller drawing box according to those limits
1458    // Row address set (command 0x2B)
1459    sendCMD(PASET);
1460    sendData(xmin);
1461    sendData(xmax);
1462
1463    // Column address set (command 0x2A)
1464    sendCMD(CASET);
1465    sendData(ymin);
1466    sendData(ymax);
1467
1468    // WRITE MEMORY
1469    sendCMD(RAMWR);
1470
1471    // loop on total number of pixels / 2
1472    for (i = 0; i < ((((xmax - xmin + 1) * (ymax - ymin + 1)) / 2) + 1); i++)
1473    {
1474      // use the color value to output three data bytes covering two pixels
1475      // For some reason, it has to send blue first then green and red
1476      sendData((color << 4) | ((color & 0xF0) >> 4));
1477      sendData(((color >> 4) & 0xF0) | (color & 0x0F));
1478      sendData((color & 0xF0) | (color >> 8));  
1479    }
1480  } 
1481  else 
1482  {
1483    // best way to draw un unfilled rectangle is to draw four lines
1484    LCDSetLine(x0, y0, x1, y0, color);
1485    LCDSetLine(x0, y1, x1, y1, color);
1486    LCDSetLine(x0, y0, x0, y1, color);
1487    LCDSetLine(x1, y0, x1, y1, color);
1488  }
1489}
1490
1491// *************************************************************************************
1492// LCDSetCircle.c
1493//
1494// Draws a line in the specified color at center (x0,y0) with radius
1495//
1496// Inputs: x0 = row address (0 .. 131)
1497// y0 = column address (0 .. 131)
1498// radius = radius in pixels
1499// color = 12-bit color value rrrrggggbbbb
1500//
1501// Returns: nothing
1502//
1503// Author: Jack Bresenham IBM, Winthrop University (Father of this algorithm, 1962)
1504//
1505// Note: taken verbatim Wikipedia article on Bresenham's line algorithm
1506// http://www.wikipedia.org
1507//
1508// *************************************************************************************
1509void LCDSetCircle(int x0, int y0, int radius, int color) 
1510{
1511  int f = 1 - radius;
1512  int ddF_x = 0;
1513  int ddF_y = -2 * radius;
1514  int x = 0;
1515  int y = radius;
1516  LCDSetPixel(x0, y0 + radius, color);
1517  LCDSetPixel(x0, y0 - radius, color);
1518  LCDSetPixel(x0 + radius, y0, color);
1519  LCDSetPixel(x0 - radius, y0, color);
1520  while (x < y) 
1521  {
1522    if (f >= 0) 
1523	{
1524      y--;
1525      ddF_y += 2;
1526      f += ddF_y;
1527    }
1528    x++;
1529    ddF_x += 2;
1530    f += ddF_x + 1;
1531    LCDSetPixel(x0 + x, y0 + y, color);
1532    LCDSetPixel(x0 - x, y0 + y, color);
1533    LCDSetPixel(x0 + x, y0 - y, color);
1534    LCDSetPixel(x0 - x, y0 - y, color);
1535    LCDSetPixel(x0 + y, y0 + x, color);
1536    LCDSetPixel(x0 - y, y0 + x, color);
1537    LCDSetPixel(x0 + y, y0 - x, color);
1538    LCDSetPixel(x0 - y, y0 - x, color);
1539   }
1540}
1541// *************************************************************************************
1542// LCDSetPixel.c
1543//
1544// Lights a single pixel in the specified color at the specified x and y addresses
1545//
1546// Inputs: x = row address (0 .. 131)
1547// y = column address (0 .. 131)
1548// color = 12-bit color value rrrrggggbbbb
1549// rrrr = 1111 full red
1550// :
1551// 0000 red is off
1552//
1553// gggg = 1111 full green
1554// :
1555// 0000 green is off
1556//
1557// bbbb = 1111 full blue
1558// :
1559// 0000 blue is off
1560//
1561// Returns: nothing
1562//
1563// Note: see lcd.h for some sample color settings
1564//
1565// Author: James P Lynch July 7, 2007
1566// Modified: Gravitech December 20, 2008
1567// *************************************************************************************
1568void LCDSetPixel(byte x, byte y, int color) 
1569{
1570  LCDSetXY(x, y);
1571  sendCMD(RAMWR);
1572  // For some reason, it has to send blue first then green and red
1573  sendData((color << 4) | ((color & 0xF0) >> 4));
1574  sendData(((color >> 4) & 0xF0));
1575  sendCMD(NOP);
1576}
1577// *****************************************************************************
1578// LCDSetXY.c
1579//
1580// Sets the Row and Column addresses
1581//
1582// Inputs: x = row address (0 .. 131)
1583// y = column address (0 .. 131)
1584//
1585//
1586// Returns: nothing
1587//
1588// Author: James P Lynch July 7, 2007
1589// Modified: Gravitech December 20, 2008
1590// *****************************************************************************
1591void LCDSetXY(byte x, byte y) 
1592{
1593  // Row address set (command 0x2B)
1594  sendCMD(PASET);
1595  sendData(x);
1596  sendData(x);
1597
1598  // Column address set (command 0x2A)
1599  sendCMD(CASET);
1600  sendData(y);
1601  sendData(y);
1602}
1603
1604void SendLcd_color(unsigned char color){
1605  
1606    LCD_DATA(LCDData);                     // set up first bit as command or data 
1607
1608    LCD_CLK(0);                     // Pull Clock LOW
1609    LCD_CLK(1);                     // Pul Clock HIGH
1610    LCD_CLK(0);  
1611    SPCR |=0x50;                  // Enable Hardware SPI
1612    SPSR |=0x1;
1613
1614    SPDR = color;                   // send data
1615    
1616    while(!(SPSR & 0x80));            // wait until send complete
1617
1618                  // disable device CS
1619
1620    SPCR &=~0x50;                  // Disable Hardware SPI, this releases the SPI pins
1621   
1622   LCD_CLK(0);                              // for general IO use. which is used to send the 1'st 
1623                           // bit out
1624}
1625
1626void LCDBitmap (unsigned char start_x, unsigned char start_y, unsigned char h_size, unsigned char v_size, unsigned char *bitmap_data) 
1627{
1628   int i;
1629   unsigned char *pBitmap;
1630   // specify the controller drawing box according to those limits 
1631      // Row address set  (command 0x2B) 
1632      sendCMD(PASET); 
1633      sendData(start_x); 
1634      sendData( start_x+h_size-1); 
1635      // Column address set  (command 0x2A) 
1636      sendCMD(CASET); 
1637      sendData(start_y); 
1638      sendData(start_y+v_size-1); 
1639 
1640      // WRITE MEMORY 
1641      sendCMD(RAMWR); 
1642
1643   pBitmap = bitmap_data;                
1644               
1645      // loop on total number of pixels / 2 
1646      for (i = 0; i< (h_size*v_size)>>1  ; i++) { 
1647         unsigned char bitmap;                  
1648
1649        LCD_CS(0);
1650        
1651          bitmap = pgm_read_byte(pBitmap++);
1652          if (levelLight>0){
1653             if ((bitmap & 0b00001111)>levelLight) bitmap=bitmap-levelLight;
1654             else bitmap=bitmap&0b11110000;
1655             if ((bitmap & 0b11110000)>(levelLight<<4)) bitmap=bitmap-(levelLight<<4);
1656             else bitmap=bitmap & 0b00001111;
1657          }
1658          SendLcd_color(bitmap); 
1659          
1660          bitmap =pgm_read_byte(pBitmap++);
1661           if (levelLight>0){
1662             if ((bitmap & 0b00001111)>levelLight) bitmap=bitmap-levelLight;
1663             else bitmap=bitmap&0b11110000;
1664             if ((bitmap & 0b11110000)>(levelLight<<4)) bitmap=bitmap-(levelLight<<4);
1665             else bitmap=bitmap & 0b00001111;
1666          }
1667          SendLcd_color(bitmap); 
1668          
1669          bitmap =pgm_read_byte(pBitmap++);
1670           if (levelLight>0){
1671             if ((bitmap & 0b00001111)>levelLight) bitmap=bitmap-levelLight;
1672             else bitmap=bitmap&0b11110000;
1673             if ((bitmap & 0b11110000)>(levelLight<<4)) bitmap=bitmap-(levelLight<<4);
1674             else bitmap=bitmap & 0b00001111;
1675          }
1676          SendLcd_color(bitmap); 
1677          
1678          LCD_CS(1);
1679      } 
1680    sendCMD(NOP); 
1681}
1682
1683void bitmap(int y,int x, char bmp){
1684  unsigned char *pbitmap;
1685  byte image_h, image_w;
1686  switch (bmp){
1687   case 0:
1688   // pbitmap=barra;
1689   pbitmap=image;
1690   break;
1691   case 1:
1692    //pbitmap=lateralizquierdo;
1693   break;
1694   case 2:
1695    //pbitmap=lateralderecho;
1696   break;    
1697  }
1698  
1699  image_w = pgm_read_byte(pbitmap+1);
1700  image_h = pgm_read_byte(pbitmap+2);
1701
1702   LCDBitmap(x, y, image_w, image_h, pbitmap+5);
1703  
1704}