реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> C++ и макросы имени Аскольда Волкова., Хочу скрестить:)
AHTOXA
сообщение Jul 29 2009, 08:41
Сообщение #1


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Тема не совсем про scmRTOS, но тут много спецов по плюсамsmile.gif

Сделал такую штуку:
Код
class BasePin
{
    public:
        virtual void On() = 0;
        virtual void Off() = 0;
        virtual void Cpl() = 0;
...
};

Это базовый абстрактный класс. Нужен, чтоб можно было передавать ссылку на любую ножку куда угодно. Например, класс TDAC(spi& spiRef, BasePin& CS), конструктору передаётся ссылка на spi и ссылка на ножку чипселекта.

Дальше начинаю городить шаблоны:
Код
template<int port, int pin, char activestate = 'H'> class Pin;

template<int pin>
class Pin<1, pin>: public BasePin
{
    public:
        virtual void On() { P1OUT |= 1<<pin; }\
...
};

template<int pin>
class Pin<1, pin, 'L'>: public BasePin
{
    public:
        virtual void On(){ P1OUT &= ~(1<<pin); }
...
};


И так 5 раз (для портов 1-5). Как-то коряво...

Пробовал так:
Код
template<int port, int pin, char activestate = 'H'>
class Pin: public BasePin
{
    public:
        virtual void On() {
            if (port == 1) P1OUT |= 1<<pin;
            if (port == 2) P2OUT |= 1<<pin;
            if (port == 3) P3OUT |= 1<<pin;
            if (port == 4) P4OUT |= 1<<pin;
            if (port == 5) P5OUT |= 1<<pin;
        }
...
};


Так вроде поменьше писанины, но тоже корявенько.

Теперь внимание, вопросsmile.gif
Есть ли какая-нибудь возможность получить вот такое:
Код
template<int port, int pin, char activestate = 'H'>
class Pin: public BasePin
{
    public:
        virtual void On() {P##portOUT |= 1<<pin; }
...
};


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


ЗЫ. А работает вроде хорошо. То есть,

Код
Pin<1, 2, 'L'> PIN12;
#define PIN_12 1, 2, L
Pin<2, 3> PIN23;
#define PIN_23 2, 3, H
...
    PIN12.On();
    on(PIN_12);
    PIN23.On();
    on(PIN_23);


компилится в
Код
    1808:    e2 c2 21 00     bic.b    #4,    &0x0021  ;r2 As==10
    180c:    e2 c2 21 00     bic.b    #4,    &0x0021  ;r2 As==10
    1810:    f2 d2 29 00     bis.b    #8,    &0x0029  ;r2 As==11
    1814:    f2 d2 29 00     bis.b    #8,    &0x0029  ;r2 As==11


Накладные расходы - vtable+процедуры на каждую созданную ножку. За это я получаю возможность передавать ссылку на ножку. Я давно этого хотел.

При обращении по ссылке (в TDAC) вызовы уже из vtable, но это для меня приемлемо.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Jul 29 2009, 10:17
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



А зачем нужен параметр шаблона activestate, если он нигде не используется?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 29 2009, 10:30
Сообщение #3


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sergeeff @ Jul 29 2009, 16:17) *
А зачем нужен параметр шаблона activestate, если он нигде не используется?


Вот же он ("L"):
Код
template<int pin>
class Pin<1, pin, 'L'>: public BasePin


Он же: Pin<1, 2, 'L'> PIN12;

Суть в том, что On() переводит ногу в состояние activestate ("L" - низкий уровень, "H" - высокий). Так сделано в макросах Волкова, я к этому привык.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 29 2009, 10:50
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(AHTOXA @ Jul 29 2009, 11:41) *
Пробовал так:
Код
template<int port, int pin, char activestate = 'H'>
class Pin: public BasePin
{
    public:
        virtual void On() {
            if (port == 1) P1OUT |= 1<<pin;
            if (port == 2) P2OUT |= 1<<pin;
            if (port == 3) P3OUT |= 1<<pin;
            if (port == 4) P4OUT |= 1<<pin;
            if (port == 5) P5OUT |= 1<<pin;
        }
...
};


Так вроде поменьше писанины, но тоже корявенько.
Я делал так. это не совсем по теме, но...:
Код
#ifndef USCIA_H__
#define USCIA_H__
#include    <io.h>

#ifndef USCIB_H__
enum usci_module_t { USCI0, USCI1 };
#endif


template <usci_module_t const module>
class uscia_t
{
public:
    class usca_ctl0_t    /* USCI Ax Control Register 0 */
    {
    public:
        uint8_t operator=(uint8_t value) { module ? UCA1CTL0 = value : UCA0CTL0 = value; return value; }
        void operator|=(uint8_t value) { module ? UCA1CTL0 |= value : UCA0CTL0 |= value; }
        void operator&=(uint8_t value) { module ? UCA1CTL0 &= value : UCA0CTL0 &= value; }
        operator uint8_t() { return module ? UCA1CTL0 : UCA0CTL0; }
    } static CTL0;
...
// pins
    class txd_bit
    {
    public:
        operator uint8_t() { return module ? (1 << 6) : (1 << 4); }
    }  static TXD_BIT;

    class rxd_bit
    {
    public:
        operator uint8_t() { return module ? (1 << 7) : (1 << 5); }
    }  static RXD_BIT;
};

template <usci_module_t module>
class uart_t
{
    typedef uscia_t<module> UCA;
public:
    static INLINE inline void init(uint32_t const divider);
....
};

template <usci_module_t module>
void uart_t<module>::init(uint32_t const divider)
{
    UCA::CTL1 |= (1  * UCSWRST);
    UCA::CTL1 = 0
        |(0 * UCRXEIE)|(0 * UCBRKIE)|(0 * UCTXADDR)
        |(1 * UCSWRST)
        |(1 * UCSSEL1)|(0 * UCSSEL0)
      ;
    UCA::CTL0 = (0 * UCPEN)|(0 * UCMSB)|(0 * UC7BIT)|(0 * UCSPB)|(0 * UCMODE1)|(0 * UCMODE0)|(0 * UCSYNC);

    UCA::BR0 = (divider / 16) & 0xFF;
    UCA::BR1 = (divider / 16) >> 8;
    UCA::MCTL = ((divider - (divider / 16) * 16) * UCBRF0)
        |(0 * UCBRS0)|(1 * UCOS16);
    UCA::CTL1 &= ~(1  * UCSWRST);
    P3SEL |= UCA::RXD_BIT | UCA::TXD_BIT;
    UCA::IFG |= UCA::TXIFG;
    UCA::IE |= UCA::RXIE;
}


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 29 2009, 11:32
Сообщение #5


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Сергей Борщ @ Jul 29 2009, 16:50) *
Я делал так. это не совсем по теме, но...:


Да, это немножко другое. Выбор из пары возможных вариантов. Вы, кстати, зря избегаете виртуализации. С ней то же самое можно сделать гораздо изящнее:
Код
enum uart_num_t {UART0, UART1};

class TBaseUart
{
private:
    static const int RxSize = 32;
    static const int TxSize = 32;
protected:
    bool tx_pending;
    RingBuf<RxSize> RxBuf;
    RingBuf<TxSize> TxBuf;
    virtual void write_tx_reg(char ch) = 0;
    virtual void disable_tx_interrupt() = 0;
    virtual void enable_tx_interrupt() = 0;
public:
    TBaseUart() : RxBuf(), TxBuf(), tx_pending(false) {}
    char getch(void) { return RxBuf.get(); }
    bool keypressed(void) { return RxBuf.count(); }
//    ... весь остальной полезный фарш
};

template<uart_num_t uart_num> class TUart;

template<>
class TUart<UART0> : public TBaseUart
{
private:
    void hw_init(uint32_t baudrate);
protected:
    virtual void write_tx_reg(char ch) { TXBUF0 = ch; }
    virtual void disable_tx_interrupt() { IE1 &= ~UTXIE0; }
    virtual void enable_tx_interrupt() { IE1 |= UTXIE0; }
public:
    TUart(uint32_t baudrate) : TBaseUart() { hw_init(baudrate); }
};

template<>
class TUart<UART1> : public TBaseUart
...


В плюсе - оба UARTа имеют тип TBaseUart, весь фарш типа gets, puts, << и проч. - реализован один раз (в TBaseUart). В минусе - небольшие накладные расходы на вызов виртуальных фанкций. По моим наблюдениям они невеликиsmile.gif

ЗЫ. Пока решил проблему вот так:
Код
#define DECLARE_PORT(portN)                                                    \
template<int pin>                                                            \
class Pin<portN, pin>: public BasePin                                        \
{                                                                            \
    public:                                                                 \
        virtual void On() { P##portN##OUT |= 1<<pin; }                        \
...
};                                                                            \
                                                                            \
template<int pin>                                                            \
class Pin<portN, pin, 'L'>: public BasePin                                    \
{                                                                            \
    public:                                                                    \
        virtual void On(){ P##portN##OUT &= ~(1<<pin); }                    \
...
};                                                                            \

DECLARE_PORT(1)
DECLARE_PORT(2)
DECLARE_PORT(3)
DECLARE_PORT(4)
DECLARE_PORT(5)


Всё же без макросов пока никудаsmile.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 29 2009, 12:35
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(AHTOXA @ Jul 29 2009, 14:32) *
Да, это немножко другое. Выбор из пары возможных вариантов.
Можно и из бОльшего количества:
Код
    class dma_ctl_t    /* DMA channel x control */
    {
    public:
        uint16_t operator=(uint16_t value)
                {
                      channel == DMA0 ? DMA0CTL = value
                    : channel == DMA1 ? DMA1CTL = value
                    : DMA2CTL = value;
                    return value;
                }
Это я к тому, что тернарный оператор короче if в записи. Ну и еще его можно использовать там, где if использовать нельзя:
Код
    static uint8_t const RXIFG = module == USCI0 ? UCB0RXIFG : UCB1RXIFG;

Цитата(AHTOXA @ Jul 29 2009, 14:32) *
Вы, кстати, зря избегаете виртуализации. С ней то же самое можно сделать гораздо изящнее:
Есть такой недостаток. Буду работать над собой.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Jul 29 2009, 13:16
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



А в чем навар в объявлении

Код
template<>
class TUart<UART0> : public TBaseUart


по сравнению с
Код
class TUart0 : public TBaseUart


Вы же все равно в каждом шаблонном классе все руками прописываете?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 29 2009, 14:29
Сообщение #8


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Сергей Борщ @ Jul 29 2009, 18:35) *
Это я к тому, что тернарный оператор короче if в записи.


А, понял. Но при пяти портах уже и то и то выглядит громоздко.


Цитата(sergeeff @ Jul 29 2009, 19:16) *
А в чем навар в объявлении


Ну я урезАл пример, и перестаралсяsmile.gif Но даже в этом, минимальном примере, вариант с шаблонами будет компилироваться при наличии только одного UART, а вариант с прямым прописыванием - нет.

А если применить подход Сергея из поста номер 4, то можно обойтись всего одной реализацией на все UART-ы. Но тут опять же, при возрастании числа UART-ов изящность решения снижается.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Jul 29 2009, 21:45
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(AHTOXA @ Jul 29 2009, 17:29) *
Ну я урезАл пример, и перестаралсяsmile.gif Но даже в этом, минимальном примере, вариант с шаблонами будет компилироваться при наличии только одного UART, а вариант с прямым прописыванием - нет.


Что-то вы любезный какими-то загадками все время говорите. Вам надо какое-то псевдоизящество, или эффективная работа с периферией?

Почему не будет компилироваться вариант с прямым прописыванием? С чего-бы это?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Jul 30 2009, 04:48
Сообщение #10


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Код
virtual void On() {
            if (port == 1) P1OUT |= 1<<pin;
            if (port == 2) P2OUT |= 1<<pin;
            if (port == 3) P3OUT |= 1<<pin;
            if (port == 4) P4OUT |= 1<<pin;
            if (port == 5) P5OUT |= 1<<pin;
        }

5 ифов подряд - по-моему, коряво...
Причём, это ведь для каждой операции?

В mspgcc есть iostructures.h, там порты объявлены в виде структур.
Тогда можно просто подставить адрес нужного порта, а дальше действовать в манере
Код
#define SPI         port1

#define RST_PIN     pin2
#define DI_PIN      pin3    // DI - вход мк, выход АЦП DO
#define RDY_PIN     pin5
#define CLK_PIN     pin6
#define DO_PIN      pin7    // DO - выход со стороны мк, вход АЦП DI

#define CLR_SCLK    SPI.out.CLK_PIN = 0
#define SET_SCLK    SPI.out.CLK_PIN = 1


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 30 2009, 04:57
Сообщение #11


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sergeeff @ Jul 30 2009, 03:45) *
Что-то вы любезный какими-то загадками все время говорите. Вам надо какое-то псевдоизящество, или эффективная работа с периферией?

Почему не будет компилироваться вариант с прямым прописыванием? С чего-бы это?


Если вам что-то непонятно, просто перечитайте. Снова не поймёте - переспросите. К чему этот надрыв? smile.gif

Я же написал: "вариант с шаблонами будет компилироваться при наличии только одного UART, а вариант с прямым прописыванием - нет". Вы это отцитировали. Значит, прочитали? И не поняли? Хорошо, я переформулирую: "при наличии только одного UART" = "при отсутствии второго UART". В системе. Так яснее? Нет? Хорошо, поясню на примере.

Код
class TUart1 : public TBaseUart
{
protected:
     virtual void write_tx_reg(char ch) { TXBUF0 = ch; }
...
};

class TUart2 : public TBaseUart
{
protected:
     virtual void write_tx_reg(char ch) { TXBUF1 = ch; }
};


Если у проца нет второго UART, то на последней строчке компилятор скажет, что не знает, что такое TXBUF1.

В случае с шаблонами - не скажет, пока вы не попытаетесь создать экземпляр TUart<UART2>.

Цитата(MrYuran @ Jul 30 2009, 10:48) *
5 ифов подряд - по-моему, коряво...
Причём, это ведь для каждой операции?


Да не, это всё выкидывается компилятором, ибо сравнение константы с константой. Остаётся один bis.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Jul 30 2009, 07:02
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(AHTOXA @ Jul 30 2009, 07:57) *
Если вам что-то непонятно, просто перечитайте. Снова не поймёте - переспросите. К чему этот надрыв? smile.gif

Я же написал: "вариант с шаблонами будет компилироваться при наличии только одного UART, а вариант с прямым прописыванием - нет". Вы это отцитировали. Значит, прочитали? И не поняли? Хорошо, я переформулирую: "при наличии только одного UART" = "при отсутствии второго UART". В системе. Так яснее? Нет?


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

По поводу "при наличии только одного UART" = "при отсутствии второго UART" - это тоже пример того, что вы хотите нам сказать и что за этим вы сами подразумеваете. Четче надо свои мысли излагать.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 30 2009, 07:55
Сообщение #13


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sergeeff @ Jul 30 2009, 13:02) *
Надрыва никакого нет. Просто вы приводите в качестве примеров куски кода, в которых отсутствуют отдельные фрагменты и мы должны догадываться, что вы имели ввиду.


Ой да ладно. Тот мой пост (с кусками кода) был адресован Сергею Борщу, и я уверен, что он там всё понял. Для иллюстрации моей мысли кода там достаточно. Если вы не догадались - сочувствую.

Цитата(sergeeff @ Jul 30 2009, 13:02) *
По поводу "при наличии только одного UART" = "при отсутствии второго UART" - это тоже пример того, что вы хотите нам сказать и что за этим вы сами подразумеваете. Четче надо свои мысли излагать.


Хм. Приведён код для двух UART. Разве в этом случае фраза "наличие только одного UART" не тождественна фразе "отсутствие второго UART"? Так что верну вам упрёк - внимательнее (вдумчивее) надо читать.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Jul 30 2009, 21:27
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(AHTOXA @ Jul 30 2009, 10:55) *
Так что верну вам упрёк - внимательнее (вдумчивее) надо читать.


1. Жизненная позиция, основанная на принципе "все вокруг недоделанные идиоты, а я самый крутой", не есть правильная.
2. Вдумчивее читать то, чего не написано - это разгадывание ребусов. Дело в принципе тоже полезное, но, как мне сдается, наш форум не для этого создан.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 31 2009, 05:10
Сообщение #15


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sergeeff @ Jul 31 2009, 03:27) *
1. Жизненная позиция, основанная на принципе "все вокруг недоделанные идиоты, а я самый крутой", не есть правильная.
2. Вдумчивее читать то, чего не написано - это разгадывание ребусов. Дело в принципе тоже полезное, но, как мне сдается, наш форум не для этого создан.


Интересная беседа получаетсяsmile.gif

1. Каким образом из того, что вы лично что-то не поняли, следует вывод, что я всех считаю идиотами? И кто начал всю эту бодягу? Вы спокойно спросили про activestate, - я спокойно ответил. Вы спокойно спросили, в чём навар в использовании шаблонов по сравнению с явным прописыванием - я спокойно ответил. Вы не поняли ответа, и спокойствие исчезло из нашего диалога. Сразу я стал "любезный", стал "говорить загадками" и делать "псевдоизящество"... Не поняли - разозлились. Это, извините, ваши комплексы. Я тут не при чём.

2. Не всё, что вы не понимаете - ребус.

ЗЫ. Вы, кстати, испортили мне тему.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 17th June 2025 - 00:44
Рейтинг@Mail.ru


Страница сгенерированна за 0.01547 секунд с 7
ELECTRONIX ©2004-2016