Поделитесь мыслями по коду

KindMan
Offline
Зарегистрирован: 19.12.2018

Всем доброго!

Имеется задача: В программе имеется несколько действий, запускаемых ИК-пультами. Например: ВКЛ, ВЫКЛ, ВВЕРХ, ВНИЗ. ИК-пультов может быть несколько, разных производителей. Посылают они свой адрес и команду.

#define ПУЛЬТ_1 0х1111
#define ПУЛЬТ_2 0х2222
#define ПУЛЬТ_3 0х3333

#define ВКЛ_1 0х01
#define ВЫКЛ_1 0х02
#define ВВЕРХ_1 0х03
#define ВНИЗ_1 0х04

#define ВКЛ_2 0хС1
#define ВЫКЛ_2 0хС2
#define ВВЕРХ_2 0хС3
#define ВНИЗ_2 0хС4

#define ВКЛ_3 0хA1
#define ВЫКЛ_3 0хA2
#define ВВЕРХ_3 0хA3
#define ВНИЗ_3 0хA4

void Пришел_сигнал(uint16_t адрес, uint16_t команда) {

  if (адрес == ПУЛЬТ_1) {
    switch (команда) {
      ВКЛ_1 { Действие 1 }
      ВЫКЛ_1 { Действие 2 }
      ВВЕРХ_1 { Действие 3 }
      ВНИЗ_1 { Действие 4 }
    }
  }

  if (адрес == ПУЛЬТ_2) {
    switch (команда) {
      ВКЛ_2 { Действие 1 }
      ВЫКЛ_2 { Действие 2 }
      ВВЕРХ_2 { Действие 3 }
      ВНИЗ_2 { Действие 4 }
    }
  }
  
  if (адрес == ПУЛЬТ_3) {
    switch (команда) {
      ВКЛ_3 { Действие 1 }
      ВЫКЛ_3 { Действие 2 }
      ВВЕРХ_3 { Действие 3 }
      ВНИЗ_3 { Действие 4 }
    }
  }

}

void Действие 1() {
  ...
}
void Действие 2() {
  ...
}
void Действие 3() {
  ...
}
void Действие 4() {
  ...
}

Сейчас у меня так сделано. Вот думаю, как бы это всё оптимизировать, если будут появляться новые действия и пульты? Есть у кого рекомендации?

Logik
Offline
Зарегистрирован: 05.08.2014

Указатели на функции действий - в массив. Можно в паре с кодом команды. Эти коды сами выбираете? Так номеруйте их подряд, проще жить будет. Не совсем понятно, если как в примере, коды команд уникальны, зачем адреса пульта?

KindMan
Offline
Зарегистрирован: 19.12.2018

Logik пишет:

Не совсем понятно, если как в примере, коды команд уникальны, зачем адреса пульта?

Команда  ВКЛ одного пульта может совпасть с ВЫКЛ другой, поэтому адреса нужно сверять.

Logik пишет:

Указатели на функции действий - в массив.

Спасибо за идею. Пока не соображу как мне это может помочь.

Logik
Offline
Зарегистрирован: 05.08.2014

Т.е. команды не уникальны, а пара адрес-команда уникальна. Каждой функции Действие ххх(), соответствует одна или несколько пар адрес-команда? тогда делаете структуру из 3-х полей адрес, команда и указатель на функцию соответствующего ей Действие ххх(). И массив из таких структур. А в Пришел_сигнал будет просто поиск в этом массиве по совпадению адрес, команда и вызов соответствующей Действие ххх() по указател. Можно и по забористей и по экономичнее придумать. То самый простой подход.

rkit
Offline
Зарегистрирован: 23.11.2016

А нужно было подумать, зачем вообще оптимизировать то что и так работает.

KindMan
Offline
Зарегистрирован: 19.12.2018

rkit пишет:

А нужно было подумать, зачем вообще оптимизировать то что и так работает.

В целях самообразования :)

Logik пишет:

делаете структуру из 3-х полей адрес, команда и указатель на функцию соответствующего ей Действие ххх(). И массив из таких структур.

Вот, что сварганил

#define CMD_COUNT 4

#define PULT_1 0x10
#define PULT_2 0x20
#define PULT_3 0x30

struct IR_DATA
{                  
    uint16_t cmd;      
    void (*pfn_my)();
};    

void fn_UP() {
  Serial.print("UP");
}
void fn_DN() {
  Serial.print("DN");
}
void fn_LEFT() {
  Serial.print("LEFT");
}
void fn_RIGHT() {
  Serial.print("RIGHT");
}

  IR_DATA Pult[][CMD_COUNT] = {{0x123, *fn_UP, 0x124, *fn_DN, 0x125, *fn_LEFT, 0x126, *fn_RIGHT},
                               {0x127, *fn_UP, 0x123, *fn_DN, 0x120, *fn_LEFT, 0x124, *fn_RIGHT},
                               {0x122, *fn_UP, 0x126, *fn_DN, 0x123, *fn_LEFT, 0x121, *fn_RIGHT}};  
  
void setup() {
  Serial.begin(9600);
}


void loop() {
Check_IR(PULT_1, 0x123);
delay(1000);
Check_IR(PULT_2, 0x123);
delay(1000);
Check_IR(PULT_3, 0x123);
delay(1000);
Check_IR(PULT_1, 0x126);
delay(1000);
}

void Check_IR(uint16_t ir_adr, uint16_t ir_cmd) {
  uint8_t col = 0;
  switch (ir_adr) {
    case PULT_1:
      col = 0;
      break;        
    case PULT_2:
      col = 1;
      break;        
    case PULT_3:
      col = 2;
      break;        
  }
  for (uint8_t n = 0; n < CMD_COUNT; n++) { 
    if (Pult[col][n].cmd == ir_cmd) {
        Pult[col][n].pfn_my();
        break;
      }
  } 
}

Пультов не много, решил адреса не вносить в структуру. Код смотрится компактнее, но не знаю, конкретно в этом случае есть ли выигрыш?  Оперативки чутка потратил.

Logik
Offline
Зарегистрирован: 05.08.2014

Конечно есть! При наращивании кол-ва команд сразу проявится. Каждая новая команда - один элемент в массив, всего 4 байта. Такой компактности тяжело добиться другими способами. Чтоб не тратить оперативку  Pult в progmem закинуть можно.