1 /*********************************************************************
   2     FileName:           Display.c
   3     Dependencies:       See #includes
   4     Processor:          PIC32MZ
   5     Hardware:           MainBrain MZ
   6     Complier:           XC32 4.40
   7     Author:             Larry Knight 2023
   8 /*********************************************************************
   9  
  10     Software License Agreement:
  11  
  12     Licensed under the Apache License, Version 2.0 (the "License");
  13     you may not use this file except in compliance with the License.
  14     You may obtain a copy of the License at
  15 
  16     http://www.apache.org/licenses/LICENSE-2.0
  17 
  18     Unless required by applicable law or agreed to in writing, software
  19     distributed under the License is distributed on an "AS IS" BASIS,
  20     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21     See the License for the specific language governing permissions and
  22     limitations under the License.
  23  
  24     Description:
  25         System Clock = 200 - 250 MHz
  26 
  27     File Description:
  28 
  29     Change History:
  30  
  31 /***********************************************************************/
  32 
  33 #include <string.h>
  34 #include <xc.h>
  35 #include "MainBrain.h"
  36 
  37 uint8_t back_level;
  38 int CanvasColor;
  39 int TextColor;
  40 unsigned ascii_char;
  41 int color1;
  42 int color2;
  43 uint16_t hchar;
  44 uint16_t vchar;
  45 uint8_t Display_Read;
  46 uint8_t disData[10];
  47 unsigned row_start;
  48 unsigned row_end;
  49 unsigned col_start;
  50 unsigned col_end;
  51 int t;
  52 
  53 void Backlight_Control(uint8_t back_level)
  54 {   
  55     //PWM Setup for backlight control
  56     //sets frequency
  57     PR2 = 300;
  58 
  59     OC5CONbits.OCTSEL = 0;  //select TMR2
  60     OC5CONbits.OCM = 6;     //PWM mode, no fault pin
  61     OC5CONbits.ON = 1;
  62 
  63     //specifies duty cycle in percent
  64     if((back_level <= 10) | (back_level >= 0))
  65     {
  66         if(back_level == 0)
  67         {
  68             OC5RS = 300;
  69         }
  70         if(back_level == 1)
  71         {
  72             OC5RS = 270;
  73         }
  74         if(back_level == 2)
  75         {
  76             OC5RS = 243;
  77         }
  78         if(back_level == 3)
  79         {
  80             OC5RS = 216;
  81         }
  82         if(back_level == 4)
  83         {
  84             OC5RS = 189;
  85         }
  86         if(back_level == 5)
  87         {
  88             OC5RS = 162;
  89         }
  90         if(back_level == 6)
  91         {
  92             OC5RS = 135;
  93         }
  94         if(back_level == 7)
  95         {
  96             OC5RS = 108;
  97         }
  98         if(back_level == 8)
  99         {
 100             OC5RS = 81;
 101         }
 102         if(back_level == 9)
 103         {
 104             OC5RS = 54;
 105         }
 106         if(back_level == 10)
 107         {
 108             OC5RS = 27;
 109         }
 110 
 111     }
 112 
 113     T2CONbits.ON = 1;
 114 
 115     return;
 116 }
 117 
 118 void Display_init(void)
 119 {
 120     //RG12 and RG14 = data bits D17 and D16
 121     TRISGbits.TRISG12 = 0;
 122     TRISGbits.TRISG14 = 0;
 123     PORTGbits.RG12 = 0;
 124     PORTGbits.RG14 = 0;
 125 
 126     //Configure Pin for D/C
 127     TRISBbits.TRISB1 = 0;
 128     PORTBbits.RB1 = 1;        
 129 
 130     //Select Display (/CS) 
 131     TRISAbits.TRISA9 = 0;
 132     PORTAbits.RA9 = 0;
 133 
 134     //Software RESET
 135     //RB1 = D/C 1=Data, 0=Command
 136     PORTBbits.RB1 = 0;
 137     PMDOUT = 0x01;
 138     while(PMMODEbits.BUSY == 1);
 139 
 140     //Select Display (/CS)    
 141     PORTAbits.RA9 = 1;
 142 
 143     //>120mS Delay
 144     //to allow display to complete reset
 145     //set Timer 5 prescaler /256
 146     Delay32(7, 65535);
 147 
 148      //Select Display (/CS)    
 149     PORTAbits.RA9 = 0;
 150 
 151     //SLPOUT
 152     //RB1 = D/C 1=Data, 0=Command
 153     PORTBbits.RB1 = 0;
 154     PMDOUT = 0x011;
 155     while(PMMODEbits.BUSY == 1);
 156 
 157     //Set pixel format = 16-bit
 158     //05h = 16-bit
 159     //06h = 18-bit
 160     //07h = 24-bit
 161     //RB1 = D/C 1=Data, 0=Command
 162     PORTBbits.RB1 = 0;
 163     PMDOUT = 0x03a;
 164     while(PMMODEbits.BUSY == 1);
 165     //RB1 = D/C 1=Data, 0=Command
 166     PORTBbits.RB1 = 1;
 167     PMDOUT = 0x05;
 168     while(PMMODEbits.BUSY == 1);
 169 
 170     //Set Screen Rotation
 171     //RB1 = D/C 1=Data, 0=Command
 172     PORTBbits.RB1 = 0;
 173 
 174     //MADCTL - Memory Access Control
 175     PMDOUT = 0x36;
 176     while(PMMODEbits.BUSY == 1);
 177 
 178     //RB1 = D/C 1=Data, 0=Command
 179     PORTBbits.RB1 = 1;
 180     //D7 (MY)
 181     //D6 (MX)
 182     //D5 (MV)
 183     //D4 (ML)
 184     //D3 (RGB) 1=BGR. 0=RGB
 185     //D2 (reserved)
 186     //D1 (SS)
 187     //D0 (GS)
 188     //0x28 = wide screen, connector on righthand side
 189     //0xe8 = wide screen, connector on Lefthand side
 190     PMDOUT = 0x28;
 191     while(PMMODEbits.BUSY == 1);
 192 
 193     //Select Display (/CS)    
 194     PORTAbits.RA9 = 1;
 195 }
 196 
 197 //00h - no operation
 198 void Display_NOP(void)
 199 {
 200     //Select Display (/CS)    
 201     PORTAbits.RA9 = 0;
 202 
 203     //RB1 = D/C 1=Data, 0=Command
 204     PORTBbits.RB1 = 0;
 205 
 206     //Command 00h = NOP
 207     PMDOUT = 0x00;
 208     while(PMMODEbits.BUSY == 1);
 209 
 210     //Select Display (/CS)    
 211     PORTAbits.RA9 = 1;
 212 
 213     return;
 214 }
 215 
 216 //01 - software reset
 217 void Display_SWRESET(void)
 218 {
 219     //Select Display (/CS)    
 220     PORTAbits.RA9 = 0;
 221 
 222     //RB1 = D/C 1=Data, 0=Command
 223     PORTBbits.RB1 = 0;
 224 
 225     //Command 01h = SWRESET
 226     PMDOUT = 0x01;
 227     while(PMMODEbits.BUSY == 1);
 228 
 229     //Select Display (/CS)    
 230     PORTAbits.RA9 = 1;
 231 
 232     return;
 233 }
 234 
 235 //04h - Read Display Identification Information
 236 uint8_t Display_RDDIDIF(void)
 237 {
 238     //Select Display (/CS)    
 239     PORTAbits.RA9 = 0;
 240 
 241     //RB1 = D/C 1=Data, 0=Command
 242     PORTBbits.RB1 = 0;
 243 
 244     //Command 04h = RDDPM
 245     PMDOUT = 0x04;
 246     while(PMMODEbits.BUSY == 1);
 247 
 248     //RB1 = D/C 1=Data, 0=Command
 249     PORTBbits.RB1 = 1;
 250 
 251     //Dummy Read
 252     disData[0] = PMRDIN;
 253     while(PMMODEbits.BUSY == 1);
 254 
 255     //Read Display Data
 256     disData[1] = PMRDIN;
 257     while(PMMODEbits.BUSY == 1);
 258 
 259     disData[2] = PMRDIN;
 260     while(PMMODEbits.BUSY == 1);
 261     
 262     //Read Display Data
 263     disData[3] = PMRDIN;
 264     while(PMMODEbits.BUSY == 1);
 265 
 266     disData[4] = PMRDIN;
 267     while(PMMODEbits.BUSY == 1);
 268 
 269     //Select Display (/CS)    
 270     PORTAbits.RA9 = 1;
 271 }
 272 
 273 //05 - Read Number of the Errors on DSI
 274 void Display_RDNUMED(void)
 275 {
 276     //Select Display (/CS)  
 277     PORTAbits.RA9 = 0;
 278 
 279     //RB1 = D/C 1=Data, 0=Command
 280     PORTBbits.RB1 = 0;
 281 
 282     //Command 05h = RDDPM
 283     PMDOUT = 0x05;
 284     while(PMMODEbits.BUSY == 1);
 285 
 286     //RB1 = D/C 1=Data, 0=Command
 287     PORTBbits.RB1 = 1;
 288 
 289     //Dummy Read for PMP
 290     disData[0] = PMRDIN;
 291     while(PMMODEbits.BUSY == 1);
 292 
 293     //Dummy read for display
 294     disData[1] = PMRDIN;
 295     while(PMMODEbits.BUSY == 1);
 296 
 297     //Read Display Data
 298     disData[2] = PMRDIN;
 299     while(PMMODEbits.BUSY == 1);
 300 
 301     //Select Display (/CS)    
 302     PORTAbits.RA9 = 1;
 303 }
 304 
 305 //09h - Read Display Status
 306 void Display_RDDST(void)
 307 {
 308     //Select Display (/CS)  
 309     PORTAbits.RA9 = 0;
 310 
 311     //RB1 = D/C 1=Data, 0=Command
 312     PORTBbits.RB1 = 0;
 313 
 314     //Command 09h = RDDPM
 315     PMDOUT = 0x09;
 316     while(PMMODEbits.BUSY == 1);
 317 
 318     //RB1 = D/C 1=Data, 0=Command
 319     PORTBbits.RB1 = 1;
 320 
 321     //Dummy Read for PMP
 322     disData[0] = PMRDIN;
 323     while(PMMODEbits.BUSY == 1);
 324 
 325     //Dummy read for display
 326     disData[1] = PMRDIN;
 327     while(PMMODEbits.BUSY == 1);
 328 
 329     //Dummy read for Display
 330     disData[2] = PMRDIN;
 331     while(PMMODEbits.BUSY == 1);
 332     
 333     //Read Display Data
 334     disData[3] = PMRDIN;
 335     while(PMMODEbits.BUSY == 1);
 336 
 337     disData[4] = PMRDIN;
 338     while(PMMODEbits.BUSY == 1);
 339 
 340     disData[5] = PMRDIN;
 341     while(PMMODEbits.BUSY == 1);
 342 
 343     //Select Display (/CS)    
 344     PORTAbits.RA9 = 1;
 345 }
 346 
 347 //0Ah - read power mode
 348 void Display_RDDPM(void)
 349 {
 350     //Select Display (/CS)    
 351     PORTAbits.RA9 = 0;
 352 
 353     //RB1 = D/C 1=Data, 0=Command
 354     PORTBbits.RB1 = 0;
 355 
 356     //Command 0ah = RDDPM
 357     PMDOUT = 0x0a;
 358     while(PMMODEbits.BUSY == 1);
 359 
 360     //RB1 = D/C 1=Data, 0=Command
 361     PORTBbits.RB1 = 1;
 362 
 363     //Dummy Read for PMP
 364     disData[0] = PMRDIN;
 365     while(PMMODEbits.BUSY == 1);
 366 
 367     //Dummy read for display
 368     disData[1] = PMRDIN;
 369     while(PMMODEbits.BUSY == 1);
 370 
 371     //Read the Data
 372     disData[2] = PMRDIN;
 373     while(PMMODEbits.BUSY == 1);
 374     
 375     //Select Display (/CS)    
 376     PORTAbits.RA9 = 1;
 377 }
 378 
 379 //0Bh - read display MADCTL
 380 uint8_t Display_RDDMADCTL(void)
 381 {
 382     //Select Display (/CS)    
 383     PORTAbits.RA9 = 0;
 384 
 385     //RB1 = D/C 1=Data, 0=Command
 386     PORTBbits.RB1 = 0;
 387 
 388     //Command 0bh = RDDPM
 389     PMDOUT = 0x0b;
 390     while(PMMODEbits.BUSY == 1);
 391 
 392     //RB1 = D/C 1=Data, 0=Command
 393     PORTBbits.RB1 = 1;
 394 
 395     //Dummy Read for PMP
 396     disData[0] = PMRDIN;
 397     while(PMMODEbits.BUSY == 1);
 398 
 399     //Dummy read for display
 400     disData[1] = PMRDIN;
 401     while(PMMODEbits.BUSY == 1);
 402 
 403     //Read the Data
 404     disData[2] = PMRDIN;
 405     while(PMMODEbits.BUSY == 1);
 406     
 407     //Select Display (/CS)    
 408     PORTAbits.RA9 = 1;
 409 }
 410 
 411 //0Ch - get pixel format
 412 void Display_RDDCOLMOD(void)
 413 {
 414     //Select Display (/CS)    
 415     PORTAbits.RA9 = 0;
 416 
 417     //RB1 = D/C 1=Data, 0=Command
 418     PORTBbits.RB1 = 0;
 419 
 420     //Command 0ch = RDDCOLMOD
 421     PMDOUT = 0x0c;
 422     while(PMMODEbits.BUSY == 1);
 423 
 424     //RB1 = D/C 1=Data, 0=Command
 425     PORTBbits.RB1 = 1;
 426 
 427     //Dummy Read for PMP
 428     disData[0] = PMRDIN;
 429     while(PMMODEbits.BUSY == 1);
 430 
 431     //Dummy read for display
 432     disData[1] = PMRDIN;
 433     while(PMMODEbits.BUSY == 1);
 434 
 435     //Read the Data
 436     disData[2] = PMRDIN;
 437     while(PMMODEbits.BUSY == 1);
 438     
 439     //Select Display (/CS)    
 440     PORTAbits.RA9 = 1;
 441 }
 442 
 443 //0Dh - get display mode
 444 void Display_RDDIM(void)
 445 {
 446     //Select Display (/CS)    
 447     PORTAbits.RA9 = 0;
 448 
 449     //RB1 = D/C 1=Data, 0=Command
 450     PORTBbits.RB1 = 0;
 451 
 452     //Command 0dh = RDDIM
 453     PMDOUT = 0x0d;
 454     while(PMMODEbits.BUSY == 1);
 455 
 456     //RB1 = D/C 1=Data, 0=Command
 457     PORTBbits.RB1 = 1;
 458 
 459     //Dummy Read for PMP
 460     disData[0] = PMRDIN;
 461     while(PMMODEbits.BUSY == 1);
 462 
 463     //Dummy read for display
 464     disData[1] = PMRDIN;
 465     while(PMMODEbits.BUSY == 1);
 466 
 467     //Read the Data
 468     disData[2] = PMRDIN;
 469     while(PMMODEbits.BUSY == 1);
 470     
 471     //Select Display (/CS)    
 472     PORTAbits.RA9 = 1;
 473 }
 474 
 475 //0Eh - get signal mode
 476 void Display_RDDSM(void)
 477 {
 478     //Select Display (/CS)    
 479     PORTAbits.RA9 = 0;
 480 
 481     //RB1 = D/C 1=Data, 0=Command
 482     PORTBbits.RB1 = 0;
 483 
 484     //Command 0eh = RDDSM
 485     PMDOUT = 0x0e;
 486     while(PMMODEbits.BUSY == 1);
 487 
 488     //RB1 = D/C 1=Data, 0=Command
 489     PORTBbits.RB1 = 1;
 490 
 491     //Dummy Read for PMP
 492     disData[0] = PMRDIN;
 493     while(PMMODEbits.BUSY == 1);
 494 
 495     //Dummy read for display
 496     disData[1] = PMRDIN;
 497     while(PMMODEbits.BUSY == 1);
 498 
 499     //Read the Data
 500     disData[2] = PMRDIN;
 501     while(PMMODEbits.BUSY == 1);
 502     
 503     //Select Display (/CS)    
 504     PORTAbits.RA9 = 1;
 505 }
 506 
 507 //0Fh - get diagnostic result
 508 void Display_RDDSDR(void)
 509 {
 510     //Select Display (/CS)    
 511     PORTAbits.RA9 = 0;
 512 
 513     //RB1 = D/C 1=Data, 0=Command
 514     PORTBbits.RB1 = 0;
 515 
 516     //Command 0fh = RDDSDR
 517     PMDOUT = 0x0f;
 518     while(PMMODEbits.BUSY == 1);
 519 
 520     //RB1 = D/C 1=Data, 0=Command
 521     PORTBbits.RB1 = 1;
 522 
 523     //Dummy Read for PMP
 524     disData[0] = PMRDIN;
 525     while(PMMODEbits.BUSY == 1);
 526 
 527     //Dummy read for display
 528     disData[1] = PMRDIN;
 529     while(PMMODEbits.BUSY == 1);
 530 
 531     //Read the Data
 532     disData[2] = PMRDIN;
 533     while(PMMODEbits.BUSY == 1);
 534     
 535     //Select Display (/CS)    
 536     PORTAbits.RA9 = 1;
 537 }
 538 
 539 //10h - enter sleep mode
 540 void Display_SLPIN(void)
 541 {
 542     //Select Display (/CS)    
 543     PORTAbits.RA9 = 0;
 544 
 545     //RB1 = D/C 1=Data, 0=Command
 546     PORTBbits.RB1 = 0;
 547 
 548     //Command 10h = SLPIN
 549     PMDOUT = 0x10;
 550     while(PMMODEbits.BUSY == 1);
 551 
 552     //Select Display (/CS)    
 553     PORTAbits.RA9 = 1;
 554 }
 555 
 556 //11h - exit sleep mode
 557 void Display_SLPOUT(void)
 558 {
 559     //Select Display (/CS)    
 560     PORTAbits.RA9 = 0;
 561 
 562     //RB1 = D/C 1=Data, 0=Command
 563     PORTBbits.RB1 = 0;
 564 
 565     //Command 11h = SLPOUT
 566     PMDOUT = 0x11;
 567     while(PMMODEbits.BUSY == 1);
 568 
 569     //Select Display (/CS)    
 570     PORTAbits.RA9 = 1;
 571 }
 572 
 573 //12h - enter partial mode
 574 void Display_PTLON(void)
 575 {
 576     //Select Display (/CS)    
 577     PORTAbits.RA9 = 0;
 578 
 579     //RB1 = D/C 1=Data, 0=Command
 580     PORTBbits.RB1 = 0;
 581 
 582     //Command 12h = PTLON
 583     PMDOUT = 0x12;
 584     while(PMMODEbits.BUSY == 1);
 585 
 586     //Select Display (/CS)    
 587     PORTAbits.RA9 = 1;
 588 }
 589 
 590 //13h - enter normal mode
 591 void Display_NORON(void)
 592 {
 593     //Select Display (/CS)    
 594     PORTAbits.RA9 = 0;
 595 
 596     //RB1 = D/C 1=Data, 0=Command
 597     PORTBbits.RB1 = 0;
 598 
 599     //Command 13h = NORON
 600     PMDOUT = 0x13;
 601     while(PMMODEbits.BUSY == 1);
 602 
 603     //Select Display (/CS)    
 604     PORTAbits.RA9 = 1;
 605 }
 606 
 607 //20h - exit inversion mode
 608 void Display_INVOFF(void)
 609 {
 610     //Select Display (/CS)    
 611     PORTAbits.RA9 = 0;
 612 
 613     //RB1 = D/C 1=Data, 0=Command
 614     PORTBbits.RB1 = 0;
 615 
 616     //Command 20h = INVOFF
 617     PMDOUT = 0x20;
 618     while(PMMODEbits.BUSY == 1);
 619 
 620     //Select Display (/CS)    
 621     PORTAbits.RA9 = 1;
 622 }
 623 
 624 //21h - enter inversion mode
 625 void Display_INVON(void)
 626 {
 627     //Select Display (/CS)    
 628     PORTAbits.RA9 = 0;
 629 
 630     //RB1 = D/C 1=Data, 0=Command
 631     PORTBbits.RB1 = 0;
 632 
 633     //Command 21h = INVON
 634     PMDOUT = 0x21;
 635     while(PMMODEbits.BUSY == 1);
 636 
 637      //Select Display (/CS)    
 638     PORTAbits.RA9 = 1;
 639 }
 640 
 641 //22h - All Pixels OFF
 642 void Display_ALLPOFF(void)
 643 {
 644     //Select Display (/CS)    
 645     PORTAbits.RA9 = 0;
 646 
 647     //RB1 = D/C 1=Data, 0=Command
 648     PORTBbits.RB1 = 0;
 649 
 650     //Command 22h = INVON
 651     PMDOUT = 0x22;
 652     while(PMMODEbits.BUSY == 1);
 653 
 654      //Select Display (/CS)    
 655     PORTAbits.RA9 = 1;
 656 }
 657 
 658 //23h - All Pixels ON
 659 void Display_ALLPON(void)
 660 {
 661     //Select Display (/CS)    
 662     PORTAbits.RA9 = 0;
 663 
 664     //RB1 = D/C 1=Data, 0=Command
 665     PORTBbits.RB1 = 0;
 666 
 667     //Command 23h = INVON
 668     PMDOUT = 0x23;
 669     while(PMMODEbits.BUSY == 1);
 670 
 671      //Select Display (/CS)    
 672     PORTAbits.RA9 = 1;
 673 
 674    return;
 675 }
 676 
 677 //28h - display off
 678 void Display_DISPOFF(void)
 679 {
 680     //Select Display (/CS)    
 681     PORTAbits.RA9 = 0;
 682 
 683     //RB1 = D/C 1=Data, 0=Command
 684     PORTBbits.RB1 = 0;
 685 
 686     //Command 28h = DSPOFF
 687     PMDOUT = 0x28;
 688     while(PMMODEbits.BUSY == 1);
 689 
 690     //Select Display (/CS)    
 691     PORTAbits.RA9 = 1;
 692 
 693     return;
 694 }
 695 
 696 //29h - display on
 697 void Display_DISPON(void)
 698 {
 699     //Select Display (/CS)    
 700     PORTAbits.RA9 = 0;
 701 
 702     //RB1 = D/C 1=Data, 0=Command
 703     PORTBbits.RB1 = 0;
 704 
 705     //Command 29h = DISPON
 706     PMDOUT = 0x29;
 707     while(PMMODEbits.BUSY == 1);
 708 
 709     //Select Display (/CS)    
 710     PORTAbits.RA9 = 1;
 711 
 712     return;
 713 }
 714 
 715 //2a - set column address
 716 void Display_CASET(uint16_t col_start, uint16_t col_end)
 717 {
 718     if(col_end == 0)
 719     {
 720         col_end = col_start + 15;
 721     }
 722 
 723     //Select Display (/CS)    
 724     PORTAbits.RA9 = 0;
 725 
 726     //RB1 = D/C 1=Data, 0=Command
 727     PORTBbits.RB1 = 0;
 728 
 729     PMDOUT = 0x02a;
 730     while(PMMODEbits.BUSY == 1);
 731     //RB1 = D/C 1=Data, 0=Command
 732     PORTBbits.RB1 = 1;
 733     //break in to bytes HI and LO
 734     //Column Start
 735     //HI
 736     if(col_start > 0xff)
 737     {
 738         PMDOUT = 1;       
 739     }
 740     else
 741     {
 742         PMDOUT = 0;               
 743     }
 744     while(PMMODEbits.BUSY == 1);
 745     //LO
 746     PMDOUT = col_start;
 747     while(PMMODEbits.BUSY == 1);
 748 
 749     //Column End
 750     //HI
 751     if(col_end > 0xff)
 752     {
 753         PMDOUT = 1;       
 754     }
 755     else
 756     {
 757         PMDOUT = 0;               
 758     }
 759     while(PMMODEbits.BUSY == 1);
 760     //LO
 761     PMDOUT = col_end;
 762     while(PMMODEbits.BUSY == 1);
 763 
 764     //Select Display (/CS)    
 765     PORTAbits.RA9 = 1;
 766 
 767     return;
 768 }
 769 
 770 //2Bh - set row address
 771 void Display_RASET(unsigned row_start, unsigned row_end)
 772 {
 773     if(row_end == 0)
 774     {
 775         row_end = row_start + 21;
 776     }
 777 
 778     //Select Display (/CS)    
 779     PORTAbits.RA9 = 0;
 780 
 781     //RB1 = D/C 1=Data, 0=Command
 782     PORTBbits.RB1 = 0;
 783 
 784     PMDOUT = 0x02b;
 785     while(PMMODEbits.BUSY == 1);
 786     //RB1 = D/C 1=Data, 0=Command
 787     PORTBbits.RB1 = 1;
 788     //break in to bytes HI and LO
 789     //Row Start
 790     //HI
 791     if(row_start > 0xff)
 792     {
 793         PMDOUT = 1;       
 794     }
 795     else
 796     {
 797         PMDOUT = 0;               
 798     }
 799     while(PMMODEbits.BUSY == 1);
 800     //LO
 801     PMDOUT = row_start;
 802     while(PMMODEbits.BUSY == 1);
 803 
 804     //Row End
 805     //HI
 806     if(row_end > 0xff)
 807     {
 808         PMDOUT = 1;       
 809     }
 810     else
 811     {
 812         PMDOUT = 0;               
 813     }
 814     while(PMMODEbits.BUSY == 1);
 815     //LO
 816     PMDOUT = row_end;
 817     while(PMMODEbits.BUSY == 1);
 818 
 819     //Select Display (/CS)    
 820     PORTAbits.RA9 = 1;
 821 
 822     return;
 823 }
 824 
 825 //2Ch - memory write
 826 void Display_RAMWR(void)
 827 {
 828     //Select Display (/CS)    
 829     PORTAbits.RA9 = 0;
 830 
 831     //RB1 = D/C 1=Data, 0=Command
 832     PORTBbits.RB1 = 0;
 833 
 834     //Command 2Ch = RAMWR
 835     PMDOUT = 0x2C;
 836     while(PMMODEbits.BUSY == 1);
 837 
 838     //RB1 = D/C 1=Data, 0=Command
 839     PORTBbits.RB1 = 1;
 840 
 841     //pixel data is then written here
 842     //until another command is given
 843 
 844     //Select Display (/CS)    
 845     //PORTAbits.RA9 = 1;
 846 
 847     return;
 848 }
 849 
 850 //2Eh - memory read
 851 void Display_RAMRD(void)
 852 {
 853     //Select Display (/CS)    
 854     PORTAbits.RA9 = 0;
 855 
 856     //RB1 = D/C 1=Data, 0=Command
 857     PORTBbits.RB1 = 0;
 858 
 859     //Command 2eh = RDDSM
 860     PMDOUT = 0x2e;
 861     while(PMMODEbits.BUSY == 1);
 862 
 863     //RB1 = D/C 1=Data, 0=Command
 864     PORTBbits.RB1 = 1;
 865 
 866     //Dummy Read for PMP
 867     disData[0] = PMRDIN;
 868     while(PMMODEbits.BUSY == 1);
 869 
 870     //Dummy read for display
 871     disData[1] = PMRDIN;
 872     while(PMMODEbits.BUSY == 1);
 873 
 874     //Read the Data
 875     disData[2] = PMRDIN;
 876     while(PMMODEbits.BUSY == 1);
 877     
 878     //Read the Data
 879     disData[3] = PMRDIN;
 880     while(PMMODEbits.BUSY == 1);
 881     
 882     //Read the Data
 883     disData[4] = PMRDIN;
 884     while(PMMODEbits.BUSY == 1);
 885     
 886     //Select Display (/CS)    
 887     PORTAbits.RA9 = 1;
 888 
 889     return;
 890 }
 891 
 892 //30h - Set_partial_area
 893 void Display_PLTAR(unsigned SR_HI, unsigned SR_LO, unsigned ER_HI, unsigned ER_LO)
 894 {
 895     //Select Display (/CS)    
 896     PORTAbits.RA9 = 0;
 897 
 898     //RB1 = D/C 1=Data, 0=Command
 899     PORTBbits.RB1 = 0;
 900 
 901     //Command 30h
 902     PMDOUT = 0x30;
 903     while(PMMODEbits.BUSY == 1);
 904 
 905     //RB1 = D/C 1=Data, 0=Command
 906     PORTBbits.RB1 = 1;
 907 
 908     //Upper byte start row
 909     PMDOUT = SR_HI;
 910     while(PMMODEbits.BUSY == 1);
 911 
 912     //Lower byte start row
 913     PMDOUT = SR_LO;
 914     while(PMMODEbits.BUSY == 1);
 915 
 916     //Upper byte end row
 917     PMDOUT = ER_HI;
 918     while(PMMODEbits.BUSY == 1);
 919 
 920     //Upper byte end row
 921     PMDOUT = ER_LO;
 922     while(PMMODEbits.BUSY == 1);
 923 
 924     //Select Display (/CS)    
 925     PORTAbits.RA9 = 1;
 926 }
 927 
 928 //draws a rectangular block of colored pixels
 929 void Display_Rect(unsigned col_start, unsigned col_end, unsigned row_start, unsigned row_end, unsigned rect_color)
 930 {
 931     unsigned a = col_start;
 932     unsigned b = row_start;
 933     unsigned c = col_end;
 934     unsigned d = row_end;
 935 
 936     Display_CASET(col_start, col_end - 1);    
 937     Display_RASET(row_start, row_end - 1);
 938 
 939     Display_RAMWR();
 940 
 941     
 942     //Select Display (/CS)    
 943     PORTAbits.RA9 = 0;
 944 
 945     for(int i=0;i<(col_end - col_start) * (row_end - row_start); i++)
 946     {
 947         PMDOUT = rect_color;
 948         while(PMMODEbits.BUSY == 1);
 949         for(int i=0;i<5;i++);   
 950     }    
 951 
 952     //Select Display (/CS)    
 953     PORTAbits.RA9 = 1;
 954 
 955     col_start = a;
 956     row_start = b;
 957     col_end = c;
 958     row_end = d;
 959 }
 960 
 961 void Display_CLRSCN(int CanvasColor)
 962 {
 963     Display_CASET(0, 479);
 964     Display_RASET(0, 319);
 965     Display_RAMWR();
 966 
 967     for(int i=0;i<=153600;i++)
 968     {
 969         PMDOUT = CanvasColor;
 970         while(PMMODEbits.BUSY == 1);            
 971     }
 972 }
 973 
 974 //Writes a character to the screen
 975 void WriteChar(unsigned col_start, unsigned row_start, unsigned ascii_char, int TextColor, int CanvasColor)
 976 {
 977     //Makes sure no out of bounds
 978     if(ascii_char > 0x7F || ascii_char < 0)
 979     {
 980         ascii_char = 0x2a;
 981     }
 982 
 983     int x;
 984     int text_char = ascii_char - 32;
 985     int off_set = lut[text_char];
 986     int read = courier_new_16pt_bold[off_set];
 987     int a = 0b10000000;
 988     int pixel = 0;
 989     int s = 0;
 990     int i;
 991 
 992     col_end = col_start + 15;
 993     row_end = row_start + 21;
 994     Display_CASET(col_start, col_end);
 995     Display_RASET(row_start, row_end);
 996 
 997     Display_RAMWR();
 998 
 999     for(s=0;s<=45;s++)
1000     {
1001         for(i=0;i<=7;i++)
1002         {
1003             x = read & a;
1004             if(x > 0)
1005             {
1006                 pixel = TextColor;
1007             }
1008             else
1009             {
1010                 pixel = CanvasColor;
1011             }
1012 
1013             //Select Display (/CS)    
1014             PORTAbits.RA9 = 0;
1015 
1016             PMDOUT = pixel;
1017             while(PMMODEbits.BUSY == 1);
1018 
1019             //Select Display (/CS)    
1020             PORTAbits.RA9 = 1;
1021 
1022             a = a / 2;
1023         }
1024         off_set++;
1025         read = courier_new_16pt_bold[off_set];
1026         a = 0b10000000;
1027     }
1028     //this keeps track of the horizontal position.
1029     hchar = hchar + 15;    return;
1030 }
1031 
1032 //Writes a null terminated string from a previously defined array
1033 void WriteString(unsigned col_start, unsigned row_start, char array_name[], int TextColor, int CanvasColor)
1034 {
1035     int offset = 0;
1036 
1037     //must initialize test_char to something other than \0
1038     //so we might as well use the array data
1039     char test_char = array_name[offset];
1040 
1041     while(test_char != '\0')
1042     {
1043         test_char = array_name[offset];
1044 
1045         Display_CASET(col_start, col_start + 15);
1046 
1047         WriteChar(col_start, row_start, test_char, TextColor, CanvasColor);    
1048         offset++;       
1049         col_start = col_start + 15;
1050     }
1051     //cleans up the extra white space
1052     hchar = hchar - 15;
1053 }
1054 
1055 //Writes a character with 2 background colors for button text
1056 void WriteButtonChar(unsigned col_start, unsigned row_start, unsigned ascii_char, int TextColor, int color1, int color2)
1057 {
1058     //Makes sure no out of bounds
1059     if(ascii_char > 0x7F || ascii_char < 0)
1060     {
1061         ascii_char = 0x2a;
1062     }
1063 
1064     int x;
1065     int text_char = ascii_char - 32;
1066     int off_set = lut[text_char];
1067     int read = courier_new_16pt_bold[off_set];
1068     int a = 0b10000000;
1069     int pixel = 0;
1070     int s = 0;
1071     int i;
1072 
1073     col_end = col_start + 15;
1074     row_end = row_start + 21;
1075     Display_CASET(col_start, col_end);
1076     Display_RASET(row_start, row_end);
1077 
1078     Display_RAMWR();
1079 
1080     for(s=0;s<44;s++)
1081     {
1082         for(i=0;i<=7;i++)
1083         {
1084             x = read & a;
1085             if(x > 0)
1086             {
1087                 pixel = TextColor;
1088             }
1089             else
1090             {
1091                 if(s < 24)
1092                 {
1093                     pixel = color1;
1094                 }
1095                 else
1096                 {
1097                     pixel = color2;
1098                 }
1099             }
1100 
1101             //Select Display (/CS)    
1102             PORTAbits.RA9 = 0;
1103 
1104             PMDOUT = pixel;
1105             while(PMMODEbits.BUSY == 1);
1106 
1107             //Select Display (/CS)    
1108             PORTAbits.RA9 = 1;
1109 
1110             a = a / 2;
1111         }
1112         off_set++;
1113         read = courier_new_16pt_bold[off_set];
1114         a = 0b10000000;
1115     }
1116     //this keeps track of the horizontal position.
1117     hchar = hchar + 15;
1118     return;
1119 }
1120 
1121 //Writes a null terminated string from a previously defined array with button colors
1122 void WriteButtonString(unsigned col_start, unsigned row_start, char array_name[], int TextColor, int color1, int color2)
1123 {
1124     int offset = 0;
1125 
1126     //must initialize test_char to something other than \0
1127     //so we might as well use the array data
1128     char test_char = array_name[offset];
1129 
1130     while(test_char != '\0')
1131     {
1132         test_char = array_name[offset];
1133 
1134         Display_CASET(col_start, col_start + 15);
1135 
1136         WriteButtonChar(col_start, row_start, test_char, TextColor, color1, color2);   
1137         offset++;       
1138         col_start = col_start + 15;
1139     }
1140     //cleans up the extra white space
1141     hchar = hchar - 15;
1142 }
1143 
1144 void DrawButton(unsigned col_start, unsigned row_start, uint8_t length, uint8_t height, int color1, int color2, int border_color, char array_name[])
1145 {
1146     //Draw border
1147     //Display_Rect(20, 170, 50, 52, 0xad55);
1148     Display_Rect(col_start, col_start + length, row_start, row_start + 2, border_color);
1149     //Display_Rect(168, 170, 50, 100, 0xad55);
1150     Display_Rect((col_start + length) - 2, col_start + length, row_start, row_start + height, border_color);
1151     //Display_Rect(20, 170, 98, 100, 0xad55);
1152     Display_Rect(col_start, col_start + length, (row_start + height) - 2, row_start + height, border_color);
1153     //Display_Rect(20, 22, 50, 100, 0xad55);
1154     Display_Rect(col_start, col_start + 2, row_start, row_start + height, border_color);
1155 
1156     //Draw upper half
1157     //Display_Rect(colStart + 2, 168, 52, 75, 0xef7d);
1158     Display_Rect(col_start + 2, (col_start + length) - 2, row_start + 2, row_start + (height / 2), color1);
1159     //Draw lower half
1160     //Display_Rect(22, 168, 75, 98, 0xd6ba);
1161     Display_Rect(col_start + 2, (col_start + length) - 2, row_start + (height / 2), (row_start + height) - 2, color2);
1162 
1163     //Draw Button Text
1164     WriteButtonString(col_start + ((length - ((strlen(array_name) * 15))) / 2), row_start + 13, array_name, TextColor, color1, color2);//((length - strlen(array_name)) / 2)
1165 }
1166