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

Плавный переход C -> C++ под МК

1 час назад, Arlleex сказал:

Только у Вас "хитрость" - по сути все send_command имеют тип аргументов "массив" или "что-то, что можно упаковать в массив".

Так и для дисплея же любая команда - поток байтов. Наша задача - объяснить компилятору, что любую команду надо трактовать как набор N байтов с некоего начального адреса.

1 час назад, Arlleex сказал:

Но send_command(1, 2), например, - уже ошибка.

Увы, это два int. Старшие байты будут нулями. Придумал их только как массив шестнадцатиричных кодов символов (вроде исправил в сообщении, но почему-то не сохранилось):

send_command({'\x01', '\x02'});

А я все команды описываю в виде осмысленных структур и уже структуры отсылаю через 

template<typename T>
void send_command(T const & what)    { send_command(&what, sizeof(T)); }

примерно так:

Спойлер
namespace tdf8599
{
    namespace core
    {
        union instruction
        {
            struct
            {

                uint8_t Mode                        : 1;    // 0 = standby, 1 = mute/operating
                uint8_t Ch1_disable                 : 1;
                uint8_t                             : 1;
                uint8_t OSC_increase                : 1;    // 0 = Rosc - 10%, 1 = Rosc + 10%
                uint8_t Freq_hopping_enable         : 1;
                uint8_t Ch1_clip_detect_disable     : 1;    // clip detection on CLIP pin
                uint8_t Ch1_offset_monitor_disable  : 1;
                uint8_t Offset_out_disable          : 1;    // offset detection on DIAG pin

                uint8_t Mute                        : 1;    // 0 = operating, 1 = mute
                uint8_t Ch2_disable                 : 1;
                uint8_t DC_load_detection           : 1;
                uint8_t Temp_pre_warning            : 1;    // 0 = 140 deg.C, 1 = 120 deg.C
                uint8_t Thermal_pre_warning_disable : 1;    // thermal pre-warning on CLIP pin
                uint8_t Ch2_clip_detect_disable     : 1;    // clip detection on CLIP pin
                uint8_t Ch2_offset_monitor_disable  : 1;
                uint8_t Offset_protection_disable   : 1;

                uint8_t Modulation                  : 1;    // 0 = AD, 1 = BD
                uint8_t OSC_phase_shift             : 3;    // 0 = 0, 1 = 1/4pi, 2 = 1/3 pi, 3 = 1/2pi, 4 = 2/3pi, 5 = 3/4pi
                uint8_t AC_load_detection           : 1;
                uint8_t                             : 2;
                uint8_t ADS_MOD_latch               : 1;    // 0 = latch on switching start, 1 = latch immediately
            };
            uint8_t     Raw[3];
        };
....
};

bool out_amp::load(config::amplifier const volatile & settings)
{
    Control = tdf8599::core::instruction(
    {
        settings.Mode != config::amplifier::mode::STANDBY,
        false,      // Ch1_disable
        !!settings.OSC_increase,
        !!settings.Freq_hopping,
        !settings.Clip_detect_enable,
        !settings.Offset_monitor_enable,
        false,      // Offset detection on DIAG pin disable

        settings.Mode == config::amplifier::mode::MUTE,
        false,      // Ch2_disable
        !!settings.DC_load_detect,
        !!settings.Temp_pre_warning,
        !settings.Temp_pre_warn_enable,
        !settings.Clip_detect_enable,
        !settings.Offset_monitor_enable,
        !settings.Offset_protection_enable,

        !!settings.Modulation,
        0,          // OSC_phase_shift
        !!settings.AC_load_detect,
        true,       // ADS_MOD_latch
    });

    return Chip.setup(Control);
}

 

 

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


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

21 минуту назад, Сергей Борщ сказал:

А я все команды описываю в виде осмысленных структур и уже структуры отсылаю через 

template<typename T>
void send_command(T const & what)    { send_command(&what, sizeof(T)); }

Вся соль в моей этой самой буферизации транзакций, о которой я на прошлой страничке в конце написал.

Каждый дескриптор состоит из одного 32-битного слова. Но в зависимости от ключевого поля обработка этих дескрипторов будет вестись по-разному.

Например, при желании отправить большой битмап в экран, я записываю в дескриптор адрес участка памяти (ОЗУ или Flash) и размер. Ну, еще состояние ножки DC. В этом случае (например, при отправке из ОЗУ) сам буфер нужно держать какое-то время (пока не отправится). А вот команды-коротыши целиком влезают в мой дескриптор как есть: до трех байтов (в моем экране куча таких команд - одно-двухбайтных). Я посчитал, что такие байтики я могу пихнуть в дескриптор, а при декодировании дескриптора происходит их копирование в 1 32-битное слово ОЗУ (статически выделенное слово) и уже на этот адрес натравливается DMA - посылка полетела. Так удобно не только команды отправлять, но и всякие "мелкие" кракозябры на экран - например, мигающие точки, символы и т.д.

Отправка стуктурами - легко! В конце концов (вот собственно в этом и вопрос сейчас с плюсами и шаблонами) - вызовется вариант send(addr, size), он установит дескриптор в режим "SEND_FROM_FLASH" или "SEND_FROM_RAM" в зависимости от численного значения addr и заполнит size, чтобы потом DMA-контроллер считал этот адрес и размер и начал транзакцию.

 

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


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

2 hours ago, Arlleex said:

Поэтому наследования от наследования от трижды абстрактных классов - нет нет нет))

