AHTOXA 15 29 июля, 2009 Опубликовано 29 июля, 2009 · Жалоба Тема не совсем про 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, но это для меня приемлемо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 29 июля, 2009 Опубликовано 29 июля, 2009 · Жалоба А зачем нужен параметр шаблона activestate, если он нигде не используется? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 29 июля, 2009 Опубликовано 29 июля, 2009 · Жалоба А зачем нужен параметр шаблона activestate, если он нигде не используется? Вот же он ("L"): template<int pin> class Pin<1, pin, 'L'>: public BasePin Он же: Pin<1, 2, 'L'> PIN12; Суть в том, что On() переводит ногу в состояние activestate ("L" - низкий уровень, "H" - высокий). Так сделано в макросах Волкова, я к этому привык. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 29 июля, 2009 Опубликовано 29 июля, 2009 · Жалоба Пробовал так: 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; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 29 июля, 2009 Опубликовано 29 июля, 2009 · Жалоба Я делал так. это не совсем по теме, но...: Да, это немножко другое. Выбор из пары возможных вариантов. Вы, кстати, зря избегаете виртуализации. С ней то же самое можно сделать гораздо изящнее: 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) Всё же без макросов пока никуда:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 29 июля, 2009 Опубликовано 29 июля, 2009 · Жалоба Да, это немножко другое. Выбор из пары возможных вариантов.Можно и из бОльшего количества: 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; Вы, кстати, зря избегаете виртуализации. С ней то же самое можно сделать гораздо изящнее:Есть такой недостаток. Буду работать над собой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 29 июля, 2009 Опубликовано 29 июля, 2009 · Жалоба А в чем навар в объявлении template<> class TUart<UART0> : public TBaseUart по сравнению с class TUart0 : public TBaseUart Вы же все равно в каждом шаблонном классе все руками прописываете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 29 июля, 2009 Опубликовано 29 июля, 2009 · Жалоба Это я к тому, что тернарный оператор короче if в записи. А, понял. Но при пяти портах уже и то и то выглядит громоздко. А в чем навар в объявлении Ну я урезАл пример, и перестарался:) Но даже в этом, минимальном примере, вариант с шаблонами будет компилироваться при наличии только одного UART, а вариант с прямым прописыванием - нет. А если применить подход Сергея из поста номер 4, то можно обойтись всего одной реализацией на все UART-ы. Но тут опять же, при возрастании числа UART-ов изящность решения снижается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 29 июля, 2009 Опубликовано 29 июля, 2009 · Жалоба Ну я урезАл пример, и перестарался:) Но даже в этом, минимальном примере, вариант с шаблонами будет компилироваться при наличии только одного UART, а вариант с прямым прописыванием - нет. Что-то вы любезный какими-то загадками все время говорите. Вам надо какое-то псевдоизящество, или эффективная работа с периферией? Почему не будет компилироваться вариант с прямым прописыванием? С чего-бы это? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 21 30 июля, 2009 Опубликовано 30 июля, 2009 · Жалоба 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 30 июля, 2009 Опубликовано 30 июля, 2009 · Жалоба Что-то вы любезный какими-то загадками все время говорите. Вам надо какое-то псевдоизящество, или эффективная работа с периферией? Почему не будет компилироваться вариант с прямым прописыванием? С чего-бы это? Если вам что-то непонятно, просто перечитайте. Снова не поймёте - переспросите. К чему этот надрыв? :) Я же написал: "вариант с шаблонами будет компилироваться при наличии только одного 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>. 5 ифов подряд - по-моему, коряво... Причём, это ведь для каждой операции? Да не, это всё выкидывается компилятором, ибо сравнение константы с константой. Остаётся один bis. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 30 июля, 2009 Опубликовано 30 июля, 2009 · Жалоба Если вам что-то непонятно, просто перечитайте. Снова не поймёте - переспросите. К чему этот надрыв? :) Я же написал: "вариант с шаблонами будет компилироваться при наличии только одного UART, а вариант с прямым прописыванием - нет". Вы это отцитировали. Значит, прочитали? И не поняли? Хорошо, я переформулирую: "при наличии только одного UART" = "при отсутствии второго UART". В системе. Так яснее? Нет? Надрыва никакого нет. Просто вы приводите в качестве примеров куски кода, в которых отсутствуют отдельные фрагменты и мы должны догадываться, что вы имели ввиду. По поводу "при наличии только одного UART" = "при отсутствии второго UART" - это тоже пример того, что вы хотите нам сказать и что за этим вы сами подразумеваете. Четче надо свои мысли излагать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 30 июля, 2009 Опубликовано 30 июля, 2009 · Жалоба Надрыва никакого нет. Просто вы приводите в качестве примеров куски кода, в которых отсутствуют отдельные фрагменты и мы должны догадываться, что вы имели ввиду. Ой да ладно. Тот мой пост (с кусками кода) был адресован Сергею Борщу, и я уверен, что он там всё понял. Для иллюстрации моей мысли кода там достаточно. Если вы не догадались - сочувствую. По поводу "при наличии только одного UART" = "при отсутствии второго UART" - это тоже пример того, что вы хотите нам сказать и что за этим вы сами подразумеваете. Четче надо свои мысли излагать. Хм. Приведён код для двух UART. Разве в этом случае фраза "наличие только одного UART" не тождественна фразе "отсутствие второго UART"? Так что верну вам упрёк - внимательнее (вдумчивее) надо читать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 30 июля, 2009 Опубликовано 30 июля, 2009 · Жалоба Так что верну вам упрёк - внимательнее (вдумчивее) надо читать. 1. Жизненная позиция, основанная на принципе "все вокруг недоделанные идиоты, а я самый крутой", не есть правильная. 2. Вдумчивее читать то, чего не написано - это разгадывание ребусов. Дело в принципе тоже полезное, но, как мне сдается, наш форум не для этого создан. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 31 июля, 2009 Опубликовано 31 июля, 2009 · Жалоба 1. Жизненная позиция, основанная на принципе "все вокруг недоделанные идиоты, а я самый крутой", не есть правильная. 2. Вдумчивее читать то, чего не написано - это разгадывание ребусов. Дело в принципе тоже полезное, но, как мне сдается, наш форум не для этого создан. Интересная беседа получается:) 1. Каким образом из того, что вы лично что-то не поняли, следует вывод, что я всех считаю идиотами? И кто начал всю эту бодягу? Вы спокойно спросили про activestate, - я спокойно ответил. Вы спокойно спросили, в чём навар в использовании шаблонов по сравнению с явным прописыванием - я спокойно ответил. Вы не поняли ответа, и спокойствие исчезло из нашего диалога. Сразу я стал "любезный", стал "говорить загадками" и делать "псевдоизящество"... Не поняли - разозлились. Это, извините, ваши комплексы. Я тут не при чём. 2. Не всё, что вы не понимаете - ребус. ЗЫ. Вы, кстати, испортили мне тему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться