Перейти к содержанию
    

Опрос клавиатуры на С

Опрос клавиатуры на С -> Как написать компактный и "красивый" код?

Дайте pls примеры опроса матрицы клавиш на С (C++ не надо).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Опрос клавиатуры на С -> Как написать компактный и "красивый" код?

Дайте pls примеры опроса матрицы клавиш на С (C++ не надо).

В своих проектах разделяю опрос клавиатуры (неважно какая, матричная или обычная) на два разных этапа:

1) опрос существующего состояния кнопок с заданной периодичностью, обычно раз в 50мс, чтобы потом не "воевать" с дребезгом.

2) анализ (сравнение) текущего и предыдущего состояния клавиатуры, тем самым выделяя события отпускания и нажатия

далее в зависимости от проекта реализовывал систему подписки на различные события, если в двух словах, то речь про колбэки и их продвинутые аналоги.

Модули, которым нужно ждать события от клавиатуры, "подписываются" на нужные события и кнопки, "обращаясь" к модулю клавиатуры.

События всего два - отпускание и нажатие. Этого обычно вполне достаточно. Долгое удержание или т. п. реализуется уже в самом модуле.

Такая схема дает возможность напрочь отвязаться от способа реализации клавиатуры: будь то "примитивные" кнопки на пинах и внешние проводные или беспроводное клавиатуры (например, пульты оператора).

 

Т.е. я жестко разделяю опрос клавиатуры от тех модулей/блоков, которые ждут от нее реакцию.

Примеры приводить не буду, т. к. вы "запретили" тут использовать C++.

Однако, на голом С все описанное выше тоже реализуется, но уже несколько "топорно" и далеко не так "компактно и красиво".