если так пугают простые наследования, то шаблоны вообще должны приводить в ужос ))

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


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

Самое смешное, что через некоторое время она станет неактуальной. Нынче год какой у нас? Кажись 2024, не так ли? А в книжечке описан стандарт, максимум, с++17. Стандарт С++11 вообще уже неактуален, эту часть можно вообще пропускать.

Хотя, оно конечно, для изучения всегда пользительно. Правда, я сейчас чаще прибегаю к помощи различных GPT.
Например, по теме вопроса вот что ИИ ответил:

Прекрасный выбор, работать с variadic шаблонами в C++17 может быть очень мощным и удобным способом обработки различного количества аргументов в шаблонных функциях и классах. Вот как можно использовать variadic шаблоны в C++17: 1. **Шаблонные функции**:

#include <iostream>

// Базовый случай для рекурсивной функции
void processArgs() {}

// Рекурсивная функция для обработки всех аргументов
template<typename T, typename... Args>
void processArgs(T first, Args... args) {
    std::cout << first << std::endl;
    processArgs(args...);
}

int main() {
    processArgs(1, "two", 3.0, '4');
    return 0;
}

 Распаковка параметров(pack expansion):

#include <iostream>

template<typename... Args>
void printAll(Args... args) {
    ((std::cout << args << " "), ...);
    std::cout << std::endl;
}

int main() {
    printAll(1, "two", 3.0, '4');
    return 0;
}

Шаблоны классов с переменным числом аргументов:

#include <iostream>

template<typename T, typename... Args>
class Tuple {
public:
    Tuple(T first, Args... rest) : head(first), tail(rest...) {}
    
    T head;
    Tuple<Args...> tail;
};

template<typename T>
class Tuple<T> {
public:
    Tuple(T first) : head(first) {}
    
    T head;
};

int main() {
    Tuple<int, std::string, double> myTuple(10, "hello", 3.14);
    std::cout << myTuple.head << std::endl;
    std::cout << myTuple.tail.head << std::endl;
    std::cout << myTuple.tail.tail.head << std::endl;
    
    return 0;
}

 

ну и так далее

Изменено пользователем EdgeAligned

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


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

12 часов назад, EdgeAligned сказал:

Например, по теме вопроса вот что ИИ ответил:

Без понимания основ тыкать чат-GPT и пытаться учиться у него довольно тупиковая стратегия) Он дергает всякого рода портянки как со стековерфлоу.

Поэтому лучше как-то по старинке - книжечку листать.

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


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

29 минут назад, Arlleex сказал:

Без понимания основ тыкать чат-GPT и пытаться учиться у него довольно тупиковая стратегия) Он дергает всякого рода портянки как со стековерфлоу.

это гугл/яндекс дергает портянки из стекоферфлоу. а гпт генерирует ответ на "знаниях", полученных из стекоферфлоу (причем со всех языков), вики, справочников, стандартов, в том числе и с книжек, подобно вашей про шаблоны. Чтоб вам получить эти знания (хотябы 1 раз прочитать, не то что получить и применить) - вам жизни не хватит. Конечно gpt3.5 "знает" всё только до 2022 и у него нет выхода в инет, gpt4o уже знает посвежее, а также может поискать за тебя в инете, если что сам не знает. Скормите в gpt4o весь свой вопрос в полный рост

Цитата

 

Хочу заиметь 2 функции: sendCommand() и sendData(). Они на 99.99% идентичны друг другу, и хотелось бы, чтобы в их телах производился вызов другой "общей" функции с правильно подсунутыми параметрами (возможно, не шаблонными).

template<args> void send(int dataCommand, args) { // тут уже надо распарсить, сколько аргументов реально, какие их типы и т.д. } template<...> void sendCommand(...) { send(0, ...); } template<...> void sendData(...) { send(1, ...); }


В конечном итоге хочу получить возможность вот такой записи

// аргументы - простые целые числа sendCommand(0x12); // должно вызваться send(0, 0x12) sendCommand(0x12, 0x34); // должно вызваться send(0, 0x12, 0x34) sendCommand(0x12, 0x34, 0x56); // должно вызваться send(0, 0x12, 0x34, 0x56) sendData(0x12, 0x34); // должно вызваться send(1, 0x12, 0x34) // аргументы - массив или строка sendCommand("hello"); // должно вызваться send(0, const char (&)[6]) u8 buf[3]; sendData(buf); // должно вызваться send(1, u8 (&)[3])


Т.е. могу вызывать перегрузку с целыми аргументами в количестве от 1 до 3, а могу запихивать прямо массив или строку - для этого передача идет по "ссылке на массив", чтобы в send() можно было взять N или sizeof(buf).

На вариативных шаблонах витиевато, не знаю - вообще возможно ли это.

 

вы будете удивлены ответу. и если он выдаст вам std::forward<Args>, скажите ему

Цитата

а std::forward() здесь обязателен? Т.е. можно ли обойтись без обращения к std вовсе?

И вы опять будете удивлены. 

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


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

В 31.05.2024 в 19:41, Arlleex сказал:

Т.е. можно ли обойтись без обращения к std вовсе?

В 31.05.2024 в 22:15, Arlleex сказал:

Было бы здорово, если можно было бы перегрузить реализации send() под 2 варианта: аргумент-массив, и аргумент-список (параметры через запятую).

если без std, то не получится определить переменное кол-во аргументов. для поддержки разного числа аргументов, нужен перегруз функции sendCommand и sendData для одного, двух и трех аргументов. Если нужно больше аргументов, то добавить соответствующие перегрузки. 

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


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

49 минут назад, juvf сказал:

если без std, то не получится определить переменное кол-во аргументов. для поддержки разного числа аргументов, нужен перегруз функции sendCommand и sendData для одного, двух и трех аргументов. Если нужно больше аргументов, то добавить соответствующие перегрузки. 

А что такого магического над C++ делает стандартная библиотека?

Насколько я понимал, что C++ и std это вещи хоть и тесно связанные, но не до уровня разрешения синтаксиса.

Ведь переменное кол-во аргументов - это фишка компилятора C++, а не библиотек. Разве не так?

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


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

Да в том то и дело, что вариативный шаблон реализован на уровне заплаток над ядром языка. Концепция существует аж со стандарта 2011 года, но так до сих пор и не реализована в адекватном инструментарии. Ядро языка исправлять уже никто не будет, поэтому улучшение инструментария только за счет дополнительных заплаток. STD и  stlкак раз представляют собой обширную коллекцию заплаток  разного рода,

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


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

В 03.06.2024 в 13:23, Arlleex сказал:

это фишка компилятора C++, а не библиотек

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

// Online IDE - Code Editor, Compiler, Interpreter

#include<stdio.h>
#include <iostream>

template<typename... Args> 
  void send(int firstByte, Args... args) 
{
  auto print = [](auto& arg) { std::cout << arg << " "; };//лямда, дла печати каждого аргумента
  
   std::cout << (firstByte == 0 ? "code0()" : "code1()") << std::endl;

  (print(args), ...);
   std::cout << std::endl;
   
}
// Обертка для sendCommand 
template<typename... Args> 
 void sendCommand(Args... args) 
{ 
	send(0, args...); 
} 

// Обертка для sendData 
template<typename... Args> 
void sendData(Args... args) 
{ 
	send(1, args...); 
}

int main() {
    // Примеры использования
    std::cout << "sendCommand(0x12) -> ";
    sendCommand(0x12);             // вызовется send(0, 0x12)
    
    std::cout << "sendCommand(0x12, 0x34) -> ";
    sendCommand(0x12, 0x34);       // вызовется send(0, 0x12, 0x34)
    
    std::cout << "sendCommand(0x12, 0x34, 0x56) -> ";
    sendCommand(0x12, 0x34, 0x56); // вызовется send(0, 0x12, 0x34, 0x56)

    std::cout << "sendData(0x12, 0x34) -> ";
    sendData(0x12, 0x34);          // вызовется send(1, 0x12, 0x34)

    // Примеры с массивами и строками
    std::cout << "sendCommand(\"hello\") -> ";
    sendCommand("hello");          // вызовется send(0, "hello")


    unsigned char buf[3] = {0x01, 0x02, 0x03};
    std::cout << "sendData(buf) -> ";
    sendData(buf);                 // вызовется send(1, buf)

    return 0;
}

Проверил тут на с++17. выхлоп

Цитата

sendCommand(0x12) -> code0()
18 
sendCommand(0x12, 0x34) -> code0()
18 52 
sendCommand(0x12, 0x34, 0x56) -> code0()
18 52 86 
sendData(0x12, 0x34) -> code1()
18 52 
sendCommand("hello")) -> code0()
hello 
sendData(buf) -> code1()

 

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


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

47 минут назад, juvf сказал:

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

Вечером буду вникать в написанное)

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


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

В 03.06.2024 в 15:55, juvf сказал:

sendData(buf) -> code1()

вот тут мне не понравилось. тут нужно докрутить. возможно нужно ещё одну send перегрузить для массивов. 

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


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

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

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

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

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

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

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

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

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

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