Easyelectronics.ru

Электроника для всех
Текущее время: 18 ноя 2018, 07:01

Часовой пояс: UTC + 5 часов



    • JLCPCB - Прототипы 10 PCBs всего за 2$ (100*100mm, 2-layer)
    • Как мы делаем платы, смотрите на YouTube
    • Крупнейшая китайская фабрика прототипов. 300000+ заказчиков и 10000+ заказов в день!
    • LCSC - Крупнейший китайский онлайн магазин комплектующих.

Начать новую тему Ответить на тему  [ Сообщений: 64 ]  На страницу 1, 2, 3  След.
Автор Сообщение
 Заголовок сообщения: Discoduino
СообщениеДобавлено: 21 янв 2018, 05:44 
Старожил

Зарегистрирован: 19 фев 2015, 17:37
Сообщения: 1200
Откуда: void
Немного мыслей в качестве предисловия. Отношение к проекту Arduino в нашем сообществе всегда было неоднозначным, подчас даже диаметрально противоположным: кто-то восхвалял простоту и доступность Arduino для всех желающих причаститься к программированию микроконтроллеров, кто-то осуждал её за дырявые абстракции, за множество людей, которые умудряются что-то делать не зная даже таких базовых понятий как «меандр» (сам был свидетелем). Для меня лично неоспоримым плюсом всегда был пример Arduino как грамотного, логичного подхода к решению существующей проблемы: как научить людей программировать микроконтроллеры, создавать встроенные системы базового уровня без предварительных курсов на сотни часов по изучению структуры контроллеров, ассемблера и языка Си. По-моему это здорово вдохновляет, когда результат можно получить буквально через несколько часов и пары десятков строк кода. Да, это никогда не станет промышленным решением (и тех, кто предлагает производственные решения сейчас на базе Arduino я никогда не пойму), но в своей (образовательной) нише это замечательное устройство, в первую очередь, потому что работает. А раз работает, - то не трогай.

Проекту Arduino на данный момент больше десяти лет и за это время многое изменилось. Сильно возросли ожидания людей, требования к человеко-машинному интерфейсу взаимодействия с устройством. Если раньше монохромные дисплеи с разрешением 128 на 64 точки казались в порядке вещей, то теперь многие привыкли к сенсорным экранам смартфонов и планшетов. Не могу их винить - это действительно удобней и наглядней. Кроме того, существенно выросли мощности микроконтроллеров. На смену 8-битной архитектуре AVR с потолком тактовой частоты в 20 МГц пришли 32-битные ARMы с частотой в 100 и более МГц. В первую очередь имею ввиду, конечно, семейство STM32. Максимально доступная flash память программ выросла с 32 Кбайт до 1 Мбайта (и это не предел). Появилась возможность организовать работу с графикой соответствующего качества.

С другой стороны, огромное сообщество людей за это же время привыкло работать с периферией микроконтроллеров через средства, предоставляемые библиотеками Arduino. Функции digitalWrite() и Serial.begin() стали де-факто стандартом в этой среде. Да, многие справедливо укажут, что такие вещи гораздо медленнее записи нужного значения в регистр, типа UCSR0B = (1 << RXEN0) | (1 << TXEN0) . Но, когда речь идет не о быстродействии, а о доступности и простоте использования, а в образовательной и DIY среде это именно так и есть, быстродействие может отойти на второй план. В конце - концов, никто не отнимает у людей возможность в дальнейшем писать код на том уровне, какой им кажется более предпочтительным, предварительно разобравшись более подробно во внутреннем устройстве. Да, этой возможностью воспользуется от силой десять процентов (или менее), но в Open Source проектах она есть, это главное.

К чему я все это веду. Попалась мне в руки платка от STM32 с названием F469 Dicovery. И те мысли, которые крутились где-то в голове на заднем фоне, внезапно обрели реальное воплощение. Вот то, что действительно может стать следующим шагом в этом направлении. Большой, качественный экран. Высокое быстродействие при относительно скромном энергопотреблении (F7 серия в этом плане гораздо хуже). Широкие возможности. Разъем для Arduino плат расширения. Но все же, чего-то ей не хватает, раз она не стала популярной? Мне трудно сформулировать, почему люди до сих пор предпочитают городить вещи в виде слабого AVR микроконтроллера в связке с внешним контроллером графического экрана по медленному последовательному интерфейсу. Им приходится мириться с низкой частотой обновления картинки на дисплее и выкраивать место для графики за счет кода программы. Или, второй вариант, использовать дорогие и проприетарные дисплеи Nextion на которых куча всего лишнего.

Изображение

Основными причинами низкой популярности и слабой известности я вижу три вещи. Во-первых, это STM32, а с ARMом у народа гораздо меньше понимания, чем с AVR. Во-вторых, существующие HAL библиотеки не представляют такой простоты использования, как Arduino. В-третьих, высокоуровневых библиотек для графического интерфейса пользователя нет вообще, так что тут даже и подступиться неоткуда. Исходя из всего вышеизложенного мне и пришла в голову идея портировать для народа библиотеки Arduino для платы F469 Disco и дополнительно добавить средства для работы с экраном (создание базовых пользовательских виджетов и т. д.). Я надеюсь, такая платформа будет полезна сообществу и станет основой для новых интересных проектов.

Буду рад услышать ваши комментарии, поддержку и ответить на возникающие вопросы. В общем, приглашаю к обсуждению. ;)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 05:52 
Старожил

Зарегистрирован: 19 фев 2015, 17:37
Сообщения: 1200
Откуда: void
Этап первый (обзор кода).

Первыми на очереди портирования функциональности Arduino стали конечно функции pinMode и digitalWrite. Вообще говоря, мне не понятно, почему при объектно-ориентированном подходе в среде Arduino для этих нужд были выбраны именно функции, а не методы соответствующих классов, что лучше бы укладывалось в общую канву. Может быть, из расчета быстродействия (хотя сомнительно). Но, тем не менее, нужно работать с чем есть. Начнем с pinMode.