К счастью (кому-то к сожалению) давно не использую подобный инструментарий и поэтому примеров на нем, увы, не сохранилось ((

 

Добавлю, что использую RTOS, т. к. под ней это реализуется значительно проще: не нужно "колдовать" с таймерами и самодельными генераторами/приемниками событий.

 

зы. В проектах с одной/двумя кнопками все реализую значительно проще, но аналогично - периодический опрос и сравнение двух состояний: предыдущего и текущего.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Добавлю, что использую RTOS, т. к. под ней это реализуется значительно проще: не нужно "колдовать" с таймерами и самодельными генераторами/приемниками событий.

 

зы. В проектах с одной/двумя кнопками все реализую значительно проще, но аналогично - периодический опрос и сравнение двух состояний: предыдущего и текущего.

Я не запрещал, но понимаю, что на плюсах удобнее - приведите свой пример pls!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

далее в зависимости от проекта реализовывал систему подписки на различные события, если в двух словах, то речь про колбэки и их продвинутые аналоги.

Модули, которым нужно ждать события от клавиатуры, "подписываются" на нужные события и кнопки, "обращаясь" к модулю клавиатуры

....

То есть у Вас модули в runtime подписываются/отписываются от событий клавиатуры ?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я не запрещал, но понимаю, что на плюсах удобнее - приведите свой пример pls!

Честно говоря, мне влом "выдерать" его из кода, чтобы было понятно, что тут происходит :laughing:

Поэтому выше я на словах довольно подробно описал сам принцип.

Имхо, так будет намного понятнее, особенно кто ни разу ничего подобного не делал.

 

Вообще, стараюсь документировать свой код визуально (использую для этого XMind). Не вдаваясь в нюансы и детали, но чтобы в целом все было все понятно сходу через энное время.

Однако, с клавиатурами пока этого не делал, пока в планах.

 

Пока копался в исходниках, нашел, что в одном из проектов делал чуть иначе: для работы с некой кнопкой нужно наследовать свой класс от шаблона Button<>,

потом реализовать пару виртуальных методов, где нужно обрабатывать реакцию на отпускание/нажатие. Если реакция, скажем, на отпускание не нужна, то можно вообще не реализовывать соотв. метод.

В моем случае функционал класса кнопки еще умеет и управлять собственной подсветкой: on/off/blink и т. п.

После этого нужно лишь "подключить" этот экземпляр класса к нужной клавиатуре (в одном проекте может быть не одна клавиатура, например, распределенная система).

То есть у Вас модули в runtime подписываются/отписываются от событий клавиатуры ?

В принципе, это возможно, но на практике мне пока не приходилось это использовать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я не запрещал, но понимаю, что на плюсах удобнее - приведите свой пример pls!

Ох уж эти местные плюсисты. Вот все могут, только показать ничего нормальное не могут.

Спрашивается на кой было в руки брать плюсы если не способен даже модульную архитектуру создать чтобы ничего не "выдирать" из кода.

 

Но я хочу показать еще один универсальный способ создания софта.

Вот модель сканирования клавиатуры в Simulink -

post-2050-1529760263_thumb.jpg

 

А вот код на C который сгенерился по этой модели

/*
* File: KeyboardScanModule.c
*
* Code generated for Simulink model 'KeyboardScanModule'.
*
* Model version                  : 1.5
* Simulink Coder version         : 8.14 (R2018a) 06-Feb-2018
* C/C++ source code generated on : Sat Jun 23 17:02:12 2018
*
* Target selection: ert.tlc
* Embedded hardware selection: ARM Compatible->ARM Cortex
* Code generation objectives:
*    1. Execution efficiency
*    2. Traceability
* Validation result: Not run
*/

#include "KeyboardScanModule.h"

/* Block signals and states (default storage) */
DW rtDW;

/* External outputs (root outports fed by signals with default storage) */
ExtY rtY;

/* Real-time model */
RT_MODEL rtM_;
RT_MODEL *const rtM = &rtM_;
static void rate_scheduler(void);

/*
*   This function updates active task flag for each subrate.
* The function is called at model base rate, hence the
* generated code self-manages all its subrates.
*/
static void rate_scheduler(void)
{
 /* Compute which subrates run during the next base time step.  Subrates
  * are an integer multiple of the base rate counter.  Therefore, the subtask
  * counter is reset when it reaches its limit (zero means run).
  */
 (rtM->Timing.TaskCounters.TID[1])++;
 if ((rtM->Timing.TaskCounters.TID[1]) > 2) {/* Sample time: [3.0s, 0.0s] */
   rtM->Timing.TaskCounters.TID[1] = 0;
 }
}

/* Model step function */
void KeyboardScanModule_step(void)
{
 int32_T uyIdx;
 int32_T currentOffset;
 int32_T nSampsAtBot;
 int32_T rtb_Add[9];
 boolean_T rtb_RelationalOperator[9];
 boolean_T rtb_TmpSignalConversionAtDelayI[9];
 boolean_T rtb_Delay[9];
 int32_T rtb_Switch[9];
 uint8_T rtb_FixPtSum1;
 boolean_T rtb_Buffer2[3];
 boolean_T rtb_Buffer1[3];
 boolean_T rtb_Buffer[3];
 int32_T i;
 int32_T rtb_Add_d;
 if (rtM->Timing.TaskCounters.TID[1] == 0) {
   for (i = 0; i < 9; i++) {
     /* Sum: '<S1>/Add' incorporates:
      *  Constant: '<S1>/Constant3'
      *  Delay: '<S1>/Delay1'
      */
     rtb_Add_d = rtDW.Delay1_DSTATE[i] + 1;

     /* RelationalOperator: '<S1>/Relational Operator' incorporates:
      *  Constant: '<S1>/Constant2'
      */
     rtb_RelationalOperator[i] = (10 > rtb_Add_d);

     /* Delay: '<S1>/Delay' */
     rtb_Delay[i] = rtDW.Delay_DSTATE[i];

     /* Sum: '<S1>/Add' */
     rtb_Add[i] = rtb_Add_d;
   }
 }

 /* Buffer: '<S1>/Buffer2' incorporates:
  *  Constant: '<S1>/Constant'
  *  MultiPortSwitch: '<S1>/Multiport Switch'
  */
 rtb_Add_d = 6;
 uyIdx = rtDW.Buffer2_inBufPtrIdx;
 if (6 - rtDW.Buffer2_inBufPtrIdx <= 1) {
   for (i = 0; i < 6 - rtDW.Buffer2_inBufPtrIdx; i++) {
     rtDW.Buffer2_CircBuf[rtDW.Buffer2_inBufPtrIdx + i] = false;
   }

   uyIdx = 0;
   rtb_Add_d = rtDW.Buffer2_inBufPtrIdx;
 }

 for (i = 0; i < rtb_Add_d - 5; i++) {
   rtDW.Buffer2_CircBuf[uyIdx + i] = false;
 }

 rtDW.Buffer2_inBufPtrIdx++;
 if (rtDW.Buffer2_inBufPtrIdx >= 6) {
   rtDW.Buffer2_inBufPtrIdx -= 6;
 }

 rtDW.Buffer2_bufferLength++;
 if (rtDW.Buffer2_bufferLength > 6) {
   rtDW.Buffer2_outBufPtrIdx = (rtDW.Buffer2_outBufPtrIdx +
     rtDW.Buffer2_bufferLength) - 6;
   if (rtDW.Buffer2_outBufPtrIdx > 6) {
     rtDW.Buffer2_outBufPtrIdx -= 6;
   }

   rtDW.Buffer2_bufferLength = 6;
 }

 if (rtM->Timing.TaskCounters.TID[1] == 0) {
   rtDW.Buffer2_bufferLength -= 3;
   if (rtDW.Buffer2_bufferLength < 0) {
     rtDW.Buffer2_outBufPtrIdx += rtDW.Buffer2_bufferLength;
     if (rtDW.Buffer2_outBufPtrIdx < 0) {
       rtDW.Buffer2_outBufPtrIdx += 6;
     }

     rtDW.Buffer2_bufferLength = 0;
   }

   uyIdx = 0;
   currentOffset = rtDW.Buffer2_outBufPtrIdx;
   if (rtDW.Buffer2_outBufPtrIdx < 0) {
     currentOffset = rtDW.Buffer2_outBufPtrIdx + 6;
   }

   nSampsAtBot = 6 - currentOffset;
   rtb_Add_d = 3;
   if (6 - currentOffset <= 3) {
     for (i = 0; i < 6 - currentOffset; i++) {
       rtb_Buffer2[i] = rtDW.Buffer2_CircBuf[currentOffset + i];
     }

     uyIdx = 6 - currentOffset;
     currentOffset = 0;
     rtb_Add_d = 3 - nSampsAtBot;
   }

   for (i = 0; i < rtb_Add_d; i++) {
     rtb_Buffer2[uyIdx + i] = rtDW.Buffer2_CircBuf[currentOffset + i];
   }

   rtDW.Buffer2_outBufPtrIdx = currentOffset + rtb_Add_d;
 }

 /* End of Buffer: '<S1>/Buffer2' */

 /* Buffer: '<S1>/Buffer1' incorporates:
  *  Constant: '<S1>/Constant'
  *  MultiPortSwitch: '<S1>/Multiport Switch2'
  */
 rtb_Add_d = 6;
 uyIdx = rtDW.Buffer1_inBufPtrIdx;
 if (6 - rtDW.Buffer1_inBufPtrIdx <= 1) {
   for (i = 0; i < 6 - rtDW.Buffer1_inBufPtrIdx; i++) {
     rtDW.Buffer1_CircBuf[rtDW.Buffer1_inBufPtrIdx + i] = false;
   }

   uyIdx = 0;
   rtb_Add_d = rtDW.Buffer1_inBufPtrIdx;
 }

 for (i = 0; i < rtb_Add_d - 5; i++) {
   rtDW.Buffer1_CircBuf[uyIdx + i] = false;
 }

 rtDW.Buffer1_inBufPtrIdx++;
 if (rtDW.Buffer1_inBufPtrIdx >= 6) {
   rtDW.Buffer1_inBufPtrIdx -= 6;
 }

 rtDW.Buffer1_bufferLength++;
 if (rtDW.Buffer1_bufferLength > 6) {
   rtDW.Buffer1_outBufPtrIdx = (rtDW.Buffer1_outBufPtrIdx +
     rtDW.Buffer1_bufferLength) - 6;
   if (rtDW.Buffer1_outBufPtrIdx > 6) {
     rtDW.Buffer1_outBufPtrIdx -= 6;
   }

   rtDW.Buffer1_bufferLength = 6;
 }

 if (rtM->Timing.TaskCounters.TID[1] == 0) {
   rtDW.Buffer1_bufferLength -= 3;
   if (rtDW.Buffer1_bufferLength < 0) {
     rtDW.Buffer1_outBufPtrIdx += rtDW.Buffer1_bufferLength;
     if (rtDW.Buffer1_outBufPtrIdx < 0) {
       rtDW.Buffer1_outBufPtrIdx += 6;
     }

     rtDW.Buffer1_bufferLength = 0;
   }

   uyIdx = 0;
   currentOffset = rtDW.Buffer1_outBufPtrIdx;
   if (rtDW.Buffer1_outBufPtrIdx < 0) {
     currentOffset = rtDW.Buffer1_outBufPtrIdx + 6;
   }

   nSampsAtBot = 6 - currentOffset;
   rtb_Add_d = 3;
   if (6 - currentOffset <= 3) {
     for (i = 0; i < 6 - currentOffset; i++) {
       rtb_Buffer1[i] = rtDW.Buffer1_CircBuf[currentOffset + i];
     }

     uyIdx = 6 - currentOffset;
     currentOffset = 0;
     rtb_Add_d = 3 - nSampsAtBot;
   }

   for (i = 0; i < rtb_Add_d; i++) {
     rtb_Buffer1[uyIdx + i] = rtDW.Buffer1_CircBuf[currentOffset + i];
   }

   rtDW.Buffer1_outBufPtrIdx = currentOffset + rtb_Add_d;
 }

 /* End of Buffer: '<S1>/Buffer1' */

 /* Buffer: '<S1>/Buffer' incorporates:
  *  Constant: '<S1>/Constant'
  *  MultiPortSwitch: '<S1>/Multiport Switch3'
  */
 rtb_Add_d = 6;
 uyIdx = rtDW.Buffer_inBufPtrIdx;
 if (6 - rtDW.Buffer_inBufPtrIdx <= 1) {
   for (i = 0; i < 6 - rtDW.Buffer_inBufPtrIdx; i++) {
     rtDW.Buffer_CircBuf[rtDW.Buffer_inBufPtrIdx + i] = false;
   }

   uyIdx = 0;
   rtb_Add_d = rtDW.Buffer_inBufPtrIdx;
 }

 for (i = 0; i < rtb_Add_d - 5; i++) {
   rtDW.Buffer_CircBuf[uyIdx + i] = false;
 }

 rtDW.Buffer_inBufPtrIdx++;
 if (rtDW.Buffer_inBufPtrIdx >= 6) {
   rtDW.Buffer_inBufPtrIdx -= 6;
 }

 rtDW.Buffer_bufferLength++;
 if (rtDW.Buffer_bufferLength > 6) {
   rtDW.Buffer_outBufPtrIdx = (rtDW.Buffer_outBufPtrIdx +
     rtDW.Buffer_bufferLength) - 6;
   if (rtDW.Buffer_outBufPtrIdx > 6) {
     rtDW.Buffer_outBufPtrIdx -= 6;
   }

   rtDW.Buffer_bufferLength = 6;
 }

 if (rtM->Timing.TaskCounters.TID[1] == 0) {
   rtDW.Buffer_bufferLength -= 3;
   if (rtDW.Buffer_bufferLength < 0) {
     rtDW.Buffer_outBufPtrIdx += rtDW.Buffer_bufferLength;
     if (rtDW.Buffer_outBufPtrIdx < 0) {
       rtDW.Buffer_outBufPtrIdx += 6;
     }

     rtDW.Buffer_bufferLength = 0;
   }

   uyIdx = 0;
   currentOffset = rtDW.Buffer_outBufPtrIdx;
   if (rtDW.Buffer_outBufPtrIdx < 0) {
     currentOffset = rtDW.Buffer_outBufPtrIdx + 6;
   }

   nSampsAtBot = 6 - currentOffset;
   rtb_Add_d = 3;
   if (6 - currentOffset <= 3) {
     for (i = 0; i < 6 - currentOffset; i++) {
       rtb_Buffer[i] = rtDW.Buffer_CircBuf[currentOffset + i];
     }

     uyIdx = 6 - currentOffset;
     currentOffset = 0;
     rtb_Add_d = 3 - nSampsAtBot;
   }

   for (i = 0; i < rtb_Add_d; i++) {
     rtb_Buffer[uyIdx + i] = rtDW.Buffer_CircBuf[currentOffset + i];
   }

   rtDW.Buffer_outBufPtrIdx = currentOffset + rtb_Add_d;

   /* SignalConversion: '<S1>/TmpSignal ConversionAtDelayInport1' */
   rtb_TmpSignalConversionAtDelayI[0] = rtb_Buffer2[0];
   rtb_TmpSignalConversionAtDelayI[3] = rtb_Buffer1[0];
   rtb_TmpSignalConversionAtDelayI[6] = rtb_Buffer[0];
   rtb_TmpSignalConversionAtDelayI[1] = rtb_Buffer2[1];
   rtb_TmpSignalConversionAtDelayI[4] = rtb_Buffer1[1];
   rtb_TmpSignalConversionAtDelayI[7] = rtb_Buffer[1];
   rtb_TmpSignalConversionAtDelayI[2] = rtb_Buffer2[2];
   rtb_TmpSignalConversionAtDelayI[5] = rtb_Buffer1[2];
   rtb_TmpSignalConversionAtDelayI[8] = rtb_Buffer[2];
   for (i = 0; i < 9; i++) {
     /* Outport: '<Root>/PressFlags' incorporates:
      *  Logic: '<S1>/Logical Operator2'
      */
     rtY.PressFlags[i] = (rtb_RelationalOperator[i] && rtb_Delay[i]);

     /* Outport: '<Root>/ReleasFlags' incorporates:
      *  Logic: '<S1>/Logical Operator3'
      *  Logic: '<S1>/Logical Operator4'
      */
     rtY.ReleasFlags[i] = (rtb_RelationalOperator[i] && (!rtb_Delay[i]));

     /* Switch: '<S1>/Switch' incorporates:
      *  Constant: '<S1>/Constant4'
      *  Logic: '<S1>/Logical Operator'
      */
     if ((boolean_T)(rtb_Delay[i] ^ rtb_TmpSignalConversionAtDelayI[i])) {
       rtb_Switch[i] = rtb_Add[i];
     } else {
       rtb_Switch[i] = 0;
     }

     /* End of Switch: '<S1>/Switch' */
   }

   for (i = 0; i < 9; i++) {
     /* Update for Delay: '<S1>/Delay1' */
     rtDW.Delay1_DSTATE[i] = rtb_Switch[i];

     /* Update for Delay: '<S1>/Delay' */
     rtDW.Delay_DSTATE[i] = rtb_TmpSignalConversionAtDelayI[i];
   }
 }

 /* End of Buffer: '<S1>/Buffer' */

 /* Sum: '<S4>/FixPt Sum1' incorporates:
  *  Constant: '<S4>/FixPt Constant'
  *  UnitDelay: '<S3>/Output'
  */
 rtb_FixPtSum1 = (uint8_T)(rtDW.Output_DSTATE + 1U);

 /* Switch: '<S5>/FixPt Switch' */
 if (rtb_FixPtSum1 > 2) {
   /* Update for UnitDelay: '<S3>/Output' incorporates:
    *  Constant: '<S5>/Constant'
    */
   rtDW.Output_DSTATE = 0U;
 } else {
   /* Update for UnitDelay: '<S3>/Output' */
   rtDW.Output_DSTATE = rtb_FixPtSum1;
 }

 /* End of Switch: '<S5>/FixPt Switch' */
 rate_scheduler();
}

/* Model initialize function */
void KeyboardScanModule_initialize(void)
{
 {
   int32_T i;

   /* InitializeConditions for Delay: '<S1>/Delay1' */
   for (i = 0; i < 9; i++) {
     rtDW.Delay1_DSTATE[i] = 1;
   }

   /* End of InitializeConditions for Delay: '<S1>/Delay1' */

   /* InitializeConditions for Buffer: '<S1>/Buffer2' */
   rtDW.Buffer2_inBufPtrIdx = 3;
   rtDW.Buffer2_bufferLength = 3;

   /* InitializeConditions for Buffer: '<S1>/Buffer1' */
   rtDW.Buffer1_inBufPtrIdx = 3;
   rtDW.Buffer1_bufferLength = 3;

   /* InitializeConditions for Buffer: '<S1>/Buffer' */
   rtDW.Buffer_inBufPtrIdx = 3;
   rtDW.Buffer_bufferLength = 3;
 }
}

/*
* File trailer for generated code.
*
* [EOF]
*/

Тут важно то, что в алгоритме сколько кнопок столько и счетчиков для антидребезга.

B такая генерация спасает от рутины громоздить огромное количество счетчиков и создания длинный битовых масок.

 

Предупреждение. Файл имеет зависимости. Типы и функция main объявлены в других файлах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

B такая генерация спасает от рутины громоздить огромное количество счетчиков и создания длинный битовых масок.

Отличный пример "героизма": сначала создать проблему на пустом месте, а потом с ней героически бороться B)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Отличный пример "героизма": сначала создать проблему на пустом месте, а потом с ней героически бороться B)

