1 /*********************************************************************
   2     FileName:           Main.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 //DEVCFG3
  33 #pragma config USERID =     12546
  34 #pragma config FMIIEN =     OFF
  35 #pragma config FETHIO =     OFF
  36 #pragma config PGL1WAY =    OFF
  37 #pragma config PMDL1WAY =   OFF
  38 #pragma config IOL1WAY =    OFF
  39 #pragma config FUSBIDIO =   OFF
  40 
  41 //DEVCFG2 
  42 #pragma config FPLLIDIV =   DIV_3
  43 #pragma config FPLLRNG =    RANGE_5_10_MHZ
  44 #pragma config FPLLICLK =   PLL_POSC
  45 #pragma config FPLLMULT =   MUL_50
  46 #pragma config FPLLODIV =   DIV_2
  47 #pragma config UPLLFSEL =   FREQ_24MHZ
  48 
  49 //DEVCFG1
  50 #pragma config FNOSC =      SPLL
  51 #pragma config DMTINTV =    WIN_127_128
  52 #pragma config FSOSCEN =    ON
  53 #pragma config IESO =       OFF
  54 #pragma config POSCMOD =    EC
  55 #pragma config OSCIOFNC =   OFF
  56 #pragma config FCKSM =      CSDCMD
  57 #pragma config WDTPS =      PS1048576
  58 #pragma config WDTSPGM =    STOP
  59 #pragma config FWDTEN =     OFF
  60 #pragma config WINDIS =     NORMAL
  61 #pragma config FWDTWINSZ =  WINSZ_25
  62 #pragma config DMTCNT =     DMT31
  63 #pragma config FDMTEN =     OFF
  64 
  65 //DEVCFG0
  66 #pragma config DEBUG =      OFF
  67 #pragma config JTAGEN =     OFF
  68 #pragma config ICESEL =     ICS_PGx2
  69 #pragma config TRCEN =      OFF
  70 #pragma config BOOTISA =    MIPS32
  71 #pragma config FECCCON =    OFF_UNLOCKED
  72 #pragma config FSLEEP =     OFF
  73 #pragma config DBGPER =     PG_ALL
  74 #pragma config SMCLR =      MCLR_NORM
  75 #pragma config SOSCGAIN =   GAIN_2X
  76 #pragma config SOSCBOOST =  ON
  77 #pragma config POSCGAIN =   GAIN_2X
  78 #pragma config POSCBOOST =  OFF
  79 #pragma config EJTAGBEN =   NORMAL
  80 #pragma config CP =         OFF
  81 
  82 #include <xc.h>
  83 
  84 #include <sys/attribs.h>
  85 #include <sys/kmem.h>
  86 #include <stdint.h> 
  87 #include <stdio.h>
  88 #include <stdlib.h>
  89 #include <string.h>
  90 #include <stdbool.h>
  91 #include <math.h>
  92 #include "MainBrain.h"
  93 
  94 bool boardInfo = false;
  95 volatile uint32_t Last_Memory[10];
  96 bool IO_Locked = false;
  97 bool getBoardInfo = false;
  98 volatile bool inMotion = false;
  99 bool test_result;
 100 bool full_access;
 101 bool screen_available = true;
 102 uint32_t lastError;
 103 char myStr[20] = "null";
 104 char ConnectedStr[10] = {"Connected"};
 105 char ReadyStr[10] = {"Ready... "};
 106 char OfflineStr[11] = {"Offline..."};
 107 char FullSpeed[7] = {"12Mb/s"};
 108 char HiSpeed[8] = {"480Mb/s"};
 109 char DACtitleStr[14] = {"DAC Utilities"};
 110 char cmdStr[4] = {"cmd"};
 111 char memStr[4] = {"mem"};
 112 char brdStr[4] = {"brd"};
 113 char scopeTitleStr[6] = {"Scope"};
 114 int8_t dev_data = 0;
 115 uint8_t screen;
 116 bool NeedsRefresh = true;
 117 uint8_t default_Display_Brightness = 1;
 118 bool Level2MenuActive = false;
 119 uint8_t CurrentLevel = HOMELEVEL;
 120 uint8_t FlashConfigData[100];
 121 uint8_t BuildPList = 0;
 122 bool requestDirective = false;
 123 uint8_t PeripheralList[7] = {0};
 124 uint8_t current_board_address;
 125 uint16_t myArray[480];
 126 int test1 = 0;
 127 bool updated = false;
 128 uint16_t adc_data = 0;
 129 int myi = 0;
 130 float ADC_Volts;
 131 uint8_t buf[10];
 132 bool screenTouched = false;
 133 bool Message = false;
 134 uint8_t old_screen = 0;
 135 
 136 uint8_t peripheral_info[7][24] = {0};
 137 
 138 int main(void)
 139 {       
 140     while(CLKSTATbits.POSCRDY == 0);
 141         
 142     SystemSetup();
 143     
 144     
 145     //Indicates System Setup completed
 146     LED_Port(0x1);
 147     
 148     PMP_init();
 149     
 150     //Indicates PMP Setup completed
 151     LED_Port(0x2);
 152     
 153     //SRAM initialize
 154     REN70V05_Init();
 155     
 156     //Indicates SRAM Setup completed
 157     LED_Port(0x3);
 158     
 159     //Test SRAM
 160     //test_result = memtest_70V05(40);
 161     
 162     //Indicates SRAM Test completed
 163     LED_Port(0x4);
 164     
 165     //Release the SRAM
 166     //ReleaseSRAM();
 167 
 168     Flash_Init();
 169 
 170     //Indicates Flash Setup completed
 171     LED_Port(0x5);
 172         
 173     //32 bit timer
 174     TMR4_init();
 175     
 176     //Indicates Timer 5 Setup completed
 177     LED_Port(0x7);    
 178     
 179     //I2C Initialize
 180     I2C_init();
 181 
 182     //Indicates Touch (I2C) Setup completed
 183     LED_Port(0x8);
 184     
 185     TMR1_init();
 186       
 187     //Indicates Timer 1 Setup completed
 188     LED_Port(0x9);
 189     
 190     ADC_init();
 191     
 192     //Indicates ADC Setup completed
 193     LED_Port(0xa);
 194     
 195     Display_init(); 
 196     
 197     //Indicates Display Setup completed
 198     LED_Port(0xb);
 199    
 200     SetDisplayBrightness();
 201     
 202     //Clear the Screen
 203     Display_CLRSCN(0xffff);   
 204 
 205     //Turn on the Display
 206     Display_DISPON();  
 207     
 208     //Timer 6 Init
 209     TMR6_init();
 210     
 211     //Indicates Real Time Clock completed
 212     LED_Port(0xc);  
 213     
 214     //Timer 3 Init
 215     TMR3_init();
 216     
 217     //Beep the buzzer to indicate full config
 218     Beep();
 219     
 220     //enable the interrupts
 221     __builtin_enable_interrupts();    
 222   
 223     //Clear the LED Port 
 224     //System Setup is Complete
 225     LED_Port(0x0);
 226     
 227     //Load the Splash Screen
 228     ShowSplashScreen(0);
 229     
 230     //Specify the screen to load
 231     screen = HOME_SCREEN;  
 232      
 233     uint8_t a = 5;
 234     
 235     //Set the Directive request flag to get the board info
 236     //Write the directive
 237     REN70V05_WR(0x400, 0);
 238     current_board_address = 1;
 239     requestDirective = 1;
 240        
 241     //Main program Loop
 242     while(1)
 243     {           
 244         //Heart beat
 245         //Signal out on pin 50
 246         PORTCbits.RC15 = !PORTCbits.RC15;  
 247         
 248         //check for an active message
 249         if(Message == 1)
 250         {
 251             //save current screen
 252             old_screen = screen;
 253             
 254             //Act on the message
 255             MessageBox(myStr, 5);
 256             CurrentLevel = HOMELEVEL;
 257             NeedsRefresh = true;
 258             
 259             //enable the screen
 260             NeedsRefresh = true;
 261             
 262             //Clear the Message flag
 263             Message = 0;            
 264         }
 265         
 266         //check for an active directive
 267         if(requestDirective == 1)
 268         {
 269             //Lock the I/O so no other Directives can occur 
 270             //until the cycle is complete
 271             IO_Locked = true;
 272             
 273             //This initiates an I/O cycle
 274             Directive(current_board_address);
 275             
 276             hchar = 10;
 277             vchar = 180;
 278             
 279             Binary2ASCIIHex(REN70V05_RD(0x419));  
 280             WriteChar(hchar, vchar, d_hex[1], black, white);
 281             WriteChar(hchar, vchar, d_hex[0], black, white);
 282 
 283             //clear the Directive flag
 284             requestDirective = 0;           
 285         }
 286         
 287         if(getBoardInfo == true)
 288         {
 289                 //only access SRAM if it is unlocked
 290                 if(IO_Locked == false)
 291                 {
 292                     //Get the board data                    
 293                     for(int i=0;i<26;i++)
 294                     {
 295                         peripheral_info[current_board_address][i] = REN70V05_RD((current_board_address * 0x400) + i);
 296                     }
 297 
 298                 }
 299                 
 300             getBoardInfo == false;
 301         }
 302         
 303         //Load the current screen
 304         switch(screen)
 305         {
 306             case HOME_SCREEN:
 307                 if(NeedsRefresh == true)
 308                 {
 309                     ShowSplashScreen(0);
 310                     NeedsRefresh = false;
 311                     CurrentLevel = HOMELEVEL;
 312                 }
 313                 break;
 314             case INFO_SCREEN:
 315                 if(NeedsRefresh == true)
 316                 {
 317                     DrawScreen(INFO_SCREEN, HeaderString);
 318                     CurrentLevel = HOMELEVEL;
 319                     NeedsRefresh = false;
 320                 }                
 321                 break;
 322             case BOARD_SCREEN:
 323                 if(NeedsRefresh == true)
 324                 {
 325                     DrawScreen(BOARD_SCREEN, HeaderString);
 326                     CurrentLevel = HOMELEVEL;
 327                     NeedsRefresh = false;
 328                 }                
 329                 break;
 330 
 331         }      
 332         
 333         //Read single point touch position
 334         if((scn_pos_x > 0) && (scn_pos_x < 480) && (scn_pos_y > 0) && (scn_pos_y < 320))
 335         {
 336             hchar = 10;
 337             vchar = 60;
 338             
 339             if(screenTouched == false)
 340             {
 341                 screen = INFO_SCREEN;
 342                 NeedsRefresh = true;
 343                 screenTouched = true;
 344             }
 345             
 346             vchar = 15;
 347             hchar = 350;
 348             Binary2ASCIIBCD(scn_pos_x);
 349             WriteChar(hchar, vchar, d2, black, 0x04D3);
 350             WriteChar(hchar, vchar, d1, black, 0x04D3);
 351             WriteChar(hchar, vchar, d0, black, 0x04D3);
 352             
 353             WriteChar(hchar, vchar, ',', black, 0x04D3);
 354             
 355             Binary2ASCIIBCD(scn_pos_y);
 356             WriteChar(hchar, vchar, d2, black, 0x04D3);
 357             WriteChar(hchar, vchar, d1, black, 0x04D3);
 358             WriteChar(hchar, vchar, d0, black, 0x04D3);
 359         }
 360     }
 361 }
 362 
 363 void SystemSetup(void)
 364 {   
 365     //disable the interrupts
 366     __builtin_disable_interrupts();    
 367     
 368     // System unlock Sequence
 369     SYSKEY = 0xAA996655;
 370     SYSKEY = 0x556699AA;  
 371     
 372     //Init USB module
 373     USB_init();
 374     
 375     // Set multi vector interrupt mode
 376     INTCONbits.MVEC = 1; 
 377     
 378     unsigned int cp0;
 379     
 380     ANSELA = 0;
 381     ANSELB = 0;
 382     ANSELC = 0;
 383     ANSELD = 0;
 384     ANSELE = 0;
 385     ANSELF = 0;
 386     ANSELG = 0;
 387     
 388     //Buzzer control pin
 389     TRISAbits.TRISA1 = 0;
 390 
 391     //This pin is used by the peripherals to indicate they need serviced
 392     TRISAbits.TRISA7 = 1;
 393     
 394     //LED Port
 395     TRISFbits.TRISF3    = 0;
 396     TRISFbits.TRISF2    = 0;
 397     TRISFbits.TRISF8    = 0;
 398     TRISAbits.TRISA6    = 0;
 399     TRISAbits.TRISA14   = 0;
 400     TRISAbits.TRISA15   = 0;
 401     TRISDbits.TRISD10   = 0;
 402     TRISDbits.TRISD11   = 0;
 403     
 404     //RC13 - Secondary OSC in
 405     TRISCbits.TRISC13 = 1;
 406 
 407     //RC15 - Pin 50
 408     //Heartbeat out (TP1))
 409     TRISCbits.TRISC15 = 0;
 410     
 411     //RG13
 412     // /ACK from peripherals
 413     TRISGbits.TRISG13 = 1;
 414     
 415     //RG6
 416     //TP2
 417     TRISGbits.TRISG6 = 0;
 418     
 419     //RA7
 420     // /INT from peripheral
 421     TRISAbits.TRISA7 = 1;
 422     
 423     //Peripherals address setup
 424     // A0 - PORTD.15
 425     TRISDbits.TRISD15 = 0;
 426     PORTDbits.RD15 = 0;
 427     
 428     // A1 - PORTF.13
 429     TRISFbits.TRISF13 = 0;
 430     PORTFbits.RF13 = 0;
 431     
 432     TRISDbits.TRISD14 = 0;
 433     // A2 - PORTD.14
 434     PORTDbits.RD14 = 0;
 435     
 436     /*********************************************************
 437     / I/O cycle change notice for RG13
 438     /*********************************************************/
 439     IPC31bits.CNGIP = 7;
 440     IPC31bits.CNGIS = 2;
 441     
 442     CNCONGbits.ON = 1;
 443     CNCONGbits.EDGEDETECT = 1;
 444     CNNEGbits.CNNEG13 = 1;
 445     IEC3bits.CNGIE = 1;
 446 
 447     
 448     IFS3bits.CNGIF = 0;
 449     
 450     //Pin Mapping
 451     //Maps OC5 to pin
 452     RPD4R = 0x0b;
 453     
 454     //USB
 455     //This allows the usage of RF3 as I/O while still using the USB module 
 456     //Device mode only
 457     USBCRCONbits.USBIDOVEN = 1;
 458     USBCRCONbits.USBIDVAL = 1;
 459     
 460     PRISS = 0x76543210;
 461     
 462     //PBCLK1 - System Clock
 463     // Peripheral Bus 1 cannot be turned off, so there's no need to turn it on
 464     PB1DIVbits.PBDIV = 0; // Peripheral Bus 1 Clock Divisor Control (PBCLK1 is SYSCLK divided by 1)
 465 
 466     //PBCLK2 - PMP
 467     PB2DIVbits.PBDIV = 1; // Peripheral Bus 2 Clock Divisor Control (PBCLK2 is SYSCLK divided by 1)
 468     PB2DIVbits.ON = 1; // Peripheral Bus 2 Output Clock Enable (Output clock is enabled)
 469     while (!PB2DIVbits.PBDIVRDY);
 470 
 471     //PBCLK3 - Feeds TMR1
 472     PB3DIVbits.PBDIV = 0; 
 473     PB3DIVbits.ON = 1; 
 474     while (!PB3DIVbits.PBDIVRDY);
 475     
 476     //PB4DIV
 477     PB4DIVbits.PBDIV = 1; // Peripheral Bus 4 Clock Divisor Control (PBCLK4 is SYSCLK divided by 1)
 478     PB4DIVbits.ON = 1; // Peripheral Bus 4 Output Clock Enable (Output clock is enabled)
 479     while (!PB4DIVbits.PBDIVRDY); // Wait until it is ready to write to
 480 
 481     //PB5DIV
 482     PB5DIVbits.PBDIV = 1; // Peripheral Bus 5 Clock Divisor Control (PBCLK5 is SYSCLK divided by 1)
 483     PB5DIVbits.ON = 1; // Peripheral Bus 5 Output Clock Enable (Output clock is enabled)
 484     while (!PB5DIVbits.PBDIVRDY); // Wait until it is ready to write to
 485 
 486     // PB7DIV
 487     PB7DIVbits.PBDIV = 0; // Peripheral Bus 7 Clock Divisor Control (PBCLK7 is SYSCLK divided by 1)
 488     PB7DIVbits.ON = 1; // Peripheral Bus 7 Output Clock Enable (Output clock is enabled)
 489     while (!PB7DIVbits.PBDIVRDY); // Wait until it is ready to write to
 490 
 491     //PB8DIV
 492     PB8DIVbits.PBDIV = 1; // Peripheral Bus 8 Clock Divisor Control (PBCLK8 is SYSCLK divided by 1)
 493     PB8DIVbits.ON = 1; // Peripheral Bus 8 Output Clock Enable (Output clock is enabled)
 494     while (!PB8DIVbits.PBDIVRDY); // Wait until it is ready to write to
 495 
 496     //PRECON - Set up prefetch
 497     PRECONbits.PFMSECEN = 0;  // Flash SEC Interrupt Enable (Do not generate an interrupt when the PFMSEC bit is set)
 498     PRECONbits.PREFEN = 3; // Predictive Prefetch Enable (Enable predictive prefetch for any address)
 499     PRECONbits.PFMWS = 2; // PFM Access Time Defined in Terms of SYSCLK Wait States (Two wait states)
 500     
 501     CFGCONbits.USBSSEN = 1;
 502 
 503     // Set up caching
 504     cp0 = _mfc0(16, 0);
 505     cp0 &= ~0x07;
 506     cp0 |= 0b011; // K0 = Cacheable, non-coherent, write-back, write allocate
 507     _mtc0(16, 0, cp0);  
 508     
 509     while(CLKSTATbits.DIVSPLLRDY == 0);
 510     
 511     //Real time clock init
 512     RTCC_init();
 513     
 514     //Increase POSC freq
 515     //56 seems to be the highest stable value
 516     SetFreqPOSC(57);
 517     
 518     //Lock system
 519     SYSKEY =  0x33333333;
 520 }
 521 
 522 void LED_Port(int8_t led_port_data)
 523 {
 524     //LED_Port:
 525     //LED0              RF3
 526     //LED1              RF2 
 527     //LED2              RF8
 528     //LED3              RA6
 529     //LED4              RA14
 530     //LED5              RA15
 531     //LED6              RD10
 532     //LED7              RD11
 533 
 534    uint32_t temp = led_port_data;
 535     
 536     //LED0
 537     temp = led_port_data & 0x01;  
 538     PORTFbits.RF3 = temp;
 539     
 540     //LED_1
 541     temp = led_port_data & 0x02;
 542     temp = temp >> 1;
 543     PORTFbits.RF2 = temp;
 544     
 545     //LED_2
 546     temp = led_port_data & 0x04;
 547     temp = temp >> 2;
 548     PORTFbits.RF8 = temp;
 549     
 550     //LED_3
 551     temp = led_port_data & 0x08;
 552     temp = temp >> 3;
 553     PORTAbits.RA6 = temp;
 554     
 555     //LED_4
 556     temp = led_port_data & 0x10;
 557     temp = temp >> 4;
 558     PORTAbits.RA14 = temp;
 559     
 560     //LED_5
 561     temp = led_port_data & 0x20;
 562     temp = temp >> 5;
 563     PORTAbits.RA15 = temp;
 564     
 565     //LED_6
 566     temp = led_port_data & 0x40;
 567     temp = temp >> 6;
 568     PORTDbits.RD10 = temp;
 569     
 570     //LED_7
 571     temp = led_port_data & 0x80;
 572     temp = temp >> 7;
 573     PORTDbits.RD11 = temp;   
 574 }
 575 
 576 void GetTime(void)
 577 {
 578 //    int a = hchar;
 579 //    int b = vchar;
 580 //    
 581 //    hchar = 350;
 582 //    vchar = 8;
 583 
 584     Binary2ASCIIBCD(RTCTIMEbits.HR10);    
 585     WriteChar(hchar, vchar, d0, black, 0x04D3);
 586     
 587     Binary2ASCIIBCD(RTCTIMEbits.HR01);    
 588     WriteChar(hchar, vchar, d0, black, 0x04D3);
 589     
 590     //colon
 591     WriteChar(hchar, vchar, ':', black, 0x04D3);
 592     
 593     Binary2ASCIIBCD(RTCTIMEbits.MIN10);    
 594     WriteChar(hchar, vchar, d0, black, 0x04D3);
 595     
 596     Binary2ASCIIBCD(RTCTIMEbits.MIN01);    
 597     WriteChar(hchar, vchar, d0, black, 0x04D3);
 598     
 599     //colon
 600     WriteChar(hchar, vchar, ':', black, 0x04D3);
 601     
 602     Binary2ASCIIBCD(RTCTIMEbits.SEC10);    
 603     WriteChar(hchar, vchar, d0, black, 0x04D3);
 604     
 605     Binary2ASCIIBCD(RTCTIMEbits.SEC01);    
 606     WriteChar(hchar, vchar, d0, black, 0x04D3);
 607     
 608 //    hchar = a;
 609 //    vchar = b;
 610 }
 611 
 612 void SystemReset(void)
 613 {
 614     //unlock the system
 615     SYSKEY = 0x00000000;
 616     //write invalid key to force lock 
 617     SYSKEY = 0xAA996655;
 618     //write key1 to SYSKEY 
 619     SYSKEY = 0x556699AA;
 620     //write key2 to SYSKEY
 621     // OSCCON is now unlocked
 622     /* set SWRST bit to arm reset */ 
 623     RSWRSTSET = 1;
 624     /* read RSWRST register to trigger reset */ 
 625     int dummy = RSWRST;
 626     /* prevent any unwanted code execution until reset occurs*/ 
 627     while(1);
 628 }
 629 
 630 /*************************************************************
 631  Sends an I/O request to the peripheral.
 632  
 633  SRAM Data must be written prior to calling this function.
 634  
 635  Once the board address is selected the peripheral reads
 636  SRAM location 0 of it's predefined memory region and returns
 637  an /ACK when finished.
 638  
 639  This function responds to the /ACK by setting the current address
 640  to zero.
 641 *************************************************************/
 642 void Directive(uint8_t badd)
 643 {
 644     //Zero Timer 3 
 645     TMR3 = 0;
 646     
 647     //clear LED Port
 648     LED_Port(0);
 649     
 650     //Set the board select address
 651     //This causes an Interrupt in the peripheral
 652     //and initiates an I/O cycle
 653     SetPeripheralAddress(badd);
 654 
 655     //Start Timer 3
 656     T3CONSET = 1 << 15;     
 657 }
 658 
 659 /*************************************************************
 660  Builds a list of all the present peripheral devices
 661  This array is used for all future I/O requests 
 662 *************************************************************/
 663 void BuildPeripheralList(void)
 664 {
 665     //Zero Timer 3
 666     PR3 = 0;
 667     
 668     //Set the pre-scaler
 669     T3CONbits.TCKPS = 7;
 670     
 671     //Start Timer 3
 672     T3CONSET = 1 << 15; 
 673     
 674     //Write the command at address 0 of the I/O card
 675     REN70V05_WR(0, EP[1].rx_buffer[2]);
 676     int i = 0;
 677 //    for(int i=1;i<=7;i++)
 678 //    {
 679         //Set the board select address
 680         SetPeripheralAddress(EP[1].rx_buffer[1]);
 681 
 682         //Wait for either the /ACK or a timeout to occur
 683         while((!IFS0bits.T3IF) && (PORTGbits.RG13));
 684 
 685         //Check to see what happened
 686         //If /ACK went low add the board to the list
 687         if(!PORTGbits.RG13)
 688         {
 689             PeripheralList[i] = 1;
 690         }
 691         else
 692         {
 693             // we timed out
 694             PeripheralList[i] = 0;
 695         }
 696 
 697         //Reset the board select address
 698         SetPeripheralAddress(0);
 699 
 700         //Stop Timer 3
 701         T3CONCLR = 1 << 15; 
 702 //    }
 703 }
 704 
 705 void SetPeripheralAddress(uint8_t padd)
 706 {
 707     if (padd >= 7) 
 708     {
 709         padd = 7;
 710     }
 711 
 712     // A0 - PORTD.15
 713     if ((padd & 0x01) != 0)  
 714     {
 715         PORTDbits.RD15 = 1;
 716     }
 717     else    
 718     {
 719         PORTDbits.RD15 = 0;
 720     }
 721 
 722     // A1 - PORTF.13
 723     if ((padd & 0x02) != 0)  
 724     {
 725         PORTFbits.RF13 = 1;
 726     }
 727     else    
 728     {
 729         PORTFbits.RF13 = 0;
 730     }
 731     
 732     // A2 - PORTD.14
 733     if ((padd & 0x04) != 0)  
 734     {
 735         PORTDbits.RD14 = 1;
 736     }
 737     else    
 738     {
 739         PORTDbits.RD14 = 0;
 740     }
 741 }
 742 
 743 void Clock(uint8_t ClockData)
 744 {       
 745     //TextColor = black;
 746     
 747 //    //Colon 1
 748 //    Display_Rect(151, 163, 120, 130, TextColor);  
 749 //    Display_Rect(151, 163, 160, 170, TextColor);  
 750 //
 751 //    //Colon 2
 752 //    Display_Rect(317, 329, 120, 130, TextColor);  
 753 //    Display_Rect(317, 329, 160, 170, TextColor);  
 754     
 755     if(ClockData == 46)
 756     {
 757         Display_Rect(hchar, hchar + 10, vchar, vchar + 10, black);    
 758     }
 759     
 760     if(ClockData == 48)
 761     {
 762             //segment A
 763             Display_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, black);    
 764             //segment B
 765             Display_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, black);
 766             //Segment C
 767             Display_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, black);
 768             //Segment D
 769             Display_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, black);    
 770             //Segment E
 771             Display_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, black);
 772             //Segment F
 773             Display_Rect(hchar, hchar + 10, vchar, vchar + 50, black);
 774             //Segment G
 775             Display_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, white);    
 776 
 777     }
 778 
 779     if(ClockData == 49)
 780     {
 781             //segment A
 782             Display_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, white);    
 783             //segment B
 784             Display_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, black);
 785             //Segment C
 786             Display_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, black);
 787             //Segment D
 788             Display_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, white);    
 789             //Segment E
 790             Display_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, white);
 791             //Segment F
 792             Display_Rect(hchar, hchar + 10, vchar, vchar + 50, white);
 793             //Segment G
 794             Display_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, white);    
 795 
 796     }
 797 
 798     if(ClockData == 50)
 799     {
 800             //segment A
 801             Display_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, black);    
 802             //segment B
 803             Display_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, black);
 804             //Segment C
 805             Display_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, white);
 806             //Segment D
 807             Display_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, black);    
 808             //Segment E
 809             Display_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, black);
 810             //Segment F
 811             Display_Rect(hchar, hchar + 10, vchar, vchar + 50, white);
 812             //Segment G
 813             Display_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, black);    
 814 
 815     }
 816 
 817     if(ClockData == 51)
 818     {
 819             //segment A
 820             Display_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, black);    
 821             //segment B
 822             Display_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, black);
 823             //Segment C
 824             Display_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, black);
 825             //Segment D
 826             Display_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, black);    
 827             //Segment E
 828             Display_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, white);
 829             //Segment F
 830             Display_Rect(hchar, hchar + 10, vchar, vchar + 50, white);
 831             //Segment G
 832             Display_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, black);    
 833 
 834     }
 835 
 836     if(ClockData == 52)
 837     {
 838             //segment A
 839             Display_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, white);    
 840             //segment B
 841             Display_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, black);
 842             //Segment C
 843             Display_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, black);
 844             //Segment D
 845             Display_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, white);    
 846             //Segment E
 847             Display_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, white);
 848             //Segment F
 849             Display_Rect(hchar, hchar + 10, vchar, vchar + 50, black);
 850             //Segment G
 851             Display_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, black);    
 852 
 853     }
 854 
 855     if(ClockData == 53)
 856     {
 857             //segment A
 858             Display_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, black);    
 859             //segment B
 860             Display_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, white);
 861             //Segment C
 862             Display_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, black);
 863             //Segment D
 864             Display_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, black);    
 865             //Segment E
 866             Display_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, white);
 867             //Segment F
 868             Display_Rect(hchar, hchar + 10, vchar, vchar + 50, black);
 869             //Segment G
 870             Display_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, black);    
 871 
 872     }
 873 
 874     if(ClockData == 54)
 875     {
 876             //segment A
 877             Display_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, white);    
 878             //segment B
 879             Display_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, white);
 880             //Segment C
 881             Display_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, black);
 882             //Segment D
 883             Display_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, black);    
 884             //Segment E
 885             Display_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, black);
 886             //Segment F
 887             Display_Rect(hchar, hchar + 10, vchar, vchar + 50, black);
 888             //Segment G
 889             Display_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, black);    
 890 
 891     }
 892 
 893     if(ClockData == 55)
 894     {
 895             //segment A
 896             Display_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, black);    
 897             //segment B
 898             Display_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, black);
 899             //Segment C
 900             Display_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, black);
 901             //Segment D
 902             Display_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, white);    
 903             //Segment E
 904             Display_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, white);
 905             //Segment F
 906             Display_Rect(hchar, hchar + 10, vchar, vchar + 50, white);
 907             //Segment G
 908             Display_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, white);    
 909 
 910     }
 911 
 912     if(ClockData == 56)
 913     {
 914             //segment A
 915             Display_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, black);    
 916             //segment B
 917             Display_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, black);
 918             //Segment C
 919             Display_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, black);
 920             //Segment D
 921             Display_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, black);    
 922             //Segment E
 923             Display_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, black);
 924             //Segment F
 925             Display_Rect(hchar, hchar + 10, vchar, vchar + 50, black);
 926             //Segment G
 927             Display_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, black);    
 928 
 929     }
 930 
 931     if(ClockData == 57)
 932     {
 933             //segment A
 934             Display_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, black);    
 935             //segment B
 936             Display_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, black);
 937             //Segment C
 938             Display_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, black);
 939             //Segment D
 940             Display_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, white);    
 941             //Segment E
 942             Display_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, white);
 943             //Segment F
 944             Display_Rect(hchar, hchar + 10, vchar, vchar + 50, black);
 945             //Segment G
 946             Display_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, black);    
 947     }
 948 }
 949 
 950 void DMM(uint8_t data, uint16_t xchar, uint16_t ychar)
 951 {
 952     switch(data)
 953     {
 954         case 46: // '.'
 955             Display_Rect(xchar + 50, xchar + 60, ychar + 100, ychar + 110, black);
 956             break;
 957 
 958         case 48: // '0'
 959             Display_Rect(xchar + 10, xchar + 50, ychar,        ychar + 10,  black); // A
 960             Display_Rect(xchar + 50, xchar + 60, ychar,        ychar + 50,  black); // B
 961             Display_Rect(xchar + 50, xchar + 60, ychar + 60,   ychar + 110, black); // C
 962             Display_Rect(xchar + 10, xchar + 50, ychar + 100,  ychar + 110, black); // D
 963             Display_Rect(xchar,      xchar + 10, ychar + 60,   ychar + 110, black); // E
 964             Display_Rect(xchar,      xchar + 10, ychar,        ychar + 50,  black); // F
 965             Display_Rect(xchar + 10, xchar + 50, ychar + 50,   ychar + 60,  white); // G
 966             break;
 967 
 968         case 49: // '1'
 969             Display_Rect(xchar + 10, xchar + 50, ychar,        ychar + 10,  white); // A
 970             Display_Rect(xchar + 50, xchar + 60, ychar,        ychar + 50,  black); // B
 971             Display_Rect(xchar + 50, xchar + 60, ychar + 60,   ychar + 110, black); // C
 972             Display_Rect(xchar + 10, xchar + 50, ychar + 100,  ychar + 110, white); // D
 973             Display_Rect(xchar,      xchar + 10, ychar + 60,   ychar + 110, white); // E
 974             Display_Rect(xchar,      xchar + 10, ychar,        ychar + 50,  white); // F
 975             Display_Rect(xchar + 10, xchar + 50, ychar + 50,   ychar + 60,  white); // G
 976             break;
 977 
 978         case 50: // '2'
 979             Display_Rect(xchar + 10, xchar + 50, ychar,        ychar + 10,  black); // A
 980             Display_Rect(xchar + 50, xchar + 60, ychar,        ychar + 50,  black); // B
 981             Display_Rect(xchar + 50, xchar + 60, ychar + 60,   ychar + 110, white); // C
 982             Display_Rect(xchar + 10, xchar + 50, ychar + 100,  ychar + 110, black); // D
 983             Display_Rect(xchar,      xchar + 10, ychar + 60,   ychar + 110, black); // E
 984             Display_Rect(xchar,      xchar + 10, ychar,        ychar + 50,  white); // F
 985             Display_Rect(xchar + 10, xchar + 50, ychar + 50,   ychar + 60,  black); // G
 986             break;
 987 
 988         case 51: // '3'
 989             Display_Rect(xchar + 10, xchar + 50, ychar,        ychar + 10,  black); // A
 990             Display_Rect(xchar + 50, xchar + 60, ychar,        ychar + 50,  black); // B
 991             Display_Rect(xchar + 50, xchar + 60, ychar + 60,   ychar + 110, black); // C
 992             Display_Rect(xchar + 10, xchar + 50, ychar + 100,  ychar + 110, black); // D
 993             Display_Rect(xchar,      xchar + 10, ychar + 60,   ychar + 110, white); // E
 994             Display_Rect(xchar,      xchar + 10, ychar,        ychar + 50,  white); // F
 995             Display_Rect(xchar + 10, xchar + 50, ychar + 50,   ychar + 60,  black); // G
 996             break;
 997 
 998         case 52: // '4'
 999             Display_Rect(xchar + 10, xchar + 50, ychar,        ychar + 10,  white); // A
1000             Display_Rect(xchar + 50, xchar + 60, ychar,        ychar + 50,  black); // B
1001             Display_Rect(xchar + 50, xchar + 60, ychar + 60,   ychar + 110, black); // C
1002             Display_Rect(xchar + 10, xchar + 50, ychar + 100,  ychar + 110, white); // D
1003             Display_Rect(xchar,      xchar + 10, ychar + 60,   ychar + 110, white); // E
1004             Display_Rect(xchar,      xchar + 10, ychar,        ychar + 50,  black); // F
1005             Display_Rect(xchar + 10, xchar + 50, ychar + 50,   ychar + 60,  black); // G
1006             break;
1007 
1008         case 53: // '5'
1009             Display_Rect(xchar + 10, xchar + 50, ychar,        ychar + 10,  black); // A
1010             Display_Rect(xchar + 50, xchar + 60, ychar,        ychar + 50,  white); // B
1011             Display_Rect(xchar + 50, xchar + 60, ychar + 60,   ychar + 110, black); // C
1012             Display_Rect(xchar + 10, xchar + 50, ychar + 100,  ychar + 110, black); // D
1013             Display_Rect(xchar,      xchar + 10, ychar + 60,   ychar + 110, white); // E
1014             Display_Rect(xchar,      xchar + 10, ychar,        ychar + 50,  black); // F
1015             Display_Rect(xchar + 10, xchar + 50, ychar + 50,   ychar + 60,  black); // G
1016             break;
1017 
1018         case 54: // '6'
1019             Display_Rect(xchar + 10, xchar + 50, ychar,        ychar + 10,  white); // A
1020             Display_Rect(xchar + 50, xchar + 60, ychar,        ychar + 50,  white); // B
1021             Display_Rect(xchar + 50, xchar + 60, ychar + 60,   ychar + 110, black); // C
1022             Display_Rect(xchar + 10, xchar + 50, ychar + 100,  ychar + 110, black); // D
1023             Display_Rect(xchar,      xchar + 10, ychar + 60,   ychar + 110, black); // E
1024             Display_Rect(xchar,      xchar + 10, ychar,        ychar + 50,  black); // F
1025             Display_Rect(xchar + 10, xchar + 50, ychar + 50,   ychar + 60,  black); // G
1026             break;
1027 
1028         case 55: // '7'
1029             Display_Rect(xchar + 10, xchar + 50, ychar,        ychar + 10,  black); // A
1030             Display_Rect(xchar + 50, xchar + 60, ychar,        ychar + 50,  black); // B
1031             Display_Rect(xchar + 50, xchar + 60, ychar + 60,   ychar + 110, black); // C
1032             Display_Rect(xchar + 10, xchar + 50, ychar + 100,  ychar + 110, white); // D
1033             Display_Rect(xchar,      xchar + 10, ychar + 60,   ychar + 110, white); // E
1034             Display_Rect(xchar,      xchar + 10, ychar,        ychar + 50,  white); // F
1035             Display_Rect(xchar + 10, xchar + 50, ychar + 50,   ychar + 60,  white); // G
1036             break;
1037 
1038         case 56: // '8'
1039             Display_Rect(xchar + 10, xchar + 50, ychar,        ychar + 10,  black); // A
1040             Display_Rect(xchar + 50, xchar + 60, ychar,        ychar + 50,  black); // B
1041             Display_Rect(xchar + 50, xchar + 60, ychar + 60,   ychar + 110, black); // C
1042             Display_Rect(xchar + 10, xchar + 50, ychar + 100,  ychar + 110, black); // D
1043             Display_Rect(xchar,      xchar + 10, ychar + 60,   ychar + 110, black); // E
1044             Display_Rect(xchar,      xchar + 10, ychar,        ychar + 50,  black); // F
1045             Display_Rect(xchar + 10, xchar + 50, ychar + 50,   ychar + 60,  black); // G
1046             break;
1047 
1048         case 57: // '9'
1049             Display_Rect(xchar + 10, xchar + 50, ychar,        ychar + 10,  black); // A
1050             Display_Rect(xchar + 50, xchar + 60, ychar,        ychar + 50,  black); // B
1051             Display_Rect(xchar + 50, xchar + 60, ychar + 60,   ychar + 110, black); // C
1052             Display_Rect(xchar + 10, xchar + 50, ychar + 100,  ychar + 110, white); // D
1053             Display_Rect(xchar,      xchar + 10, ychar + 60,   ychar + 110, white); // E
1054             Display_Rect(xchar,      xchar + 10, ychar,        ychar + 50,  black); // F
1055             Display_Rect(xchar + 10, xchar + 50, ychar + 50,   ychar + 60,  black); // G
1056             break;
1057 
1058         default:
1059             // Draw nothing for unsupported characters
1060             break;
1061     }
1062 }
1063 
1064 void SetDisplayBrightness(void)
1065 {
1066     Flash_RD(0);
1067     default_Display_Brightness = data_flash;
1068     
1069     //If the flash is not programmed then set the default
1070     if(data_flash == 0xff)
1071     {
1072         default_Display_Brightness = 5;
1073     }
1074     Backlight_Control(default_Display_Brightness);    
1075 }
1076 
1077 void Beep(void)
1078 {
1079     //Beep speaker
1080     //Indicates System is ready
1081     //~2.7KHz
1082     
1083     for(int i=0;i<700;i++)
1084     {
1085         PORTAbits.RA1 = 1;
1086         Delay32(0, 0xb000);
1087         PORTAbits.RA1 = 0;
1088         Delay32(0, 0x7000);
1089     }    
1090 }
1091 
1092 bool SetFreqPOSC(uint8_t f)
1093 {
1094     //increase system clock
1095     //This seems to be the max to have stable USB
1096     SPLLCONbits.PLLMULT = f;
1097     
1098     //The primary oscillator has started, stabilized, and is producing 
1099     //a valid clock signal.
1100     while(CLKSTATbits.POSCRDY == 0);
1101     
1102     //The final PLL clock?after multiplying and dividing?has settled and
1103     //can safely be used as the system clock.
1104     while(CLKSTATbits.DIVSPLLRDY == 0);
1105     
1106     return true;
1107 }
1108 
1109 void __attribute__((nomips16)) _general_exception_handler(void)
1110 {
1111    unsigned int exccode = (_CP0_GET_CAUSE() & 0x7C) >> 2;
1112 
1113     LED_Port(exccode);  // show the raw exception code
1114 
1115     while(1)
1116     {
1117         Beep();
1118     }
1119 }
1120 
1121 void __attribute__((vector(_CHANGE_NOTICE_G_VECTOR), interrupt(ipl7srs), nomips16)) CNG_handler()
1122 {
1123     // /ACK 
1124     if(CNFGbits.CNFG13)
1125     {
1126         T3CONbits.ON = 0;
1127         
1128         //signals I/O good
1129         PORTFbits.RF2 = 1;
1130         
1131         SetPeripheralAddress(0);
1132 
1133         //Unlock the Directive to allow future I/O cycles
1134         IO_Locked = false;
1135 
1136         CNFGbits.CNFG13 = 0;
1137     }
1138     
1139     IFS3bits.CNGIF = 0;
1140 }