Блог о Gentoo и около-линуксовым штукам

Показаны сообщения с ярлыком AVR. Показать все сообщения
Показаны сообщения с ярлыком AVR. Показать все сообщения

10 апреля 2018 г.

NoWOL: питание ПК через интернет. Часть 1.

04:28 Опубликовал Дмитрий Исаенко , , , Нет комментариев
Ох, давно хотел уже задокументировать это здесь, да всё времени не было. И вот, спустя полтора года…

Какую проблему решаем?

Стоит задача включать и выключать ПК нажимая на кнопки включения\выключения и сброса не руками, а через интернет (ну или через тоннель в интранет). В идеале спросонья через виджет в телефоне а-ля узнал погоду за бортом, включил ПК и можно идти ставить кофе.

Для этого было решено пилить какой-то контроллер Atmega с каким-то ethernet-свистком, чтобы он через оптопары замыкал кнопки включения. А заодно сообщал об успехе или неуспехе затеи.

Немного покопавшись я решил закупить основанную на enc28j60 приблуду для ардуины, а заодно и саму ардуину. Изучив особенности программирования enc28j60 руками (без высокоуровневых IDE и готовых библиотек) и бегло осмотрев errata, который, надо отметить, чуть ли не больше даташита, стало ясно, что на низком уровне рулить “этим” сущий ад и боль. Поэтому, будем собирать всё на базе добротного китайского клона Arduino nano или функционального аналога (лучше просто взять arduino, правда).

В итоге система будет состоять из основного модуля в виде связки Arduino+enc28j60 и выносного блока с оптопарами и резисторами.

В целом выглядеть и подключаться всё будет так:

Но перед тем, как начать…

Поставим себе пару пакетов:
1. dev-embedded/arduino
2. sci-electronics/eagle (ветка 7.x.x и лучше из нестабильной ветки) 
Все необходимые файлы лежат в проекте на GitHub:
https://github.com/developersu/NoWOL

Про выносной модуль

Файлы для Eagle CAD находятся в директории eagle_files/m2Board/ .
Необходимые библиотеки в eagle_files/lib/ .

Для выносного модуля понадобится:

Part Value Device Package Library Sheet
IC2 КР293КП4А DIL08 ic-package 1
IC3 КР293КП4А DIL08 ic-package 1
IN PINHD-1X6 1X06 pinhead 1
OUT PINHD-1X6 1X06 pinhead 1
R1 450Ω или 470Ω R-EU_0204/5 0204/5 resistor 1
R2 450Ω или 470Ω R-EU_0204/5 0204/5 resistor 1
R3 330Ω R-EU_0204/5 0204/5 resistor 1
TO_MCU PINHD-1X5 1X05 pinhead 1

По-поводу R1 и R2 резисторов, я собрал две пары, чтобы получилось 450 Ом в каждой. Думаю, что если взять просто пару штук на 470 Ом всё тоже будет работать. Но всё же обещать не буду.

Его принципиальная схема выглядит весьма просто:

Разводка выполняется на односторонней плате:


* 'cuz soviet works better
Если присмотреться, разводка слегка отличается от той, что приведена на первом рисунке. Тут я убрал перемычку.

Как вы уже поняли, в качестве оптопар используется отечественная схема КР293КП4А в корпусе DIP8. Внутри каждой микросхемы находится 2 оптопары. Одна из схем замыкает и размыкает кнопки (питание и сброс), а вторая говорит микроконтроллеру включена ли система, определяя это по светодиоду-индикатору питания. Если первую микросхему замыкает МК, то вторую — ПК. Через отдельный пин микроконтроллер зажигает индикатор питания сам, когда понимает, что и система (ПК) тоже его зажгла. Уж не знаю.. может это несколько избыточно и можно было сделать проще. Впрочем, получилось как получилось.

Примечание: наверное надо было навесить на вторую оптопару какие-то резисторы.. но блин, datasheet по ним такой немногословный. В общем как-то работает уже больше года, так что, пока всё не сгорело, имеет право на жизнь.

Если всё спаять и приправить должным количеством пыли, получится примерно следующее:


Про программирование Arduino

Теперь перейдём к программированию Arduino. Как говорилось ранее, предполагается использование Arduino Nano.
Я уже не помню что куда нажимать и подключать, чтобы это дело прошить но у меня есть скетч!
Для этого скетча понадобится библиотека ehtercard. И скетч и библиотека находятся в директории arduino_sketchbook/.

А вот и сам код:
#include <EtherCard.h>

#define PWR_PIN 6
#define RST_PIN 7
#define PWR_LED_IN 8
#define PWR_LED_OUT 5


int i;
// Зададим MAC адрес устройства
static byte mymac[] = { 0xDE,0xAD,0xBE,0xEE,0xEE,0xEF };
 
// Чем больше данных отображается на странице, тем больше требуется буфер для них
byte Ethernet::buffer[900];
BufferFiller bfill;
 
//Массив задействованных контактов для управления оптопарами
int LedPins[] = {PWR_PIN,RST_PIN};
 
//Массив для фиксации изменений
boolean PinUpdate = 0;      //100-reset 200-power 5050-powerOFF
 
const char http_OK[] PROGMEM =
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n\r\n"
"\r\n"
"<html>"
  "<head><title>"
    "noWOL"
  "</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><style>"
  "body { font-family: monospace;\n"
   "background-color: #000000;\n"
   "font-size: 30px;\n"
   "font-weight: bold;\n"
   "color: #b2b2b2;}\n"
   "a:link, a:visited {  display: inline-block;\n"
  "color: #b2b2b2;\n"
  "font-weight: 700;\n"
  "text-decoration: none;\n"
  "padding: .3em 2em;\n"
  "outline: none;\n"
  "border: 2px solid;\n"
  "border-radius: 15px;\n"
  "transition: 0.2s;}\n"
  "a:hover {color: #fefefe;}\n"
  "</style></head>"
  "<body><center>"
;
const char http_Found[] PROGMEM =
"HTTP/1.0 302 Found\r\n"
"Location: /\r\n\r\n";

const char http_Unauthorized[] PROGMEM =
"HTTP/1.0 401 Unauthorized\r\n"
"Content-Type: text/html\r\n\r\n"
"401 Unauthorized";
 
void homePage()
{
bfill.emit_p(PSTR("$F"
  " "
  "$F<p>"
  "<a href='?RESET=on'>  RESET   </a><p>"  //D6
  "<a href='?POWER0=on'>  POWER   </a><p>" //D7 short
  "<a href='?POWER1=on'>POWER 5sec</a><br />"),  //D7 long
  //"PWR LED out D5 : $F <br /></body></html>"),
  
  http_OK,
  (digitalRead(PWR_LED_IN) == HIGH)?PSTR("<span style=\"color: #AA0000\">          ▄▄▄▄▄▄</span>"):PSTR("<span style=\"color: #00c600\">          ▄▄▄▄▄▄</span>")),//⬤
//  (bitRead(PORTD,PWR_LED_OUT) == HIGH)?PSTR("HIGH"):PSTR("LOW")),

"</center></body>"
"</html>"
  ;
}

void pick_pin(int pin, int del) {
      digitalWrite(pin,HIGH);
        delay(del);
        digitalWrite(pin,LOW);
        PinUpdate = 0;
}
 
void setup()
{
// SET UART
//  Serial.begin(9600);
//Change default ethercard CS - pin 8 to 10
  //if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0)

//  Serial.println( "Access to Ethernet controller failed");
    ether.begin(sizeof Ethernet::buffer, mymac, 10);
    ether.dhcpSetup();
//  if (!ether.dhcpSetup())
//       Serial.println("DHCP routine failed");
    //Print over UART configuration recieved:
//  ether.printIp("IP:  ", ether.myip);          
//  ether.printIp("GW:  ", ether.gwip);  
//  ether.printIp("DNS: ", ether.dnsip);  

  for(i = 0; i < 2; i++) {
    pinMode(LedPins[i],OUTPUT);
  }
  
    pinMode(PWR_LED_OUT,OUTPUT);
    pinMode(PWR_LED_IN,INPUT_PULLUP); // LED-питания как вход
}
 
void loop()
{
    delay(1);

        if (digitalRead(PWR_LED_IN) == HIGH) {        // если мать выключена
            if (bitRead(PORTD,PWR_LED_OUT) == HIGH) digitalWrite(PWR_LED_OUT,LOW);
        }
        else if (bitRead(PORTD,PWR_LED_OUT) == LOW) {
          digitalWrite(PWR_LED_OUT,HIGH);
        }

        switch (PinUpdate) {
          case 0:
            break;
          case 1:
            pick_pin(RST_PIN, 200);
            break;
          case 2:
            pick_pin(PWR_PIN, 200);
            break;
          case 3:
            pick_pin(PWR_PIN, 5050);
            break;
        }

    word len = ether.packetReceive(); //Проверить ethernet пакеты
    word pos = ether.packetLoop(len); //Проверить TCP пакеты
    if (pos) {
        bfill = ether.tcpOffset();
        char *data = (char *) Ethernet::buffer + pos;
        if (strncmp("GET /", data, 5) != 0) {
            bfill.emit_p(http_Unauthorized);
        }
        else {
            data += 5;
            if (data[0] == ' ') {
                    homePage(); //Если обнаружено изменения на станице, то запускаем функцию
            }
            //"10" = количество символов "?RESET=on ".
            else if (strncmp("?RESET=on ", data, 10) == 0) {
                bfill.emit_p(http_Found);
                                PinUpdate = 1;
            }
 
            else if (strncmp("?POWER0=on ", data, 11) == 0) {
                  bfill.emit_p(http_Found);
                                PinUpdate = 2;
            }
 
            else if (strncmp("?POWER1=on ", data, 11) == 0) {
                    bfill.emit_p(http_Found);
                                PinUpdate = 3;
            }

            else {
                //Страница не найдена
                bfill.emit_p(http_Unauthorized);
            }
        }
        ether.httpServerReply(bfill.position());
    }
}
Теперь, когда всё что надо прошито, соединяем как указано на рисунке в начале публикации и подключаем это дело к сети. На машрутизаторе должен быть настроен DHCP сервер.
Мак-адрес нового устройства, как ясно из исходного кода, будет de:ad:be:ee:ee:ef. Лучше сразу назначить постоянную аренду. В OpenWRT с LuCI идём в:
«Сеть» → «DHCP и DNS» → вкладка «Основные настройки» → «Постоянные аренды» → «Добавить».
Пишем там как показано на рисунке:


Когда всё настроено и подключено, заходим на адрес http://192.168.1.100 и видим следующее:


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

То, что всё это находится в интрасети и не отсвечивает в мир меня вполне устраивает, ведь при подключении по VPN доступ появляется и в Android-приложении и через WEB-интерфейс. Ах да! Для всего этого дела есть ещё и Android-приложение :) Но о нём во второй части.

Вредные советы

Как бы не использовать Arduino?

Лучше таки его использовать.
Но можно и спаять свою ардуину, с блекджеком и профусетками, чтобы она была поменьше и конкретно под этот проект.
Сразу оговорюсь, я наделал кучу ошибок и паял отдельные костыли чтобы всё сошлось.. потом переделал схему, потом ещё пару раз, и уже не помню на сколько там правильная разводка. Так что лучше внимательно изучить и прислать мне фидбек в виде линки на исправленную версию. Или апробировать, если всё правильно =)

Используется двусторонний текстолит. Перемычки тут не помогут.

Находится всё в директории eagle_files/atmegaBoard/ .

Список компонентов:

Part Value Device Package Library Sheet
C1 22pF C-EUC0603 C0603 resistor 1
C2 22pF C-EUC0603 C0603 resistor 1
C3 10uF CC0603 C0603 eagle-ltspice 1
C4 22uF CC0603 C0603 eagle-ltspice 1
IC1 atmega328p atmega328p TQFP32-08 avr-6 1
IC3 LM1117IMPX-3.3 LM1117IMPX-3.3 SOT223 lm1117 1
JP1
PINHD-2X5 2X05 pinhead 1
JP3 PINHD-1X2 1X02 pinhead 1
Q1 16MHz XTAL/S QS special 1
SV1 MA05-1 MA05-1 con-lstb 1
U1 USB"" USB-MICRO-SMD MicroUSB 1

Схема принципиальная:


Сама разводка:


Что тут добавить.. земля на гребёнке справа. JP3 нужен для прошивки схемы. Прошивается она через Arduino IDE.. Кажется с помощью самой ардуины. Ну или через USBasp программатор. В общем, главное ничего не перепутать. А настройки должны быть вроде таких:

1)
 

2)


В следующей части будет обзор Android-приложения. APK файл находится в папке Android_APK.

Итого

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



Что касается дальнейшего развития этой инициативы, то я планирую добавить сюда ещё один выносной модуль для ещё одного ПК.

--
Особая благодарность Unyuu за неоценимый вклад. Во многом благодаря его советам этот проект стал возможен.


Лицензия Creative Commons
Текстовый материал распространяется по лицензии Creative Commons С указанием авторства-Некоммерческая-С сохранением условий 4.0 Всемирная.
Обратите внимание: это ограничение не касается графических изображений и исходного кода. Если на самом изображении не указано иного, они доступны по лицензии Creative Commons С указанием авторства 4.0 Всемирная.

20 марта 2016 г.

Делаем IR приёмник для LIRC (igorplugusb)

16:51 Опубликовал Дмитрий Исаенко , , Нет комментариев
Сегодня будем делать инфракрасный приёмник. В таком качестве мною был выбран распространённый igorplugusb — старая, не лишенная недостатков, но очень простая в создании схема. Прекрасный пример реализации я нашел на сайте JumpTruck, который в свою очередь почти без изменений списан с проекта Дика Стрифланда (Dick Streefland). Но не смотря на это, готовые схемы мне не понравились. Мне хотелось micro-usb штекер и миниатюрную плату, поэтому я решил переделать реализацию под себя. 
Для новой разводки был использован бесплатный (условно) Eagle cad, который прекрасно подходит для разработки небольших схем и обладает огромным набором библиотек компонентов. В конечном итоге у меня получилось следующее (кликабельно):



Скачать их, вместе с прошивкой и самую-малость-кривым-PDF для лазерного утюга можно отсюда: https://cloud.mail.ru/public/CH4D/Sw3D5nLh5

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

Если вы в первый раз используете Eagle (у меня это версия 7.4.0), то после установки и первого запуска он предложит вам создать папку по-умолчанию для проектов и всего-такого-прочего. В неё-то и надо скопировать директории IR3 и lib.

Теперь о том, что касается компонентов (нагло содрано):
Комп. Значение Корпус Описание
C1 27pf 0603 Керамический конденсатор
C2 27pf 0603 Керамический конденсатор
C3 0.1uf 0603 Керамический конденсатор
C4 4,7uf 0603 Конденсатор (тут у автора была ошибка - нужен именно 4,7uf)
C5 100uf E2,5-6 Электролит. конденсатор
D1 3,6V SOD80C Стабилитрон 3.6V
D2 3,6V SOD80C Стабилитрон 3.6V
IC1 ATtiny2313 DIL20 ATTINY2313-20PU
LED1 LED3MM 3mm LED (синенький)
Q1 12MHz HC49U70 Кварц
R1 68 0805 (или 0603) 68Ом резистор
R2 1k5 0603 1,5КОм резистор
R3 68 0805 (или 0603) 68Ом резистор
R4 330 0603 330Ом резистор
R5 22k 0603 22КОм резистор
R6 100 0603 100Ом резистор
R7 4,7КОм 0603 4,7КОм резистор
U$1 TSOP4838 782-TSOP4838 IR приёмник 38kHz
X1 Micro-usb USB-MICRO-SMD micro-usb разъём

Теперь несколько слов о прошивке. Я использовал, как и Jumptruck, прошивку main.hex из папки IR из пакета 1,4. Сейчас на сайте доступен для скачивания архив 1.7 — что там внутри и как оно работает я не знаю. Если есть желание проверить, то пожалуйста.

Прошивал я своим программатором usbasp через avrdude. Тут проблем у вас возникнуть не должно. Как настроить окружение я писал в одной из предыдущих публикаций. Тут же традиционно показываю выкладку:
 # avrdude -c usbasp -pt2313 -U flash:w:main.hex                     

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e910a
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "main.hex"
avrdude: input file main.hex auto detected as Intel Hex
avrdude: writing flash (2006 bytes):

Writing | ################################################## | 100% 18.64s


avrdude: 2006 bytes of flash written
avrdude: verifying flash memory against main.hex:
avrdude: load data flash data from input file main.hex:
avrdude: input file main.hex auto detected as Intel Hex
avrdude: input file main.hex contains 2006 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 8.66s


avrdude: verifying ...
avrdude: 2006 bytes of flash verified
avrdude: safemode: Fuses OK

avrdude done.  Thank you.

 # avrdude -pt2313 -U hfuse:w:0xdb:m -U lfuse:w:0xef:m -c usbasp

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e910a
avrdude: reading input file "0xdb"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xdb:
avrdude: load data hfuse data from input file 0xdb:
avrdude: input file 0xdb contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0xef"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xef:
avrdude: load data lfuse data from input file 0xef:
avrdude: input file 0xef contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

Перейдём к настройке LIRC. 

Для начала, необходимо правильно сконфигурировать ядро. Для этого включим следующие необходимые фичи через menuconfig.
Device Drivers -> Multimedia Support
  [*]   Remote Controller support
  [*]   Remote controller decoders  ---> 
      <M>   LIRC interface driver
      <M>     Enable IR to LIRC bridge
      <M>   Enable IR raw decoder for the NEC protocol
      <M>   Enable IR raw decoder for the RC-5 protocol
      <M>   Enable IR raw decoder for the RC6 protocol
      <M>   Enable IR raw decoder for the JVC protocol
      <M>   Enable IR raw decoder for the Sony protocol
      <M>   Enable IR raw decoder for the Sanyo protocol
      <M>   Enable IR raw decoder for the Sharp protocol
      <M>   Enable IR raw decoder for the MCE keyboard/mouse protocol
      <M>   Enable IR raw decoder for the XMP protocol
  [*]   Remote Controller devices  --->
         IgorPlug-USB IR Receiver
  Input device support  --->
      <*>   Event interface  (не знаю на сколько это актуально)

После того, как мы настроили ядро и перезагрузились, при подключении устройства в dmesg должно появиться следующее:
[57672.609962] usb 1-5.2: new low-speed USB device number 9 using xhci_hcd
[57672.699435] usb 1-5.2: New USB device found, idVendor=03eb, idProduct=0002
[57672.699438] usb 1-5.2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[57672.699439] usb 1-5.2: Product: USBtiny IR/LCD
[57672.700146] Registered IR keymap rc-hauppauge
[57672.700217] input: IgorPlug-USB IR Receiver as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2:1.0/rc/rc0/input20
[57672.700250] rc0: IgorPlug-USB IR Receiver as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2:1.0/rc/rc0
[57672.700309] input: MCE IR Keyboard/Mouse (igorplugusb) as /devices/virtual/input/input21
[57672.700452] rc rc0: lirc_dev: driver ir-lirc-codec (igorplugusb) registered at minor = 0
Соответсвенно в /dev теперь есть устройство /dev/lirc0.

Теперь самое интересное - заставить всё это дело работать. Версия lirc-0.9.0-r5, которая есть сейчас в portage безумно устарела и, строго говоря, не работает. Поэтому я решил написать ebuild для более свежей, но не последней версии 0.9.3a.

Вот выкладка:
$ cat lirc-0.9.3a.ebuild    
# Copyright 1999-2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

EAPI=4

inherit eutils systemd flag-o-matic autotools

DESCRIPTION="decode and send infra-red signals of many commonly used remote controls"
HOMEPAGE="http://www.lirc.org/"

MY_P=${PN}-${PV/_/}

if [[ "${PV/_pre/}" = "${PV}" ]]; then
        SRC_URI="mirror://sourceforge/lirc/${MY_P}.tar.bz2"
else
        SRC_URI="http://www.lirc.org/software/snapshots/${MY_P}.tar.bz2"
fi

LICENSE="GPL-2"
SLOT="0"
KEYWORDS="amd64 ppc ppc64 x86"
IUSE="doc static-libs X audio irman ftdi inputlirc iguanair"

S="${WORKDIR}/${MY_P}"


REQUIRED_USE="
        iguanair? ( irman )
"
DEPEND="
        doc? ( app-doc/doxygen )
"

RDEPEND="
        X? (
                x11-libs/libX11
                x11-libs/libSM
                x11-libs/libICE
        )
        audio? ( 
                >media-libs/portaudio-18 
                media-libs/alsa-lib
        )
        irman? ( media-libs/libirman )

        iguanair? ( app-misc/iguanaIR )

        ftdi? ( dev-embedded/libftdi:0 )

        inputlirc? ( app-misc/inputlircd )
"

pkg_setup() {

        # set default configure options
        LIRC_DRIVER_DEVICE="/dev/lirc0"

        filter-flags -Wl,-O1
}

src_prepare() {
        # Rip out dos CRLF
        edos2unix contrib/lirc.rules
}

src_configure() {
        econf \
                $(use_enable static-libs static) \
                $(use_with X x)
}


src_install() {
        emake DESTDIR="${D}" install

        newinitd "${FILESDIR}"/lircd lircd
        newinitd "${FILESDIR}"/lircmd lircmd
        newconfd "${FILESDIR}"/lircd.conf.4 lircd

        insinto /etc/modprobe.d/
        newins "${FILESDIR}"/modprobed.lirc lirc.conf

        newinitd "${FILESDIR}"/irexec-initd irexec
        newconfd "${FILESDIR}"/irexec-confd irexec

        systemd_dounit "${FILESDIR}"/irexec.service
        systemd_dounit "${FILESDIR}"/lirc.service
        systemd_dounit "${FILESDIR}"/lircm.service

        if use doc ; then
                dohtml doc/html/*.html
                insinto /usr/share/doc/${PF}/images
                doins doc/images/*
        fi

        keepdir /etc/lirc
        if [[ -e "${D}"/etc/lirc/lircd.conf ]]; then
                newdoc "${D}"/etc/lirc/lircd.conf lircd.conf.example
        fi

        use static-libs || rm "${D}/usr/$(get_libdir)/liblirc_client.la"
}

pkg_preinst() {

        local dir="${EROOT}/etc/modprobe.d"
        if [[ -a "${dir}"/lirc && ! -a "${dir}"/lirc.conf ]]; then
                elog "Renaming ${dir}/lirc to lirc.conf"
                mv -f "${dir}/lirc" "${dir}/lirc.conf"
        fi

        # copy the first file that can be found
        if [[ -f "${EROOT}"/etc/lirc/lircd.conf ]]; then
                cp "${EROOT}"/etc/lirc/lircd.conf "${T}"/lircd.conf
        elif [[ -f "${EROOT}"/etc/lircd.conf ]]; then
                cp "${EROOT}"/etc/lircd.conf "${T}"/lircd.conf
                MOVE_OLD_LIRCD_CONF=1
        elif [[ -f "${D}"/etc/lirc/lircd.conf ]]; then
                cp "${D}"/etc/lirc/lircd.conf "${T}"/lircd.conf
        fi

        # stop portage from touching the config file
        if [[ -e "${D}"/etc/lirc/lircd.conf ]]; then
                rm -f "${D}"/etc/lirc/lircd.conf
        fi

}

pkg_postinst() {

        # copy config file to new location
        # without portage knowing about it
        # so it will not delete it on unmerge or ever touch it again
        if [[ -e "${T}"/lircd.conf ]]; then
                cp "${T}"/lircd.conf "${EROOT}"/etc/lirc/lircd.conf
                if [[ "$MOVE_OLD_LIRCD_CONF" = "1" ]]; then
                        elog "Moved /etc/lircd.conf to /etc/lirc/lircd.conf"
                        rm -f "${EROOT}"/etc/lircd.conf
                fi
        fi

        einfo "The new default location for lircd.conf is inside of"
        einfo "/etc/lirc/ directory"
}

Ну и листинги всего остального, что есть в папке (чего уж мелочиться):
$ ls 
files  lirc-0.9.3a.ebuild  Manifest  metadata.xml

$ cat metadata.xml 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
  <maintainer type="project">
    <email></email>
  </maintainer>
  <use>
    <flag name="audio">Build alsa-lib and portaudio required for some receivers</flag>
    <flag name="ftdi">Build libftdi required by FTDI driver</flag>
    <flag name="iguanair">Build libiguanair required by iguanaIR</flag>
    <flag name="inputlirc">Build inputlirc</flag>
    <flag name="irman">Build libirman required by Irman</flag>
  </use>
</pkgmetadata>
$ cat files/irexec-confd
# Options to pass to the irexec process
IREXEC_OPTS="/etc/lircrc"

# User to execute irexec as.
# Warning: Running irexec as root can open security holes
#IREXEC_USER="root"

# Use this to disable the warning printed when starting irexec as root
# IREXEC_DISABLE_ROOT_WARNING=yes 
$ cat files/irexec-initd 
#!/sbin/runscript
# Copyright 2003 Martin Hierling <mad@cc.fh-lippe.de>
# Distributed under the terms of the GNU General Public License v2
# $Id$

: ${IREXEC_USER:=root}

depend() {
        need lirc
}

start() {
        if [ "x${IREXEC_USER}" = "xroot" -a "x${IREXEC_DISABLE_ROOT_WARNING}" != "xyes" ]; then
                ewarn "Warning: Running irexec as root can open security holes"
        fi

        ebegin "Starting irexec"
        start-stop-daemon --start --chuid ${IREXEC_USER} --user ${IREXEC_USER} --chdir / \
                --exec /usr/bin/irexec -- --daemon ${IREXEC_OPTS}
        eend $? "Failed to start irexec."
}

stop() {
        ebegin "Stopping irexec"
        start-stop-daemon --stop --exec /usr/bin/irexec --user ${IREXEC_USER}
        eend $? "Failed to stop irexec."
}
 $ cat files/irexec.service 
[Unit]
Description=IR Exec
After=lirc.service
Wants=lirc.service

[Service]
ExecStart=/usr/bin/irexec

[Install]
WantedBy=multi-user.target
$ cat files/lircd
#!/sbin/runscript
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

PIDFILE=/var/run/lirc/${SVCNAME}.pid
: ${LIRCD_SYMLINKFILE:=/dev/lircd}
: ${LIRCD_SOCKET:=/var/run/lirc/lircd}

depend() {
        need localmount
        use modules
        provide lirc
}

start() {
        local retval

        ebegin "Starting lircd"

        for retval in ${LIRCD_SET_SYSCLASSRCS} ; do
                if [ -e /sys/class/rc/${retval}/protocols ] && \
                grep -qs 'lirc' /sys/class/rc/${retval}/protocols ; then
                        einfo "Setting lirc protocol active for ${retval}"
                        echo lirc >/sys/class/rc/${retval}/protocols
                fi
        done

        checkpath -q -d -m 0755 -o root:root /var/run/lirc
        rm -Rf ${LIRCD_SOCKET} && ln -s ${LIRCD_SOCKET} ${LIRCD_SYMLINKFILE}
        if [ $? -ne 0 ]; then
                eend $? "Unable to create symbolic link ${LIRCD_SYMLINKFILE}"
                return 1
        fi

        start-stop-daemon --start --quiet --pidfile "${PIDFILE}" --exec /usr/sbin/lircd -- \
                -P "${PIDFILE}" ${LIRCD_OPTS}
        retval=$?

        if [ ${retval} -ne 0 ]; then
                rm -Rf ${LIRCD_SOCKET}
        fi

        eend ${retval}
}

stop() {
        ebegin "Stopping lircd"
        rm -f ${LIRCD_SYMLINKFILE}
        start-stop-daemon --stop --quiet --pidfile "${PIDFILE}" --exec /usr/sbin/lircd
        eend $?
}
 $ cat files/lircd.conf.4 
# Options to pass to the lircd process

# for devices with lirc-kernel-module
#LIRCD_OPTS="-d /dev/lirc0"
#LIRCD_OPTS="-d /dev/lirc"

# for devices using the input-layer
#LIRCD_OPTS="-H devinput -d /dev/input/by-path/pci-0000:00:0a.0--event-ir"
# This should work, Bug #235107
#LIRCD_OPTS="-H devinput -d name=*DVB*"

# set default protocol to 'lirc' for in-kernel IR decoding
# for the following entries in /sys/class/rc/
# (space-separated list if there is more than one)
LIRCD_SET_SYSCLASSRCS="rc0"

# If running mulitple instances of lircd, the following
# can be used to override the default socket path and
# socket symlink
#LIRCD_SOCKET="/var/run/lirc/lircd"
#LIRCD_SYMLINKFILE="/dev/lircd"
$ cat files/lircmd 
#!/sbin/runscript
# Copyright 1999-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

depend() {
        need lircd
}

start() {
        ebegin "Starting lircmd"
        start-stop-daemon --start --quiet --exec /usr/sbin/lircmd
        eend $?
}

stop() {
        ebegin "Stopping lircmd"
        start-stop-daemon --stop --quiet --exec /usr/sbin/lircmd
        eend $?
}
$ cat files/lirc.service 
[Unit]
Description=Linux Infrared Remote Control
After=network.target

[Service]
ExecStart=/usr/sbin/lircd --nodaemon --driver=default --device=/dev/lirc0

[Install]
WantedBy=multi-user.target
$ cat files/modprobed.lirc 
#
# For first serial receivers:
#
#options lirc_serial irq=4 io=0x3f8
#options lirc_sir irq=4 io=0x3f8

#
# Detach first serial port from serial-driver.
# Use this when you have your serial-port-driver statically
# compiled into your kernel, or as a module but loaded before
# the lirc-module.
# 
#install lirc_serial setserial /dev/ttyS0 uart none; modprobe --ignore-install lirc_serial
#
#install lirc_sir    setserial /dev/ttyS0 uart none; modprobe --ignore-install lirc_sir


#
# For parallel receivers:
#
#options lirc_parallel irq=7 io=0x3bc

Таким образом, всё что вам нужно сделать - так это добавить ебилд в локальный репозиторий, выполнить repoman manifest и установить пакет.
# emerge lirc

Скачать zip можно отсюда: https://cloud.mail.ru/public/2Mdy/yGnm7BVgX
Да, я тут подумал, что так жить нельзя, и решил завести себе аккаунт на GitHub. Так что теперь ебилды можно будет качать и отсюда: https://github.com/developersu/loperOverlay

Теперь добавим демон lircd в автозагрузку:
# rc-update add lircd default
И запустим его:
# /etc/init.d/lircd start
 * Starting lircd ...
 * Setting lirc protocol active for rc0        [ ok ]
Проверить, что всё работает как надо можно коммандой mode2. Когда она запущена нужно поклацать пультом и диод замигает, а в консоли вы увидите примерно следующее:
# mode2 
Using device: /dev/lirc0
Using device: /dev/lirc0
Warning: Running as root.
pulse 9045
space 4607
pulse 511
space 1706
pulse 511
space 597
pulse 597
space 511
pulse 597
space 511
pulse 597
space 511
pulse 597
space 597
pulse 597
space 511
pulse 597
space 511
pulse 597
space 511
pulse 597
space 1621
pulse 682
space 1706
pulse 597
space 511
pulse 597
space 597
pulse 597
space 1706
pulse 597
space 1706
pulse 597
space 1621
pulse 682


О том, как настроить конкретный пульт для управление системой в KDE мы поговорим в следующий раз.

На этом у меня всё.

Источники:
https://dicks.home.xs4all.nl/avr/usbtiny/
http://jumptuck.com/2008/10/26/usb-ir-receiver/
http://gentoo-en.vfose.ru/wiki/LIRC

14 февраля 2016 г.

Crossdev окружение для AVR

18:43 Опубликовал Дмитрий Исаенко , , Нет комментариев
Сегодня хочется поговорить о том, как настроить crossdev окружение в Gentoo, которое необходимо для компиляции под микроконтроллеры AVR. По аналогичной схеме собираются тулчейны и для других популярных архитектур, к примеру MIPS или различных веток ARM.

Перед началом работы размаскируем последнюю версию crossdev и установим её:
# echo "sys-devel/crossdev ~amd64" >>  /etc/portage/package.accept_keywords
Теперь создадим и настроим отдельный оверлей, для пакетов crossdev.
# mkdir /usr/local/crossdev-overlay
# cd /usr/local/crossdev-overlay
# mkdir -p /usr/local/crossdev-overlay/{profiles,metadata}
# echo 'crossdevLocalOverlay' > profiles/repo_name
# vim metadata/layout.conf
masters = gentoo
thin-manifests = true
# chown  -R portage:portage /usr/local/crossdev-overlay
Также следует описать оверлей в repos.conf:
# vim /etc/portage/repos.conf/crossdev.conf
[crossdevLocalOverlay]
location = /usr/local/crossdev-overlay
priority = 10
masters = gentoo
auto-sync = no
Тут есть один важный нюанс. Если у нас в системе уже был один локальный оверлей, а для crossdev мы хотим использовать отдельный, то следует существующему оверлею назначить более высокий приоритет. Сделать это можно изменив его настройки там же, в директории repos.conf. В моём случае это выглядело так:
#echo 'priority = 13' >> /etc/portage/repos.conf/local.conf
Соберём окружение для AVR, явно указав версии необходимого нам ПО. У меня всё заработало со следующими параметрами GCC, binutils и libc:
USE="multilib -cxx" crossdev --g 4.6.2 --b 2.21.1-r1 --l 1.7.0 -S -s1 --target avr
USE="multilib cxx" crossdev --g 4.6.2 --b 2.21.1-r1 --l 1.7.0 -S -s4 --target avr 
Если не вышло, можно попробовать проще:
crossdev -s4 --stable --portage --verbose --target avr
Теперь нужно создать ссылку на ldscripts, иначе ничего не соберётся (эта проблема существует уже лет 6, но никто не шевелится её исправлять):
ln -s /usr/x86_64-pc-linux-gnu/avr/lib/ldscripts/ /usr/avr/lib/ldscripts
Осталось установить avrdude:
# emerge avrdude
Попробуем помирать диодиком на PC5:
# vim me.cpp
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>

void sleep(uint8_t millisec)
{
        while(millisec)
        {
              _delay_ms(1);
                millisec--;
        }
}

int main(void)
{
while (1) {

DDRC |=1<<PC5;
               PORTC &= ~(1<<PC5);
               sleep(100);

               PORTC |=(1<<PC5);
               sleep(100);
}
}
Теперь скомпилируем и прошьём (я использую программатрор от Thomas Fischl).
# avr-gcc  -O2 -mmcu=atmega8  me.cpp -o me.elf
# avr-objcopy -O ihex me.elf me.hex
# avrdude -c usbasp -p m8 -U hfuse:w:0xd9:m -U lfuse:w:0xe1:m
# avrdude -c usbasp -p m8 -U flash:w:me.hex:i
Вот и всё. Схему приводить тут не вижу смысла, но если кому интересно — смотрите на иконку к этой публикации. Удачи!


Полезные ссылки:
https://wiki.gentoo.org/wiki/Overlay/Local_overlay
http://gentoo-en.vfose.ru/wiki/Crossdev