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