Results 1 to 3 of 3
  1. #1
    300+ Forum Addict Tom_G_2010's Avatar
    Join Date
    Mar 2011
    Location
    Central Mass
    Posts
    437
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    My Nav/Comm Radio with 32 Channel Memory and my Transponder

    OK, so here it is. After a very long time away from my build. I came back to find FS2Multi in full bloom so I had to redo my old code to work with it. Instead of trying to edit the old code, I decided to start from scratch and leverage more of the FS2Muti functionality.

    I have sketches written and under test for my Whiskey Compass, my Annunciator panel, my Autopilot, my elevator trim servo for the auto pilot, and a few other things.

    But, tonight, I finally finished testing on my Nav Comm Radio and my Transponder. It's bread boarded and working well. I have a face plate kit from DIY Realism that I am building the boards and display mount for now and I'llpost some updates when that's in a more finished state, likely some time early next month.

    I'm using some of those MAX7219 serial display boards, an Arduino Mega, a pair of ELMA 37 encoders, and the DIY Realism face plate kit which comes with all the other switches and a set of 5 character seven segment displays. The Serial display boards are made to drive two 4 character displays and as many of you know they come pre fab'd with the chip, misc components, pin headers, and the two 7 segment displays.

    With the displays mounted on them, they don't fit behind the face plate kit. However, they are a simple enough circuit that I was going to buy some chips and solder up my own on a breadboard. Then I priced them and found that the pref fab'd displays where less expensive. So my cost cutting solution is to use the circuit board from the prefab'd 8 segment displays to drive my 5 segment displays. It turns out to work quite well.

    I was looking at some online info about the actual Bendix King Radio and discovered that they at some point added the ability to have up to 32 channel presets and that tickled my fancy so I purchased an SD Card Shield and wrote the code to create the same functionality. I am still reading through that code because I find it to be bulky and messy. I want to put it on a diet but haven't figured out just how yet.

    So with that long winded intro here are some pics and the code. I have a couple videos as well, but my phone is refusing to send them so I'll have to post them later.

    IMG_20140325_240302_770.jpgIMG_20140325_240323_744.jpgIMG_20140328_213501_138.jpgIMG_20140328_213527_134.jpg

    Unlike my old code, in this code I learned how to use some array variables and did a much better job of replacing repeat code with sub routines. I'm sure it could all be done much cleaner and in far fewer lines by someone who knows how to write code, but I'm not them. And, for a hack like me I figure what I've dons is fairly slick.

    The code will be in the next post. Apparently I exceeded the per post character limit...
    https://www.facebook.com/mycessnasim PC: Intel Core i7 Haswell @ 3.8GHz, 8Gb Ram, Win 7 64Bit, dual SSDs, GeFroce 780 SIM: FSX w/Aclrtn Pk, FSUIPC4, ASN, UTX, GEX, REX 4

  2. Thanks Jim NZ thanked for this post
  3. #2
    300+ Forum Addict Tom_G_2010's Avatar
    Join Date
    Mar 2011
    Location
    Central Mass
    Posts
    437
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: My Nav/Comm Radio with 32 Channel Memory and my Transponder

    Code:
    #include 
    #include 
    #include "math.h"
    #include "Quadrature.h"
    
    
    // lc0=LedControl(,,,)
    LedControl lc0=LedControl(10,12,11,5);
    
    
    int dspCnt0=lc0.getDeviceCount(); // sets the variable to indicate the number of serial display modules
    
    
    int dspBrghtns = 8;       // These three variables are used with a potentiometer
    int dspBrghtVal = 511;    //  to adjust the brighness of the displays
    int dspBrghtValLast = 0;
    
    
    /*
    It is cheaper to buy the pre fab'd 8 character display mosdules to drive my 5 character displays in the radios
     than it is to but MAX72xx chips and fab my own drivers.
     The following two dimensional array variableis helps me to manage my 7 Segment LED Displays
     You will see it used in the "SVN_SEG_DSP" and "KILL_DSP" functions.  I am using the first five character positions
     of four 8 charcter boards for each radio display.  I then use the two of the remaining charcter segemtns off two of
     the boards to show my trnasponder display
     */
    
    
    int strtPstn[24][24]=  // 7 Segment LED Display Driver array. Used by SVN_SEG_DSP and KILL_DSP functions
    {
      {
        0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,1,1,3,3  }
      ,
      {
        7,6,5,4,3,7,6,5,4,3,7,6,5,4,3,7,6,5,4,3,2,1,2,1  }
    };
    
    
    //Variables and configuration for my SD Card Shield
    File sdCrdFile;
    int sdCrdSlctDgOut = 53;
    Sd2Card card;
    SdVolume volume;
    SdFile root;
    
    
    //Varibles used for the 32 channel memory
    char chnMem_1_State = 'X';
    char chnWrt_1_State = 'X';
    char chnMem_2_State = 'X';
    char chnWrt_2_State = 'X';
    int memChnRad1[2] = {
      0,1};
    int memChnRad2[2] = {
      0,1};
    int memChnRadNo = 1;
    char chnFreqC[] = "----";
    String chnFreqS = "----";
    int chnWrtNo = 0;
    char freqWrtC[] = "----";
    
    
    /*
    Outputs below are for the backlight LED and an RGB LED (my Actv/Stdby swap buttons are illuminated)
     The LED colors indicate the tuning mode
     Off (or backlight only on) = normal tuning with standby freq and swap button
     Red = Channel Tuning mode.  The standby display is replaced by a "ch__"
     Blue = Frequency programing mode
     Green = Storage channel select mode for programming
     */
    //keep these pins sequential
    int memRead_1_DgOutLED = 44;   //Red
    int memWrite_1F_DgOutLED = 45; //Blue
    int memWrite_1C_DgOutLED = 46; //Green
    int btnBckLt_1_DgOutLED = 47;
    
    
    int memRead_2_DgOutLED = 40;   //Red
    int memWrite_2F_DgOutLED = 41; //Blue
    int memWrite_2C_DgOutLED = 42; //Green
    int btnBckLt_2_DgOutLED = 43;
    
    
    // switch inputs
    int com_1_PwrDgIn = 4;
    int com_1_ActvStdbySwapDgIn = 5;
    int com_1_ChanModeDgIn = 6;
    int nav_1_PwrDgIn = 7;
    int nav_1_ActvStdbySwapDgIn = 8;
    int nav_1_ChanModeDgIn = 9;
    
    
    int xPndrBtn_0_DgIn = 23;
    int xPndrBtn_1_DgIn = 22;
    int xPndrBtn_2_DgIn = 25;
    int xPndrBtn_3_DgIn = 24;
    int xPndrBtn_4_DgIn = 27;
    int xPndrBtn_5_DgIn = 26;
    int xPndrBtn_6_DgIn = 29;
    int xPndrBtn_7_DgIn = 28;
    int xPndrIdentDgIn = 34;
    int xPndrVFRDgIn = 35;
    int xPndrClrDgIn = 36;
    int xPndrPwrDgIn = 37;
    
    
    //Encoder Inputs
    Quadrature quad_1_Otr(14, 15);
    Quadrature quad_1_Inr(16, 17);
    Quadrature quad_2_Otr(18, 19);
    Quadrature quad_2_Inr(20, 21);
    
    
    int R1;
    int Rold1;
    int Rdif1;
    String R1Drctn = "X";
    int R2;
    int R3;
    int R4;
    int Rold2;
    int Rdif2;
    int Rold3;
    int Rdif3;
    int Rold4;
    int Rdif4;
    String R2Drctn = "X";
    String R3Drctn = "X";
    String R4Drctn = "X";
    
    
    int ExtTyp; // Gets the serial read of the first two characters of an Extraction
    String ExtVal = ""; // Gets the serial read of the value of an Extraction
    
    
    //Variables to detect single and double click for channel Memory mode select
    unsigned long dblClkStart_1;
    int dblClkDrtn_1 = 500;
    int dblClkCnt_1 = 0;
    
    
    unsigned long dblClkStart_2;
    int dblClkDrtn_2 = 500;
    int dblClkCnt_2 = 0;
    
    
    // Switch debounce timing variables
    long debounceTimeLast = 0;
    long debounceDelay = 50;
    
    
    // Input button state variables
    const int btnCnt = 18;     // Number of switch inputs
    int btnRead;
    // Array variable used so I have flaxability on what input pins I use
    //Doing it this way I don't need to have them sequential or concurrent
    int btnList[btnCnt]={
      com_1_PwrDgIn,           // 0 "XX0",
      com_1_ActvStdbySwapDgIn, // 1 "A06",
      com_1_ChanModeDgIn,      // 2 "XX1",
      nav_1_ActvStdbySwapDgIn, // 3 "A18",
      nav_1_PwrDgIn,           // 4 "XX2",
      nav_1_ChanModeDgIn,      // 5 "XX3",
      xPndrBtn_0_DgIn,         // 6 "A42",
      xPndrBtn_1_DgIn,         // 7 "A42",
      xPndrBtn_2_DgIn,         // 8 "A42",
      xPndrBtn_3_DgIn,         // 9 "A42",
      xPndrBtn_4_DgIn,         // 10 "A42",
      xPndrBtn_5_DgIn,         // 11 "A42",
      xPndrBtn_6_DgIn,         // 12 "A42",
      xPndrBtn_7_DgIn,         // 13 "A42",
      xPndrIdentDgIn,          // 14 "XX7",
      xPndrVFRDgIn,            // 15 "A42",
      xPndrClrDgIn,            // 16 "A42",
      xPndrPwrDgIn};           // 17 "XX9",
    
    
    // Two more array variables to track currrent and last button state
    // Those with 3's and 4's are the power buttons and were done to
    // force an immediate check of the switch state
    int btnState[btnCnt]={
      3,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,3};
    int btnStateLast[btnCnt]={
      4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,4};
    // Serial string associated with each button
    // The |XX_" strings are dummy strings for monitoring and debugging of 
    //Functions that don't send anything to FSX
    String btnString[btnCnt]={
      "XX0",
      "A06",
      "XX1",
      "A18",
      "XX2",
      "XX3",
      "A42",
      "A42",
      "A42",
      "A42",
      "A42",
      "A42",
      "A42",
      "A42",
      "XX7",
      "A42",
      "A42",
      "XX9"};
    
    
    // Bus Voltage variables
    String mstrBusVoltLast = "--.-";
    String avncsBusVoltLast = "--.-";
    String mstrBusVolt = "--.-";
    String avncsBusVolt = "--.-";
    int mstrBusVoltInt = 0;
    int avncsBusVoltInt = 0;
    int avncsBusVoltIntLast = 0;
    int lowVolThshld = 20;
    
    
    // Last Frequency Variables
    String com_1_ActvLast = "---.---";
    String com_1_StbyLast = "---.---";
    String nav_1_ActvLast = "---.--";
    String nav_1_StbyLast = "---.--";
    String xPndrLast = "----";
    
    
    // Power State Variables
    boolean com_1_Pwr = 0;
    boolean nav_1_Pwr = 0;
    boolean xPndrPwr = 0;
    
    
    // Trnasponder input time out variables
    unsigned long xPndrStart;
    int xPndrDelay = 7000;
    boolean xPndrRefresh = 1;
    String SQUAWKCode = "XXXX";
    
    
    void setup(){
    
    
      pinMode(memRead_1_DgOutLED, OUTPUT);
      pinMode(memWrite_1F_DgOutLED, OUTPUT);
      pinMode(memWrite_1C_DgOutLED, OUTPUT);
      pinMode(btnBckLt_1_DgOutLED,OUTPUT);
      pinMode(memRead_2_DgOutLED, OUTPUT);
      pinMode(memWrite_2F_DgOutLED, OUTPUT);
      pinMode(memWrite_2C_DgOutLED, OUTPUT);
      pinMode(btnBckLt_2_DgOutLED,OUTPUT);
      pinMode(sdCrdSlctDgOut, OUTPUT);
    
    
      for(int fCnt = memRead_1_DgOutLED;fCnt <= btnBckLt_2_DgOutLED;fCnt++){
        digitalWrite(fCnt,HIGH);
      }
    
    
      for(int fCnt=0;fCnt < btnCnt; fCnt++){
        pinMode(btnList[fCnt], INPUT_PULLUP);
        btnStateLast[fCnt] = HIGH;
      }
    
    
      INIT_LED_DSP(0,24); // A sub routine that initialises the serial displays
      delay(100);
    
    
      // Check the state of the radio power buttons
      if(digitalRead(com_1_PwrDgIn) == LOW){
        com_1_Pwr = 1;
      }
      else{
        com_1_Pwr = 0;
      }
      CHANNEL_MODE_LED('X',1); // A sub Routine that sets the color of the RGB channel mode LED
    
    
      if(digitalRead(nav_1_PwrDgIn) == LOW){
        nav_1_Pwr = 1;
      }
      else{
        nav_1_Pwr = 0;
      }
      CHANNEL_MODE_LED('X',2);
    
    
      if(digitalRead(xPndrPwrDgIn) == LOW){
        xPndrPwr = 1;
      }
      else{
        xPndrPwr = 0;
      }
    
    
      if (!SD.begin(sdCrdSlctDgOut))Serial.println("initialization failed!");
    
    
      Serial.begin(115200);
    }
    
    
    void loop() {
    
    
      {OTHER();}
      {SIMCONNECT();}
      {ENCODERS();}
    
    
      if (Serial.available()) { 
        ExtTyp = getChar();
    
    
        if (ExtTyp == '=') {
          EQUALS();
        } 
        if (ExtTyp == '<') {
          LESSTHAN();
        }
        if (ExtTyp == '?') {
          QUESTION();
        }
        if (ExtTyp == '/') {
          SLASH();
        }
      }
    }
    
    
    char getChar(){
      while(Serial.available() == 0);
      return((char)Serial.read());
    }
    
    
    void GetString(int ChrCnt){
      ExtVal = "";
      for(int fCnt=0;fCnt xPndrStart + xPndrDelay){
          SQUAWK(16);
        }
      }
    }
    
    
    void SIMCONNECT(){
      // Added Switch Debounce to the Sim Connect code and used the array variables to determine what swith to act on
      for(int fCnt = 0; fCnt < btnCnt;fCnt++){
        btnRead = digitalRead(btnList[fCnt]);
        if(btnRead != btnStateLast[fCnt]){
          debounceTimeLast = millis();
        }
        if ((millis() - debounceTimeLast) > debounceDelay) {
          if (btnRead != btnState[fCnt]) {
            btnState[fCnt] = btnRead;
            if (btnState[fCnt] == LOW) {
              switch(fCnt){
              case 0:                                    // Com Power Buttin
                com_1_Pwr = 1;                           // Sets Power State variable to high
                INIT_LED_DSP(0,10);                      // Initialises the LED Dsiaplays
                SVN_SEG_DSP(0,6,2,com_1_ActvLast);       // Sends the last tuned freq to the displays
                SVN_SEG_DSP(5,6,2,com_1_StbyLast);
                CHANNEL_MODE_LED('X',1);                 // Defaults the channel mode to normal tuning on power up
                break;
              case 1:                                    // Com Act Stby Swap AND Channel Store functions
                if(com_1_Pwr == 0)break;                 // Do nothing if radio power is off
                if(chnMem_1_State == 'W'){               // Button swaps between freq and chan in Store (Write) mode
                  if(chnWrt_1_State == 'F'){             // Frequency Select
                    chnWrt_1_State = 'C';                // Channel Select
                    CHANNEL_MODE_LED('C',1);             // Set color of RGB mode LED to Green
                  }
                  else if(chnWrt_1_State == 'C'){        // Channel Select
                    CHANNEL_STORE(chnWrtNo,freqWrtC,1);  // Sub Routine to Store the selected freq/chan pair on the SD card
                    chnWrt_1_State = 'F';                // swap back to freq select mode
                    CHANNEL_MODE_LED('F',1);             // Set color of RGB mode LED to Blue
                  }
                }
                else if(chnMem_1_State == 'X'){          // Normal tuning mode
                  chnWrt_1_State = 'X';                  // defualt chasnnel write state to off
                  CHANNEL_MODE_LED('X',1);               // Turn off RGB LED and turn on back light LED
                  Serial.println(btnString[fCnt]);       // Send Sim Connect String
                }
                break;
              case 2:                                     // Channel Memory Mode Slector Switch Click and
                if(com_1_Pwr == 0)break;                  // Double Click count and timer start
                dblClkCnt_1++;
                if(dblClkCnt_1 == 1){
                  dblClkStart_1 = millis();
                }
                break;
              case 3:                                    // Same set of functions for Nav side of radio
                if(nav_1_Pwr == 0)break;
                if(chnMem_2_State == 'W'){
                  if(chnWrt_2_State == 'F'){
                    chnWrt_2_State = 'C';
                    CHANNEL_MODE_LED('C',2);
                  }
                  else if(chnWrt_2_State == 'C'){
                    CHANNEL_STORE(chnWrtNo,freqWrtC,2);
                    chnWrt_2_State = 'F';
                    CHANNEL_MODE_LED('F',2);
                  }
                }
                else if(chnMem_2_State == 'X'){
                  chnWrt_2_State = 'X';
                  CHANNEL_MODE_LED('X',2);
                  Serial.println(btnString[fCnt]);
                }
                break;
              case 4:  // Nav Power
                nav_1_Pwr = 1;
                INIT_LED_DSP(10,10);
                SVN_SEG_DSP(10,6,2,nav_1_ActvLast);
                SVN_SEG_DSP(15,6,2,nav_1_StbyLast);
                CHANNEL_MODE_LED('X',2);
                break;
              case 5:    // Nav Radio Mode Switch
                if(nav_1_Pwr == 0)break;
                dblClkCnt_2++;
                if(dblClkCnt_2 == 1){
                  dblClkStart_2 = millis();
                }
                break;
              case 6: // Transponder Digit Inputs
              case 7: //breaks intetionaly omitted for Transponser Digits
              case 8:
              case 9:
              case 10:
              case 11:
              case 12:
              case 13:
              case 14:
              case 15:
              case 16:
                SQUAWK(fCnt);    // Transponder Sub Routine 
                ExtVal = "";
                break;
              case 17:          // Transponder Power
                xPndrPwr = 1;
                INIT_LED_DSP(20,4);
                delay(200);
                SVN_SEG_DSP(20,4,99,xPndrLast);
                break;
              default:         // All other Button Serial sends
                Serial.println(btnString[fCnt]);
              }
            }
            else if (btnState[fCnt] == HIGH) {  // Opposite button condition Actions
              switch(fCnt){
              case 0:                           // Com 1 Power
                com_1_Pwr = 0;
                CHANNEL_MODE_LED('O',1);
                KILL_LED_DSP(0,10);
                chnMem_1_State = 'X';
                chnWrt_1_State = 'X';
                break;
              case 4:                           // Nav 1 Power
                nav_1_Pwr = 0;
                CHANNEL_MODE_LED('O',2);
                KILL_LED_DSP(10,10);
                break;
              case 17:                          // Transponder Power
                xPndrPwr = 0;
                KILL_LED_DSP(20,4);
                break;
              }
            }
          }
        }
        btnStateLast[fCnt] = btnRead;
        if(fCnt == 2){ // Click and Double Click Capture for Radio Channel Mode Switches
          if(dblClkCnt_1 == 1){
            if(millis()- dblClkStart_1 > dblClkDrtn_1){
              dblClkCnt_1 = 0;
              CHANNEL_MODE('R',1);  // Sub Routine, single click toggles between normal tuning and channel mode
            }
          }
          else if(dblClkCnt_1 == 2){
            if(millis()- dblClkStart_1 <= dblClkDrtn_1){
              dblClkCnt_1 = 0;
              CHANNEL_MODE('W',1);  // double click toggles between frequency store mode andd normal tuning mode
            }
          }
        }
        if(fCnt == 5){  // Click and Double Click Capture for Nav Radio Mode Switches
          if(dblClkCnt_2 == 1){
            if(millis()- dblClkStart_2 > dblClkDrtn_2){
              dblClkCnt_2 = 0;
              CHANNEL_MODE('R',2);
            }
          }
          else if(dblClkCnt_2 == 2){
            if(millis()- dblClkStart_2 <= dblClkDrtn_2){
              dblClkCnt_2 = 0;
              CHANNEL_MODE('W',2);
            }
          }
        }
      }
    }
    
    
    void ENCODERS(){                         // Encoder sub Routinhe
      R1 =(quad_1_Otr.position());           // Outer knob Mhz tuning
      if (R1 != Rold1  && com_1_Pwr == 1){
        (Rdif1 = (R1-Rold1));
        if (Rdif1 == 1) R1Drctn = "Down";
        if (Rdif1 == -1) R1Drctn = "Up";
        Rold1 = R1;
    
    
        // Encoder action determined by Channel Mode
    
    
        if(chnMem_1_State == 'X'){            // X = normal Standby Frequency Tuning
          if (R1Drctn == "Up")Serial.println("A02");
          if (R1Drctn == "Down")Serial.println("A01");
        }
        else if(chnMem_1_State == 'R'){       // R = channel tuning mode (Read)
          if (R1Drctn == "Up")SET_CHANNEL(10,"Up",1);  // Channel Display Subroutine, tens digit up/down
          if (R1Drctn == "Down")SET_CHANNEL(10,"Down",1); 
        }
        else if(chnMem_1_State == 'W'){       // W = Channel Storage mode (Write), Frequency select
          if(chnWrt_1_State == 'F'){
            if (R1Drctn == "Up")Serial.println("A02");
            if (R1Drctn == "Down")Serial.println("A01");
          }
          else if(chnWrt_1_State == 'C'){     // C = Channel Storage mode (Write), Channel select
            if (R1Drctn == "Up")SET_CHANNEL(10,"Up",1);  // Channel Display Subroutine, ones digit up/down
            if (R1Drctn == "Down")SET_CHANNEL(10,"Down",1);
          }
        }
    
    
      } 
      R2 =(quad_1_Inr.position());           // Inner knob khz tuning
      if (R2 != Rold2  && com_1_Pwr == 1) {
        (Rdif2 = (R2-Rold2));
        if (Rdif2 == 1) R2Drctn = "Down";
        if (Rdif2 == -1) R2Drctn = "Up";
        Rold2 = R2;
    
    
        if(chnMem_1_State == 'X'){
          if (R2Drctn == "Up")Serial.println("A04");
          if (R2Drctn == "Down")Serial.println("A03");
        }
        else if(chnMem_1_State == 'R'){
          if (R2Drctn == "Up")SET_CHANNEL(1,"Up",1);
          if (R2Drctn == "Down")SET_CHANNEL(1,"Down",1);
        }
        else if(chnMem_1_State == 'W'){
          if(chnWrt_1_State == 'F'){
            if (R2Drctn == "Up")Serial.println("A04");
            if (R2Drctn == "Down")Serial.println("A03");
          }
          else if(chnWrt_1_State == 'C'){
            if (R2Drctn == "Up")SET_CHANNEL(1,"Up",1);
            if (R2Drctn == "Down")SET_CHANNEL(1,"Down",1);
          }
        }
    
    
      }
      R3 =(quad_2_Otr.position());
      if (R3 != Rold3  && nav_1_Pwr == 1) {
        (Rdif3 = (R3-Rold3));
        if (Rdif3 == 1) R3Drctn = "Down";
        if (Rdif3 == -1) R3Drctn = "Up";
        Rold3 = R3;
    
    
        if(chnMem_2_State == 'X'){
          if (R3Drctn == "Up")Serial.println("A14");
          if (R3Drctn == "Down")Serial.println("A13");
        }
        else if(chnMem_2_State == 'R'){
          if (R3Drctn == "Up")SET_CHANNEL(10,"Up",2);
          if (R3Drctn == "Down")SET_CHANNEL(10,"Down",2);
        }
        else if(chnMem_2_State == 'W'){
          if(chnWrt_2_State == 'F'){
            if (R3Drctn == "Up")Serial.println("A14");
            if (R3Drctn == "Down")Serial.println("A13");
          }
          else if(chnWrt_2_State == 'C'){
            if (R3Drctn == "Up")SET_CHANNEL(10,"Up",2);
            if (R3Drctn == "Down")SET_CHANNEL(10,"Down",2);
          }
        }
    
    
      }
      R4 =(quad_2_Inr.position());
      if (R4 != Rold4  && nav_1_Pwr == 1) {
        (Rdif4 = (R4-Rold4));
        if (Rdif4 == 1) R4Drctn = "Down";
        if (Rdif4 == -1) R4Drctn = "Up";
        Rold4 = R4;
    
    
        if(chnMem_2_State == 'X'){
          if (R4Drctn == "Up")Serial.println("A16");
          if (R4Drctn == "Down")Serial.println("A15");
        }
        else if(chnMem_2_State == 'R'){
          if (R4Drctn == "Up")SET_CHANNEL(1,"Up",2);
          if (R4Drctn == "Down")SET_CHANNEL(1,"Down",2);
        }
        else if(chnMem_2_State == 'W'){
          if(chnWrt_2_State == 'F'){
            if (R4Drctn == "Up")Serial.println("A16");
            if (R4Drctn == "Down")Serial.println("A15");
          }
          else if(chnWrt_2_State == 'C'){
            if (R4Drctn == "Up")SET_CHANNEL(1,"Up",2);
            if (R4Drctn == "Down")SET_CHANNEL(1,"Down",2);
          }
        }
    
    
      }
    
    
    }
    
    
    void EQUALS(){
    
    
      ExtTyp = getChar();
      switch(ExtTyp) {
    
    
      case 'A':                         // Com 1 Active Freq
        GetString(7);                   // sub routine to get extraction value
        if(ExtVal != com_1_ActvLast){   // has value changed
          if(com_1_Pwr == 1){           // is power on
            SVN_SEG_DSP (0,6,2,ExtVal); // send extraction value to 7 segment diaply
          }
          com_1_ActvLast = ExtVal;      // update last freq
        }
        ExtVal = "";
        break;
      case 'B':                         // Com 1 Standby Freq
        GetString(7);
        if(ExtVal != com_1_StbyLast){
          if(com_1_Pwr == 1 && chnMem_1_State != 'R'){          // if power is on and channel mode is not in channel tune
            if(chnMem_1_State == 'W' && chnWrt_1_State == 'F'){ // if channel mode is in Write/Freq Select Mode 
              SVN_SEG_DSP (0,6,2,ExtVal);                       // display frequency in active radio display
            }
            else{
              SVN_SEG_DSP (5,6,2,ExtVal);                       // else display it in the standby display
            }
          }
          com_1_StbyLast = ExtVal;                              // set last to new freq
          freqWrtC[0] = com_1_StbyLast.charAt(1);               // store last in char array variable for writing to SD Card
          freqWrtC[1] = com_1_StbyLast.charAt(2);
          freqWrtC[2] = com_1_StbyLast.charAt(4);
          freqWrtC[3] = com_1_StbyLast.charAt(5);
        }
        ExtVal = "";
        break;
      case 'E':                       // Nav 1 Active freq
        GetString(6);
        if(ExtVal != nav_1_ActvLast){
          if(nav_1_Pwr == 1){
            SVN_SEG_DSP (10,6,2,ExtVal);
          }
          nav_1_ActvLast = ExtVal;
        }
        ExtVal = "";
        break;
      case 'F':                      // Nav 1 Standby freq
        GetString(6);
        if(ExtVal != nav_1_StbyLast){
          if(nav_1_Pwr == 1 && chnMem_2_State != 'R'){
            if(chnMem_2_State == 'W' && chnWrt_2_State == 'F'){
              SVN_SEG_DSP (10,6,2,ExtVal);
            }
            else{
              SVN_SEG_DSP (15,6,2,ExtVal);
            }
          }
          nav_1_StbyLast = ExtVal;
          freqWrtC[0] = nav_1_StbyLast.charAt(1);
          freqWrtC[1] = nav_1_StbyLast.charAt(2);
          freqWrtC[2] = nav_1_StbyLast.charAt(4);
          freqWrtC[3] = nav_1_StbyLast.charAt(5);
        }
        ExtVal = "";
        break;
      case 'J':                    // Transponder freq
        GetString(4);
        if(ExtVal != xPndrLast){
          if(xPndrRefresh == 1){   // used to freeze upates while a new code is being keyed in
            if(xPndrPwr == 1){     
              SVN_SEG_DSP (20,4,99,ExtVal);  // send squack code to display
            } 
          }
          xPndrLast = ExtVal;
        }
        ExtVal = "";
        break;
      }
    }
    
    
    void LESSTHAN(){
    
    
    }
    
    
    void QUESTION(){
    
    
      ExtTyp = getChar();
      switch(ExtTyp) {
    
    
      case 'K':
        //    mstrBusVolt = "";
        GetString(4);
        //    for (int fCnt=0;fCnt<4;fCnt++) {
        //      mstrBusVolt += getChar();
        //      delay(10);
        //    }
        if (ExtVal != mstrBusVoltLast){ 
          mstrBusVoltInt = ExtVal.toInt();
          if (mstrBusVoltInt > lowVolThshld) {
            // MASTER BUS VOLTAGE RESTORED
          }
          else {
            // MASTER BUS VOLTAGE TOO LOW
          }
          mstrBusVoltLast = ExtVal;
        }
        ExtVal = "";
        break;
    
    
      case 'U':
        //    avncsBusVolt = "";
        GetString(4);
        //    for (int fCnt=0;fCnt<4;fCnt++) {
        //      avncsBusVolt += getChar();
        //      delay(10);
        //    }
        if (ExtVal != avncsBusVoltLast){
          avncsBusVoltInt = ExtVal.toInt();
          if (avncsBusVoltInt > lowVolThshld) {
            // AVIONICS BUS VOLTAGE RESTORED
            if(avncsBusVoltIntLast <= lowVolThshld && avncsBusVoltInt > lowVolThshld && mstrBusVoltInt > lowVolThshld){
              INIT_LED_DSP(0,24);
            }
            com_1_ActvLast = "---.---";
            com_1_StbyLast = "---.---";
            nav_1_ActvLast = "---.--";
            nav_1_StbyLast = "---.--";
            xPndrLast = "----";
            CHANNEL_MODE_LED('X',1);
            CHANNEL_MODE_LED('X',2);
          }
          else {
            // AVIONICS BUS VOLTAGE TOO LOW
            CHANNEL_MODE_LED('O',1);
            CHANNEL_MODE_LED('O',2);
            KILL_LED_DSP(0,24);
            delay(250);
          }
          avncsBusVoltLast = ExtVal;
          avncsBusVoltIntLast = avncsBusVoltLast.toInt();
        }
        ExtVal = "";
        break;
      }
    }
    
    
    void SLASH(){
    
    
    }
    
    
    // sub routine to drive 7 segment displays
    void SVN_SEG_DSP (int dspChrStrt,int dspChrCnt, int dspDcmPlc, String dspVal){
    
    
      int dcmOfst = 0;                        // used to skip decimal point in string
    
    
      for(int fCnt=0;fCnt
    
    https://www.facebook.com/mycessnasim PC: Intel Core i7 Haswell @ 3.8GHz, 8Gb Ram, Win 7 64Bit, dual SSDs, GeFroce 780 SIM: FSX w/Aclrtn Pk, FSUIPC4, ASN, UTX, GEX, REX 4

  4. #3
    300+ Forum Addict Tom_G_2010's Avatar
    Join Date
    Mar 2011
    Location
    Central Mass
    Posts
    437
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: My Nav/Comm Radio with 32 Channel Memory and my Transponder

    Continued...

    Code:
    // Channel Mode toggle sub routine
    
    void CHANNEL_MODE(char chMode, int radioNo){
    
    /*
       This and the remaining sub routines create the ability to set and use 32 channel presets
       For each of the two radios, comm and nav.  I may add dedicated button to each but for now
       the mode selection is donw using the push button in the encpoders
       A single click toggles the channel read mode on and off
       A double click toggles the Write Mode on and off
       When in write mode swap button steps from freq input, chan input, and store
    */
    
    
      if(radioNo == 1){                 // Radio 1 = comm radio
        if(chMode == 'R'){              // channel mode sent to sub routine is Read
          switch(chnMem_1_State){
          case 'R':                             // if already in Read mode
            chnMem_1_State = 'X';               // set back to normal tuning mode
            chnWrt_1_State = 'X';               // set write mode to off
            CHANNEL_MODE_LED('X',1);            // turn off RGB LED and turn back light LED on
            SVN_SEG_DSP(0,6,2,com_1_ActvLast);  // restore last used freq to active display
            SVN_SEG_DSP(5,6,2,com_1_StbyLast);  // resotre last used freq to standby display
            break; 
          case 'X':                   // mode is currently normal switch to read
          case 'W':                   // or if mode is currently write switch to read
            chnMem_1_State = 'R';     // set channel memory state variable to Read
            chnWrt_1_State = 'X';     // set write state variable to off
            CHANNEL_MODE_LED('R',1);  // Turn on Red RGB LED
            SET_CHANNEL(0,"X",1);     // set standby display to show last selected memory channel
            break; 
          }
        }
        else if (chMode == 'W'){        // channel mode sent to sub routine is Read
          switch(chnMem_1_State){
          case 'X':                   // mode is currently normal set to write
          case 'R':                   // or mode is currently read set to write
            chnMem_1_State = 'W';     // set channel memory state variable to Write
            chnWrt_1_State = 'F';     // set channel write state variable to frequency select
            CHANNEL_MODE_LED('F',1);  // Turn on Blue RGB LED
            SET_CHANNEL(99,"X",1);    // set standby display to show no channel selected
            break; 
          case 'W':
            chnMem_1_State = 'X';              // mode is currently Write set back to normal
            chnWrt_1_State = 'X';              // set write mode to off
            SVN_SEG_DSP(0,6,2,com_1_ActvLast); // restore last used freq to active display
            SVN_SEG_DSP(5,6,2,com_1_StbyLast); // resotre last used freq to standby display
            CHANNEL_MODE_LED('X',1);           // turn off RGB LED and turn back light LED on
            break; 
          }
        }
      }
    
    
      else if(radioNo == 2){           // All the same for the Nav Radio
        if(chMode == 'R'){
          switch(chnMem_2_State){
          case 'X':
            chnMem_2_State = 'R';
            chnWrt_2_State = 'X';
            CHANNEL_MODE_LED('R',2);
            SET_CHANNEL(0,"X",2);
            break; 
          case 'R':
            chnMem_2_State = 'X';
            chnWrt_2_State = 'X';
            CHANNEL_MODE_LED('X',2);
            SVN_SEG_DSP(10,6,2,nav_1_ActvLast);
            SVN_SEG_DSP(15,6,2,nav_1_StbyLast);
            break; 
          case 'W':
            chnMem_2_State = 'R';
            chnWrt_2_State = 'X';
            CHANNEL_MODE_LED('R',2);
            SET_CHANNEL(0,"X",2);
            break; 
          }
        }
        else if (chMode == 'W'){
          switch(chnMem_2_State){
          case 'X':
            chnMem_2_State = 'W';
            chnWrt_2_State = 'F';
            CHANNEL_MODE_LED('F',2);
            SET_CHANNEL(99,"X",2);
            break; 
          case 'R':
            chnMem_2_State = 'W';
            chnWrt_2_State = 'F';
            CHANNEL_MODE_LED('F',2);
            SET_CHANNEL(99,"X",2);
            break; 
          case 'W':
            chnMem_2_State = 'X';
            chnWrt_2_State = 'X';
            SVN_SEG_DSP(10,6,2,nav_1_ActvLast);
            SVN_SEG_DSP(15,6,2,nav_1_StbyLast);
            CHANNEL_MODE_LED('X',2);
            break; 
          }
        }
      }
    }
    
    
    // Sub Routine to control the channel selection and display
    
    
    void SET_CHANNEL(int dgtMlt, String chnDrctn, int radioNo){
    
    
      int dspNo;
      int chnNoDsp[2] = {
        0,1  };  // channel selection array
      dspNo = 0;
    
    
      if(radioNo == 1){                // code for radio 1 - Comm
        chnNoDsp[0] = memChnRad1[0];   // Read last selected channel tens digit into temp variable
        chnNoDsp[1] = memChnRad1[1];   // read last selected channel ones digit onto temp variable
      }
      else if(radioNo == 2){
        chnNoDsp[0] = memChnRad2[0];
        chnNoDsp[1] = memChnRad2[1];
      }
    
    
      if(dgtMlt == 10){                             // Tens digit is being changed
        if(chnDrctn == "Up"){                       // incremented up by encoder
          chnNoDsp[0]++;                            // increment the temp variable
          if(chnNoDsp[0] > 2 && chnNoDsp[1] > 2){   // The next few if statements insure that the tens digit can never go above three
            chnNoDsp[0] = 0;                        // but instead wraps back around to 0 or 1 depending on the ones digit.
          }
          if(chnNoDsp[0] > 3 && chnNoDsp[1] == '0'){
            chnNoDsp[0] = 1;
          }
          if(chnNoDsp[0] > 3){
            chnNoDsp[0] = 0;
          }
        }
        else if(chnDrctn == "Down"){                // Similar to the tens digit increment code but for tens digit decrement
          chnNoDsp[0]--;
          if(chnNoDsp[0] < 1 && chnNoDsp[1] == 0){  // These if statements ensure the tens digit can never go below 0 OR
            chnNoDsp[0] = 3;                        // below 1 if the ones digit is a zero
          }
          if(chnNoDsp[0] < 0 && chnNoDsp[1] < 3){
            chnNoDsp[0] = 3;
          }
          if(chnNoDsp[0] < 0 && chnNoDsp[1] > 2){
            chnNoDsp[0] = 2;
          }
        }
      }
      else if(dgtMlt == 1){                         // Increment code for the ones digit
        if(chnDrctn == "Up"){
          chnNoDsp[1]++;
          if(chnNoDsp[1] > 2 && chnNoDsp[0] == 3){  // ensures the ones digit wraps form 9 back around
            chnNoDsp[1] = 0;                        // except when the tens digits is a 3 in which case it wraps after 2
          }                                         // And the wrap will be to 1 if the tens digit is a 0
          if(chnNoDsp[1] > 9 && chnNoDsp[0] == 0){  // Or to 1 if the tens digit is anything else
            chnNoDsp[1] = 1;
          }
          if(chnNoDsp[1] > 9){
            chnNoDsp[1] = 0;
          }
        }
        else if(chnDrctn == "Down"){
          chnNoDsp[1]--;
          if(chnNoDsp[1] < 1 && chnNoDsp[0] == 0){
            chnNoDsp[1] = 9;
          }
          if(chnNoDsp[1] < 0 && chnNoDsp[0] == 3){
            chnNoDsp[1] = 2;
          }
          if(chnNoDsp[1] < 0){
            chnNoDsp[1] = 9;
          }
        }
      }
    
    
      if(dgtMlt == 99){                            // Sets the default starting display when entering one of the memory modes
        if(radioNo == 1){                          // 99 is used for the defaut start to the Write mode
          SVN_SEG_DSP (0,11,2,"---.-- ch--");
        }
        else if(radioNo == 2){
          SVN_SEG_DSP (10,11,2,"---.-- ch--");
        }
      }
      else{                                        // Else shows the approriate channel value in the Standby slot
        if(radioNo == 1){
          SVN_SEG_DSP (5,5,2," ch--");
          SVN_SEG_DSP (8,1,99,String(chnNoDsp[0]));
          SVN_SEG_DSP (9,1,99,String(chnNoDsp[1]));
        }
        else if(radioNo == 2){
          SVN_SEG_DSP (15,5,2," ch--");
          SVN_SEG_DSP (18,1,99,String(chnNoDsp[0]));
          SVN_SEG_DSP (19,1,99,String(chnNoDsp[1]));
        }
      }
    
    
      if(radioNo == 1){               // Store the last selected channel
        memChnRad1[0] = chnNoDsp[0];
        memChnRad1[1] = chnNoDsp[1];
      }
      else if(radioNo == 2){
        memChnRad2[0] = chnNoDsp[0];
        memChnRad2[1] = chnNoDsp[1];
      }
    
    
      //Read the selected channel or Define channel for Writing
    
    
      if(radioNo == 1){
        if(chnMem_1_State == 'R'){                 // If in Read Mode
          int chN = chnNoDsp[0]*10 + chnNoDsp[1];  // format channel
          CHANNEL_READ(chN,1);                     // Channel Read Sub Routine
          if(chnFreqS == "----"){                  // If returned channel memory is blank
            SVN_SEG_DSP (0,6,2,"---.---");         // display all dashes
          }
          else{
            Serial.println("A05"+chnFreqS);        // Otherwise tune radio to slected channel
          }
        }
        else if(chnMem_1_State == 'W'){            // If in Write Mode
          chnWrtNo = chnNoDsp[0]*10 + chnNoDsp[1]; // Set Channel Write Number
        }
      }
      else if(radioNo == 2){                       // Same for Radio 2 - Nav
        if(chnMem_2_State == 'R'){
          int chN = chnNoDsp[0]*10 + chnNoDsp[1];
          CHANNEL_READ(chN,2);
          if(chnFreqS == "----"){
            SVN_SEG_DSP (10,6,2,"---.---");
          }
          else{
            Serial.println("A17"+chnFreqS);
          }
        }
        else if(chnMem_2_State == 'W'){
          chnWrtNo = chnNoDsp[0]*10 + chnNoDsp[1];
        }
      }
    
    
    
    
    } //End of Set Channel
    
    
    // Channel Read Sub Routine
    void CHANNEL_READ(int chnNo, int radioNo){
    
    
      char fileExtradioNo = 0;  //Clear file Extention Radio Number variable
    
    
      if(radioNo == 1){         // For Radsio 1 - Comm
        fileExtradioNo = '1';   // Set Radio number portion of file name variable
      }
      else if(radioNo == 2){    // Or for Rasdio 2 - Nav
        fileExtradioNo = '2';
      }
    
    
      char fileName[] = "CHNMEM00.RD0";       // Set Defualt File Name to read
      int onesDigit = 0;                      // Set defuial channel number ones digit to 0
      int tensDigit = chnNo / 10;             // Extracxt tens digit form channel number
      if(tensDigit > 0){                      // set ones digit if channel is above 09
        onesDigit = chnNo - (tensDigit * 10); // Then set ones digit
      }
      else{
        onesDigit = chnNo;                    // Otherwise juct setr ones digit
      }
    
    
      fileName[6] = tensDigit + '0';          // Modifiy file names to read requested channel memory
      fileName[7] = onesDigit + '0';
      fileName[11] = fileExtradioNo;
    
    
      sdCrdFile = SD.open(fileName);          // open selected file on the SD Card
      if (sdCrdFile) {                        // If opened ok  Read selected file contents
        sdCrdFile.seek(0);                    // Start Readomg file contents from position 0
        chnFreqC[0] = sdCrdFile.read();       // Store read channel in character array variable
        chnFreqC[1] = sdCrdFile.read();       // as it is read one character at a time
        chnFreqC[2] = sdCrdFile.read();
        chnFreqC[3] = sdCrdFile.read();
        chnFreqS = String(chnFreqC);          // Convert character array to String
        sdCrdFile.close();                    // Close the file on the SD Card
      } 
      else {
        Serial.println("ERROR Reading Freq"); // Trouble shooting error message
      }
    }
    
    
    
    
    // Channel Sore Sub routine
    void CHANNEL_STORE(int chnNo, String chnFrq, int radioNo){
    
    
      char fileExtradioNo = 0; // Same file name setup steps as with channel read
    
    
      if(radioNo == 1){
        fileExtradioNo = '1';
      }
      else if(radioNo == 2){
        fileExtradioNo = '2';
      }
    
    
      char fileName[] = "CHNMEM00.RD0";  
      int onesDigit = 0; 
      int tensDigit = chnNo / 10;
      if(tensDigit > 0){
        onesDigit = chnNo - (tensDigit * 10);
      }
      else{
        onesDigit = chnNo;
      }
    
    
      fileName[6] = tensDigit + '0';
      fileName[7] = onesDigit + '0';
      fileName[11] = fileExtradioNo;
    
    
      sdCrdFile = SD.open(fileName, FILE_WRITE);  // Opne selected file on SD Card
      if (sdCrdFile) {
        sdCrdFile.seek(0);                        // Start writing to file at position zero
        sdCrdFile.print(chnFrq);                  // Store slected frequency
        sdCrdFile.close();                        // Close file
    
    
    
    
          CHANNEL_MODE_LED('X',radioNo);            // Blink Channel Mode LED twice green if file stored ok
        delay(500);
        CHANNEL_MODE_LED('C',radioNo);
        delay(500);
        CHANNEL_MODE_LED('X',radioNo);
        delay(500);
        CHANNEL_MODE_LED('C',radioNo);
        delay(500);
      }
      else {
        Serial.println("ERROR Storing Freq");     // If file did not sore ok blink channel LED Red three times
    
    
        CHANNEL_MODE_LED('X',radioNo);
        delay(250);
        CHANNEL_MODE_LED('R',radioNo);
        delay(250);
        CHANNEL_MODE_LED('X',radioNo);
        delay(250);
        CHANNEL_MODE_LED('R',radioNo);
        delay(250);
        CHANNEL_MODE_LED('X',radioNo);
        delay(250);
        CHANNEL_MODE_LED('R',radioNo);
        delay(250);
        CHANNEL_MODE_LED('X',radioNo);
    
    
      }
    }
    
    
    // Channel Mode LED Sub Rouitine
    void CHANNEL_MODE_LED(char ledMode, int radioNo){
    
    
      // Set state of RGB LED
    
    
      int pinShft = 0;  // Variable to switch between the two channel Mode LEDS
    
    
      if(radioNo == 1){ // Use first four digital outputs for radio one RGB LED
        pinShft = 0;
      }
      else if(radioNo == 2){  // Use second four digital outputs for radio one RGB LED
        pinShft = 4;
      }
      else{
        return;
      }
    
    
      if(ledMode == 'X' && radioNo == 1){  // Modify requested Channel Mem LED Mode based on radio being on or off
        if(com_1_Pwr == 1){
          ledMode = 'X';
        }
        else if(com_1_Pwr == 0){
          ledMode = 'O';
        }
      }
    
    
      if(ledMode == 'X' && radioNo == 2){
        if(nav_1_Pwr == 1){
          ledMode = 'X';
        }
        else if(nav_1_Pwr == 0){
          ledMode = 'O';
        }
      }
    
    
      switch(ledMode){
      case 'R':  // Red LED On for Read
        digitalWrite(memRead_1_DgOutLED + pinShft, LOW);
        digitalWrite(memWrite_1F_DgOutLED + pinShft, HIGH);
        digitalWrite(memWrite_1C_DgOutLED + pinShft, HIGH);
        digitalWrite(btnBckLt_1_DgOutLED + pinShft, HIGH);
        break; 
      case 'F':  // Blue LED On for Write, Freq Select
        digitalWrite(memRead_1_DgOutLED + pinShft, HIGH);
        digitalWrite(memWrite_1F_DgOutLED + pinShft, LOW);
        digitalWrite(memWrite_1C_DgOutLED + pinShft, HIGH);
        digitalWrite(btnBckLt_1_DgOutLED + pinShft, HIGH);
        break; 
      case 'C':  // Green LED On for Write, Chan Select
        digitalWrite(memRead_1_DgOutLED + pinShft, HIGH);
        digitalWrite(memWrite_1F_DgOutLED + pinShft, HIGH);
        digitalWrite(memWrite_1C_DgOutLED + pinShft, LOW);
        digitalWrite(btnBckLt_1_DgOutLED + pinShft, HIGH);
        break; 
      case 'X':  // Stanard backlight LED On for Normal Mode
        digitalWrite(memRead_1_DgOutLED + pinShft, HIGH);
        digitalWrite(memWrite_1F_DgOutLED + pinShft, HIGH);
        digitalWrite(memWrite_1C_DgOutLED + pinShft, HIGH);
        digitalWrite(btnBckLt_1_DgOutLED + pinShft, LOW);
        break;
      case 'O':  // All LEDs off for radio power off or loss of bus voltage.
        digitalWrite(memRead_1_DgOutLED + pinShft, HIGH);
        digitalWrite(memWrite_1F_DgOutLED + pinShft, HIGH);
        digitalWrite(memWrite_1C_DgOutLED + pinShft, HIGH);
        digitalWrite(btnBckLt_1_DgOutLED + pinShft, HIGH);
        break;
      }
    }
    https://www.facebook.com/mycessnasim PC: Intel Core i7 Haswell @ 3.8GHz, 8Gb Ram, Win 7 64Bit, dual SSDs, GeFroce 780 SIM: FSX w/Aclrtn Pk, FSUIPC4, ASN, UTX, GEX, REX 4