Как известно, в HAL библиотеках для конфигурации вывода используется определенная структура, облегчающая настройку параметров. Первым (наивным) порывом было использовать оператор switch, который бы заполнял поля структуры в соответствии с входными параметрами вывода (в системе отсчета Arduino) и нужным режимом работы (вход/выход/с подтяжкой). Но уже со следующей мыслью пришлось решительно отказаться от такого подхода, ведь итоговый оператор switch для всех 13 контактов (и еще дополнительных, о чем ниже) вышел бы поистине гигантским по объему. Это плохой код, который трудно читать и сопровождать, а мы все-таки боремся за чистоту и качество исходного кода. Поэтому я решил проверить, как же решили эту проблему ребята из Arduino. Раньше я глубоко их библиотеки не копал, ограничиваясь документацией (кстати, качественной) на сайте, но теперь уже было интересно посмотреть, что там внутри. Так как подобного подробного разбора я нигде не нашел, решил поделиться с общественностью здесь, ибо то, что я увидел, оказалось не так и тривиально. Во всяком случае, для меня (уровень владения AVR средний). Должен оговорится, что все сказанное справедливо для версии Arduino 1.8.5 и может отличаться от других версий.

Итак, объявление функции pinMode нашлось здесь: «Contents/Java/hardware/arduino/avr/cores/arduino/Arduino.h». Что в имени пути делает «Java» Я НЕ ЗНАЮ И ДАЖЕ НЕ ИМЕЮ ПОНЯТИЯ. Это сильно сбивало меня с толку, пока я искал исходные файлы в многочисленных подкаталогах. Однако второго файла «Arduino.c» в каталоге не нашлось, поэтому поиски определения pinMode продолжились. В итоге определения нашлись рядом, в файлике «wiring_digital.c». Вот код:

Код:
void pinMode(uint8_t pin, uint8_t mode)
{
   uint8_t bit = digitalPinToBitMask(pin);
   uint8_t port = digitalPinToPort(pin);
   volatile uint8_t *reg, *out;

   if (port == NOT_A_PIN) return;

   // JWS: can I let the optimizer do this?
   reg = portModeRegister(port);
   out = portOutputRegister(port);

   if (mode == INPUT) {
      uint8_t oldSREG = SREG;
                cli();
      *reg &= ~bit;
      *out &= ~bit;
      SREG = oldSREG;
   } else if (mode == INPUT_PULLUP) {
      uint8_t oldSREG = SREG;
                cli();
      *reg &= ~bit;
      *out |= bit;
      SREG = oldSREG;
   } else {
      uint8_t oldSREG = SREG;
                cli();
      *reg |= bit;
      SREG = oldSREG;
   }
}


Как видно, процесс преобразования номера вывода из принятого в Arduino к номеру в представлении микроконтроллера облегчают две функции: digitalPinToBitMask и digitalPinToPort. Весь код далее - просто настройка в соответствии с режимом. Вроде бы все очевидно, но только на первый взгляд. Попытаемся найти для них код. Однако это оказывается вовсе не функции, а макросы (снова файл «Arduino.h»).

Код:
// Get the bit location within the hardware port of the given virtual pin.
// This comes from the pins_*.c file for the active board configuration.
//
// These perform slightly better as macros compared to inline functions
//
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
#define analogInPinToBit(P) (P)
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )


Окей, теперь нас интересует «что-то» (будем впредь осторожны) с именами pgm_read_byte и digital_pin_to_port_PGM. Где искать второе - более-менее понятно, в файлике «pins_*», который находится уже здесь: «Contents/Java/hardware/arduino/avr/variants/standard» и называется «pins_arduino.h». Это массив с номерами портов, что уже ближе к «железному» представлению микроконтроллера.

Код:
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
   PD, /* 0 */
   PD,
   PD,
   PD,
   PD,
   PD,
   PD,
   PD,
   PB, /* 8 */
   PB,
   PB,
   PB,
   PB,
   PB,
   PC, /* 14 */
   PC,
   PC,
   PC,
   PC,
   PC,
};