Возьмем тон чуть конструктивней. :biggrin:

 

"Героизм" - это про счетчик на каждую кнопку?

Тогда жду альтернативы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возьмем тон чуть конструктивней

Другой разговор!

 

"Героизм" - это про счетчик на каждую кнопку?

Полагаю, что именно с этим вы и пытаетесь "бороться".

 

Но в моем решении таймер всего один, да и тот используется в виде соотв. сервиса RTOS.

Число кнопок, их принцип работы, размещение и т. п. никакого значения не имеют.

Именно так выглядит модульное построение проекта - зависимости минимизированы и предельно абстрактны.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Другой разговор!

 

 

Полагаю, что именно с этим вы и пытаетесь "бороться".

 

Но в моем решении таймер всего один, да и тот используется в виде соотв. сервиса RTOS. Если RTOS нет, то нужен всего лишь один аппаратный таймер.

Число кнопок, их принцип работы, размещение и т. п. никакого значения не имеют.

Именно так выглядит модульное построение проекта - зависимости минимизированы и предельно абстрактны.

Таймер то со счетчиком не путайте.

Я прекрасно знаю как вы используете таймер.

В вашем случае все так же надо хранить метки времени для каждой кнопки.

И все также делать каскад сравнений. Метод ничего не упрощающий и не экономящий. Плюсы тут ни к селу ни к городу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Таймер то со счетчиком не путайте.

Я прекрасно знаю как вы используете таймер.

Сильно сомневаюсь, что вы поняли мою реализацию.

Однако, распишите, как вы это поняли?

 

В вашем случае все так же надо хранить метки времени для каждой кнопки.

Какие еще "временные метки"???

Перечитайте мой первый пост в этой теме.

Ведь очень простое и очевидное решение. Я не сам его придумал, а как обычно - подсмотрел у более опытных комрадов.

 

И все также делать каскад сравнений. Метод ничего не упрощающий.

Да нут тут никаких "каскадов сравнений" (где вы берете такие архаичные термины? )

Есть один-два банальных цикла для сравнения двух "слепков" состояния кнопок - текущее и прежнее.

В целом все очень компактно и просто. Именно так, как я описал в первых постах.

Но конкретная реализация сильно зависит от программиста и его видения "проблемы".

 

Плюсы тут ни к селу ни к городу.
Да спрячьте вы уже свой "баян" или хотя бы разучите новые мотивы! ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какие еще "временные метки"???

Перечитайте мой первый пост в этой теме.

Ведь очень простое и очевидное решение. Я не сам его придумал, а как обычно - подсмотрел у более опытных комрадов.

Че...? 50 мс?

Да не смешите. Скажите это геймерам которые за миллисекунды трясутся на своей клавиатуре.

