Understanding Commands

Continuing downward on my_pages.h the next section is a large two dimensional array containing the definitions of the rows of commands. Each entry in the array is a structure of type cmnd_t which is defined in the main tab of the program as follows.

//Each command consists of a character display, the 32-bit IR value to be
// transmitted, the protocol number, and a special flag hich alternatively may indicate
// the number of bits.
typedef struct cmnd {
  uint8_t Glyph;    //The character to be displayed
  int32_t Value;    //string of bits to be transmitted or page number two change to
                    // if Special == SPL_CHANGE_PAGE
  uint8_t Protocol; //Sony, NEC etc.
  uint8_t Special;  //special handling flag or number of bits
} cmnd_t;

If you're not a C++ programmer, this will look like gibberish to you. Don't worry, we will explain what it means. Let's look at one of the existing rows of commands back in my_pages.h. At approximately line number 129 you will see the following code. This is the second row of my definitions for my Samsung 3D TV.

  //TV 2: menu, tools, left, right, up, down, select, exit, return, 3-D
  #define ROW_TV_2 13
  {{'m',TV_MENU,NECX,0}, {'t',TV_TOOLS,NECX,0}, {MY_LEFT_ARROW,TV_LEFT,NECX,0},
   {MY_RIGHT_ARROW,TV_RIGHT,NECX,0}, {MY_UP_ARROW,TV_UP,NECX,0}, {MY_DOWN_ARROW,TV_DOWN,NECX,0},
   {'*',TV_SELECT,NECX,0}, {'x',TV_EXIT,NECX,0}, {'r',TV_RETURN,NECX,0}, {'3',TV_3D,NECX,0}},

The first line is just a comment reminding us what commands are going to be on this particular row of the page. The next define is a definition of the row name and number. Each row needs a unique name and number. The row number needs to be in order with the definitions above and below it. This numbering system applies to the entire remo, not just the page we are working on.

The next three lines are the series of 10 commands that make up the row. The entire row is enclosed in scroll braces {} followed by a comma. Each of the commands within the row consists of 4 items separated by commas and enclosed in scroll brackets. Let's look at the first command it reads {'m',TV_MENU, NECX,0}

This tells us that the character to be displayed on the screen is the letter 'm'. The IR code to be transmitted is named TV_MENU. That value is defined in the file samsung_necx_codes.h where I have all of the IR codes for this particular TV. The next item is the protocol number. In this case it is NECX. The possible values for this protocol number are defined in Arduino/Libraries/IRLibProtocols/IRLibProtocols.h as follows. For more information see the IRLib documentation.

#define UNKNOWN 0
#define NEC 1
#define SONY 2
#define RC5 3
#define RC6 4
#define PANASONIC_OLD 5
#define JVC 6
#define NECX 7
#define SAMSUNG36 8
#define GICABLE 9 
#define DIRECTV 10
#define RCMM 11
#define CYKM 12

The final item is a special flag that has multiple purposes. We will describe later. In this instance it is simply 0.

The next entry is to bring up the Tools menu on the TV. Its display letter is 't'. The next 4 entries are for the arrow keys on the remote. Rather than use a text character for the display we are going to use a special graphics character called MY_LEFT_ARROW as well as special characters for right, up, and down. You can see a complete list of the available special graphics characters in the file SymbolMono18pt7b.h.

Defining New Commands

Now that we've seen how the commands are laid out, let's define new commands for the RCA TV. We are going to create a page with three rows of commands. We are not going to define a button for absolutely every command on the remote because we don't use everything very often. Also as mentioned earlier, it isn't really practical to enter channel numbers with the Ultimate Remote at this time.

In my_pages.h scroll down to approximately line number 210. You will see the end of the keyboard page definitions ending with ROW_KB_6 32. Below that are some empty commands we've thrown in just in case we accidentally get some index out of range. We are now going to insert three rows of commands after the end of the keyboard definitions but before these extra entries. It will look like this.

  //RCA TV 1: power, input, ch up, ch down, vol up, vol down, mute, info, back, minus
  #define ROW_RCATV_1 33
  {{MY_POWER_SYMBOL,RCA_POWER,NEC,0}, {'i',RCA_INPUT,NEC,0}, {MY_CH_UP,RCA_CH_UP,NEC,0},
   {MY_CH_DOWN,RCA_CH_DN, NEC,0}, {'+',RCA_VOLUP, NEC,0}, {'-',RCA_VOLDN, NEC,0}, 
   {'0',RCA_MUTE, NEC,0}, {'?',RCA_EPG_I, NEC,0}, {'b',RCA_BACK, NEC,0}, {'-',RCA_MINUS, NEC,0}},
  //RCA TV 2: menu, left, right, up, down, select, exit, home, netflix, vudo
  #define ROW_RCATV_2 34
  {{'m',RCA_MENU, NEC,0}, {MY_LEFT_ARROW,RCA_LEFT,NEC,0},{MY_RIGHT_ARROW,RCA_RIGHT,NEC,0},
   {MY_UP_ARROW,RCA_UP,NEC,0},{MY_DOWN_ARROW,RCA_DOWN,NEC,0}, {'*',RCA_OKAY,NEC,0},
   {'x',RCA_EXIT,NEC,0},{'h',RCA_HOME,NEC,0},{'N',RCA_NETFLIX,NEC,0},{'V',RCA_VUDU,NEC,0}},
  //RCA TV 3: rew, play/Pause, ff, stop, Red, green, yellow, blue,apps, blank left,
  #define ROW_RCATV_3 35
  {{MY_REWIND,RCA_REWIND,NEC,0},{MY_PLAY,RCA_PLAY_PAUSE,NEC,0},{MY_FF,RCA_FF,NEC,0},
   {MY_STOP,RCA_STOP,NEC,0},{'R',RCA_RED,NEC,0}, {'G',RCA_GREEN,NEC,0},
   {'Y',RCA_YELLOW,NEC,0},{'B',RCA_BLUE,NEC,0},{'a',RCA_APPS,NEC,0}, {' ',0x0,0,0}},

The first two rows have 10 commands each in the final row has only 9. We replaced it with a blank entry because we didn't need it. As you can see we use a combination of special symbols such as MY_POWER_SYMBOL and regular print characters such as 'i' for the input key. The IR codes such as RCA_POWER came from the file rca_tv_codes.h that we created earlier.

There are just a couple of more items we need to edit to add these rows and the new page that we've created. Just below the command definitions you will see the following code:

const char Num_Rows_in_Page[]= {5, 6, 7, 4, 4, 5, 8, 1};

//Define which pages contain which rows
const uint8_t Pages [] [10]= {
  /*Cable*/   {ROW_PAGES, ROW_CBL_PLAY, ROW_CBL_CH, ROW_CBL_ARROW, ROW_CBL_PIP},
  /*Mouse*/   {ROW_PAGES, ROW_MSAR_1, ROW_MSAR_2, ROW_MSAR_3, ROW_MSAR_4, ROW_MSAR_5},
  /*Keyboard*/{ROW_PAGES, ROW_KB_1,ROW_KB_2,ROW_KB_3,ROW_KB_4,ROW_KB_5,ROW_KB_6},
  /*Amp*/     {ROW_PAGES, ROW_AMP_1, ROW_AMP_2, ROW_AMP_3},
  /*TV*/      {ROW_PAGES, ROW_TV_1, ROW_TV_2, ROW_TV_3},
  /*Bluray*/  {ROW_PAGES, ROW_BLU_1, ROW_BLU_2, ROW_BLU_3, ROW_BLU_4},
  /*Test*/    {ROW_PAGES, ROW_TEST_1, ROW_TEST_2, ROW_TEST_3, ROW_TEST_4, ROW_TEST_5, ROW_TEST_6, ROW_TEST_7}
};

The top row of numbers is just what it says: it is the number of rows in each page. Note that this includes the page selection row at the top. Our new page consists of 3 rows plus the page selection row means 4 rows. The "1" at the end of the list is for the Bluetooth page. So we will insert "4" just before that and after the "8" rows of the test page as follows.

const char Num_Rows_in_Page[]= {5, 6, 7, 4, 4, 5, 8, 4, 1};

Now we need to tell it which rows go on this page at the bottom just after the section which defines the test page edit it as shown below. Note that each of these rows has to be separated by a comma so be sure to add a comma at the end of the Test row.

  /*Test*/    {ROW_PAGES, ROW_TEST_1, ROW_TEST_2, ROW_TEST_3, ROW_TEST_4, ROW_TEST_5, ROW_TEST_6, ROW_TEST_7},
  /*RCA TV*/  {ROW_PAGES, ROW_RCATV_1, ROW_RCATV_2, ROW_RCATV_3}
};

We have now fully defined our new page of commands for the RCA TV but we can't get there from here. We need a way to navigate to that page. Go back up the top of my_pages.h at approximately line number 59. You will see the very first row of commands that appears at the top of every screen. The code looks like this:

//An array of rows of commands each row is at most COL_MAX long but could be shorter.
const cmnd_t  MyCommands[][COL_MAX] = {
  //Page change commands: cable, mouse/arrows, keyboard, kitchen, amplifier, TV, Blu-ray, extra, Bluetooth, blank, blank
  #define ROW_PAGES     0
  {{'C',PAGE_CBL,0,SPL_CHANGE_PAGE},  {'M',PAGE_MSAR,0,SPL_CHANGE_PAGE}, {'K',PAGE_KB,0,SPL_CHANGE_PAGE}, 
   {'A',PAGE_AMP,0,SPL_CHANGE_PAGE},  {'T',PAGE_TV,0,SPL_CHANGE_PAGE},  {'B',PAGE_BLU,0,SPL_CHANGE_PAGE}, 
   {'X',PAGE_TEST,0,SPL_CHANGE_PAGE}, {MY_BLUETOOTH,PAGE_BLE,0,SPL_CHANGE_PAGE},
   {' ',0x0,0,0}, {' ',0x0,0,0}, {' ',0x0,0,0}, {' ',0x0,0,0}, {' ',0x0,0,0}, {' ',0x0,0,0}},

Like other rows of commands, each entry consists of 4 parts. The first is the character or symbol that will be displayed on the screen. Next is usually the IR command but these particular commands don't send any IR signals. Instead this field is used to specify the number of the page. We previously defined PAGE_RCA_TV at approximately line number 48 of this file. The third entry usually defines the IR protocol but again we are not sending any IR this time so it remains 0. The final item in each command is a flag that we have not previously used. It's the way we tell the program that this is a special different command than the usual IR transmission command. We put in the entry SPL_CHANGE_PAGE. There are a variety of these special flags which we will discuss later. After editing this row of commands to include a link to our new RCA TV page it will look like this.

  //Page change commands: cable, mouse/arrows, keyboard, kitchen, amplifier, TV, Blu-ray, extra, RCA TV, Bluetooth, blank, blank
  #define ROW_PAGES     0
  {{'C',PAGE_CBL,0,SPL_CHANGE_PAGE},  {'M',PAGE_MSAR,0,SPL_CHANGE_PAGE}, {'K',PAGE_KB,0,SPL_CHANGE_PAGE}, 
   {'A',PAGE_AMP,0,SPL_CHANGE_PAGE},  {'T',PAGE_TV,0,SPL_CHANGE_PAGE},  {'B',PAGE_BLU,0,SPL_CHANGE_PAGE}, 
   {'X',PAGE_TEST,0,SPL_CHANGE_PAGE}, {'R',PAGE_RCA,0,SPL_CHANGE_PAGE}, {MY_BLUETOOTH,PAGE_BLE,0,SPL_CHANGE_PAGE},
   {' ',0x0,0,0}, {' ',0x0,0,0}, {' ',0x0,0,0}, {' ',0x0,0,0}, {' ',0x0,0,0}},

You can now compile and upload the sketch. If you navigate to the RCA page which is designated by "R" you should see in the following page of commands.

This guide was first published on Sep 23, 2019. It was last updated on Sep 23, 2019.

This page (Defining New Rows) was last updated on Jan 08, 2020.

Text editor powered by tinymce.