|
C++ и макросы имени Аскольда Волкова., Хочу скрестить:) |
|
|
|
Jul 29 2009, 08:41
|

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

|
Тема не совсем про scmRTOS, но тут много спецов по плюсам  Сделал такую штуку: Код 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; } ... }; Так вроде поменьше писанины, но тоже корявенько. Теперь внимание, вопрос Есть ли какая-нибудь возможность получить вот такое: Код 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, но это для меня приемлемо.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 29 2009, 10:30
|

фанат дивана
     
Группа: Свой
Сообщений: 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" - высокий). Так сделано в макросах Волкова, я к этому привык.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 29 2009, 10:50
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Jul 29 2009, 11:32
|

фанат дивана
     
Группа: Свой
Сообщений: 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). В минусе - небольшие накладные расходы на вызов виртуальных фанкций. По моим наблюдениям они невелики  ЗЫ. Пока решил проблему вот так: Код #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) Всё же без макросов пока никуда
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 29 2009, 12:35
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Jul 29 2009, 13:16
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
А в чем навар в объявлении Код template<> class TUart<UART0> : public TBaseUart по сравнению с Код class TUart0 : public TBaseUart Вы же все равно в каждом шаблонном классе все руками прописываете?
|
|
|
|
|
Jul 29 2009, 14:29
|

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

|
Цитата(Сергей Борщ @ Jul 29 2009, 18:35)  Это я к тому, что тернарный оператор короче if в записи. А, понял. Но при пяти портах уже и то и то выглядит громоздко. Цитата(sergeeff @ Jul 29 2009, 19:16)  А в чем навар в объявлении Ну я урезАл пример, и перестарался  Но даже в этом, минимальном примере, вариант с шаблонами будет компилироваться при наличии только одного UART, а вариант с прямым прописыванием - нет. А если применить подход Сергея из поста номер 4, то можно обойтись всего одной реализацией на все UART-ы. Но тут опять же, при возрастании числа UART-ов изящность решения снижается.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 30 2009, 04:48
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 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 =)
|
|
|
|
|
Jul 30 2009, 04:57
|

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

|
Цитата(sergeeff @ Jul 30 2009, 03:45)  Что-то вы любезный какими-то загадками все время говорите. Вам надо какое-то псевдоизящество, или эффективная работа с периферией?
Почему не будет компилироваться вариант с прямым прописыванием? С чего-бы это? Если вам что-то непонятно, просто перечитайте. Снова не поймёте - переспросите. К чему этот надрыв?  Я же написал: " вариант с шаблонами будет компилироваться при наличии только одного 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.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 30 2009, 07:02
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(AHTOXA @ Jul 30 2009, 07:57)  Если вам что-то непонятно, просто перечитайте. Снова не поймёте - переспросите. К чему этот надрыв?  Я же написал: " вариант с шаблонами будет компилироваться при наличии только одного UART, а вариант с прямым прописыванием - нет". Вы это отцитировали. Значит, прочитали? И не поняли? Хорошо, я переформулирую: "при наличии только одного UART" = "при отсутствии второго UART". В системе. Так яснее? Нет? Надрыва никакого нет. Просто вы приводите в качестве примеров куски кода, в которых отсутствуют отдельные фрагменты и мы должны догадываться, что вы имели ввиду. По поводу "при наличии только одного UART" = "при отсутствии второго UART" - это тоже пример того, что вы хотите нам сказать и что за этим вы сами подразумеваете. Четче надо свои мысли излагать.
|
|
|
|
|
Jul 30 2009, 07:55
|

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

|
Цитата(sergeeff @ Jul 30 2009, 13:02)  Надрыва никакого нет. Просто вы приводите в качестве примеров куски кода, в которых отсутствуют отдельные фрагменты и мы должны догадываться, что вы имели ввиду. Ой да ладно. Тот мой пост (с кусками кода) был адресован Сергею Борщу, и я уверен, что он там всё понял. Для иллюстрации моей мысли кода там достаточно. Если вы не догадались - сочувствую. Цитата(sergeeff @ Jul 30 2009, 13:02)  По поводу "при наличии только одного UART" = "при отсутствии второго UART" - это тоже пример того, что вы хотите нам сказать и что за этим вы сами подразумеваете. Четче надо свои мысли излагать. Хм. Приведён код для двух UART. Разве в этом случае фраза "наличие только одного UART" не тождественна фразе "отсутствие второго UART"? Так что верну вам упрёк - внимательнее (вдумчивее) надо читать.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 31 2009, 05:10
|

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

|
Цитата(sergeeff @ Jul 31 2009, 03:27)  1. Жизненная позиция, основанная на принципе "все вокруг недоделанные идиоты, а я самый крутой", не есть правильная. 2. Вдумчивее читать то, чего не написано - это разгадывание ребусов. Дело в принципе тоже полезное, но, как мне сдается, наш форум не для этого создан. Интересная беседа получается  1. Каким образом из того, что вы лично что-то не поняли, следует вывод, что я всех считаю идиотами? И кто начал всю эту бодягу? Вы спокойно спросили про activestate, - я спокойно ответил. Вы спокойно спросили, в чём навар в использовании шаблонов по сравнению с явным прописыванием - я спокойно ответил. Вы не поняли ответа, и спокойствие исчезло из нашего диалога. Сразу я стал "любезный", стал "говорить загадками" и делать "псевдоизящество"... Не поняли - разозлились. Это, извините, ваши комплексы. Я тут не при чём. 2. Не всё, что вы не понимаете - ребус. ЗЫ. Вы, кстати, испортили мне тему.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|