Не, с такими упрощениями мне не интересно.

Факт только в том, что я свой алгоритм сделал и выложил элементарно, а вы свой даже частями показать не можете.

Он мне конечно не интересен, но мы же меряемся за принцип. :smile3009:

 

Кста MATLAB может и на C++ сгенерить исходники, и под разные процессоры, и под RTOS и без RTOS.

Т.е. показанная модель реально универсальна.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Че...? 50 мс? Да не смешите. Скажите это геймерам которые за миллисекунды трясутся на своей клавиатуре.

Вы точно остались где-то в 90-х и пишите на паскале в DOSе. :biggrin:

 

Для геймеров можно поставить 10мс, 1мс, 100мкс. Это - не проблема. Но мои проекты рассчитаны на обычных рядовых юзеров.

А такой юзер не отличит реакции кнопки 50 мс от 100 мс. Можете сами убедиться.

 

Не, с такими упрощениями мне не интересно.

Ну, разумеется! Ведь ваш конек - создавать из воздуха проблемы и героически с ними бороться :lol:

 

Факт только в том, что я свой алгоритм сделал и выложил элементарно, а вы свой даже частями показать не можете.

Ваш код - практически нечитаем, крайне запутан и слишком сложен в реализации и необходимости применения сложных инструментариев (MATLAB) на ровном месте.

Алгоритм, который я предложил, - прекрасно читаем (написан по-русски), просто и поэтому легко реализуем на любом языке практически любым программистом,

Продолжать?

 

но мы же меряемся за принцип. :smile3009:
Говорите лучше за себя.

 

Кста MATLAB может и на C++ сгенерить исходники, и под разные процессоры, и под RTOS и без RTOS.

Вы молодец - освоили MATLAB: теперь умеете "отрезать тонкие веточки" "промышленной бензопилой". Подравляю! :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Но я хочу показать еще один универсальный способ создания софта.

...

Но это же тихий ужас !

P.S. Но это личное дело конечно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но это же тихий ужас !
Ну почему же? Стильно, модно, молодежно. Следующим этапом будем искать кнопки с переключающими контактам, потому что только такие есть в модели.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...