Commit 1af1e3b1 authored by Kai Lauterbach's avatar Kai Lauterbach Committed by André Weber
Browse files

atmo: add support for new device fnordlicht

Fnordlicht - is a serial device with up to four channels
- http://github.com/fd0/fnordlicht/raw/master/doc/PROTOCOL
- http://github.com/fd0/fnordlicht/



Signed-off-by: default avatarAndré Weber <atmo@videolan.org>
parent ac3514ed
......@@ -71,6 +71,7 @@ SOURCES_atmo = atmo/atmo.cpp \
atmo/DmxTools.cpp atmo/DmxTools.h \
atmo/AtmoMultiConnection.cpp atmo/AtmoMultiConnection.h \
atmo/MoMoConnection.cpp atmo/MoMoConnection.h \
atmo/FnordlichtConnection.cpp atmo/FnordlichtConnection.h \
atmo/AtmoPacketQueue.cpp atmo/AtmoPacketQueue.h
SOURCES_gradfun = gradfun.c gradfun.h
noinst_HEADERS = filter_picture.h
......
......@@ -44,6 +44,10 @@ CAtmoConfig::CAtmoConfig()
m_AtmoZoneDefCount = -1;
m_DMX_BaseChannels = NULL;
m_chWhiteAdj_Red = NULL;
m_chWhiteAdj_Green = NULL;
m_chWhiteAdj_Blue = NULL;
LoadDefaults();
}
......@@ -59,6 +63,10 @@ CAtmoConfig::~CAtmoConfig() {
m_ZoneDefinitions = NULL;
}
delete []m_chWhiteAdj_Red;
delete []m_chWhiteAdj_Green;
delete []m_chWhiteAdj_Blue;
free( m_DMX_BaseChannels );
#if defined (_ATMO_VLC_PLUGIN_)
......@@ -99,8 +107,6 @@ void CAtmoConfig::LoadDefaults() {
m_UpdateEdgeWeightningFlag = 0;
m_Software_gamma_mode = agcNone;
m_Software_gamma_red = 10;
m_Software_gamma_green = 10;
......@@ -112,6 +118,17 @@ void CAtmoConfig::LoadDefaults() {
m_WhiteAdjustment_Blue = 255;
m_UseSoftwareWhiteAdj = 1;
m_WhiteAdjPerChannel = ATMO_FALSE;
m_chWhiteAdj_Count = 0;
delete []m_chWhiteAdj_Red;
delete []m_chWhiteAdj_Green;
delete []m_chWhiteAdj_Blue;
m_chWhiteAdj_Red = NULL;
m_chWhiteAdj_Green = NULL;
m_chWhiteAdj_Blue = NULL;
m_ColorChanger_iSteps = 50;
m_ColorChanger_iDelay = 25;
......@@ -145,6 +162,7 @@ void CAtmoConfig::LoadDefaults() {
m_LiveView_DisplayNr = 0;
m_LiveView_FrameDelay = 30;
m_LiveView_GDI_FrameRate = 25;
m_LiveView_RowsPerFrame = 0;
m_Hardware_global_gamma = 128;
......@@ -161,6 +179,7 @@ void CAtmoConfig::LoadDefaults() {
m_DMX_RGB_Channels = 5; // so wie atmolight
m_MoMo_Channels = 3; // default momo, there exists also a 4 ch version!
m_Fnordlicht_Amount = 2; // default fnordlicht, there are 2 fnordlicht's!
m_ZonesTopCount = 1;
m_ZonesBottomCount = 1;
......@@ -168,7 +187,6 @@ void CAtmoConfig::LoadDefaults() {
m_ZoneSummary = ATMO_FALSE;
UpdateZoneCount();
clearAllChannelMappings();
m_CurrentChannelAssignment = 0;
CAtmoChannelAssignment *temp = new CAtmoChannelAssignment();
......@@ -201,6 +219,25 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
this->m_WhiteAdjustment_Blue = pAtmoConfigSrc->m_WhiteAdjustment_Blue;
this->m_UseSoftwareWhiteAdj = pAtmoConfigSrc->m_UseSoftwareWhiteAdj;
this->m_WhiteAdjPerChannel = pAtmoConfigSrc->m_WhiteAdjPerChannel;
this->m_chWhiteAdj_Count = pAtmoConfigSrc->m_chWhiteAdj_Count;
delete []m_chWhiteAdj_Red;
delete []m_chWhiteAdj_Green;
delete []m_chWhiteAdj_Blue;
if(m_chWhiteAdj_Count > 0)
{
m_chWhiteAdj_Red = new int[ m_chWhiteAdj_Count ];
m_chWhiteAdj_Green = new int[ m_chWhiteAdj_Count ];
m_chWhiteAdj_Blue = new int[ m_chWhiteAdj_Count ];
memcpy(m_chWhiteAdj_Red, pAtmoConfigSrc->m_chWhiteAdj_Red, sizeof(int) * m_chWhiteAdj_Count);
memcpy(m_chWhiteAdj_Green, pAtmoConfigSrc->m_chWhiteAdj_Green, sizeof(int) * m_chWhiteAdj_Count);
memcpy(m_chWhiteAdj_Blue, pAtmoConfigSrc->m_chWhiteAdj_Blue, sizeof(int) * m_chWhiteAdj_Count);
} else {
m_chWhiteAdj_Red = NULL;
m_chWhiteAdj_Green = NULL;
m_chWhiteAdj_Blue = NULL;
}
this->m_IsSetShutdownColor = pAtmoConfigSrc->m_IsSetShutdownColor;
this->m_ShutdownColor_Red = pAtmoConfigSrc->m_ShutdownColor_Red;
this->m_ShutdownColor_Green = pAtmoConfigSrc->m_ShutdownColor_Green;
......@@ -223,7 +260,6 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
this->m_show_statistics = pAtmoConfigSrc->m_show_statistics;
this->m_LiveView_EdgeWeighting = pAtmoConfigSrc->m_LiveView_EdgeWeighting;
this->m_LiveView_BrightCorrect = pAtmoConfigSrc->m_LiveView_BrightCorrect;
this->m_LiveView_DarknessLimit = pAtmoConfigSrc->m_LiveView_DarknessLimit;
......@@ -236,6 +272,7 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
this->m_LiveView_DisplayNr = pAtmoConfigSrc->m_LiveView_DisplayNr;
this->m_LiveView_FrameDelay = pAtmoConfigSrc->m_LiveView_FrameDelay;
this->m_LiveView_GDI_FrameRate = pAtmoConfigSrc->m_LiveView_GDI_FrameRate;
this->m_LiveView_RowsPerFrame = pAtmoConfigSrc->m_LiveView_RowsPerFrame;
this->m_ZonesTopCount = pAtmoConfigSrc->m_ZonesTopCount;
this->m_ZonesBottomCount = pAtmoConfigSrc->m_ZonesBottomCount;
......@@ -255,6 +292,8 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
this->m_MoMo_Channels = pAtmoConfigSrc->m_MoMo_Channels;
this->m_Fnordlicht_Amount = pAtmoConfigSrc->m_Fnordlicht_Amount;
this->m_CurrentChannelAssignment = pAtmoConfigSrc->m_CurrentChannelAssignment;
clearChannelMappings();
......@@ -278,8 +317,6 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
UpdateZoneDefinitionCount();
}
int CAtmoConfig::getNumChannelAssignments() {
int z=0;
for(int i=0;i<10;i++)
......@@ -336,8 +373,6 @@ void CAtmoConfig::UpdateZoneCount()
m_computed_zones_count++;
}
int CAtmoConfig::getZoneCount()
{
return(m_computed_zones_count);
......@@ -423,3 +458,50 @@ void CAtmoConfig::setDMX_BaseChannels(char *channels)
m_DMX_BaseChannels = strdup(channels);
}
void CAtmoConfig::getChannelWhiteAdj(int channel,int &red,int &green,int &blue)
{
if(channel >= m_chWhiteAdj_Count)
{
red = 256;
green = 256;
blue = 256;
} else {
red = m_chWhiteAdj_Red[ channel ];
green = m_chWhiteAdj_Green[ channel ];
blue = m_chWhiteAdj_Blue[ channel ];
}
}
void CAtmoConfig::setChannelWhiteAdj(int channel,int red,int green,int blue)
{
if(channel >= m_chWhiteAdj_Count)
{
int *tmp = new int[channel+1];
if(m_chWhiteAdj_Red)
memcpy( tmp, m_chWhiteAdj_Red, m_chWhiteAdj_Count * sizeof(int) );
delete []m_chWhiteAdj_Red;
m_chWhiteAdj_Red = tmp;
tmp = new int[channel + 1];
if(m_chWhiteAdj_Green)
memcpy( tmp, m_chWhiteAdj_Green, m_chWhiteAdj_Count * sizeof(int) );
delete []m_chWhiteAdj_Green;
m_chWhiteAdj_Green = tmp;
tmp = new int[channel + 1];
if(m_chWhiteAdj_Blue)
memcpy( tmp, m_chWhiteAdj_Blue, m_chWhiteAdj_Count * sizeof(int) );
delete []m_chWhiteAdj_Blue;
m_chWhiteAdj_Blue = tmp;
m_chWhiteAdj_Count = channel + 1;
}
m_chWhiteAdj_Red[channel] = red;
m_chWhiteAdj_Green[channel] = green;
m_chWhiteAdj_Blue[channel] = blue;
}
......@@ -19,11 +19,10 @@
# include <string.h>
#endif
class CAtmoConfig {
protected:
int m_IsShowConfigDialog;
int m_IsShowConfigDialog;
#if defined(_ATMO_VLC_PLUGIN_)
char *m_devicename;
char *m_devicenames[3]; // additional Devices ?
......@@ -42,6 +41,12 @@ class CAtmoConfig {
int m_WhiteAdjustment_Green;
int m_WhiteAdjustment_Blue;
ATMO_BOOL m_WhiteAdjPerChannel;
int m_chWhiteAdj_Count;
int *m_chWhiteAdj_Red;
int *m_chWhiteAdj_Green;
int *m_chWhiteAdj_Blue;
protected:
int m_IsSetShutdownColor;
int m_ShutdownColor_Red;
......@@ -76,7 +81,6 @@ class CAtmoConfig {
CAtmoZoneDefinition **m_ZoneDefinitions;
int m_AtmoZoneDefCount;
/*
zone layout description for generating the default Zone weightning
*/
......@@ -94,7 +98,6 @@ class CAtmoConfig {
public:
int getZoneCount();
protected:
/* Live View Parameters (most interesting) */
AtmoFilterMode m_LiveViewFilterMode;
......@@ -104,6 +107,9 @@ class CAtmoConfig {
ATMO_BOOL m_show_statistics;
// number of rows to process each frame
int m_LiveView_RowsPerFrame;
// weighting of distance to edge
int m_LiveView_EdgeWeighting; // = 8;
// brightness correction
......@@ -154,6 +160,9 @@ class CAtmoConfig {
protected:
int m_MoMo_Channels;
protected:
int m_Fnordlicht_Amount;
protected:
AtmoGammaCorrect m_Software_gamma_mode;
......@@ -165,7 +174,6 @@ class CAtmoConfig {
public:
volatile int m_UpdateEdgeWeightningFlag;
public:
CAtmoConfig();
virtual ~CAtmoConfig();
......@@ -210,6 +218,13 @@ class CAtmoConfig {
ATMO_BOOL isUseSoftwareWhiteAdj() { return m_UseSoftwareWhiteAdj; }
void setUseSoftwareWhiteAdj(ATMO_BOOL value) { m_UseSoftwareWhiteAdj = value; }
/* White ADJ per Channel settings */
ATMO_BOOL isWhiteAdjPerChannel() { return m_WhiteAdjPerChannel; }
void setWhiteAdjPerChannel( ATMO_BOOL value) { m_WhiteAdjPerChannel = value; }
void setChannelWhiteAdj(int channel,int red,int green,int blue);
void getChannelWhiteAdj(int channel,int &red,int &green,int &blue);
int isSetShutdownColor() { return m_IsSetShutdownColor; }
void SetSetShutdownColor(int value) { m_IsSetShutdownColor = value; }
int getShutdownColor_Red() { return m_ShutdownColor_Red; }
......@@ -236,7 +251,6 @@ class CAtmoConfig {
int getStaticColor_Blue() { return m_StaticColor_Blue; }
void setStaticColor_Blue(int value) { m_StaticColor_Blue=value; }
AtmoConnectionType getConnectionType() { return m_eAtmoConnectionType; }
void setConnectionType(AtmoConnectionType value) { m_eAtmoConnectionType = value; }
......@@ -258,7 +272,10 @@ class CAtmoConfig {
int getLiveView_EdgeWeighting() { return m_LiveView_EdgeWeighting; }
void setLiveView_EdgeWeighting(int value) { m_LiveView_EdgeWeighting=value; }
int getLiveView_BrightCorrect() { return m_LiveView_BrightCorrect; }
int getLiveView_RowsPerFrame() { return m_LiveView_RowsPerFrame; }
void setLiveView_RowsPerFrame(int value) { m_LiveView_RowsPerFrame=value; }
int getLiveView_BrightCorrect() { return m_LiveView_BrightCorrect; }
void setLiveView_BrightCorrect(int value) { m_LiveView_BrightCorrect=value; }
int getLiveView_DarknessLimit() { return m_LiveView_DarknessLimit; }
......@@ -312,7 +329,6 @@ class CAtmoConfig {
int getHardware_gamma_blue() { return m_Hardware_gamma_blue; }
void setHardware_gamma_blue(int value) { m_Hardware_gamma_blue=value; }
AtmoGammaCorrect getSoftware_gamma_mode() { return m_Software_gamma_mode; }
int getSoftware_gamma_red() { return m_Software_gamma_red; }
int getSoftware_gamma_green() { return m_Software_gamma_green; }
......@@ -359,6 +375,9 @@ class CAtmoConfig {
int getMoMo_Channels() { return m_MoMo_Channels; }
void setMoMo_Channels(int chCount) { m_MoMo_Channels = chCount; }
int getFnordlicht_Amount() { return m_Fnordlicht_Amount; }
void setFnordlicht_Amount(int fnordlichtAmount) { m_Fnordlicht_Amount = fnordlichtAmount; }
};
#endif
......@@ -114,7 +114,8 @@ enum AtmoConnectionType
actNUL = 3,
actMultiAtmo = 4,
actMondolight = 5,
actMoMoLight = 6
actMoMoLight = 6,
actFnordlicht = 7
};
static const char *AtmoDeviceTypes[] = {
"Atmo-Classic",
......@@ -123,10 +124,10 @@ static const char *AtmoDeviceTypes[] = {
"Nul-Device",
"Multi-Atmo",
"Mondolight",
"MoMoLight"
"MoMoLight",
"Fnordlicht"
};
#define ATMO_DEVICE_COUNT 7
#define ATMO_DEVICE_COUNT 8
#if defined(_ATMO_VLC_PLUGIN_)
enum EffectMode {
......
......@@ -13,6 +13,7 @@
#include "AtmoDmxSerialConnection.h"
#include "AtmoMultiConnection.h"
#include "MoMoConnection.h"
#include "FnordlichtConnection.h"
#include "AtmoExternalCaptureInput.h"
#include <math.h>
......@@ -27,7 +28,6 @@
# include "AtmoGdiDisplayCaptureInput.h"
#endif
CAtmoTools::CAtmoTools(void)
{
}
......@@ -40,7 +40,6 @@ void CAtmoTools::ShowShutdownColor(CAtmoDynData *pDynData)
{
pDynData->LockCriticalSection();
CAtmoConnection *atmoConnection = pDynData->getAtmoConnection();
CAtmoConfig *atmoConfig = pDynData->getAtmoConfig();
if((atmoConnection != NULL) && (atmoConfig!=NULL) && atmoConfig->isSetShutdownColor()) {
......@@ -403,6 +402,24 @@ ATMO_BOOL CAtmoTools::RecreateConnection(CAtmoDynData *pDynData)
return ATMO_TRUE;
}
case actFnordlicht: {
CFnordlichtConnection *tempConnection = new CFnordlichtConnection( atmoConfig );
if(tempConnection->OpenConnection() == ATMO_FALSE) {
pDynData->setAtmoConnection(tempConnection);
pDynData->UnLockCriticalSection();
return ATMO_FALSE;
}
pDynData->setAtmoConnection(tempConnection);
pDynData->ReloadZoneDefinitionBitmaps();
tempConnection->CreateDefaultMapping( atmoConfig->getChannelAssignment(0) );
CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment() );
pDynData->UnLockCriticalSection();
return ATMO_TRUE;
}
default: {
pDynData->UnLockCriticalSection();
return ATMO_FALSE;
......
/*
* FnordlichtConnection.h: class to access a FnordlichtLight Hardware
* - the description could be found
* here: http://github.com/fd0/fnordlicht/raw/master/doc/PROTOCOL
*
* (C) Kai Lauterbach (klaute at gmail.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id$
*/
#include "AtmoDefs.h"
#include "FnordlichtConnection.h"
#if !defined(_ATMO_VLC_PLUGIN_)
# include "FnordlichtConfigDialog.h"
#endif
#include <stdio.h>
#include <fcntl.h>
#if !defined(WIN32)
#include <termios.h>
#include <unistd.h>
#endif
CFnordlichtConnection::CFnordlichtConnection(CAtmoConfig *cfg)
: CAtmoConnection(cfg)
{
m_hComport = INVALID_HANDLE_VALUE;
}
CFnordlichtConnection::~CFnordlichtConnection()
{
}
ATMO_BOOL CFnordlichtConnection::OpenConnection()
{
#if defined(_ATMO_VLC_PLUGIN_)
char *serdevice = m_pAtmoConfig->getSerialDevice();
if ( !serdevice )
return ATMO_FALSE;
#else
int portNummer = m_pAtmoConfig->getComport();
m_dwLastWin32Error = 0;
if ( portNummer < 1 )
return ATMO_FALSE; // make no real sense;-)
#endif
CloseConnection();
#if !defined(_ATMO_VLC_PLUGIN_)
char serdevice[16]; // com4294967295
sprintf(serdevice,"com%d",portNummer);
#endif
#if defined(WIN32)
m_hComport = CreateFile(serdevice,
GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
if ( m_hComport == INVALID_HANDLE_VALUE )
{
// we have a problem here can't open com port...
// somebody else may use it?
// m_dwLastWin32Error = GetLastError();
return ATMO_FALSE;
}
/* change serial settings (Speed, stopbits etc.) */
DCB dcb; // fr comport-parameter
dcb.DCBlength = sizeof(DCB);
GetCommState(m_hComport, &dcb); // ger current serialport settings
dcb.BaudRate = 19200; // set speed
dcb.ByteSize = 8; // set databits
dcb.Parity = NOPARITY; // set parity
dcb.StopBits = ONESTOPBIT; // set one stop bit
SetCommState(m_hComport, &dcb); // apply settings
#else
int bconst = B19200;
m_hComport = open(serdevice,O_RDWR |O_NOCTTY);
if ( m_hComport < 0 )
return ATMO_FALSE;
struct termios tio;
memset(&tio,0,sizeof(tio));
tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
tio.c_iflag = (INPCK | BRKINT);
cfsetispeed(&tio, bconst);
cfsetospeed(&tio, bconst);
if( ! tcsetattr(m_hComport, TCSANOW, &tio) )
tcflush(m_hComport, TCIOFLUSH);
else {
// can't change parms
close(m_hComport);
m_hComport = -1;
return false;
}
#endif
// sync fnordlicht
if ( sync() )
// stop fading on all devices
if ( stop(255) )
return true; // fnordlicht initialized...
return false; // something is going wrong...
}
void CFnordlichtConnection::CloseConnection()
{
if ( m_hComport != INVALID_HANDLE_VALUE )
{
reset(255);
#if defined(WIN32)
CloseHandle(m_hComport);
#else
close(m_hComport);
#endif
m_hComport = INVALID_HANDLE_VALUE;
}
}
ATMO_BOOL CFnordlichtConnection::isOpen(void)
{
return (m_hComport != INVALID_HANDLE_VALUE);
}
ATMO_BOOL CFnordlichtConnection::HardwareWhiteAdjust(int global_gamma,
int global_contrast,
int contrast_red,
int contrast_green,
int contrast_blue,
int gamma_red,
int gamma_green,
int gamma_blue,
ATMO_BOOL storeToEeprom)
{
return ATMO_FALSE; //no hardware adjust required
}
/*
def fade_rgb(addr, r, g, b, step, delay)
$dev.write addr.chr
$dev.write "\x01"
$dev.write step.chr
$dev.write delay.chr
$dev.write r.chr
$dev.write g.chr
$dev.write b.chr
$dev.write "\x00\x00\x00\x00\x00"
$dev.write "\x00\x00\x00"
$dev.flush
end
*/
ATMO_BOOL CFnordlichtConnection::SendData(pColorPacket data)
{
if ( m_hComport == INVALID_HANDLE_VALUE )
return ATMO_FALSE;
int amount = getAmountFnordlichter();
unsigned char buffer[15];
memset(&buffer, 0, sizeof(buffer) ); // zero buffer
int iBytesWritten;
Lock();
buffer[1] = 0x01; // fade to rgb color
buffer[2] = 0x80; // in two steps
buffer[3] = 0x01; // 1ms pause between steps
// send all packages to all fnordlicht's
for( unsigned char i=0; i < amount; i++ )
{
int idx;
if ( m_ChannelAssignment && i < m_NumAssignedChannels )
idx = m_ChannelAssignment[i];
else
idx = -1; // no channel assigned to fnordlicht[i]
if( idx >= 0 && idx <= data->numColors )
{
// fnordlicht address equals to a MoMo Channel
buffer[0] = i; // fnordlicht address (0..254, 255 = broadcast)
buffer[4] = data->zone[idx].r;
buffer[5] = data->zone[idx].g;
buffer[6] = data->zone[idx].b;
}
#if defined(WIN32)
// send to COM-Port
WriteFile( m_hComport, buffer, sizeof(buffer),
(DWORD*)&iBytesWritten, NULL );
#else
iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
tcflush(m_hComport, TCIOFLUSH);
tcdrain(m_hComport); // flush buffer
#endif
if (iBytesWritten != sizeof(buffer))
{
Unlock();
return ATMO_FALSE; // shouldn't be...
}
}
Unlock();
return ATMO_TRUE;
}
ATMO_BOOL CFnordlichtConnection::CreateDefaultMapping(CAtmoChannelAssignment *ca)
{
if ( !ca )
return ATMO_FALSE;
ca->setSize