Таким образом, номер вывода задает смещение относительно начала массива, по которому находится значение соответствующего порта. Это гораздо быстрее вызова функции. Почему здесь не используется индексация самого массива, вроде бы не совсем понятно, но это проясняется недостающей частью выражения: pgm_read_byte. Название недвусмысленно отсылает нас к библиотеке «pgmspace.h», которая расположена по адресу «Contents/Java/hardware/tools/avr/avr/include/avr/». Тут все обильно скрыто наслоенными макросами (строка #1055, далее строка #645, #612 и строка #440):

Код:
#define __LPM_enhanced__(addr)  \
(__extension__({                \
    uint16_t __addr16 = (uint16_t)(addr); \
    uint8_t __result;           \
    __asm__ __volatile__        \
    (                           \
        "lpm %0, Z" "\n\t"      \
        : "=r" (__result)       \
        : "z" (__addr16)        \
    );                          \
    __result;                   \
}))


Итого этой функции нужен адрес (а не элемент массива!), по которому она ищет значение в памяти с помощью инструкции LPM. Честно говоря, детали этого кода от меня ускользают, поэтому если кто-то разберет его подробно, буду признателен. Но основное здесь ясно - массив расположен во flash памяти, а для доступна к ней используется ассемблерная вставка в коде на Си. Как видим, код оптимизирован достаточно тщательно.

Код:
if (port == NOT_A_PIN) return;


А вот дальше в коде есть ошибка! Значение переменной port сравнивается с определением NOT_A_PIN, которое, очевидно, справедливо для вывода, но не для порта. Почему же все работает? Да у них значения одинаковые (строка 185):

Код:
#define NOT_A_PIN 0
#define NOT_A_PORT 0


Мелочь, а осадочек остается. Смотрим далее, указатели reg и out инициализируются адресами соответствующих регистров. Метод определения используется аналогичный разобранному выше, поэтому я не вижу смысла на нем останавливаться подробно во второй раз. В конце кода функции происходят стандартные манипуляции с выставлением соответствующих битов в регистрах, тут ничего нового.

Код:
void digitalWrite(uint8_t pin, uint8_t val)
{
   uint8_t timer = digitalPinToTimer(pin);
   uint8_t bit = digitalPinToBitMask(pin);
   uint8_t port = digitalPinToPort(pin);
   volatile uint8_t *out;

   if (port == NOT_A_PIN) return;

   // If the pin that support PWM output, we need to turn it off
   // before doing a digital write.
   if (timer != NOT_ON_TIMER) turnOffPWM(timer);

   out = portOutputRegister(port);

   uint8_t oldSREG = SREG;
   cli();

   if (val == LOW) {
      *out &= ~bit;
   } else {
      *out |= bit;
   }

   SREG = oldSREG;
}

int digitalRead(uint8_t pin)
{
   uint8_t timer = digitalPinToTimer(pin);
   uint8_t bit = digitalPinToBitMask(pin);
   uint8_t port = digitalPinToPort(pin);

   if (port == NOT_A_PIN) return LOW;

   // If the pin that support PWM output, we need to turn it off
   // before getting a digital reading.
   if (timer != NOT_ON_TIMER) turnOffPWM(timer);

   if (*portInputRegister(port) & bit) return HIGH;
   return LOW;
}


Прежде чем приступать к написанию кода для STM, разберем еще функцию digitalWrite и digitalRead. Тут снова встречается сравнение с NOT_A_PIN и это заставило меня задуматься. Один раз - случайность, два - совпадение, три уже закономерность. Хотя разумного объяснения я найти так и не смог. Более того, что вызывает дополнительные вопросы, так это зачем сравнивать полученное в таблице поиска значение порта, если можно проверять внутри функции полученное значение вывода. Если задан некорректный вывод, то даже поиск по таблицам не стоит проводить и сэкономить на этом вычисления. Сплошные загадки.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 05:55 
Старожил

Зарегистрирован: 19 фев 2015, 17:37
Сообщения: 1200
Откуда: void
Этап первый (написание кода).

Сам процесс написания кода был достаточно простым, разве что возник небольшой затык с включением тактирования на портах общего назначения. Сперва я вообще забыл об этом и был немало удивлен когда часть выводов работала, а часть нет (некоторые должно быть были включены для работы другой периферии). Хотелось оптимизировать быстродействие кода, но сделать это было не так просто, как выполнить поиск по таблицам, нужно было еще вызвать функцию. Какое-то время я даже думал вынести включение тактирования в отдельную функцию инициализации и мириться с паразитным энергопотреблением неактивных блоков микроконтроллера (какие-то микроамперы, ей-богу). К счастью, тут на форуме Финский поделился со мной неочевидным синтаксисом оператора switch, это помогло написать довольно компактный код, учитывая общее количество контактов. Вообще, я надеялся обойтись этого оператора, но видно не судьба. Также я учел нюансы и проверяю корректность заданного контакта еще до поиска значений по таблицам, чтобы не выполнять лишнюю работу.

Код:
void pinMode(uint8_t pin, uint8_t mode)
{
    GPIO_InitTypeDef newPin;
   
    /* Do  nothing in case of wrong pin */
    if (pin >= PIN_TOTAL) return;
   
    /* Enable clock on pin's port */
    switch(pin)
    {
        case PIN3: case PIN5: case PIN6: case PIN9:
            __HAL_RCC_GPIOA_CLK_ENABLE();
            break;
        case PIN11: case PIN12: case PIN14: case PIN15:
            __HAL_RCC_GPIOB_CLK_ENABLE();
            break;
        case PIN13: case PIN17: case PIN18:
            __HAL_RCC_GPIOD_CLK_ENABLE();
            break;
        case PIN0: case PIN1: case PIN2: case PIN4: case PIN7:
        case PIN8: case PIN19:
            __HAL_RCC_GPIOG_CLK_ENABLE();
            break;
        case PIN10:
            __HAL_RCC_GPIOH_CLK_ENABLE();
            break;
        case PIN16:
            __HAL_RCC_GPIOK_CLK_ENABLE();
            break;
    }
   
    /* Fill structure */
    newPin.Pin = digital_pin_to_bitmask[pin];
    newPin.Mode = mode_to_mode[mode];
    newPin.Pull = mode_to_pull[mode];
    newPin.Speed = GPIO_SPEED_FREQ_LOW;
   
    HAL_GPIO_Init((GPIO_TypeDef *) digital_pin_to_port[pin], &newPin);
}

void digitalWrite(uint8_t pin, uint8_t value)
{
    /* Do  nothing in case of wrong pin */
    if (pin >= PIN_TOTAL) return;
   
    HAL_GPIO_WritePin((GPIO_TypeDef *) digital_pin_to_port[pin], \
    digital_pin_to_bitmask[pin], value_to_state[value]);
}

int digitalRead(uint8_t pin)
{
    /* Do  nothing in case of wrong pin */
    if (pin >= PIN_TOTAL) return LOW;
   
    return HAL_GPIO_ReadPin((GPIO_TypeDef *) digital_pin_to_port[pin], \
    digital_pin_to_bitmask[pin]);
}


Код:
/* Look-up tables */
static const GPIO_TypeDef* digital_pin_to_port[] =
{
    /* Arduino pins */
    GPIOG, /* Pin 0 */
    GPIOG,
    GPIOG,
    GPIOA,
    GPIOG,
    GPIOA,
    GPIOA,
    GPIOG,
    GPIOG, /* Pin 8 */
    GPIOA,
    GPIOH,
    GPIOB,
    GPIOB,
    GPIOD, /* Pin 13, LED */
    GPIOB,
    GPIOB, /* Pin 15 */
    /* Additional pins */
    GPIOK, /* Pin 16, LED */
    GPIOD, /* Pin 17, LED */
    GPIOD, /* Pin 18, LED */
    GPIOG  /* Pin 19, LED */
};

static const uint32_t digital_pin_to_bitmask[] =
{
    /* Arduino pins */
    GPIO_PIN_9,  /* Pin 0 */
    GPIO_PIN_14,
    GPIO_PIN_13,
    GPIO_PIN_1,
    GPIO_PIN_12,
    GPIO_PIN_2,
    GPIO_PIN_6,
    GPIO_PIN_11,
    GPIO_PIN_10, /* Pin 8 */
    GPIO_PIN_7,
    GPIO_PIN_6,
    GPIO_PIN_15,
    GPIO_PIN_14,
    GPIO_PIN_3,  /* Pin 13, LED */
    GPIO_PIN_9,
    GPIO_PIN_8,  /* Pin 15 */
    /* Additional pins */
    GPIO_PIN_3,  /* Pin 16, LED */
    GPIO_PIN_5,  /* Pin 17, LED */
    GPIO_PIN_4,  /* Pin 18, LED */
    GPIO_PIN_6   /* Pin 19, LED */
};

static const uint32_t mode_to_pull[] =
{
    GPIO_NOPULL,
    GPIO_NOPULL,
    GPIO_PULLUP,
    GPIO_PULLDOWN
};

static const uint32_t mode_to_mode[] =
{
    GPIO_MODE_INPUT,
    GPIO_MODE_OUTPUT_PP,
    GPIO_MODE_INPUT,
    GPIO_MODE_INPUT
};

static const GPIO_PinState value_to_state[] =
{
    GPIO_PIN_SET,
    GPIO_PIN_RESET
};


Тут мало интересного.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 05:58 
Старожил

Зарегистрирован: 19 фев 2015, 17:37
Сообщения: 1200
Откуда: void
Этап второй: виджеты (кнопка)

Чтобы не было перекосов, я решил писать части проекта постепенно, уделяя внимание поочередно как аппаратной части, так и программной, как портированию функциональности Arduino, так и своим добавлениям. Поэтому на очереди было самое простое, что можно придумать вообще: обычная кнопка для сенсорного экрана. Впрочем, свои нюансы оказались и тут.

Для самого первого типа виджетов нужно было подготовить некоторую базу. Я решил разделить графическую часть на две составляющие: собственно библиотека виджетов и поддерживающие библиотеки ввода (сенсорный экран) и вывода (дисплей). Подход, на таком уровне - только объектно-ориентированный, нечего экономить такты микроконтроллера, удобство использования конечным пользователем важнее. С поддержкой оказалось все достаточно прямолинейно - нужно было только обернуть методами соответствующих классов функции из прилагаемых библиотек BSP для платы, ну и внести кое-какие изменения по мелочам. Все это послужит ресурсами для библиотеки Widgets. Хотя, стоит заметить, что существующая реализация меня не устраивает и я намерен в будущем переписать как минимум библиотеку для дисплея в полностью объектно-ориентированном подходе, взяв за основу тот же SFML, например. Но пока хватает более насущных проблем.

Код:
class Display
{           
    public:       
        Display();
       
        /* Colors */
        void setTextColor(color_t color) {BSP_LCD_SetTextColor(color);}
        void setBackColor(color_t color) {BSP_LCD_SetBackColor(color);}
        color_t getTextColor() {return BSP_LCD_GetTextColor();}
        color_t getBaackColor() {return BSP_LCD_GetBackColor();}
       
        /* Clear display */
        void clear(color_t color) {BSP_LCD_Clear(color);}
       
        /* Display strings */
        void displayStringAtLine(uint16_t line, char *str)
            {BSP_LCD_DisplayStringAtLine(line, (uint8_t *) str);}
        void clearStringAtLine(uint16_t line) {BSP_LCD_ClearStringLine(line);}
        void displayStringAt(uint16_t x, uint16_t y, char *str, text_mode_t tm = LEFT_MODE)
            {BSP_LCD_DisplayStringAt(x, y, (uint8_t *) str, tm);}
        void setFont(sFONT *fonts) {BSP_LCD_SetFont(fonts);}
       
        /* Draw basic figures */
        void fillCircle(uint16_t x, uint16_t y, uint16_t radius)
            {BSP_LCD_FillCircle(x, y, radius);}
        void fillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
            {BSP_LCD_FillRect(x, y, width, height);}
        void drawRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
            {BSP_LCD_DrawRect(x, y, width, height);}
};


Перейдем к главному. Основой всей библиотеки виджетов послужит базовый абстрактный класс Widget, который сам ничего не реализовывает (ну, почти), но зато определяет интерфейсы для потомков. Единственная операция, которую я решил сюда поместить - это метод isTouched, ибо у каждого виджета должна быть стандартная возможность определить, был ли он тыкнутым пользователем, даже если конкретный виджет представляет из себя простое текстовое описание (вдруг это будет в данный момент операция удаления). Так как каждый виджет по сути уникален (и отображается на экране в определенном месте), я сознательно запретил конструктор копирования и оператор присваивания, дабы не вводить пользователя во искушение. Вообще, это стандартная рекомендация из «Эффективного использования С++» Скотта Мэйерса. Как и чисто виртуальный деструктор для базового класса в иерархии наследования.

Код:
/* Abstract base class */
class Widget
{   
    private:
        /* Restrict acccess to copy constructor and assignment opreator */
        Widget(Widget &w);
        Widget& operator = (Widget &w);
   
    protected:
        /* Constructor */
        Widget(const uint16_t x, const uint16_t y, const uint16_t width,
            const uint16_t height, const color_t backClr = LCD_COLOR_WHITE,
            const color_t textClr = LCD_COLOR_BLACK) :
            xPos(x), yPos(y), xDim(width), yDim(height),
            backColor(backClr), textColor(textClr) {}
       
        /* Data fields */
        const uint16_t xPos;
        const uint16_t yPos;
        const uint16_t xDim;
        const uint16_t yDim;
       
        color_t backColor;
        color_t textColor;
       
        /* Monostate pattern */
        static Display LCD;
        static TouchScreen TS;
       
    public:
        /* Pure virtual destructor */
        virtual ~Widget() = 0;
        bool isTouched();
       
        /* For child classes */
        virtual void draw() {};
        virtual void update() {};
};


Кроме того, уже занявшись проектированием класса для кнопки, я добавил два подмешанных класса, HasState и GenEvent. На данном этапе мне видится логичным разделить эти две категории запросов от пользователя к объекту. Хотя в этом решении я до конца не уверен, но по идее, нас интересуют либо однократно возникающие события (типо нажатия на кнопку; отправляем одну строчку в UART) либо протяженные во времени состояния объектов (кнопка нажата, значит блокируем вращение мотора). Это тоже абстрактные классы и они всего лишь служат для определения стандартизованного интерфейса с помощью виртуальных функций. С классом GenEvent были некоторые трудности в концептуальном плане. В качестве основы тут служат две переменные, внешнее и внутреннее состояния объекта. Звучит несколько коряво и интуитивно непонятно (на мой взгляд), но ничего лучше я пока не придумал. Если внутренне состояние изменяется как только происходит любое воздействие на объект (кнопку нажали, тумблер переключили), то внешнее состояние изменяется только после поступления соответствующе запроса из другой части программы. После обработки запроса (ну, вернее, во время работы метода event) состояния синхронизируются и на все последующие запросы объект уже отвечает стандартно (до возникновения нового рассинхронизирующего события) . Если это выглядит пока туманно, то на примере кнопки, думаю, станет понятнее.

Код:
/* Abstract mix-in class */
class HasState
{
    protected:
        uint8_t internalState;
        uint8_t externalState;
   
    public:
        static const uint8_t DEFAULT = 0;
       
        HasState(uint8_t state) : internalState(state), externalState(state) {}
           
        virtual uint8_t state() = 0;
};

/* Abstract mix-in class */
class GenEvent
{
    public:
        static const uint8_t NO_EVENT = 0;
        virtual uint8_t event() = 0;
};


Имея под руками все эти составляющие, было достаточно легко написать класс Button для кнопки. Больше всего времени ушло на метод draw. Сперва я просто рисовал прямоугольник для своих тестов, затем скруглил ему края, а под конец добавил что-то вроде тени. Еще я какое-то время экспериментировал с бликами и фасками на «поверхностях» кнопки, но выходило как-то топорно, так что я от них отказался. Думаю, лучшего результата вполне можно добиться (особенно если грузить изображения из файлов с SD карты), но это потребует лишних ресурсов. Не то, чтобы их было в недостатке, но пока лучше экономить.

Код:
/* Concrete class */
class Button : public Widget, HasState, GenEvent
{   
    public:
        /* Color masks */
        static const uint32_t MASK = 0xFFDDDDDD;
        static const uint32_t FADEMASK = 0xFFBBBBBB;
       
        /* Dimensions of a button */
        static const uint16_t DIMX = 70;
        static const uint16_t DIMY = 70;
       
        /* Diffrent states (also events) */
        static const uint8_t PRESSED = 1;
        static const uint8_t RELEASED = 2;
   
        /* Initial state of Button is "RELEASED" */
        Button(const uint16_t x, const uint16_t y, const color_t clr) :
            Widget(x, y, DIMX, DIMY, clr), HasState(RELEASED)
            {draw();}
           
        virtual void draw();
        virtual void update();
       
        virtual uint8_t state();
        virtual uint8_t event();
};


Завершающим (пока) этапом я создал класс Screen, чтобы унифицировать обновление всех объектов на экране. Для этого был использован паттерн Компоновщик с некоторыми отходами от классики (описанной в книге «банды четырех»). Screen наследует классу Widget закрыто, что, во-первых, явно декларирует мнение о том, что сам экран не является виджетом и лишь использует его ресурсы, во-вторых, мешает составлять композиции из нескольких вложенных экранов (это противоречит смыслу). Кроме того, интерфейс по работе с вложенными объектами (метод add) не объявлен в базовом классе Widget. Это компромисс между прозрачностью иерархии и возможностью компилятора распознавать некорректные вызовы функций пользователем. В качестве контейнера для хранения указателей на виджеты экрана я выбрал вектор из стандартной библиотеки, просто потому что пока рано делать какие-то заключения о производительности в данном месте. Ну и мне просто лень. Кстати, примечательно, что из всех классов только Screen обновляет информацию с сенсорного экрана. Другие классы работают с уже полученными данными, хранящимися в ОЗУ. Сделано это для того, чтобы минимизировать число обращений по шине I2C. А вот с экраном работают все.

Код:
/* Composition pattern */
class Screen : private Widget
{
    private:
        static const uint16_t DIMX = 800;
        static const uint16_t DIMY = 480;
       
        std::vector<Widget*> vWidgets;
       
    public:
        Screen(color_t clr): Widget(0, 0,  DIMX, DIMY, clr)
            {LCD.clear(backColor);}
        virtual ~Screen();
        void add(Widget *w) {vWidgets.push_back(w);}
           
        virtual void update();
};


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 06:03 
Старожил

Зарегистрирован: 19 фев 2015, 17:37
Сообщения: 1200
Откуда: void
Ну и в качестве промежуточного результата, как это в итоге выглядит:

Код:
#include "xDuino.h"
#include "Screen.h"
#include "Button.h"

const int LED = 16;

int main()
{   
    /* Setup */
    Screen screen(LCD_COLOR_WHITE); /* Fill display */
    Button button(20, 20, LCD_COLOR_BLUE); /* Create a button */
    screen.add(&button); /* Add button to a screen to update it */

    pinMode(LED, OUTPUT); /* Configure pin */
    digitalWrite(LED, LOW); /* Initial value of pin */
   
    /* Main loop */
    while(1)
    {
        screen.update(); /* Update view of all widgets on screen */
       
        switch(button.event()) /* For button's events */
        {
           case Button::PRESSED: digitalWrite(LED, HIGH); break;
           case Button::RELEASED: digitalWrite(LED, LOW); break;
        }
         
           
        delay(10); /* Small delay for stability */
    }
}


Для Arduino стиля, как мне кажется, пока слишком много строк на единицу полезной работы. И если с директивами включения еще можно разобраться, вынеся в отдельный заголовочный файл, то операция взятия адреса от виджета (для включения в список обновления у экрана) может оказаться новой для любителя. В общем, я пока в поисках простого и понятного интерфейса, а на очереди АЦП и текст на экране.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 06:51 
Старожил
Аватара пользователя

Зарегистрирован: 04 окт 2011, 10:19
Сообщения: 1532
А какая цена у ней в городе Москва и на aliexpress ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 07:01 
Старожил

Зарегистрирован: 19 фев 2015, 17:37
Сообщения: 1200
Откуда: void
Около 5000 в Москве. На али не знаю. Дорого, но дисплеи Nextion стоят дороже при худшем качестве (меньше функциональность + 16 битный цвет).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 07:19 
Старожил
Аватара пользователя

Зарегистрирован: 04 окт 2011, 10:19
Сообщения: 1532
Так за ними вроде очередь и не стоит. Думаю, что за 5000 никто не будет брать. А чем не подошел STM32duino и ещё несколько пакетов для STM32 под Arduino ?
Библиотеку для дисплея можно приделать.
А еще есть mbed.org - для полных гуру программирования (Arduino это для гуру).
PlatformIO опять же.

Хотя при наличии времени можно и самому попрограммировать.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 07:31 
Старожил
Аватара пользователя

Зарегистрирован: 18 май 2013, 20:43
Сообщения: 3746
Откуда: Кемеровская область, Киселевск
Faberge, не порите чушь ей больно. Вы что от этой платы хотите получить в результате?

_________________
RADIOWOLF.RU


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 07:37 
Старожил

Зарегистрирован: 19 фев 2015, 17:37
Сообщения: 1200
Откуда: void
Что я хочу получить, я написал. Ну и да, по-программировать в свое удовольствие.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 07:40 
Старожил
Аватара пользователя

Зарегистрирован: 18 май 2013, 20:43
Сообщения: 3746
Откуда: Кемеровская область, Киселевск
Читать времени нет к сожалению, в какой IDE программируете ее? RTOS используется?

_________________
RADIOWOLF.RU


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 09:54 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 1424
Откуда: Китай, Пекин
Faberge писал(а):
«меандр»


меандр? и после этого предлагаешь воспользоваться либой для вывода графики?
Faberge писал(а):
Сильно возросли ожидания людей, требования к человеко-машинному интерфейсу взаимодействия с устройством. Если раньше монохромные дисплеи с разрешением 128 на 64 точки казались в порядке вещей, то теперь многие привыкли к сенсорным экранам смартфонов и планшетов.


я протестую. это копипаста из описания BlackBox ;)

