Results 1 to 1 of 1
  1. #1
    25+ Posting Member
    Join Date
    Apr 2010
    Location
    BLR
    Posts
    34
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Level-D B767 MCP and Link2fs Multi (Experts)

    Hi,
    Having completed my MCP (coding) for the PMDG 737 NGX using BU0836X for inputs and Arduino for outputs, I have begun considering other detailed payware airliners, and this venerable bird (the LD B763) presents immediate opportunities because Nico Kaan's lekseecon_f allows access to Level-D SDK offsets via FSUIPC.
    So it didn't take very long to write the .ino which manages all the outputs for the numeric displays and led annunciators (lighted MCP switches) for the B767 MCP. (Please note that I have complete control over the INPUTS via Level-D key assignments/FSUIPC mouse macros and BU0836X/Pokeys 56U cards.)
    I have tested it, and the code works, though it is not as efficient or as rapidly responsive as the PMDG code. I am sure others have worked on this before, but I am attaching my own work-in-progress with a screen-shot of the Link2FS page and a photo of the five cascaded LED modules, in case it can be of any use to anyone.
    Thank you Jim, for Link2fs, and Nico for Lekseecon_f, and Fess_ter for your code examples and for introducing me to those neat 8-digit 7-segment LED modules.
    Regards,
    Chakko.

    Code:
    //for FSX Level-D B767-300ER with running Lekseecon_f by Nico Kaan
    //this .ino manages all OUTPUTS for central MCP numeric displays & led annunciators in illuminated switches)
    //it also manages OUTPUTS for Pedestal ILS Freq and Course numeric displays, but does not access VOR1 Freq and Crs
    //display units used here are 5 cascaded 8-digit 7-segment LED modules driven by MAX7219
    //thanks of course to Jim for Link2fs, Nico Kaan for Lekseecon_f and Fess_ter for his code examples
    
    #include 
    
    LedControl led_Display_1 = LedControl(12,10,11,5);   // 5 modules 
    
    int CodeIn;        // used on all serial reads from Jim's code
    String Digit;      //
    int Count;         // This variable used in loops in the EQUALS() function
    
    int MCP_IASMach_set[3];
    int MCP_Heading_set[3];
    int MCP_VertSpeed_minus;
    int MCP_VertSpeed_set[4];
    int MCP_Altitude_set[5];
    
    String PED_ILS_Freq;
    String ilsfreq;
    int PED_ILS_Crs[3];
    
    unsigned long MCP_buttons;
    String mcpbut;
    
    int MCP_CMD_L;
    int MCP_CMD_C;
    int MCP_CMD_R;
    int MCP_SpeedMode;
    int MCP_SpeedInterv;
    int MCP_X;  //free offset
    int MCP_LNAV;
    int MCP_VNAV;
    int MCP_FLCH;
    int MCP_HDGHOLD;
    int MCP_VS;
    int MCP_ALTHOLD;
    int MCP_LOC;
    int MCP_APP;
    int MCP_BCRS;
    int MCP_N1;
    int MCP_SPD;
    
    // **************************************************************************************************
    
    void setup() 
    {
      // The MAX72XX is in power-saving mode on startup, we have to do a wakeup call
      delay (500);
      led_Display_1.shutdown(0,false);      
      delay (500);                          
      led_Display_1.shutdown(1,false);
      delay (500);                          
      led_Display_1.shutdown(2,false);
      delay (500);                          
      led_Display_1.shutdown(3,false);  
      delay (500);                          
      led_Display_1.shutdown(4,false);
      
      // Set the brightness to a lower than medium values 
      led_Display_1.setIntensity(0,4);
      led_Display_1.setIntensity(1,4);
      led_Display_1.setIntensity(2,4);
      led_Display_1.setIntensity(3,4);
      led_Display_1.setIntensity(4,4);
      
      // and clear the display 
      led_Display_1.clearDisplay(0);
      led_Display_1.clearDisplay(1);
      led_Display_1.clearDisplay(2);
      led_Display_1.clearDisplay(3);
      led_Display_1.clearDisplay(4);
      
      // Get all the "project" OUTPUT pins ready
      for (int PinNo = 2; PinNo <= 9; PinNo++)  
      {pinMode(PinNo, OUTPUT);}
      for (int PinNo = 21; PinNo <= 52; PinNo++)
      {pinMode(PinNo, OUTPUT);}
        
      Serial.begin(115200);   
    }//end of setup
    
    //*******************************************
    
    void loop() 
    {if (Serial.available()) 
      { CodeIn = getChar();
        if (CodeIn == '#') 
        {
         POUND();              // The first identifier is "#"
         iasmDisplay();        // to hsaten response of IAS/M display
         vsDisplay();          // to hsaten response of V/S display  
        } 
      }
    }
    
    //*********************************************************
    
    void iasmDisplay() // special void to manage ias/m display and blanking
    { if (MCP_SpeedInterv ==0)  //blank display (managed mode)
        {led_Display_1.setChar(0,7,' ',false);
        led_Display_1.setChar(0,6,' ',false);
        led_Display_1.setChar(0,5,' ',false);
        led_Display_1.setChar(0,4,' ',false);}
        
      else if ((MCP_SpeedInterv ==1) && (MCP_SpeedMode ==0))  //ias mode
        {led_Display_1.setChar(0,7,' ',false);
        led_Display_1.setDigit(0,6,MCP_IASMach_set[0],false);
        led_Display_1.setDigit(0,5,MCP_IASMach_set[1],false);
        led_Display_1.setDigit(0,4,MCP_IASMach_set[2],false);}
        
      else if ((MCP_SpeedInterv ==1) && (MCP_SpeedMode ==1))  //mach mode
        {led_Display_1.setChar(0,7,' ',true);  //insert leading dp
        led_Display_1.setDigit(0,6,MCP_IASMach_set[0],false);
        led_Display_1.setDigit(0,5,MCP_IASMach_set[1],false);
        led_Display_1.setDigit(0,4,MCP_IASMach_set[2],false);}
    }
    
    //*********************************************************
    
    void vsDisplay()  // special void to manage v/s display and blanking
    {if (MCP_VS ==0)  //blank display (managed mode)
        {led_Display_1.setChar(1,7,' ',false);
        led_Display_1.setChar(1,6,' ',false);
        led_Display_1.setChar(1,5,' ',false);
        led_Display_1.setChar(1,4,' ',false);
        led_Display_1.setChar(1,3,' ',false);
        led_Display_1.setChar(1,2,' ',false);
        led_Display_1.setChar(1,1,' ',false);
        led_Display_1.setChar(1,0,' ',false);}
     else if (MCP_VS ==1)  //show v/s with leading minus if required
        {led_Display_1.setChar(1,7,' ',false);
        led_Display_1.setChar(1,6,' ',false);
        led_Display_1.setChar(1,5,' ',false);
        led_Display_1.setChar(1,4,MCP_VertSpeed_minus,false);
        led_Display_1.setDigit(1,3,MCP_VertSpeed_set[0],false);
        led_Display_1.setDigit(1,2,MCP_VertSpeed_set[1],false);
        led_Display_1.setDigit(1,1,MCP_VertSpeed_set[2],false);
        led_Display_1.setDigit(1,0,MCP_VertSpeed_set[3],false);} 
    }
    
    //*********************************************************
    
    char getChar()// Get a character from the serial buffer
    {
      while(Serial.available() == 0);   // wait for data
      return((char)Serial.read());      
    }                                   
    
    //*********************************************************
    
    void POUND(){      // The first identifier was "#"
    
            CodeIn = getChar(); // Get another character
            switch(CodeIn) {// Now lets find what to do with it
          
         case 'a':    //  MCP_IASMach set (fsuipc offset 296 = 0x8b18, in knots/mach, range 100 to 950) 
            //Note: Mach values are given x 1000, so .802 = 802
            Count = 0;
            while (Count < 3)
            {Digit = "";
            Digit += getChar();
            MCP_IASMach_set[Count] = Digit.toInt();
            Count++;}
         break;
        
            
         case 'b':    //  MCP_buttons state (fsuipc offset 742 = 0x8bb8)
            mcpbut = "";
            mcpbut += getChar();
            mcpbut += getChar();
            mcpbut += getChar();
            mcpbut += getChar();
            mcpbut += getChar();
            MCP_buttons = mcpbut.toInt();
            
            //read led annunciators and display states
            //16 bit value on level-d/lekseecon/fsuipc offset 742 = 0x8b18 
            //0 Left Autopilot engaged //1 Centre Autopilot engaged   //2 Right Autopilot engaged   //3 Speed Mode: 0=IAS, 1=MACH 
            //4 Speed intervention: 0=IAS window blanked, 1=window displayed   //5 -- free -   //6 LNAV   //7 VNAV 
            //8 FLCH   //9 HDG HOLD   //10 V/S   //11 ALT HOLD   //12 LOC   //13 APP   //14 BCRS   //15 N1   //16 SPD
            //extract bit states, right to left (lsb to msb, by 16 successive division, remainders modulo 2, on fsuipc extraction in long int form
            MCP_CMD_L = MCP_buttons % 2;  //least significant bit 0 (right-most)       
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_CMD_C = MCP_buttons % 2;   
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_CMD_R = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_SpeedMode = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_SpeedInterv = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_X = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_LNAV = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_VNAV = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_FLCH = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_HDGHOLD = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_VS = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_ALTHOLD = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_LOC = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_APP = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_BCRS = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_N1 = MCP_buttons % 2;
            MCP_buttons = (int) (MCP_buttons/2);
            MCP_SPD = MCP_buttons % 2;  //most significant bit 16 (left-most)
            
            //write to mcp led annunciators                
            if (MCP_CMD_L ==1) {digitalWrite (27, HIGH);}
            else if (MCP_CMD_L ==0) {digitalWrite (27, LOW);}
            if (MCP_CMD_C ==1) {digitalWrite (26, HIGH);}
            else if (MCP_CMD_C ==0) {digitalWrite (26, LOW);}
            if (MCP_CMD_R ==1) {digitalWrite (25, HIGH);}
            else if (MCP_CMD_R ==0) {digitalWrite (25, LOW);}
            if (MCP_LNAV ==1) {digitalWrite (24, HIGH);}
            else if (MCP_LNAV ==0) {digitalWrite (24, LOW);}
            if (MCP_VNAV ==1) {digitalWrite (23, HIGH);}
            else if (MCP_VNAV ==0) {digitalWrite (23, LOW);}
            if (MCP_FLCH ==1) {digitalWrite (22, HIGH);}
            else if (MCP_FLCH ==0) {digitalWrite (22, LOW);}
            if (MCP_HDGHOLD ==1) {digitalWrite (2, HIGH);}
            else if (MCP_HDGHOLD ==0) {digitalWrite (2, LOW);}
            if (MCP_VS ==1) {digitalWrite (3, HIGH);}
            else if (MCP_VS ==0) {digitalWrite (3, LOW);}
            if (MCP_ALTHOLD ==1) {digitalWrite (4, HIGH);}
            else if (MCP_ALTHOLD ==0) {digitalWrite (4, LOW);}
            if (MCP_LOC ==1) {digitalWrite (5, HIGH);}
            else if (MCP_LOC ==0) {digitalWrite (5, LOW);}
            if (MCP_APP ==1) {digitalWrite (6, HIGH);}
            else if (MCP_APP ==0) {digitalWrite (6, LOW);}
            if (MCP_BCRS ==1) {digitalWrite (7, HIGH);}
            else if (MCP_BCRS ==0) {digitalWrite (7, LOW);}
            if (MCP_N1 ==1) {digitalWrite (8, HIGH);}
            else if (MCP_N1 ==0) {digitalWrite (8, LOW);}
            if (MCP_SPD ==1) {digitalWrite (9, HIGH);}
            else if (MCP_SPD ==0) {digitalWrite (9, LOW);}
         break;
        
          
         case 'c':    //  MCP_Heading set (fsuipc offset 297 = 0x8b1c, in degrees, range 0 to 359)
              Count = 0;
              while (Count < 3)
              {Digit = "";
              Digit += getChar();
              MCP_Heading_set[Count] = Digit.toInt();
              Count++;}
              
              led_Display_1.setDigit(0,3,' ',false);
              led_Display_1.setDigit(0,2,MCP_Heading_set[0],false);
              led_Display_1.setDigit(0,1,MCP_Heading_set[1],false);
              led_Display_1.setDigit(0,0,MCP_Heading_set[2],false);
         break;
        
        
         case 'd':    //  MCP_VertSpeed set with minus (fsuipc offset 298 = 0x8b20, range -9900 to 9900)
              Count = 0;
              while (Count < 4)
              {Digit = "";
              Digit += getChar();
                  if (Count == 0)
                  {if (Digit == "-")
                  {MCP_VertSpeed_minus = '-';
                  Digit = "";
                  Digit += getChar();}
                  else 
                  {MCP_VertSpeed_minus = ' ';}}                     
              MCP_VertSpeed_set[Count] = Digit.toInt();
              Count++;}
          break;
          
        
          case 'e':    //  MCP_Altitude set  (fsuipc offset 299 = 0x8b24, in feet x100, range 0 to 640)
              Count = 0;
              while (Count < 5)
              {Digit = "";
              Digit += getChar();
              MCP_Altitude_set[Count] = Digit.toInt();
              Count++;}
              
              {led_Display_1.setDigit(2,7,' ',false);
              led_Display_1.setDigit(2,6,' ',false);
              led_Display_1.setDigit(2,5,' ',false);
              led_Display_1.setDigit(2,4,MCP_Altitude_set[0],false);
              led_Display_1.setDigit(2,3,MCP_Altitude_set[1],false); 
              led_Display_1.setDigit(2,2,MCP_Altitude_set[2],false);
              led_Display_1.setDigit(2,1,MCP_Altitude_set[3],false);
              led_Display_1.setDigit(2,0,MCP_Altitude_set[4],false);}
          break;
       
        
          case 'f':    //  Pedestal_ILS_Frequency set (fsuipc offset NAV1 freq 0x0350)
              /*Count = 0;
              while (Count < 5)
              {Digit = "";
              Digit += getChar();
              PED_ILS_Freq[Count] = Digit.toInt();
              Count++;}*/
              ilsfreq = "";
              ilsfreq += getChar();
              ilsfreq += getChar();
              ilsfreq += getChar();
              ilsfreq += getChar();
              ilsfreq += getChar();
              PED_ILS_Freq = ilsfreq;
              
              if (PED_ILS_Freq =="10800")
              {led_Display_1.setChar(3,7,'-',false);
              led_Display_1.setChar(3,6,'-',false); 
              led_Display_1.setChar(3,5,'-',false);
              led_Display_1.setChar(3,4,'-',false);
              led_Display_1.setChar(3,3,'-',false);}
              
              else
              {led_Display_1.setChar(3,7,PED_ILS_Freq[0],false);
              led_Display_1.setChar(3,6,PED_ILS_Freq[1],false); 
              led_Display_1.setChar(3,5,PED_ILS_Freq[2],true); // activate dp
              led_Display_1.setChar(3,4,PED_ILS_Freq[3],false);
              led_Display_1.setChar(3,3,PED_ILS_Freq[4],false);}
          break;
        
          
          case 'g':    //  Pedestal_ILS_Course set (fsuipc offset NAV1 OBS 0x0C4E)
              Count = 0;
              while (Count < 3)
              {Digit = "";
              Digit += getChar();
              PED_ILS_Crs[Count] = Digit.toInt();
              Count++;}
              
              led_Display_1.setChar(4,7,' ',false);
              led_Display_1.setDigit(4,6,PED_ILS_Crs[0],false);
              led_Display_1.setDigit(4,5,PED_ILS_Crs[1],false);
              led_Display_1.setDigit(4,4,PED_ILS_Crs[2],false);
           break;
       
        }  // end of switch
    } // end of void pound
    
    Attached Images Attached Images
    Last edited by tomahawk66; 01-01-2015 at 10:55 AM. Reason: amended code, added photo