Библиотека для цифрового выхода

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Библиотека упрощает объявление цифровых выходов и управление ими.

Имеет функцию установки высокого уровня на выходе, низкого уровня на выходе, инвертирование выхода, а так-же проверку состояния выхода.

Пример Blink`a с применением библиотеки

#include <DigOut.h>//подключаем библиотеку
DigOut LED(13);//инициализация цифрового выхода 13 без установки уровня

void setup() { }

void loop() {
  LED.HI();//устанвливаем низкий уровень на выходе
  delay(1000);
  LED.LO();//устанвливаем низкий уровень на выходе
  delay(1000);
}

или

#include <DigOut.h>//подключаем библиотеку
DigOut LED(13,0);//инициализация цифрового выхода 13 с установкой низкого уровня

void setup() {  
  Serial.begin(9600);  
}
void loop() {
  LED.invert();//инвертируем состояние выхода
  Serial.println(LED.state());//Получаем состояние цифрового выхода и выводим
  delay(1000);
}

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Жесть. Реализовывать ногодрыг в классах через Wiring. Фсё, ушел на пензию.. :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

yul-i-an пишет:

Библиотека упрощает 

Можете пояснить в чём именно состоит упрощение?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Пропадает необходимость забивать Setup() строками типа pinMode(13,OUTPUT), писать #define LED 13 или #define LED_on digitalWrite(LED, HIGH)

Просто даем имя выходу (если так можно выразится), а дальше всё просто LED.HI(), LED.LO(), LED.invert() или проверяем состояние if(LED.state()==1){}/

Но Вам это незачем Уважаемые эксперты.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

yul-i-an пишет:

Но Вам это незачем Уважаемые эксперты.

Вы меня хотите оскорбить? Напрасно. Я задал Вам вопрос, мне кажется не хамил и позвольте мне самому решать что мне зачем, что что незачем.

Я действительно хочу разобраться, в чем именно упрщение. Читаю Ваш ответ и аытаюсь понять.

yul-i-an пишет:

Пропадает необходимость забивать Setup() строками типа pinMode(13,OUTPUT)

Меняем одну строку pinMode... на одну строку DigOut LED(13). Т.е. "строку на строку" выгоды пока не вижу.

yul-i-an пишет:

писать #define LED 13

 
Ну, да, потому, что Вы написали DigOut LED(13). А если бы определили 13 через константу, то был бы тот же дефайн.

Нет, я всё-таки хочу понять, поэтому объясните пожалуйста, толком. Вот Ваш код.

#include <DigOut.h>//подключаем библиотеку
DigOut LED(13);//инициализация цифрового выхода 13 без установки уровня

void setup() { }

void loop() {
  LED.HI();//устанвливаем низкий уровень на выходе
  delay(1000);
  LED.LO();//устанвливаем низкий уровень на выходе
  delay(1000);
}

а вот стандартный код

#define MyPIN	13
void setup() {
  pinMode(MyPIN, OUTPUT);
}

void loop() {
  digitalWrite(MyPIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(MyPIN3, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

Строк одинаково. Чем Ваш код удобнее? Может объяснить?

 

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Дело не в количестве строк, а в читаемости (визуальном восприятии) кода. Меньше подготовительной работы - #define MyPIN 13, pinMode(MyPIN, OUTPUT). Просто - DigOut MyPin(13)

 

dhog1
Offline
Зарегистрирован: 01.03.2016

Я устал. Я ухожу. (цитата)

Держал в коллекции библиотеку AH_74HC165.h (должна гуглиться, но если нет это "Created by A. Hinkel 2012-08-05 и " Download from "http://www.arduino-projekte.de".  Это еще не все. Там в заголовке еще Code license: CC-BY-SA, не меньше. У меня есть еще примеров библиотекописательства.

Это восхитительно в плане э-ээ... донесения до общественности результатов своих изысканий, как на кулинарном форуме. Ну и собирания "лайков" вроде "чмоки". Заслуживает внимания и чеканный оборот, сродни do ... while  -  просто ... а дальше все просто (конец оборота).

Ну вот кто дернул уважаемых экспертов на непродуманные и эмоциональные реплики?

(уходит, бормоча) ... прости, Г-ди, дитей ардуиновых, ибо не ведают что

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

yul-i-an пишет:

Дело не в количестве строк, а в читаемости (визуальном восприятии) кода. Меньше подготовительной работы - #define MyPIN 13, pinMode(MyPIN, OUTPUT). Просто - DigOut MyPin(13)

Значит, вместо #define MyPIN 13, pinMode(MyPIN, OUTPUT), будет #define MyPIN 13, DigOut MyPin(MyPIN) и это гораздо, удобнее. Понятно!

Можно поинтересоваться, а для чего в классе свойство _state? Используется оно единственный раз в методе DigOut и больше нигде. Если его убрать, то ничего не изментися. Так, для чего оно? "На вырост"? Для использования в будущих расширениях? Или просто, чтобы память занимала?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Чтобы память занимала. Надо её занять чем-то пока светодиодами моргаем, чтобы транзисторы не атрофировались)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

yul-i-an пишет:

Чтобы память занимала. Надо её занять чем-то пока светодиодами моргаем, чтобы транзисторы не атрофировались)

Ну, вот, теперь понятно.

Можете же объяснять толково, а то сразу "вам не надо" ...

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ну так и чтобы тормозила внятнее .. а то 16 мгц как-то много шибко. Да даже 100кгц digitalWrite() глазом не уследишь .. :)

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Подправил. Избавился от _state)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

yul-i-an пишет:

Подправил. Избавился от _state)

Молодец.

Теперь обратите внимание на два практически одинаковых метода

DigOut::DigOut(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
}

DigOut::DigOut(int pin, bool state)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
  digitalWrite(_pin, state);
}

Зачем?

Они запросто объединяются в один. Для этого достаточно выбросить первый, а в описании класса, второму задать значение параметра state по умолчанию. Тогда к этому методу можно будет обращаться как с двумя параметрами, так и с одним.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Э-э.. нет. ТАК не пойдет. В первом конструкторе установка состояния вывода НЕ вызывается и вовсе, а во втором установка происходит в заданное значение. Параметр по умолчанию БУДЕТ делать установку в значение по умолчанию. Автор таким способом хотел "сэкономить" код (помазав сверху пирог wiring ещё и своим).

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Arhat109-2 пишет:

Э-э.. нет. ТАК не пойдет. В первом конструкторе установка состояния вывода НЕ вызывается и вовсе, а во втором установка происходит в заданное значение. Параметр по умолчанию БУДЕТ делать установку в значение по умолчанию. 

Кто Вам такое сказал? Сделайте его не bool, а int8_t. По умолчанию -1, а внутри, если меньше нуля - не устанавливать, а в противном случае установить. Делов-то!

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

То есть Вы предлагаете ДОБАВИТЬ проверку в том месте где ТС хотел СЭКОНОМИТЬ?!? (он хотел конечно странного, но все же!)

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Покопался в интернете, получилось следующее

DigOut.h


#ifndef DigOut_h
#define DigOut_h
class DigOut
{
  public:
DigOut(int pin=13, bool state=0);
	void HI();
    void LO();
	void invert();
	bool state();
  private:
    int _pin;
};
 
#endif

DigOut.cpp


#include <arduino.h>	
#include "DigOut.h"

DigOut::DigOut(int pin, bool state)
{
  _pin = pin;
  pinMode(_pin, OUTPUT);
  digitalWrite(_pin, state);
}
 
void DigOut::HI()
{
  digitalWrite(_pin, HIGH);
}
 
void DigOut::LO()
{
  digitalWrite(_pin, LOW);
}

bool DigOut::state()
{
  return digitalRead(_pin);
}

void DigOut::invert()
{
  digitalWrite(_pin, !digitalRead(_pin));
}

Теперь можно вызывать и без второго параметра (0 по умолчанию).

Теперь экземпляр класса можно описать

DigOut x; - с параметрами по умолчанию (имя экземпляра x, 13 пин, состояние LOW)

DigOut x(myPin); - (имя экземпляра x, пин myPin, состояние LOW по умолчанию)

DigOut x(myPin, 1); - (имя экземпляра x, пин myPin, состояние HIGH задано)

Библиотека DigOut

MacSim
Offline
Зарегистрирован: 28.11.2012

... а теперь попробуйте с прямым доступом к портам, и диджитал врайт забудите.

за библиотеку спасибо, еще один пример создания библиотеки.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Последнее время пытаюсь облегчить процесс написания программ, вот недавно еще библиотеку для терморезистора писал тут.

Arduino позволяет пользователю сосредоточиться на разработке проектов, а не изучении устройства и принципов функционирования отдельных элементов.

Я думаю что большенству (для моргалок, теплиц, лестниц с подсветкой, паяльных станций и т.п. ) хватит и дигталВритев, а кому мало ... можно и глубже копнуть.)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Arhat109-2 пишет:

То есть Вы предлагаете ДОБАВИТЬ проверку в том месте где ТС хотел СЭКОНОМИТЬ?!? (он хотел конечно странного, но все же!)

Он хотел сэкномить? Впервые слышу. Ну, если не хотите добавлять проверку, то можно оставить оба метода, но не дублировать, а вызывать один из другого. В любом случае одинаковые куски кода - абсолютное зло.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

yul-i-an пишет:

Покопался в интернете, получилось следующее

Я так понимаю, Вы упражняетесь в написании классов. Если так, давайте упражнаяться дальше.

Следующее упражнение, добавьте возможность присваивания уровня  пину. Т.е., чтобы можно было писать.

DigOut pin(13);
...
pin = HIGH;
...
pin = LOW;

Потом, присваивание пинов друг другу (по уровню, чтобы уровень одного присваивался другому)

DigOut pin10(10), pin12(12);
...
pin10 = HIGH;
...
pin12 = pin10; // теперь и 12 стал HIGH

Как сделаете, попробуйте добавить сравнения пинов по уровню, чтобы можно было писать

DigOut pin10(10), pin12(12);
...
if (pin10 == pin12) { если оба HIGH или LOW }
else { если разные }

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Заинтриговали, да и вплане воспоминания С++, тоже решил поучаствовать:

// файл pins.h:
#include <inttypes.h>
#include <avr/pgmspace.h>

// ========================= Определения, зависящие от процессора ========================= //
// @TODO: Вынести в отдельный файл настроек, типа arduino_pins.h или arhat_pinsXXXX.h

#if !defined(_DIG_ARRAYS_)
  #define _DIG_ARRAYS_ 1

  volatile uint8_t * PROGMEM pin2ddr[] =
  {
    &DDRA, &DDRB, &DDRC, &DDRD, &DDRE, &DDRF, &DDRG, &DDRH, 0, &DDRJ, &DDRK, &DDRL
  };
  volatile uint8_t * PROGMEM pin2port[] =
  {
    &PORTA, &PORTB, &PORTC, &PORTD, &PORTE, &PORTF, &PORTG, &PORTH, 0, &PORTJ, &PORTK, &PORTL
  };
  volatile uint8_t * PROGMEM pin2pin[] =
  {
    &PINA, &PINB, &PINC, &PIND, &PINE, &PINF, &PING, &PINH, 0, &PINJ, &PINK, &PINL
  };
#endif // _DIG_ARRAYS_

#define DLed	{1,7}	/* PB 7 ** D13 + PWM13 + T0outA + T1outC + PC_INT_7 !!! INTERNAL LED! Can't be input D!!! ** */

#define D0	{4,0}	/* PE 0 ** D0 + USART0_RX + PC_INT_8 ** */
#define D1	{4,1}	/* PE 1 ** D1 + USART0_TX ** */
#define D2	{4,4}	/* PE 4 ** D2 + PWM2 + T3outB + INT_4 ** */
#define D3	{4,5}	/* PE 5 ** D3 + PWM3 + T3outC + INT_5 ** */
#define D4	{6,5}	/* PG 5 ** D4 + PWM4 + T0outB ** */
#define D5	{4,3}	/* PE 3 ** D5 + PWM5 + T3outA + AIN1 ** */
#define D6	{7,3}	/* PH 3 ** D6 + PWM6 + T4outA ** */
#define D7	{7,4}	/* PH 4 ** D7 + PWM7 + T4outB ** */
#define D8	{7,5}	/* PH 5 ** D8 + PWM8 + T4outC ** */
#define D9	{7,6}	/* PH 6 ** D9 + PWM9 + T2outB ** */
#define D10	{1,4}	/* PB 4 ** D10 + PWM10 + T2outA + PC_INT_4 ** */
#define D11	{1,5}	/* PB 5 ** D11 + PWM11 + T1outA + PC_INT_5 ** */
#define D12	{1,6}	/* PB 6 ** D12 + PWM12 + T1outB + PC_INT_6 ** */
#define D13	{1,7}	/* PB 7 ** D13 + PWM13 + T0outA + T1outC + PC_INT_7 !!! INTERNAL LED! Can't be input D!!! ** */
#define D14	{9,0}	/* PJ 1 ** D14 + USART3_TX + PC_INT_10 ** */
#define D15	{9,0}	/* PJ 0 ** D15 + USART3_RX + PC_INT_9 ** */
#define D16	{7,0}	/* PH 1 ** D16 + USART2_TX ** */
#define D17	{7,0}	/* PH 0 ** D17 + USART2_RX ** */
#define D18	{3,0}	/* PD 3 ** D18 + USART1_TX + INT_3 ** */
#define D19	{3,0}	/* PD 2 ** D19 + USART1_RX + INT_2 ** */
#define D20	{3,0}	/* PD 1 ** D20 + I2C_SDA + INT_1 ** */
#define D21	{3,0}	/* PD 0 ** D21 + I2C_SCL + INT_0 ** */
#define D22	{0,0}	/* PA 0 ** D22 (D22) + BUS_AD0 ** */
#define D23	{0,0}	/* PA 1 ** D23 (D23) + BUS_AD1 ** */
#define D24	{0,0}	/* PA 2 ** D24 (D24) + BUS_AD2 ** */
#define D25	{0,0}	/* PA 3 ** D25 (D25) + BUS_AD3 ** */
#define D26	{0,0}	/* PA 4 ** D26 (D26) + BUS_AD4 ** */
#define D27	{0,0}	/* PA 5 ** D27 (D27) + BUS_AD5 ** */
#define D28	{0,0}	/* PA 6 ** D28 (D28) + BUS_AD6 ** */
#define D29	{0,0}	/* PA 7 ** D29 (D29) + BUS_AD7 ** */
#define D30	{2,0}	/* PC 7 ** D30 (D30) + BUS_A15 ** */
#define D31	{2,0}	/* PC 6 ** D31 (D31) + BUS_A14 ** */
#define D32	{2,0}	/* PC 5 ** D32 (D32) + BUS_A13 ** */
#define D33	{2,0}	/* PC 4 ** D33 (D33) + BUS_A12 ** */
#define D34	{2,0}	/* PC 3 ** D34 (D34) + BUS_A11 ** */
#define D35	{2,0}	/* PC 2 ** D35 (D35) + BUS_A10 ** */
#define D36	{2,0}	/* PC 1 ** D36 (D36) + BUS_A9 ** */
#define D37	{2,0}	/* PC 0 ** D37 (D37) + BUS_A8 ** */
#define D38	{3,0}	/* PD 7 ** D38 (D38) + T0_IN ** */
#define D39	{6,0}	/* PG 2 ** D39 (D39) + BUS_ALE ** */
#define D40	{6,0}	/* PG 1 ** D40 (D40) + BUS_RD ** */
#define D41	{6,0}	/* PG 0 ** D41 (D41) + BUS_WR ** */
#define D42	{11,0}	/* PL 7 ** D42 (D42) not other use ** */
#define D43	{11,0}	/* PL 6 ** D43 (D43) not other use ** */
#define D44	{11,0}	/* PL 5 ** D44 (D44) + PWM44 + T5outC ** */
#define D45	{11,0}	/* PL 4 ** D45 (D45) + PWM45 + T5outB ** */
#define D46	{11,0}	/* PL 3 ** D46 (D46) + PWM46 + T5outA ** */
#define D47	{11,0}	/* PL 2 ** D47 (D47) + T5_IN ** */
#define D48	{11,0}	/* PL 1 ** D48 (D48) + T5_ICP ** */
#define D49	{11,0}	/* PL 0 ** D49 (D49) + T4_ICP ** */
#define D50	{1,0}	/* PB 3 ** D50 (D50) + SPI_MISO + PC_INT_3 ** */
#define D51	{1,0}	/* PB 2 ** D51 (D51) + SPI_MOSI + PC_INT_2 ** */
#define D52	{1,0}	/* PB 1 ** D52 (D52) + SPI_SCK + PC_INT_1 ** */
#define D53	{1,0}	/* PB 0 ** D53 (D53) + SPI_SS + PC_INT_0 ** */
#define D54	{5,0}	/* PF 0 ** Analog0 ** */
#define D55	{5,0}	/* PF 1 ** Analog1 ** */
#define D56	{5,0}	/* PF 2 ** Analog2 ** */
#define D57	{5,0}	/* PF 3 ** Analog3 ** */
#define D58	{5,0}	/* PF 4 ** Analog4 + JTAG_TCK ** */
#define D59	{5,0}	/* PF 5 ** Analog5 + JTAG_TMS ** */
#define D60	{5,0}	/* PF 6 ** Analog6 + JTAG_TDO ** */
#define D61	{5,0}	/* PF 7 ** Analog7 + JTAG_TDI ** */
#define D62	{10,0}	/* PK 0 ** Analog8 + PC_INT_16 ** */
#define D63	{10,0}	/* PK 1 ** Analog9 + PC_INT_17 ** */
#define D64	{10,0}	/* PK 2 ** Analog10 + PC_INT_18 ** */
#define D65	{10,0}	/* PK 3 ** Analog11 + PC_INT_19 ** */
#define D66	{10,0}	/* PK 4 ** Analog12 + PC_INT_20 ** */
#define D67	{10,0}	/* PK 5 ** Analog13 + PC_INT_21 ** */
#define D68	{10,0}	/* PK 6 ** Analog14 + PC_INT_22 ** */
#define D69	{10,0}	/* PK 7 ** Analog15 + PC_INT_23 ** */

// ========================= Конец зависимых определений тут ========================= //
// ========================= "C"-онистам: внутренние определения ========================= //

#ifdef __cplusplus
  extern "C" {
#endif

// for speed use. Demand 3 byte for each pin variable
typedef struct {
  volatile uint8_t * port;
  uint8_t            mask;
} _Dig_pin;

/**
 * Will be compiled into Asm:
 *      in   reg_data, port | lds reg_data, port(Z)
 *      tst  val_reg
 *      breq .ELSE
 *        or   reg_data, reg_mask
 *        jmp  .ENDIF
 * .ELSE:
 *        com reg_mask
 *        and reg_data,reg_mask
 * .ENDIF:
 *      out port,reg_data | sts port(Z), reg_data
 */
#define __dig_out(port, mask, val) \
{                                  \
  uint8_t    data = *(port);       \
                                   \
  if(val) (data) |= (mask);        \
  else    (data) &= ~(mask);       \
  *(port) = (data);                \
}

// @param _Dig_pin p -- const|vars, not for Dxx macro! or classes
#define _dig_out(p, val)                \
{                                       \
  DigitalPin  tmp = p;                  \
  __dig_out(tmp.port, tmp.mask, (val)); \
}

#define __dig_set_bits(port, mask) \
{                                  \
  uint8_t    data = *(port);       \
  (data) |= (mask);                \
  *(port) = (data);                \
}

#define __dig_clr_bits(port, mask) \
{                                  \
  uint8_t    data = *(port);       \
  (data) &= ~(mask);               \
  *(port) = (data);                \
}

// Converting port number [0..7,9..11] into port ram address:
#define __dignum_2_ddr(p)  (pgm_read_word( pin2ddr[(p)] ))
#define __dignum_2_port(p) (pgm_read_word( pin2port[(p)] ))
#define __dignum_2_pin(p)  (pgm_read_word( pin2pin[(p)] ))

#ifdef __cplusplus
  } // extern "C"
#endif
// ========================= Конец внутренних определений ========================= //
// ========================= "Классным любителям" ========================= //

/* сделай это, и не придется писать каждый раз квалификатор класса перед константой..
#define INPUT    0
#define OUTPUT   1
#define INPULLUP 2
#define LOW      0
#define HIGH     1
*/
class PinAbstract
{
  const uint8_t INPUT    = 0;
  const uint8_t OUTPUT   = 1;
  const uint8_t INPULLUP = 2;

  const uint8_t LOW   = 0;
  const uint8_t HIGH  = 1;

  uint8_t Mode (const uint8_t _mode) = 0;
  uint8_t Out  (const uint8_t _val)  = 0;
  uint8_t In   (void) = 0;

};

class DigitalPin :: public PinAbstract {
private:
  uint8_t portnum; // номер портов пина [0..7,9..11]
  uint8_t mask;    // маска номера бита пина в порту ИЛИ групповая маска пинов одного порта
public:
  inline DigitalPin::DigitalPin (const DigitalPin _pin);
  DigitalPin::DigitalPin (const DigitalPin _pin, uint8_t _mode = PinAbstract::INPUT, uint8_t _val = PinAbstract::LOW);

         uint8_t Mode (uint8_t _mode);
         uint8_t Out  (uint8_t _val);
  inline uint8_t In   (void);
}

// ========================= Реализация С++ ========================= //

DigitalPin::DigitalPin(const DigitalPin _pin)
: portnum(_pin.portnum), mask(_pin.mask)
{}

DigitalPin::DigitalPin(const DigitalPin _pin, uint8_t _mode, uint8_t _val)
: portnum(_pin.portnum), mask(_pin.mask)
{
  this.Mode(_mode);
  this.Out(_val);
}

DigitalPin::Mode(const uint8_t _mode)
{
  uint8_t * mem = __dignum_2_ddr(this->portnum);

  if( _mode == PinAbstract::OUTPUT )    __dig_set_bits(mem, this->mask);
  else {
    __dig_clr_bits(mem, this->mask);
    if( _mode == PinAbstract::INPULLUP  ){
      mem = __dignum_2_port(this->portnum);
      __dig_set_bits(mem, this->mask);
    }
  }
  return _mode;
}

DigitalPin::Out(const uint8_t _val)
{
  _dig_out(this, _val);
  return _val;
}

uint8_t DigitalPin::In(void)
{
  uint8_t * mem = __dignum_2_pin(this.portnum);
  return *mem;
}

И? Сравнил части файла "для Си-онистов" и "для классных г-кодеров" .. и вот не могу понять чем же С++ выгоднее и лучше? Явно код будет больше и ЗНАЧИТЕЛЬНО, писать - больше И ЗНАЧИТЕЛЬНО, возможностей ошибитьсядаже в написании методов, классов .. больше и ЗНАЧИТЕЛЬНО. Как итог: на "С" часть, вместе с платформозависимым куском (больше всего времени) ушло от силы минут 30. Кусок "для классных кодеров" писался 2(ДВА) часа!

Ладно, это одна из первых моих поделок для С++ после 17-и летнего перерыва .. мож и намудрил чего. Ну ТАК ПОКАЖИТЕ мне как оно пишется "легко и ненапряжно", а главное "шустрее и абстрактнее" .. вот сильно сомневаюсь, что кто-то тут из апологетов С++ возьмется изменить хоть что-то..

А в довесок ко всему .. оно ещё и НЕ КОМПИЛЯЕТСЯ в ИДЕ вот таким одним файлом .. ни в какой версии. (1.0 не имею и давно уже).

Жесть. Линус Торвальд абсолютно прав, когда пишет, что С++ -- инструмент говнокодера.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Arhat109-2 пишет:

тоже решил поучаствовать:

Решения поставленных задач в коде не обнаружено. Участие не засчитывается.

Arhat109-2 пишет:

не могу понять чем же С++ выгоднее и лучше?

И не поймёте.  Из того, что использовано слово class, ещё не следует, что это программа на С++. Известно, что "настоящий программист может написать фортрановскую программу на любом языке".

Arhat109-2 пишет:

Кусок "для классных кодеров" писался 2(ДВА) часа!

Ну, не я же виноват, что Вы писать не умеете, правда?

Arhat109-2 пишет:

Ну ТАК ПОКАЖИТЕ мне как оно пишется "легко и ненапряжно", а главное "шустрее и абстрактнее"

Вы хотите нанять меня в качестве персонального преподавателя (репетитора)?

Arhat109-2 пишет:

.. вот сильно сомневаюсь, что кто-то тут из апологетов С++ возьмется изменить хоть что-то..

Ну, почему же? $200 в час и я готов работать. Хотя, я наверное не подхожу потому, что я вовсе не апологет С++ ... у меня другие "любимые языки".

Arhat109-2 пишет:

А в довесок ко всему .. оно ещё и НЕ КОМПИЛЯЕТСЯ в ИДЕ вот таким одним файлом

То, что Ваш код не компилируется - это вина языка? Или Вашего неумения на нём писать? Подумайте.

Arhat109-2 пишет:

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

Конечно, прав! Как, впрочем, и любой другой язык. Инструментом говнокодера может выступать абсолютно любой язык. Говнокод определяется не языком, а стилем программирования.

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ваш ответ, извините, обыкновенная для вас "вода" без привязки к поставленным вопросам и утверждениям. То есть - не по делу.

1. Вопрос не в том, что есть слово class или нет. вопрос в том, что жмакать кнопочки для версии С++ оказалось в 3 раза больше. Об чем и было указано: "писать больше и ЗНАЧИТЕЛЬНО" .. вы этот момент умолчали, ответив не по делу. Вопрос не в том, что не умею или умею, а просто технически БОЛЬШЕ.

2. Там не было вопроса о найме и тем более конкретно вас в каком-либо качестве. Было предложение ПОКАЗАТЬ что утверждение п.1 - неверно. Вы попытались перевести стрелки.

3. Оно не компиляется по причине того что в Arduino.h торчит #define INPUT 0 .. что замещает имя классной константы на "бардак". :) и это всё, что было утверждено. Вы же снова попытались перевести стрелки и что печально на обсуждение моей личности, вместо обсуждения дела. Вот и подумайте сами.

4. "Говнокод определяется не языком, а стилем программирования." Требует доказательств. В данном конкретном случае, стиль разработки на С++ ПРОВОЦИРУЕТ на писание говнокода. Это стиль порождающий говнокод. Аргумент "за":

в данном примере использован абстрактный интерфейс пинов + класс реализации. С т.з. языка и архитектурного планирования подход более чем оправдан: предыдущее обсуждение в соседней теме "что случилось с компилятором" показало что существует НЕСКОЛЬКО оптимальных имплементаций этого интерфейса для разных случаев.

Так вот: описание одних и тех же сущностей приходится делать .. ТРИЖДЫ .. в абстрактном классе, заголовочном описании класса реализации и в самой реализации методов. Ошибиться в одном из них "по ходу пьесы" очень даже легко (что и было проделано мной несколько раз) .. поиск описок, их исправление .. вот это и есть те самые ДВА ЧАСА плюсом к конечно же меньшей скорости разработки в силу малого опыта. Там ещё "осталось".. :)

Вот это и есть провоцирующий к говнокоду язык.

А самое главное, что получить настолько же эффективную реализацию в конечном скетче, даже для такого простого класса практически не представляется возможным. То есть мало того, что имеем язык провоцирующий к говнокоду, так ещё и его компиляция приводит к говно-системам с неизбежностью очевидного.

Вот это, как понимаю и сокрыто в словах Торвальдса.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Arhat109-2 пишет:

Ваш ответ, извините, обыкновенная для вас "вода" без привязки к поставленным вопросам и утверждениям. То есть - не по делу.

Это Ваше оценочное суждения. Я считаю, что мой ответ был по делу.

Arhat109-2 пишет:

1. Вопрос не в том, что есть слово class или нет.

Так и я о том же. То, что у Вас написано - не является программой на С++, хотя и использован синтаксис этого языка. Поэтому делать выводы о языке на основании Вашего кода просто некорректно.

Arhat109-2 пишет:

2. Там не было вопроса о найме ... Было предложение ПОКАЗАТЬ

"показать" означает, что я должен поработать какое-то время на Вас, показывая Вам что-то. На рынке труда это называется наймом.

Arhat109-2 пишет:

3. Оно не компиляется по причине того что ...

Какая разница по какой причине? Что-то другое не компилируется по причине того, что точку с запятой не поставили, и что? Язык-то то тут при каких делах?

Arhat109-2 пишет:

С++ ПРОВОЦИРУЕТ на писание говнокода.

Написание говнокода провоцируется в первую очередь, неумением программировать, а во-вторую, незнанием языка и неумением на нём писать.  Например, Вы не знали как устроена целочисленная арифметика и вполне благополучно наговнокодили на самом что ни на есть кошерном С. Помните? Потом ещё в своей обычной манере доказывали мне, что Вы правы. 

Arhat109-2 пишет:

описание одних и тех же сущностей приходится делать .. ТРИЖДЫ .. 

Мне остаётся только повторить, что не я виноват в том, что Вы не знаете языка и не умеете на нём писать.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Я вижу появилось дополнение

Arhat109-2 пишет:

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

Сделать, чтобы установка HIGH или LOW в этом (иди подобном этому) классе производилась одной командой процессора - как два пальца. При этом устанавливать можно и присваиванием, как я предложил ИС сделать - и всё равно будет одна команда. То, что Вы этого не умеете - это Ваша проблема, а не проблема языка.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Цитата:
Например, Вы не знали как устроена целочисленная арифметика и вполне благополучно наговнокодили на самом что ни на есть кошерном С. Помните?

Я помню, как вы не разобравшись, по незнанию С, указали на некую ашипку, а потом не поняли, что так написано было сознательно. Просто не для тех, кто не знает языка. :) И до сих пор не можете себе в этом банальном вопросе признаться, чьто и подтверждает вышеизложенный текст. Помню конечно.

[qoute]Сделать, чтобы установка HIGH или LOW в этом (иди подобном этому) классе производилась одной командой процессора - как два пальца. При этом устанавливать можно и присваиванием, как я предложил ИС сделать - и всё равно будет одна команда. То, что Вы этого не умеете - это Ваша проблема, а не проблема языка.[/quote]

Что я умею, а чего нет - ни разу не ваша проблема. Ваши непрерывные попытки заострять на этом внимание - говорят только о том, что Вы ПРИЗНАЕТЕ, что вам до моих знаний и умений - как до Пекина пешком. Спасибо конечно, "мелочь, но приятно". Тем не менее, я буду настаивать на переводе этого и ЛЮБЫХ ИНЫХ обсуждений в конструктивное русло, а не СРАЧА, как вам оно больше НРАВИТСЯ.

Так вот, то что тут можно компилять в одну команду .. я тоже вижу. Я также вижу что в целом(!) язык ПРОВОЦИРУЕТ на длинное компилирование. И в этом вопросе, мнение иных ветеранов программирования (и не только Торвальдса, но и Страуструпа, Вирта) - однозначно. Вы таки "пготив"? :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Arhat109-2 пишет:

а потом не поняли, что так написано было сознательно. 

Сознательно? Архат, это уже ни в какие ворота не лезет! Тогда Вы признали свою ошибку и написали "Похоже "улучшил" макрос когда переносил в файл" (правда тут же новую сдлелали, но сейчас не об этом). А теперь это уже стало "сознательно" и ошибся, оказывается, я? Т.е. Вы не только безграмотный прогер, но ещё и ... как бы помягче .. брехло? Ну, ладно, живите с этим. Обсуждать что-то с человеком, который врёт в глаза я как-то уже давно отвык.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Вы на самом деле дурак или только прикидываетесь? Перечитайте что там написано:

"Это макропродстановка и в нормальном выражении он будет выглядеть так:

int time = 100*TSC_PERIOD; что после разворачивания макроса даст

int time = 100*(1000/1024); что после предвычисления компилятором константы даст 97,65625 что после преобразования компилятором к целой константе даст 97, что и требовалось. :)"

и далее: "Похоже "улучшил" макрос когда переносил в файл." сказано про добавленные СКОБКИ и только.

Так что не поняли до сих пор. И "брехло" - тут только Вы. Кстати ваше утверждение - "Сделать, чтобы установка HIGH или LOW в этом (иди подобном этому) классе производилась одной командой процессора - как два пальца."

Есть ПРЯМОЕ ВРАНЬЁ. Я же вам и давал ссылку на то КАК оно делается в С++ .. запамятовали?

Или вам напомнить вашу "эквилибристику" в классом Print? В отличии от вас, я не храню ссылки на ваши перлы, мне это незачем. А вот вам оно ОЧЕНЬ НАДО, ибо бабский склочник.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Впрочем, я уже отписал вам, что все ваши нападки на меня лично и хотелки подколоть в незнании чего-либо, я рассматриваю как признание вашей собственной несостоятельности в ваших же собственных глазах и только. Никак иначе. Так что - спасибо ещё раз. Мне - приятно.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не, я всё понял про Вас, можете дальше не разоряться. Ухудшить моё мнение о Вас Вам уже не удастся. Расслабьтесь уже. Всё закончилось.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

ЕвгенийП, уже в сотый раз пишу о том, что мне глубоко наплевать на ваше мнение обо мне конкретно. Особенно в свете вашей истории появления тут и обучении работе с микроконтроллерами и языком С на примерах МОЕГО кода И обсуждения ваших ляпов. Меня утсраивает тот факт, что код, который написан мною - вам помог освоить эту ветвь программирования.

А неблагодарных дураков, я за свою жизнь повидал много. Вы - далеко не первый.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Arhat109-2 пишет:

обучении работе с микроконтроллерами и языком С на примерах МОЕГО кода 

Чего? Вы здоровы? Обратитесь к врачу, на всякий случай, а то как бы эта мания величия во что-нибудь более серьъёзное не перешла. 

Radjah
Offline
Зарегистрирован: 06.08.2014

Опять промышленное велосипедостроение? :)

arduinec
Offline
Зарегистрирован: 01.09.2015

Опять ЕвгенийП и Arhat109-2 на ровном месте разругались. Вам что заняться нечем? Напомню: ЕвгенийП обещал этюд "Память 2", а Arhat109-2 - дешёвое дополнение к ОЗУ для Меги. Давайте не руганью, а делами доказывать свою крутость!

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Мне казалось, что я уже выложил достаточно .. что ещё надо описать, показать? Давайте на выходных сяду..

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

arduinec пишет:

ЕвгенийП обещал этюд "Память 2"

Давно готов. И третий тоже. Не выкладывается по каким-то мистическим причинам - типа есть ощущение, что никому нафиг не надо.

arduinec пишет:
делами доказывать свою крутость!

Нет, так не пойдёт. Не буду я никому ничего доказывать. Давно уже никому ничего не доказываю. Если пишу что-то, то только потому, что мне это нравится.

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

yul-i-an,

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

arduinec
Offline
Зарегистрирован: 01.09.2015

ЕвгенийП пишет:

arduinec пишет:

ЕвгенийП обещал этюд "Память 2"

Давно готов. И третий тоже. Не выкладывается по каким-то мистическим причинам - типа есть ощущение, что никому нафиг не надо.

Моё мнение по этому поводу такое: Чем больше качественной информации (по программированию и микроконтроллерам), тем лучше и для опытных программистов и для новичков. Лично мне эти этюды нравятся, получаю из них полезную информацию.

Кстати, может целую книгу написать (в электронном виде)?

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Интересно, что конкретно для вас там оказалось полезным? Вот просто любопытно. На мой взгляд (и кое-где я его там излагал) - больше как раз вредной инфы .. а вам? :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Спасибо на добром слове.

arduinec пишет:

Кстати, может целую книгу написать (в электронном виде)?

Не думаю, что она хорошей получится. Я не умею останавливаться, если начинаю писать, то копаю вглубь и очень быстро ухожу в дебри, которые совсем не для новичков. И знаю про это, но поделать ничего не могу. Мне всё время кажется. что если я не докопал до дна, то материал типа неполный и непонятный :) Поэтому книги для профессионалов у меня получаются (есть несколько), а для новичков только вот здесь тренируюсь.

Вот, пример. Есть вроде и неплохая книга Брайана Эванса. И чего я к ней прикопался? Но вот открываю 10-ую страницу и просто глаза режет фраза: "Точка с запятой должна использоваться в конце выражения и разделять элементы программы". Нормальная фраза для начинающего, но по факту неправильная. На самом деле, это в Паскале точка с запятой является разделителем, а в С - она не разделитель, а часть выражения. Разница между этими вещами неощутима пока не полезешь в теорию компиляции и тысячи людей программируют, не понимая этой разницы, и им это ничуть не мешает. Но мне как-то не по себе от таких неточностей. Но это мои внутренние тараканы.

Вот ... видите пост №39. Сейчас опубликую, опять срач начнётся, а я уже устал от дремучего невежества этого господина и ему подобных.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Вы мне нравитесь. Развели сами срач .. и сами же оппонента в нем обвинили. Я кстати, вас неоднократно призвал прекратить троллизм .. так нет жеж .. ну и кто тут "невежда", впрочем как и "брехло"? :)

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

В какую сторону копать?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да, прекратите уж, надоело. КТо брехло и невежда я уже говорил с тех пор ничего не поменялось. По второму кругу что-ли?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

yul-i-an пишет:

В какую сторону копать?

Это Вы про мой двадцатый пост?

Если про него, то почитайте хоть вот здесь и попробуйте сделать. Все три задачи примерно одинаково делаются. Будут непонятки, обращайтесь.

arduinec
Offline
Зарегистрирован: 01.09.2015

ЕвгенийП пишет:

Сейчас опубликую, опять срач начнётся, а я уже устал от дремучего невежества этого господина и ему подобных.

Так публикуй для тех кому это интересно, а злопыхатели всегда найдутся (не стоит на них своё время растрачивать).

arduinec
Offline
Зарегистрирован: 01.09.2015

ЕвгенийП пишет:

Спасибо на добром слове.

arduinec пишет:

Кстати, может целую книгу написать (в электронном виде)?

Не думаю, что она хорошей получится. Я не умею останавливаться, если начинаю писать, то копаю вглубь и очень быстро ухожу в дебри, которые совсем не для новичков. И знаю про это, но поделать ничего не могу. Мне всё время кажется. что если я не докопал до дна, то материал типа неполный и непонятный :) Поэтому книги для профессионалов у меня получаются (есть несколько), а для новичков только вот здесь тренируюсь.

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

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

ЕвгенийП, я так понимаю необходимо использовать перегрузку оператора "=".

Тут помоему более доходчиво описано. Скоро реализую.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Архат, вставлю свои пять копеек: тот код, который ты привёл как код С++ - таковым не является, т.к. безграмотный совершенно. Спихивать на язык и компилятор своё неумение с ним обращаться - некрасиво. Обсирать инструмент, не умея им пользоваться - некрасиво вдвойне.

Я прекрасно понимаю и осознаю, что в каждом языке есть плюсы и минусы, более того, есть задачи определённого свойства, где использовать всю мощь С++ - это как из пушки по воробьям. Есть и наоборот, такие, где писать код на С - значит сходу загнать себя в гроб, скажем образно.

Но написать безграмотный код и аппелировать при этом к тому, что "раз я ДВА часа писал простенький С++ код и так и не смог написать его грамотно и правильно - значит С++ избыточен, ущербен и вообще гавно" - это как-то неконструктивно, как по мне.

Это ты ещё, наверное, не знаешь всей красоты шаблонов в С++ - помнится, читал я на изиэлектроникс статейку, где шаблонный С++-код вполне себе разворачивался ооченно эффективно. Да, первоначальное вхождение в вопрос в виде написания кода там было посложнее, чем простенький класс (посложнее - это мягко сказано), но: это, пожалуй, единственное самое грамотное с архитектурной точки зрения решение для имплементации истинной кроссплатформенности средствами языка, а не средствами препроцессора.

В общем, каждому инструменту - своё применение. Скажем, я сознательно пишу на С++ под дуину, ибо - век, как никак, на дворе двадцать первый, и уже давно доказано, что оверхэд, при грамотном проектировании, при использовании С++ - минимален. Во-вторых - я привык к архитектурный решениям, пусть и доморощенно кривоватым, а не сваливать весь код в кучу малу.  В третьих - вся обвязка Wiring - это, по сути, набор С++-классов, хочется тебе этого или нет ;)

Но, если надо - могу писать и на чистом С в стиле процедурного программирования, не вопрос. Могу и на LUA, и на других языках. И если у меня что-то не получается - виноват не язык, это точно.

З.Ы. Про LUA чего-то вспомнилось - сначала мне он казался каким-то не таким, но потом, когда вкурил все прелести метатаблиц - оказалось, что эта пицца - самая вкусная пицца на свете. А мог бы и @бнуть не разобравшись ведь, как говорится ;)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

"тот код, который ты привёл как код С++ - таковым не является, т.к. безграмотный совершенно. Спихивать на язык и компилятор своё неумение с ним обращаться - некрасиво. Обсирать инструмент, не умея им пользоваться - некрасиво вдвойне."

DIYMan, перечитайте мой пост. Там ТАК и написано: "и вот не могу понять чем же С++ выгоднее и лучше? .. Ладно, это одна из первых моих поделок для С++ после 17-и летнего перерыва .. мож и намудрил чего. Ну ТАК ПОКАЖИТЕ мне как оно пишется "легко и ненапряжно", а главное "шустрее и абстрактнее" ..  что кто-то тут из апологетов С++ возьмется изменить хоть что-то .. А в довесок ко всему .. оно ещё и НЕ КОМПИЛЯЕТСЯ в ИДЕ вот таким одним файлом .. ни в какой версии. (1.0 не имею и давно уже). Жесть. Линус Торвальд абсолютно прав, когда пишет, что С++ -- инструмент говнокодера."

То есть, я полностью согласен с выводом, что данная реализация - плоха. Можете ответить, мне (и думаю ТС-у тоже будет полезно), почему НИКТО, и вы в т.ч. так и НЕ ПОКАЗАЛ НАМ ОБОИМ как должен выглядеть такой класс? Подход ТС - точно тотже самый .. то есть НЕУМЕЛЫЙ. Описание и реализация конечного класса ногодрыга - ОДИНАКОВА.

Почему, вместо разъяснения мы все вынуждены читать чьи-то помои? Я ведь ТРИЖДЫ просил прекратить этот процесс!!! По доброиу просил и предлагал...

2. Да, вы совершенно правы. Код, который эффективно реализует ногодрыг на С++ - этот тот самый пример с "изиэлектроника" .. в котором применен вовсе не простой класс (как тут ЕвгенийП соврал "как два пальца") .. и даже НЕ ТЕМПЛЕЙТ классов, а применен СИМБИОЗ препроцессора и темплейтов, где препроцессор использован как генератор темплейтов... что согласитесь, далеко не уровень ТС-а и не представленного им примера.

3. "В общем, каждому инструменту - своё применение. Скажем, я сознательно пишу на С++ под дуину, ибо - век, как никак, на дворе двадцать первый, и уже давно доказано, что оверхэд, при грамотном проектировании, при использовании С++ - минимален. Во-вторых - я привык к архитектурный решениям, пусть и доморощенно кривоватым, а не сваливать весь код в кучу малу.  В третьих - вся обвязка Wiring - это, по сути, набор С++-классов, хочется тебе этого или нет ;)"

Конечно так: "каждомоу овощу свое место на своей кухне". Но только вот в программирования микроконтроллеров - овощу "С++" - места НЕТ. Есть? Покажите!

Ваше право выбирать языки и инструменты на свой скус и из собственных предпочтений. Вы же это никому не навязываете? Вот и я считаю, что этого НЕ СТОИТ делать. А только учить хорошему. Автор сам выберет что и как ему лучше. Каждый.

И третье: Wiring -- исключительно УЧЕБНЫЙ проект (об чем у авторов на сайте тоже сказано). Использовать учебный велосипед в промыщленном (да и домашнем практическом) применении - НЕЛЬЗЯ. Поучился, освоил - пожалте в Атмел студию, порты, битики, байтики .. да хоть теми же темплейтами из того же примера с изиэлектроника.. но никак не c Wiring.

Это все равно, что вы придете в парикмахерскую стричься и вас начнут стричь игрушечным, пластмассовым инструментом. Все, кто отказывается учиться далее и пытается пользовать Wiring для разработок - выглядят именно такими "парикмахерами".

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Давайте сравним. Вот класс ТС-а:

/*
  DigOut.h - A. Taranov (yul-i-an) 04.2016
*/

#ifndef DigOut_h
#define DigOut_h
class DigOut
{
  public:
  //DigOut(int pin);
DigOut(int pin=13, bool state=0);
	void HI();
    void LO();
	void invert();
	bool state();
  private:
    int _pin;
};
 
#endif

//===================================
/*
  DigOut.cpp - A. Taranov (yul-i-an) 04.2016 
*/
#include <arduino.h>	
#include "DigOut.h"

/*DigOut::DigOut(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
}*/

DigOut::DigOut(int pin, bool state)
{
  _pin = pin;
  pinMode(_pin, OUTPUT);
  digitalWrite(_pin, state);
}
 
void DigOut::HI()
{
  digitalWrite(_pin, HIGH);
}
 
void DigOut::LO()
{
  digitalWrite(_pin, LOW);
}

bool DigOut::state()
{
  return digitalRead(_pin);
}

void DigOut::invert()
{
  digitalWrite(_pin, !digitalRead(_pin));
}

А вот моя "безграмотная реализация":

class PinAbstract
{
  const uint8_t INPUT    = 0;
  const uint8_t OUTPUT   = 1;
  const uint8_t INPULLUP = 2;

  const uint8_t LOW   = 0;
  const uint8_t HIGH  = 1;

  uint8_t Mode (const uint8_t _mode) = 0;
  uint8_t Out  (const uint8_t _val)  = 0;
  uint8_t In   (void) = 0;

};

class DigitalPin :: public PinAbstract {
private:
  uint8_t portnum; // номер портов пина [0..7,9..11]
  uint8_t mask;    // маска номера бита пина в порту ИЛИ групповая маска пинов одного порта
public:
  inline DigitalPin::DigitalPin (const DigitalPin _pin);
  DigitalPin::DigitalPin (const DigitalPin _pin, uint8_t _mode = PinAbstract::INPUT, uint8_t _val = PinAbstract::LOW);

         uint8_t Mode (uint8_t _mode);
         uint8_t Out  (uint8_t _val);
  inline uint8_t In   (void);
}
DigitalPin::DigitalPin(const DigitalPin _pin)
: portnum(_pin.portnum), mask(_pin.mask)
{}

DigitalPin::DigitalPin(const DigitalPin _pin, uint8_t _mode, uint8_t _val)
: portnum(_pin.portnum), mask(_pin.mask)
{
  this.Mode(_mode);
  this.Out(_val);
}

DigitalPin::Mode(const uint8_t _mode)
{
  uint8_t * mem = __dignum_2_ddr(this->portnum);

  if( _mode == PinAbstract::OUTPUT )    __dig_set_bits(mem, this->mask);
  else {
    __dig_clr_bits(mem, this->mask);
    if( _mode == PinAbstract::INPULLUP  ){
      mem = __dignum_2_port(this->portnum);
      __dig_set_bits(mem, this->mask);
    }
  }
  return _mode;
}

DigitalPin::Out(const uint8_t _val)
{
  _dig_out(this, _val);
  return _val;
}

uint8_t DigitalPin::In(void)
{
  uint8_t * mem = __dignum_2_pin(this.portnum);
  return *mem;
}

Что называется "найдите 2 отличия". :)