Faberge писал(а):
Не могу их винить - это действительно удобней и наглядней.

винить???? ты правда именно так и написал? тебя досикус покусал?

Faberge писал(а):
Кроме того, существенно выросли мощности микроконтроллеров. На смену 8-битной архитектуре

Минуточнку. Где это такое произошло? Дури в восьмибитниках (я про STM8) попрежнему более чем хватает для 90% проектов. И они всегда будут дешевле 32 битных. Для тех, кому только ПОПРОБОВАТЬ цена решает.

Faberge писал(а):
К чему я все это веду. Попалась мне в руки платка от STM32 с названием F469 Dicovery. И те мысли, которые крутились где-то в голове на заднем фоне, внезапно обрели реальное воплощение. Вот то, что действительно может стать следующим шагом в этом направлении. Большой, качественный экран.

внезапно??? ну-ну... ;)

Faberge писал(а):
Мне трудно сформулировать, почему люди до сих пор предпочитают городить вещи в виде слабого AVR микроконтроллера

помогу сформулировать. цена решает.

Faberge писал(а):
в связке с внешним контроллером графического экрана по медленному последовательному интерфейсу. Им приходится мириться с низкой частотой обновления картинки на дисплее и выкраивать место для графики за счет кода программы. Или, второй вариант, использовать дорогие и проприетарные дисплеи Nextion на которых куча всего лишнего.


