]> git.sesse.net Git - vlc/blob - modules/video_filter/atmo/FnordlichtConnection.cpp
583a1651db2d999a4264b7374fd71e579c5ed1c2
[vlc] / modules / video_filter / atmo / FnordlichtConnection.cpp
1 /*
2  * FnordlichtConnection.h: class to access a FnordlichtLight Hardware
3  * - the description could be found
4  * here: http://github.com/fd0/fnordlicht/raw/master/doc/PROTOCOL
5  *
6  * (C) Kai Lauterbach (klaute at gmail.com)
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  *
22  * $Id$
23  */
24
25
26 #include "AtmoDefs.h"
27 #include "FnordlichtConnection.h"
28
29 #if !defined(_ATMO_VLC_PLUGIN_)
30 # include "FnordlichtConfigDialog.h"
31 #endif
32
33 #include <stdio.h>
34 #include <fcntl.h>
35
36 #if !defined(WIN32)
37 #include <termios.h>
38 #include <unistd.h>
39 #endif
40
41 CFnordlichtConnection::CFnordlichtConnection(CAtmoConfig *cfg)
42         : CAtmoConnection(cfg)
43 {
44         m_hComport = INVALID_HANDLE_VALUE;
45 }
46
47 CFnordlichtConnection::~CFnordlichtConnection()
48 {
49 }
50
51 ATMO_BOOL CFnordlichtConnection::OpenConnection()
52 {
53 #if defined(_ATMO_VLC_PLUGIN_)
54         char *serdevice = m_pAtmoConfig->getSerialDevice();
55         if ( !serdevice )
56                 return ATMO_FALSE;
57 #else
58         int portNummer = m_pAtmoConfig->getComport();
59         m_dwLastWin32Error = 0;
60         if ( portNummer < 1 )
61                 return ATMO_FALSE; // make no real sense;-)
62 #endif
63
64         CloseConnection();
65
66 #if !defined(_ATMO_VLC_PLUGIN_)
67         char serdevice[16];  // com4294967295
68         sprintf(serdevice,"com%d",portNummer);
69 #endif
70
71 #if defined(WIN32)
72
73         m_hComport = CreateFile(serdevice,
74                                         GENERIC_WRITE, 0, NULL,
75                                         OPEN_EXISTING, 0, NULL);
76         if ( m_hComport == INVALID_HANDLE_VALUE )
77         {
78                 // we have a problem here can't open com port...
79                 // somebody else may use it?
80                 // m_dwLastWin32Error = GetLastError();
81                 return ATMO_FALSE;
82         }
83         /* change serial settings (Speed, stopbits etc.) */
84         DCB dcb; // für comport-parameter
85         dcb.DCBlength = sizeof(DCB);
86         GetCommState(m_hComport, &dcb); // ger current serialport settings
87         dcb.BaudRate = 19200;      // set speed
88         dcb.ByteSize = 8;                 // set databits
89         dcb.Parity   = NOPARITY;        // set parity
90         dcb.StopBits = ONESTOPBIT;   // set one stop bit
91         SetCommState(m_hComport, &dcb);    // apply settings
92
93 #else
94
95         int bconst = B19200;
96         m_hComport = open(serdevice,O_RDWR |O_NOCTTY);
97         if ( m_hComport < 0 )
98                 return ATMO_FALSE;
99
100         struct termios tio;
101         memset(&tio,0,sizeof(tio));
102         tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
103         tio.c_iflag = (INPCK | BRKINT);
104         cfsetispeed(&tio, bconst);
105         cfsetospeed(&tio, bconst);
106         if( ! tcsetattr(m_hComport, TCSANOW, &tio) )
107                 tcflush(m_hComport, TCIOFLUSH);
108         else {
109                 // can't change parms
110                 close(m_hComport);
111                 m_hComport = -1;
112                 return false;
113         }
114
115 #endif
116
117         // sync fnordlicht
118         if ( sync() )
119                 // stop fading on all devices
120                 if ( stop(255) )
121                         return true; // fnordlicht initialized...
122
123         return false; // something is going wrong...
124 }
125
126 void CFnordlichtConnection::CloseConnection()
127 {
128         if ( m_hComport != INVALID_HANDLE_VALUE )
129         {
130                 reset(255);
131
132 #if defined(WIN32)
133                 CloseHandle(m_hComport);
134 #else
135                 close(m_hComport);
136 #endif
137                 m_hComport = INVALID_HANDLE_VALUE;
138         }
139 }
140
141 ATMO_BOOL CFnordlichtConnection::isOpen(void)
142 {
143         return (m_hComport != INVALID_HANDLE_VALUE);
144 }
145
146 ATMO_BOOL CFnordlichtConnection::HardwareWhiteAdjust(int global_gamma,
147                                                                                    int global_contrast,
148                                                                                    int contrast_red,
149                                                                                    int contrast_green,
150                                                                                    int contrast_blue,
151                                                                                    int gamma_red,
152                                                                                    int gamma_green,
153                                                                                    int gamma_blue,
154                                                                                    ATMO_BOOL storeToEeprom)
155 {
156         return ATMO_FALSE; //no hardware adjust required
157 }
158
159 /*
160     def fade_rgb(addr, r, g, b, step, delay)
161            $dev.write addr.chr
162            $dev.write "\x01"
163            $dev.write step.chr
164            $dev.write delay.chr
165            $dev.write r.chr
166            $dev.write g.chr
167            $dev.write b.chr
168            $dev.write "\x00\x00\x00\x00\x00"
169            $dev.write "\x00\x00\x00"
170            $dev.flush
171     end
172 */
173 ATMO_BOOL CFnordlichtConnection::SendData(pColorPacket data)
174 {
175         if ( m_hComport == INVALID_HANDLE_VALUE )
176                 return ATMO_FALSE;
177
178         int amount = getAmountFnordlichter();
179         unsigned char buffer[15];
180         memset(&buffer, 0, sizeof(buffer) ); // zero buffer
181         int iBytesWritten;
182
183         Lock();
184
185         buffer[1] = 0x01; // fade to rgb color
186         buffer[2] = 0x80; // in two steps
187         buffer[3] = 0x01; // 1ms pause between steps
188
189         // send all packages to all fnordlicht's
190         for( unsigned char i=0; i < amount; i++ )
191         {
192                 int idx;
193                 if ( m_ChannelAssignment && i < m_NumAssignedChannels )
194                         idx = m_ChannelAssignment[i];
195                 else
196                         idx = -1; // no channel assigned to fnordlicht[i]
197
198                 if( idx >= 0 && idx <= data->numColors )
199                 {
200                         // fnordlicht address equals to a MoMo Channel
201                         buffer[0] = i; // fnordlicht address (0..254, 255 = broadcast)
202                         buffer[4] = data->zone[idx].r;
203                         buffer[5] = data->zone[idx].g;
204                         buffer[6] = data->zone[idx].b;
205                 }
206
207 #if defined(WIN32)
208                 // send to COM-Port
209                 WriteFile( m_hComport, buffer, sizeof(buffer),
210                                         (DWORD*)&iBytesWritten, NULL );
211 #else
212                 iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
213                 tcflush(m_hComport, TCIOFLUSH);
214                 tcdrain(m_hComport); // flush buffer
215 #endif
216
217                 if (iBytesWritten != sizeof(buffer))
218                 {
219                         Unlock();
220                         return ATMO_FALSE; // shouldn't be...
221                 }
222
223         }
224
225         Unlock();
226
227         return ATMO_TRUE;
228 }
229
230
231 ATMO_BOOL CFnordlichtConnection::CreateDefaultMapping(CAtmoChannelAssignment *ca)
232 {
233         if ( !ca )
234                 return ATMO_FALSE;
235         ca->setSize( getAmountFnordlichter() );  // oder 4 ? depending on config!
236         ca->setZoneIndex(0, 0); // Zone 5
237         ca->setZoneIndex(1, 1);
238         ca->setZoneIndex(2, 2);
239         ca->setZoneIndex(3, 3);
240         return ATMO_TRUE;
241 }
242
243 int CFnordlichtConnection::getAmountFnordlichter()
244 {
245    return m_pAtmoConfig->getFnordlicht_Amount();
246 }
247
248 /*
249     def sync(addr = 0)
250            1.upto(15) do
251                   $dev.write "\e"
252            end
253            $dev.write addr.chr
254            $dev.flush
255     end
256 */
257 ATMO_BOOL CFnordlichtConnection::sync(void)
258 {
259         if ( m_hComport == INVALID_HANDLE_VALUE )
260                 return ATMO_FALSE;
261
262         unsigned char buffer[16];
263         int iBytesWritten;
264
265         Lock();
266
267         // fill buffer with 15 escape character
268         memset(&buffer, 0x1b, sizeof(buffer)-1);
269
270         buffer[sizeof(buffer)-1] = 0x00; // append one zero byte
271
272 #if defined(WIN32)
273                 // send to COM-Port
274                 WriteFile( m_hComport, buffer, sizeof(buffer),
275                                         (DWORD*)&iBytesWritten, NULL );
276 #else
277                 iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
278                 tcflush(m_hComport, TCIOFLUSH);
279                 tcdrain(m_hComport); // flush buffer
280 #endif
281
282         Unlock();
283
284         return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
285
286 }
287
288 /*
289     def stop(addr, fading = 1)
290            $dev.write addr.chr
291            $dev.write "\x08"
292            $dev.write fading.chr
293            $dev.write "\x00\x00\x00\x00"
294            $dev.write "\x00\x00\x00\x00\x00"
295            $dev.write "\x00\x00\x00"
296            $dev.flush
297     end
298 */
299 ATMO_BOOL CFnordlichtConnection::stop(unsigned char addr)
300 {
301         if(m_hComport == INVALID_HANDLE_VALUE)
302                 return ATMO_FALSE;
303
304         unsigned char buffer[15];
305         memset(&buffer, 0, sizeof(buffer)); // zero buffer
306         int iBytesWritten;
307
308         Lock();
309
310         buffer[0] = addr; // fnordlicht address (255 = broadcast)
311         buffer[1] = 0x08; // stop command
312         buffer[2] = 1;    // fading
313
314 #if defined(WIN32)
315                 // send to COM-Port
316                 WriteFile( m_hComport, buffer, sizeof(buffer),
317                                         (DWORD*)&iBytesWritten, NULL );
318 #else
319                 iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
320                 tcflush(m_hComport, TCIOFLUSH);
321                 tcdrain(m_hComport); // flush buffer
322 #endif
323
324         Unlock();
325
326         return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
327 }
328
329 /*
330 */
331 ATMO_BOOL CFnordlichtConnection::reset(unsigned char addr)
332 {
333         if(m_hComport == INVALID_HANDLE_VALUE)
334                 return ATMO_FALSE;
335
336         stop(255);
337
338         if ( sync() && start_bootloader(addr) )
339         {
340 #if defined(_ATMO_VLC_PLUGIN_)
341         do_sleep(200000); // wait 200ms
342 #else
343         do_sleep(200); // wait 200ms
344 #endif
345                 if ( sync() && boot_enter_application(addr) )
346                                 return ATMO_TRUE;
347         }
348
349         return ATMO_FALSE;
350 }
351
352 /*
353     def start_bootloader(addr)
354         $dev.write(addr.chr)
355         $dev.write("\x80")
356         $dev.write("\x6b\x56\x27\xfc")
357         $dev.write("\x00\x00\x00\x00\x00\x00\x00\x00\x00")
358         $dev.flush
359     end
360 */
361 ATMO_BOOL CFnordlichtConnection::start_bootloader(unsigned char addr)
362 {
363         if(m_hComport == INVALID_HANDLE_VALUE)
364                 return ATMO_FALSE;
365
366         unsigned char buffer[15];
367         memset(&buffer, 0, sizeof(buffer)); // zero buffer
368         int iBytesWritten;
369
370         Lock();
371
372         buffer[0] = addr; // fnordlicht address (255 = broadcast)
373         buffer[1] = 0x80; // start_bootloader
374         buffer[2] = 0x6b;
375         buffer[3] = 0x56;
376         buffer[4] = 0x27;
377         buffer[5] = 0xfc;
378
379 #if defined(WIN32)
380                 // send to COM-Port
381                 WriteFile( m_hComport, buffer, sizeof(buffer),
382                                         (DWORD*)&iBytesWritten, NULL );
383 #else
384                 iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
385                 tcflush(m_hComport, TCIOFLUSH);
386                 tcdrain(m_hComport); // flush buffer
387 #endif
388
389         Unlock();
390
391         return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
392 }
393
394 /*
395     def boot_enter_application(addr)
396         $dev.write(addr.chr)
397         $dev.write("\x87")
398         $dev.write("\x00"*13)
399         $dev.flush
400     end
401 */
402 ATMO_BOOL CFnordlichtConnection::boot_enter_application(unsigned char addr)
403 {
404         if(m_hComport == INVALID_HANDLE_VALUE)
405                 return ATMO_FALSE;
406
407         unsigned char buffer[15];
408         memset(&buffer, 0, sizeof(buffer)); // zero buffer
409         int iBytesWritten;
410
411         Lock();
412
413         buffer[0] = addr; // fnordlicht address (255 = broadcast)
414         buffer[1] = 0x87; // boot_ender_application command
415
416 #if defined(WIN32)
417                 // send to COM-Port
418                 WriteFile( m_hComport, buffer, sizeof(buffer),
419                                         (DWORD*)&iBytesWritten, NULL );
420 #else
421                 iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
422                 tcflush(m_hComport, TCIOFLUSH);
423                 tcdrain(m_hComport); // flush buffer
424 #endif
425
426         Unlock();
427
428         return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
429 }
430
431 #if !defined(_ATMO_VLC_PLUGIN_)
432
433 char *CFnordlichtConnection::getChannelName(int ch)
434 {
435         char buf[60];
436         if( ch < 0 ) return NULL;
437         if( ch >= getAmountFnordlichter() ) return NULL;
438
439         sprintf(buf,"Number [%d]",ch);
440         return strdup(buf);
441         // sorry asprintf is not defined on Visual Studio :)
442         // return (asprintf(&ret, "Number [%d]", ch) != -1) ? ret : NULL;
443
444 }
445
446 ATMO_BOOL CFnordlichtConnection::ShowConfigDialog(HINSTANCE hInst, HWND parent,
447                                                                                                         CAtmoConfig *cfg)
448 {
449         CFnordlichtConfigDialog *dlg = new CFnordlichtConfigDialog(hInst,
450                                                                                                                                 parent,
451                                                                                                                                 cfg);
452
453         INT_PTR result = dlg->ShowModal();
454
455         delete dlg;
456
457         if(result == IDOK)
458                 return ATMO_TRUE;
459         else
460                 return ATMO_FALSE;
461 }
462
463 #endif
464