|
|
  |
Библиотеки для STM32 |
|
|
|
Apr 19 2017, 13:21
|

Профессионал
    
Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045

|
Цитата Эта выгода микроскопическая и думать над этим нужно только если уже все, флеш полностью закончился. Цитата(Reflector @ Apr 19 2017, 17:28)  Ну что ж, еще раз  Есть два класса: PinX и GpioX. Первый имеет дело с одним пином, второй с портом в целом, но пишет/читает только в область ограниченную маской. Теперь подумай сколько ног используется при динамической индикации и какой класс больше для этих целей подходит  Эта выгода есть или нет? Вы пишете что всё таки эта выгода есть, но она макроскопическая. Я не оспариваю есть она или нет, я сразу написал - поправте меня. И всё же вы пишете что она есть, и что над этим нужно только если уже все, флеш полностью закончился. Я не согласен именно с тем пунктом, что над макроскопической выгодой нужно думать, когда флешь закончилась. флеши может быть ещё вагон целый... можно фоты хранить, но если использовать это в прерывании, то тут каждая "спичка" на счету. Зачем вы меня носом в PinX и GpioX? Если нет выгоды - вопрос снят!
|
|
|
|
|
Apr 19 2017, 13:35
|

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

|
Цитата(juvf @ Apr 19 2017, 16:09)  Ни фига вы не слышите... спички спички.... вам говорият - каждая спичка на счету. В контексте темы (Библиотеки для STM32) - думаю, очевидно, что универсальность библиотеки не даётся бесплатно. И пользователь библиотеки при необходимости может отойти от стиля, и использовать прямой доступ к портам и проч. Но это ведь не отменяет удобства использования библиотек и пользы от них? К тому же, вместо макросов можно написать специализированный класс, который будет столь же эффективен, но гораздо более читаем. Цитата(Reflector @ Apr 19 2017, 18:08)  Нет, у меня всего один класс и отдельно от него функция инициализации. Тогда я не видел этого кода. Я видел только вот это: Код template<uint32_t gpio, uint32_t pin, uint32_t af_> struct PinT { static auto base() { return (GPIO_TypeDef*)gpio; }
PinT() {} PinT(PinMode mode) { init(mode); } ..... static void write(bool data) { base()->BSRR = (0x10000 << pin) | (data << pin); } };
... PinA<5> redLed; // хоть глобально, код еще не генерится .... redLed.init(PinMode::PushPull_HighSpeed); redLed.set(); Цитата(Reflector @ Apr 19 2017, 18:08)  Это хорошо, но с дебагом все равно нужно что-то делать  C -O0 оно вообще не собирается. У gcc есть отладочный ключик -Og, с ним не такой большой размер выходит. Проект hello-led c -O2 занимает 1472 байта, а с -Og - 1680. Вполне.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Apr 19 2017, 13:39
|

Профессионал
    
Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045

|
Цитата(AHTOXA @ Apr 19 2017, 18:22)  В контексте темы (Библиотеки для STM32) - думаю, очевидно, что универсальность библиотеки не даётся бесплатно. И пользователь библиотеки при необходимости может отойти от стиля, и использовать прямой доступ к портам и проч. Но это ведь не отменяет удобства использования библиотек и пользы от них? К тому же, вместо макросов можно написать специализированный класс, который будет столь же эффективен, но гораздо более читаем. А я не против библиотек. я использую и спл, и хал, и калокуб и прямой доступ и классы/шаблоны. Там где удобно использовать 0x82 - я использую. Там где удобно использовать 0b0101010 - я использую. Просто я пояснил, что иногда использование прямого доступа, а также литералов x и b удобнее и даже эффективнее, чем самописные библиотеки/шаблоны. Просто есть религиозные люди, которые сало не едят 0b0101010 - не приемлют ... и начинают учить правильно жить по их вкусу. Цитата Я поделился своим опытом, показал примеры. спасибо большое.... только там куски... какие то... был бы совсем респект, если бы свои pin.рhh в полный рост в студию... и с примером... тогда точно кому-то пригодится, и вы будете рады  Цитата К тому же, вместо макросов можно написать специализированный класс, который будет столь же эффективен, но гораздо более читаем. наверно можно гипотетический пример придумать такой... но #define csOn() (GPIOA->BSRR = (1<<4)) написал за несколько секунд. отлаживать не надо, в использовании csOn(); Теперь какой можно написать класс... гораздо быстрее, который будет столь же эффективней и при этом будет ГОРАЗДО читаемый?
|
|
|
|
|
Apr 19 2017, 13:47
|
Участник

Группа: Участник
Сообщений: 48
Регистрация: 15-07-06
Пользователь №: 18 836

|
Цитата(juvf @ Apr 19 2017, 16:21)  Эта выгода есть или нет? Вы пишете что всё таки эта выгода есть, но она макроскопическая. Я не оспариваю есть она или нет, я сразу написал - поправте меня. И всё же вы пишете что она есть, и что над этим нужно только если уже все, флеш полностью закончился. Я не согласен именно с тем пунктом, что над макроскопической выгодой нужно думать, когда флешь закончилась. флеши может быть ещё вагон целый... можно фоты хранить, но если использовать это в прерывании, то тут каждая "спичка" на счету. Зачем вы меня носом в PinX и GpioX? Если нет выгоды - вопрос снят!  Имелось в виду, что выгоды нет, если пишешь в GpioX сразу столько бит, сколько нужно, или когда берешь у группы PinX pinMask, объединешь их и пишешь в BSRR. Второй способ - это нечто достаточно редко используемое, но тут уже есть выгода относительно установки значения для каждого пина по отдельности. Не помню чтобы так делал, не рекомендую этим злоупотреблять, потому и не написал функции такой подход упрощающий
|
|
|
|
|
Apr 19 2017, 14:12
|
Профессионал
    
Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882

|
Цитата(juvf @ Apr 19 2017, 17:00)  Пока что в твоём подходе использовать ООП всюду, отвергая литералы, - я не вижу смысла и удобства. У тебя в майне 3 строчки - у меня в майне 3 строчки. У тебя всё в майне понятно и прозрачно, у меня в майне всё понятно и прозрачно. Я перенесу на другую платформу - поправлю дефайны, майн не буду трогать. ты перенесешь на др платформу - так же будешь писать новый Pin.hpp, майн не изменишь. Парни вдоховлены ногодрыгом? Переход на другой камень - это помимо других ног еще и другая периферия, даже внутри одной серии. Да даже в пределах одного камня, другие ноги - другая периферия. А тут похлеще начинается: сменилась периферия->сменились каналы DMA/таймеров->сменились имена обработчиков перывания... И вперед, переписывать все имена констант.... Играйтесь светодиодами дальше.
|
|
|
|
|
Apr 19 2017, 14:18
|

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

|
Цитата(juvf @ Apr 19 2017, 18:39)  Просто я пояснил, что иногда использование прямого доступа, а также литералов x и b удобнее и даже эффективнее, чем самописные библиотеки/шаблоны. А, вон вы о чём. Я тоже считаю, что двоичные литералы не помешают. К тому же использовать их можно как в низкоуровневом коде, так и в коде более высокого уровня. Просто ещё один удобный способ представления числа. Цитата(juvf @ Apr 19 2017, 18:39)  наверно можно гипотетический пример придумать такой... но #define csOn() (GPIOA->BSRR = (1<<4))
написал за несколько секунд. отлаживать не надо, в использовании csOn(); Теперь какой можно написать класс... гораздо быстрее, который будет столь же эффективней и при этом будет ГОРАЗДО читаемый? Насчёт быстрее - вряд ли, скорее будет паритет. Насчёт удобнее - всяко. Сравните: Код #define csOn() (GPIOA->BSRR = (1<<4)) #define csOff() (GPIOA->BSRR = (1<< (4 + 16))) #define csCpl() (GPIOA->ODR ^ (1<<4)) vs Код using CS = Pin<'A', 4>; CS::On(); CS::Off(); CS::Cpl(); Второй вариант на мой взгляд удобнее в сопровождении: при необходимости поменять ножку/порт нужно исправить только одно определение. С макросами тоже можно сделать так (определить отдельно порт, отдельно ножку, и использовать это во всех макросах). Но макросы нельзя передать в качестве параметра шаблона класса.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Apr 19 2017, 14:32
|
Участник

Группа: Участник
Сообщений: 48
Регистрация: 15-07-06
Пользователь №: 18 836

|
Цитата(AHTOXA @ Apr 19 2017, 16:35)  C -O0 оно вообще не собирается. У gcc есть отладочный ключик -Og, с ним не такой большой размер выходит. Проект hello-led c -O2 занимает 1472 байта, а с -Og - 1680. Вполне. С -O0 и не компилировалось пока я компилятору не помог принудительно не задав одной из функций -O2  С -Og размер действительно меньше, только увы, отладка с ним нормально не работает. Ставишь брейкпоинт в одном месте, ее пролетает и останавливается где-то в другом.
|
|
|
|
|
Apr 19 2017, 14:43
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(juvf @ Apr 19 2017, 16:39)  спасибо большое.... только там куски... какие то... был бы совсем респект, если бы свои pin.рhh в полный рост в студию... и с примером... тогда точно кому-то пригодится, и вы будете рады  CODE //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Project: Any // Description: Pin (STM32L1xx) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once #include "stm32l1xx_rcc.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef enum { PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9, PA10, PA11, PA12, PA13, PA14, PA15, PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15, PC0, PC1, PC2, PC3, PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, PC13, PC14, PC15, PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9, PD10, PD11, PD12, PD13, PD14, PD15, PE0, PE1, PE2, PE3, PE4, PE5, PE6, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15, PF0, PF1, PF2, PF3, PF4, PF5, PF6, PF7, PF8, PF9, PF10, PF11, PF12, PF13, PF14, PF15, PH0, PH1, PH2, PH3, PH4, PH5, PH6, PH7, PH8, PH9, PH10, PH11, PH12, PH13, PH14, PH15, } PIN;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class PinBase { public: PinBase(PIN pin) { portIndex = pin / 16; pinIndex = pin % 16; pinMask = (((UNSIGNED32)1) << pinIndex);
switch (portIndex) { #ifdef GPIOA_BASE case (0): port = GPIOA; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); break; #endif #ifdef GPIOB_BASE case (1): port = GPIOB; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); break; #endif #ifdef GPIOC_BASE case (2): port = GPIOC; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); break; #endif #ifdef GPIOD_BASE case (3): port = GPIOD; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE); break; #endif #ifdef GPIOE_BASE case (4): port = GPIOE; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE); break; #endif #ifdef GPIOF_BASE case (5): port = GPIOF; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE); break; #endif #ifdef GPIOH_BASE case (6): port = GPIOH; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOH, ENABLE); break; #endif default : break; } disablePullUpAndPullDown(); }
void setAsDigitalInput() // MODER = 0 { port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x00) << (pinIndex * 2)); } void setAsDigitalOutput() // MODER = 1 { port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x01) << (pinIndex * 2)); }
typedef UNSIGNED8 AlternativeFunction; void setAsAlternative(AlternativeFunction function) // MODER = 2 { port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x02) << (pinIndex * 2)); if (pinIndex < 8) { port->AFR[0] &= ~(((UNSIGNED32)0x0F) << (pinIndex * 4)); port->AFR[0] |= (((UNSIGNED32)function & 0x0F) << (pinIndex * 4)); } else { port->AFR[1] &= ~(((UNSIGNED32)0x0F) << ((pinIndex - 8) * 4)); port->AFR[1] |= (((UNSIGNED32)function & 0x0F) << ((pinIndex - 8) * 4)); } } void setAsAnalogInput() // MODER = 3 { disablePullUpAndPullDown(); port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x03) << (pinIndex * 2)); } void setAsAnalogOutput() // MODER = 3 { disablePullUpAndPullDown(); port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x03) << (pinIndex * 2)); } void setAsPushPull() { port->OTYPER &= ~(1 << pinIndex); } // OTYPER = 0 void setAsOpenDrain() { port->OTYPER |= (1 << pinIndex); } // OTYPER = 1 void setOutputSpeed400kHz() { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x00) << (pinIndex * 2)); } // OSPEEDR = 0 void setOutputSpeed2MHz() { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x01) << (pinIndex * 2)); } // OSPEEDR = 1 void setOutputSpeed10MHz() { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x02) << (pinIndex * 2)); } // OSPEEDR = 2 void setOutputSpeed40MHz() { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x03) << (pinIndex * 2)); } // OSPEEDR = 3 void disablePullUpAndPullDown() { port->PUPDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->PUPDR |= (((UNSIGNED32)0x00) << (pinIndex * 2)); } // PUPDR = 0 void enablePullUp() { port->PUPDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->PUPDR |= (((UNSIGNED32)0x01) << (pinIndex * 2)); } // PUPDR = 1 void enablePullDown() { port->PUPDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->PUPDR |= (((UNSIGNED32)0x02) << (pinIndex * 2)); } // PUPDR = 2 inline void setToHigh() __attribute__((always_inline)) { port->BSRRL = pinMask; } inline void setToLow() __attribute__((always_inline)) { port->BSRRH = pinMask; } inline bool isHigh() __attribute__((always_inline)) { return (((port->IDR) & pinMask) != 0); } inline bool isLow() __attribute__((always_inline)) { return (((port->IDR) & pinMask) == 0); } inline void toggle() __attribute__((always_inline)) { port->ODR ^= pinMask; }
void lock() { // TODO } protected: volatile GPIO_TypeDef * port; volatile UNSIGNED8 portIndex; volatile UNSIGNED8 pinIndex; volatile UNSIGNED32 pinMask; };
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <PIN pin> class Pin : public PinBase { public: Pin() : PinBase(pin) { } };
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <PIN pin> class DigitalOutputPin : public PinBase { public: DigitalOutputPin() : PinBase(pin) { setAsDigitalOutput(); setAsPushPull(); setOutputSpeed40MHz(); } };
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <PIN pin> class LedOpenDrain : public PinBase { public: LedOpenDrain() : PinBase(pin) { setAsDigitalOutput(); setAsOpenDrain(); setOutputSpeed10MHz(); off(); }
void on() { setToLow(); } void off() { setToHigh(); } };
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <PIN pin> class DigitalInputPin : public PinBase { public: DigitalInputPin() : PinBase(pin) { setAsDigitalInput(); } };
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <PIN pin> class AnalogInputPin : public PinBase { public: AnalogInputPin() : PinBase(pin) { setAsAnalogInput(); } };
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ПримерНекоторые моменты сыроваты (в частности сохранились куски кода для SPL), но функционал полностью соответствует моим хотелкам. В процессе участия в этой теме у меня появились еще задумки как что исправить/улучшить/проверить )))
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Apr 19 2017, 14:59
|
Участник

Группа: Участник
Сообщений: 48
Регистрация: 15-07-06
Пользователь №: 18 836

|
Цитата(juvf @ Apr 19 2017, 16:39)  наверно можно гипотетический пример придумать такой... но #define csOn() (GPIOA->BSRR = (1<<4))
написал за несколько секунд. отлаживать не надо, в использовании csOn(); Теперь какой можно написать класс... гораздо быстрее, который будет столь же эффективней и при этом будет ГОРАЗДО читаемый? Здорово, но раз есть csOn(), то как минимум должен быть и csOff(), потом захочется записать битик и дополнительно придется делать проверки... А инициализация, она ведь тоже нужна? Итого сколько всего будет таких макросов для одного пина? Цитата(Forger @ Apr 19 2017, 17:43)  В процессе участия в этой теме у меня появились еще задумки как что исправить/улучшить/проверить ))) В качестве одной из таких задумок рекомендую выбросить из класса включение тактирования порта при каждой инициализации пина, заодно и от SPL избавишься
Сообщение отредактировал Reflector - Apr 19 2017, 15:04
|
|
|
|
|
Apr 19 2017, 15:07
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(Reflector @ Apr 19 2017, 17:59)  В качестве одной из таких задумок рекомендую выбросить из класса включение тактирования порта при каждой инициализации пина, заодно и от SPL избавишься  Пока что так мне удобнее - тактирование включается автоматом. Обращение к SPL заменю, как руки дойдут )) Делается это все равно лишь на этапе вызова конструктора класса пина, т. е. один раз после подачи питания. Если не используется ни одного пина из некого порта, то он и не тактируется. В таком случае не приходится искать какие порты используются, а какие нет. Раньше приходилось тактировать ВСЕ порты.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Apr 19 2017, 15:29
|
Знающий
   
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839

|
Цитата(Reflector @ Apr 19 2017, 17:59)  Здорово, но раз есть csOn(), то как минимум должен быть и csOff(), потом захочется записать битик и дополнительно придется делать проверки... А инициализация, она ведь тоже нужна? Итого сколько всего будет таких макросов для одного пина? Не могу таки понять в чем проблема - инициализация всего собирается в одном месте, там и макросы не нужны (для доступа к портам они тоже кстати не слишком нужны  ). Обсуждается какой-то конь в вакууме. По поводу переносимости, это не проблема - инициализация правится отдельно, обращение к портам отдельно.
|
|
|
|
|
Apr 19 2017, 15:31
|

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

|
Цитата(Forger @ Apr 19 2017, 19:43)  Код volatile UNSIGNED8 portIndex; volatile UNSIGNED8 pinIndex; volatile UNSIGNED32 pinMask; juvf уже спрашивал, я удваиваю его вопрос: какой смысл использовать странные UNSIGNED8/UNSIGNED32 при наличии замечательных (а главное - стандартных) типов из <stdint.h>? И второй вопрос - зачем тут volatile? Цитата(Шаманъ @ Apr 19 2017, 20:29)  Не могу таки понять в чем проблема - инициализация всего собирается в одном месте, там и макросы не нужны (для доступа к портам они тоже кстати не слишком нужны  ). Обсуждается какой-то конь в вакууме. Так ещё хуже - инициализация в одном месте, остальное в другом. Если надо поменять порт и ножку, то будет морока - править в нескольких местах. Вероятность ошибки больше. Тут не конь в вакууме. Тут на примере довольно простого класса для доступа к ножкам микроконтроллера обсуждается подход к программированию в целом. И уже продемонстрировано несколько подходов. Конечно, каждый участник считает, что его подход самый лучший, и переубедить друг друга скорее всего не удастся. Но, думаю, кое-что полезное из обсуждения можно почерпнуть.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Apr 19 2017, 15:39
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(AHTOXA @ Apr 19 2017, 18:31)  juvf уже спрашивал, я удваиваю его вопрос: какой смысл использовать странные UNSIGNED8/UNSIGNED32 при наличии замечательных (а главное - стандартных) типов из <stdint.h>? Форма написание "стандартных" типов меня не устраивает - не соответствует моей концепции именования. Поэтому в соотв. местах существуют соотв. typedef-ы в зависимости от платформы (в файле выше нет соотв. инклуда, он подключается в другом месте). Цитата И второй вопрос - зачем тут volatile? Не помню зачем их ставил. А рыться в истории svn-базы как-то нет особого желания.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Apr 19 2017, 17:41
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(AHTOXA @ Apr 19 2017, 20:27)  Мне кажется, это противоречит концепции "чистого кода" в смысле "кода, понятного для других". И вы зря взяли слово "стандартных" в кавычки - <stdint.h>/<cstdint> действительно входит в стандарт языка. Чистый код - это прежде всего код, который хорошо понятен для того, кто его пишет и сопровождает. Но, если удастся себя переучить под большинство, это будет только на пользу коду. Убежден, что "общепринятый стандарт" придуман для тех, у кого нет своих правил и стандартов. У меня есть свой стандарт, долго его формировал из чужого кода и книжек. Мне ломает глаз эта uint32_t, мне лично удобнее U32 (постепенно перехожу на такую форму записи со слишком длинной UNSIGNER32). Я привел файл Pin.hpp в качестве примера, т.е. as is. Если что-то не нравится или кажется неудобным - переписывайте под себя, я не против ))) Буду рад если найдете баги или еще более лучшие решения, но придирки к оформлению и мелочам предлагаю все же оставить за кадром.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|