небыло BlackBox, вот и страдали.

Faberge писал(а):
Основными причинами низкой популярности и слабой известности я вижу три вещи. Во-первых, это STM32, а с ARMом у народа гораздо меньше понимания, чем с AVR.

в STM32 слишком много всего. глаза разбегаются и толщина документации пугает. STM8 - то, что надо

Faberge писал(а):
Во-вторых, существующие HAL библиотеки не представляют такой простоты использования, как Arduino.

именно это я попытался и сделал для STM8.

Faberge писал(а):
высокоуровневых библиотек для графического интерфейса пользователя нет вообще, так что тут даже и подступиться неоткуда.

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

Faberge писал(а):
Я надеюсь, такая платформа будет полезна сообществу и станет основой для новых интересных проектов.
Буду рад услышать ваши комментарии, поддержку и ответить на возникающие вопросы. В общем, приглашаю к обсуждению. ;)


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

интересно наблюдать какие формы обретают однажды высказанные идеи
пока не полное принятие, но пройдет немного времени...

Да, BlackBox затевался с целью дать мощный инструмент в руки практикующих, подтянуть начинающих и вовлечь тех, кто програмирует на С# или JAVA в мир микроконтроллеров.

На основе простейшего описания протокола формируется оттестрованный исходый код, в который програмисту, как при програмировании на VBA в Excel, на событие получения пакета с данными нужно вставить свою логику.

Специально для создания пользовательского интерфейса предлагается использовать Android Studio. Очень просто и доступно.

Более того в ближайших планах BlackBox, помимо генерации исходников обработки протокола, также генерация базового пользовательского интерфейса под Android и C#.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 12:28 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 2997
Откуда: КЧР, поселок Нижний Архыз
Очень хорошо, что рукожопы не лезут в "серьезные микроконтроллеры".
Пусть и дальше на устаревших 15 лет назад аврках разминаются.
К счастью, с STM32 невозможно работать, не прочитав даташита. И страдания лентяев, пытающихся напрямую из калокуба код генерировать, это подтверждают!

Не нужно никаких "абстракций": МК достаточно простые, и все решается набором сниппетов и внимательным чтением даташита, RM и errata.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 12:32 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 2997
Откуда: КЧР, поселок Нижний Архыз
cheblin писал(а):
вовлечь тех, кто програмирует на С# или JAVA в мир микроконтроллеров

Жечь их надо, а не вовлекать! Подлить побольше бензинчику, и пусть полыхают, ироды!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 12:56 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 2473
Уууу, сколько буковок...
Удивляетесь, что нету библиотек на графику? Хм. Ну, знаете ли, такая плата - не для трусов и сопляков :))) Дисплейчик 800*480, по дифф.интерфейсу. Да че там библиотэки.. Возьмите Куб - и будет вам счастье для тех, кто боится сложностей. Настраиваем ноги, настраиваем MIPI-модуль, а графику в основном рисуем с помощью DMA2D-ускорителя. Причем, это не только банальные заливки, но и в том числе bmp-декодер. Рисуется намного быстрее, чем программно. Кстати, если обращали внимание, то плата поставляется с демо-прошивкой, в которой есть небольшая демо-игрушка, и в ней есть кнопочка - Soft/ChomeArt процессинг (или как-то так называется), наглядно показывающая скорость отрисовки графики в режиме чисто софтовом и в режиме хром-арт ускорителя.
Так я так и не понял, топикстартер запустил-таки дисплей или нет? Че-то вот эта вот ардуиновская надстройка над HAL-ом - это вообще чето куда-то невтуда, однако. Лучше бы смонтировали RTOS.

....
digitalWrite? Извините, по-моему это полный атас. Я конечно не в курсе че там у Ардуины делает эта ф-ция, но по-моему, для простого дергания ножками порта гораздо лучше работает банальная до чертиков GPIOx->ODR = (uint8_t)xx или (uint16_t)xxxx, либо для отдельных ножек GPIOx->BSRR = чччч.
Лучше уж оформить это в виде макросов типа #define PINSET(PORT, PIN).
Не, ну правда же... Ув. топикстартер, вы со своей этой говнодуриной сведете быстродействие классного МК до уровня этих ваших АВР-ок на Ардуине. Серьёзно же! Посчитайте, сколько долбаных операций занимает у вас настройка каждой ножки на выход, если по-человечьи это выглядит вот так:
GPIOA->MODER |= (0x01 << (2 * 5)) | (0x01 << (2 * 6)) ; // PA5, PA6: PP OUT
Эта строчка выполнится в десятки раз быстрее, чем ваша портянка в стиле ардуины поверх HAL-а.
Вы объясните, за каким же чертом, если уж затеяли ардуино-стайл, то пихать его поверх HAL-а? Вы наслоили два одинаковых уровня и два одинаковых стиля друг на друга. Да, я понимаю, что по-другому вы не умеете. Это нынче распространено - "к черту подробности - сели и поехали, тапку в пол". А потом будут переломы и синяки.
Вы сначала вникните хотя бы в HAL, и вы поймете, что на HAL-е сделано всё то же самое, что вы пытаетесь щас наворотить на ардуино-стиле. Короче говоря, ваша работа, хоть и объемная, но не больше чем "мартышкин труд" - код жутко тормозной, тяжелый, прожорливый на память и ресурсы.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 14:38 
Старожил
Аватара пользователя

Зарегистрирован: 23 сен 2012, 20:35
Сообщения: 2474
BusMaster писал(а):
если по-человечьи это выглядит вот так:
GPIOA->MODER |= (0x01 << (2 * 5)) | (0x01 << (2 * 6)) ; // PA5, PA6: PP OUT
Эта строчка выполнится в десятки раз быстрее.

Это как угодно, но не по человечьи. Хотя со всем остальным, в принципе, согласен.

P.S. странно, что так мало упоминаний о том, что куб умеет генерить код без HAL. Думаю, для многих ситуаций это вполне адекватный компромис между эффективностью и читабельностью.
P.P.S. еще более странно, что никто не упоминает еще один большой плюс ардуины - простота ретаргетинга (сменил название платы в меню и вот код уже работает на совершенно другой плате с другим МК, часто другой архитектуры). Да, это далеко не так эффективно, но часто это и не нужно.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 14:55 
Старожил
Аватара пользователя

Зарегистрирован: 04 окт 2011, 10:19
Сообщения: 1532
Все эти дискуссии (не только эта тема) напоминают мне этот монолог
https://www.youtube.com/watch?v=NRcDGV0qQ9M


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 15:19 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 2997
Откуда: КЧР, поселок Нижний Архыз
evsi писал(а):
P.S. странно, что так мало упоминаний о том, что куб умеет генерить код без HAL. Думаю, для многих ситуаций это вполне адекватный компромис между эффективностью и читабельностью.
P.P.S. еще более странно, что никто не упоминает еще один большой плюс ардуины - простота ретаргетинга (сменил название платы в меню и вот код уже работает на совершенно другой плате с другим МК, часто другой архитектуры).

Генерируемый кубом код — это нечитаемая портянка! Вы больше времени потратите на доведение ее до ума, чем если бы написали сразу по-человечески.
А "простота ретаргетинга" абдурины выливается в уйму лишнего кода. В результате и прошивка жирнее в несколько раз, и тормозит намного круче! Наиболее оптимальный в данном случае вариант — выносить в отдельные файлы все аппаратнозависимое. Тогда при смене платформы изменения будет проще сделать. Скажем, вызываем где-то макрос REINIT_PINS(), а в аппаратнозависимом файле определяем этот макрос.
В принципе, даже абдурину можно было бы сделать по-человечески, если бы все эти жуткие жирные функции оформлялись как true inline или даже макросы с ifdef'ами под конкретную платформу. Тот же digitalWrite должен быть не функцией, а макросом.
Ну и извращения с софтовыми I2C, SPI и т.п. надо выбросить.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 16:55 
Старожил
Аватара пользователя

Зарегистрирован: 23 сен 2012, 20:35
Сообщения: 2474
Eddy_Em писал(а):
Генерируемый кубом код — это нечитаемая портянка! Вы больше времени потратите на доведение ее до ума, чем если бы написали сразу по-человечески.

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

P.S. я в курсе, какой ценой ардуина дистигает простоты ретаргетинга. Проблема в том, что противники ардуины пока не предложили адекватной альтернативы. И макросы, и вынесение чипо-зависимого кода в отдельные файлы, ни разу не похожи на альтернативу.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 16:59 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 2997
Откуда: КЧР, поселок Нижний Архыз
Не нужна никакая альтернатива! И так все отлично.
При правильной организации портирование кода вручную займет максимум 3-4 дня! По сравнению с неделями разработки с нуля это — фигня!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 17:20 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 2473
evsi писал(а):
[Это как угодно, но не по человечьи. Хотя со всем остальным, в принципе, согласен.
.

Так без проблем можно же заменить циферки на буковки и оформить в виде макроса или в виде ф-ции. Просто например для таких вещей, как SDRAM, с большим числом выводов, которые почти все, за исключением нескольких, жестко фиксированы по расположению, для таких вещей лучше один раз написать быстрый код для конкретного случая, нежели ковырять универсальные настройки. Ведь даже при ардуино-подходе текста будет немало, и даже больше. Уж не говоря о скорости исполнения. Или топикстартер опять надеется на чьи-то не-ардуино-библиотеки?

Простота ретаргетинга? Тут тоже вопрос двоякий. Вообще-то, программисту голова на то и дана, чтобы думать, а не просто менять название в заголовке. Скажете, что типа быстрее и проще? Да нет, не всегда. Для простых АВР-ок на стандартной ардуино-плате, м.б. да, но не для таких плат, как вот эта, в заголовке темы.
В пределах одной линейки то несложно заменить МК. А если из разных серий? Тут уже все равно не обойтись без документации. Например, знаете ли вы, что в F7, в отличие от F4, таймеры имеют уже по 6 каналов захвата/сравнения? Ну а как быть с тем же дисплеем на DSI, который не сможет работать на МК той же серии, но без поддержки DSI? И это не говоря о таких простых вещах, как разный набор таймеров, да и вообще, количества ног в пределах одной модели МК.

Код:
Все эти дискуссии (не только эта тема) напоминают мне этот монолог

Ну как бы не совсем так... У меня есть такая плата, да и не только такая, если честно. Так что я не так, как в монологе Жванецкого.

Топикстартер по-началу вроде как радуется производительности графики, которую он думает получить. Видимо, на ютубах насмотрелся. Грит, что типа не надо, как в АВР-ах, выделять место для графики за счет кода программы. Да только с таким ардуино-подходом он щас эту производительность быстро просадит до уровня АВР-ок.
Быстрый DSI-интерфейс дисплея - это еще ровным счетом ничего не значит! Картинка может загоняться в дисплей хоть 50 раз в секунду, но если полный кадр формируется за 100 мс, то реальная скорость графики так и останется 10 fps, что равнозначно Ардуине на АВР-ке.
Всё-таки, МК - это не универсальный процессор, и писать высокоуровневый код надо уже после ознакомления с низкоуровневой частью. Топикстартер конечно же еще даже и не подозревает о наличии видеоускорителя, да и вообще, о тонкостях работы.

Например, та же самая кнопка. Можно ее рисовать программно, "по пикселям". А как делаю например я.
Вот к примеру есть у меня красивая кнопочка, с градиентной заливкой, рамочкой, бликами, находящаяся в монохромном bmp с градациями серого - универсальная кнопочка для случая кнопочек разных цветов. Мне нужно из этих кнопочек сделать числовую клавиатуру с циферками. Что я делаю: беру видеоускоритель DMA2D, настраиваю нижний его слой на эту кнопочку, настраиваю там же закраску кнопочки цветами из таблицы индексных цветов, а второй слой ускорителя настраиваю на массив растрового шрифта, на нужную циферку, указывая так же ей нужный цвет. Указываю координаты вывода из ускорителя, как смещение в теневом буфере кадра. Ну и запускаю DMA2D. По прерыванию от него повторяю процедуру для остальных кнопочек, меняя лишь указатель на циферку и указатель на координаты вывода. Учитывая, что эта штука работает по прерыванию, то ядро переключается на другой код, пока идет рисование кнопочки. Таким образом, получаем во-первых, красивенькую кнопочку (а не топорную квадратную одноцветную), и во-вторых, красивая кнопка рисуется даже гораздо быстрее, чем простая топорная.
Далее, допустим, мне нужно вывести текст крупным шрифтом. Поступаю подобным же методом - настраиваю верхний слой DMA2D на массив данных шрифта и - всё остальное выполняет ускоритель.
Ну а уж закраска больших прямоугольных областей, рисование залитых квадратиков, и в особенности декодирование bmp - это вообще влет выполняется ускорителем, а не программным попиксельным копированием.
И еще учтите такую фишку - SDRAM быстро работает только в пакетном режиме, а пакетный режим дает только аппаратный модуль. Программные запросы - это всегда одиночные запросы, а они в несколько раз медленнее.

Вот такие вот дела. То, что ТС тешит себя мыслью "че считать такты", в конечном итоге выльется в тормознутую систему. Причем, это не миф. Я сам пробовал - заливка большого дисплея попиксельно в цикле - это жуть. Особенно когда дело имеешь с SDRAM.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 18:21 
Старожил

Зарегистрирован: 15 янв 2018, 18:52
Сообщения: 771
как только на стм32 появится порт ide ардуины (не те потуги, что есть сейчас, а полноценный) вся общага ардуинщиков перелезет на стм32. во гон то будет. термометры, часы, метеостанции :)
з.ы. надо бы самому начинать с стм32 разбираться. а то чет засиделся на аврках


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 18:34 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 1424
Откуда: Китай, Пекин
mazahakka v2.0 писал(а):
как только на стм32 появится порт ide ардуины (не те потуги, что есть сейчас, а полноценный) вся общага ардуинщиков перелезет на стм32. во гон то будет. термометры, часы, метеостанции :)
з.ы. надо бы самому начинать с стм32 разбираться. а то чет засиделся на аврках

VisualStudio значительно лучше ide ардуины. чёт не переходят.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 18:36 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 2997
Откуда: КЧР, поселок Нижний Архыз
Угу, будут абдуринщики орать, что им 128кБ для мигания светодиодом не хватает, надо брать камень с мегабайтом флеша!
=D


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Discoduino
СообщениеДобавлено: 21 янв 2018, 18:39 
Старожил

Зарегистрирован: 15 янв 2018, 18:52
Сообщения: 771
cheblin писал(а):
mazahakka v2.0 писал(а):
как только на стм32 появится порт ide ардуины (не те потуги, что есть сейчас, а полноценный) вся общага ардуинщиков перелезет на стм32. во гон то будет. термометры, часы, метеостанции :)
з.ы. надо бы самому начинать с стм32 разбираться. а то чет засиделся на аврках

VisualStudio значительно лучше ide ардуины. чёт не переходят.

имхо не такая попсовая. хайп ардуино то начался от всяких видосиков и статей от забугорных товарищей, про то как легко [s]жечь[/s] зажигать светодиоды :)


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 64 ]  На страницу 1, 2, 3  След.

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB