diff --git a/ChangeLog b/ChangeLog index 4eee4820..03d1b779 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15487,3 +15487,6 @@ 2016-10-20 Fred Gleason * Added a 'LockRdairplayMemory=' parameter to the [Hacks] section of rd.conf(5). +2016-11-26 Fred Gleason + * Modified the LiveWire Multicast GPIO driver to generate GPO + events using the 'I' event type. diff --git a/ripcd/livewire_mcastgpio.cpp b/ripcd/livewire_mcastgpio.cpp index ac3a6226..f0bcd869 100644 --- a/ripcd/livewire_mcastgpio.cpp +++ b/ripcd/livewire_mcastgpio.cpp @@ -70,15 +70,26 @@ LiveWireMcastGpio::LiveWireMcastGpio(RDMatrix *matrix,QObject *parent) connect(livewire_gpi_timers.back(),SIGNAL(timeout()), livewire_gpi_timer_mapper,SLOT(map())); } - livewire_gpo_timer_mapper=new QSignalMapper(this); - connect(livewire_gpo_timer_mapper,SIGNAL(mapped(int)), - this,SLOT(gpoTimeoutData(int))); + livewire_gpo_out_timer_mapper=new QSignalMapper(this); + connect(livewire_gpo_out_timer_mapper,SIGNAL(mapped(int)), + this,SLOT(gpoOutTimeoutData(int))); for(unsigned i=0;isetMapping(livewire_gpo_timers.back(),i); - connect(livewire_gpo_timers.back(),SIGNAL(timeout()), - livewire_gpo_timer_mapper,SLOT(map())); - livewire_gpo_states.push_back(false); + livewire_gpo_out_timers.push_back(new QTimer(this)); + livewire_gpo_out_timer_mapper->setMapping(livewire_gpo_out_timers.back(),i); + connect(livewire_gpo_out_timers.back(),SIGNAL(timeout()), + livewire_gpo_out_timer_mapper,SLOT(map())); + livewire_gpo_out_states.push_back(false); + } + + livewire_gpo_in_timer_mapper=new QSignalMapper(this); + connect(livewire_gpo_in_timer_mapper,SIGNAL(mapped(int)), + this,SLOT(gpoInTimeoutData(int))); + for(unsigned i=0;isetMapping(livewire_gpo_in_timers.back(),i); + connect(livewire_gpo_in_timers.back(),SIGNAL(timeout()), + livewire_gpo_in_timer_mapper,SLOT(map())); + livewire_gpo_in_states.push_back(false); } // @@ -150,8 +161,11 @@ LiveWireMcastGpio::~LiveWireMcastGpio() for(unsigned i=0;iarg(1).toString().lower()=="i") { + slot=(cmd->arg(2).toInt()-1)/5; + line=(cmd->arg(2).toInt()-1)%5; + if(livewire_source_numbers[slot]<=0) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + return; + } + if(cmd->arg(4).toInt()>0) { + livewire_gpo_in_timers[cmd->arg(2).toInt()-1]-> + start(cmd->arg(4).toInt(),true); + } + ProcessGpoIn(livewire_source_numbers[slot],line,cmd->arg(3).toInt()); + livewire_gpo_in_states[cmd->arg(2).toInt()-1]=cmd->arg(3).toInt(); + /* emit gpiChanged(livewire_matrix,cmd->arg(2).toInt()-1, cmd->arg(3).toInt()); if(cmd->arg(4).toInt()>0) { livewire_gpi_timers[cmd->arg(2).toInt()-1]-> start(cmd->arg(4).toInt(),true); } + */ } if(cmd->arg(1).toString().lower()=="o") { slot=(cmd->arg(2).toInt()-1)/5; @@ -220,11 +249,11 @@ void LiveWireMcastGpio::processCommand(RDMacro *cmd) return; } if(cmd->arg(4).toInt()>0) { - livewire_gpo_timers[cmd->arg(2).toInt()-1]-> + livewire_gpo_out_timers[cmd->arg(2).toInt()-1]-> start(cmd->arg(4).toInt(),true); } - ProcessGpo(livewire_source_numbers[slot],line,cmd->arg(3).toInt()); - livewire_gpo_states[cmd->arg(2).toInt()-1]=cmd->arg(3).toInt(); + ProcessGpoOut(livewire_source_numbers[slot],line,cmd->arg(3).toInt()); + livewire_gpo_out_states[cmd->arg(2).toInt()-1]=cmd->arg(3).toInt(); } cmd->acknowledge(true); emit rmlEcho(cmd); @@ -266,14 +295,26 @@ void LiveWireMcastGpio::gpiTimeoutData(int gpi) } -void LiveWireMcastGpio::gpoTimeoutData(int gpo) +void LiveWireMcastGpio::gpoInTimeoutData(int gpo) { int slot=gpo/5; int line=gpo%5; if(livewire_source_numbers[slot]>0) { - ProcessGpo(livewire_source_numbers[slot],line,!livewire_gpo_states[gpo]); - livewire_gpo_states[gpo]=!livewire_gpo_states[gpo]; + ProcessGpoIn(livewire_source_numbers[slot],line,!livewire_gpo_in_states[gpo]); + livewire_gpo_in_states[gpo]=!livewire_gpo_in_states[gpo]; + } +} + + +void LiveWireMcastGpio::gpoOutTimeoutData(int gpo) +{ + int slot=gpo/5; + int line=gpo%5; + + if(livewire_source_numbers[slot]>0) { + ProcessGpoOut(livewire_source_numbers[slot],line,!livewire_gpo_out_states[gpo]); + livewire_gpo_out_states[gpo]=!livewire_gpo_out_states[gpo]; } } @@ -296,7 +337,54 @@ void LiveWireMcastGpio::ProcessGpi(const QHostAddress &src_addr,int chan, } -void LiveWireMcastGpio::ProcessGpo(int chan,unsigned line,bool state) +void LiveWireMcastGpio::ProcessGpoIn(int chan,unsigned line,bool state) +{ + // + // Destination Address + // + struct sockaddr_in sa; + memset(&sa,0,sizeof(sa)); + sa.sin_family=AF_INET; + sa.sin_port=htons(RD_LIVEWIRE_GPIO_RECV_PORT); + sa.sin_addr.s_addr= + htonl(QHostAddress(RD_LIVEWIRE_GPIO_MCAST_ADDR).toIPv4Address()); + + uint8_t data[60]={0x03,0x00,0x02,0x07,0x36,0x0B,0x97,0xA9, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 'W','R','N','I',0x00,0x04,0x00,0x03,0xF6, + 0x05,0x07,0xCA,0xFF,0xFF,0xFF,0xFD,0x07, + 0x01,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x02, + 0x15,0x07,0x00,0x12,0x00,0x8F,0xFF,0xFF, + 0xFF,0xFF,0x09,0x00,0x02,0x15,0x07,0x00, + 0x00,0x00,0x8F}; + data[4]=0xFF&(livewire_gpio_send_serial>>24); + data[5]=0xFF&(livewire_gpio_send_serial>>16); + data[6]=0xFF&(livewire_gpio_send_serial>>8); + data[7]=0xFF&livewire_gpio_send_serial; + data[23]=0xFF&(chan>>8); + data[24]=0xFF&chan; + data[25]=0x08-(0x07&line); + if(state) { + data[27]|=0x40; + } + else { + data[27]&=~0x40; + } + data[27]&=~0x0A; // No pulse + sendto(livewire_gpio_write_socket,data,28,MSG_DONTWAIT, + (struct sockaddr *)(&sa),sizeof(sa)); + livewire_gpio_send_serial++; + data[4]=0xFF&(livewire_gpio_send_serial>>24); + data[5]=0xFF&(livewire_gpio_send_serial>>16); + data[6]=0xFF&(livewire_gpio_send_serial>>8); + data[7]=0xFF&livewire_gpio_send_serial; + sendto(livewire_gpio_write_socket,data,60,MSG_DONTWAIT, + (struct sockaddr *)(&sa),sizeof(sa)); + livewire_gpio_send_serial++; +} + + +void LiveWireMcastGpio::ProcessGpoOut(int chan,unsigned line,bool state) { // // Destination Address diff --git a/ripcd/livewire_mcastgpio.h b/ripcd/livewire_mcastgpio.h index 7707fa22..fe4e2f09 100644 --- a/ripcd/livewire_mcastgpio.h +++ b/ripcd/livewire_mcastgpio.h @@ -57,12 +57,14 @@ class LiveWireMcastGpio : public Switcher private slots: void gpioActivatedData(int sock); void gpiTimeoutData(int gpo); - void gpoTimeoutData(int gpo); + void gpoInTimeoutData(int gpo); + void gpoOutTimeoutData(int gpo); private: void ProcessGpi(const QHostAddress &src_addr,int chan,unsigned line, bool state,bool pulse); - void ProcessGpo(int chan,unsigned line,bool state); + void ProcessGpoIn(int chan,unsigned line,bool state); + void ProcessGpoOut(int chan,unsigned line,bool state); QString AddressString(uint32_t addr) const; void subscribe(const QHostAddress &addr) const; void subscribe(const uint32_t addr) const; @@ -81,9 +83,12 @@ class LiveWireMcastGpio : public Switcher std::map livewire_gpio_recv_serials; QSignalMapper *livewire_gpi_timer_mapper; std::vector livewire_gpi_timers; - QSignalMapper *livewire_gpo_timer_mapper; - std::vector livewire_gpo_timers; - std::vector livewire_gpo_states; + QSignalMapper *livewire_gpo_in_timer_mapper; + std::vector livewire_gpo_in_timers; + std::vector livewire_gpo_in_states; + QSignalMapper *livewire_gpo_out_timer_mapper; + std::vector livewire_gpo_out_timers; + std::vector livewire_gpo_out_states; };