From 04d7e53c2b334ef4c0aee65eb0dc90d81913c234 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Fri, 18 Nov 2016 16:07:44 +0100 Subject: [PATCH 01/73] modify ac3flags --- libspark/playback_libeplayer3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libspark/playback_libeplayer3.cpp b/libspark/playback_libeplayer3.cpp index b714d28..13f9bef 100644 --- a/libspark/playback_libeplayer3.cpp +++ b/libspark/playback_libeplayer3.cpp @@ -309,7 +309,7 @@ void cPlayback::FindAllPids(int *pids, unsigned int *ac3flags, unsigned int *num std::vector tracks = player->manager.getAudioTracks(); for (std::vector::iterator it = tracks.begin(); it != tracks.end() && i < *numpids; ++it) { pids[i] = it->pid; - ac3flags[i] = it->ac3flags; + ac3flags[i] = (it->ac3flags > 2) ? 1 : 0; language[i] = it->title; i++; } From 5d72d67ccadf24b0001cc70dc9017e3163a2820c Mon Sep 17 00:00:00 2001 From: TangoCash Date: Tue, 4 Apr 2017 11:03:37 +0200 Subject: [PATCH 02/73] fix generic compile --- generic-pc/playback.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/generic-pc/playback.cpp b/generic-pc/playback.cpp index 47d483a..87dfbee 100644 --- a/generic-pc/playback.cpp +++ b/generic-pc/playback.cpp @@ -18,7 +18,7 @@ bool cPlayback::Start(std::string filename, std::string headers) return Start((char*) filename.c_str(),0,0,0,0,0, headers); } -bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, int, std::string headers) +bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers) { printf("%s:%s - filename=%s vpid=%u vtype=%d apid=%u ac3=%d duration=%i\n", FILENAME, __func__, filename, vpid, vtype, apid, ac3, duration); @@ -131,6 +131,11 @@ void cPlayback::SetTitle(int /*title*/) { } +uint64_t cPlayback::GetReadCount() +{ + return 0; +} + cPlayback::cPlayback(int /*num*/) { printf("%s:%s\n", FILENAME, __func__); From a5198e44d2cdf670ef1d73583ec4b4eb21ad4755 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Wed, 31 May 2017 18:18:59 +0200 Subject: [PATCH 03/73] adding initial support for gstreamer 1.0 --- configure.ac | 30 +- generic-pc/Makefile.am | 11 +- .../{playback_gst.cpp => playback_gst_01.cpp} | 0 generic-pc/playback_gst_10.cpp | 826 ++++++++++++++++++ 4 files changed, 855 insertions(+), 12 deletions(-) rename generic-pc/{playback_gst.cpp => playback_gst_01.cpp} (100%) create mode 100644 generic-pc/playback_gst_10.cpp diff --git a/configure.ac b/configure.ac index e605b7b..82df74a 100644 --- a/configure.ac +++ b/configure.ac @@ -24,20 +24,30 @@ if test x"$BOXTYPE" = x"tripledragon"; then TUXBOX_APPS_LIB_PKGCONFIG(DIRECTFB, directfb) fi -AC_ARG_ENABLE(gstreamer, - AS_HELP_STRING(--enable-gstreamer,use gstreamer playback), - ,[enable_gstreamer=no]) +AC_ARG_ENABLE(gstreamer_01, + AS_HELP_STRING(--enable-gstreamer_01,use gstreamer 0.10 playback), + ,[enable_gstreamer_01=no]) -AM_CONDITIONAL(ENABLE_GSTREAMER,test "$enable_gstreamer" = "yes") -if test "$enable_gstreamer" = "yes"; then - AC_DEFINE(ENABLE_GSTREAMER,1,[enable gstreamer]) +AM_CONDITIONAL(ENABLE_GSTREAMER_01,test "$enable_gstreamer_01" = "yes") +if test "$enable_gstreamer_01" = "yes"; then + AC_DEFINE(ENABLE_GSTREAMER_01,1,[use gstreamer 0.10 playback]) + PKG_CHECK_MODULES([GSTREAMER], [gstreamer-0.10]) + PKG_CHECK_MODULES([GSTREAMER_INTERFACES], [gstinterfaces-0.10]) +fi + +AC_ARG_ENABLE(gstreamer_10, + AS_HELP_STRING(--enable-gstreamer_10,use gstreamer 1.0 playback), + ,[enable_gstreamer_10=no]) + +AM_CONDITIONAL(ENABLE_GSTREAMER_10,test "$enable_gstreamer_10" = "yes") +if test "$enable_gstreamer_10" = "yes"; then + AC_DEFINE(ENABLE_GSTREAMER_10,1,[use gstreamer 1.0 playback]) + PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0]) + PKG_CHECK_MODULES([GSTREAMER_AUDIO], [gstreamer-audio-1.0]) + PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0]) fi if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then -if test x$ENABLE_GSTREAMER = x1; then - PKG_CHECK_MODULES([GSTREAMER], [gstreamer-0.10]) - PKG_CHECK_MODULES([GSTREAMER_INTERFACES], [gstinterfaces-0.10]) -fi PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1]) PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0]) # don't know which version is exactly needed here... diff --git a/generic-pc/Makefile.am b/generic-pc/Makefile.am index f00130d..58f5114 100644 --- a/generic-pc/Makefile.am +++ b/generic-pc/Makefile.am @@ -25,14 +25,21 @@ libgeneric_la_SOURCES = \ pwrmngr.cpp \ record.cpp -if ENABLE_GSTREAMER +if ENABLE_GSTREAMER_01 libgeneric_la_SOURCES += \ - playback_gst.cpp + playback_gst_01.cpp AM_LDFLAGS += \ -lgstreamer-0.10 \ -lgstinterfaces-0.10 else +if ENABLE_GSTREAMER_10 +libgeneric_la_SOURCES += \ + playback_gst_10.cpp +AM_LDFLAGS += \ + -lgstreamer-1.0 +else libgeneric_la_SOURCES += \ playback.cpp endif +endif diff --git a/generic-pc/playback_gst.cpp b/generic-pc/playback_gst_01.cpp similarity index 100% rename from generic-pc/playback_gst.cpp rename to generic-pc/playback_gst_01.cpp diff --git a/generic-pc/playback_gst_10.cpp b/generic-pc/playback_gst_10.cpp new file mode 100644 index 0000000..482a607 --- /dev/null +++ b/generic-pc/playback_gst_10.cpp @@ -0,0 +1,826 @@ +/* + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include "dmx_lib.h" +#include "audio_lib.h" +#include "video_lib.h" +#include "glfb.h" + +#include "playback_gst.h" + +#include "lt_debug.h" +#define lt_debug(args...) _lt_debug(HAL_DEBUG_PLAYBACK, this, args) +#define lt_info(args...) _lt_info(HAL_DEBUG_PLAYBACK, this, args) +#define lt_debug_c(args...) _lt_debug(HAL_DEBUG_PLAYBACK, NULL, args) +#define lt_info_c(args...) _lt_info(HAL_DEBUG_PLAYBACK, NULL, args) + +static const char * FILENAME = "[playback.cpp]"; + +#include +#include +#include + +typedef enum +{ + GST_PLAY_FLAG_VIDEO = 0x00000001, + GST_PLAY_FLAG_AUDIO = 0x00000002, + GST_PLAY_FLAG_TEXT = 0x00000004, + GST_PLAY_FLAG_VIS = 0x00000008, + GST_PLAY_FLAG_SOFT_VOLUME = 0x00000010, + GST_PLAY_FLAG_NATIVE_AUDIO = 0x00000020, + GST_PLAY_FLAG_NATIVE_VIDEO = 0x00000040, + GST_PLAY_FLAG_DOWNLOAD = 0x00000080, + GST_PLAY_FLAG_BUFFERING = 0x000000100 +} GstPlayFlags; + + +GstElement * m_gst_playbin = NULL; +GstElement * audioSink = NULL; +GstElement * videoSink = NULL; +gchar * uri = NULL; +GstTagList * m_stream_tags = 0; +static int end_eof = 0; + +extern GLFramebuffer *glfb; + +gint match_sinktype(GstElement *element, gpointer type) +{ + return strcmp(g_type_name(G_OBJECT_TYPE(element)), (const char*)type); +} +GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) +{ + gchar * sourceName; + + // source + GstObject * source; + source = GST_MESSAGE_SRC(msg); + + if (!GST_IS_OBJECT(source)) + return GST_BUS_DROP; + + sourceName = gst_object_get_name(source); + + switch (GST_MESSAGE_TYPE(msg)) + { + case GST_MESSAGE_EOS: + { + g_message("End-of-stream"); + end_eof = 1; + break; + } + + case GST_MESSAGE_ERROR: + { + gchar * debug; + GError *err; + gst_message_parse_error(msg, &err, &debug); + g_free (debug); + lt_info_c( "%s:%s - GST_MESSAGE_ERROR: %s (%i) from %s\n", FILENAME, __FUNCTION__, err->message, err->code, sourceName ); + if ( err->domain == GST_STREAM_ERROR ) + { + if ( err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND ) + { + if ( g_strrstr(sourceName, "videosink") ) + lt_info_c( "%s:%s - GST_MESSAGE_ERROR: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? + else if ( g_strrstr(sourceName, "audiosink") ) + lt_info_c( "%s:%s - GST_MESSAGE_ERROR: audioSink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? + } + } + g_error_free(err); + + end_eof = 1; // NOTE: just to exit + + break; + } + + case GST_MESSAGE_INFO: + { + gchar *debug; + GError *inf; + + gst_message_parse_info (msg, &inf, &debug); + g_free (debug); + if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE ) + { + if ( g_strrstr(sourceName, "videosink") ) + lt_info_c( "%s:%s - GST_MESSAGE_INFO: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? + } + g_error_free(inf); + break; + } + + case GST_MESSAGE_TAG: + { + GstTagList *tags, *result; + gst_message_parse_tag(msg, &tags); + + result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE); + if (result) + { + if (m_stream_tags) + gst_tag_list_free(m_stream_tags); + m_stream_tags = result; + } + + const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0); + if ( gv_image ) + { + GstBuffer *buf_image; + buf_image = gst_value_get_buffer (gv_image); + int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644); + if(fd >= 0) + { + GstMapInfo Info; + gst_buffer_map(buf_image, &Info,(GstMapFlags)( GST_MAP_READ)); + int ret = write(fd, Info.data, Info.size); + close(fd); + gst_buffer_unmap(buf_image, &Info); + lt_info_c( "%s:%s - GST_MESSAGE_INFO: cPlayback::state /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__ , ret); + } + //FIXME: how shall playback handle this event??? + } + gst_tag_list_free(tags); + lt_info_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event??? + break; + } + + case GST_MESSAGE_STATE_CHANGED: + { + if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) + break; + + GstState old_state, new_state; + gst_message_parse_state_changed(msg, &old_state, &new_state, NULL); + + if(old_state == new_state) + break; + lt_info_c( "%s:%s - GST_MESSAGE_STATE_CHANGED: state transition %s -> %s\n", FILENAME, __FUNCTION__, gst_element_state_get_name(old_state), gst_element_state_get_name(new_state)); + + GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state); + + switch(transition) + { + case GST_STATE_CHANGE_NULL_TO_READY: + { + } break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + { + GstIterator *children; + if (audioSink) + { + gst_object_unref(GST_OBJECT(audioSink)); + audioSink = NULL; + } + + if (videoSink) + { + gst_object_unref(GST_OBJECT(videoSink)); + videoSink = NULL; + } + children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); + GValue *elem; + audioSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, elem, (gpointer)"GstDVBAudioSink")); + videoSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, elem, (gpointer)"GstDVBVideoSink")); + gst_iterator_free(children); + + } break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + { + } break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + { + } break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + { + if (audioSink) + { + gst_object_unref(GST_OBJECT(audioSink)); + audioSink = NULL; + } + if (videoSink) + { + gst_object_unref(GST_OBJECT(videoSink)); + videoSink = NULL; + } + } break; + case GST_STATE_CHANGE_READY_TO_NULL: + { + } break; + } + break; + } +#if 0 + case GST_MESSAGE_ELEMENT: + { + if(gst_structure_has_name(gst_message_get_structure(msg), "prepare-xwindow-id")) + { + // set window id + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), glfb->getWindowID()); + + // reshape window + gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), 0, 0, glfb->getOSDWidth(), glfb->getOSDHeight()); + + // sync frames + gst_video_overlay_expose(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg))); + } + } +#endif + break; + default: + break; + } + + return GST_BUS_DROP; +} + + +cPlayback::cPlayback(int num) +{ + lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + const gchar *nano_str; + guint major, minor, micro, nano; + + gst_init(NULL, NULL); + + gst_version (&major, &minor, µ, &nano); + + if (nano == 1) + nano_str = "(CVS)"; + else if (nano == 2) + nano_str = "(Prerelease)"; + else + nano_str = ""; + + lt_info( "%s:%s - This program is linked against GStreamer %d.%d.%d %s\n", + FILENAME, __FUNCTION__, + major, minor, micro, nano_str); + + mAudioStream = 0; + mSpeed = 0; + + playing = false; + playstate = STATE_STOP; +} + +cPlayback::~cPlayback() +{ + lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + //FIXME: all deleting stuff is done in Close() +} + +//Used by Fileplay +bool cPlayback::Open(playmode_t PlayMode) +{ + lt_info("%s: PlayMode %d\n", __func__, PlayMode); + return true; +} + +// used by movieplay +void cPlayback::Close(void) +{ + lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + + Stop(); + + // disconnect bus handler + if (m_gst_playbin) + { + // disconnect sync handler callback + GstBus * bus = gst_pipeline_get_bus(GST_PIPELINE (m_gst_playbin)); + gst_bus_set_sync_handler(bus, NULL, NULL, NULL); + gst_object_unref(bus); + lt_info( "%s:%s - GST bus handler closed\n", FILENAME, __FUNCTION__); + } + + if (m_stream_tags) + gst_tag_list_free(m_stream_tags); + + // close gst + if (m_gst_playbin) + { + if (audioSink) + { + gst_object_unref(GST_OBJECT(audioSink)); + audioSink = NULL; + + lt_info( "%s:%s - GST audio Sink closed\n", FILENAME, __FUNCTION__); + } + + if (videoSink) + { + gst_object_unref(GST_OBJECT(videoSink)); + videoSink = NULL; + + lt_info( "%s:%s - GST video Sink closed\n", FILENAME, __FUNCTION__); + } + + // unref m_gst_playbin + gst_object_unref (GST_OBJECT (m_gst_playbin)); + lt_info( "%s:%s - GST playbin closed\n", FILENAME, __FUNCTION__); + + m_gst_playbin = NULL; + } +} + +// start +bool cPlayback::Start(std::string filename, std::string headers) +{ + return Start((char*) filename.c_str(),0,0,0,0,0, headers); +} + +bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, int /*ac3*/, int /*duration*/, std::string headers) +{ + lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + + mAudioStream = 0; + + //create playback path + char file[400] = {""}; + bool isHTTP = false; + + if(!strncmp("http://", filename, 7)) + { + isHTTP = true; + } + else if(!strncmp("file://", filename, 7)) + { + isHTTP = false; + } + else if(!strncmp("upnp://", filename, 7)) + { + isHTTP = true; + } + else if(!strncmp("rtmp://", filename, 7)) + { + isHTTP = true; + } + else if(!strncmp("rtsp://", filename, 7)) + { + isHTTP = true; + } + else if(!strncmp("mms://", filename, 6)) + { + isHTTP = true; + } + else + strcat(file, "file://"); + + strcat(file, filename); + + if (isHTTP) + uri = g_uri_escape_string(filename, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS, true); + else + uri = g_filename_to_uri(filename, NULL, NULL); + + lt_info("%s:%s - filename=%s\n", FILENAME, __FUNCTION__, filename); + + // create gst pipeline + m_gst_playbin = gst_element_factory_make ("playbin", "playbin"); + + if(m_gst_playbin) + { + lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__); + + guint flags; + g_object_get(G_OBJECT (m_gst_playbin), "flags", &flags, NULL); + /* avoid video conversion, let the (hardware) sinks handle that */ + flags |= GST_PLAY_FLAG_NATIVE_VIDEO; + /* volume control is done by hardware */ + flags &= ~GST_PLAY_FLAG_SOFT_VOLUME; + + g_object_set(G_OBJECT (m_gst_playbin), "uri", uri, NULL); + g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL); + + //gstbus handler + GstBus * bus = gst_pipeline_get_bus( GST_PIPELINE(m_gst_playbin) ); + gst_bus_set_sync_handler(bus, Gst_bus_call, NULL, NULL); + gst_object_unref(bus); + + // state playing + gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + + playing = true; + playstate = STATE_PLAY; + } + else + { + lt_info("%s:%s - failed to create GStreamer pipeline!, sorry we can not play\n", FILENAME, __FUNCTION__); + playing = false; + + return false; + } + + g_free(uri); + + // set buffer size + /* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */ + int m_buffer_size = 5*1024*1024; + //g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL); + g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL); + + return true; +} + +bool cPlayback::Play(void) +{ + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + if(playing == true) + return true; + + if(m_gst_playbin) + { + gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING); + + playing = true; + playstate = STATE_PLAY; + } + lt_info("%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + return playing; +} + +bool cPlayback::Stop(void) +{ + if(playing == false) + return false; + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + // stop + if(m_gst_playbin) + { + gst_element_set_state(m_gst_playbin, GST_STATE_NULL); + } + + playing = false; + + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + playstate = STATE_STOP; + + return true; +} + +bool cPlayback::SetAPid(int pid , bool /*ac3*/) +{ + lt_info("%s: pid %i\n", __func__, pid); + + int current_audio; + + if(pid != mAudioStream) + { + g_object_set (G_OBJECT (m_gst_playbin), "current-audio", pid, NULL); + printf("%s: switched to audio stream %i\n", __FUNCTION__, pid); + mAudioStream = pid; + } + + return true; +} + +void cPlayback::trickSeek(int ratio) +{ + bool validposition = false; + gint64 pos = 0; + int position; + int duration; + + if( GetPosition(position, duration) ) + { + validposition = true; + pos = position; + } + + gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + + if (validposition) + { + if(ratio >= 0.0) + gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1); + else + gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos); + } +} + +bool cPlayback::SetSpeed(int speed) +{ + lt_info( "%s:%s speed %d\n", FILENAME, __FUNCTION__, speed); + + if(playing == false) + return false; + + if(m_gst_playbin) + { + // pause + if(speed == 0) + { + gst_element_set_state(m_gst_playbin, GST_STATE_PAUSED); + //trickSeek(0); + playstate = STATE_PAUSE; + } + // play/continue + else if(speed == 1) + { + trickSeek(1); + //gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + // + playstate = STATE_PLAY; + } + //ff + else if(speed > 1) + { + trickSeek(speed); + // + playstate = STATE_FF; + } + //rf + else if(speed < 0) + { + trickSeek(speed); + // + playstate = STATE_REW; + } + } + + mSpeed = speed; + + return true; +} + +bool cPlayback::SetSlow(int slow) +{ + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + if(playing == false) + return false; + + if(m_gst_playbin) + { + trickSeek(0.5); + } + + playstate = STATE_SLOW; + + mSpeed = slow; + + return true; +} + +bool cPlayback::GetSpeed(int &speed) const +{ + speed = mSpeed; + + return true; +} + +// in milliseconds +bool cPlayback::GetPosition(int &position, int &duration) +{ + if(playing == false) + return false; + + //EOF + if(end_eof) + { + end_eof = 0; + return false; + } + + if(m_gst_playbin) + { + //position + GstFormat fmt = GST_FORMAT_TIME; //Returns time in nanosecs + + gint64 pts = 0; + unsigned long long int sec = 0; + + gst_element_query_position(m_gst_playbin, fmt, &pts); + position = pts / 1000000.0; + + // duration + GstFormat fmt_d = GST_FORMAT_TIME; //Returns time in nanosecs + double length = 0; + gint64 len; + + gst_element_query_duration(m_gst_playbin, fmt_d, &len); + length = len / 1000000.0; + if(length < 0) + length = 0; + + duration = (int)(length); + } + + return true; +} + +bool cPlayback::SetPosition(int position, bool absolute) +{ + lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing); + + if(playing == false) + return false; + + gint64 time_nanoseconds; + gint64 pos; + GstFormat fmt = GST_FORMAT_TIME; + + if(m_gst_playbin) + { + gst_element_query_position(m_gst_playbin, fmt, &pos); + time_nanoseconds = pos + (position * 1000000.0); + if(time_nanoseconds < 0) + time_nanoseconds = 0; + + gst_element_seek(m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + } + + return true; +} + +void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string * language) +{ + lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + + if(m_gst_playbin) + { + gint i, n_audio = 0; + //GstStructure * structure = NULL; + + // get audio + g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL); + printf("%s: %d audio\n", __FUNCTION__, n_audio); + + if(n_audio == 0) + return; + + for (i = 0; i < n_audio; i++) + { + // apids + apids[i]=i; + + GstPad * pad = 0; + g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad); + GstCaps * caps = gst_pad_get_current_caps(pad); + if (!caps) + continue; + + GstStructure * structure = gst_caps_get_structure(caps, 0); + //const gchar *g_type = gst_structure_get_name(structure); + + //if (!structure) + //return atUnknown; + //ac3flags[0] = 0; + + // ac3flags + if ( gst_structure_has_name (structure, "audio/mpeg")) + { + gint mpegversion, layer = -1; + + if (!gst_structure_get_int (structure, "mpegversion", &mpegversion)) + //return atUnknown; + ac3flags[i] = 0; + + switch (mpegversion) + { + case 1: + /* + { + gst_structure_get_int (structure, "layer", &layer); + if ( layer == 3 ) + return atMP3; + else + return atMPEG; + ac3flags[0] = 4; + break; + } + */ + ac3flags[i] = 4; + case 2: + //return atAAC; + ac3flags[i] = 5; + case 4: + //return atAAC; + ac3flags[i] = 5; + default: + //return atUnknown; + ac3flags[i] = 0; + } + } + else if ( gst_structure_has_name (structure, "audio/x-ac3") || gst_structure_has_name (structure, "audio/ac3") ) + //return atAC3; + ac3flags[i] = 1; + else if ( gst_structure_has_name (structure, "audio/x-dts") || gst_structure_has_name (structure, "audio/dts") ) + //return atDTS; + ac3flags[i] = 6; + else if ( gst_structure_has_name (structure, "audio/x-raw-int") ) + //return atPCM; + ac3flags[i] = 0; + + gst_caps_unref(caps); + } + + // numpids + *numpida=i; + } +} + +void cPlayback::getMeta() +{ + if(playing) + return; +} + +bool cPlayback::SyncAV(void) +{ + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + if(playing == false ) + return false; + + return true; +} + +void cPlayback::RequestAbort() +{ +} + +void cPlayback::FindAllSubs(uint16_t *, unsigned short *, uint16_t *numpida, std::string *) +{ + printf("%s:%s\n", FILENAME, __func__); + *numpida = 0; +} + +void cPlayback::GetChapters(std::vector &positions, std::vector &titles) +{ + positions.clear(); + titles.clear(); +} + +bool cPlayback::SelectSubtitles(int pid) +{ + printf("%s:%s pid %i\n", FILENAME, __func__, pid); + return true; +} + +void cPlayback::GetMetadata(std::vector &keys, std::vector &values) +{ + keys.clear(); + values.clear(); +} + +void cPlayback::FindAllTeletextsubtitlePids(int *, unsigned int *numpids, std::string *, int *, int *) +{ + *numpids = 0; +} + +void cPlayback::FindAllSubtitlePids(int * /*pids*/, unsigned int *numpids, std::string * /*language*/) +{ + *numpids = 0; +} + +bool cPlayback::SetSubtitlePid(int /*pid*/) +{ + return true; +} + +void cPlayback::GetPts(uint64_t &/*pts*/) +{ +} + +bool cPlayback::SetTeletextPid(int /*pid*/) +{ + return true; +} + +uint64_t cPlayback::GetReadCount() +{ + return 0; +} From a1f7fb921733de8536bed7d8904da9d3ee0447df Mon Sep 17 00:00:00 2001 From: TangoCash Date: Wed, 31 May 2017 20:07:43 +0200 Subject: [PATCH 04/73] small fix for gstreamer 1.0 playback --- generic-pc/playback_gst_10.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/generic-pc/playback_gst_10.cpp b/generic-pc/playback_gst_10.cpp index 482a607..57d891d 100644 --- a/generic-pc/playback_gst_10.cpp +++ b/generic-pc/playback_gst_10.cpp @@ -72,10 +72,12 @@ static int end_eof = 0; extern GLFramebuffer *glfb; -gint match_sinktype(GstElement *element, gpointer type) +gint match_sinktype(const GValue *velement, const gchar *type) { - return strcmp(g_type_name(G_OBJECT_TYPE(element)), (const char*)type); + GstElement *element = GST_ELEMENT_CAST(g_value_get_object(velement)); + return strcmp(g_type_name(G_OBJECT_TYPE(element)), type); } + GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) { gchar * sourceName; @@ -207,9 +209,13 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) videoSink = NULL; } children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); - GValue *elem; - audioSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, elem, (gpointer)"GstDVBAudioSink")); - videoSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, elem, (gpointer)"GstDVBVideoSink")); + GValue r = G_VALUE_INIT; + gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink"); + audioSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); + g_value_unset (&r); + gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink"); + videoSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); + g_value_unset (&r); gst_iterator_free(children); } break; From fcfd96f8cd68bbcfe2c52192fc9c8a0f50d3d091 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Wed, 31 May 2017 22:43:56 +0200 Subject: [PATCH 05/73] small fix for gstreamer 1.0 playback --- generic-pc/playback_gst_10.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generic-pc/playback_gst_10.cpp b/generic-pc/playback_gst_10.cpp index 57d891d..e386f12 100644 --- a/generic-pc/playback_gst_10.cpp +++ b/generic-pc/playback_gst_10.cpp @@ -171,7 +171,7 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) //FIXME: how shall playback handle this event??? } gst_tag_list_free(tags); - lt_info_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event??? + lt_debug_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event??? break; } @@ -247,7 +247,7 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) #if 0 case GST_MESSAGE_ELEMENT: { - if(gst_structure_has_name(gst_message_get_structure(msg), "prepare-xwindow-id")) + if(gst_structure_has_name(gst_message_get_structure(msg), "prepare-window-handle")) { // set window id gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), glfb->getWindowID()); From 2e765e73c2b5f0b7942a1afd0be8f62342397951 Mon Sep 17 00:00:00 2001 From: Jacek Jendrzej Date: Mon, 20 Mar 2017 14:30:16 +0100 Subject: [PATCH 06/73] generic-pc/video.cpp dont set output format with negative height size --- generic-pc/video.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/generic-pc/video.cpp b/generic-pc/video.cpp index 6cd7ec4..208cc57 100644 --- a/generic-pc/video.cpp +++ b/generic-pc/video.cpp @@ -82,6 +82,7 @@ cVideo::cVideo(int, void *, void *, unsigned int) display_aspect = DISPLAY_AR_16_9; display_crop = DISPLAY_AR_MODE_LETTERBOX; v_format = VIDEO_FORMAT_MPEG2; + output_h = 0; } cVideo::~cVideo(void) @@ -98,7 +99,7 @@ int cVideo::setAspectRatio(int vformat, int cropping) display_aspect = (DISPLAY_AR) vformat; if (cropping >= 0) display_crop = (DISPLAY_AR_MODE) cropping; - if (display_aspect < DISPLAY_AR_RAW) /* don't know what to do with this */ + if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */ glfb->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop); return 0; } @@ -197,7 +198,7 @@ int cVideo::SetVideoSystem(int system, bool) } v_std = (VIDEO_STD) system; output_h = h; - if (display_aspect < DISPLAY_AR_RAW) /* don't know what to do with this */ + if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */ glfb->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop); return 0; } From ad24fab431a4f0cc4c8b1ceff119cbf5664bba12 Mon Sep 17 00:00:00 2001 From: Jacek Jendrzej Date: Sun, 18 Jun 2017 13:15:35 +0200 Subject: [PATCH 07/73] fix compile --- generic-pc/video.cpp | 12 ++++++++++++ generic-pc/video_lib.h | 1 + 2 files changed, 13 insertions(+) diff --git a/generic-pc/video.cpp b/generic-pc/video.cpp index 208cc57..bf54a27 100644 --- a/generic-pc/video.cpp +++ b/generic-pc/video.cpp @@ -203,6 +203,18 @@ int cVideo::SetVideoSystem(int system, bool) return 0; } +int cVideo::GetVideoSystem() +{ + int current_video_system = VIDEO_STD_1080I50; + + if(dec_w < 720) + current_video_system = VIDEO_STD_PAL; + else if(dec_w > 720 && dec_w <= 1280) + current_video_system = VIDEO_STD_720P50; + + return 0; +} + int cVideo::getPlayState(void) { return VIDEO_PLAYING; diff --git a/generic-pc/video_lib.h b/generic-pc/video_lib.h index 3b075d4..e48aa71 100644 --- a/generic-pc/video_lib.h +++ b/generic-pc/video_lib.h @@ -177,6 +177,7 @@ class cVideo : public Thread /* set video_system */ int SetVideoSystem(int video_system, bool remember = true); + int GetVideoSystem(); int SetStreamType(VIDEO_FORMAT type); void SetSyncMode(AVSYNC_TYPE mode); bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; }; From d8c3c47b86cda823892c560a938ed01f17511985 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Tue, 12 Sep 2017 16:10:27 +0200 Subject: [PATCH 08/73] adding armbox --- Makefile.am | 6 + acinclude.m4 | 23 +- configure.ac | 7 + include/audio_hal.h | 3 + include/cs_api.h | 2 + include/dmx_hal.h | 2 + include/playback_hal.h | 2 + include/pwrmngr.h | 2 + include/record_hal.h | 2 + include/video_hal.h | 2 + libarmbox/Makefile.am | 28 + libarmbox/README.libtriple | 72 + libarmbox/audio.cpp | 480 ++++ libarmbox/audio_lib.h | 109 + libarmbox/audio_mixer.cpp | 68 + libarmbox/audio_mixer.h | 36 + libarmbox/cs_api.h | 66 + libarmbox/dmx.cpp | 615 ++++++ libarmbox/dmx_cs.h | 1 + libarmbox/dmx_lib.h | 72 + libarmbox/hardware_caps.c | 43 + libarmbox/init.cpp | 311 +++ libarmbox/init_cs.h | 2 + libarmbox/init_lib.h | 5 + libarmbox/irmp.c | 4284 ++++++++++++++++++++++++++++++++++++ libarmbox/irmp.h | 528 +++++ libarmbox/irmpconfig.h | 191 ++ libarmbox/lirmp_input.cpp | 445 ++++ libarmbox/lirmp_input.h | 7 + libarmbox/playback_gst.cpp | 837 +++++++ libarmbox/playback_gst.h | 97 + libarmbox/pwrmngr.cpp | 102 + libarmbox/pwrmngr.h | 53 + libarmbox/record.cpp | 383 ++++ libarmbox/record_lib.h | 57 + libarmbox/video.cpp | 1053 +++++++++ libarmbox/video_lib.h | 218 ++ 37 files changed, 10212 insertions(+), 2 deletions(-) create mode 100644 libarmbox/Makefile.am create mode 100644 libarmbox/README.libtriple create mode 100644 libarmbox/audio.cpp create mode 100644 libarmbox/audio_lib.h create mode 100644 libarmbox/audio_mixer.cpp create mode 100644 libarmbox/audio_mixer.h create mode 100644 libarmbox/cs_api.h create mode 100644 libarmbox/dmx.cpp create mode 100644 libarmbox/dmx_cs.h create mode 100644 libarmbox/dmx_lib.h create mode 100644 libarmbox/hardware_caps.c create mode 100644 libarmbox/init.cpp create mode 100644 libarmbox/init_cs.h create mode 100644 libarmbox/init_lib.h create mode 100644 libarmbox/irmp.c create mode 100644 libarmbox/irmp.h create mode 100644 libarmbox/irmpconfig.h create mode 100644 libarmbox/lirmp_input.cpp create mode 100644 libarmbox/lirmp_input.h create mode 100644 libarmbox/playback_gst.cpp create mode 100644 libarmbox/playback_gst.h create mode 100644 libarmbox/pwrmngr.cpp create mode 100644 libarmbox/pwrmngr.h create mode 100644 libarmbox/record.cpp create mode 100644 libarmbox/record_lib.h create mode 100644 libarmbox/video.cpp create mode 100644 libarmbox/video_lib.h diff --git a/Makefile.am b/Makefile.am index b901233..4fd06a1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,3 +52,9 @@ libstb_hal_la_LIBADD += \ libeplayer3/libeplayer3.la \ libdvbci/libdvbci.la endif +if BOXTYPE_ARMBOX +libstb_hal_test_LDADD += -lasound +SUBDIRS += libarmbox +libstb_hal_la_LIBADD += \ + libarmbox/libarmbox.la +endif diff --git a/acinclude.m4 b/acinclude.m4 index 6931874..f36f39a 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -273,7 +273,7 @@ _TUXBOX_APPS_LIB_SYMBOL($1,$2,$3,WARN) AC_DEFUN([TUXBOX_BOXTYPE],[ AC_ARG_WITH(boxtype, - [ --with-boxtype valid values: dbox2,tripledragon,dreambox,ipbox,coolstream,spark,azbox,generic,duckbox,spark7162], + [ --with-boxtype valid values: dbox2,tripledragon,dreambox,ipbox,coolstream,spark,azbox,generic,duckbox,spark7162,armbox], [case "${withval}" in dbox2|dreambox|ipbox|tripledragon|coolstream|azbox|generic) BOXTYPE="$withval" @@ -330,6 +330,10 @@ AC_ARG_WITH(boxtype, BOXTYPE="duckbox" BOXMODEL="$withval" ;; + armbox) + BOXTYPE="armbox" + BOXMODEL="$withval" + ;; *) AC_MSG_ERROR([bad value $withval for --with-boxtype]) ;; esac], [BOXTYPE="generic"]) @@ -338,7 +342,8 @@ AC_ARG_WITH(boxmodel, [ --with-boxmodel valid for dreambox: dm500, dm500plus, dm600pvr, dm56x0, dm7000, dm7020, dm7025 valid for ipbox: ip200, ip250, ip350, ip400 valid for duckbox: ufs910, ufs912, ufs913, ufs922, atevio7500, fortis_hdbox, octagon1008, hs7110, hs7810a, hs7119, hs7819, dp7000, cuberevo, cuberevo_mini, cuberevo_mini2, cuberevo_250hd, cuberevo_2000hd, cuberevo_3000hd, ipbox9900, ipbox99, ipbox55, arivalink200, tf7700, hl101 - valid for spark: spark, spark7162], + valid for spark: spark, spark7162 + valid for armbox: armbox], [case "${withval}" in dm500|dm500plus|dm600pvr|dm56x0|dm7000|dm7020|dm7025) if test "$BOXTYPE" = "dreambox"; then @@ -375,6 +380,13 @@ AC_ARG_WITH(boxmodel, AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE]) fi ;; + armbox) + if test "$BOXTYPE" = "armbox"; then + BOXMODEL="$withval" + else + AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE]) + fi + ;; *) AC_MSG_ERROR([unsupported value $withval for --with-boxmodel]) ;; @@ -395,6 +407,7 @@ AM_CONDITIONAL(BOXTYPE_COOL, test "$BOXTYPE" = "coolstream") AM_CONDITIONAL(BOXTYPE_SPARK, test "$BOXTYPE" = "spark") AM_CONDITIONAL(BOXTYPE_GENERIC, test "$BOXTYPE" = "generic") AM_CONDITIONAL(BOXTYPE_DUCKBOX, test "$BOXTYPE" = "duckbox") +AM_CONDITIONAL(BOXTYPE_ARMBOX, test "$BOXTYPE" = "armbox") AM_CONDITIONAL(BOXMODEL_DM500,test "$BOXMODEL" = "dm500") AM_CONDITIONAL(BOXMODEL_DM500PLUS,test "$BOXMODEL" = "dm500plus") @@ -437,6 +450,8 @@ AM_CONDITIONAL(BOXMODEL_HL101,test "$BOXMODEL" = "hl101") AM_CONDITIONAL(BOXMODEL_RASPI,test "$BOXMODEL" = "raspi") +AM_CONDITIONAL(BOXMODEL_ARMBOX,test "$BOXMODEL" = "armbox") + if test "$BOXTYPE" = "dbox2"; then AC_DEFINE(HAVE_DBOX_HARDWARE, 1, [building for a dbox2]) elif test "$BOXTYPE" = "azbox"; then @@ -451,6 +466,8 @@ elif test "$BOXTYPE" = "coolstream"; then AC_DEFINE(HAVE_COOL_HARDWARE, 1, [building for a coolstream]) elif test "$BOXTYPE" = "spark"; then AC_DEFINE(HAVE_SPARK_HARDWARE, 1, [building for a goldenmedia 990 or edision pingulux]) +elif test "$BOXTYPE" = "armbox"; then + AC_DEFINE(HAVE_ARM_HARDWARE, 1, [building for a armbox]) elif test "$BOXTYPE" = "generic"; then AC_DEFINE(HAVE_GENERIC_HARDWARE, 1, [building for a generic device like a standard PC]) elif test "$BOXTYPE" = "duckbox"; then @@ -522,6 +539,8 @@ elif test "$BOXMODEL" = "hl101"; then AC_DEFINE(BOXMODEL_HL101, 1, [hl101]) elif test "$BOXMODEL" = "raspi"; then AC_DEFINE(BOXMODEL_RASPI, 1, [Raspberry pi]) +elif test "$BOXMODEL" = "armbox"; then + AC_DEFINE(BOXMODEL_ARMBOX, 1, [armbox]) fi ]) diff --git a/configure.ac b/configure.ac index 82df74a..6335ce9 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,12 @@ if test "$enable_gstreamer_10" = "yes"; then PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0]) fi +if test x$BOXTYPE = xarmbox ; then + PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0]) + PKG_CHECK_MODULES([GSTREAMER_AUDIO], [gstreamer-audio-1.0]) + PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0]) +fi + if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1]) PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0]) @@ -66,6 +72,7 @@ libduckbox/Makefile libdvbci/Makefile libtriple/Makefile libspark/Makefile +libarmbox/Makefile raspi/Makefile tools/Makefile ]) diff --git a/include/audio_hal.h b/include/audio_hal.h index 984f2ef..6f50cd5 100644 --- a/include/audio_hal.h +++ b/include/audio_hal.h @@ -7,6 +7,9 @@ #elif HAVE_SPARK_HARDWARE #include "../libspark/audio_lib.h" #include "../libspark/audio_mixer.h" +#elif HAVE_ARM_HARDWARE +#include "../libarmbox/audio_lib.h" +#include "../libarmbox/audio_mixer.h" #elif HAVE_AZBOX_HARDWARE #include "../azbox/audio_lib.h" #elif HAVE_GENERIC_HARDWARE diff --git a/include/cs_api.h b/include/cs_api.h index 7364bff..58913c2 100644 --- a/include/cs_api.h +++ b/include/cs_api.h @@ -5,6 +5,8 @@ #include "../libduckbox/cs_api.h" #elif HAVE_SPARK_HARDWARE #include "../libspark/cs_api.h" +#elif HAVE_ARM_HARDWARE +#include "../libarmbox/cs_api.h" #elif HAVE_AZBOX_HARDWARE #include "../azbox/cs_api.h" #elif HAVE_GENERIC_HARDWARE diff --git a/include/dmx_hal.h b/include/dmx_hal.h index db4330f..db8ca72 100644 --- a/include/dmx_hal.h +++ b/include/dmx_hal.h @@ -7,6 +7,8 @@ #include "../libspark/dmx_lib.h" #elif HAVE_AZBOX_HARDWARE #include "../azbox/dmx_lib.h" +#elif HAVE_ARM_HARDWARE +#include "../libarmbox/dmx_lib.h" #elif HAVE_GENERIC_HARDWARE #if BOXMODEL_RASPI #include "../raspi/dmx_lib.h" diff --git a/include/playback_hal.h b/include/playback_hal.h index 82ec96a..982a856 100644 --- a/include/playback_hal.h +++ b/include/playback_hal.h @@ -5,6 +5,8 @@ #include "../libduckbox/playback_libeplayer3.h" #elif HAVE_SPARK_HARDWARE #include "../libspark/playback_libeplayer3.h" +#elif HAVE_ARM_HARDWARE +#include "../libarmbox/playback_gst.h" #elif HAVE_AZBOX_HARDWARE #include "../azbox/playback.h" #elif HAVE_GENERIC_HARDWARE diff --git a/include/pwrmngr.h b/include/pwrmngr.h index dea558f..74fc806 100644 --- a/include/pwrmngr.h +++ b/include/pwrmngr.h @@ -5,6 +5,8 @@ #include "../libduckbox/pwrmngr.h" #elif HAVE_SPARK_HARDWARE #include "../libspark/pwrmngr.h" +#elif HAVE_ARM_HARDWARE +#include "../libarmbox/pwrmngr.h" #elif HAVE_AZBOX_HARDWARE #include "../azbox/pwrmngr.h" #elif HAVE_GENERIC_HARDWARE diff --git a/include/record_hal.h b/include/record_hal.h index e4467b5..40f50e6 100644 --- a/include/record_hal.h +++ b/include/record_hal.h @@ -5,6 +5,8 @@ #include "../libduckbox/record_lib.h" #elif HAVE_SPARK_HARDWARE #include "../libspark/record_lib.h" +#elif HAVE_ARM_HARDWARE +#include "../libarmbox/record_lib.h" #elif HAVE_AZBOX_HARDWARE #include "../azbox/record_lib.h" #elif HAVE_GENERIC_HARDWARE diff --git a/include/video_hal.h b/include/video_hal.h index ec63331..db01265 100644 --- a/include/video_hal.h +++ b/include/video_hal.h @@ -5,6 +5,8 @@ #include "../libduckbox/video_lib.h" #elif HAVE_SPARK_HARDWARE #include "../libspark/video_lib.h" +#elif HAVE_ARM_HARDWARE +#include "../libarmbox/video_lib.h" #elif HAVE_AZBOX_HARDWARE #include "../azbox/video_lib.h" #elif HAVE_GENERIC_HARDWARE diff --git a/libarmbox/Makefile.am b/libarmbox/Makefile.am new file mode 100644 index 0000000..e3218f7 --- /dev/null +++ b/libarmbox/Makefile.am @@ -0,0 +1,28 @@ +noinst_LTLIBRARIES = libarmbox.la + +AM_CPPFLAGS = -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS +AM_CPPFLAGS += \ + -I$(top_srcdir)/common \ + -I$(top_srcdir)/include + +AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing + +AM_LDFLAGS = \ + -lOpenThreads \ + @AVFORMAT_LIBS@ \ + @AVUTIL_LIBS@ \ + @AVCODEC_LIBS@ \ + @SWRESAMPLE_LIBS@ \ + -lpthread -lasound -lass -lrt \ + -lgstreamer-1.0 + +libarmbox_la_SOURCES = \ + hardware_caps.c \ + dmx.cpp \ + video.cpp \ + audio.cpp \ + audio_mixer.cpp \ + init.cpp \ + playback_gst.cpp \ + pwrmngr.cpp \ + record.cpp diff --git a/libarmbox/README.libtriple b/libarmbox/README.libtriple new file mode 100644 index 0000000..89f65b7 --- /dev/null +++ b/libarmbox/README.libtriple @@ -0,0 +1,72 @@ +libtriple reimplements the interfaces of the libcoolstrem library for +the Tripledragon receiver. + +There are a few debugging or configuration helpers which affect the +way libtriple does some things. They are all configured by exporting +environment variables, which are described here: + +TRIPLE_NOSCART=1 - makes neutrino *not* do any voltage switching on + SCART pin 8, probably not useful for anyone but me + +TRIPLE_DEBUG=... - controls various debugging levels in libtriple + valid values for the different component: + audio 0x01 + video 0x02 + demux 0x04 + play 0x08 + power 0x10 + init 0x20 + ca 0x40 + record 0x80 + all 0xff + multiple levels are added / ORed together, so if you want to + debug record and playback code, do "export TRIPLE_DEBUG=0x88" + for audio & video use TRIPLE_DEBUG=0x3 + +DSP_DEVICE +MIX_DEVICE - alternative audio devices for the audioplayer and internet + radio. Those are used to output music to e.g. USB audio devices. + Here is what you need to do: + * look in /dev/sound which devices are already there. Probably + /dev/sound/dsp and /dev/sound/mixer, created by the tdoss driver + * make sure that the USB HC driver is loaded: + modprobe ohci-hcd + * load the USB audio driver: + modprobe audio + * plug in your USB audio device, check with "dmesg" that it is + recognised by the kernel + * look in /dev/sound which new devices are there. Probably it's + /dev/sound/dsp1 and /dev/sound/mixer1. If there are more - well + it's time to experiment ;) + * export DSP_DEVICE=/dev/sound/dsp1 and MIX_DEVICE=/dev/sound/mixer1 + (of course the devices you found in the last step) + * from the same shell you exported the variables, start neutrino + (make sure that an already running neutrino is stopped before you + do that) + * start the audioplayer, play a track. Look for log lines like + [LT:106b5788:audio ] PrepareClipPlay: dsp_dev /dev/sound/dsp1 mix_dev /dev/sound/mixer1 + * if it works - fine :-) + * if it does not work, look for: + PrepareClipPlay: DSP_DEVICE is set (/dev/sound/dsp1) but cannot be opened, fall back to /dev/sound/dsp + PrepareClipPlay: dsp_dev /dev/sound/dsp mix_dev /dev/sound/mixer1 + PrepareClipPlay: open mixer /dev/sound/mixer1 failed (No such file or directory) + * this basically means that the device is not there. Different errors + will get different messages - I cannot trigger those now, so you'll + need to find them out by yourself ;) + * another possible messag you may get is: + PrepareClipPlay: more than one mixer control: devmask 00000021 stereo 00000021 + This means that your device has more than one mixer. The set bit + numbers in the devmask are the different mixers, in this case + it would be number 0 and 5. To select one of those, export + MIX_NUMBER=5 or MIX_NUMBER=0 (this code is untested, there may + be bugs) + + So now I found out what devices to use, but how do I make that permanent? + That's easy: + * create or extend /etc/rcS.local with + modprobe ohci-hcd + modprobe audio + * create or extend /etc/profile.local with + export DSP_DEVICE=/dev/sound/dsp1 + export MIX_DEVICE=/dev/sound/mixer1 + * reboot. Enjoy. diff --git a/libarmbox/audio.cpp b/libarmbox/audio.cpp new file mode 100644 index 0000000..7a55814 --- /dev/null +++ b/libarmbox/audio.cpp @@ -0,0 +1,480 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include "audio_lib.h" +#include "audio_mixer.h" +#include "lt_debug.h" + +#define AUDIO_DEVICE "/dev/dvb/adapter0/audio0" +#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_AUDIO, this, args) +#define lt_info(args...) _lt_info(TRIPLE_DEBUG_AUDIO, this, args) + +#include + +cAudio * audioDecoder = NULL; + +static int proc_put(const char *path, const char *value, const int len) +{ + int ret, ret2; + int pfd = open(path, O_WRONLY); + if (pfd < 0) + return pfd; + ret = write(pfd, value, len); + ret2 = close(pfd); + if (ret2 < 0) + return ret2; + return ret; +} + +cAudio::cAudio(void *, void *, void *) +{ + fd = -1; + clipfd = -1; + mixer_fd = -1; + + mixerAnalog = mixerHDMI = mixerSPDIF = NULL; + volumeAnalog = volumeHDMI = volumeSPDIF = 0; + mixersMuted = false; + + openDevice(); + Muted = false; +} + +cAudio::~cAudio(void) +{ + closeMixers(); + closeDevice(); +} + +void cAudio::openDevice(void) +{ + openMixers(); + + if (fd < 0) + { + if ((fd = open(AUDIO_DEVICE, O_RDWR)) < 0) + lt_info("openDevice: open failed (%m)\n"); + fcntl(fd, F_SETFD, FD_CLOEXEC); + do_mute(true, false); + } + else + lt_info("openDevice: already open (fd = %d)\n", fd); +} + +void cAudio::closeDevice(void) +{ + closeMixers(); + + if (fd > -1) { + close(fd); + fd = -1; + } + if (clipfd > -1) { + close(clipfd); + clipfd = -1; + } + if (mixer_fd > -1) { + close(mixer_fd); + mixer_fd = -1; + } +} + +int cAudio::do_mute(bool enable, bool remember) +{ + lt_debug("%s(%d, %d)\n", __FUNCTION__, enable, remember); + char str[4]; + + if (remember) + Muted = enable; + + sprintf(str, "%d", Muted); + proc_put("/proc/stb/audio/j1_mute", str, strlen(str)); + + if (!enable) + { + int f = open("/proc/stb/avs/0/volume", O_RDWR); + read(f, str, 4); + close(f); + str[3] = '\0'; + proc_put("/proc/stb/avs/0/volume", str, strlen(str)); + } + return 0; +} + +int map_volume(const int volume) +{ + unsigned char vol = volume; + if (vol > 100) + vol = 100; + + vol = 63 - vol * 63 / 100; + return vol; +} + + +int cAudio::setVolume(unsigned int left, unsigned int right) +{ + lt_debug("%s(%d, %d)\n", __func__, left, right); + + volume = (left + right) / 2; + int v = map_volume(volume); +#if 0 + if (clipfd != -1 && mixer_fd != -1) { + int tmp = 0; + /* not sure if left / right is correct here, but it is always the same anyways ;-) */ + if (! Muted) + tmp = left << 8 | right; + int ret = ioctl(mixer_fd, MIXER_WRITE(mixer_num), &tmp); + if (ret == -1) + lt_info("%s: MIXER_WRITE(%d),%04x: %m\n", __func__, mixer_num, tmp); + return ret; + } +#endif + + char str[4]; + sprintf(str, "%d", v); + + proc_put("/proc/stb/avs/0/volume", str, strlen(str)); + return 0; +} + +int cAudio::Start(void) +{ + int ret; + ret = ioctl(fd, AUDIO_PLAY); + return ret; +} + +int cAudio::Stop(void) +{ + return ioctl(fd, AUDIO_STOP); +} + +bool cAudio::Pause(bool Pcm) +{ + ioctl(fd, Pcm ? AUDIO_PAUSE : AUDIO_CONTINUE, 1); + return true; +} + +void cAudio::SetSyncMode(AVSYNC_TYPE Mode) +{ + lt_debug("%s %d\n", __func__, Mode); + ioctl(fd, AUDIO_SET_AV_SYNC, Mode); +} + +// E2 streamtype values. These correspond to +// player2/linux/drivers/media/dvb/stm/dvb/dvb_audio.c:AudioIoctlSetBypassMode +#define AUDIO_STREAMTYPE_AC3 0 +#define AUDIO_STREAMTYPE_MPEG 1 +#define AUDIO_STREAMTYPE_DTS 2 +#define AUDIO_STREAMTYPE_AAC 8 +#define AUDIO_STREAMTYPE_AACHE 9 + +void cAudio::SetStreamType(AUDIO_FORMAT type) +{ + int bypass = AUDIO_STREAMTYPE_MPEG; + lt_debug("%s %d\n", __FUNCTION__, type); + StreamType = type; + + switch (type) + { + case AUDIO_FMT_DD_PLUS: + case AUDIO_FMT_DOLBY_DIGITAL: + bypass = AUDIO_STREAMTYPE_AC3; + break; + case AUDIO_FMT_AAC: + bypass = AUDIO_STREAMTYPE_AAC; + break; + case AUDIO_FMT_AAC_PLUS: + bypass = AUDIO_STREAMTYPE_AACHE; + break; + case AUDIO_FMT_DTS: + bypass = AUDIO_STREAMTYPE_DTS; + break; + default: + break; + } + + // Normaly the encoding should be set using AUDIO_SET_ENCODING + // But as we implemented the behavior to bypass (cause of e2) this is correct here + if (ioctl(fd, AUDIO_SET_BYPASS_MODE, bypass) < 0) + lt_info("%s: AUDIO_SET_BYPASS_MODE failed (%m)\n", __func__); +} + +int cAudio::setChannel(int channel) +{ + lt_debug("%s %d\n", __FUNCTION__, channel); + return 0; +} + +int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian) +{ + int fmt; + unsigned int devmask, stereo, usable; + const char *dsp_dev = getenv("DSP_DEVICE"); + const char *mix_dev = getenv("MIX_DEVICE"); + lt_debug("%s ch %d srate %d bits %d le %d\n", __FUNCTION__, ch, srate, bits, little_endian); + if (clipfd > -1) { + lt_info("%s: clipfd already opened (%d)\n", __FUNCTION__, clipfd); + return -1; + } + mixer_num = -1; + /* a different DSP device can be given with DSP_DEVICE and MIX_DEVICE + * if this device cannot be opened, we fall back to the internal OSS device + * Example: + * modprobe snd-usb-audio + * export DSP_DEVICE=/dev/sound/dsp2 + * export MIX_DEVICE=/dev/sound/mixer2 + * neutrino + */ + if ((!dsp_dev) || (access(dsp_dev, W_OK))) { + if (dsp_dev) + lt_info("%s: DSP_DEVICE is set (%s) but cannot be opened," + " fall back to /dev/dsp1\n", __func__, dsp_dev); + dsp_dev = "/dev/dsp1"; + } + lt_info("%s: dsp_dev %s mix_dev %s\n", __func__, dsp_dev, mix_dev); /* NULL mix_dev is ok */ + /* the tdoss dsp driver seems to work only on the second open(). really. */ + clipfd = open(dsp_dev, O_WRONLY); + if (clipfd < 0) { + lt_info("%s open %s: %m\n", dsp_dev, __FUNCTION__); + return -1; + } + fcntl(clipfd, F_SETFD, FD_CLOEXEC); + /* no idea if we ever get little_endian == 0 */ + if (little_endian) + fmt = AFMT_S16_BE; + else + fmt = AFMT_S16_LE; + if (ioctl(clipfd, SNDCTL_DSP_SETFMT, &fmt)) + perror("SNDCTL_DSP_SETFMT"); + if (ioctl(clipfd, SNDCTL_DSP_CHANNELS, &ch)) + perror("SNDCTL_DSP_CHANNELS"); + if (ioctl(clipfd, SNDCTL_DSP_SPEED, &srate)) + perror("SNDCTL_DSP_SPEED"); + if (ioctl(clipfd, SNDCTL_DSP_RESET)) + perror("SNDCTL_DSP_RESET"); + + if (!mix_dev) + return 0; + + mixer_fd = open(mix_dev, O_RDWR); + if (mixer_fd < 0) { + lt_info("%s: open mixer %s failed (%m)\n", __func__, mix_dev); + /* not a real error */ + return 0; + } + if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { + lt_info("%s: SOUND_MIXER_READ_DEVMASK %m\n", __func__); + devmask = 0; + } + if (ioctl(mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { + lt_info("%s: SOUND_MIXER_READ_STEREODEVS %m\n", __func__); + stereo = 0; + } + usable = devmask & stereo; + if (usable == 0) { + lt_info("%s: devmask: %08x stereo: %08x, no usable dev :-(\n", + __func__, devmask, stereo); + close(mixer_fd); + mixer_fd = -1; + return 0; /* TODO: should we treat this as error? */ + } + /* __builtin_popcount needs GCC, it counts the set bits... */ + if (__builtin_popcount (usable) != 1) { + /* TODO: this code is not yet tested as I have only single-mixer devices... */ + lt_info("%s: more than one mixer control: devmask %08x stereo %08x\n" + "%s: querying MIX_NUMBER environment variable...\n", + __func__, devmask, stereo, __func__); + const char *tmp = getenv("MIX_NUMBER"); + if (tmp) + mixer_num = atoi(tmp); + lt_info("%s: mixer_num is %d -> device %08x\n", + __func__, mixer_num, (mixer_num >= 0) ? (1 << mixer_num) : 0); + /* no error checking, you'd better know what you are doing... */ + } else { + mixer_num = 0; + while (!(usable & 0x01)) { + mixer_num++; + usable >>= 1; + } + } + setVolume(volume, volume); + + return 0; +} + +int cAudio::WriteClip(unsigned char *buffer, int size) +{ + int ret; + // lt_debug("cAudio::%s\n", __FUNCTION__); + if (clipfd < 0) { + lt_info("%s: clipfd not yet opened\n", __FUNCTION__); + return -1; + } + ret = write(clipfd, buffer, size); + if (ret < 0) + lt_info("%s: write error (%m)\n", __FUNCTION__); + return ret; +}; + +int cAudio::StopClip() +{ + lt_debug("%s\n", __FUNCTION__); + if (clipfd < 0) { + lt_info("%s: clipfd not yet opened\n", __FUNCTION__); + return -1; + } + close(clipfd); + clipfd = -1; + if (mixer_fd >= -1) { + close(mixer_fd); + mixer_fd = -1; + } + setVolume(volume, volume); + return 0; +}; + +void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode) +{ + lt_debug("%s\n", __FUNCTION__); + type = 0; + layer = 0; + freq = 0; + bitrate = 0; + mode = 0; +#if 0 + unsigned int atype; + static const int freq_mpg[] = {44100, 48000, 32000, 0}; + static const int freq_ac3[] = {48000, 44100, 32000, 0}; + scratchl2 i; + if (ioctl(fd, MPEG_AUD_GET_DECTYP, &atype) < 0) + perror("cAudio::getAudioInfo MPEG_AUD_GET_DECTYP"); + if (ioctl(fd, MPEG_AUD_GET_STATUS, &i) < 0) + perror("cAudio::getAudioInfo MPEG_AUD_GET_STATUS"); + + type = atype; +#if 0 +/* this does not work, some of the values are negative?? */ + AMPEGStatus A; + memcpy(&A, &i.word00, sizeof(i.word00)); + layer = A.audio_mpeg_layer; + mode = A.audio_mpeg_mode; + bitrate = A.audio_mpeg_bitrate; + switch(A.audio_mpeg_frequency) +#endif + /* layer and bitrate are not used anyway... */ + layer = 0; //(i.word00 >> 17) & 3; + bitrate = 0; //(i.word00 >> 12) & 3; + switch (type) + { + case 0: /* MPEG */ + mode = (i.word00 >> 6) & 3; + freq = freq_mpg[(i.word00 >> 10) & 3]; + break; + case 1: /* AC3 */ + mode = (i.word00 >> 28) & 7; + freq = freq_ac3[(i.word00 >> 16) & 3]; + break; + default: + mode = 0; + freq = 0; + } + //fprintf(stderr, "type: %d layer: %d freq: %d bitrate: %d mode: %d\n", type, layer, freq, bitrate, mode); +#endif +}; + +void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/) +{ + lt_debug("%s\n", __FUNCTION__); +}; + +void cAudio::SetHdmiDD(bool enable) +{ + const char *opt[] = { "pcm", "spdif" }; + lt_debug("%s %d\n", __func__, enable); + proc_put("/proc/stb/hdmi/audio_source", opt[enable], strlen(opt[enable])); +} + +void cAudio::SetSpdifDD(bool enable) +{ + lt_debug("%s %d\n", __func__, enable); + setBypassMode(!enable); +} + +void cAudio::ScheduleMute(bool On) +{ + lt_debug("%s %d\n", __FUNCTION__, On); +} + +void cAudio::EnableAnalogOut(bool enable) +{ + lt_debug("%s %d\n", __FUNCTION__, enable); +} + +#define AUDIO_BYPASS_ON 0 +#define AUDIO_BYPASS_OFF 1 +void cAudio::setBypassMode(bool disable) +{ + const char *opt[] = { "passthrough", "downmix" }; + lt_debug("%s %d\n", __func__, disable); + proc_put("/proc/stb/audio/ac3", opt[disable], strlen(opt[disable])); +} + +void cAudio::openMixers(void) +{ + if (!mixerAnalog) + mixerAnalog = new mixerVolume("Analog", "1"); + if (!mixerHDMI) + mixerHDMI = new mixerVolume("HDMI", "1"); + if (!mixerSPDIF) + mixerSPDIF = new mixerVolume("SPDIF", "1"); +} + +void cAudio::closeMixers(void) +{ + delete mixerAnalog; + delete mixerHDMI; + delete mixerSPDIF; + mixerAnalog = mixerHDMI = mixerSPDIF = NULL; +} + +void cAudio::setMixerVolume(const char *name, long value, bool remember) +{ + if (!strcmp(name, "Analog")) { + mixerAnalog->setVolume(value); + if (remember) + volumeAnalog = value; + } + if (!strcmp(name, "HDMI")) { + mixerHDMI->setVolume(value); + if (remember) + volumeHDMI = value; + } + if (!strcmp(name, "SPDIF")) { + mixerSPDIF->setVolume(value); + if (remember) + volumeSPDIF = value; + } +} + +void cAudio::muteMixers(bool m) +{ + if (m && !mixersMuted) { + mixersMuted = true; + setMixerVolume("Analog", 0, false); + setMixerVolume("HDMI", 0, false); + setMixerVolume("SPDIF", 0, false); + } else if (!m && mixersMuted) { + mixersMuted = false; + setMixerVolume("Analog", volumeAnalog, false); + setMixerVolume("HDMI", volumeHDMI, false); + setMixerVolume("SPDIF", volumeSPDIF, false); + } +} diff --git a/libarmbox/audio_lib.h b/libarmbox/audio_lib.h new file mode 100644 index 0000000..b2b78d6 --- /dev/null +++ b/libarmbox/audio_lib.h @@ -0,0 +1,109 @@ +/* public header file */ + +#ifndef _AUDIO_TD_H_ +#define _AUDIO_TD_H_ +#include "../common/cs_types.h" + +typedef enum +{ + AUDIO_SYNC_WITH_PTS, + AUDIO_NO_SYNC, + AUDIO_SYNC_AUDIO_MASTER +} AUDIO_SYNC_MODE; + +typedef enum { + HDMI_ENCODED_OFF, + HDMI_ENCODED_AUTO, + HDMI_ENCODED_FORCED +} HDMI_ENCODED_MODE; + +typedef enum +{ + AUDIO_FMT_AUTO = 0, + AUDIO_FMT_MPEG, + AUDIO_FMT_MP3, + AUDIO_FMT_DOLBY_DIGITAL, + AUDIO_FMT_BASIC = AUDIO_FMT_DOLBY_DIGITAL, + AUDIO_FMT_AAC, + AUDIO_FMT_AAC_PLUS, + AUDIO_FMT_DD_PLUS, + AUDIO_FMT_DTS, + AUDIO_FMT_AVS, + AUDIO_FMT_MLP, + AUDIO_FMT_WMA, + AUDIO_FMT_MPG1, // TD only. For Movieplayer / cPlayback + AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP +} AUDIO_FORMAT; + +class mixerVolume; + +class cAudio +{ + friend class cPlayback; + private: + int fd; + bool Muted; + + int clipfd; /* for pcm playback */ + int mixer_fd; /* if we are using the OSS mixer */ + int mixer_num; /* oss mixer to use, if any */ + + AUDIO_FORMAT StreamType; + AUDIO_SYNC_MODE SyncMode; + bool started; + + int volume; + + void openDevice(void); + void closeDevice(void); + + int do_mute(bool enable, bool remember); + void setBypassMode(bool disable); + + mixerVolume *mixerAnalog, *mixerHDMI, *mixerSPDIF; + int volumeAnalog, volumeHDMI, volumeSPDIF; + bool mixersMuted; + + public: + /* construct & destruct */ + cAudio(void *, void *, void *); + ~cAudio(void); + + void *GetHandle() { return NULL; }; + /* shut up */ + int mute(bool remember = true) { return do_mute(true, remember); }; + int unmute(bool remember = true) { return do_mute(false, remember); }; + + /* volume, min = 0, max = 255 */ + int setVolume(unsigned int left, unsigned int right); + int getVolume(void) { return volume;} + bool getMuteStatus(void) { return Muted; }; + + /* start and stop audio */ + int Start(void); + int Stop(void); + bool Pause(bool Pcm = true); + void SetStreamType(AUDIO_FORMAT type); + AUDIO_FORMAT GetStreamType(void) { return StreamType; } + void SetSyncMode(AVSYNC_TYPE Mode); + + /* select channels */ + int setChannel(int channel); + int PrepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian); + int WriteClip(unsigned char * buffer, int size); + int StopClip(); + void getAudioInfo(int &type, int &layer, int& freq, int &bitrate, int &mode); + void SetSRS(int iq_enable, int nmgr_enable, int iq_mode, int iq_level); + bool IsHdmiDDSupported() { return true; }; + void SetHdmiDD(bool enable); + void SetSpdifDD(bool enable); + void ScheduleMute(bool On); + void EnableAnalogOut(bool enable); + + void openMixers(void); + void closeMixers(void); + void setMixerVolume(const char *name, long value, bool remember = true); + void muteMixers(bool m = true); +}; + +#endif diff --git a/libarmbox/audio_mixer.cpp b/libarmbox/audio_mixer.cpp new file mode 100644 index 0000000..f361209 --- /dev/null +++ b/libarmbox/audio_mixer.cpp @@ -0,0 +1,68 @@ +/* + * audio_mixer.cpp + * + * (C) 2012 martii + * + * 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, see . + */ + +#include + +mixerVolume::mixerVolume(const char *name, const char *card, long volume) { + snd_mixer_selem_id_t *sid = NULL; + elem = NULL; + handle = NULL; + min = 0; + max = 100; + char cardId[10]; + + if (!name || !card) + return; + + int cx = snd_card_get_index(card); + if (cx < 0 || cx > 31) + return; + snprintf(cardId, sizeof(cardId), "hw:%i", cx); + + if (0 > snd_mixer_open(&handle, 0)) + return; + if (0 > snd_mixer_attach(handle, cardId)) + return; + if (0 > snd_mixer_selem_register(handle, NULL, NULL)) + return; + if (0 > snd_mixer_load(handle)) + return; + snd_mixer_selem_id_alloca(&sid); + if (!sid) + return; + snd_mixer_selem_id_set_index(sid, 0); + snd_mixer_selem_id_set_name(sid, name); + elem = snd_mixer_find_selem(handle, sid); + if (elem) { + snd_mixer_selem_get_playback_volume_range(elem, &min, &max); + setVolume(volume); + } +} +mixerVolume::~mixerVolume() +{ + if (handle) + snd_mixer_close(handle); +} + +bool mixerVolume::setVolume(long volume) { + return elem + && (volume > -1) + && (volume < 101) + && !snd_mixer_selem_set_playback_volume_all(elem, min + volume * (max - min)/100); +} diff --git a/libarmbox/audio_mixer.h b/libarmbox/audio_mixer.h new file mode 100644 index 0000000..2a6f6fc --- /dev/null +++ b/libarmbox/audio_mixer.h @@ -0,0 +1,36 @@ +/* + * audio_mixer.h + * + * (C) 2012 martii + * + * 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, see . + */ + +#ifndef __AUDIO_MIXER_H__ +#define __AUDIO_MIXER_H__ +#include + +class mixerVolume +{ + private: + long min, max; + snd_mixer_t *handle; + snd_mixer_elem_t* elem; + public: + mixerVolume(const char *selem_name, const char *Card, long volume = -1); + ~mixerVolume(void); + bool setVolume(long volume); +}; +#endif + diff --git a/libarmbox/cs_api.h b/libarmbox/cs_api.h new file mode 100644 index 0000000..fb5d613 --- /dev/null +++ b/libarmbox/cs_api.h @@ -0,0 +1,66 @@ +/* compatibility header for tripledragon. I'm lazy, so I just left it + as "cs_api.h" so that I don't need too many ifdefs in the code */ + +#ifndef __CS_API_H_ +#define __CS_API_H_ + +#include "init_lib.h" +typedef void (*cs_messenger) (unsigned int msg, unsigned int data); + +#if 0 +enum CS_LOG_MODULE { + CS_LOG_CI = 0, + CS_LOG_HDMI_CEC, + CS_LOG_HDMI, + CS_LOG_VIDEO, + CS_LOG_VIDEO_DRM, + CS_LOG_AUDIO, + CS_LOG_DEMUX, + CS_LOG_DENC, + CS_LOG_PVR_RECORD, + CS_LOG_PVR_PLAY, + CS_LOG_POWER_CTRL, + CS_LOG_POWER_CLK, + CS_LOG_MEM, + CS_LOG_API, +}; +#endif + +inline void cs_api_init() +{ + init_td_api(); +}; + +inline void cs_api_exit() +{ + shutdown_td_api(); +}; + +#define cs_malloc_uncached malloc +#define cs_free_uncached free + +// Callback function helpers +static inline void cs_register_messenger(cs_messenger) { return; }; +static inline void cs_deregister_messenger(void) { return; }; +//cs_messenger cs_get_messenger(void); + +#if 0 +// Logging functions +void cs_log_enable(void); +void cs_log_disable(void); +void cs_log_message(const char *prefix, const char *fmt, ...); +void cs_log_module_enable(enum CS_LOG_MODULE module); +void cs_log_module_disable(enum CS_LOG_MODULE module); +void cs_log_module_message(enum CS_LOG_MODULE module, const char *fmt, ...); + +// TS Routing +unsigned int cs_get_ts_output(void); +int cs_set_ts_output(unsigned int port); + +// Serial nr and revision accessors +unsigned long long cs_get_serial(void); +#endif +/* compat... HD1 seems to be version 6. everything newer ist > 6... */ +static inline unsigned int cs_get_revision(void) { return 1; }; +extern int cnxt_debug; +#endif //__CS_API_H_ diff --git a/libarmbox/dmx.cpp b/libarmbox/dmx.cpp new file mode 100644 index 0000000..d3ba4e7 --- /dev/null +++ b/libarmbox/dmx.cpp @@ -0,0 +1,615 @@ +/* + * cDemux implementation for SH4 receivers (tested on fulan spark and + * fulan spark7162 hardware) + * + * derived from libtriple/dmx_td.cpp + * + * (C) 2010-2013 Stefan Seyfried + * + * 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, see . + */ + +/* + * Theory of operation (or "why is this dmx_source thing so strange and + * what is the _open() good for?") + * + * the sh4 pti driver, driving the /dev/dvb/adapter0/dmxN devices, can + * apparently only map one input to on demux device at a time, so e.g. + * DMX_SOURCE_FRONT1 -> demux0 + * DMX_SOURCE_FRONT2 -> demux0 + * DMX_SOURCE_FRONT1 -> demux1 + * does not work. The driver makes sure that a one-to-one mapping of + * DMX_SOURCE_FRONTn to demuxM is maintained, and it does by e.g changing + * the default of + * FRONT0 -> demux0 + * FRONT1 -> demux1 + * FRONT2 -> demux2 + * to + * FRONT1 -> demux0 + * FRONT0 -> demux1 + * FRONT2 -> demux2 + * if you do a DMX_SET_SOURCE(FRONT1) ioctl on demux0. + * This means, it also changes demux1's source on the SET_SOURCE ioctl on + * demux0, potentially disturbing any operation on demux1 (e.g. recording). + * + * In order to avoid this, I do not change the source->demuxdev mapping + * but instead just always use the demux device that is attached to the + * correct source. + * + * The tricky part is, that the source might actually be changed after + * Open() has been called, so Open() gets a dummy placeholder that just + * sets some variables while the real device open is put into _open(). + * _open() gets called later, whenever the device is actually used or + * configured and -- if the source has changed -- closes the old and + * opens the correct new device node. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "dmx_lib.h" +#include "lt_debug.h" + +/* Ugh... see comment in destructor for details... */ +#include "video_lib.h" +extern cVideo *videoDecoder; + +#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args) +#define lt_info(args...) _lt_info(TRIPLE_DEBUG_DEMUX, this, args) +#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_DEMUX, NULL, args) + +#define dmx_err(_errfmt, _errstr, _revents) do { \ + uint16_t _pid = (uint16_t)-1; uint16_t _f = 0;\ + if (dmx_type == DMX_PSI_CHANNEL) { \ + _pid = s_flt.pid; _f = s_flt.filter.filter[0]; \ + } else { \ + _pid = p_flt.pid; \ + }; \ + lt_info("%s " _errfmt " fd:%d, ev:0x%x %s pid:0x%04hx flt:0x%02hx\n", \ + __func__, _errstr, fd, _revents, DMX_T[dmx_type], _pid, _f); \ +} while(0); + +cDemux *videoDemux = NULL; +cDemux *audioDemux = NULL; +//cDemux *pcrDemux = NULL; + +static const char *DMX_T[] = { + "DMX_INVALID", + "DMX_VIDEO", + "DMX_AUDIO", + "DMX_PES", + "DMX_PSI", + "DMX_PIP", + "DMX_TP", + "DMX_PCR" +}; + +/* this is the number of different cDemux() units, not the number of + * /dev/dvb/.../demuxX devices! */ +#define NUM_DEMUX 4 +/* the current source of each cDemux unit */ +static int dmx_source[NUM_DEMUX] = { 0, 0, 0, 0 }; + +/* map the device numbers. */ +#define NUM_DEMUXDEV 3 +static const char *devname[NUM_DEMUXDEV] = { + "/dev/dvb/adapter0/demux0", + "/dev/dvb/adapter0/demux1", + "/dev/dvb/adapter0/demux2" +}; +/* did we already DMX_SET_SOURCE on that demux device? */ +static bool init[NUM_DEMUXDEV] = { false, false, false }; + +/* uuuugly */ +static int dmx_tp_count = 0; +#define MAX_TS_COUNT 1 + +cDemux::cDemux(int n) +{ + if (n < 0 || n >= NUM_DEMUX) + { + lt_info("%s ERROR: n invalid (%d)\n", __FUNCTION__, n); + num = 0; + } + else + num = n; + fd = -1; + measure = false; + last_measure = 0; + last_data = 0; + last_source = -1; +} + +cDemux::~cDemux() +{ + lt_debug("%s #%d fd: %d\n", __FUNCTION__, num, fd); + Close(); + /* in zapit.cpp, videoDemux is deleted after videoDecoder + * in the video watchdog, we access videoDecoder + * the thread still runs after videoDecoder has been deleted + * => set videoDecoder to NULL here to make the check in the + * watchdog thread pick this up. + * This is ugly, but it saves me from changing neutrino + * + * if the delete order in neutrino will ever be changed, this + * will blow up badly :-( + */ + if (dmx_type == DMX_VIDEO_CHANNEL) + videoDecoder = NULL; +} + +bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize) +{ + if (fd > -1) + lt_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd); + + dmx_type = pes_type; + buffersize = uBufferSize; + + /* return code is unchecked anyway... */ + return true; +} + +bool cDemux::_open(void) +{ + int flags = O_RDWR|O_CLOEXEC; + int devnum = dmx_source[num]; + if (last_source == devnum) { + lt_debug("%s #%d: source (%d) did not change\n", __func__, num, last_source); + if (fd > -1) + return true; + } + if (fd > -1) { + /* we changed source -> close and reopen the fd */ + lt_debug("%s #%d: FD ALREADY OPENED fd = %d lastsource %d devnum %d\n", + __func__, num, fd, last_source, devnum); + close(fd); + } + + if (dmx_type != DMX_PSI_CHANNEL) + flags |= O_NONBLOCK; + + fd = open(devname[devnum], flags); + if (fd < 0) + { + lt_info("%s %s: %m\n", __FUNCTION__, devname[devnum]); + return false; + } + lt_debug("%s #%d pes_type: %s(%d), uBufferSize: %d fd: %d\n", __func__, + num, DMX_T[dmx_type], dmx_type, buffersize, fd); + + /* this would actually need locking, but the worst that weill happen is, that + * we'll DMX_SET_SOURCE twice per device, so don't bother... */ + if (!init[devnum]) + { + /* this should not change anything... */ + int n = DMX_SOURCE_FRONT0 + devnum; + lt_info("%s: setting %s to source %d\n", __func__, devname[devnum], n); + if (ioctl(fd, DMX_SET_SOURCE, &n) < 0) + lt_info("%s DMX_SET_SOURCE failed!\n", __func__); + else + init[devnum] = true; + } + if (buffersize == 0) + buffersize = 0xffff; // may or may not be reasonable --martii + if (buffersize > 0) + { + /* probably uBufferSize == 0 means "use default size". TODO: find a reasonable default */ + if (ioctl(fd, DMX_SET_BUFFER_SIZE, buffersize) < 0) + lt_info("%s DMX_SET_BUFFER_SIZE failed (%m)\n", __func__); + } + + last_source = devnum; + return true; +} + +void cDemux::Close(void) +{ + lt_debug("%s #%d, fd = %d\n", __FUNCTION__, num, fd); + if (fd < 0) + { + lt_info("%s #%d: not open!\n", __FUNCTION__, num); + return; + } + + pesfds.clear(); + ioctl(fd, DMX_STOP); + close(fd); + fd = -1; + if (measure) + return; + if (dmx_type == DMX_TP_CHANNEL) + { + dmx_tp_count--; + if (dmx_tp_count < 0) + { + lt_info("%s dmx_tp_count < 0!!\n", __func__); + dmx_tp_count = 0; + } + } +} + +bool cDemux::Start(bool) +{ + if (fd < 0) + { + lt_info("%s #%d: not open!\n", __FUNCTION__, num); + return false; + } + ioctl(fd, DMX_START); + return true; +} + +bool cDemux::Stop(void) +{ + if (fd < 0) + { + lt_info("%s #%d: not open!\n", __FUNCTION__, num); + return false; + } + ioctl(fd, DMX_STOP); + return true; +} + +int cDemux::Read(unsigned char *buff, int len, int timeout) +{ +#if 0 + if (len != 4095 && timeout != 10) + fprintf(stderr, "cDemux::%s #%d fd: %d type: %s len: %d timeout: %d\n", + __FUNCTION__, num, fd, DMX_T[dmx_type], len, timeout); +#endif + if (fd < 0) + { + lt_info("%s #%d: not open!\n", __func__, num); + return -1; + } + int rc; + int to = timeout; + struct pollfd ufds; + ufds.fd = fd; + ufds.events = POLLIN|POLLPRI|POLLERR; + ufds.revents = 0; + + /* hack: if the frontend loses and regains lock, the demuxer often will not + * return from read(), so as a "emergency exit" for e.g. NIT scan, set a (long) + * timeout here */ + if (dmx_type == DMX_PSI_CHANNEL && timeout <= 0) + to = 60 * 1000; + + if (to > 0) + { + retry: + rc = ::poll(&ufds, 1, to); + if (!rc) + { + if (timeout == 0) /* we took the emergency exit */ + { + dmx_err("timed out for timeout=0!, %s", "", 0); + return -1; /* this timeout is an error */ + } + return 0; // timeout + } + else if (rc < 0) + { + dmx_err("poll: %s,", strerror(errno), 0) + //lt_info("%s poll: %m\n", __FUNCTION__); + /* happens, when running under gdb... */ + if (errno == EINTR) + goto retry; + return -1; + } +#if 0 + if (ufds.revents & POLLERR) /* POLLERR means buffer error, i.e. buffer overflow */ + { + dmx_err("received %s,", "POLLERR", ufds.revents); + /* this seems to happen sometimes at recording start, without bad effects */ + return 0; + } +#endif + if (ufds.revents & POLLHUP) /* we get POLLHUP if e.g. a too big DMX_BUFFER_SIZE was set */ + { + dmx_err("received %s,", "POLLHUP", ufds.revents); + return -1; + } + if (!(ufds.revents & POLLIN)) /* we requested POLLIN but did not get it? */ + { + dmx_err("received %s, please report!", "POLLIN", ufds.revents); + return 0; + } + } + + rc = ::read(fd, buff, len); + //fprintf(stderr, "fd %d ret: %d\n", fd, rc); + if (rc < 0) + dmx_err("read: %s", strerror(errno), 0); + + return rc; +} + +bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filter, + const unsigned char * const mask, int len, int timeout, + const unsigned char * const negmask) +{ + memset(&s_flt, 0, sizeof(s_flt)); + + _open(); + + if (len > DMX_FILTER_SIZE) + { + lt_info("%s #%d: len too long: %d, DMX_FILTER_SIZE %d\n", __func__, num, len, DMX_FILTER_SIZE); + len = DMX_FILTER_SIZE; + } + s_flt.pid = pid; + s_flt.timeout = timeout; + memcpy(s_flt.filter.filter, filter, len); + memcpy(s_flt.filter.mask, mask, len); + if (negmask != NULL) + memcpy(s_flt.filter.mode, negmask, len); + + s_flt.flags = DMX_IMMEDIATE_START|DMX_CHECK_CRC; + + int to = 0; + switch (filter[0]) { + case 0x00: /* program_association_section */ + to = 2000; + break; + case 0x01: /* conditional_access_section */ + to = 6000; + break; + case 0x02: /* program_map_section */ + to = 1500; + break; + case 0x03: /* transport_stream_description_section */ + to = 10000; + break; + /* 0x04 - 0x3F: reserved */ + case 0x40: /* network_information_section - actual_network */ + to = 10000; + break; + case 0x41: /* network_information_section - other_network */ + to = 15000; + break; + case 0x42: /* service_description_section - actual_transport_stream */ + to = 10000; + break; + /* 0x43 - 0x45: reserved for future use */ + case 0x46: /* service_description_section - other_transport_stream */ + to = 10000; + break; + /* 0x47 - 0x49: reserved for future use */ + case 0x4A: /* bouquet_association_section */ + to = 11000; + break; + /* 0x4B - 0x4D: reserved for future use */ + case 0x4E: /* event_information_section - actual_transport_stream, present/following */ + to = 2000; + break; + case 0x4F: /* event_information_section - other_transport_stream, present/following */ + to = 10000; + break; + /* 0x50 - 0x5F: event_information_section - actual_transport_stream, schedule */ + /* 0x60 - 0x6F: event_information_section - other_transport_stream, schedule */ + case 0x70: /* time_date_section */ + s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */ + s_flt.flags |= DMX_ONESHOT; + //s_flt.pid = 0x0014; + to = 30000; + break; + case 0x71: /* running_status_section */ + s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */ + to = 0; + break; + case 0x72: /* stuffing_section */ + s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */ + to = 0; + break; + case 0x73: /* time_offset_section */ + s_flt.flags |= DMX_ONESHOT; + //s_flt.pid = 0x0014; + to = 30000; + break; + /* 0x74 - 0x7D: reserved for future use */ + case 0x7E: /* discontinuity_information_section */ + s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */ + to = 0; + break; + case 0x7F: /* selection_information_section */ + to = 0; + break; + /* 0x80 - 0x8F: ca_message_section */ + /* 0x90 - 0xFE: user defined */ + /* 0xFF: reserved */ + default: + break; +// return -1; + } + /* the negmask == NULL is a hack: the users of negmask are PMT-update + * and sectionsd EIT-Version change. And they really want no timeout + * if timeout == 0 instead of "default timeout" */ + if (timeout == 0 && negmask == NULL) + s_flt.timeout = to; + + lt_debug("%s #%d pid:0x%04hx fd:%d type:%s len:%d to:%d flags:%x flt[0]:%02x\n", __func__, num, + pid, fd, DMX_T[dmx_type], len, s_flt.timeout,s_flt.flags, s_flt.filter.filter[0]); +#if 0 + fprintf(stderr,"filt: ");for(int i=0;i= 0x0002 && pid <= 0x000f) || pid >= 0x1fff) + return false; + + lt_debug("%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]); + + _open(); + + memset(&p_flt, 0, sizeof(p_flt)); + p_flt.pid = pid; + p_flt.output = DMX_OUT_DECODER; + p_flt.input = DMX_IN_FRONTEND; + p_flt.flags = DMX_IMMEDIATE_START; + + switch (dmx_type) { + case DMX_PCR_ONLY_CHANNEL: + p_flt.pes_type = DMX_PES_PCR; + break; + case DMX_AUDIO_CHANNEL: + p_flt.pes_type = DMX_PES_AUDIO; + break; + case DMX_VIDEO_CHANNEL: + p_flt.pes_type = DMX_PES_VIDEO; + break; + case DMX_PIP_CHANNEL: /* PIP is a special version of DMX_VIDEO_CHANNEL */ + p_flt.pes_type = DMX_PES_VIDEO1; + break; + case DMX_PES_CHANNEL: + p_flt.pes_type = DMX_PES_OTHER; + p_flt.output = DMX_OUT_TAP; + break; + case DMX_TP_CHANNEL: + p_flt.pes_type = DMX_PES_OTHER; + p_flt.output = DMX_OUT_TSDEMUX_TAP; + break; + default: + lt_info("%s #%d invalid dmx_type %d!\n", __func__, num, dmx_type); + return false; + } + return (ioctl(fd, DMX_SET_PES_FILTER, &p_flt) >= 0); +} + +void cDemux::SetSyncMode(AVSYNC_TYPE /*mode*/) +{ + lt_debug("%s #%d\n", __FUNCTION__, num); +} + +void *cDemux::getBuffer() +{ + lt_debug("%s #%d\n", __FUNCTION__, num); + return NULL; +} + +void *cDemux::getChannel() +{ + lt_debug("%s #%d\n", __FUNCTION__, num); + return NULL; +} + +bool cDemux::addPid(unsigned short Pid) +{ + lt_debug("%s: pid 0x%04hx\n", __func__, Pid); + pes_pids pfd; + int ret; + if (dmx_type != DMX_TP_CHANNEL) + { + lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid); + return false; + } + _open(); + if (fd == -1) + lt_info("%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid); + pfd.fd = fd; /* dummy */ + pfd.pid = Pid; + pesfds.push_back(pfd); + ret = (ioctl(fd, DMX_ADD_PID, &Pid)); + if (ret < 0) + lt_info("%s: DMX_ADD_PID (%m) pid=%hx\n", __func__, Pid); + return (ret != -1); +} + +void cDemux::removePid(unsigned short Pid) +{ + if (dmx_type != DMX_TP_CHANNEL) + { + lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid); + return; + } + for (std::vector::iterator i = pesfds.begin(); i != pesfds.end(); ++i) + { + if ((*i).pid == Pid) { + lt_debug("removePid: removing demux fd %d pid 0x%04x\n", fd, Pid); + if (ioctl(fd, DMX_REMOVE_PID, Pid) < 0) + lt_info("%s: (DMX_REMOVE_PID, 0x%04hx): %m\n", __func__, Pid); + pesfds.erase(i); + return; /* TODO: what if the same PID is there multiple times */ + } + } + lt_info("%s pid 0x%04x not found\n", __FUNCTION__, Pid); +} + +void cDemux::getSTC(int64_t * STC) +{ + /* apparently I can only get the PTS of the video decoder, + * but that's good enough for dvbsub */ + lt_debug("%s #%d\n", __func__, num); + int64_t pts = 0; + if (videoDecoder) + pts = videoDecoder->GetPTS(); + *STC = pts; +} + +int cDemux::getUnit(void) +{ + lt_debug("%s #%d\n", __FUNCTION__, num); + /* just guessed that this is the right thing to do. + right now this is only used by the CA code which is stubbed out + anyway */ + return num; +} + +bool cDemux::SetSource(int unit, int source) +{ + if (unit >= NUM_DEMUX || unit < 0) { + lt_info_c("%s: unit (%d) out of range, NUM_DEMUX %d\n", __func__, unit, NUM_DEMUX); + return false; + } + lt_info_c("%s(%d, %d) => %d to %d\n", __func__, unit, source, dmx_source[unit], source); + if (source < 0 || source >= NUM_DEMUXDEV) + lt_info_c("%s(%d, %d) ERROR: source %d out of range!\n", __func__, unit, source, source); + else + dmx_source[unit] = source; + return true; +} + +int cDemux::GetSource(int unit) +{ + if (unit >= NUM_DEMUX || unit < 0) { + lt_info_c("%s: unit (%d) out of range, NUM_DEMUX %d\n", __func__, unit, NUM_DEMUX); + return -1; + } + lt_info_c("%s(%d) => %d\n", __func__, unit, dmx_source[unit]); + return dmx_source[unit]; +} diff --git a/libarmbox/dmx_cs.h b/libarmbox/dmx_cs.h new file mode 100644 index 0000000..175d8cb --- /dev/null +++ b/libarmbox/dmx_cs.h @@ -0,0 +1 @@ +#include "dmx_lib.h" diff --git a/libarmbox/dmx_lib.h b/libarmbox/dmx_lib.h new file mode 100644 index 0000000..af87a02 --- /dev/null +++ b/libarmbox/dmx_lib.h @@ -0,0 +1,72 @@ +#ifndef __DEMUX_TD_H +#define __DEMUX_TD_H + +#include +#include +#include +#include +#include +#include "../common/cs_types.h" + +#define MAX_DMX_UNITS 4 + +typedef enum +{ + DMX_INVALID = 0, + DMX_VIDEO_CHANNEL = 1, + DMX_AUDIO_CHANNEL, + DMX_PES_CHANNEL, + DMX_PSI_CHANNEL, + DMX_PIP_CHANNEL, + DMX_TP_CHANNEL, + DMX_PCR_ONLY_CHANNEL +} DMX_CHANNEL_TYPE; + +typedef struct +{ + int fd; + unsigned short pid; +} pes_pids; + +class cDemux +{ + private: + int num; + int fd; + int buffersize; + bool measure; + uint64_t last_measure, last_data; + DMX_CHANNEL_TYPE dmx_type; + std::vector pesfds; + struct dmx_sct_filter_params s_flt; + struct dmx_pes_filter_params p_flt; + int last_source; + bool _open(void); + public: + + bool Open(DMX_CHANNEL_TYPE pes_type, void * unused = NULL, int bufsize = 0); + void Close(void); + bool Start(bool record = false); + bool Stop(void); + int Read(unsigned char *buff, int len, int Timeout = 0); + bool sectionFilter(unsigned short pid, const unsigned char * const filter, const unsigned char * const mask, int len, int Timeout = 0, const unsigned char * const negmask = NULL); + bool pesFilter(const unsigned short pid); + void SetSyncMode(AVSYNC_TYPE mode); + void * getBuffer(); + void * getChannel(); + DMX_CHANNEL_TYPE getChannelType(void) { return dmx_type; }; + bool addPid(unsigned short pid); + void getSTC(int64_t * STC); + int getUnit(void); + static bool SetSource(int unit, int source); + static int GetSource(int unit); + // TD only functions + int getFD(void) { return fd; }; /* needed by cPlayback class */ + void removePid(unsigned short Pid); /* needed by cRecord class */ + std::vector getPesPids(void) { return pesfds; }; + // + cDemux(int num = 0); + ~cDemux(); +}; + +#endif //__DEMUX_H diff --git a/libarmbox/hardware_caps.c b/libarmbox/hardware_caps.c new file mode 100644 index 0000000..5dd7fd8 --- /dev/null +++ b/libarmbox/hardware_caps.c @@ -0,0 +1,43 @@ +/* + * determine the capabilities of the hardware. + * part of libstb-hal + * + * (C) 2010-2012 Stefan Seyfried + * + * License: GPL v2 or later + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define FP_DEV "/dev/vfd" +static int initialized = 0; +static hw_caps_t caps; + +hw_caps_t *get_hwcaps(void) +{ + if (initialized) + return ∩︀ + + memset(&caps, 0, sizeof(hw_caps_t)); + + initialized = 1; + caps.has_CI = 0; + caps.can_cec = 1; + caps.can_shutdown = 1; + caps.display_type = HW_DISPLAY_LED_NUM; + caps.can_set_display_brightness = 0; + caps.has_HDMI = 1; + caps.display_xres = 4; + strcpy(caps.boxvendor, "armbox"); + strcpy(caps.boxname, "armbox"); + strcpy(caps.boxarch,caps.boxname); + return ∩︀ +} diff --git a/libarmbox/init.cpp b/libarmbox/init.cpp new file mode 100644 index 0000000..b52ecca --- /dev/null +++ b/libarmbox/init.cpp @@ -0,0 +1,311 @@ + +#include + +#include + +#include "init_lib.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "pwrmngr.h" + +#include "lt_debug.h" +#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args) +#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VIRTUALINPUT "/sys/devices/virtual/input" +#define DEVINPUT "/dev/input" + +typedef struct { + const char *name; + const char *desc; + int fd; + unsigned int major; + unsigned int minor; + time_t next_discovery; +} input_device_t; + +static input_device_t input_device[] = { + { "/dev/input/nevis_ir", "lircd", -1, 0, 0, 0 }, + { "/dev/input/tdt_rc", "TDT RC event driver", -1, 0, 0, 0 }, + { "/dev/input/fulan_fp", "fulan front panel buttons", -1, 0, 0, 0 }, + { "/dev/input/event0", NULL, -1, 0, 0, 0 }, + { "/dev/input/event1", NULL, -1, 0, 0, 0 }, + { "/dev/input/event2", NULL, -1, 0, 0, 0 }, + { "/dev/input/event3", NULL, -1, 0, 0, 0 }, + { "/dev/input/event4", NULL, -1, 0, 0, 0 }, + { "/dev/input/event5", NULL, -1, 0, 0, 0 }, + { "/dev/input/event6", NULL, -1, 0, 0, 0 }, + { "/dev/input/event7", NULL, -1, 0, 0, 0 }, + { NULL, NULL, -1, 0, 0, 0 } +}; + +#define number_of_input_devices (sizeof(input_device)/sizeof(input_device_t) - 1) + +static void do_mknod(int i, char *d_name) { + char name[255]; + int dev = -1; + // I've no idea how the event device number is actually calculated. Just loop. --martii + + for (int j = 0; j < 99 && dev < 0; j++) { + snprintf(name, sizeof(name), VIRTUALINPUT "/%s/event%d/dev", d_name, j); + dev = open (name, O_RDONLY); + } + + if (dev > -1) { + char buf[255]; + int l = read(dev, buf, sizeof(buf) - 1); + close(dev); + if (l > -1) { + buf[l] = 0; + if (2 == sscanf(buf, "%d:%d", &input_device[i].major, &input_device[i].minor)) { + mknod(input_device[i].name, 0666 | S_IFCHR, + gnu_dev_makedev(input_device[i].major, input_device[i].minor)); + } + } + } +} + +static void create_input_devices (void) { + DIR *d = opendir (VIRTUALINPUT); + if (d) { + struct dirent *e; + while ((e = readdir(d))) { + char name[255]; + if (e->d_name[0] == '.') + continue; + snprintf(name, sizeof(name), VIRTUALINPUT "/%s/name", e->d_name); + int n = open(name, O_RDONLY); + if (n > -1) { + char buf[255]; + int l = read(n, buf, sizeof(buf) - 1); + close(n); + if (l > 1) { + do + buf[l--] = 0; + while (l > 1 && buf[l] == '\n'); + + for (unsigned int i = 0; i < number_of_input_devices; i++) + if (input_device[i].desc && !strcmp(buf, input_device[i].desc)) { + do_mknod(i, e->d_name); + break; + } + } + } + } + closedir(d); + } + // remove any event* files left that point to our "well-known" inputs + d = opendir (DEVINPUT); + if (d) { + struct dirent *e; + while ((e = readdir(d))) { + char name[255]; + if (strncmp(e->d_name, "event", 5)) + continue; + snprintf(name, sizeof(name), DEVINPUT "/%s", e->d_name); + struct stat st; + if (stat(name, &st)) + continue; + for (unsigned int i = 0; i < number_of_input_devices; i++) + if (input_device[i].major && + gnu_dev_major(st.st_rdev) == input_device[i].major && + gnu_dev_minor(st.st_rdev) == input_device[i].minor) + unlink(name); + } + closedir(d); + } +} + +static pthread_t inmux_task = 0; +static int inmux_thread_running = 0; + +static void open_input_devices(void) { + time_t now = time(NULL); + for (unsigned int i = 0; i < number_of_input_devices; i++) + if ((input_device[i].fd < 0) && (input_device[i].next_discovery <= now)) { + input_device[i].next_discovery = now + 60; + input_device[i].fd = open(input_device[i].name, O_RDWR | O_NONBLOCK); + } +} + +static void reopen_input_devices(void) { + create_input_devices(); + time_t now = time(NULL); + for (unsigned int i = 0; i < number_of_input_devices; i++) { + input_device[i].next_discovery = now + 60; + int fd = open(input_device[i].name, O_RDWR | O_NONBLOCK); + if (fd > -1) { + if (input_device[i].fd > -1) { + dup2(fd, input_device[i].fd); + close (fd); + } else { + input_device[i].fd = fd; + } + } else if (input_device[i].fd > -1) { + close (input_device[i].fd); + input_device[i].fd = -1; + } + } +} + +static void close_input_devices(void) { + for (unsigned int i = 0; i < number_of_input_devices; i++) + if (input_device[i].fd > -1) { + close(input_device[i].fd); + input_device[i].fd = -1; + } +} + +static void poll_input_devices(void) { + struct pollfd fds[number_of_input_devices]; + input_device_t *inputs[number_of_input_devices]; + int nfds = 0; + for (unsigned int i = 1; i < number_of_input_devices; i++) + if (input_device[i].fd > -1) { + fds[nfds].fd = input_device[i].fd; + fds[nfds].events = POLLIN | POLLHUP | POLLERR; + fds[nfds].revents = 0; + inputs[nfds] = &input_device[i]; + nfds++; + } + + if (nfds == 0) { + // Only a single input device, which happens to be our master. poll() to avoid looping too fast. + fds[0].fd = input_device[0].fd; + fds[0].events = POLLIN | POLLHUP | POLLERR; + fds[0].revents = 0; + poll(fds, 1, 60000 /* ms */); + return; + } + + int r = poll(fds, nfds, 60000 /* ms */); + if (r < 0) { + if (errno != EAGAIN) { + lt_info("%s: poll(): %m\n", __func__); + inmux_thread_running = 0; + } + return; + } + for (int i = 0; i < nfds && r > 0; i++) { + if (fds[i].revents & POLLIN) { +//fprintf(stderr, "### input from fd %d (%s)\n", fds[i].fd, inputs[i]->name); + struct input_event ev; + while (sizeof(ev) == read(fds[i].fd, &ev, sizeof(ev))) + write(input_device[0].fd, &ev, sizeof(ev)); + r--; + } else if (fds[i].revents & (POLLHUP | POLLERR | POLLNVAL)) { +//fprintf(stderr, "### error on %d (%s)\n", fds[i].fd, inputs[i]->name); + close (fds[i].fd); + inputs[i]->fd = -1; + r--; + } + } +} + +static void *inmux_thread(void *) +{ + char threadname[17]; + strncpy(threadname, __func__, sizeof(threadname)); + threadname[16] = 0; + prctl (PR_SET_NAME, (unsigned long)&threadname); + + inmux_thread_running = 1; + while (inmux_thread_running) { + open_input_devices(); + poll_input_devices(); + } + + return NULL; +} + +void start_inmux_thread(void) +{ + input_device[0].fd = open(input_device[0].name, O_RDWR | O_NONBLOCK); // nevis_ir. This is mandatory. + if (input_device[0].fd < 0){ + lt_info("%s: open(%s): %m\n", __func__, input_device[0].name); + return; + } + if (pthread_create(&inmux_task, 0, inmux_thread, NULL) != 0) + { + lt_info("%s: inmux thread pthread_create: %m\n", __func__); + inmux_thread_running = 0; + return; + } + pthread_detach(inmux_task); +} + +void stop_inmux_thread(void) +{ + inmux_thread_running = 0; +} + +static bool initialized = false; + +void init_td_api() +{ + if (!initialized) + lt_debug_init(); + lt_info("%s begin, initialized=%d, debug=0x%02x\n", __FUNCTION__, (int)initialized, debuglevel); + if (!initialized) + { + cCpuFreqManager f; + f.SetCpuFreq(0); /* CPUFREQ == 0 is the trigger for leaving standby */ + create_input_devices(); + start_inmux_thread(); + +#if 0 + /* this is a strange hack: the drivers seem to only work correctly after + * demux0 has been used once. After that, we can use demux1,2,... */ + struct dmx_pes_filter_params p; + int dmx = open("/dev/dvb/adapter0/demux0", O_RDWR|O_CLOEXEC); + if (dmx < 0) + lt_info("%s: ERROR open /dev/dvb/adapter0/demux0 (%m)\n", __func__); + else + { + memset(&p, 0, sizeof(p)); + p.output = DMX_OUT_DECODER; + p.input = DMX_IN_FRONTEND; + p.flags = DMX_IMMEDIATE_START; + p.pes_type = DMX_PES_VIDEO; + ioctl(dmx, DMX_SET_PES_FILTER, &p); + ioctl(dmx, DMX_STOP); + close(dmx); + } +#endif + } + else + reopen_input_devices(); + initialized = true; + lt_info("%s end\n", __FUNCTION__); +} + +void shutdown_td_api() +{ + lt_info("%s, initialized = %d\n", __FUNCTION__, (int)initialized); + if (initialized) { + stop_inmux_thread(); + close_input_devices(); + } + initialized = false; +} diff --git a/libarmbox/init_cs.h b/libarmbox/init_cs.h new file mode 100644 index 0000000..7f9e341 --- /dev/null +++ b/libarmbox/init_cs.h @@ -0,0 +1,2 @@ +#warning using init_cs.h from libspark +#include "init_lib.h" diff --git a/libarmbox/init_lib.h b/libarmbox/init_lib.h new file mode 100644 index 0000000..d9a6f09 --- /dev/null +++ b/libarmbox/init_lib.h @@ -0,0 +1,5 @@ +#ifndef __INIT_TD_H +#define __INIT_TD_H +void init_td_api(); +void shutdown_td_api(); +#endif diff --git a/libarmbox/irmp.c b/libarmbox/irmp.c new file mode 100644 index 0000000..68b82cc --- /dev/null +++ b/libarmbox/irmp.c @@ -0,0 +1,4284 @@ +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * irmp.c - infrared multi-protocol decoder, supports several remote control protocols + * + * Copyright (c) 2009-2011 Frank Meyer - frank(at)fli4l.de + * + * $Id: irmp.c,v 1.115 2012/02/21 08:41:46 fm Exp $ + * + * ATMEGA88 @ 8 MHz + * + * Supported mikrocontrollers: + * + * ATtiny45, ATtiny85 + * ATtiny84 + * ATmega8, ATmega16, ATmega32 + * ATmega162 + * ATmega164, ATmega324, ATmega644, ATmega644P, ATmega1284 + * ATmega88, ATmega88P, ATmega168, ATmega168P, ATmega328P + * + * Typical manufacturers of remote controls: + * + * SIRCS - Sony + * NEC - NEC, Yamaha, Canon, Tevion, Harman/Kardon, Hitachi, JVC, Pioneer, Toshiba, Xoro, Orion, and many other Japanese manufacturers + * SAMSUNG - Samsung + * SAMSUNG32 - Samsung + * MATSUSHITA - Matsushita + * KASEIKYO - Panasonic, Denon & other Japanese manufacturers (members of "Japan's Association for Electric Home Application") + * RECS80 - Philips, Nokia, Thomson, Nordmende, Telefunken, Saba + * RC5 - Philips and other European manufacturers + * DENON - Denon, Sharp + * RC6 - Philips and other European manufacturers + * APPLE - Apple + * NUBERT - Nubert Subwoofer System + * B&O - Bang & Olufsen + * PANASONIC - Panasonic (older, yet not implemented) + * GRUNDIG - Grundig + * NOKIA - Nokia + * SIEMENS - Siemens, e.g. Gigaset M740AV + * FDC - FDC IR keyboard + * RCCAR - IR remote control for RC cars + * JVC - JVC + * THOMSON - Thomson + * NIKON - Nikon cameras + * RUWIDO - T-Home + * KATHREIN - Kathrein + * LEGO - Lego Power Functions RC + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * SIRCS + * ----- + * + * frame: 1 start bit + 12-20 data bits + no stop bit + * data: 7 command bits + 5 address bits + 0 to 8 additional bits + * + * start bit: data "0": data "1": stop bit: + * -----------------_________ ------_____ ------------______ + * 2400us 600us 600us 600us 1200us 600 us no stop bit + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * NEC + extended NEC + * ------------------------- + * + * frame: 1 start bit + 32 data bits + 1 stop bit + * data NEC: 8 address bits + 8 inverted address bits + 8 command bits + 8 inverted command bits + * data extended NEC: 16 address bits + 8 command bits + 8 inverted command bits + * + * start bit: data "0": data "1": stop bit: + * -----------------_________ ------______ ------________________ ------______.... + * 9000us 4500us 560us 560us 560us 1690 us 560us + * + * + * Repetition frame: + * + * -----------------_________------______ .... ~100ms Pause, then repeat + * 9000us 2250us 560us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * SAMSUNG + * ------- + * + * frame: 1 start bit + 16 data(1) bits + 1 sync bit + additional 20 data(2) bits + 1 stop bit + * data(1): 16 address bits + * data(2): 4 ID bits + 8 command bits + 8 inverted command bits + * + * start bit: data "0": data "1": sync bit: stop bit: + * ----------______________ ------______ ------________________ ------______________ ------______.... + * 4500us 4500us 550us 450us 550us 1450us 550us 4500us 550us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * SAMSUNG32 + * ---------- + * + * frame: 1 start bit + 32 data bits + 1 stop bit + * data: 16 address bits + 16 command bits + * + * start bit: data "0": data "1": stop bit: + * ----------______________ ------______ ------________________ ------______.... + * 4500us 4500us 550us 450us 550us 1450us 550us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * MATSUSHITA + * ---------- + * + * frame: 1 start bit + 24 data bits + 1 stop bit + * data: 6 custom bits + 6 command bits + 12 address bits + * + * start bit: data "0": data "1": stop bit: + * ----------_________ ------______ ------________________ ------______.... + * 3488us 3488us 872us 872us 872us 2616us 872us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * KASEIKYO + * -------- + * + * frame: 1 start bit + 48 data bits + 1 stop bit + * data: 16 manufacturer bits + 4 parity bits + 4 genre1 bits + 4 genre2 bits + 10 command bits + 2 id bits + 8 parity bits + * + * start bit: data "0": data "1": stop bit: + * ----------______ ------______ ------________________ ------______.... + * 3380us 1690us 423us 423us 423us 1269us 423us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * RECS80 + * ------ + * + * frame: 2 start bits + 10 data bits + 1 stop bit + * data: 1 toggle bit + 3 address bits + 6 command bits + * + * start bit: data "0": data "1": stop bit: + * -----_____________________ -----____________ -----______________ ------_______.... + * 158us 7432us 158us 4902us 158us 7432us 158us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * RECS80EXT + * --------- + * + * frame: 2 start bits + 11 data bits + 1 stop bit + * data: 1 toggle bit + 4 address bits + 6 command bits + * + * start bit: data "0": data "1": stop bit: + * -----_____________________ -----____________ -----______________ ------_______.... + * 158us 3637us 158us 4902us 158us 7432us 158us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * RC5 + RC5X + * ---------- + * + * RC5 frame: 2 start bits + 12 data bits + no stop bit + * RC5 data: 1 toggle bit + 5 address bits + 6 command bits + * RC5X frame: 1 start bit + 13 data bits + no stop bit + * RC5X data: 1 inverted command bit + 1 toggle bit + 5 address bits + 6 command bits + * + * start bit: data "0": data "1": + * ______----- ------______ ______------ + * 889us 889us 889us 889us 889us 889us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * DENON + * ----- + * + * frame: 0 start bits + 16 data bits + stop bit + 65ms pause + 16 inverted data bits + stop bit + * data: 5 address bits + 10 command bits + * + * Theory: + * + * data "0": data "1": + * ------________________ ------______________ + * 275us 775us 275us 1900us + * + * Practice: + * + * data "0": data "1": + * ------________________ ------______________ + * 310us 745us 310us 1780us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * RC6 + * --- + * + * RC6 frame: 1 start bit + 1 bit "1" + 3 mode bits + 1 toggle bit + 16 data bits + 2666 us pause + * RC6 data: 8 address bits + 8 command bits + * + * start bit toggle bit "0": toggle bit "1": data/mode "0": data/mode "1": + * ____________------- _______------- -------_______ _______------- -------_______ + * 2666us 889us 889us 889us 889us 889us 444us 444us 444us 444us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * APPLE + * ----- + * + * frame: 1 start bit + 32 data bits + 1 stop bit + * data: 16 address bits + 11100000 + 8 command bits + * + * start bit: data "0": data "1": stop bit: + * -----------------_________ ------______ ------________________ ------______.... + * 9000us 4500us 560us 560us 560us 1690 us 560us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * NUBERT (subwoofer system) + * ------------------------- + * + * frame: 1 start bit + 10 data bits + 1 stop bit + * data: 0 address bits + 10 command bits ? + * + * start bit: data "0": data "1": stop bit: + * ----------_____ ------______ ------________________ ------______.... + * 1340us 340us 500us 1300us 1340us 340us 500us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * BANG_OLUFSEN + * ------------ + * + * frame: 4 start bits + 16 data bits + 1 trailer bit + 1 stop bit + * data: 0 address bits + 16 command bits + * + * 1st start bit: 2nd start bit: 3rd start bit: 4th start bit: + * -----________ -----________ -----_____________ -----________ + * 210us 3000us 210us 3000us 210us 15000us 210us 3000us + * + * data "0": data "1": data "repeat bit": trailer bit: stop bit: + * -----________ -----_____________ -----___________ -----_____________ -----____... + * 210us 3000us 210us 9000us 210us 6000us 210us 12000us 210us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * GRUNDIG + * ------- + * + * packet: 1 start frame + 19,968ms pause + N info frames + 117,76ms pause + 1 stop frame + * frame: 1 pre bit + 1 start bit + 9 data bits + no stop bit + * pause between info frames: 117,76ms + * + * data of start frame: 9 x 1 + * data of info frame: 9 command bits + * data of stop frame: 9 x 1 + * + * pre bit: start bit data "0": data "1": + * ------____________ ------______ ______------ ------______ + * 528us 2639us 528us 528us 528us 528us 528us 528us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * NOKIA: + * ------ + * + * Timing similar to Grundig, but 16 data bits: + * frame: 1 pre bit + 1 start bit + 8 command bits + 8 address bits + no stop bit + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * SIEMENS or RUWIDO: + * ------------------ + * + * SIEMENS frame: 1 start bit + 22 data bits + no stop bit + * SIEMENS data: 13 address bits + 1 repeat bit + 7 data bits + 1 unknown bit + * + * start bit data "0": data "1": + * -------_______ _______------- -------_______ + * 250us 250us 250us 250us 250us 250us + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * PANASONIC (older protocol, yet not implemented, see also MATSUSHITA, timing very similar) + * ----------------------------------------------------------------------------------------- + * + * frame: 1 start bit + 22 data bits + 1 stop bit + * 22 data bits = 5 custom bits + 6 data bits + 5 inverted custom bits + 6 inverted data bits + * + * European version: T = 456us + * USA & Canada version: T = 422us + * + * start bit: data "0": data "1": stop bit: + * 8T 8T 2T 2T 2T 6T 2T + * -------------____________ ------_____ ------_____________ ------_______.... + * 3648us 3648us 912us 912us 912us 2736us 912us (Europe) + * 3376us 3376us 844us 844us 844us 2532us 844us (US) + * + *--------------------------------------------------------------------------------------------------------------------------------------------------- + * + * 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. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +#if defined(__18CXX) +#define PIC_C18 // Microchip C18 Compiler +#endif + +#if defined(__PCM__) || defined(__PCB__) || defined(__PCH__) // CCS PIC Compiler instead of AVR +#define PIC_CCS_COMPILER +#endif + +#ifdef unix // test on linux/unix +#include +#include +#include +#include +#include + +/* for crazy lirc stuff... */ +#include +#include +#include +#include + +#define ANALYZE +#define PROGMEM +#define memcpy_P memcpy + +#else // not unix: + +#ifdef WIN32 +#include +#include +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +#define ANALYZE +#define PROGMEM +#define memcpy_P memcpy + +#else + +#if defined (PIC_CCS_COMPILER) || defined(PIC_C18) + +#include +#define PROGMEM +#define memcpy_P memcpy + +#if defined (PIC_CCS_COMPILER) +typedef unsigned int8 uint8_t; +typedef unsigned int16 uint16_t; +#endif + +#else // AVR: + +#include +#include +#include +#include +#include +#include + +#endif // PIC_CCS_COMPILER or PIC_C18 + +#endif // windows +#endif // unix + +#ifndef IRMP_USE_AS_LIB +#include "irmpconfig.h" +#endif +#include "irmp.h" + +#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRMP_SUPPORT_NOKIA_PROTOCOL == 1 || IRMP_SUPPORT_IR60_PROTOCOL == 1 +#define IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL 1 +#else +#define IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 || IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 +#define IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL 1 +#else +#define IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 || \ + IRMP_SUPPORT_RC6_PROTOCOL == 1 || \ + IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 || \ + IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 || \ + IRMP_SUPPORT_GRUNDIG2_PROTOCOL == 1 || \ + IRMP_SUPPORT_IR60_PROTOCOL +#define IRMP_SUPPORT_MANCHESTER 1 +#else +#define IRMP_SUPPORT_MANCHESTER 0 +#endif + +#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 +#define IRMP_SUPPORT_SERIAL 1 +#else +#define IRMP_SUPPORT_SERIAL 0 +#endif + +#define IRMP_KEY_REPETITION_LEN (uint16_t)(F_INTERRUPTS * 150.0e-3 + 0.5) // autodetect key repetition within 150 msec + +#define MIN_TOLERANCE_00 1.0 // -0% +#define MAX_TOLERANCE_00 1.0 // +0% + +#define MIN_TOLERANCE_05 0.95 // -5% +#define MAX_TOLERANCE_05 1.05 // +5% + +#define MIN_TOLERANCE_10 0.9 // -10% +#define MAX_TOLERANCE_10 1.1 // +10% + +#define MIN_TOLERANCE_15 0.85 // -15% +#define MAX_TOLERANCE_15 1.15 // +15% + +#define MIN_TOLERANCE_20 0.8 // -20% +#define MAX_TOLERANCE_20 1.2 // +20% + +#define MIN_TOLERANCE_30 0.7 // -30% +#define MAX_TOLERANCE_30 1.3 // +30% + +#define MIN_TOLERANCE_40 0.6 // -40% +#define MAX_TOLERANCE_40 1.4 // +40% + +#define MIN_TOLERANCE_50 0.5 // -50% +#define MAX_TOLERANCE_50 1.5 // +50% + +#define MIN_TOLERANCE_60 0.4 // -60% +#define MAX_TOLERANCE_60 1.6 // +60% + +#define MIN_TOLERANCE_70 0.3 // -70% +#define MAX_TOLERANCE_70 1.7 // +70% + +#define SIRCS_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIRCS_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIRCS_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#if IRMP_SUPPORT_NETBOX_PROTOCOL // only 5% to avoid conflict with NETBOX: +#define SIRCS_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5)) +#else // only 5% + 1 to avoid conflict with RC6: +#define SIRCS_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#endif +#define SIRCS_1_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIRCS_1_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIRCS_0_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIRCS_0_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIRCS_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIRCS_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define NEC_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define NEC_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define NEC_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define NEC_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define NEC_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define NEC_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +// autodetect nec repetition frame within 50 msec: +// NEC seems to send the first repetition frame after 40ms, further repetition frames after 100 ms +#if 0 +#define NEC_FRAME_REPEAT_PAUSE_LEN_MAX (uint16_t)(F_INTERRUPTS * NEC_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) +#else +#define NEC_FRAME_REPEAT_PAUSE_LEN_MAX (uint16_t)(F_INTERRUPTS * 100.0e-3 * MAX_TOLERANCE_20 + 0.5) +#endif + +#define SAMSUNG_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SAMSUNG_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SAMSUNG_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SAMSUNG_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SAMSUNG_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define SAMSUNG_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define SAMSUNG_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define SAMSUNG_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define SAMSUNG_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define SAMSUNG_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) + +#define MATSUSHITA_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define MATSUSHITA_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define MATSUSHITA_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define MATSUSHITA_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define MATSUSHITA_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define MATSUSHITA_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define MATSUSHITA_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define MATSUSHITA_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define MATSUSHITA_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define MATSUSHITA_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) + +#define KASEIKYO_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KASEIKYO_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KASEIKYO_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KASEIKYO_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KASEIKYO_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME * MIN_TOLERANCE_50 + 0.5) - 1) +#define KASEIKYO_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME * MAX_TOLERANCE_50 + 0.5) + 1) +#define KASEIKYO_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define KASEIKYO_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define KASEIKYO_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME * MIN_TOLERANCE_50 + 0.5) - 1) +#define KASEIKYO_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME * MAX_TOLERANCE_50 + 0.5) + 1) + +#define RECS80_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME * MIN_TOLERANCE_00 + 0.5) - 1) +#define RECS80_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RECS80_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RECS80_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RECS80_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RECS80_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define RC5_START_BIT_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC5_START_BIT_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define RC5_BIT_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC5_BIT_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define DENON_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * DENON_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define DENON_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * DENON_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define DENON_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define DENON_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 +#define DENON_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5)) // no -1, avoid conflict with RUWIDO +#else +#define DENON_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) // be more tolerant +#endif +#define DENON_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define THOMSON_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define THOMSON_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define THOMSON_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define THOMSON_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define THOMSON_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define THOMSON_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define RC6_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC6_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RC6_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC6_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RC6_TOGGLE_BIT_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC6_TOGGLE_BIT_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RC6_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC6_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC6_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC6_BIT_TIME * MAX_TOLERANCE_60 + 0.5) + 1) // pulses: 300 - 800 +#define RC6_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC6_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC6_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC6_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1) // pauses: 300 - 600 + +#define RECS80EXT_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME * MIN_TOLERANCE_00 + 0.5) - 1) +#define RECS80EXT_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME * MAX_TOLERANCE_00 + 0.5) + 1) +#define RECS80EXT_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RECS80EXT_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#define RECS80EXT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80EXT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RECS80EXT_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80EXT_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RECS80EXT_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80EXT_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define NUBERT_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NUBERT_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NUBERT_1_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_1_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NUBERT_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NUBERT_0_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_0_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NUBERT_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX ((PAUSE_LEN)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) // value must be below IRMP_TIMEOUT +#define BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_R_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_R_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define IR60_TIMEOUT_LEN ((uint8_t)(F_INTERRUPTS * IR60_TIMEOUT_TIME * 0.5)) +#define GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define GRUNDIG_NOKIA_IR60_BIT_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define GRUNDIG_NOKIA_IR60_BIT_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) + 1) +#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define GRUNDIG2_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG2_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define GRUNDIG2_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG2_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define GRUNDIG2_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG2_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define GRUNDIG2_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG2_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define GRUNDIG2_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG2_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define GRUNDIG2_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG2_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define GRUNDIG2_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG2_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define GRUNDIG2_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG2_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define FDC_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) // 5%: avoid conflict with NETBOX +#define FDC_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5)) +#define FDC_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define FDC_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5)) +#define FDC_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * FDC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define FDC_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * FDC_PULSE_TIME * MAX_TOLERANCE_50 + 0.5) + 1) +#define FDC_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define FDC_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#if 0 +#define FDC_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) // could be negative: 255 +#else +#define FDC_0_PAUSE_LEN_MIN (1) // simply use 1 +#endif +#define FDC_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define RCCAR_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RCCAR_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RCCAR_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RCCAR_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RCCAR_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define RCCAR_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define RCCAR_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define RCCAR_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define RCCAR_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define RCCAR_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) + +#define JVC_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define JVC_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define JVC_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * (JVC_FRAME_REPEAT_PAUSE_TIME - IRMP_TIMEOUT_TIME) * MIN_TOLERANCE_40 + 0.5) - 1) // HACK! +#define JVC_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * (JVC_FRAME_REPEAT_PAUSE_TIME - IRMP_TIMEOUT_TIME) * MAX_TOLERANCE_70 + 0.5) - 1) // HACK! +#define JVC_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * JVC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define JVC_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * JVC_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define JVC_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define JVC_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define JVC_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define JVC_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +// autodetect JVC repetition frame within 50 msec: +#define JVC_FRAME_REPEAT_PAUSE_LEN_MAX (uint16_t)(F_INTERRUPTS * JVC_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + +#define NIKON_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_START_BIT_PAUSE_LEN_MIN ((uint16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_START_BIT_PAUSE_LEN_MAX ((uint16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NIKON_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NIKON_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_FRAME_REPEAT_PAUSE_LEN_MAX (uint16_t)(F_INTERRUPTS * NIKON_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + +#define KATHREIN_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_1_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_1_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_0_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_0_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_SYNC_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_SYNC_BIT_PAUSE_LEN_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_SYNC_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_SYNC_BIT_PAUSE_LEN_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define NETBOX_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NETBOX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define NETBOX_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NETBOX_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define NETBOX_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NETBOX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define NETBOX_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NETBOX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define NETBOX_PULSE_LEN ((uint8_t)(F_INTERRUPTS * NETBOX_PULSE_TIME)) +#define NETBOX_PAUSE_LEN ((uint8_t)(F_INTERRUPTS * NETBOX_PAUSE_TIME)) +#define NETBOX_PULSE_REST_LEN ((uint8_t)(F_INTERRUPTS * NETBOX_PULSE_TIME / 4)) +#define NETBOX_PAUSE_REST_LEN ((uint8_t)(F_INTERRUPTS * NETBOX_PAUSE_TIME / 4)) + +#define LEGO_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define LEGO_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define LEGO_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define LEGO_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define LEGO_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * LEGO_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define LEGO_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * LEGO_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define LEGO_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define LEGO_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define LEGO_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define LEGO_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) + +#define AUTO_FRAME_REPETITION_LEN (uint16_t)(F_INTERRUPTS * AUTO_FRAME_REPETITION_TIME + 0.5) // use uint16_t! + +#ifdef ANALYZE +#define ANALYZE_PUTCHAR(a) { if (! silent) { putchar (a); } } +#ifndef LIRC_IRMP +#define ANALYZE_ONLY_NORMAL_PUTCHAR(a) { if (! silent && !verbose) { putchar (a); } } +#else +#define ANALYZE_ONLY_NORMAL_PUTCHAR(a) +#endif +#define ANALYZE_PRINTF(...) { if (verbose) { printf (__VA_ARGS__); } } +#define ANALYZE_NEWLINE() { if (verbose) { putchar ('\n'); } } +static int silent = TRUE; +static int time_counter; +static int verbose; +#else +#define ANALYZE_PUTCHAR(a) +#define ANALYZE_ONLY_NORMAL_PUTCHAR(a) +#define ANALYZE_PRINTF(...) +#define ANALYZE_NEWLINE() +#endif + +#if IRMP_USE_CALLBACK == 1 +static void (*irmp_callback_ptr) (uint8_t); +#endif // IRMP_USE_CALLBACK == 1 + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Protocol names + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if IRMP_PROTOCOL_NAMES == 1 +char * +irmp_protocol_names[IRMP_N_PROTOCOLS + 1] = +{ + "UNKNOWN", + "SIRCS", + "NEC", + "SAMSUNG", + "MATSUSH", + "KASEIKYO", + "RECS80", + "RC5", + "DENON", + "RC6", + "SAMSG32", + "APPLE", + "RECS80EX", + "NUBERT", + "BANG OLU", + "GRUNDIG", + "NOKIA", + "SIEMENS", + "FDC", + "RCCAR", + "JVC", + "RC6A", + "NIKON", + "RUWIDO", + "IR60", + "KATHREIN", + "NETBOX", + "NEC16", + "NEC42", + "LEGO", + "THOMSON" +}; +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Logging + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if IRMP_LOGGING == 1 // logging via UART + +#if IRMP_EXT_LOGGING == 1 // use external logging +#include "irmpextlog.h" +#else // normal UART log (IRMP_EXT_LOGGING == 0) +#define BAUD 9600L +#include + +#ifdef UBRR0H + +#define UART0_UBRRH UBRR0H +#define UART0_UBRRL UBRR0L +#define UART0_UCSRA UCSR0A +#define UART0_UCSRB UCSR0B +#define UART0_UCSRC UCSR0C +#define UART0_UDRE_BIT_VALUE (1< ENDBITS) + { // if stop condition is true, output on uart + uint16_t i; + + for (i = 0; i < STARTCYCLES; i++) + { + irmp_uart_putc ('0'); // the ignored starting zeros + } + + for (i = 0; i < (buf_idx - ENDBITS + 20) / 8; i++) // transform bitset into uart chars + { + uint8_t d = buf[i]; + uint8_t j; + + for (j = 0; j < 8; j++) + { + irmp_uart_putc ((d & 1) + '0'); + d >>= 1; + } + } + + irmp_uart_putc ('\n'); + buf_idx = 0; + } + } + else + { + cnt = 0; + } + } + } +} + +#else +#define irmp_log(val) +#endif //IRMP_LOGGING + +typedef struct +{ + uint8_t protocol; // ir protocol + uint8_t pulse_1_len_min; // minimum length of pulse with bit value 1 + uint8_t pulse_1_len_max; // maximum length of pulse with bit value 1 + uint8_t pause_1_len_min; // minimum length of pause with bit value 1 + uint8_t pause_1_len_max; // maximum length of pause with bit value 1 + uint8_t pulse_0_len_min; // minimum length of pulse with bit value 0 + uint8_t pulse_0_len_max; // maximum length of pulse with bit value 0 + uint8_t pause_0_len_min; // minimum length of pause with bit value 0 + uint8_t pause_0_len_max; // maximum length of pause with bit value 0 + uint8_t address_offset; // address offset + uint8_t address_end; // end of address + uint8_t command_offset; // command offset + uint8_t command_end; // end of command + uint8_t complete_len; // complete length of frame + uint8_t stop_bit; // flag: frame has stop bit + uint8_t lsb_first; // flag: LSB first + uint8_t flags; // some flags +} IRMP_PARAMETER; + +#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER sircs_param = +{ + IRMP_SIRCS_PROTOCOL, // protocol: ir protocol + SIRCS_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + SIRCS_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + SIRCS_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + SIRCS_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + SIRCS_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + SIRCS_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + SIRCS_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + SIRCS_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + SIRCS_ADDRESS_OFFSET, // address_offset: address offset + SIRCS_ADDRESS_OFFSET + SIRCS_ADDRESS_LEN, // address_end: end of address + SIRCS_COMMAND_OFFSET, // command_offset: command offset + SIRCS_COMMAND_OFFSET + SIRCS_COMMAND_LEN, // command_end: end of command + SIRCS_COMPLETE_DATA_LEN, // complete_len: complete length of frame + SIRCS_STOP_BIT, // stop_bit: flag: frame has stop bit + SIRCS_LSB, // lsb_first: flag: LSB first + SIRCS_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER nec_param = +{ + IRMP_NEC_PROTOCOL, // protocol: ir protocol + NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + NEC_ADDRESS_OFFSET, // address_offset: address offset + NEC_ADDRESS_OFFSET + NEC_ADDRESS_LEN, // address_end: end of address + NEC_COMMAND_OFFSET, // command_offset: command offset + NEC_COMMAND_OFFSET + NEC_COMMAND_LEN, // command_end: end of command + NEC_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NEC_STOP_BIT, // stop_bit: flag: frame has stop bit + NEC_LSB, // lsb_first: flag: LSB first + NEC_FLAGS // flags: some flags +}; + +static const PROGMEM IRMP_PARAMETER nec_rep_param = +{ + IRMP_NEC_PROTOCOL, // protocol: ir protocol + NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + 0, // address_offset: address offset + 0, // address_end: end of address + 0, // command_offset: command offset + 0, // command_end: end of command + 0, // complete_len: complete length of frame + NEC_STOP_BIT, // stop_bit: flag: frame has stop bit + NEC_LSB, // lsb_first: flag: LSB first + NEC_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER nec42_param = +{ + IRMP_NEC42_PROTOCOL, // protocol: ir protocol + NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + NEC42_ADDRESS_OFFSET, // address_offset: address offset + NEC42_ADDRESS_OFFSET + NEC42_ADDRESS_LEN, // address_end: end of address + NEC42_COMMAND_OFFSET, // command_offset: command offset + NEC42_COMMAND_OFFSET + NEC42_COMMAND_LEN, // command_end: end of command + NEC42_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NEC_STOP_BIT, // stop_bit: flag: frame has stop bit + NEC_LSB, // lsb_first: flag: LSB first + NEC_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER samsung_param = +{ + IRMP_SAMSUNG_PROTOCOL, // protocol: ir protocol + SAMSUNG_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + SAMSUNG_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + SAMSUNG_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + SAMSUNG_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + SAMSUNG_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + SAMSUNG_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + SAMSUNG_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + SAMSUNG_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + SAMSUNG_ADDRESS_OFFSET, // address_offset: address offset + SAMSUNG_ADDRESS_OFFSET + SAMSUNG_ADDRESS_LEN, // address_end: end of address + SAMSUNG_COMMAND_OFFSET, // command_offset: command offset + SAMSUNG_COMMAND_OFFSET + SAMSUNG_COMMAND_LEN, // command_end: end of command + SAMSUNG_COMPLETE_DATA_LEN, // complete_len: complete length of frame + SAMSUNG_STOP_BIT, // stop_bit: flag: frame has stop bit + SAMSUNG_LSB, // lsb_first: flag: LSB first + SAMSUNG_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER matsushita_param = +{ + IRMP_MATSUSHITA_PROTOCOL, // protocol: ir protocol + MATSUSHITA_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + MATSUSHITA_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + MATSUSHITA_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + MATSUSHITA_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + MATSUSHITA_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + MATSUSHITA_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + MATSUSHITA_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + MATSUSHITA_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + MATSUSHITA_ADDRESS_OFFSET, // address_offset: address offset + MATSUSHITA_ADDRESS_OFFSET + MATSUSHITA_ADDRESS_LEN, // address_end: end of address + MATSUSHITA_COMMAND_OFFSET, // command_offset: command offset + MATSUSHITA_COMMAND_OFFSET + MATSUSHITA_COMMAND_LEN, // command_end: end of command + MATSUSHITA_COMPLETE_DATA_LEN, // complete_len: complete length of frame + MATSUSHITA_STOP_BIT, // stop_bit: flag: frame has stop bit + MATSUSHITA_LSB, // lsb_first: flag: LSB first + MATSUSHITA_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER kaseikyo_param = +{ + IRMP_KASEIKYO_PROTOCOL, // protocol: ir protocol + KASEIKYO_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + KASEIKYO_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + KASEIKYO_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + KASEIKYO_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + KASEIKYO_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + KASEIKYO_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + KASEIKYO_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + KASEIKYO_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + KASEIKYO_ADDRESS_OFFSET, // address_offset: address offset + KASEIKYO_ADDRESS_OFFSET + KASEIKYO_ADDRESS_LEN, // address_end: end of address + KASEIKYO_COMMAND_OFFSET, // command_offset: command offset + KASEIKYO_COMMAND_OFFSET + KASEIKYO_COMMAND_LEN, // command_end: end of command + KASEIKYO_COMPLETE_DATA_LEN, // complete_len: complete length of frame + KASEIKYO_STOP_BIT, // stop_bit: flag: frame has stop bit + KASEIKYO_LSB, // lsb_first: flag: LSB first + KASEIKYO_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RECS80_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER recs80_param = +{ + IRMP_RECS80_PROTOCOL, // protocol: ir protocol + RECS80_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + RECS80_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + RECS80_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + RECS80_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + RECS80_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + RECS80_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + RECS80_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + RECS80_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + RECS80_ADDRESS_OFFSET, // address_offset: address offset + RECS80_ADDRESS_OFFSET + RECS80_ADDRESS_LEN, // address_end: end of address + RECS80_COMMAND_OFFSET, // command_offset: command offset + RECS80_COMMAND_OFFSET + RECS80_COMMAND_LEN, // command_end: end of command + RECS80_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RECS80_STOP_BIT, // stop_bit: flag: frame has stop bit + RECS80_LSB, // lsb_first: flag: LSB first + RECS80_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER rc5_param = +{ + IRMP_RC5_PROTOCOL, // protocol: ir protocol + RC5_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + RC5_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + RC5_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + RC5_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + RC5_ADDRESS_OFFSET, // address_offset: address offset + RC5_ADDRESS_OFFSET + RC5_ADDRESS_LEN, // address_end: end of address + RC5_COMMAND_OFFSET, // command_offset: command offset + RC5_COMMAND_OFFSET + RC5_COMMAND_LEN, // command_end: end of command + RC5_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RC5_STOP_BIT, // stop_bit: flag: frame has stop bit + RC5_LSB, // lsb_first: flag: LSB first + RC5_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER denon_param = +{ + IRMP_DENON_PROTOCOL, // protocol: ir protocol + DENON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + DENON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + DENON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + DENON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + DENON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + DENON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + DENON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + DENON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + DENON_ADDRESS_OFFSET, // address_offset: address offset + DENON_ADDRESS_OFFSET + DENON_ADDRESS_LEN, // address_end: end of address + DENON_COMMAND_OFFSET, // command_offset: command offset + DENON_COMMAND_OFFSET + DENON_COMMAND_LEN, // command_end: end of command + DENON_COMPLETE_DATA_LEN, // complete_len: complete length of frame + DENON_STOP_BIT, // stop_bit: flag: frame has stop bit + DENON_LSB, // lsb_first: flag: LSB first + DENON_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER rc6_param = +{ + IRMP_RC6_PROTOCOL, // protocol: ir protocol + + RC6_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + RC6_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + RC6_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + RC6_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + RC6_ADDRESS_OFFSET, // address_offset: address offset + RC6_ADDRESS_OFFSET + RC6_ADDRESS_LEN, // address_end: end of address + RC6_COMMAND_OFFSET, // command_offset: command offset + RC6_COMMAND_OFFSET + RC6_COMMAND_LEN, // command_end: end of command + RC6_COMPLETE_DATA_LEN_SHORT, // complete_len: complete length of frame + RC6_STOP_BIT, // stop_bit: flag: frame has stop bit + RC6_LSB, // lsb_first: flag: LSB first + RC6_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER recs80ext_param = +{ + IRMP_RECS80EXT_PROTOCOL, // protocol: ir protocol + RECS80EXT_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + RECS80EXT_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + RECS80EXT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + RECS80EXT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + RECS80EXT_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + RECS80EXT_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + RECS80EXT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + RECS80EXT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + RECS80EXT_ADDRESS_OFFSET, // address_offset: address offset + RECS80EXT_ADDRESS_OFFSET + RECS80EXT_ADDRESS_LEN, // address_end: end of address + RECS80EXT_COMMAND_OFFSET, // command_offset: command offset + RECS80EXT_COMMAND_OFFSET + RECS80EXT_COMMAND_LEN, // command_end: end of command + RECS80EXT_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RECS80EXT_STOP_BIT, // stop_bit: flag: frame has stop bit + RECS80EXT_LSB, // lsb_first: flag: LSB first + RECS80EXT_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER nubert_param = +{ + IRMP_NUBERT_PROTOCOL, // protocol: ir protocol + NUBERT_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NUBERT_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NUBERT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NUBERT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NUBERT_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NUBERT_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NUBERT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NUBERT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + NUBERT_ADDRESS_OFFSET, // address_offset: address offset + NUBERT_ADDRESS_OFFSET + NUBERT_ADDRESS_LEN, // address_end: end of address + NUBERT_COMMAND_OFFSET, // command_offset: command offset + NUBERT_COMMAND_OFFSET + NUBERT_COMMAND_LEN, // command_end: end of command + NUBERT_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NUBERT_STOP_BIT, // stop_bit: flag: frame has stop bit + NUBERT_LSB, // lsb_first: flag: LSB first + NUBERT_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER bang_olufsen_param = +{ + IRMP_BANG_OLUFSEN_PROTOCOL, // protocol: ir protocol + BANG_OLUFSEN_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + BANG_OLUFSEN_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + BANG_OLUFSEN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + BANG_OLUFSEN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + BANG_OLUFSEN_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + BANG_OLUFSEN_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + BANG_OLUFSEN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + BANG_OLUFSEN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + BANG_OLUFSEN_ADDRESS_OFFSET, // address_offset: address offset + BANG_OLUFSEN_ADDRESS_OFFSET + BANG_OLUFSEN_ADDRESS_LEN, // address_end: end of address + BANG_OLUFSEN_COMMAND_OFFSET, // command_offset: command offset + BANG_OLUFSEN_COMMAND_OFFSET + BANG_OLUFSEN_COMMAND_LEN, // command_end: end of command + BANG_OLUFSEN_COMPLETE_DATA_LEN, // complete_len: complete length of frame + BANG_OLUFSEN_STOP_BIT, // stop_bit: flag: frame has stop bit + BANG_OLUFSEN_LSB, // lsb_first: flag: LSB first + BANG_OLUFSEN_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 + +static uint8_t first_bit; + +static const PROGMEM IRMP_PARAMETER grundig_param = +{ + IRMP_GRUNDIG_PROTOCOL, // protocol: ir protocol + + GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + GRUNDIG_NOKIA_IR60_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + GRUNDIG_NOKIA_IR60_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + GRUNDIG_ADDRESS_OFFSET, // address_offset: address offset + GRUNDIG_ADDRESS_OFFSET + GRUNDIG_ADDRESS_LEN, // address_end: end of address + GRUNDIG_COMMAND_OFFSET, // command_offset: command offset + GRUNDIG_COMMAND_OFFSET + GRUNDIG_COMMAND_LEN + 1, // command_end: end of command (USE 1 bit MORE to STORE NOKIA DATA!) + NOKIA_COMPLETE_DATA_LEN, // complete_len: complete length of frame, here: NOKIA instead of GRUNDIG! + GRUNDIG_NOKIA_IR60_STOP_BIT, // stop_bit: flag: frame has stop bit + GRUNDIG_NOKIA_IR60_LSB, // lsb_first: flag: LSB first + GRUNDIG_NOKIA_IR60_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER ruwido_param = +{ + IRMP_RUWIDO_PROTOCOL, // protocol: ir protocol + SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + RUWIDO_ADDRESS_OFFSET, // address_offset: address offset + RUWIDO_ADDRESS_OFFSET + RUWIDO_ADDRESS_LEN, // address_end: end of address + RUWIDO_COMMAND_OFFSET, // command_offset: command offset + RUWIDO_COMMAND_OFFSET + RUWIDO_COMMAND_LEN, // command_end: end of command + SIEMENS_COMPLETE_DATA_LEN, // complete_len: complete length of frame, here: SIEMENS instead of RUWIDO! + SIEMENS_OR_RUWIDO_STOP_BIT, // stop_bit: flag: frame has stop bit + SIEMENS_OR_RUWIDO_LSB, // lsb_first: flag: LSB first + SIEMENS_OR_RUWIDO_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_GRUNDIG2_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER grundig2_param = +{ + IRMP_GRUNDIG2_PROTOCOL, // protocol: ir protocol + GRUNDIG2_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + GRUNDIG2_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + GRUNDIG2_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + GRUNDIG2_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + GRUNDIG2_ADDRESS_OFFSET, // address_offset: address offset + GRUNDIG2_ADDRESS_OFFSET + GRUNDIG2_ADDRESS_LEN, // address_end: end of address + GRUNDIG2_COMMAND_OFFSET, // command_offset: command offset + GRUNDIG2_COMMAND_OFFSET + GRUNDIG2_COMMAND_LEN, // command_end: end of command + GRUNDIG2_COMPLETE_DATA_LEN, // complete_len: complete length of frame + GRUNDIG2_STOP_BIT, // stop_bit: flag: frame has stop bit + GRUNDIG2_LSB, // lsb_first: flag: LSB first + GRUNDIG2_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_FDC_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER fdc_param = +{ + IRMP_FDC_PROTOCOL, // protocol: ir protocol + FDC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + FDC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + FDC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + FDC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + FDC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + FDC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + FDC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + FDC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + FDC_ADDRESS_OFFSET, // address_offset: address offset + FDC_ADDRESS_OFFSET + FDC_ADDRESS_LEN, // address_end: end of address + FDC_COMMAND_OFFSET, // command_offset: command offset + FDC_COMMAND_OFFSET + FDC_COMMAND_LEN, // command_end: end of command + FDC_COMPLETE_DATA_LEN, // complete_len: complete length of frame + FDC_STOP_BIT, // stop_bit: flag: frame has stop bit + FDC_LSB, // lsb_first: flag: LSB first + FDC_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER rccar_param = +{ + IRMP_RCCAR_PROTOCOL, // protocol: ir protocol + RCCAR_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + RCCAR_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + RCCAR_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + RCCAR_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + RCCAR_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + RCCAR_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + RCCAR_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + RCCAR_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + RCCAR_ADDRESS_OFFSET, // address_offset: address offset + RCCAR_ADDRESS_OFFSET + RCCAR_ADDRESS_LEN, // address_end: end of address + RCCAR_COMMAND_OFFSET, // command_offset: command offset + RCCAR_COMMAND_OFFSET + RCCAR_COMMAND_LEN, // command_end: end of command + RCCAR_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RCCAR_STOP_BIT, // stop_bit: flag: frame has stop bit + RCCAR_LSB, // lsb_first: flag: LSB first + RCCAR_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER nikon_param = +{ + IRMP_NIKON_PROTOCOL, // protocol: ir protocol + NIKON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NIKON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NIKON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NIKON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NIKON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NIKON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NIKON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NIKON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + NIKON_ADDRESS_OFFSET, // address_offset: address offset + NIKON_ADDRESS_OFFSET + NIKON_ADDRESS_LEN, // address_end: end of address + NIKON_COMMAND_OFFSET, // command_offset: command offset + NIKON_COMMAND_OFFSET + NIKON_COMMAND_LEN, // command_end: end of command + NIKON_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NIKON_STOP_BIT, // stop_bit: flag: frame has stop bit + NIKON_LSB, // lsb_first: flag: LSB first + NIKON_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER kathrein_param = +{ + IRMP_KATHREIN_PROTOCOL, // protocol: ir protocol + KATHREIN_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + KATHREIN_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + KATHREIN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + KATHREIN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + KATHREIN_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + KATHREIN_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + KATHREIN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + KATHREIN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + KATHREIN_ADDRESS_OFFSET, // address_offset: address offset + KATHREIN_ADDRESS_OFFSET + KATHREIN_ADDRESS_LEN, // address_end: end of address + KATHREIN_COMMAND_OFFSET, // command_offset: command offset + KATHREIN_COMMAND_OFFSET + KATHREIN_COMMAND_LEN, // command_end: end of command + KATHREIN_COMPLETE_DATA_LEN, // complete_len: complete length of frame + KATHREIN_STOP_BIT, // stop_bit: flag: frame has stop bit + KATHREIN_LSB, // lsb_first: flag: LSB first + KATHREIN_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER netbox_param = +{ + IRMP_NETBOX_PROTOCOL, // protocol: ir protocol + NETBOX_PULSE_LEN, // pulse_1_len_min: minimum length of pulse with bit value 1, here: exact value + NETBOX_PULSE_REST_LEN, // pulse_1_len_max: maximum length of pulse with bit value 1, here: rest value + NETBOX_PAUSE_LEN, // pause_1_len_min: minimum length of pause with bit value 1, here: exact value + NETBOX_PAUSE_REST_LEN, // pause_1_len_max: maximum length of pause with bit value 1, here: rest value + NETBOX_PULSE_LEN, // pulse_0_len_min: minimum length of pulse with bit value 0, here: exact value + NETBOX_PULSE_REST_LEN, // pulse_0_len_max: maximum length of pulse with bit value 0, here: rest value + NETBOX_PAUSE_LEN, // pause_0_len_min: minimum length of pause with bit value 0, here: exact value + NETBOX_PAUSE_REST_LEN, // pause_0_len_max: maximum length of pause with bit value 0, here: rest value + NETBOX_ADDRESS_OFFSET, // address_offset: address offset + NETBOX_ADDRESS_OFFSET + NETBOX_ADDRESS_LEN, // address_end: end of address + NETBOX_COMMAND_OFFSET, // command_offset: command offset + NETBOX_COMMAND_OFFSET + NETBOX_COMMAND_LEN, // command_end: end of command + NETBOX_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NETBOX_STOP_BIT, // stop_bit: flag: frame has stop bit + NETBOX_LSB, // lsb_first: flag: LSB first + NETBOX_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER lego_param = +{ + IRMP_LEGO_PROTOCOL, // protocol: ir protocol + LEGO_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + LEGO_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + LEGO_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + LEGO_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + LEGO_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + LEGO_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + LEGO_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + LEGO_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + LEGO_ADDRESS_OFFSET, // address_offset: address offset + LEGO_ADDRESS_OFFSET + LEGO_ADDRESS_LEN, // address_end: end of address + LEGO_COMMAND_OFFSET, // command_offset: command offset + LEGO_COMMAND_OFFSET + LEGO_COMMAND_LEN, // command_end: end of command + LEGO_COMPLETE_DATA_LEN, // complete_len: complete length of frame + LEGO_STOP_BIT, // stop_bit: flag: frame has stop bit + LEGO_LSB, // lsb_first: flag: LSB first + LEGO_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER thomson_param = +{ + IRMP_THOMSON_PROTOCOL, // protocol: ir protocol + THOMSON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + THOMSON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + THOMSON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + THOMSON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + THOMSON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + THOMSON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + THOMSON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + THOMSON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + THOMSON_ADDRESS_OFFSET, // address_offset: address offset + THOMSON_ADDRESS_OFFSET + THOMSON_ADDRESS_LEN, // address_end: end of address + THOMSON_COMMAND_OFFSET, // command_offset: command offset + THOMSON_COMMAND_OFFSET + THOMSON_COMMAND_LEN, // command_end: end of command + THOMSON_COMPLETE_DATA_LEN, // complete_len: complete length of frame + THOMSON_STOP_BIT, // stop_bit: flag: frame has stop bit + THOMSON_LSB, // lsb_first: flag: LSB first + THOMSON_FLAGS // flags: some flags +}; + +#endif + +static uint8_t irmp_bit; // current bit position +static IRMP_PARAMETER irmp_param; + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) +static IRMP_PARAMETER irmp_param2; +#endif + +static volatile uint8_t irmp_ir_detected; +static volatile uint8_t irmp_protocol; +static volatile uint16_t irmp_address; +static volatile uint16_t irmp_command; +static volatile uint16_t irmp_id; // only used for SAMSUNG protocol +static volatile uint8_t irmp_flags; +// static volatile uint8_t irmp_busy_flag; + +#ifdef ANALYZE +static uint8_t IRMP_PIN; +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Initialize IRMP decoder + * @details Configures IRMP input pin + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef ANALYZE +void +irmp_init (void) +{ +#ifndef ARDUINO +#if !defined(PIC_CCS_COMPILER) && !defined(PIC_C18) // only AVR + IRMP_PORT &= ~(1<> 8) == (~irmp_command & 0x00FF)) + { + irmp_command &= 0xff; + irmp_command |= irmp_id << 8; + rtc = TRUE; + } + break; +#endif +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + case IRMP_NEC_PROTOCOL: + if ((irmp_command >> 8) == (~irmp_command & 0x00FF)) + { + irmp_command &= 0xff; + rtc = TRUE; + } + else if (irmp_address == 0x87EE) + { + ANALYZE_PRINTF ("Switching to APPLE protocol\n"); + irmp_protocol = IRMP_APPLE_PROTOCOL; + irmp_address = (irmp_command & 0xFF00) >> 8; + irmp_command &= 0x00FF; + rtc = TRUE; + } + break; +#endif +#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + case IRMP_SIEMENS_PROTOCOL: + case IRMP_RUWIDO_PROTOCOL: + if (((irmp_command >> 1) & 0x0001) == (~irmp_command & 0x0001)) + { + irmp_command >>= 1; + rtc = TRUE; + } + break; +#endif +#if IRMP_SUPPORT_GRUNDIG2_PROTOCOL == 1 + case IRMP_GRUNDIG2_PROTOCOL: + if (irmp_command & 0x0001) + { + irmp_command >>= 1; + rtc = TRUE; + } + break; +#endif +#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 + case IRMP_KATHREIN_PROTOCOL: + if (irmp_command != 0x0000) + { + rtc = TRUE; + } + break; +#endif +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 + case IRMP_RC5_PROTOCOL: + irmp_address &= ~0x20; // clear toggle bit + rtc = TRUE; + break; +#endif +#if IRMP_SUPPORT_IR60_PROTOCOL == 1 + case IRMP_IR60_PROTOCOL: + if (irmp_command != 0x007d) // 0x007d (== 62<<1 + 1) is start instruction frame + { + rtc = TRUE; + } + break; +#endif +#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + case IRMP_RCCAR_PROTOCOL: + // frame in irmp_data: + // Bit 12 11 10 9 8 7 6 5 4 3 2 1 0 + // V D7 D6 D5 D4 D3 D2 D1 D0 A1 A0 C1 C0 // 10 9 8 7 6 5 4 3 2 1 0 + irmp_address = (irmp_command & 0x000C) >> 2; // addr: 0 0 0 0 0 0 0 0 0 A1 A0 + irmp_command = ((irmp_command & 0x1000) >> 2) | // V-Bit: V 0 0 0 0 0 0 0 0 0 0 + ((irmp_command & 0x0003) << 8) | // C-Bits: 0 C1 C0 0 0 0 0 0 0 0 0 + ((irmp_command & 0x0FF0) >> 4); // D-Bits: D7 D6 D5 D4 D3 D2 D1 D0 + rtc = TRUE; // Summe: V C1 C0 D7 D6 D5 D4 D3 D2 D1 D0 + break; +#endif + +#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 // squeeze code to 8 bit, upper bit indicates release-key + case IRMP_NETBOX_PROTOCOL: + if (irmp_command & 0x1000) // last bit set? + { + if ((irmp_command & 0x1f) == 0x15) // key pressed: 101 01 (LSB) + { + irmp_command >>= 5; + irmp_command &= 0x7F; + rtc = TRUE; + } + else if ((irmp_command & 0x1f) == 0x10) // key released: 000 01 (LSB) + { + irmp_command >>= 5; + irmp_command |= 0x80; + rtc = TRUE; + } + else + { + ANALYZE_PRINTF("error NETBOX: bit6/7 must be 0/1\n"); + } + } + else + { + ANALYZE_PRINTF("error NETBOX: last bit not set\n"); + } + break; +#endif +#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 + case IRMP_LEGO_PROTOCOL: + { + uint8_t crc = 0x0F ^ ((irmp_command & 0xF000) >> 12) ^ ((irmp_command & 0x0F00) >> 8) ^ ((irmp_command & 0x00F0) >> 4); + + if ((irmp_command & 0x000F) == crc) + { + irmp_command >>= 4; + rtc = TRUE; + } + else + { + ANALYZE_PRINTF ("CRC error in LEGO protocol\n"); + rtc = TRUE; + } + break; + } +#endif + default: + rtc = TRUE; + } + + if (rtc) + { + irmp_data_p->protocol = irmp_protocol; + irmp_data_p->address = irmp_address; + irmp_data_p->command = irmp_command; + irmp_data_p->flags = irmp_flags; + irmp_command = 0; + irmp_address = 0; + irmp_flags = 0; + } + + irmp_ir_detected = FALSE; + } + + return rtc; +} + +// uint8_t +// irmp_is_busy (void) +// { +// return irmp_busy_flag; +// } + +#if IRMP_USE_CALLBACK == 1 +void +irmp_set_callback_ptr (void (*cb)(uint8_t)) +{ + irmp_callback_ptr = cb; +} +#endif // IRMP_USE_CALLBACK == 1 + +// these statics must not be volatile, because they are only used by irmp_store_bit(), which is called by irmp_ISR() +static uint16_t irmp_tmp_address; // ir address +static uint16_t irmp_tmp_command; // ir command + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) || IRMP_SUPPORT_NEC42_PROTOCOL == 1 +static uint16_t irmp_tmp_address2; // ir address +static uint16_t irmp_tmp_command2; // ir command +#endif + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 +static uint16_t irmp_tmp_id; // ir id (only SAMSUNG) +#endif +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 +static uint8_t xor_check[6]; // check kaseikyo "parity" bits +static uint8_t genre2; // save genre2 bits here, later copied to MSB in flags +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * store bit + * @details store bit in temp address or temp command + * @param value to store: 0 or 1 + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +// verhindert, dass irmp_store_bit() inline compiliert wird: +// static void irmp_store_bit (uint8_t) __attribute__ ((noinline)); + +static void +irmp_store_bit (uint8_t value) +{ +#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 + if (irmp_bit == 0 && irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL) + { + first_bit = value; + } + else +#endif + + if (irmp_bit >= irmp_param.address_offset && irmp_bit < irmp_param.address_end) + { + if (irmp_param.lsb_first) + { + irmp_tmp_address |= (((uint16_t) (value)) << (irmp_bit - irmp_param.address_offset)); // CV wants cast + } + else + { + irmp_tmp_address <<= 1; + irmp_tmp_address |= value; + } + } + else if (irmp_bit >= irmp_param.command_offset && irmp_bit < irmp_param.command_end) + { + if (irmp_param.lsb_first) + { + irmp_tmp_command |= (((uint16_t) (value)) << (irmp_bit - irmp_param.command_offset)); // CV wants cast + } + else + { + irmp_tmp_command <<= 1; + irmp_tmp_command |= value; + } + } + +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit >= 13 && irmp_bit < 26) + { + irmp_tmp_address2 |= (((uint16_t) (value)) << (irmp_bit - 13)); // CV wants cast + } +#endif + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_SAMSUNG_PROTOCOL && irmp_bit >= SAMSUNG_ID_OFFSET && irmp_bit < SAMSUNG_ID_OFFSET + SAMSUNG_ID_LEN) + { + irmp_tmp_id |= (((uint16_t) (value)) << (irmp_bit - SAMSUNG_ID_OFFSET)); // store with LSB first + } +#endif + +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL) + { + if (irmp_bit >= 20 && irmp_bit < 24) + { + irmp_tmp_command |= (((uint16_t) (value)) << (irmp_bit - 8)); // store 4 system bits (genre 1) in upper nibble with LSB first + } + else if (irmp_bit >= 24 && irmp_bit < 28) + { + genre2 |= (((uint8_t) (value)) << (irmp_bit - 20)); // store 4 system bits (genre 2) in upper nibble with LSB first + } + + if (irmp_bit < KASEIKYO_COMPLETE_DATA_LEN) + { + if (value) + { + xor_check[irmp_bit / 8] |= 1 << (irmp_bit % 8); + } + else + { + xor_check[irmp_bit / 8] &= ~(1 << (irmp_bit % 8)); + } + } + } +#endif + + irmp_bit++; +} + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * store bit + * @details store bit in temp address or temp command + * @param value to store: 0 or 1 + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) +static void +irmp_store_bit2 (uint8_t value) +{ + uint8_t irmp_bit2; + + if (irmp_param.protocol) + { + irmp_bit2 = irmp_bit - 2; + } + else + { + irmp_bit2 = irmp_bit - 1; + } + + if (irmp_bit2 >= irmp_param2.address_offset && irmp_bit2 < irmp_param2.address_end) + { + irmp_tmp_address2 |= (((uint16_t) (value)) << (irmp_bit2 - irmp_param2.address_offset)); // CV wants cast + } + else if (irmp_bit2 >= irmp_param2.command_offset && irmp_bit2 < irmp_param2.command_end) + { + irmp_tmp_command2 |= (((uint16_t) (value)) << (irmp_bit2 - irmp_param2.command_offset)); // CV wants cast + } +} +#endif // IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * ISR routine + * @details ISR routine, called 10000 times per second + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +uint8_t +irmp_ISR (uint8_t x42) +{ + static uint8_t irmp_start_bit_detected; // flag: start bit detected + static uint8_t wait_for_space; // flag: wait for data bit space + static uint8_t wait_for_start_space; // flag: wait for start bit space + static uint8_t irmp_pulse_time; // count bit time for pulse + static PAUSE_LEN irmp_pause_time; // count bit time for pause + static uint16_t last_irmp_address = 0xFFFF; // save last irmp address to recognize key repetition + static uint16_t last_irmp_command = 0xFFFF; // save last irmp command to recognize key repetition + static uint16_t repetition_len; // SIRCS repeats frame 2-5 times with 45 ms pause + static uint8_t repetition_frame_number; +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + static uint16_t last_irmp_denon_command; // save last irmp command to recognize DENON frame repetition +#endif +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 + static uint8_t rc5_cmd_bit6; // bit 6 of RC5 command is the inverted 2nd start bit +#endif +#if IRMP_SUPPORT_MANCHESTER == 1 + static PAUSE_LEN last_pause; // last pause value +#endif +#if IRMP_SUPPORT_MANCHESTER == 1 || IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + static uint8_t last_value; // last bit value +#endif + uint8_t irmp_input; // input value + +#ifdef ANALYZE + time_counter++; +#endif + + irmp_input = input(x42); + +#if IRMP_USE_CALLBACK == 1 + if (irmp_callback_ptr) + { + static uint8_t last_inverted_input; + + if (last_inverted_input != !irmp_input) + { + (*irmp_callback_ptr) (! irmp_input); + last_inverted_input = !irmp_input; + } + } +#endif // IRMP_USE_CALLBACK == 1 + + irmp_log(irmp_input); // log ir signal, if IRMP_LOGGING defined + + if (! irmp_ir_detected) // ir code already detected? + { // no... + if (! irmp_start_bit_detected) // start bit detected? + { // no... + if (! irmp_input) // receiving burst? + { // yes... +// irmp_busy_flag = TRUE; +#ifdef ANALYZE + if (! irmp_pulse_time) + { + ANALYZE_PRINTF("%8.3fms [starting pulse]\n", (double) (time_counter * 1000) / F_INTERRUPTS); + } +#endif + irmp_pulse_time++; // increment counter + } + else + { // no... + if (irmp_pulse_time) // it's dark.... + { // set flags for counting the time of darkness... + irmp_start_bit_detected = 1; + wait_for_start_space = 1; + wait_for_space = 0; + irmp_tmp_command = 0; + irmp_tmp_address = 0; +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + genre2 = 0; +#endif + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) || IRMP_SUPPORT_NEC42_PROTOCOL == 1 + irmp_tmp_command2 = 0; + irmp_tmp_address2 = 0; +#endif + + irmp_bit = 0xff; + irmp_pause_time = 1; // 1st pause: set to 1, not to 0! +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 + rc5_cmd_bit6 = 0; // fm 2010-03-07: bugfix: reset it after incomplete RC5 frame! +#endif + } + else + { + if (repetition_len < 0xFFFF) // avoid overflow of counter + { + repetition_len++; + } + } + } + } + else + { + if (wait_for_start_space) // we have received start bit... + { // ...and are counting the time of darkness + if (irmp_input) // still dark? + { // yes + irmp_pause_time++; // increment counter + +#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 + if (((irmp_pulse_time < NIKON_START_BIT_PULSE_LEN_MIN || irmp_pulse_time > NIKON_START_BIT_PULSE_LEN_MAX) && irmp_pause_time > IRMP_TIMEOUT_LEN) || + irmp_pause_time > IRMP_TIMEOUT_NIKON_LEN) +#else + if (irmp_pause_time > IRMP_TIMEOUT_LEN) // timeout? +#endif + { // yes... +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + if (irmp_protocol == IRMP_JVC_PROTOCOL) // don't show eror if JVC protocol, irmp_pulse_time has been set below! + { + ; + } + else +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + { + ANALYZE_PRINTF ("%8.3fms error 1: pause after start bit pulse %d too long: %d\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); + } +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // reset flags, let's wait for another start bit + irmp_pulse_time = 0; + irmp_pause_time = 0; + } + } + else + { // receiving first data pulse! + IRMP_PARAMETER * irmp_param_p = (IRMP_PARAMETER *) 0; + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) + irmp_param2.protocol = 0; +#endif + + ANALYZE_PRINTF ("%8.3fms [start-bit: pulse = %2d, pause = %2d]\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_pulse_time, irmp_pause_time); + +#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 + if (irmp_pulse_time >= SIRCS_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SIRCS_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= SIRCS_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SIRCS_START_BIT_PAUSE_LEN_MAX) + { // it's SIRCS + ANALYZE_PRINTF ("protocol = SIRCS, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + SIRCS_START_BIT_PULSE_LEN_MIN, SIRCS_START_BIT_PULSE_LEN_MAX, + SIRCS_START_BIT_PAUSE_LEN_MIN, SIRCS_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) (IRMP_PARAMETER *) &sircs_param; + } + else +#endif // IRMP_SUPPORT_SIRCS_PROTOCOL == 1 + +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + if (irmp_protocol == IRMP_JVC_PROTOCOL && // last protocol was JVC, awaiting repeat frame + irmp_pulse_time >= JVC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= JVC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= JVC_REPEAT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= JVC_REPEAT_START_BIT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("protocol = NEC or JVC (type 1) repeat frame, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + JVC_START_BIT_PULSE_LEN_MIN, JVC_START_BIT_PULSE_LEN_MAX, + JVC_REPEAT_START_BIT_PAUSE_LEN_MIN, JVC_REPEAT_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &nec_param; + } + else +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + if (irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NEC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_START_BIT_PAUSE_LEN_MAX) + { +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 + ANALYZE_PRINTF ("protocol = NEC42, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, + NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &nec42_param; +#else + ANALYZE_PRINTF ("protocol = NEC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, + NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &nec_param; +#endif + + } + else if (irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NEC_REPEAT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_REPEAT_START_BIT_PAUSE_LEN_MAX) + { // it's NEC +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + if (irmp_protocol == IRMP_JVC_PROTOCOL) // last protocol was JVC, awaiting repeat frame + { // some jvc remote controls use nec repetition frame for jvc repetition frame + ANALYZE_PRINTF ("protocol = JVC repeat frame type 2, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, + NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &nec_param; + } + else +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + { + ANALYZE_PRINTF ("protocol = NEC (repetition frame), start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, + NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX); + + irmp_param_p = (IRMP_PARAMETER *) &nec_rep_param; + } + } + else + +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + if (irmp_protocol == IRMP_JVC_PROTOCOL && // last protocol was JVC, awaiting repeat frame + irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NEC_0_PAUSE_LEN_MIN && irmp_pause_time <= NEC_0_PAUSE_LEN_MAX) + { // it's JVC repetition type 3 + ANALYZE_PRINTF ("protocol = JVC repeat frame type 3, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, + NEC_0_PAUSE_LEN_MIN, NEC_0_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &nec_param; + } + else +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + +#endif // IRMP_SUPPORT_NEC_PROTOCOL == 1 + +#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 + if (irmp_pulse_time >= NIKON_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NIKON_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NIKON_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NIKON_START_BIT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("protocol = NIKON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NIKON_START_BIT_PULSE_LEN_MIN, NIKON_START_BIT_PULSE_LEN_MAX, + NIKON_START_BIT_PAUSE_LEN_MIN, NIKON_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &nikon_param; + } + else +#endif // IRMP_SUPPORT_NIKON_PROTOCOL == 1 + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + if (irmp_pulse_time >= SAMSUNG_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= SAMSUNG_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_START_BIT_PAUSE_LEN_MAX) + { // it's SAMSUNG + ANALYZE_PRINTF ("protocol = SAMSUNG, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + SAMSUNG_START_BIT_PULSE_LEN_MIN, SAMSUNG_START_BIT_PULSE_LEN_MAX, + SAMSUNG_START_BIT_PAUSE_LEN_MIN, SAMSUNG_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &samsung_param; + } + else +#endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + +#if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 + if (irmp_pulse_time >= MATSUSHITA_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MATSUSHITA_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= MATSUSHITA_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MATSUSHITA_START_BIT_PAUSE_LEN_MAX) + { // it's MATSUSHITA + ANALYZE_PRINTF ("protocol = MATSUSHITA, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + MATSUSHITA_START_BIT_PULSE_LEN_MIN, MATSUSHITA_START_BIT_PULSE_LEN_MAX, + MATSUSHITA_START_BIT_PAUSE_LEN_MIN, MATSUSHITA_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &matsushita_param; + } + else +#endif // IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 + +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + if (irmp_pulse_time >= KASEIKYO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= KASEIKYO_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= KASEIKYO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KASEIKYO_START_BIT_PAUSE_LEN_MAX) + { // it's KASEIKYO + ANALYZE_PRINTF ("protocol = KASEIKYO, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + KASEIKYO_START_BIT_PULSE_LEN_MIN, KASEIKYO_START_BIT_PULSE_LEN_MAX, + KASEIKYO_START_BIT_PAUSE_LEN_MIN, KASEIKYO_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &kaseikyo_param; + } + else +#endif // IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + +#if IRMP_SUPPORT_RECS80_PROTOCOL == 1 + if (irmp_pulse_time >= RECS80_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RECS80_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RECS80_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RECS80_START_BIT_PAUSE_LEN_MAX) + { // it's RECS80 + ANALYZE_PRINTF ("protocol = RECS80, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RECS80_START_BIT_PULSE_LEN_MIN, RECS80_START_BIT_PULSE_LEN_MAX, + RECS80_START_BIT_PAUSE_LEN_MIN, RECS80_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &recs80_param; + } + else +#endif // IRMP_SUPPORT_RECS80_PROTOCOL == 1 + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 + if (((irmp_pulse_time >= RC5_START_BIT_LEN_MIN && irmp_pulse_time <= RC5_START_BIT_LEN_MAX) || + (irmp_pulse_time >= 2 * RC5_START_BIT_LEN_MIN && irmp_pulse_time <= 2 * RC5_START_BIT_LEN_MAX)) && + ((irmp_pause_time >= RC5_START_BIT_LEN_MIN && irmp_pause_time <= RC5_START_BIT_LEN_MAX) || + (irmp_pause_time >= 2 * RC5_START_BIT_LEN_MIN && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX))) + { // it's RC5 +#if IRMP_SUPPORT_FDC_PROTOCOL == 1 + if (irmp_pulse_time >= FDC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FDC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= FDC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FDC_START_BIT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("protocol = RC5 or FDC\n"); + ANALYZE_PRINTF ("FDC start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX, + FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX); + ANALYZE_PRINTF ("RC5 start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX); + memcpy_P (&irmp_param2, &fdc_param, sizeof (IRMP_PARAMETER)); + } + else +#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 + +#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + if (irmp_pulse_time >= RCCAR_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RCCAR_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_START_BIT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("protocol = RC5 or RCCAR\n"); + ANALYZE_PRINTF ("RCCAR start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX, + RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX); + ANALYZE_PRINTF ("RC5 start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX); + memcpy_P (&irmp_param2, &rccar_param, sizeof (IRMP_PARAMETER)); + } + else +#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + { + ANALYZE_PRINTF ("protocol = RC5, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or pulse: %3d - %3d, pause: %3d - %3d\n", + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, + 2 * RC5_START_BIT_LEN_MIN, 2 * RC5_START_BIT_LEN_MAX, + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, + 2 * RC5_START_BIT_LEN_MIN, 2 * RC5_START_BIT_LEN_MAX); + } + + irmp_param_p = (IRMP_PARAMETER *) &rc5_param; + last_pause = irmp_pause_time; + + if ((irmp_pulse_time > RC5_START_BIT_LEN_MAX && irmp_pulse_time <= 2 * RC5_START_BIT_LEN_MAX) || + (irmp_pause_time > RC5_START_BIT_LEN_MAX && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX)) + { + last_value = 0; + rc5_cmd_bit6 = 1<<6; + } + else + { + last_value = 1; + } + } + else +#endif // IRMP_SUPPORT_RC5_PROTOCOL == 1 + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + if ( (irmp_pulse_time >= DENON_PULSE_LEN_MIN && irmp_pulse_time <= DENON_PULSE_LEN_MAX) && + ((irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX) || + (irmp_pause_time >= DENON_0_PAUSE_LEN_MIN && irmp_pause_time <= DENON_0_PAUSE_LEN_MAX))) + { // it's DENON + ANALYZE_PRINTF ("protocol = DENON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or %3d - %3d\n", + DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX, + DENON_1_PAUSE_LEN_MIN, DENON_1_PAUSE_LEN_MAX, + DENON_0_PAUSE_LEN_MIN, DENON_0_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &denon_param; + } + else +#endif // IRMP_SUPPORT_DENON_PROTOCOL == 1 + +#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 + if ( (irmp_pulse_time >= THOMSON_PULSE_LEN_MIN && irmp_pulse_time <= THOMSON_PULSE_LEN_MAX) && + ((irmp_pause_time >= THOMSON_1_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_1_PAUSE_LEN_MAX) || + (irmp_pause_time >= THOMSON_0_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_0_PAUSE_LEN_MAX))) + { // it's THOMSON + ANALYZE_PRINTF ("protocol = THOMSON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or %3d - %3d\n", + THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX, + THOMSON_1_PAUSE_LEN_MIN, THOMSON_1_PAUSE_LEN_MAX, + THOMSON_0_PAUSE_LEN_MIN, THOMSON_0_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &thomson_param; + } + else +#endif // IRMP_SUPPORT_THOMSON_PROTOCOL == 1 + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_pulse_time >= RC6_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RC6_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RC6_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RC6_START_BIT_PAUSE_LEN_MAX) + { // it's RC6 + ANALYZE_PRINTF ("protocol = RC6, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RC6_START_BIT_PULSE_LEN_MIN, RC6_START_BIT_PULSE_LEN_MAX, + RC6_START_BIT_PAUSE_LEN_MIN, RC6_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &rc6_param; + last_pause = 0; + last_value = 1; + } + else +#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 + +#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 + if (irmp_pulse_time >= RECS80EXT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RECS80EXT_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RECS80EXT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RECS80EXT_START_BIT_PAUSE_LEN_MAX) + { // it's RECS80EXT + ANALYZE_PRINTF ("protocol = RECS80EXT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RECS80EXT_START_BIT_PULSE_LEN_MIN, RECS80EXT_START_BIT_PULSE_LEN_MAX, + RECS80EXT_START_BIT_PAUSE_LEN_MIN, RECS80EXT_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &recs80ext_param; + } + else +#endif // IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 + +#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 + if (irmp_pulse_time >= NUBERT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NUBERT_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NUBERT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NUBERT_START_BIT_PAUSE_LEN_MAX) + { // it's NUBERT + ANALYZE_PRINTF ("protocol = NUBERT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NUBERT_START_BIT_PULSE_LEN_MIN, NUBERT_START_BIT_PULSE_LEN_MAX, + NUBERT_START_BIT_PAUSE_LEN_MIN, NUBERT_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &nubert_param; + } + else +#endif // IRMP_SUPPORT_NUBERT_PROTOCOL == 1 + +#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + if (irmp_pulse_time >= BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN && irmp_pulse_time <= BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX && + irmp_pause_time >= BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX) + { // it's BANG_OLUFSEN + ANALYZE_PRINTF ("protocol = BANG_OLUFSEN\n"); + ANALYZE_PRINTF ("start bit 1 timings: pulse: %3d - %3d, pause: %3d - %3d\n", + BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX); + ANALYZE_PRINTF ("start bit 2 timings: pulse: %3d - %3d, pause: %3d - %3d\n", + BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX); + ANALYZE_PRINTF ("start bit 3 timings: pulse: %3d - %3d, pause: %3d - %3d\n", + BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX); + ANALYZE_PRINTF ("start bit 4 timings: pulse: %3d - %3d, pause: %3d - %3d\n", + BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &bang_olufsen_param; + last_value = 0; + } + else +#endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + +#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 + if (irmp_pulse_time >= GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN && irmp_pulse_time <= GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX && + irmp_pause_time >= GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN && irmp_pause_time <= GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX) + { // it's GRUNDIG + ANALYZE_PRINTF ("protocol = GRUNDIG, pre bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN, GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX, + GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN, GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &grundig_param; + last_pause = irmp_pause_time; + last_value = 1; + } + else +#endif // IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 + +#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + if (((irmp_pulse_time >= SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX) || + (irmp_pulse_time >= 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX)) && + ((irmp_pause_time >= SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX) || + (irmp_pause_time >= 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX))) + { // it's RUWIDO or SIEMENS + ANALYZE_PRINTF ("protocol = RUWIDO, start bit timings: pulse: %3d - %3d or %3d - %3d, pause: %3d - %3d or %3d - %3d\n", + SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX, + 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX, + SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX, + 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &ruwido_param; + last_pause = irmp_pause_time; + last_value = 1; + } + else +#endif // IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + +#if IRMP_SUPPORT_GRUNDIG2_PROTOCOL == 1 + if ((irmp_pulse_time >= GRUNDIG2_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= GRUNDIG2_START_BIT_PULSE_LEN_MAX) && + (irmp_pause_time >= GRUNDIG2_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= GRUNDIG2_START_BIT_PAUSE_LEN_MAX)) + { // it's GRUNDIG2 + ANALYZE_PRINTF ("protocol = GRUNDIG2, start bit timings: pulse: %3d - %3d or %3d - %3d, pause: %3d - %3d or %3d - %3d\n", + GRUNDIG2_START_BIT_PULSE_LEN_MIN, GRUNDIG2_START_BIT_PULSE_LEN_MAX, + 2 * GRUNDIG2_START_BIT_PULSE_LEN_MIN, 2 * GRUNDIG2_START_BIT_PULSE_LEN_MAX, + GRUNDIG2_START_BIT_PAUSE_LEN_MIN, GRUNDIG2_START_BIT_PAUSE_LEN_MAX, + 2 * GRUNDIG2_START_BIT_PAUSE_LEN_MIN, 2 * GRUNDIG2_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &grundig2_param; + last_pause = irmp_pause_time; + last_value = 1; + } + else +#endif // IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + +#if IRMP_SUPPORT_FDC_PROTOCOL == 1 + if (irmp_pulse_time >= FDC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FDC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= FDC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FDC_START_BIT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("protocol = FDC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX, + FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &fdc_param; + } + else +#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 + +#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + if (irmp_pulse_time >= RCCAR_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RCCAR_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_START_BIT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("protocol = RCCAR, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX, + RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &rccar_param; + } + else +#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + +#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 + if (irmp_pulse_time >= KATHREIN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= KATHREIN_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= KATHREIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_START_BIT_PAUSE_LEN_MAX) + { // it's KATHREIN + ANALYZE_PRINTF ("protocol = KATHREIN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + KATHREIN_START_BIT_PULSE_LEN_MIN, KATHREIN_START_BIT_PULSE_LEN_MAX, + KATHREIN_START_BIT_PAUSE_LEN_MIN, KATHREIN_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &kathrein_param; + } + else +#endif // IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 + +#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 + if (irmp_pulse_time >= NETBOX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NETBOX_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NETBOX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NETBOX_START_BIT_PAUSE_LEN_MAX) + { // it's NETBOX + ANALYZE_PRINTF ("protocol = NETBOX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NETBOX_START_BIT_PULSE_LEN_MIN, NETBOX_START_BIT_PULSE_LEN_MAX, + NETBOX_START_BIT_PAUSE_LEN_MIN, NETBOX_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &netbox_param; + } + else +#endif // IRMP_SUPPORT_NETBOX_PROTOCOL == 1 + +#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 + if (irmp_pulse_time >= LEGO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= LEGO_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= LEGO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= LEGO_START_BIT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("protocol = LEGO, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + LEGO_START_BIT_PULSE_LEN_MIN, LEGO_START_BIT_PULSE_LEN_MAX, + LEGO_START_BIT_PAUSE_LEN_MIN, LEGO_START_BIT_PAUSE_LEN_MAX); + irmp_param_p = (IRMP_PARAMETER *) &lego_param; + } + else +#endif // IRMP_SUPPORT_LEGO_PROTOCOL == 1 + + { + ANALYZE_PRINTF ("protocol = UNKNOWN\n"); +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // wait for another start bit... + } + + if (irmp_start_bit_detected) + { + memcpy_P (&irmp_param, irmp_param_p, sizeof (IRMP_PARAMETER)); + +#ifdef ANALYZE + if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) + { + ANALYZE_PRINTF ("pulse_1: %3d - %3d\n", irmp_param.pulse_1_len_min, irmp_param.pulse_1_len_max); + ANALYZE_PRINTF ("pause_1: %3d - %3d\n", irmp_param.pause_1_len_min, irmp_param.pause_1_len_max); + } + else + { + ANALYZE_PRINTF ("pulse: %3d - %3d or %3d - %3d\n", irmp_param.pulse_1_len_min, irmp_param.pulse_1_len_max, + 2 * irmp_param.pulse_1_len_min, 2 * irmp_param.pulse_1_len_max); + ANALYZE_PRINTF ("pause: %3d - %3d or %3d - %3d\n", irmp_param.pause_1_len_min, irmp_param.pause_1_len_max, + 2 * irmp_param.pause_1_len_min, 2 * irmp_param.pause_1_len_max); + } + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) + if (irmp_param2.protocol) + { + ANALYZE_PRINTF ("pulse_0: %3d - %3d\n", irmp_param2.pulse_0_len_min, irmp_param2.pulse_0_len_max); + ANALYZE_PRINTF ("pause_0: %3d - %3d\n", irmp_param2.pause_0_len_min, irmp_param2.pause_0_len_max); + ANALYZE_PRINTF ("pulse_1: %3d - %3d\n", irmp_param2.pulse_1_len_min, irmp_param2.pulse_1_len_max); + ANALYZE_PRINTF ("pause_1: %3d - %3d\n", irmp_param2.pause_1_len_min, irmp_param2.pause_1_len_max); + } +#endif + + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC6_PROTOCOL) + { + ANALYZE_PRINTF ("pulse_toggle: %3d - %3d\n", RC6_TOGGLE_BIT_LEN_MIN, RC6_TOGGLE_BIT_LEN_MAX); + } +#endif + + if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) + { + ANALYZE_PRINTF ("pulse_0: %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); + ANALYZE_PRINTF ("pause_0: %3d - %3d\n", irmp_param.pause_0_len_min, irmp_param.pause_0_len_max); + } + else + { + ANALYZE_PRINTF ("pulse: %3d - %3d or %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max, + 2 * irmp_param.pulse_0_len_min, 2 * irmp_param.pulse_0_len_max); + ANALYZE_PRINTF ("pause: %3d - %3d or %3d - %3d\n", irmp_param.pause_0_len_min, irmp_param.pause_0_len_max, + 2 * irmp_param.pause_0_len_min, 2 * irmp_param.pause_0_len_max); + } + +#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_BANG_OLUFSEN_PROTOCOL) + { + ANALYZE_PRINTF ("pulse_r: %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); + ANALYZE_PRINTF ("pause_r: %3d - %3d\n", BANG_OLUFSEN_R_PAUSE_LEN_MIN, BANG_OLUFSEN_R_PAUSE_LEN_MAX); + } +#endif + + ANALYZE_PRINTF ("command_offset: %2d\n", irmp_param.command_offset); + ANALYZE_PRINTF ("command_len: %3d\n", irmp_param.command_end - irmp_param.command_offset); + ANALYZE_PRINTF ("complete_len: %3d\n", irmp_param.complete_len); + ANALYZE_PRINTF ("stop_bit: %3d\n", irmp_param.stop_bit); +#endif // ANALYZE + } + + irmp_bit = 0; + +#if IRMP_SUPPORT_MANCHESTER == 1 + if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && + irmp_param.protocol != IRMP_RUWIDO_PROTOCOL && // Manchester, but not RUWIDO + irmp_param.protocol != IRMP_RC6_PROTOCOL) // Manchester, but not RC6 + { + if (irmp_pause_time > irmp_param.pulse_1_len_max && irmp_pause_time <= 2 * irmp_param.pulse_1_len_max) + { + ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '0' : '1'); + ANALYZE_NEWLINE (); + irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 0 : 1); + } + else if (! last_value) // && irmp_pause_time >= irmp_param.pause_1_len_min && irmp_pause_time <= irmp_param.pause_1_len_max) + { + ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); + + ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '1' : '0'); + ANALYZE_NEWLINE (); + irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0); + } + } + else +#endif // IRMP_SUPPORT_MANCHESTER == 1 + +#if IRMP_SUPPORT_SERIAL == 1 + if (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) + { + ; // do nothing + } + else +#endif // IRMP_SUPPORT_SERIAL == 1 + + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_DENON_PROTOCOL) + { + ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); + + if (irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX) + { // pause timings correct for "1"? + ANALYZE_PUTCHAR ('1'); // yes, store 1 + ANALYZE_NEWLINE (); + irmp_store_bit (1); + } + else // if (irmp_pause_time >= DENON_0_PAUSE_LEN_MIN && irmp_pause_time <= DENON_0_PAUSE_LEN_MAX) + { // pause timings correct for "0"? + ANALYZE_PUTCHAR ('0'); // yes, store 0 + ANALYZE_NEWLINE (); + irmp_store_bit (0); + } + } + else +#endif // IRMP_SUPPORT_DENON_PROTOCOL == 1 +#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_THOMSON_PROTOCOL) + { + ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); + + if (irmp_pause_time >= THOMSON_1_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_1_PAUSE_LEN_MAX) + { // pause timings correct for "1"? + ANALYZE_PUTCHAR ('1'); // yes, store 1 + ANALYZE_NEWLINE (); + irmp_store_bit (1); + } + else // if (irmp_pause_time >= THOMSON_0_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_0_PAUSE_LEN_MAX) + { // pause timings correct for "0"? + ANALYZE_PUTCHAR ('0'); // yes, store 0 + ANALYZE_NEWLINE (); + irmp_store_bit (0); + } + } + else +#endif // IRMP_SUPPORT_THOMSON_PROTOCOL == 1 + { + ; // else do nothing + } + + irmp_pulse_time = 1; // set counter to 1, not 0 + irmp_pause_time = 0; + wait_for_start_space = 0; + } + } + else if (wait_for_space) // the data section.... + { // counting the time of darkness.... + uint8_t got_light = FALSE; + + if (irmp_input) // still dark? + { // yes... + if (irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 1) + { + if ( +#if IRMP_SUPPORT_MANCHESTER == 1 + (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) || +#endif +#if IRMP_SUPPORT_SERIAL == 1 + (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) || +#endif + (irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max)) + { +#ifdef ANALYZE + if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) + { + ANALYZE_PRINTF ("stop bit detected\n"); + } +#endif + irmp_param.stop_bit = 0; + } + else + { + ANALYZE_PRINTF ("error: stop bit timing wrong, irmp_bit = %d, irmp_pulse_time = %d, pulse_0_len_min = %d, pulse_0_len_max = %d\n", + irmp_bit, irmp_pulse_time, irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); + +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // wait for another start bit... + irmp_pulse_time = 0; + irmp_pause_time = 0; + } + } + else + { + irmp_pause_time++; // increment counter + +#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && // Sony has a variable number of bits: + irmp_pause_time > SIRCS_PAUSE_LEN_MAX && // minimum is 12 + irmp_bit >= 12 - 1) // pause too long? + { // yes, break and close this frame + irmp_param.complete_len = irmp_bit + 1; // set new complete length + got_light = TRUE; // this is a lie, but helps (generates stop bit) + irmp_tmp_address |= (irmp_bit - SIRCS_MINIMUM_DATA_LEN + 1) << 8; // new: store number of additional bits in upper byte of address! + irmp_param.command_end = irmp_param.command_offset + irmp_bit + 1; // correct command length + irmp_pause_time = SIRCS_PAUSE_LEN_MAX - 1; // correct pause length + } + else +#endif +#if IRMP_SUPPORT_SERIAL == 1 + // NETBOX generates no stop bit, here is the timeout condition: + if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) && irmp_param.protocol == IRMP_NETBOX_PROTOCOL && + irmp_pause_time >= NETBOX_PULSE_LEN * (NETBOX_COMPLETE_DATA_LEN - irmp_bit)) + { + got_light = TRUE; // this is a lie, but helps (generates stop bit) + } + else +#endif +#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && !irmp_param.stop_bit) + { + if (irmp_pause_time > IR60_TIMEOUT_LEN && irmp_bit == 6) + { + ANALYZE_PRINTF ("Switching to IR60 protocol\n"); + got_light = TRUE; // this is a lie, but generates a stop bit ;-) + irmp_param.stop_bit = TRUE; // set flag + + irmp_param.protocol = IRMP_IR60_PROTOCOL; // change protocol + irmp_param.complete_len = IR60_COMPLETE_DATA_LEN; // correct complete len + irmp_param.address_offset = IR60_ADDRESS_OFFSET; + irmp_param.address_end = IR60_ADDRESS_OFFSET + IR60_ADDRESS_LEN; + irmp_param.command_offset = IR60_COMMAND_OFFSET; + irmp_param.command_end = IR60_COMMAND_OFFSET + IR60_COMMAND_LEN; + + irmp_tmp_command <<= 1; + irmp_tmp_command |= first_bit; + } + else if (irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN - 2) + { // special manchester decoder + irmp_param.complete_len = GRUNDIG_COMPLETE_DATA_LEN; // correct complete len + got_light = TRUE; // this is a lie, but generates a stop bit ;-) + irmp_param.stop_bit = TRUE; // set flag + } + else if (irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN) + { + ANALYZE_PRINTF ("Switching to NOKIA protocol\n"); + irmp_param.protocol = IRMP_NOKIA_PROTOCOL; // change protocol + irmp_param.address_offset = NOKIA_ADDRESS_OFFSET; + irmp_param.address_end = NOKIA_ADDRESS_OFFSET + NOKIA_ADDRESS_LEN; + irmp_param.command_offset = NOKIA_COMMAND_OFFSET; + irmp_param.command_end = NOKIA_COMMAND_OFFSET + NOKIA_COMMAND_LEN; + + if (irmp_tmp_command & 0x300) + { + irmp_tmp_address = (irmp_tmp_command >> 8); + irmp_tmp_command &= 0xFF; + } + } + } + else +#endif +#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RUWIDO_PROTOCOL && !irmp_param.stop_bit) + { + if (irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= RUWIDO_COMPLETE_DATA_LEN - 2) + { // special manchester decoder + irmp_param.complete_len = RUWIDO_COMPLETE_DATA_LEN; // correct complete len + got_light = TRUE; // this is a lie, but generates a stop bit ;-) + irmp_param.stop_bit = TRUE; // set flag + } + else if (irmp_bit >= RUWIDO_COMPLETE_DATA_LEN) + { + ANALYZE_PRINTF ("Switching to SIEMENS protocol\n"); + irmp_param.protocol = IRMP_SIEMENS_PROTOCOL; // change protocol + irmp_param.address_offset = SIEMENS_ADDRESS_OFFSET; + irmp_param.address_end = SIEMENS_ADDRESS_OFFSET + SIEMENS_ADDRESS_LEN; + irmp_param.command_offset = SIEMENS_COMMAND_OFFSET; + irmp_param.command_end = SIEMENS_COMMAND_OFFSET + SIEMENS_COMMAND_LEN; + + // 76543210 + // RUWIDO: AAAAAAAAACCCCCCCp + // SIEMENS: AAAAAAAAAAACCCCCCCCCCp + irmp_tmp_address <<= 2; + irmp_tmp_address |= (irmp_tmp_command >> 6); + irmp_tmp_command &= 0x003F; + irmp_tmp_command <<= 4; + irmp_tmp_command |= last_value; + } + } + else +#endif +#if IRMP_SUPPORT_MANCHESTER == 1 + if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && + irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= irmp_param.complete_len - 2 && !irmp_param.stop_bit) + { // special manchester decoder + got_light = TRUE; // this is a lie, but generates a stop bit ;-) + irmp_param.stop_bit = TRUE; // set flag + } + else +#endif // IRMP_SUPPORT_MANCHESTER == 1 + if (irmp_pause_time > IRMP_TIMEOUT_LEN) // timeout? + { // yes... + if (irmp_bit == irmp_param.complete_len - 1 && irmp_param.stop_bit == 0) + { + irmp_bit++; + } +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_NEC_PROTOCOL && (irmp_bit == 16 || irmp_bit == 17)) // it was a JVC stop bit + { + ANALYZE_PRINTF ("Switching to JVC protocol, irmp_bit = %d\n", irmp_bit); + irmp_param.stop_bit = TRUE; // set flag + irmp_param.protocol = IRMP_JVC_PROTOCOL; // switch protocol + irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 + irmp_tmp_command = (irmp_tmp_address >> 4); // set command: upper 12 bits are command bits + irmp_tmp_address = irmp_tmp_address & 0x000F; // lower 4 bits are address bits + irmp_start_bit_detected = 1; // tricky: don't wait for another start bit... + } +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit == 32) // it was a NEC stop bit + { + ANALYZE_PRINTF ("Switching to NEC protocol\n"); + irmp_param.stop_bit = TRUE; // set flag + irmp_param.protocol = IRMP_NEC_PROTOCOL; // switch protocol + irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 + + // 0123456789ABC0123456789ABC0123456701234567 + // NEC42: AAAAAAAAAAAAAaaaaaaaaaaaaaCCCCCCCCcccccccc + // NEC: AAAAAAAAaaaaaaaaCCCCCCCCcccccccc + irmp_tmp_address |= (irmp_tmp_address2 & 0x0007) << 13; // fm 2012-02-13: 12 -> 13 + irmp_tmp_command = (irmp_tmp_address2 >> 3) | (irmp_tmp_command << 10); + } +#endif // IRMP_SUPPORT_NEC_PROTOCOL == 1 +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && (irmp_bit == 16 || irmp_bit == 17)) // it was a JVC stop bit + { + ANALYZE_PRINTF ("Switching to JVC protocol, irmp_bit = %d\n", irmp_bit); + irmp_param.stop_bit = TRUE; // set flag + irmp_param.protocol = IRMP_JVC_PROTOCOL; // switch protocol + irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 + + // 0123456789ABC0123456789ABC0123456701234567 + // NEC42: AAAAAAAAAAAAAaaaaaaaaaaaaaCCCCCCCCcccccccc + // JVC: AAAACCCCCCCCCCCC + irmp_tmp_command = (irmp_tmp_address >> 4) | (irmp_tmp_address2 << 9); // set command: upper 12 bits are command bits + irmp_tmp_address = irmp_tmp_address & 0x000F; // lower 4 bits are address bits + } +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 +#endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1 + else + { + ANALYZE_PRINTF ("error 2: pause %d after data bit %d too long\n", irmp_pause_time, irmp_bit); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); + +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // wait for another start bit... + irmp_pulse_time = 0; + irmp_pause_time = 0; + } + } + } + } + else + { // got light now! + got_light = TRUE; + } + + if (got_light) + { + ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); + +#if IRMP_SUPPORT_MANCHESTER == 1 + if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) // Manchester + { +#if 1 + if (irmp_pulse_time > irmp_param.pulse_1_len_max /* && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max */) +#else // better, but some IR-RCs use asymmetric timings :-/ + if (irmp_pulse_time > irmp_param.pulse_1_len_max && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max && + irmp_pause_time <= 2 * irmp_param.pause_1_len_max) +#endif + { +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 4 && irmp_pulse_time > RC6_TOGGLE_BIT_LEN_MIN) // RC6 toggle bit + { + ANALYZE_PUTCHAR ('T'); + if (irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG) // RC6 mode 6A + { + irmp_store_bit (1); + last_value = 1; + } + else // RC6 mode 0 + { + irmp_store_bit (0); + last_value = 0; + } + ANALYZE_NEWLINE (); + } + else +#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 + { + ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '0' : '1'); + irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 0 : 1 ); + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 4 && irmp_pulse_time > RC6_TOGGLE_BIT_LEN_MIN) // RC6 toggle bit + { + ANALYZE_PUTCHAR ('T'); + irmp_store_bit (1); + + if (irmp_pause_time > 2 * irmp_param.pause_1_len_max) + { + last_value = 0; + } + else + { + last_value = 1; + } + ANALYZE_NEWLINE (); + } + else +#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 + { + ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '1' : '0'); + irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0 ); +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) + if (! irmp_param2.protocol) +#endif + { + ANALYZE_NEWLINE (); + } + last_value = (irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0; + } + } + } + else if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max + /* && irmp_pause_time <= 2 * irmp_param.pause_1_len_max */) + { + uint8_t manchester_value; + + if (last_pause > irmp_param.pause_1_len_max && last_pause <= 2 * irmp_param.pause_1_len_max) + { + manchester_value = last_value ? 0 : 1; + last_value = manchester_value; + } + else + { + manchester_value = last_value; + } + + ANALYZE_PUTCHAR (manchester_value + '0'); + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) + if (! irmp_param2.protocol) +#endif + { + ANALYZE_NEWLINE (); + } + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 1 && manchester_value == 1) // RC6 mode != 0 ??? + { + ANALYZE_PRINTF ("Switching to RC6A protocol\n"); + irmp_param.complete_len = RC6_COMPLETE_DATA_LEN_LONG; + irmp_param.address_offset = 5; + irmp_param.address_end = irmp_param.address_offset + 15; + irmp_param.command_offset = irmp_param.address_end + 1; // skip 1 system bit, changes like a toggle bit + irmp_param.command_end = irmp_param.command_offset + 16 - 1; + irmp_tmp_address = 0; + } +#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 + + irmp_store_bit (manchester_value); + } + else + { +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_FDC_PROTOCOL == 1 + if (irmp_param2.protocol == IRMP_FDC_PROTOCOL && + irmp_pulse_time >= FDC_PULSE_LEN_MIN && irmp_pulse_time <= FDC_PULSE_LEN_MAX && + ((irmp_pause_time >= FDC_1_PAUSE_LEN_MIN && irmp_pause_time <= FDC_1_PAUSE_LEN_MAX) || + (irmp_pause_time >= FDC_0_PAUSE_LEN_MIN && irmp_pause_time <= FDC_0_PAUSE_LEN_MAX))) + { + ANALYZE_PUTCHAR ('?'); + irmp_param.protocol = 0; // switch to FDC, see below + } + else +#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + if (irmp_param2.protocol == IRMP_RCCAR_PROTOCOL && + irmp_pulse_time >= RCCAR_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_PULSE_LEN_MAX && + ((irmp_pause_time >= RCCAR_1_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_1_PAUSE_LEN_MAX) || + (irmp_pause_time >= RCCAR_0_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_0_PAUSE_LEN_MAX))) + { + ANALYZE_PUTCHAR ('?'); + irmp_param.protocol = 0; // switch to RCCAR, see below + } + else +#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + { + ANALYZE_PUTCHAR ('?'); + ANALYZE_NEWLINE (); + ANALYZE_PRINTF ("error 3 manchester: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_FDC_PROTOCOL == 1 + if (irmp_param2.protocol == IRMP_FDC_PROTOCOL && irmp_pulse_time >= FDC_PULSE_LEN_MIN && irmp_pulse_time <= FDC_PULSE_LEN_MAX) + { + if (irmp_pause_time >= FDC_1_PAUSE_LEN_MIN && irmp_pause_time <= FDC_1_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF (" 1 (FDC)\n"); + irmp_store_bit2 (1); + } + else if (irmp_pause_time >= FDC_0_PAUSE_LEN_MIN && irmp_pause_time <= FDC_0_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF (" 0 (FDC)\n"); + irmp_store_bit2 (0); + } + + if (! irmp_param.protocol) + { + ANALYZE_PRINTF ("Switching to FDC protocol\n"); + memcpy (&irmp_param, &irmp_param2, sizeof (IRMP_PARAMETER)); + irmp_param2.protocol = 0; + irmp_tmp_address = irmp_tmp_address2; + irmp_tmp_command = irmp_tmp_command2; + } + } +#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + if (irmp_param2.protocol == IRMP_RCCAR_PROTOCOL && irmp_pulse_time >= RCCAR_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_PULSE_LEN_MAX) + { + if (irmp_pause_time >= RCCAR_1_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_1_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF (" 1 (RCCAR)\n"); + irmp_store_bit2 (1); + } + else if (irmp_pause_time >= RCCAR_0_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_0_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF (" 0 (RCCAR)\n"); + irmp_store_bit2 (0); + } + + if (! irmp_param.protocol) + { + ANALYZE_PRINTF ("Switching to RCCAR protocol\n"); + memcpy (&irmp_param, &irmp_param2, sizeof (IRMP_PARAMETER)); + irmp_param2.protocol = 0; + irmp_tmp_address = irmp_tmp_address2; + irmp_tmp_command = irmp_tmp_command2; + } + } +#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + + last_pause = irmp_pause_time; + wait_for_space = 0; + } + else +#endif // IRMP_SUPPORT_MANCHESTER == 1 + +#if IRMP_SUPPORT_SERIAL == 1 + if (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) + { + while (irmp_bit < irmp_param.complete_len && irmp_pulse_time > irmp_param.pulse_1_len_max) + { + ANALYZE_PUTCHAR ('1'); + irmp_store_bit (1); + + if (irmp_pulse_time >= irmp_param.pulse_1_len_min) + { + irmp_pulse_time -= irmp_param.pulse_1_len_min; + } + else + { + irmp_pulse_time = 0; + } + } + + while (irmp_bit < irmp_param.complete_len && irmp_pause_time > irmp_param.pause_1_len_max) + { + ANALYZE_PUTCHAR ('0'); + irmp_store_bit (0); + + if (irmp_pause_time >= irmp_param.pause_1_len_min) + { + irmp_pause_time -= irmp_param.pause_1_len_min; + } + else + { + irmp_pause_time = 0; + } + } + ANALYZE_NEWLINE (); + wait_for_space = 0; + } + else +#endif // IRMP_SUPPORT_SERIAL == 1 + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_SAMSUNG_PROTOCOL && irmp_bit == 16) // Samsung: 16th bit + { + if (irmp_pulse_time >= SAMSUNG_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_PULSE_LEN_MAX && + irmp_pause_time >= SAMSUNG_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_START_BIT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("SYNC\n"); + wait_for_space = 0; + irmp_tmp_id = 0; + irmp_bit++; + } + else if (irmp_pulse_time >= SAMSUNG_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_PULSE_LEN_MAX) + { + irmp_param.protocol = IRMP_SAMSUNG32_PROTOCOL; + irmp_param.command_offset = SAMSUNG32_COMMAND_OFFSET; + irmp_param.command_end = SAMSUNG32_COMMAND_OFFSET + SAMSUNG32_COMMAND_LEN; + irmp_param.complete_len = SAMSUNG32_COMPLETE_DATA_LEN; + + if (irmp_pause_time >= SAMSUNG_1_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_1_PAUSE_LEN_MAX) + { + ANALYZE_PUTCHAR ('1'); + ANALYZE_NEWLINE (); + irmp_store_bit (1); + wait_for_space = 0; + } + else + { + ANALYZE_PUTCHAR ('0'); + ANALYZE_NEWLINE (); + irmp_store_bit (0); + wait_for_space = 0; + } + + ANALYZE_PRINTF ("Switching to SAMSUNG32 protocol\n"); + } + else + { // timing incorrect! + ANALYZE_PRINTF ("error 3 Samsung: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + else +#endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL + +#if IRMP_SUPPORT_NEC16_PROTOCOL +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && +#else // IRMP_SUPPORT_NEC_PROTOCOL instead + if (irmp_param.protocol == IRMP_NEC_PROTOCOL && +#endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1 + irmp_bit == 8 && irmp_pause_time >= NEC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_START_BIT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("Switching to NEC16 protocol\n"); + irmp_param.protocol = IRMP_NEC16_PROTOCOL; + irmp_param.address_offset = NEC16_ADDRESS_OFFSET; + irmp_param.address_end = NEC16_ADDRESS_OFFSET + NEC16_ADDRESS_LEN; + irmp_param.command_offset = NEC16_COMMAND_OFFSET; + irmp_param.command_end = NEC16_COMMAND_OFFSET + NEC16_COMMAND_LEN; + irmp_param.complete_len = NEC16_COMPLETE_DATA_LEN; + wait_for_space = 0; + } + else +#endif // IRMP_SUPPORT_NEC16_PROTOCOL + +#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_BANG_OLUFSEN_PROTOCOL) + { + if (irmp_pulse_time >= BANG_OLUFSEN_PULSE_LEN_MIN && irmp_pulse_time <= BANG_OLUFSEN_PULSE_LEN_MAX) + { + if (irmp_bit == 1) // Bang & Olufsen: 3rd bit + { + if (irmp_pause_time >= BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("3rd start bit\n"); + wait_for_space = 0; + irmp_bit++; + } + else + { // timing incorrect! + ANALYZE_PRINTF ("error 3a B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + else if (irmp_bit == 19) // Bang & Olufsen: trailer bit + { + if (irmp_pause_time >= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("trailer bit\n"); + wait_for_space = 0; + irmp_bit++; + } + else + { // timing incorrect! + ANALYZE_PRINTF ("error 3b B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + else + { + if (irmp_pause_time >= BANG_OLUFSEN_1_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_1_PAUSE_LEN_MAX) + { // pulse & pause timings correct for "1"? + ANALYZE_PUTCHAR ('1'); + ANALYZE_NEWLINE (); + irmp_store_bit (1); + last_value = 1; + wait_for_space = 0; + } + else if (irmp_pause_time >= BANG_OLUFSEN_0_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_0_PAUSE_LEN_MAX) + { // pulse & pause timings correct for "0"? + ANALYZE_PUTCHAR ('0'); + ANALYZE_NEWLINE (); + irmp_store_bit (0); + last_value = 0; + wait_for_space = 0; + } + else if (irmp_pause_time >= BANG_OLUFSEN_R_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_R_PAUSE_LEN_MAX) + { + ANALYZE_PUTCHAR (last_value + '0'); + ANALYZE_NEWLINE (); + irmp_store_bit (last_value); + wait_for_space = 0; + } + else + { // timing incorrect! + ANALYZE_PRINTF ("error 3c B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + } + else + { // timing incorrect! + ANALYZE_PRINTF ("error 3d B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + else +#endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL + + if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max && + irmp_pause_time >= irmp_param.pause_1_len_min && irmp_pause_time <= irmp_param.pause_1_len_max) + { // pulse & pause timings correct for "1"? + ANALYZE_PUTCHAR ('1'); + ANALYZE_NEWLINE (); + irmp_store_bit (1); + wait_for_space = 0; + } + else if (irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max && + irmp_pause_time >= irmp_param.pause_0_len_min && irmp_pause_time <= irmp_param.pause_0_len_max) + { // pulse & pause timings correct for "0"? + ANALYZE_PUTCHAR ('0'); + ANALYZE_NEWLINE (); + irmp_store_bit (0); + wait_for_space = 0; + } + else +#if IRMP_SUPPORT_KATHREIN_PROTOCOL + + if (irmp_param.protocol == IRMP_KATHREIN_PROTOCOL && + irmp_pulse_time >= KATHREIN_1_PULSE_LEN_MIN && irmp_pulse_time <= KATHREIN_1_PULSE_LEN_MAX && + (((irmp_bit == 8 || irmp_bit == 6) && + irmp_pause_time >= KATHREIN_SYNC_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_SYNC_BIT_PAUSE_LEN_MAX) || + (irmp_bit == 12 && + irmp_pause_time >= KATHREIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_START_BIT_PAUSE_LEN_MAX))) + + { + if (irmp_bit == 8) + { + irmp_bit++; + ANALYZE_PUTCHAR ('S'); + ANALYZE_NEWLINE (); + irmp_tmp_command <<= 1; + } + else + { + ANALYZE_PUTCHAR ('S'); + ANALYZE_NEWLINE (); + irmp_store_bit (1); + } + wait_for_space = 0; + } + else +#endif // IRMP_SUPPORT_KATHREIN_PROTOCOL + { // timing incorrect! + ANALYZE_PRINTF ("error 3: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + + irmp_pulse_time = 1; // set counter to 1, not 0 + } + } + else + { // counting the pulse length ... + if (! irmp_input) // still light? + { // yes... + irmp_pulse_time++; // increment counter + } + else + { // now it's dark! + wait_for_space = 1; // let's count the time (see above) + irmp_pause_time = 1; // set pause counter to 1, not 0 + } + } + + if (irmp_start_bit_detected && irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 0) // enough bits received? + { + if (last_irmp_command == irmp_tmp_command && repetition_len < AUTO_FRAME_REPETITION_LEN) + { + repetition_frame_number++; + } + else + { + repetition_frame_number = 0; + } + +#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 + // if SIRCS protocol and the code will be repeated within 50 ms, we will ignore 2nd and 3rd repetition frame + if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && (repetition_frame_number == 1 || repetition_frame_number == 2)) + { + ANALYZE_PRINTF ("code skipped: SIRCS auto repetition frame #%d, counter = %d, auto repetition len = %d\n", + repetition_frame_number + 1, repetition_len, AUTO_FRAME_REPETITION_LEN); + repetition_len = 0; + } + else +#endif + +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + // if KASEIKYO protocol and the code will be repeated within 50 ms, we will ignore 2nd repetition frame + if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL && repetition_frame_number == 1) + { + ANALYZE_PRINTF ("code skipped: KASEIKYO auto repetition frame #%d, counter = %d, auto repetition len = %d\n", + repetition_frame_number + 1, repetition_len, AUTO_FRAME_REPETITION_LEN); + repetition_len = 0; + } + else +#endif + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + // if SAMSUNG32 protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame + if (irmp_param.protocol == IRMP_SAMSUNG32_PROTOCOL && (repetition_frame_number & 0x01)) + { + ANALYZE_PRINTF ("code skipped: SAMSUNG32 auto repetition frame #%d, counter = %d, auto repetition len = %d\n", + repetition_frame_number + 1, repetition_len, AUTO_FRAME_REPETITION_LEN); + repetition_len = 0; + } + else +#endif + +#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 + // if NUBERT protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame + if (irmp_param.protocol == IRMP_NUBERT_PROTOCOL && (repetition_frame_number & 0x01)) + { + ANALYZE_PRINTF ("code skipped: NUBERT auto repetition frame #%d, counter = %d, auto repetition len = %d\n", + repetition_frame_number + 1, repetition_len, AUTO_FRAME_REPETITION_LEN); + repetition_len = 0; + } + else +#endif + + { + ANALYZE_PRINTF ("%8.3fms code detected, length = %d\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit); + irmp_ir_detected = TRUE; + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_DENON_PROTOCOL) + { // check for repetition frame + if ((~irmp_tmp_command & 0x3FF) == last_irmp_denon_command) // command bits must be inverted + { + irmp_tmp_command = last_irmp_denon_command; // use command received before! + + irmp_protocol = irmp_param.protocol; // store protocol + irmp_address = irmp_tmp_address; // store address + irmp_command = irmp_tmp_command ; // store command + } + else + { + ANALYZE_PRINTF ("waiting for inverted command repetition\n"); + irmp_ir_detected = FALSE; + last_irmp_denon_command = irmp_tmp_command; + } + } + else +#endif // IRMP_SUPPORT_DENON_PROTOCOL + +#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && irmp_tmp_command == 0x01ff) + { // Grundig start frame? + ANALYZE_PRINTF ("Detected GRUNDIG start frame, ignoring it\n"); + irmp_ir_detected = FALSE; + } + else +#endif // IRMP_SUPPORT_GRUNDIG_PROTOCOL + +#if IRMP_SUPPORT_NOKIA_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_NOKIA_PROTOCOL && irmp_tmp_address == 0x00ff && irmp_tmp_command == 0x00fe) + { // Nokia start frame? + ANALYZE_PRINTF ("Detected NOKIA start frame, ignoring it\n"); + irmp_ir_detected = FALSE; + } + else +#endif // IRMP_SUPPORT_NOKIA_PROTOCOL + { +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_NEC_PROTOCOL && irmp_bit == 0) // repetition frame + { + if (repetition_len < NEC_FRAME_REPEAT_PAUSE_LEN_MAX) + { + ANALYZE_PRINTF ("Detected NEC repetition frame, repetition_len = %d\n", repetition_len); + irmp_tmp_address = last_irmp_address; // address is last address + irmp_tmp_command = last_irmp_command; // command is last command + irmp_flags |= IRMP_FLAG_REPETITION; + repetition_len = 0; + } + else + { + ANALYZE_PRINTF ("Detected NEC repetition frame, ignoring it: timeout occured, repetition_len = %d > %d\n", + repetition_len, NEC_FRAME_REPEAT_PAUSE_LEN_MAX); + irmp_ir_detected = FALSE; + } + } +#endif // IRMP_SUPPORT_NEC_PROTOCOL + +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL) + { + uint8_t xor; + // ANALYZE_PRINTF ("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + // xor_check[0], xor_check[1], xor_check[2], xor_check[3], xor_check[4], xor_check[5]); + + xor = (xor_check[0] & 0x0F) ^ ((xor_check[0] & 0xF0) >> 4) ^ (xor_check[1] & 0x0F) ^ ((xor_check[1] & 0xF0) >> 4); + + if (xor != (xor_check[2] & 0x0F)) + { + ANALYZE_PRINTF ("error 4: wrong XOR check for customer id: 0x%1x 0x%1x\n", xor, xor_check[2] & 0x0F); + irmp_ir_detected = FALSE; + } + + xor = xor_check[2] ^ xor_check[3] ^ xor_check[4]; + + if (xor != xor_check[5]) + { + ANALYZE_PRINTF ("error 4: wrong XOR check for data bits: 0x%02x 0x%02x\n", xor, xor_check[5]); + irmp_ir_detected = FALSE; + } + + irmp_flags |= genre2; // write the genre2 bits into MSB of the flag byte + } +#endif // IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG) // RC6 mode = 6? + { + irmp_protocol = IRMP_RC6A_PROTOCOL; + } + else +#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 + + irmp_protocol = irmp_param.protocol; + +#if IRMP_SUPPORT_FDC_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_FDC_PROTOCOL) + { + if (irmp_tmp_command & 0x000F) // released key? + { + irmp_tmp_command = (irmp_tmp_command >> 4) | 0x80; // yes, set bit 7 + } + else + { + irmp_tmp_command >>= 4; // no, it's a pressed key + } + irmp_tmp_command |= (irmp_tmp_address << 2) & 0x0F00; // 000000CCCCAAAAAA -> 0000CCCC00000000 + irmp_tmp_address &= 0x003F; + } +#endif + + irmp_address = irmp_tmp_address; // store address +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_NEC_PROTOCOL) + { + last_irmp_address = irmp_tmp_address; // store as last address, too + } +#endif + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC5_PROTOCOL) + { + irmp_tmp_command |= rc5_cmd_bit6; // store bit 6 + } +#endif + irmp_command = irmp_tmp_command; // store command + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + irmp_id = irmp_tmp_id; +#endif + } + } + + if (irmp_ir_detected) + { + if (last_irmp_command == irmp_tmp_command && + last_irmp_address == irmp_tmp_address && + repetition_len < IRMP_KEY_REPETITION_LEN) + { + irmp_flags |= IRMP_FLAG_REPETITION; + } + + last_irmp_address = irmp_tmp_address; // store as last address, too + last_irmp_command = irmp_tmp_command; // store as last command, too + + repetition_len = 0; + } + else + { + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); + } + +// irmp_busy_flag = FALSE; + irmp_start_bit_detected = 0; // and wait for next start bit + irmp_tmp_command = 0; + irmp_pulse_time = 0; + irmp_pause_time = 0; + +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + if (irmp_protocol == IRMP_JVC_PROTOCOL) // the stop bit of JVC frame is also start bit of next frame + { // set pulse time here! + irmp_pulse_time = ((uint8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME)); + } +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + } + } + } + return (irmp_ir_detected); +} + +#ifdef ANALYZE + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * main functions - for Unix/Linux + Windows only! + * + * AVR: see main.c! + * + * Compile it under linux with: + * cc irmp.c -o irmp + * + * usage: ./irmp [-v|-s|-a|-l|-p] < file + * + * options: + * -v verbose + * -s silent + * -a analyze + * -l list pulse/pauses + * -p print timings + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +#ifndef IRMP_EMBED +static void +print_timings (void) +{ + printf ("IRMP_TIMEOUT_LEN: %d [%d byte(s)]\n", IRMP_TIMEOUT_LEN, sizeof (PAUSE_LEN)); + printf ("IRMP_KEY_REPETITION_LEN %d\n", IRMP_KEY_REPETITION_LEN); + puts (""); + printf ("PROTOCOL S S-PULSE S-PAUSE PULSE-0 PAUSE-0 PULSE-1 PAUSE-1\n"); + printf ("====================================================================================\n"); + printf ("SIRCS 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + SIRCS_START_BIT_PULSE_LEN_MIN, SIRCS_START_BIT_PULSE_LEN_MAX, SIRCS_START_BIT_PAUSE_LEN_MIN, SIRCS_START_BIT_PAUSE_LEN_MAX, + SIRCS_0_PULSE_LEN_MIN, SIRCS_0_PULSE_LEN_MAX, SIRCS_PAUSE_LEN_MIN, SIRCS_PAUSE_LEN_MAX, + SIRCS_1_PULSE_LEN_MIN, SIRCS_1_PULSE_LEN_MAX, SIRCS_PAUSE_LEN_MIN, SIRCS_PAUSE_LEN_MAX); + + printf ("NEC 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX, + NEC_PULSE_LEN_MIN, NEC_PULSE_LEN_MAX, NEC_0_PAUSE_LEN_MIN, NEC_0_PAUSE_LEN_MAX, + NEC_PULSE_LEN_MIN, NEC_PULSE_LEN_MAX, NEC_1_PAUSE_LEN_MIN, NEC_1_PAUSE_LEN_MAX); + + printf ("NEC (rep) 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX, + NEC_PULSE_LEN_MIN, NEC_PULSE_LEN_MAX, NEC_0_PAUSE_LEN_MIN, NEC_0_PAUSE_LEN_MAX, + NEC_PULSE_LEN_MIN, NEC_PULSE_LEN_MAX, NEC_1_PAUSE_LEN_MIN, NEC_1_PAUSE_LEN_MAX); + + printf ("SAMSUNG 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + SAMSUNG_START_BIT_PULSE_LEN_MIN, SAMSUNG_START_BIT_PULSE_LEN_MAX, SAMSUNG_START_BIT_PAUSE_LEN_MIN, SAMSUNG_START_BIT_PAUSE_LEN_MAX, + SAMSUNG_PULSE_LEN_MIN, SAMSUNG_PULSE_LEN_MAX, SAMSUNG_0_PAUSE_LEN_MIN, SAMSUNG_0_PAUSE_LEN_MAX, + SAMSUNG_PULSE_LEN_MIN, SAMSUNG_PULSE_LEN_MAX, SAMSUNG_1_PAUSE_LEN_MIN, SAMSUNG_1_PAUSE_LEN_MAX); + + printf ("MATSUSHITA 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + MATSUSHITA_START_BIT_PULSE_LEN_MIN, MATSUSHITA_START_BIT_PULSE_LEN_MAX, MATSUSHITA_START_BIT_PAUSE_LEN_MIN, MATSUSHITA_START_BIT_PAUSE_LEN_MAX, + MATSUSHITA_PULSE_LEN_MIN, MATSUSHITA_PULSE_LEN_MAX, MATSUSHITA_0_PAUSE_LEN_MIN, MATSUSHITA_0_PAUSE_LEN_MAX, + MATSUSHITA_PULSE_LEN_MIN, MATSUSHITA_PULSE_LEN_MAX, MATSUSHITA_1_PAUSE_LEN_MIN, MATSUSHITA_1_PAUSE_LEN_MAX); + + printf ("KASEIKYO 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + KASEIKYO_START_BIT_PULSE_LEN_MIN, KASEIKYO_START_BIT_PULSE_LEN_MAX, KASEIKYO_START_BIT_PAUSE_LEN_MIN, KASEIKYO_START_BIT_PAUSE_LEN_MAX, + KASEIKYO_PULSE_LEN_MIN, KASEIKYO_PULSE_LEN_MAX, KASEIKYO_0_PAUSE_LEN_MIN, KASEIKYO_0_PAUSE_LEN_MAX, + KASEIKYO_PULSE_LEN_MIN, KASEIKYO_PULSE_LEN_MAX, KASEIKYO_1_PAUSE_LEN_MIN, KASEIKYO_1_PAUSE_LEN_MAX); + + printf ("RECS80 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + RECS80_START_BIT_PULSE_LEN_MIN, RECS80_START_BIT_PULSE_LEN_MAX, RECS80_START_BIT_PAUSE_LEN_MIN, RECS80_START_BIT_PAUSE_LEN_MAX, + RECS80_PULSE_LEN_MIN, RECS80_PULSE_LEN_MAX, RECS80_0_PAUSE_LEN_MIN, RECS80_0_PAUSE_LEN_MAX, + RECS80_PULSE_LEN_MIN, RECS80_PULSE_LEN_MAX, RECS80_1_PAUSE_LEN_MIN, RECS80_1_PAUSE_LEN_MAX); + + printf ("RC5 1 %3d - %3d %3d - %3d %3d - %3d\n", + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, + RC5_BIT_LEN_MIN, RC5_BIT_LEN_MAX); + + printf ("DENON 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX, + DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX, DENON_0_PAUSE_LEN_MIN, DENON_0_PAUSE_LEN_MAX, + DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX, DENON_1_PAUSE_LEN_MIN, DENON_1_PAUSE_LEN_MAX); + + printf ("THOMSON 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX, + THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX, THOMSON_0_PAUSE_LEN_MIN, THOMSON_0_PAUSE_LEN_MAX, + THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX, THOMSON_1_PAUSE_LEN_MIN, THOMSON_1_PAUSE_LEN_MAX); + + printf ("RC6 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + RC6_START_BIT_PULSE_LEN_MIN, RC6_START_BIT_PULSE_LEN_MAX, RC6_START_BIT_PAUSE_LEN_MIN, RC6_START_BIT_PAUSE_LEN_MAX, + RC6_BIT_PULSE_LEN_MIN, RC6_BIT_PULSE_LEN_MAX, RC6_BIT_PAUSE_LEN_MIN, RC6_BIT_PAUSE_LEN_MAX); + + printf ("RECS80EXT 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + RECS80EXT_START_BIT_PULSE_LEN_MIN, RECS80EXT_START_BIT_PULSE_LEN_MAX, RECS80EXT_START_BIT_PAUSE_LEN_MIN, RECS80EXT_START_BIT_PAUSE_LEN_MAX, + RECS80EXT_PULSE_LEN_MIN, RECS80EXT_PULSE_LEN_MAX, RECS80EXT_0_PAUSE_LEN_MIN, RECS80EXT_0_PAUSE_LEN_MAX, + RECS80EXT_PULSE_LEN_MIN, RECS80EXT_PULSE_LEN_MAX, RECS80EXT_1_PAUSE_LEN_MIN, RECS80EXT_1_PAUSE_LEN_MAX); + + printf ("NUBERT 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + NUBERT_START_BIT_PULSE_LEN_MIN, NUBERT_START_BIT_PULSE_LEN_MAX, NUBERT_START_BIT_PAUSE_LEN_MIN, NUBERT_START_BIT_PAUSE_LEN_MAX, + NUBERT_0_PULSE_LEN_MIN, NUBERT_0_PULSE_LEN_MAX, NUBERT_0_PAUSE_LEN_MIN, NUBERT_0_PAUSE_LEN_MAX, + NUBERT_1_PULSE_LEN_MIN, NUBERT_1_PULSE_LEN_MAX, NUBERT_1_PAUSE_LEN_MIN, NUBERT_1_PAUSE_LEN_MAX); + + printf ("BANG_OLUFSEN 1 %3d - %3d %3d - %3d\n", + BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX); + + printf ("BANG_OLUFSEN 2 %3d - %3d %3d - %3d\n", + BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX); + + printf ("BANG_OLUFSEN 3 %3d - %3d %3d - %3d\n", + BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX); + + printf ("BANG_OLUFSEN 4 %3d - %3d %3d - %3d\n", + BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX); + + printf ("BANG_OLUFSEN - %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + BANG_OLUFSEN_PULSE_LEN_MIN, BANG_OLUFSEN_PULSE_LEN_MAX, BANG_OLUFSEN_0_PAUSE_LEN_MIN, BANG_OLUFSEN_0_PAUSE_LEN_MAX, + BANG_OLUFSEN_PULSE_LEN_MIN, BANG_OLUFSEN_PULSE_LEN_MAX, BANG_OLUFSEN_1_PAUSE_LEN_MIN, BANG_OLUFSEN_1_PAUSE_LEN_MAX); + + printf ("GRUNDIG/NOKIA 1 %3d - %3d %3d - %3d %3d - %3d\n", + GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN, GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX, + GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN, GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX, + GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, GRUNDIG_NOKIA_IR60_BIT_LEN_MAX); + + printf ("SIEMENS/RUWIDO 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX, + SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX, + SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN, SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX, + SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN, SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX, + 2 * SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX, + 2 * SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX); + + printf ("GRUNDIG2 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + GRUNDIG2_START_BIT_PULSE_LEN_MIN, GRUNDIG2_START_BIT_PULSE_LEN_MAX, + GRUNDIG2_START_BIT_PAUSE_LEN_MIN, GRUNDIG2_START_BIT_PAUSE_LEN_MAX, + GRUNDIG2_BIT_PULSE_LEN_MIN, GRUNDIG2_BIT_PULSE_LEN_MAX, + GRUNDIG2_BIT_PAUSE_LEN_MIN, GRUNDIG2_BIT_PAUSE_LEN_MAX, + 2 * GRUNDIG2_BIT_PULSE_LEN_MIN, 2 * GRUNDIG2_BIT_PULSE_LEN_MAX, + 2 * GRUNDIG2_BIT_PAUSE_LEN_MIN, 2 * GRUNDIG2_BIT_PAUSE_LEN_MAX); + + printf ("FDC 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX, FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX, + FDC_PULSE_LEN_MIN, FDC_PULSE_LEN_MAX, FDC_0_PAUSE_LEN_MIN, FDC_0_PAUSE_LEN_MAX, + FDC_PULSE_LEN_MIN, FDC_PULSE_LEN_MAX, FDC_1_PAUSE_LEN_MIN, FDC_1_PAUSE_LEN_MAX); + + printf ("RCCAR 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX, RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX, + RCCAR_PULSE_LEN_MIN, RCCAR_PULSE_LEN_MAX, RCCAR_0_PAUSE_LEN_MIN, RCCAR_0_PAUSE_LEN_MAX, + RCCAR_PULSE_LEN_MIN, RCCAR_PULSE_LEN_MAX, RCCAR_1_PAUSE_LEN_MIN, RCCAR_1_PAUSE_LEN_MAX); + + printf ("NIKON 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + NIKON_START_BIT_PULSE_LEN_MIN, NIKON_START_BIT_PULSE_LEN_MAX, NIKON_START_BIT_PAUSE_LEN_MIN, NIKON_START_BIT_PAUSE_LEN_MAX, + NIKON_PULSE_LEN_MIN, NIKON_PULSE_LEN_MAX, NIKON_0_PAUSE_LEN_MIN, NIKON_0_PAUSE_LEN_MAX, + NIKON_PULSE_LEN_MIN, NIKON_PULSE_LEN_MAX, NIKON_1_PAUSE_LEN_MIN, NIKON_1_PAUSE_LEN_MAX); + + printf ("LEGO 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", + LEGO_START_BIT_PULSE_LEN_MIN, LEGO_START_BIT_PULSE_LEN_MAX, LEGO_START_BIT_PAUSE_LEN_MIN, LEGO_START_BIT_PAUSE_LEN_MAX, + LEGO_PULSE_LEN_MIN, LEGO_PULSE_LEN_MAX, LEGO_0_PAUSE_LEN_MIN, LEGO_0_PAUSE_LEN_MAX, + LEGO_PULSE_LEN_MIN, LEGO_PULSE_LEN_MAX, LEGO_1_PAUSE_LEN_MIN, LEGO_1_PAUSE_LEN_MAX); + +} + +void +print_spectrum (char * text, int * buf, int is_pulse) +{ + int i; + int j; + int min; + int max; + int max_value = 0; + int value; + int sum = 0; + int counter = 0; + double average = 0; + double tolerance; + + puts ("-------------------------------------------------------------------------------"); + printf ("%s:\n", text); + + for (i = 0; i < 256; i++) + { + if (buf[i] > max_value) + { + max_value = buf[i]; + } + } + + for (i = 1; i < 100; i++) + { + if (buf[i] > 0) + { + printf ("%3d ", i); + value = (buf[i] * 60) / max_value; + + for (j = 0; j < value; j++) + { + putchar ('o'); + } + printf (" %d\n", buf[i]); + + sum += i * buf[i]; + counter += buf[i]; + } + else + { + max = i - 1; + + if (counter > 0) + { + average = (float) sum / (float) counter; + + if (is_pulse) + { + printf ("pulse "); + } + else + { + printf ("pause "); + } + + printf ("avg: %4.1f=%6.1f us, ", average, (1000000. * average) / (float) F_INTERRUPTS); + printf ("min: %2d=%6.1f us, ", min, (1000000. * min) / (float) F_INTERRUPTS); + printf ("max: %2d=%6.1f us, ", max, (1000000. * max) / (float) F_INTERRUPTS); + + tolerance = (max - average); + + if (average - min > tolerance) + { + tolerance = average - min; + } + + tolerance = tolerance * 100 / average; + printf ("tol: %4.1f%%\n", tolerance); + } + + counter = 0; + sum = 0; + min = i + 1; + } + } +} +#endif + +#define STATE_LEFT_SHIFT 0x01 +#define STATE_RIGHT_SHIFT 0x02 +#define STATE_LEFT_CTRL 0x04 +#define STATE_LEFT_ALT 0x08 +#define STATE_RIGHT_ALT 0x10 + +#define KEY_ESCAPE 0x1B // keycode = 0x006e +#define KEY_MENUE 0x80 // keycode = 0x0070 +#define KEY_BACK 0x81 // keycode = 0x0071 +#define KEY_FORWARD 0x82 // keycode = 0x0072 +#define KEY_ADDRESS 0x83 // keycode = 0x0073 +#define KEY_WINDOW 0x84 // keycode = 0x0074 +#define KEY_1ST_PAGE 0x85 // keycode = 0x0075 +#define KEY_STOP 0x86 // keycode = 0x0076 +#define KEY_MAIL 0x87 // keycode = 0x0077 +#define KEY_FAVORITES 0x88 // keycode = 0x0078 +#define KEY_NEW_PAGE 0x89 // keycode = 0x0079 +#define KEY_SETUP 0x8A // keycode = 0x007a +#define KEY_FONT 0x8B // keycode = 0x007b +#define KEY_PRINT 0x8C // keycode = 0x007c +#define KEY_ON_OFF 0x8E // keycode = 0x007c + +#define KEY_INSERT 0x90 // keycode = 0x004b +#define KEY_DELETE 0x91 // keycode = 0x004c +#define KEY_LEFT 0x92 // keycode = 0x004f +#define KEY_HOME 0x93 // keycode = 0x0050 +#define KEY_END 0x94 // keycode = 0x0051 +#define KEY_UP 0x95 // keycode = 0x0053 +#define KEY_DOWN 0x96 // keycode = 0x0054 +#define KEY_PAGE_UP 0x97 // keycode = 0x0055 +#define KEY_PAGE_DOWN 0x98 // keycode = 0x0056 +#define KEY_RIGHT 0x99 // keycode = 0x0059 +#define KEY_MOUSE_1 0x9E // keycode = 0x0400 +#define KEY_MOUSE_2 0x9F // keycode = 0x0800 + +#ifndef LIRC_IRMP +static uint8_t +get_fdc_key (uint16_t cmd) +{ + static uint8_t key_table[128] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, '^', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'ß', '´', 0, '\b', + '\t','q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 'ü', '+', 0, 0, 'a', + 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä', '#', '\r', 0, '<', 'y', 'x', + 'c', 'v', 'b', 'n', 'm', ',', '.', '-', 0, 0, 0, 0, 0, ' ', 0, 0, + + 0, '°', '!', '"', '§', '$', '%', '&', '/', '(', ')', '=', '?', '`', 0, '\b', + '\t','Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 'Ü', '*', 0, 0, 'A', + 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Ö', 'Ä', '\'','\r', 0, '>', 'Y', 'X', + 'C', 'V', 'B', 'N', 'M', ';', ':', '_', 0, 0, 0, 0, 0, ' ', 0, 0 + }; + static uint8_t state; + + uint8_t key = 0; + + switch (cmd) + { + case 0x002C: state |= STATE_LEFT_SHIFT; break; // pressed left shift + case 0x00AC: state &= ~STATE_LEFT_SHIFT; break; // released left shift + case 0x0039: state |= STATE_RIGHT_SHIFT; break; // pressed right shift + case 0x00B9: state &= ~STATE_RIGHT_SHIFT; break; // released right shift + case 0x003A: state |= STATE_LEFT_CTRL; break; // pressed left ctrl + case 0x00BA: state &= ~STATE_LEFT_CTRL; break; // released left ctrl + case 0x003C: state |= STATE_LEFT_ALT; break; // pressed left alt + case 0x00BC: state &= ~STATE_LEFT_ALT; break; // released left alt + case 0x003E: state |= STATE_RIGHT_ALT; break; // pressed left alt + case 0x00BE: state &= ~STATE_RIGHT_ALT; break; // released left alt + + case 0x006e: key = KEY_ESCAPE; break; + case 0x004b: key = KEY_INSERT; break; + case 0x004c: key = KEY_DELETE; break; + case 0x004f: key = KEY_LEFT; break; + case 0x0050: key = KEY_HOME; break; + case 0x0051: key = KEY_END; break; + case 0x0053: key = KEY_UP; break; + case 0x0054: key = KEY_DOWN; break; + case 0x0055: key = KEY_PAGE_UP; break; + case 0x0056: key = KEY_PAGE_DOWN; break; + case 0x0059: key = KEY_RIGHT; break; + case 0x0400: key = KEY_MOUSE_1; break; + case 0x0800: key = KEY_MOUSE_2; break; + + default: + { + if (!(cmd & 0x80)) // pressed key + { + if (cmd >= 0x70 && cmd <= 0x7F) // function keys + { + key = cmd + 0x10; // 7x -> 8x + } + else if (cmd < 64) // key listed in key_table + { + if (state & (STATE_LEFT_ALT | STATE_RIGHT_ALT)) + { + switch (cmd) + { + case 0x0003: key = '²'; break; + case 0x0008: key = '{'; break; + case 0x0009: key = '['; break; + case 0x000A: key = ']'; break; + case 0x000B: key = '}'; break; + case 0x000C: key = '\\'; break; + case 0x001C: key = '~'; break; + case 0x002D: key = '|'; break; + case 0x0034: key = 0xB5; break; // Mu + } + } + else if (state & (STATE_LEFT_CTRL)) + { + if (key_table[cmd] >= 'a' && key_table[cmd] <= 'z') + { + key = key_table[cmd] - 'a' + 1; + } + else + { + key = key_table[cmd]; + } + } + else + { + int idx = cmd + ((state & (STATE_LEFT_SHIFT | STATE_RIGHT_SHIFT)) ? 64 : 0); + + if (key_table[idx]) + { + key = key_table[idx]; + } + } + } + } + break; + } + } + + return (key); +} + +static int analyze = FALSE; +static int list = FALSE; +static IRMP_DATA irmp_data; + +static void +next_tick (void) +{ + if (! analyze && ! list) + { + (void) irmp_ISR (); + + if (irmp_get_data (&irmp_data)) + { + uint8_t key; + + ANALYZE_ONLY_NORMAL_PUTCHAR (' '); + + if (verbose) + { + printf ("%8.3fms ", (double) (time_counter * 1000) / F_INTERRUPTS); + } + + if (irmp_data.protocol == IRMP_FDC_PROTOCOL && (key = get_fdc_key (irmp_data.command)) != 0) + { + if ((key >= 0x20 && key < 0x7F) || key >= 0xA0) + { + printf ("p = %2d, a = 0x%04x, c = 0x%04x, f = 0x%02x, asc = 0x%02x, key = '%c'\n", + irmp_data.protocol, irmp_data.address, irmp_data.command, irmp_data.flags, key, key); + } + else if (key == '\r' || key == '\t' || key == KEY_ESCAPE || (key >= 0x80 && key <= 0x9F)) // function keys + { + char * p = (char *) NULL; + + switch (key) + { + case '\t' : p = "TAB"; break; + case '\r' : p = "CR"; break; + case KEY_ESCAPE : p = "ESCAPE"; break; + case KEY_MENUE : p = "MENUE"; break; + case KEY_BACK : p = "BACK"; break; + case KEY_FORWARD : p = "FORWARD"; break; + case KEY_ADDRESS : p = "ADDRESS"; break; + case KEY_WINDOW : p = "WINDOW"; break; + case KEY_1ST_PAGE : p = "1ST_PAGE"; break; + case KEY_STOP : p = "STOP"; break; + case KEY_MAIL : p = "MAIL"; break; + case KEY_FAVORITES : p = "FAVORITES"; break; + case KEY_NEW_PAGE : p = "NEW_PAGE"; break; + case KEY_SETUP : p = "SETUP"; break; + case KEY_FONT : p = "FONT"; break; + case KEY_PRINT : p = "PRINT"; break; + case KEY_ON_OFF : p = "ON_OFF"; break; + + case KEY_INSERT : p = "INSERT"; break; + case KEY_DELETE : p = "DELETE"; break; + case KEY_LEFT : p = "LEFT"; break; + case KEY_HOME : p = "HOME"; break; + case KEY_END : p = "END"; break; + case KEY_UP : p = "UP"; break; + case KEY_DOWN : p = "DOWN"; break; + case KEY_PAGE_UP : p = "PAGE_UP"; break; + case KEY_PAGE_DOWN : p = "PAGE_DOWN"; break; + case KEY_RIGHT : p = "RIGHT"; break; + case KEY_MOUSE_1 : p = "KEY_MOUSE_1"; break; + case KEY_MOUSE_2 : p = "KEY_MOUSE_2"; break; + default : p = ""; break; + } + + printf ("p = %2d, a = 0x%04x, c = 0x%04x, f = 0x%02x, asc = 0x%02x, key = %s\n", + irmp_data.protocol, irmp_data.address, irmp_data.command, irmp_data.flags, key, p); + } + else + { + printf ("p = %2d, a = 0x%04x, c = 0x%04x, f = 0x%02x, asc = 0x%02x\n", + irmp_data.protocol, irmp_data.address, irmp_data.command, irmp_data.flags, key); + } + } + else + { + printf ("p = %2d, a = 0x%04x, c = 0x%04x, f = 0x%02x\n", + irmp_data.protocol, irmp_data.address, irmp_data.command, irmp_data.flags); + } + } + } +} +#endif + +#ifndef LIRC_IRMP +int +main (int argc, char ** argv) +{ + int i; + int ch; + int last_ch = 0; + int pulse = 0; + int pause = 0; + + int start_pulses[256]; + int start_pauses[256]; + int pulses[256]; + int pauses[256]; + + int first_pulse = TRUE; + int first_pause = TRUE; + + if (argc == 2) + { + if (! strcmp (argv[1], "-v")) + { + verbose = TRUE; + } + else if (! strcmp (argv[1], "-l")) + { + list = TRUE; + } + else if (! strcmp (argv[1], "-a")) + { + analyze = TRUE; + } + else if (! strcmp (argv[1], "-s")) + { + silent = TRUE; + } + else if (! strcmp (argv[1], "-p")) + { + print_timings (); + return (0); + } + } + + for (i = 0; i < 256; i++) + { + start_pulses[i] = 0; + start_pauses[i] = 0; + pulses[i] = 0; + pauses[i] = 0; + } + + IRMP_PIN = 0xFF; + + while ((ch = getchar ()) != EOF) + { + if (ch == '_' || ch == '0') + { + if (last_ch != ch) + { + if (pause > 0) + { + if (list) + { + printf ("pause: %d\n", pause); + } + + if (analyze) + { + if (first_pause) + { + if (pause < 256) + { + start_pauses[pause]++; + } + first_pause = FALSE; + } + else + { + if (pause < 256) + { + pauses[pause]++; + } + } + } + } + pause = 0; + } + pulse++; + IRMP_PIN = 0x00; + } + else if (ch == 0xaf || ch == '-' || ch == '1') + { + if (last_ch != ch) + { + if (list) + { + printf ("pulse: %d ", pulse); + } + + if (analyze) + { + if (first_pulse) + { + if (pulse < 256) + { + start_pulses[pulse]++; + } + first_pulse = FALSE; + } + else + { + if (pulse < 256) + { + pulses[pulse]++; + } + } + } + pulse = 0; + } + + pause++; + IRMP_PIN = 0xff; + } + else if (ch == '\n') + { + IRMP_PIN = 0xff; + + if (list && pause > 0) + { + printf ("pause: %d\n", pause); + } + pause = 0; + + if (! analyze) + { + for (i = 0; i < (int) ((8000.0 * F_INTERRUPTS) / 10000); i++) // newline: long pause of 800 msec + { + next_tick (); + } + } + first_pulse = TRUE; + first_pause = TRUE; + } + else if (ch == '#') + { + if (analyze) + { + while ((ch = getchar()) != '\n' && ch != EOF) + { + ; + } + } + else + { + puts ("-------------------------------------------------------------------"); + putchar (ch); + + while ((ch = getchar()) != '\n' && ch != EOF) + { + if (ch != '\r') // ignore CR in DOS/Windows files + { + putchar (ch); + } + } + putchar ('\n'); + } + + } + + last_ch = ch; + + next_tick (); + } + + if (analyze) + { + print_spectrum ("START PULSES", start_pulses, TRUE); + print_spectrum ("START PAUSES", start_pauses, FALSE); + print_spectrum ("PULSES", pulses, TRUE); + print_spectrum ("PAUSES", pauses, FALSE); + puts ("-------------------------------------------------------------------------------"); + } + return 0; +} +#else +#ifndef IRMP_EMBED +/* 50 ms. This should be longer than the longest light pulse */ +#define POLL_MS (50 * 1000) +#define LIRC_PULSE 0x01000000 +#define LIRC_PULSE_MASK 0x00FFFFFF + +int main (int argc, char ** argv) +{ + int fd; + int pulse; + int last_pulse = 1; + uint32_t lircdata; /* lirc_t to be correct... */ + unsigned int count = 0; /* how many timeouts? */ + IRMP_DATA d; + + silent = TRUE; + + if (argc == 2) + { + if (! strcmp (argv[1], "-v")) + { + verbose = TRUE; + silent = FALSE; + } + else if (! strcmp (argv[1], "-p")) + { + print_timings (); + return (0); + } + } + + IRMP_PIN = 0xFF; + fd = open("/dev/lirc", O_RDONLY); + if (fd < 0) + { + perror ("open /dev/lirc"); + return 1; + } + /* TODO: ioctl to find out if we have a compatible LIRC_MODE2 device */ + + while(1) + { + fd_set fds; + struct timeval tv; + int ret; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + tv.tv_sec = 0; + tv.tv_usec = POLL_MS; + /* any singal can interrupt select. we rely on the linux-only feature + * that the timeout is automatcally recalculated in this case! */ + do { + ret = select(fd + 1, &fds, NULL, NULL, &tv); + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + /* errno != EINTR... */ + perror("lirmp: select"); + break; + } + + if (ret == 0) + { + count++; + lircdata = POLL_MS; /* timeout */ + pulse = !last_pulse; /* lirc sends data on signal change */ + } + else + { + if (read(fd, &lircdata, sizeof(lircdata)) != sizeof(lircdata)) + { + perror("read"); + break; + } + pulse = (lircdata & LIRC_PULSE); /* we got light... */ + last_pulse = pulse; + lircdata &= LIRC_PULSE_MASK; /* how long the pulse was in microseconds */ + } + + if (ret && count) + { + if (count * POLL_MS > lircdata) + lircdata = 0; + else + lircdata -= count * POLL_MS; + count = 0; + } + //printf("lircdata: ret:%d c:%d %d\n", ret, ch - '0', lircdata); + lircdata /= (1000000 / F_INTERRUPTS); + + if (pulse) + IRMP_PIN = 0x00; + else + IRMP_PIN = 0xff; + + do { + (void) irmp_ISR (); + if (irmp_get_data (&d)) + { + printf("protocol: %2d address: 0x%04x command: 0x%04x flags: %d\n", + d.protocol, d.address, d.command, d.flags); + + /* do something else here... */ + + /* todo: do we need to complete the loop if we already + * detected the singal in this pulse? */ + } + } while (lircdata-- > 0); + } + return 0; +} +#endif // IRMP_EMBED +#endif // LIRC_IRMP +#endif // ANALYZE diff --git a/libarmbox/irmp.h b/libarmbox/irmp.h new file mode 100644 index 0000000..1e3852b --- /dev/null +++ b/libarmbox/irmp.h @@ -0,0 +1,528 @@ +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * irmp.h + * + * Copyright (c) 2009-2011 Frank Meyer - frank(at)fli4l.de + * + * $Id: irmp.h,v 1.70 2012/02/21 08:41:46 fm Exp $ + * + * ATMEGA88 @ 8 MHz + * + * 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. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +#ifndef _WC_IRMP_H_ +#define _WC_IRMP_H_ + +#if defined(__18CXX) // Microchip C18 declaration of missing typedef +typedef unsigned char uint8_t; +typedef unsigned int uint16_t; +#endif //Microchip C18 + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * timing constants: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +// fm 22.09.2011: may not be more than 16000L, otherwise some JVC codes will not be accepted +#define IRMP_TIMEOUT_TIME 15500.0e-6 // timeout after 15.5 ms darkness +#define IRMP_TIMEOUT_TIME_MS 15500L // timeout after 15.5 ms darkness + +#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 +#define IRMP_TIMEOUT_NIKON_TIME 29500.0e-6 // 2nd timeout after 29.5 ms darkness (only for NIKON!) +#define IRMP_TIMEOUT_NIKON_TIME_MS 29500L // 2nd timeout after 29.5 ms darkness +typedef uint16_t PAUSE_LEN; +#define IRMP_TIMEOUT_NIKON_LEN (PAUSE_LEN)(F_INTERRUPTS * IRMP_TIMEOUT_NIKON_TIME + 0.5) +#else +#if (F_INTERRUPTS * IRMP_TIMEOUT_TIME_MS) / 1000000 >= 254 +typedef uint16_t PAUSE_LEN; +#else +typedef uint8_t PAUSE_LEN; +#endif +#endif + +#define IRMP_TIMEOUT_LEN (PAUSE_LEN)(F_INTERRUPTS * IRMP_TIMEOUT_TIME + 0.5) + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * IR protocols + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define IRMP_SIRCS_PROTOCOL 1 // Sony +#define IRMP_NEC_PROTOCOL 2 // NEC, Pioneer, JVC, Toshiba, NoName etc. +#define IRMP_SAMSUNG_PROTOCOL 3 // Samsung +#define IRMP_MATSUSHITA_PROTOCOL 4 // Matsushita +#define IRMP_KASEIKYO_PROTOCOL 5 // Kaseikyo (Panasonic etc) +#define IRMP_RECS80_PROTOCOL 6 // Philips, Thomson, Nordmende, Telefunken, Saba +#define IRMP_RC5_PROTOCOL 7 // Philips etc +#define IRMP_DENON_PROTOCOL 8 // Denon, Sharp +#define IRMP_RC6_PROTOCOL 9 // Philips etc +#define IRMP_SAMSUNG32_PROTOCOL 10 // Samsung32: no sync pulse at bit 16, length 32 instead of 37 +#define IRMP_APPLE_PROTOCOL 11 // Apple, very similar to NEC +#define IRMP_RECS80EXT_PROTOCOL 12 // Philips, Technisat, Thomson, Nordmende, Telefunken, Saba +#define IRMP_NUBERT_PROTOCOL 13 // Nubert +#define IRMP_BANG_OLUFSEN_PROTOCOL 14 // Bang & Olufsen +#define IRMP_GRUNDIG_PROTOCOL 15 // Grundig +#define IRMP_NOKIA_PROTOCOL 16 // Nokia +#define IRMP_SIEMENS_PROTOCOL 17 // Siemens, e.g. Gigaset +#define IRMP_FDC_PROTOCOL 18 // FDC keyboard +#define IRMP_RCCAR_PROTOCOL 19 // RC Car +#define IRMP_JVC_PROTOCOL 20 // JVC (NEC with 16 bits) +#define IRMP_RC6A_PROTOCOL 21 // RC6A, e.g. Kathrein, XBOX +#define IRMP_NIKON_PROTOCOL 22 // Nikon +#define IRMP_RUWIDO_PROTOCOL 23 // Ruwido, e.g. T-Home Mediareceiver +#define IRMP_IR60_PROTOCOL 24 // IR60 (SAB2008) +#define IRMP_KATHREIN_PROTOCOL 25 // Kathrein +#define IRMP_NETBOX_PROTOCOL 26 // Netbox keyboard (bitserial) +#define IRMP_NEC16_PROTOCOL 27 // NEC with 16 bits (incl. sync) +#define IRMP_NEC42_PROTOCOL 28 // NEC with 42 bits +#define IRMP_LEGO_PROTOCOL 29 // LEGO Power Functions RC +#define IRMP_THOMSON_PROTOCOL 30 // Thomson +#define IRMP_GRUNDIG2_PROTOCOL 31 // Grundig, e.g. TP400 + +#define IRMP_N_PROTOCOLS 31 // number of supported protocols + +// some flags of struct IRMP_PARAMETER: +#define IRMP_PARAM_FLAG_IS_MANCHESTER 0x01 +#define IRMP_PARAM_FLAG_1ST_PULSE_IS_1 0x02 +#define IRMP_PARAM_FLAG_IS_SERIAL 0x04 + +#define SIRCS_START_BIT_PULSE_TIME 2400.0e-6 // 2400 usec pulse +#define SIRCS_START_BIT_PAUSE_TIME 600.0e-6 // 600 usec pause +#define SIRCS_1_PULSE_TIME 1200.0e-6 // 1200 usec pulse +#define SIRCS_0_PULSE_TIME 600.0e-6 // 600 usec pulse +#define SIRCS_PAUSE_TIME 600.0e-6 // 600 usec pause +#define SIRCS_FRAMES 3 // SIRCS sends each frame 3 times +#define SIRCS_AUTO_REPETITION_PAUSE_TIME 25.0e-3 // auto repetition after 25ms +#define SIRCS_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms +#define SIRCS_ADDRESS_OFFSET 15 // skip 15 bits +#define SIRCS_ADDRESS_LEN 5 // read up to 5 address bits +#define SIRCS_COMMAND_OFFSET 0 // skip 0 bits +#define SIRCS_COMMAND_LEN 15 // read 12-15 command bits +#define SIRCS_MINIMUM_DATA_LEN 12 // minimum data length +#define SIRCS_COMPLETE_DATA_LEN 20 // complete length - may be up to 20 +#define SIRCS_STOP_BIT 0 // has no stop bit +#define SIRCS_LSB 1 // LSB...MSB +#define SIRCS_FLAGS 0 // flags + +#define NEC_START_BIT_PULSE_TIME 9000.0e-6 // 9000 usec pulse +#define NEC_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause +#define NEC_REPEAT_START_BIT_PAUSE_TIME 2250.0e-6 // 2250 usec pause +#define NEC_PULSE_TIME 560.0e-6 // 560 usec pulse +#define NEC_1_PAUSE_TIME 1690.0e-6 // 1690 usec pause +#define NEC_0_PAUSE_TIME 560.0e-6 // 560 usec pause +#define NEC_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms +#define NEC_ADDRESS_OFFSET 0 // skip 0 bits +#define NEC_ADDRESS_LEN 16 // read 16 address bits +#define NEC_COMMAND_OFFSET 16 // skip 16 bits (8 address + 8 /address) +#define NEC_COMMAND_LEN 16 // read 16 bits (8 command + 8 /command) +#define NEC_COMPLETE_DATA_LEN 32 // complete length +#define NEC_STOP_BIT 1 // has stop bit +#define NEC_LSB 1 // LSB...MSB +#define NEC_FLAGS 0 // flags + +#define NEC42_ADDRESS_OFFSET 0 // skip 0 bits +#define NEC42_ADDRESS_LEN 13 // read 13 address bits +#define NEC42_COMMAND_OFFSET 26 // skip 26 bits (2 x 13 address bits) +#define NEC42_COMMAND_LEN 8 // read 8 command bits +#define NEC42_COMPLETE_DATA_LEN 42 // complete length (2 x 13 + 2 x 8) + +#define NEC16_ADDRESS_OFFSET 0 // skip 0 bits +#define NEC16_ADDRESS_LEN 8 // read 8 address bits +#define NEC16_COMMAND_OFFSET 8 // skip 8 bits (8 address) +#define NEC16_COMMAND_LEN 8 // read 8 bits (8 command) +#define NEC16_COMPLETE_DATA_LEN 16 // complete length + +#define SAMSUNG_START_BIT_PULSE_TIME 4500.0e-6 // 4500 usec pulse +#define SAMSUNG_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause +#define SAMSUNG_PULSE_TIME 550.0e-6 // 550 usec pulse +#define SAMSUNG_1_PAUSE_TIME 1650.0e-6 // 1650 usec pause +#define SAMSUNG_0_PAUSE_TIME 550.0e-6 // 550 usec pause + +#define SAMSUNG_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms +#define SAMSUNG_ADDRESS_OFFSET 0 // skip 0 bits +#define SAMSUNG_ADDRESS_LEN 16 // read 16 address bits +#define SAMSUNG_ID_OFFSET 17 // skip 16 + 1 sync bit +#define SAMSUNG_ID_LEN 4 // read 4 id bits +#define SAMSUNG_COMMAND_OFFSET 21 // skip 16 + 1 sync + 4 data bits +#define SAMSUNG_COMMAND_LEN 16 // read 16 command bits +#define SAMSUNG_COMPLETE_DATA_LEN 37 // complete length +#define SAMSUNG_STOP_BIT 1 // has stop bit +#define SAMSUNG_LSB 1 // LSB...MSB? +#define SAMSUNG_FLAGS 0 // flags + +#define SAMSUNG32_COMMAND_OFFSET 16 // skip 16 bits +#define SAMSUNG32_COMMAND_LEN 16 // read 16 command bits +#define SAMSUNG32_COMPLETE_DATA_LEN 32 // complete length +#define SAMSUNG32_FRAMES 1 // SAMSUNG32 sends each frame 1 times +#define SAMSUNG32_AUTO_REPETITION_PAUSE_TIME 47.0e-3 // repetition after 47 ms +#define SAMSUNG32_FRAME_REPEAT_PAUSE_TIME 47.0e-3 // frame repeat after 47ms + +#define MATSUSHITA_START_BIT_PULSE_TIME 3488.0e-6 // 3488 usec pulse +#define MATSUSHITA_START_BIT_PAUSE_TIME 3488.0e-6 // 3488 usec pause +#define MATSUSHITA_PULSE_TIME 872.0e-6 // 872 usec pulse +#define MATSUSHITA_1_PAUSE_TIME 2616.0e-6 // 2616 usec pause +#define MATSUSHITA_0_PAUSE_TIME 872.0e-6 // 872 usec pause +#define MATSUSHITA_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define MATSUSHITA_ADDRESS_OFFSET 12 // skip 12 bits +#define MATSUSHITA_ADDRESS_LEN 12 // read 12 address bits +#define MATSUSHITA_COMMAND_OFFSET 0 // skip 0 bits +#define MATSUSHITA_COMMAND_LEN 12 // read 12 bits (6 custom + 6 command) +#define MATSUSHITA_COMPLETE_DATA_LEN 24 // complete length +#define MATSUSHITA_STOP_BIT 1 // has stop bit +#define MATSUSHITA_LSB 1 // LSB...MSB? +#define MATSUSHITA_FLAGS 0 // flags + +#define KASEIKYO_START_BIT_PULSE_TIME 3380.0e-6 // 3380 usec pulse +#define KASEIKYO_START_BIT_PAUSE_TIME 1690.0e-6 // 1690 usec pause +#define KASEIKYO_PULSE_TIME 423.0e-6 // 525 usec pulse +#define KASEIKYO_1_PAUSE_TIME 1269.0e-6 // 525 usec pause +#define KASEIKYO_0_PAUSE_TIME 423.0e-6 // 1690 usec pause +#define KASEIKYO_AUTO_REPETITION_PAUSE_TIME 74.0e-3 // repetition after 74 ms +#define KASEIKYO_FRAME_REPEAT_PAUSE_TIME 74.0e-3 // frame repeat after 74 ms +#define KASEIKYO_ADDRESS_OFFSET 0 // skip 0 bits +#define KASEIKYO_ADDRESS_LEN 16 // read 16 address bits +#define KASEIKYO_COMMAND_OFFSET 28 // skip 28 bits (16 manufacturer & 4 parity & 8 genre) +#define KASEIKYO_COMMAND_LEN 12 // read 12 command bits (10 real command & 2 id) +#define KASEIKYO_COMPLETE_DATA_LEN 48 // complete length +#define KASEIKYO_STOP_BIT 1 // has stop bit +#define KASEIKYO_LSB 1 // LSB...MSB? +#define KASEIKYO_FRAMES 2 // KASEIKYO sends 1st frame 2 times +#define KASEIKYO_FLAGS 0 // flags + +#define RECS80_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse +#define RECS80_START_BIT_PAUSE_TIME 7432.0e-6 // 7432 usec pause +#define RECS80_PULSE_TIME 158.0e-6 // 158 usec pulse +#define RECS80_1_PAUSE_TIME 7432.0e-6 // 7432 usec pause +#define RECS80_0_PAUSE_TIME 4902.0e-6 // 4902 usec pause +#define RECS80_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define RECS80_ADDRESS_OFFSET 1 // skip 1 bit (toggle bit) +#define RECS80_ADDRESS_LEN 3 // read 3 address bits +#define RECS80_COMMAND_OFFSET 4 // skip 4 bits (1 toggle + 3 address) +#define RECS80_COMMAND_LEN 6 // read 6 command bits +#define RECS80_COMPLETE_DATA_LEN 10 // complete length +#define RECS80_STOP_BIT 1 // has stop bit +#define RECS80_LSB 0 // MSB...LSB +#define RECS80_FLAGS 0 // flags + +#define RC5_BIT_TIME 889.0e-6 // 889 usec pulse/pause +#define RC5_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms + +#define RC5_ADDRESS_OFFSET 1 // skip 1 bit (2nd start) +#define RC5_ADDRESS_LEN 6 // read 1 toggle bit (for key repetition detection) + 5 address bits +#define RC5_COMMAND_OFFSET 7 // skip 5 bits (2nd start + 1 toggle + 5 address) +#define RC5_COMMAND_LEN 6 // read 6 command bits +#define RC5_COMPLETE_DATA_LEN 13 // complete length +#define RC5_STOP_BIT 0 // has no stop bit +#define RC5_LSB 0 // MSB...LSB +#define RC5_FLAGS IRMP_PARAM_FLAG_IS_MANCHESTER // flags + +#define DENON_PULSE_TIME 310.0e-6 // 310 usec pulse in practice, 275 in theory +#define DENON_1_PAUSE_TIME 1780.0e-6 // 1780 usec pause in practice, 1900 in theory +#define DENON_0_PAUSE_TIME 745.0e-6 // 745 usec pause in practice, 775 in theory +#define DENON_FRAMES 2 // DENON sends each frame 2 times +#define DENON_AUTO_REPETITION_PAUSE_TIME 65.0e-3 // inverted repetition after 65ms +#define DENON_FRAME_REPEAT_PAUSE_TIME 65.0e-3 // frame repeat after 65ms +#define DENON_ADDRESS_OFFSET 0 // skip 0 bits +#define DENON_ADDRESS_LEN 5 // read 5 address bits +#define DENON_COMMAND_OFFSET 5 // skip 5 +#define DENON_COMMAND_LEN 10 // read 10 command bits +#define DENON_COMPLETE_DATA_LEN 15 // complete length +#define DENON_STOP_BIT 1 // has stop bit +#define DENON_LSB 0 // MSB...LSB +#define DENON_FLAGS 0 // flags + +#define RC6_START_BIT_PULSE_TIME 2666.0e-6 // 2.666 msec pulse +#define RC6_START_BIT_PAUSE_TIME 889.0e-6 // 889 usec pause +#define RC6_TOGGLE_BIT_TIME 889.0e-6 // 889 msec pulse/pause +#define RC6_BIT_TIME 444.0e-6 // 889 usec pulse/pause +#define RC6_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define RC6_ADDRESS_OFFSET 5 // skip "1" + 3 mode bits + 1 toggle bit +#define RC6_ADDRESS_LEN 8 // read 8 address bits +#define RC6_COMMAND_OFFSET 13 // skip 12 bits ("1" + 3 mode + 1 toggle + 8 address) +#define RC6_COMMAND_LEN 8 // read 8 command bits +#define RC6_COMPLETE_DATA_LEN_SHORT 21 // complete length +#define RC6_COMPLETE_DATA_LEN_LONG 36 // complete length +#define RC6_STOP_BIT 0 // has no stop bit +#define RC6_LSB 0 // MSB...LSB +#define RC6_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags + +#define RECS80EXT_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse +#define RECS80EXT_START_BIT_PAUSE_TIME 3637.0e-6 // 3637 usec pause +#define RECS80EXT_PULSE_TIME 158.0e-6 // 158 usec pulse +#define RECS80EXT_1_PAUSE_TIME 7432.0e-6 // 7432 usec pause +#define RECS80EXT_0_PAUSE_TIME 4902.0e-6 // 4902 usec pause +#define RECS80EXT_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define RECS80EXT_ADDRESS_OFFSET 2 // skip 2 bits (2nd start + 1 toggle) +#define RECS80EXT_ADDRESS_LEN 4 // read 4 address bits +#define RECS80EXT_COMMAND_OFFSET 6 // skip 6 bits (2nd start + 1 toggle + 4 address) +#define RECS80EXT_COMMAND_LEN 6 // read 6 command bits +#define RECS80EXT_COMPLETE_DATA_LEN 12 // complete length +#define RECS80EXT_STOP_BIT 1 // has stop bit +#define RECS80EXT_LSB 0 // MSB...LSB +#define RECS80EXT_FLAGS 0 // flags + +#define NUBERT_START_BIT_PULSE_TIME 1340.0e-6 // 1340 usec pulse +#define NUBERT_START_BIT_PAUSE_TIME 340.0e-6 // 340 usec pause +#define NUBERT_1_PULSE_TIME 1340.0e-6 // 1340 usec pulse +#define NUBERT_1_PAUSE_TIME 340.0e-6 // 340 usec pause +#define NUBERT_0_PULSE_TIME 500.0e-6 // 500 usec pulse +#define NUBERT_0_PAUSE_TIME 1300.0e-6 // 1300 usec pause +#define NUBERT_FRAMES 2 // Nubert sends 2 frames +#define NUBERT_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms +#define NUBERT_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 45ms +#define NUBERT_ADDRESS_OFFSET 0 // skip 0 bits +#define NUBERT_ADDRESS_LEN 0 // read 0 address bits +#define NUBERT_COMMAND_OFFSET 0 // skip 0 bits +#define NUBERT_COMMAND_LEN 10 // read 10 bits +#define NUBERT_COMPLETE_DATA_LEN 10 // complete length +#define NUBERT_STOP_BIT 1 // has stop bit +#define NUBERT_LSB 0 // MSB? +#define NUBERT_FLAGS 0 // flags + +#define BANG_OLUFSEN_START_BIT1_PULSE_TIME 200.0e-6 // 200 usec pulse +#define BANG_OLUFSEN_START_BIT1_PAUSE_TIME 3125.0e-6 // 3125 usec pause +#define BANG_OLUFSEN_START_BIT2_PULSE_TIME 200.0e-6 // 200 usec pulse +#define BANG_OLUFSEN_START_BIT2_PAUSE_TIME 3125.0e-6 // 3125 usec pause +#define BANG_OLUFSEN_START_BIT3_PULSE_TIME 200.0e-6 // 200 usec pulse +#define BANG_OLUFSEN_START_BIT3_PAUSE_TIME 15625.0e-6 // 15625 usec pause +#define BANG_OLUFSEN_START_BIT4_PULSE_TIME 200.0e-6 // 200 usec pulse +#define BANG_OLUFSEN_START_BIT4_PAUSE_TIME 3125.0e-6 // 3125 usec pause +#define BANG_OLUFSEN_PULSE_TIME 200.0e-6 // 200 usec pulse +#define BANG_OLUFSEN_1_PAUSE_TIME 9375.0e-6 // 9375 usec pause +#define BANG_OLUFSEN_0_PAUSE_TIME 3125.0e-6 // 3125 usec pause +#define BANG_OLUFSEN_R_PAUSE_TIME 6250.0e-6 // 6250 usec pause (repeat last bit) +#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME 12500.0e-6 // 12500 usec pause (trailer bit) +#define BANG_OLUFSEN_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define BANG_OLUFSEN_ADDRESS_OFFSET 0 // no address bits +#define BANG_OLUFSEN_ADDRESS_LEN 0 // no address bits +#define BANG_OLUFSEN_COMMAND_OFFSET 3 // skip startbits 2, 3, 4 +#define BANG_OLUFSEN_COMMAND_LEN 16 // read 16 command bits +#define BANG_OLUFSEN_COMPLETE_DATA_LEN 20 // complete length: startbits 2, 3, 4 + 16 data bits + trailer bit +#define BANG_OLUFSEN_STOP_BIT 1 // has stop bit +#define BANG_OLUFSEN_LSB 0 // MSB...LSB +#define BANG_OLUFSEN_FLAGS 0 // flags + +#define GRUNDIG_NOKIA_IR60_BIT_TIME 528.0e-6 // 528 usec pulse/pause +#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME 2639.0e-6 // 2639 usec pause after pre bit +#define GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_TIME 117.76e-3 // info frame repeat after 117.76 ms +#define GRUNDIG_NOKIA_IR60_STOP_BIT 0 // has no stop bit +#define GRUNDIG_NOKIA_IR60_LSB 1 // MSB...LSB +#define GRUNDIG_NOKIA_IR60_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags + +#define GRUNDIG_FRAMES 2 // GRUNDIG sends each frame 1+1 times +#define GRUNDIG_AUTO_REPETITION_PAUSE_TIME 20.0e-3 // repetition after 20ms +#define GRUNDIG_ADDRESS_OFFSET 0 // no address +#define GRUNDIG_ADDRESS_LEN 0 // no address +#define GRUNDIG_COMMAND_OFFSET 1 // skip 1 start bit +#define GRUNDIG_COMMAND_LEN 9 // read 9 command bits +#define GRUNDIG_COMPLETE_DATA_LEN 10 // complete length: 1 start bit + 9 data bits + +#define NOKIA_FRAMES 3 // NOKIA sends each frame 1 + 1 + 1 times +#define NOKIA_AUTO_REPETITION_PAUSE_TIME 20.0e-3 // repetition after 20ms +#define NOKIA_ADDRESS_OFFSET 9 // skip 9 bits (1 start bit + 8 data bits) +#define NOKIA_ADDRESS_LEN 8 // 7 address bits +#define NOKIA_COMMAND_OFFSET 1 // skip 1 bit (1 start bit) +#define NOKIA_COMMAND_LEN 8 // read 8 command bits +#define NOKIA_COMPLETE_DATA_LEN 17 // complete length: 1 start bit + 8 address bits + 8 command bits + +#define IR60_TIMEOUT_TIME 5000.0e-6 // timeout grundig frame, switch to IR60 +#define IR60_ADDRESS_OFFSET 0 // skip 1 bits +#define IR60_ADDRESS_LEN 0 // read 0 address bits +#define IR60_COMMAND_OFFSET 0 // skip 1 bit (start bit after pre bit, always 1) +#define IR60_COMMAND_LEN 7 // read 6 command bits +#define IR60_COMPLETE_DATA_LEN 7 // complete length + +#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME 275.0e-6 // 275 usec pulse +#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME 550.0e-6 // 550 usec pause +#define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME 275.0e-6 // 275 usec short pulse +#define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME_2 550.0e-6 // 550 usec long pulse +#define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME 275.0e-6 // 275 usec short pause +#define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME_2 550.0e-6 // 550 usec long pause +#define SIEMENS_OR_RUWIDO_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define SIEMENS_OR_RUWIDO_STOP_BIT 0 // has no stop bit +#define SIEMENS_OR_RUWIDO_LSB 0 // MSB...LSB +#define SIEMENS_OR_RUWIDO_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags + +#define RUWIDO_ADDRESS_OFFSET 0 // skip 0 bits +#define RUWIDO_ADDRESS_LEN 9 // read 9 address bits +#define RUWIDO_COMMAND_OFFSET 9 // skip 9 bits +#define RUWIDO_COMMAND_LEN 8 // read 7 + 1 command bits, last bit is only check bit +#define RUWIDO_COMPLETE_DATA_LEN 17 // complete length + +#define SIEMENS_ADDRESS_OFFSET 0 // skip 0 bits +#define SIEMENS_ADDRESS_LEN 11 // read 11 bits +#define SIEMENS_COMMAND_OFFSET 11 // skip 11 bits +#define SIEMENS_COMMAND_LEN 11 // read 10 + 1 command bits, last bit is only check bit +#define SIEMENS_COMPLETE_DATA_LEN 22 // complete length + +#define FDC_START_BIT_PULSE_TIME 2085.0e-6 // 2085 usec pulse +#define FDC_START_BIT_PAUSE_TIME 966.0e-6 // 966 usec pause +#define FDC_PULSE_TIME 300.0e-6 // 300 usec pulse +#define FDC_1_PAUSE_TIME 715.0e-6 // 715 usec pause +#define FDC_0_PAUSE_TIME 220.0e-6 // 220 usec pause +#define FDC_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms +#define FDC_ADDRESS_OFFSET 0 // skip 0 bits +#define FDC_ADDRESS_LEN 14 // read 14 address bits, but use only 6, shift 8 into command +#define FDC_COMMAND_OFFSET 20 // skip 20 bits +#define FDC_COMMAND_LEN 12 // read 12 bits +#define FDC_COMPLETE_DATA_LEN 40 // complete length +#define FDC_STOP_BIT 1 // has stop bit +#define FDC_LSB 1 // LSB...MSB +#define FDC_FLAGS 0 // flags + +#define RCCAR_START_BIT_PULSE_TIME 2000.0e-6 // 2000 usec pulse +#define RCCAR_START_BIT_PAUSE_TIME 2000.0e-6 // 2000 usec pause +#define RCCAR_PULSE_TIME 600.0e-6 // 360 usec pulse +#define RCCAR_1_PAUSE_TIME 450.0e-6 // 650 usec pause +#define RCCAR_0_PAUSE_TIME 900.0e-6 // 180 usec pause +#define RCCAR_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms +#define RCCAR_ADDRESS_OFFSET 0 // skip 0 bits +#define RCCAR_ADDRESS_LEN 0 // read 0 address bits +#define RCCAR_COMMAND_OFFSET 0 // skip 0 bits +#define RCCAR_COMMAND_LEN 13 // read 13 bits +#define RCCAR_COMPLETE_DATA_LEN 13 // complete length +#define RCCAR_STOP_BIT 1 // has stop bit +#define RCCAR_LSB 1 // LSB...MSB +#define RCCAR_FLAGS 0 // flags + +#define JVC_START_BIT_PULSE_TIME 9000.0e-6 // 9000 usec pulse +#define JVC_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause +#define JVC_PULSE_TIME 560.0e-6 // 560 usec pulse +#define JVC_1_PAUSE_TIME 1690.0e-6 // 1690 usec pause +#define JVC_0_PAUSE_TIME 560.0e-6 // 560 usec pause +#define JVC_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after 22ms +#define JVC_ADDRESS_OFFSET 0 // skip 0 bits +#define JVC_ADDRESS_LEN 4 // read 4 address bits +#define JVC_COMMAND_OFFSET 4 // skip 4 bits +#define JVC_COMMAND_LEN 12 // read 12 bits +#define JVC_COMPLETE_DATA_LEN 16 // complete length +#define JVC_STOP_BIT 1 // has stop bit +#define JVC_LSB 1 // LSB...MSB +#define JVC_FLAGS 0 // flags + +#define NIKON_START_BIT_PULSE_TIME 2200.0e-6 // 2200 usec pulse +#define NIKON_START_BIT_PAUSE_TIME 27100.0e-6 // 27100 usec pause +#define NIKON_PULSE_TIME 500.0e-6 // 500 usec pulse +#define NIKON_1_PAUSE_TIME 3500.0e-6 // 3500 usec pause +#define NIKON_0_PAUSE_TIME 1500.0e-6 // 1500 usec pause +#define NIKON_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms +#define NIKON_ADDRESS_OFFSET 0 // skip 0 bits +#define NIKON_ADDRESS_LEN 0 // read 0 address bits +#define NIKON_COMMAND_OFFSET 0 // skip 0 bits +#define NIKON_COMMAND_LEN 2 // read 2 bits +#define NIKON_COMPLETE_DATA_LEN 2 // complete length +#define NIKON_STOP_BIT 1 // has stop bit +#define NIKON_LSB 0 // LSB...MSB +#define NIKON_FLAGS 0 // flags + +#define KATHREIN_START_BIT_PULSE_TIME 210.0e-6 // 1340 usec pulse +#define KATHREIN_START_BIT_PAUSE_TIME 6218.0e-6 // 340 usec pause +#define KATHREIN_1_PULSE_TIME 210.0e-6 // 1340 usec pulse +#define KATHREIN_1_PAUSE_TIME 3000.0e-6 // 340 usec pause +#define KATHREIN_0_PULSE_TIME 210.0e-6 // 500 usec pulse +#define KATHREIN_0_PAUSE_TIME 1400.0e-6 // 1300 usec pause +#define KATHREIN_SYNC_BIT_PAUSE_LEN_TIME 4600.0e-6 // 4600 usec sync (on 6th and/or 8th bit) +#define KATHREIN_FRAMES 1 // Kathrein sends 1 frame +#define KATHREIN_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms +#define KATHREIN_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms +#define KATHREIN_ADDRESS_OFFSET 1 // skip 1 bits +#define KATHREIN_ADDRESS_LEN 4 // read 4 address bits +#define KATHREIN_COMMAND_OFFSET 5 // skip 5 bits +#define KATHREIN_COMMAND_LEN 7 // read 7 bits +#define KATHREIN_COMPLETE_DATA_LEN 13 // complete length +#define KATHREIN_STOP_BIT 1 // has stop bit +#define KATHREIN_LSB 0 // MSB +#define KATHREIN_FLAGS 0 // flags + +#define NETBOX_START_BIT_PULSE_TIME 2400.0e-6 // 2400 usec pulse +#define NETBOX_START_BIT_PAUSE_TIME 800.0e-6 // 800 usec pause +#define NETBOX_PULSE_TIME 800.0e-6 // 800 usec pulse +#define NETBOX_PAUSE_TIME 800.0e-6 // 800 usec pause +#define NETBOX_FRAMES 1 // Netbox sends 1 frame +#define NETBOX_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms +#define NETBOX_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms +#define NETBOX_ADDRESS_OFFSET 0 // skip 0 bits +#define NETBOX_ADDRESS_LEN 3 // read 3 address bits +#define NETBOX_COMMAND_OFFSET 3 // skip 3 bits +#define NETBOX_COMMAND_LEN 13 // read 13 bits +#define NETBOX_COMPLETE_DATA_LEN 16 // complete length +#define NETBOX_STOP_BIT 0 // has no stop bit +#define NETBOX_LSB 1 // LSB +#define NETBOX_FLAGS IRMP_PARAM_FLAG_IS_SERIAL // flags + +#define LEGO_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse ( 6 x 1/38kHz) +#define LEGO_START_BIT_PAUSE_TIME 1026.0e-6 // 1026 usec pause (39 x 1/38kHz) +#define LEGO_PULSE_TIME 158.0e-6 // 158 usec pulse ( 6 x 1/38kHz) +#define LEGO_1_PAUSE_TIME 553.0e-6 // 553 usec pause (21 x 1/38kHz) +#define LEGO_0_PAUSE_TIME 263.0e-6 // 263 usec pause (10 x 1/38kHz) +#define LEGO_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms +#define LEGO_ADDRESS_OFFSET 0 // skip 0 bits +#define LEGO_ADDRESS_LEN 0 // read 0 address bits +#define LEGO_COMMAND_OFFSET 0 // skip 0 bits +#define LEGO_COMMAND_LEN 16 // read 16 bits (12 command + 4 CRC) +#define LEGO_COMPLETE_DATA_LEN 16 // complete length +#define LEGO_STOP_BIT 1 // has stop bit +#define LEGO_LSB 0 // MSB...LSB +#define LEGO_FLAGS 0 // flags + +#define THOMSON_PULSE_TIME 550.0e-6 // 550 usec pulse +#define THOMSON_1_PAUSE_TIME 4500.0e-6 // 4500 usec pause +#define THOMSON_0_PAUSE_TIME 2000.0e-6 // 2000 usec pause +#define THOMSON_FRAMES 1 // THOMSON sends 1 frame +#define THOMSON_AUTO_REPETITION_PAUSE_TIME 65.0e-3 // repetition after 65ms +#define THOMSON_FRAME_REPEAT_PAUSE_TIME 65.0e-3 // frame repeat after 65ms +#define THOMSON_ADDRESS_OFFSET 0 // skip 0 bits +#define THOMSON_ADDRESS_LEN 4 // read 4 address bits +#define THOMSON_COMMAND_OFFSET 5 // skip 4 address bits + 1 toggle bit +#define THOMSON_COMMAND_LEN 7 // read 7 command bits +#define THOMSON_COMPLETE_DATA_LEN 12 // complete length +#define THOMSON_STOP_BIT 1 // has stop bit +#define THOMSON_LSB 0 // MSB...LSB +#define THOMSON_FLAGS 0 // flags + +#define GRUNDIG2_START_BIT_PULSE_TIME 550.0e-6 // 550 usec pulse +#define GRUNDIG2_START_BIT_PAUSE_TIME 2700.0e-6 // 2700 usec pause +#define GRUNDIG2_BIT_PULSE_TIME 550.0e-6 // 550 usec short pulse +#define GRUNDIG2_BIT_PAUSE_TIME 550.0e-6 // 550 usec short pause +#define GRUNDIG2_FRAME_REPEAT_PAUSE_TIME 100.0e-3 // frame repeat after 100ms +#define GRUNDIG2_STOP_BIT 0 // has no stop bit +#define GRUNDIG2_LSB 1 // MSB...LSB +#define GRUNDIG2_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags +#define GRUNDIG2_ADDRESS_OFFSET 0 // skip 0 bits +#define GRUNDIG2_ADDRESS_LEN 0 // read 0 bits +#define GRUNDIG2_COMMAND_OFFSET 0 // skip 0 bits +#define GRUNDIG2_COMMAND_LEN 7 // read 6 + 1 command bits, last bit is always 1 +#define GRUNDIG2_COMPLETE_DATA_LEN 7 // complete length + +#define AUTO_FRAME_REPETITION_TIME 80.0e-3 // SIRCS/SAMSUNG32/NUBERT: automatic repetition after 25-50ms + // KASEIKYO: automatic repetition after 75ms + +#define TRUE 1 +#define FALSE 0 + +#define IRMP_FLAG_REPETITION 0x01 + +typedef struct +{ + uint8_t protocol; // protocol, i.e. NEC_PROTOCOL + uint16_t address; // address + uint16_t command; // command + uint8_t flags; // flags, e.g. repetition +} IRMP_DATA; + +extern void irmp_init (void); +extern uint8_t irmp_get_data (IRMP_DATA *); +extern uint8_t irmp_is_busy (void); +extern uint8_t irmp_ISR (uint8_t); + +#if IRMP_PROTOCOL_NAMES == 1 +extern char * irmp_protocol_names[IRMP_N_PROTOCOLS + 1]; +#endif + +#if IRMP_USE_CALLBACK == 1 +extern void irmp_set_callback_ptr (void (*cb)(uint8_t)); +#endif // IRSND_USE_CALLBACK == 1 + +#endif /* _WC_IRMP_H_ */ diff --git a/libarmbox/irmpconfig.h b/libarmbox/irmpconfig.h new file mode 100644 index 0000000..10b34b7 --- /dev/null +++ b/libarmbox/irmpconfig.h @@ -0,0 +1,191 @@ +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * irmpconfig.h + * + * Copyright (c) 2009-2011 Frank Meyer - frank(at)fli4l.de + * + * $Id: irmpconfig.h,v 1.80 2012/02/21 08:41:46 fm Exp $ + * + * ATMEGA88 @ 8 MHz + * + * 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. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +#ifndef _IRMPCONFIG_H_ +#define _IRMPCONFIG_H_ + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change F_INTERRUPTS if you change the number of interrupts per second, + * Normally, F_INTERRUPTS should be in the range from 10000 to 15000, typical is 15000 + * A value above 15000 costs additional program space, absolute maximum value is 20000. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef F_INTERRUPTS +#define F_INTERRUPTS 15000 // interrupts per second, min: 10000, max: 20000, typ: 15000 +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change settings from 1 to 0 if you want to disable one or more decoders. + * This saves program space. + * + * 1 enable decoder + * 0 disable decoder + * + * The standard decoders are enabled per default. + * Less common protocols are disabled here, you need to enable them manually. + * + * If you want to use FDC or RCCAR simultaneous with RC5 protocol, additional program space is required. + * If you don't need RC5 when using FDC/RCCAR, you should disable RC5. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +// typical protocols, disable here! Enable Remarks F_INTERRUPTS Program Space +#define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~150 bytes +#define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE >= 10000 ~300 bytes +#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsung32 >= 10000 ~300 bytes +#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~50 bytes +#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~250 bytes +#define IRMP_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~250 bytes + +// more protocols, enable here! Enable Remarks F_INTERRUPTS Program Space +#define IRMP_SUPPORT_RC5_PROTOCOL 0 // RC5 >= 10000 ~250 bytes +#define IRMP_SUPPORT_RC6_PROTOCOL 0 // RC6 & RC6A >= 10000 ~250 bytes +#define IRMP_SUPPORT_JVC_PROTOCOL 0 // JVC >= 10000 ~150 bytes +#define IRMP_SUPPORT_NEC16_PROTOCOL 0 // NEC16 >= 10000 ~100 bytes +#define IRMP_SUPPORT_NEC42_PROTOCOL 0 // NEC42 >= 10000 ~300 bytes +#define IRMP_SUPPORT_IR60_PROTOCOL 0 // IR60 (SAB2008) >= 10000 ~300 bytes +#define IRMP_SUPPORT_GRUNDIG_PROTOCOL 0 // Grundig >= 10000 ~300 bytes +#define IRMP_SUPPORT_SIEMENS_PROTOCOL 0 // Siemens Gigaset >= 15000 ~550 bytes +#define IRMP_SUPPORT_NOKIA_PROTOCOL 0 // Nokia >= 10000 ~300 bytes + +// exotic protocols, enable here! Enable Remarks F_INTERRUPTS Program Space +#define IRMP_SUPPORT_GRUNDIG2_PROTOCOL 0 // Grundig TP400 >= 10000 ~300 bytes +#define IRMP_SUPPORT_KATHREIN_PROTOCOL 0 // Kathrein >= 10000 ~200 bytes +#define IRMP_SUPPORT_NUBERT_PROTOCOL 0 // NUBERT >= 10000 ~50 bytes +#define IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL 0 // Bang & Olufsen >= 10000 ~200 bytes +#define IRMP_SUPPORT_RECS80_PROTOCOL 0 // RECS80 (SAA3004) >= 15000 ~50 bytes +#define IRMP_SUPPORT_RECS80EXT_PROTOCOL 0 // RECS80EXT (SAA3008) >= 15000 ~50 bytes +#define IRMP_SUPPORT_THOMSON_PROTOCOL 0 // Thomson >= 10000 ~250 bytes +#define IRMP_SUPPORT_NIKON_PROTOCOL 0 // NIKON camera >= 10000 ~250 bytes +#define IRMP_SUPPORT_NETBOX_PROTOCOL 0 // Netbox keyboard >= 10000 ~400 bytes (PROTOTYPE!) +#define IRMP_SUPPORT_FDC_PROTOCOL 0 // FDC3402 keyboard >= 10000 (better 15000) ~150 bytes (~400 in combination with RC5) +#define IRMP_SUPPORT_RCCAR_PROTOCOL 0 // RC Car >= 10000 (better 15000) ~150 bytes (~500 in combination with RC5) +#define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 // RUWIDO, T-Home >= 15000 ~550 bytes +#define IRMP_SUPPORT_LEGO_PROTOCOL 0 // LEGO Power RC >= 20000 ~150 bytes + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if defined (PIC_C18) // Microchip C18 Compiler +#include // main PIC18 h file +#define IRMP_PIN PORTBbits.RB4 // use RB4 as IR input on PIC +#define input(x) (x) + +#elif defined (PIC_CCS_COMPILER) // PIC CCS Compiler: +#define IRMP_PIN PIN_B4 // use PB4 as IR input on PIC + +#else // AVR: + +#ifndef ARDUINO +#define IRMP_PORT PORTB +#define IRMP_DDR DDRB +#define IRMP_PIN PINB +#define IRMP_BIT 6 // use PB6 as IR input on AVR +#else // ARDUINO +#define IRMP_PIN PIND // use digital pin 2 as IR input +#define IRMP_BIT 2 // on arduino +#endif // ARDUINO + +#define input(x) ((x) & (1 << IRMP_BIT)) +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Set IRMP_LOGGING to 1 if want to log data to UART with 9600Bd + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef IRMP_LOGGING +#define IRMP_LOGGING 0 // 1: log IR signal (scan), 0: do not (default) +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Use external logging routines + * If you enable external logging, you have also to enable IRMP_LOGGING above + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef IRMP_EXT_LOGGING +#define IRMP_EXT_LOGGING 0 // 1:log, 0: do not log ; +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Set IRMP_PROTOCOL_NAMES to 1 if want to access protocol names (for logging etc), costs ~300 bytes RAM! + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define IRMP_PROTOCOL_NAMES 0 // 1: access protocol names, 0: do not (default), + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Use Callbacks to indicate input signal + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define IRMP_USE_CALLBACK 0 // flag: 0 = don't use callbacks, 1 = use callbacks, default is 0 + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * DO NOT CHANGE THE FOLLOWING LINES ! + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 && F_INTERRUPTS < 15000 +# warning F_INTERRUPTS too low, SIEMENS protocol disabled (should be at least 15000) +# undef IRMP_SUPPORT_SIEMENS_PROTOCOL +# define IRMP_SUPPORT_SIEMENS_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 && F_INTERRUPTS < 15000 +# warning F_INTERRUPTS too low, RUWIDO protocol disabled (should be at least 15000) +# undef IRMP_SUPPORT_RUWIDO_PROTOCOL +# define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RECS80_PROTOCOL == 1 && F_INTERRUPTS < 15000 +# warning F_INTERRUPTS too low, RECS80 protocol disabled (should be at least 15000) +# undef IRMP_SUPPORT_RECS80_PROTOCOL +# define IRMP_SUPPORT_RECS80_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 && F_INTERRUPTS < 15000 +# warning F_INTERRUPTS too low, RECS80EXT protocol disabled (should be at least 15000) +# undef IRMP_SUPPORT_RECS80EXT_PROTOCOL +# define IRMP_SUPPORT_RECS80EXT_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 && F_INTERRUPTS < 20000 +# warning F_INTERRUPTS too low, LEGO protocol disabled (should be at least 20000) +# undef IRMP_SUPPORT_LEGO_PROTOCOL +# define IRMP_SUPPORT_LEGO_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 +# warning JVC protocol needs also NEC protocol, NEC protocol enabled +# undef IRMP_SUPPORT_NEC_PROTOCOL +# define IRMP_SUPPORT_NEC_PROTOCOL 1 +#endif + +#if IRMP_SUPPORT_NEC16_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 +# warning NEC16 protocol needs also NEC protocol, NEC protocol enabled +# undef IRMP_SUPPORT_NEC_PROTOCOL +# define IRMP_SUPPORT_NEC_PROTOCOL 1 +#endif + +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 +# warning NEC42 protocol needs also NEC protocol, NEC protocol enabled +# undef IRMP_SUPPORT_NEC_PROTOCOL +# define IRMP_SUPPORT_NEC_PROTOCOL 1 +#endif + +#if F_INTERRUPTS > 20000 +#error F_INTERRUPTS too high (should be not greater than 20000) +#endif + +#endif /* _WC_IRMPCONFIG_H_ */ diff --git a/libarmbox/lirmp_input.cpp b/libarmbox/lirmp_input.cpp new file mode 100644 index 0000000..73dcc06 --- /dev/null +++ b/libarmbox/lirmp_input.cpp @@ -0,0 +1,445 @@ +/* + * Simulate a linux input device via uinput + * Get lirc remote events, decode with IRMP and inject them via uinput + * + * (C) 2012 Stefan Seyfried + * + * 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, see . + */ + +/* the C++ compiler did not like this code, so let's put it into a + * separate file and compile with gcc insead of g++... + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "lirmp_input.h" +extern "C" { +#include "irmp.h" +} +static uint8_t IRMP_PIN; + +#include +#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args) +#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args) + +/* same defines as in neutrino's rcinput.h */ +#define KEY_TTTV KEY_FN_1 +#define KEY_TTZOOM KEY_FN_2 +#define KEY_REVEAL KEY_FN_D +/* only defined in newer kernels / headers... */ +#ifndef KEY_ZOOMIN +#define KEY_ZOOMIN KEY_FN_E +#endif +#ifndef KEY_ZOOMOUT +#define KEY_ZOOMOUT KEY_FN_F +#endif + +typedef struct { + uint16_t ir; /* IR command */ + int code; /* input key code */ +} key_map_t; + +static const key_map_t key_map[] = { + { 0x13, KEY_0 }, + { 0x1a, KEY_1 }, + { 0x1f, KEY_2 }, + { 0x58, KEY_3 }, + { 0x16, KEY_4 }, + { 0x1b, KEY_5 }, + { 0x54, KEY_6 }, + { 0x12, KEY_7 }, + { 0x17, KEY_8 }, + { 0x50, KEY_9 }, + { 0x5f, KEY_OK }, + { 0x59, KEY_TIME }, + { 0x43, KEY_FAVORITES }, + { 0x4f, KEY_SAT }, + { 0x0f, KEY_NEXT }, /* V.Format */ + { 0x1e, KEY_POWER }, + { 0x5a, KEY_MUTE }, + { 0x1c, KEY_MENU }, + { 0x5d, KEY_EPG }, + { 0x07, KEY_INFO }, + { 0x60, KEY_EXIT }, + { 0x48, KEY_PAGEUP }, + { 0x44, KEY_PAGEDOWN }, + { 0x02, KEY_LEFT }, + { 0x40, KEY_RIGHT }, + { 0x03, KEY_UP }, + { 0x5e, KEY_DOWN }, + { 0x0a, KEY_VOLUMEUP }, + { 0x06, KEY_VOLUMEDOWN }, + { 0x49, KEY_RED }, + { 0x4e, KEY_GREEN }, + { 0x11, KEY_YELLOW }, + { 0x4a, KEY_BLUE }, + { 0x4c, KEY_TV }, /* TV/Radio */ + { 0x5c, KEY_VIDEO }, /* FIND */ + { 0x19, KEY_AUDIO }, /* FOLDER */ +/* KEY_AUX, + KEY_TEXT, + KEY_TTTV, + KEY_TTZOOM, + KEY_REVEAL, +*/ + { 0x01, KEY_REWIND }, + { 0x53, KEY_FORWARD }, + { 0x22, KEY_STOP }, + { 0x4d, KEY_PAUSE }, + { 0x15, KEY_PLAY }, + { 0x20, KEY_PREVIOUS }, + { 0x23, KEY_NEXT }, +// KEY_EJECTCD, + { 0x10, KEY_RECORD } +}; + +static const int key_list[] = { + KEY_0, + KEY_1, + KEY_2, + KEY_3, + KEY_4, + KEY_5, + KEY_6, + KEY_7, + KEY_8, + KEY_9, + KEY_OK, + KEY_TIME, + KEY_FAVORITES, + KEY_SAT, + KEY_ZOOMOUT, + KEY_ZOOMIN, + KEY_NEXT, + KEY_POWER, + KEY_MUTE, + KEY_MENU, + KEY_EPG, + KEY_INFO, + KEY_EXIT, + KEY_PAGEUP, + KEY_PAGEDOWN, + KEY_LEFT, + KEY_RIGHT, + KEY_UP, + KEY_DOWN, + KEY_VOLUMEUP, + KEY_VOLUMEDOWN, + KEY_RED, + KEY_GREEN, + KEY_YELLOW, + KEY_BLUE, + KEY_TV, + KEY_VIDEO, + KEY_AUDIO, +// KEY_AUX, +// KEY_TEXT, +// KEY_TTTV, +// KEY_TTZOOM, +// KEY_REVEAL, + KEY_REWIND, + KEY_STOP, + KEY_PAUSE, + KEY_PLAY, + KEY_FORWARD, + KEY_PREVIOUS, + KEY_NEXT, +// KEY_EJECTCD, + KEY_RECORD, + -1 +}; + +static pthread_t thread; +static int thread_running; + +static void *input_thread(void *) +{ + int uinput; + struct input_event u; + struct uinput_user_dev ud; + FILE *f; + int lircfd; + int pulse; + int i = 0; + int last_pulse = 1; + int last_code = -1; + uint32_t lircdata; /* lirc_t to be correct... */ + unsigned int count = 0; /* how many timeouts? */ + unsigned int nodec = 0; /* how many timeouts since last decoded? */ + int aotom_fd = -1; + IRMP_DATA d; + + lt_info("LIRC/IRMP input converter thread starting...\n"); + + /* modprobe does not complain if the module is already loaded... */ + system("/sbin/modprobe uinput"); + do { + usleep(100000); /* mdev needs some time to create the device? */ + uinput = open("/dev/uinput", O_WRONLY|O_NDELAY); + } while (uinput < 0 && ++count < 100); + + if (uinput < 0) + { + lt_info("LIRC/IRMP input thread: unable to open /dev/uinput (%m)\n"); + thread_running = 2; + return NULL; + } + + fcntl(uinput, F_SETFD, FD_CLOEXEC); + ioctl(uinput, UI_SET_EVBIT, EV_KEY); + /* do not use kernel repeat EV_REP since neutrino will be confused by the + * generated SYN_REPORT events... + ioctl(uinput, UI_SET_EVBIT, EV_REP); + */ + /* register keys */ + for (i = 0; key_list[i] != -1; i++) + ioctl(uinput, UI_SET_KEYBIT, key_list[i]); + + /* configure the device */ + memset(&ud, 0, sizeof(ud)); + strncpy(ud.name, "Neutrino LIRC/IRMP to Input Device converter", UINPUT_MAX_NAME_SIZE); + ud.id.version = 0x42; + ud.id.vendor = 0x1234; + ud.id.product = 0x5678; + ud.id.bustype = BUS_I2C; /* ?? */ + write(uinput, &ud, sizeof(ud)); + + if (ioctl(uinput, UI_DEV_CREATE)) + { + lt_info("LIRC/IRMP input thread UI_DEV_CREATE: %m\n"); + close(uinput); + return NULL; + } + + /* this is ugly: parse the new input device from /proc/...devices + * and symlink it to /dev/input/nevis_ir... */ +#define DEVLINE "I: Bus=0018 Vendor=1234 Product=5678 Version=0042" + f = fopen("/proc/bus/input/devices", "r"); + if (f) + { + int found = 0; + int evdev = -1; + size_t n = 0; + char *line = NULL; + char *p; + char newdev[20]; + while (getline(&line, &n, f) != -1) + { + switch(line[0]) + { + case 'I': + if (strncmp(line, DEVLINE, strlen(DEVLINE)) == 0) + found = 1; + break; + case 'H': + if (! found) + break; + p = strstr(line, " event"); + if (! p) + { + evdev = -1; + break; + } + evdev = atoi(p + 6); + sprintf(newdev, "event%d", evdev); + lt_info("LIRC/IRMP input thread: symlink /dev/input/nevis_ir to %s\n", newdev); + unlink("/dev/input/nevis_ir"); + symlink(newdev, "/dev/input/nevis_ir"); + break; + default: + break; + } + if (evdev != -1) + break; + } + fclose(f); + free(line); + } + + u.type = EV_KEY; + u.value = 0; /* initialize: first event wil be a key press */ + + lircfd = open("/dev/lirc", O_RDONLY); + if (lircfd < 0) + { + lt_info("%s: open /dev/lirc: %m\n", __func__); + goto out; + } + IRMP_PIN = 0xFF; + +/* 50 ms. This should be longer than the longest light pulse */ +#define POLL_MS (100 * 1000) +#define LIRC_PULSE 0x01000000 +#define LIRC_PULSE_MASK 0x00FFFFFF + lt_info("LIRC/IRMP input converter going into main loop...\n"); + + aotom_fd = open("/dev/vfd", O_RDONLY); + + /* TODO: ioctl to find out if we have a compatible LIRC_MODE2 device */ + thread_running = 1; + while (thread_running) + { + fd_set fds; + struct timeval tv; + int ret; + + FD_ZERO(&fds); + FD_SET(lircfd, &fds); + tv.tv_sec = 0; + tv.tv_usec = POLL_MS; + /* any singal can interrupt select. we rely on the linux-only feature + * that the timeout is automatcally recalculated in this case! */ + do { + ret = select(lircfd + 1, &fds, NULL, NULL, &tv); + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + /* errno != EINTR... */ + lt_info("%s: lirmp: lircfd select: %m\n", __func__); + break; + } + + if (ret == 0) + { + count++; + nodec++; + lircdata = POLL_MS; /* timeout */ + pulse = !last_pulse; /* lirc sends data on signal change */ + if (last_code != -1 && nodec > 1) + { + // fprintf(stderr, "timeout!\n"); + u.code = last_code; + u.value = 0; /* release */ + write(uinput, &u, sizeof(u)); + last_code = -1; + } + } + else + { + if (read(lircfd, &lircdata, sizeof(lircdata)) != sizeof(lircdata)) + { + perror("read"); + break; + } + pulse = (lircdata & LIRC_PULSE); /* we got light... */ + last_pulse = pulse; + lircdata &= LIRC_PULSE_MASK; /* how long the pulse was in microseconds */ + } + + if (ret && count) + { + if (count * POLL_MS > lircdata) + lircdata = 0; + else + lircdata -= count * POLL_MS; + count = 0; + } + //printf("lircdata: ret:%d c:%d %d\n", ret, ch - '0', lircdata); + lircdata /= (1000000 / F_INTERRUPTS); + + if (pulse) + IRMP_PIN = 0x00; + else + IRMP_PIN = 0xff; + + do { + (void) irmp_ISR (IRMP_PIN); + if (irmp_get_data (&d)) + { + nodec = 0; + lt_debug("irmp_get_data proto: %2d addr: 0x%04x cmd: 0x%04x fl: %d\n", + d.protocol, d.address, d.command, d.flags); + + /* todo: do we need to complete the loop if we already + * detected the singal in this pulse? */ + if (d.protocol == IRMP_NEC_PROTOCOL && d.address == 0xba45) + { + for (i = 0; i < (int)(sizeof(key_map)/sizeof(key_map_t)); i++) + { + if (key_map[i].ir == d.command) + { + if (last_code != -1 && last_code != key_map[i].code) + { + u.code = last_code; + u.value = 0; + write(uinput, &u, sizeof(u)); + } + u.code = key_map[i].code; + u.value = (d.flags & 0x1) + 1; + //lt_debug("uinput write: value: %d code: %d\n", u.value, u.code); + last_code = u.code; + write(uinput, &u, sizeof(u)); + if (aotom_fd > -1) { + struct aotom_ioctl_data vfd_data; + vfd_data.u.led.led_nr = 1; + vfd_data.u.led.on = 10; + ioctl(aotom_fd, VFDSETLED, &vfd_data); + } + break; + } + } + } + } + } while (lircdata-- > 0); + } + /* clean up */ + close (lircfd); + + if (aotom_fd > -1) + close(aotom_fd); + + out: + ioctl(uinput, UI_DEV_DESTROY); + return NULL; +} + +void start_input_thread(void) +{ + if (pthread_create(&thread, 0, input_thread, NULL) != 0) + { + lt_info("%s: LIRC/IRMP input thread pthread_create: %m\n", __func__); + thread_running = 0; + return; + } + /* wait until the device is created before continuing */ + while (! thread_running) + usleep(1000); + if (thread_running == 2) /* failed... :-( */ + thread_running = 0; +} + +void stop_input_thread(void) +{ + if (! thread_running) + return; + thread_running = 0; + pthread_join(thread, NULL); +} diff --git a/libarmbox/lirmp_input.h b/libarmbox/lirmp_input.h new file mode 100644 index 0000000..c277dda --- /dev/null +++ b/libarmbox/lirmp_input.h @@ -0,0 +1,7 @@ +/* functions from lirmp_input.cpp */ + +#ifndef __LIRMP_INPUT_H_ +#define __LIRMP_INPUT_H_ +void start_input_thread(void); +void stop_input_thread(void); +#endif diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp new file mode 100644 index 0000000..53d9a5c --- /dev/null +++ b/libarmbox/playback_gst.cpp @@ -0,0 +1,837 @@ +/* + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include "dmx_lib.h" +#include "audio_lib.h" +#include "video_lib.h" + +#include "playback_gst.h" + +#include "lt_debug.h" +#define lt_debug(args...) _lt_debug(HAL_DEBUG_PLAYBACK, this, args) +#define lt_info(args...) _lt_info(HAL_DEBUG_PLAYBACK, this, args) +#define lt_debug_c(args...) _lt_debug(HAL_DEBUG_PLAYBACK, NULL, args) +#define lt_info_c(args...) _lt_info(HAL_DEBUG_PLAYBACK, NULL, args) + +static const char * FILENAME = "[playback.cpp]"; + +#include +#include + +typedef enum +{ + GST_PLAY_FLAG_VIDEO = 0x00000001, + GST_PLAY_FLAG_AUDIO = 0x00000002, + GST_PLAY_FLAG_TEXT = 0x00000004, + GST_PLAY_FLAG_VIS = 0x00000008, + GST_PLAY_FLAG_SOFT_VOLUME = 0x00000010, + GST_PLAY_FLAG_NATIVE_AUDIO = 0x00000020, + GST_PLAY_FLAG_NATIVE_VIDEO = 0x00000040, + GST_PLAY_FLAG_DOWNLOAD = 0x00000080, + GST_PLAY_FLAG_BUFFERING = 0x000000100 +} GstPlayFlags; + + +GstElement * m_gst_playbin = NULL; +GstElement * audioSink = NULL; +GstElement * videoSink = NULL; +gchar * uri = NULL; +GstTagList * m_stream_tags = 0; +static int end_eof = 0; + +gint match_sinktype(const GValue *velement, const gchar *type) +{ + GstElement *element = GST_ELEMENT_CAST(g_value_get_object(velement)); + return strcmp(g_type_name(G_OBJECT_TYPE(element)), type); +} + +GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) +{ + gchar * sourceName; + + // source + GstObject * source; + source = GST_MESSAGE_SRC(msg); + + if (!GST_IS_OBJECT(source)) + return GST_BUS_DROP; + + sourceName = gst_object_get_name(source); + + switch (GST_MESSAGE_TYPE(msg)) + { + case GST_MESSAGE_EOS: + { + g_message("End-of-stream"); + end_eof = 1; + break; + } + + case GST_MESSAGE_ERROR: + { + gchar * debug; + GError *err; + gst_message_parse_error(msg, &err, &debug); + g_free (debug); + lt_info_c( "%s:%s - GST_MESSAGE_ERROR: %s (%i) from %s\n", FILENAME, __FUNCTION__, err->message, err->code, sourceName ); + if ( err->domain == GST_STREAM_ERROR ) + { + if ( err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND ) + { + if ( g_strrstr(sourceName, "videosink") ) + lt_info_c( "%s:%s - GST_MESSAGE_ERROR: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? + else if ( g_strrstr(sourceName, "audiosink") ) + lt_info_c( "%s:%s - GST_MESSAGE_ERROR: audioSink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? + } + } + g_error_free(err); + + end_eof = 1; // NOTE: just to exit + + break; + } + + case GST_MESSAGE_INFO: + { + gchar *debug; + GError *inf; + + gst_message_parse_info (msg, &inf, &debug); + g_free (debug); + if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE ) + { + if ( g_strrstr(sourceName, "videosink") ) + lt_info_c( "%s:%s - GST_MESSAGE_INFO: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? + } + g_error_free(inf); + break; + } + + case GST_MESSAGE_TAG: + { + GstTagList *tags, *result; + gst_message_parse_tag(msg, &tags); + + result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE); + if (result) + { + if (m_stream_tags) + gst_tag_list_free(m_stream_tags); + m_stream_tags = result; + } + + const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0); + if ( gv_image ) + { + GstBuffer *buf_image; + buf_image = gst_value_get_buffer (gv_image); + int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644); + if(fd >= 0) + { + GstMapInfo Info; + gst_buffer_map(buf_image, &Info,(GstMapFlags)( GST_MAP_READ)); + int ret = write(fd, Info.data, Info.size); + close(fd); + gst_buffer_unmap(buf_image, &Info); + lt_info_c( "%s:%s - GST_MESSAGE_INFO: cPlayback::state /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__ , ret); + } + //FIXME: how shall playback handle this event??? + } + gst_tag_list_free(tags); + lt_debug_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event??? + break; + } + + case GST_MESSAGE_STATE_CHANGED: + { + if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) + break; + + GstState old_state, new_state; + gst_message_parse_state_changed(msg, &old_state, &new_state, NULL); + + if(old_state == new_state) + break; + lt_info_c( "%s:%s - GST_MESSAGE_STATE_CHANGED: state transition %s -> %s\n", FILENAME, __FUNCTION__, gst_element_state_get_name(old_state), gst_element_state_get_name(new_state)); + + GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state); + + switch(transition) + { + case GST_STATE_CHANGE_NULL_TO_READY: + { + } break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + { + GstIterator *children; + if (audioSink) + { + gst_object_unref(GST_OBJECT(audioSink)); + audioSink = NULL; + } + + if (videoSink) + { + gst_object_unref(GST_OBJECT(videoSink)); + videoSink = NULL; + } + children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); + GValue r = G_VALUE_INIT; + gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink"); + audioSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); + g_value_unset (&r); + gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink"); + videoSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); + g_value_unset (&r); + gst_iterator_free(children); + + } break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + { + } break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + { + } break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + { + if (audioSink) + { + gst_object_unref(GST_OBJECT(audioSink)); + audioSink = NULL; + } + if (videoSink) + { + gst_object_unref(GST_OBJECT(videoSink)); + videoSink = NULL; + } + } break; + case GST_STATE_CHANGE_READY_TO_NULL: + { + } break; + } + break; + } + break; + default: + break; + } + + return GST_BUS_DROP; +} + + +cPlayback::cPlayback(int num) +{ + lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + const gchar *nano_str; + guint major, minor, micro, nano; + + gst_init(NULL, NULL); + + gst_version (&major, &minor, µ, &nano); + + if (nano == 1) + nano_str = "(CVS)"; + else if (nano == 2) + nano_str = "(Prerelease)"; + else + nano_str = ""; + + lt_info( "%s:%s - This program is linked against GStreamer %d.%d.%d %s\n", + FILENAME, __FUNCTION__, + major, minor, micro, nano_str); + + mAudioStream = 0; + mSpeed = 0; + + playing = false; + playstate = STATE_STOP; +} + +cPlayback::~cPlayback() +{ + lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + //FIXME: all deleting stuff is done in Close() +} + +//Used by Fileplay +bool cPlayback::Open(playmode_t PlayMode) +{ + lt_info("%s: PlayMode %d\n", __func__, PlayMode); + return true; +} + +// used by movieplay +void cPlayback::Close(void) +{ + lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + + Stop(); + + // disconnect bus handler + if (m_gst_playbin) + { + // disconnect sync handler callback + GstBus * bus = gst_pipeline_get_bus(GST_PIPELINE (m_gst_playbin)); + gst_bus_set_sync_handler(bus, NULL, NULL, NULL); + gst_object_unref(bus); + lt_info( "%s:%s - GST bus handler closed\n", FILENAME, __FUNCTION__); + } + + if (m_stream_tags) + gst_tag_list_free(m_stream_tags); + + // close gst + if (m_gst_playbin) + { + if (audioSink) + { + gst_object_unref(GST_OBJECT(audioSink)); + audioSink = NULL; + + lt_info( "%s:%s - GST audio Sink closed\n", FILENAME, __FUNCTION__); + } + + if (videoSink) + { + gst_object_unref(GST_OBJECT(videoSink)); + videoSink = NULL; + + lt_info( "%s:%s - GST video Sink closed\n", FILENAME, __FUNCTION__); + } + + // unref m_gst_playbin + gst_object_unref (GST_OBJECT (m_gst_playbin)); + lt_info( "%s:%s - GST playbin closed\n", FILENAME, __FUNCTION__); + + m_gst_playbin = NULL; + } +} + +// start +bool cPlayback::Start(std::string filename, std::string headers) +{ + return Start((char*) filename.c_str(),0,0,0,0,0, headers); +} + +bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, int /*ac3*/, int /*duration*/, std::string headers) +{ + lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + + mAudioStream = 0; + + //create playback path + char file[400] = {""}; + bool isHTTP = false; + + if(!strncmp("http://", filename, 7)) + { + isHTTP = true; + } + else if(!strncmp("file://", filename, 7)) + { + isHTTP = false; + } + else if(!strncmp("upnp://", filename, 7)) + { + isHTTP = true; + } + else if(!strncmp("rtmp://", filename, 7)) + { + isHTTP = true; + } + else if(!strncmp("rtsp://", filename, 7)) + { + isHTTP = true; + } + else if(!strncmp("mms://", filename, 6)) + { + isHTTP = true; + } + else + strcat(file, "file://"); + + strcat(file, filename); + + if (isHTTP) + uri = g_uri_escape_string(filename, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS, true); + else + uri = g_filename_to_uri(filename, NULL, NULL); + + lt_info("%s:%s - filename=%s\n", FILENAME, __FUNCTION__, filename); + + // create gst pipeline + m_gst_playbin = gst_element_factory_make ("playbin", "playbin"); + + if(m_gst_playbin) + { + lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__); + + guint flags; + g_object_get(G_OBJECT (m_gst_playbin), "flags", &flags, NULL); + /* avoid video conversion, let the (hardware) sinks handle that */ + flags |= GST_PLAY_FLAG_NATIVE_VIDEO; + /* volume control is done by hardware */ + flags &= ~GST_PLAY_FLAG_SOFT_VOLUME; + + g_object_set(G_OBJECT (m_gst_playbin), "uri", uri, NULL); + g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL); + + //gstbus handler + GstBus * bus = gst_pipeline_get_bus( GST_PIPELINE(m_gst_playbin) ); + gst_bus_set_sync_handler(bus, Gst_bus_call, NULL, NULL); + gst_object_unref(bus); + + // state playing + gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + + playing = true; + playstate = STATE_PLAY; + } + else + { + lt_info("%s:%s - failed to create GStreamer pipeline!, sorry we can not play\n", FILENAME, __FUNCTION__); + playing = false; + + return false; + } + + g_free(uri); + + // set buffer size + /* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */ + int m_buffer_size = 5*1024*1024; + //g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL); + g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL); + + return true; +} + +bool cPlayback::Play(void) +{ + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + if(playing == true) + return true; + + if(m_gst_playbin) + { + gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING); + + playing = true; + playstate = STATE_PLAY; + } + lt_info("%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + return playing; +} + +bool cPlayback::Stop(void) +{ + if(playing == false) + return false; + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + // stop + if(m_gst_playbin) + { + gst_element_set_state(m_gst_playbin, GST_STATE_NULL); + } + + playing = false; + + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + playstate = STATE_STOP; + + return true; +} + +bool cPlayback::SetAPid(int pid , bool /*ac3*/) +{ + lt_info("%s: pid %i\n", __func__, pid); + + int current_audio; + + if(pid != mAudioStream) + { + g_object_set (G_OBJECT (m_gst_playbin), "current-audio", pid, NULL); + printf("%s: switched to audio stream %i\n", __FUNCTION__, pid); + mAudioStream = pid; + } + + return true; +} + +void cPlayback::trickSeek(int ratio) +{ + bool validposition = false; + gint64 pos = 0; + int position; + int duration; + + if( GetPosition(position, duration) ) + { + validposition = true; + pos = position; + } + + gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + + if (validposition) + { + if(ratio >= 0.0) + gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1); + else + gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos); + } +} + +bool cPlayback::SetSpeed(int speed) +{ + lt_info( "%s:%s speed %d\n", FILENAME, __FUNCTION__, speed); + + if(playing == false) + return false; + + if(m_gst_playbin) + { + // pause + if(speed == 0) + { + gst_element_set_state(m_gst_playbin, GST_STATE_PAUSED); + //trickSeek(0); + playstate = STATE_PAUSE; + } + // play/continue + else if(speed == 1) + { + trickSeek(1); + //gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + // + playstate = STATE_PLAY; + } + //ff + else if(speed > 1) + { + trickSeek(speed); + // + playstate = STATE_FF; + } + //rf + else if(speed < 0) + { + trickSeek(speed); + // + playstate = STATE_REW; + } + } + + mSpeed = speed; + + return true; +} + +bool cPlayback::SetSlow(int slow) +{ + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + if(playing == false) + return false; + + if(m_gst_playbin) + { + trickSeek(0.5); + } + + playstate = STATE_SLOW; + + mSpeed = slow; + + return true; +} + +bool cPlayback::GetSpeed(int &speed) const +{ + speed = mSpeed; + + return true; +} + +// in milliseconds +bool cPlayback::GetPosition(int &position, int &duration) +{ + if(playing == false) + return false; + + //EOF + if(end_eof) + { + end_eof = 0; + return false; + } + + if(m_gst_playbin) + { + //position + GstFormat fmt = GST_FORMAT_TIME; //Returns time in nanosecs + + gint64 pts = 0; + unsigned long long int sec = 0; + + gst_element_query_position(m_gst_playbin, fmt, &pts); + position = pts / 1000000.0; + + // duration + GstFormat fmt_d = GST_FORMAT_TIME; //Returns time in nanosecs + double length = 0; + gint64 len; + + gst_element_query_duration(m_gst_playbin, fmt_d, &len); + length = len / 1000000.0; + if(length < 0) + length = 0; + + duration = (int)(length); + } + + return true; +} + +bool cPlayback::SetPosition(int position, bool absolute) +{ + lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing); + + if(playing == false) + return false; + + gint64 time_nanoseconds; + gint64 pos; + GstFormat fmt = GST_FORMAT_TIME; + + if(m_gst_playbin) + { + gst_element_query_position(m_gst_playbin, fmt, &pos); + time_nanoseconds = pos + (position * 1000000.0); + if(time_nanoseconds < 0) + time_nanoseconds = 0; + + gst_element_seek(m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + } + + return true; +} + +void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string * language) +{ + lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + + if(m_gst_playbin) + { + gint i, n_audio = 0; + //GstStructure * structure = NULL; + + // get audio + g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL); + printf("%s: %d audio\n", __FUNCTION__, n_audio); + + if(n_audio == 0) + return; + + for (i = 0; i < n_audio; i++) + { + // apids + apids[i]=i; + + GstPad * pad = 0; + g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad); + GstCaps * caps = gst_pad_get_current_caps(pad); + if (!caps) + continue; + + GstStructure * structure = gst_caps_get_structure(caps, 0); + //const gchar *g_type = gst_structure_get_name(structure); + + //if (!structure) + //return atUnknown; + //ac3flags[0] = 0; + + // ac3flags + if ( gst_structure_has_name (structure, "audio/mpeg")) + { + gint mpegversion, layer = -1; + + if (!gst_structure_get_int (structure, "mpegversion", &mpegversion)) + //return atUnknown; + ac3flags[i] = 0; + + switch (mpegversion) + { + case 1: + /* + { + gst_structure_get_int (structure, "layer", &layer); + if ( layer == 3 ) + return atMP3; + else + return atMPEG; + ac3flags[0] = 4; + break; + } + */ + ac3flags[i] = 4; + case 2: + //return atAAC; + ac3flags[i] = 5; + case 4: + //return atAAC; + ac3flags[i] = 5; + default: + //return atUnknown; + ac3flags[i] = 0; + } + } + else if ( gst_structure_has_name (structure, "audio/x-ac3") || gst_structure_has_name (structure, "audio/ac3") ) + //return atAC3; + ac3flags[i] = 1; + else if ( gst_structure_has_name (structure, "audio/x-dts") || gst_structure_has_name (structure, "audio/dts") ) + //return atDTS; + ac3flags[i] = 6; + else if ( gst_structure_has_name (structure, "audio/x-raw-int") ) + //return atPCM; + ac3flags[i] = 0; + + gst_caps_unref(caps); + } + + // numpids + *numpida=i; + } +} + +void cPlayback::getMeta() +{ + if(playing) + return; +} + +bool cPlayback::SyncAV(void) +{ + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + + if(playing == false ) + return false; + + return true; +} + +void cPlayback::RequestAbort() +{ +} + +void cPlayback::FindAllSubs(uint16_t *, unsigned short *, uint16_t *numpida, std::string *) +{ + printf("%s:%s\n", FILENAME, __func__); + *numpida = 0; +} + +void cPlayback::GetChapters(std::vector &positions, std::vector &titles) +{ + positions.clear(); + titles.clear(); +} + +bool cPlayback::SelectSubtitles(int pid) +{ + printf("%s:%s pid %i\n", FILENAME, __func__, pid); + return true; +} + +void cPlayback::GetMetadata(std::vector &keys, std::vector &values) +{ + keys.clear(); + values.clear(); +} + +void cPlayback::FindAllTeletextsubtitlePids(int *, unsigned int *numpids, std::string *, int *, int *) +{ + *numpids = 0; +} + +void cPlayback::FindAllSubtitlePids(int * /*pids*/, unsigned int *numpids, std::string * /*language*/) +{ + *numpids = 0; +} + +bool cPlayback::SetSubtitlePid(int /*pid*/) +{ + return true; +} + +void cPlayback::GetPts(uint64_t &/*pts*/) +{ +} + +bool cPlayback::SetTeletextPid(int /*pid*/) +{ + return true; +} + +uint64_t cPlayback::GetReadCount() +{ + return 0; +} + +int cPlayback::GetAPid(void) +{ + lt_info("%s\n", __func__); + return 0; +} + +int cPlayback::GetVPid(void) +{ + return 0; +} + +int cPlayback::GetSubtitlePid(void) +{ + return 0; +} + +AVFormatContext *cPlayback::GetAVFormatContext() +{ + return NULL; +} + +void cPlayback::ReleaseAVFormatContext() +{ +} diff --git a/libarmbox/playback_gst.h b/libarmbox/playback_gst.h new file mode 100644 index 0000000..25331bd --- /dev/null +++ b/libarmbox/playback_gst.h @@ -0,0 +1,97 @@ +/* + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __PLAYBACK_CS_H +#define __PLAYBACK_CS_H + +#include +#include +#include + +#include + + +typedef enum { + STATE_STOP, + STATE_PLAY, + STATE_PAUSE, + STATE_FF, + STATE_REW, + STATE_SLOW +} playstate_t; + +typedef enum { + PLAYMODE_TS = 0, + PLAYMODE_FILE, +} playmode_t; + +struct AVFormatContext; + +class cPlayback +{ + private: + bool playing; + + int mSpeed; + int mAudioStream; + + public: + playstate_t playstate; + + cPlayback(int); + bool Open(playmode_t PlayMode); + void Close(void); + bool Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = ""); + bool Start(std::string filename, std::string headers = ""); + bool Play(void); + bool SyncAV(void); + + bool Stop(void); + bool SetAPid(int pid, bool ac3); + bool SetSubtitlePid(int pid); + bool SetTeletextPid(int pid); + + void trickSeek(int ratio); + bool SetSpeed(int speed); + bool SetSlow(int slow); + bool GetSpeed(int &speed) const; + bool GetPosition(int &position, int &duration); + void GetPts(uint64_t &pts); + int GetAPid(void); + int GetVPid(void); + int GetSubtitlePid(void); + bool SetPosition(int position, bool absolute = false); + void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language); + void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language); + void FindAllTeletextsubtitlePids(int *pids, unsigned int *numpidt, std::string *tlanguage, int *mags, int *pages); + void RequestAbort(void); + void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language); + bool SelectSubtitles(int pid); + uint64_t GetReadCount(void); + void GetChapters(std::vector &positions, std::vector &titles); + void GetMetadata(std::vector &keys, std::vector &values); + AVFormatContext *GetAVFormatContext(); + void ReleaseAVFormatContext(); + + // + ~cPlayback(); + void getMeta(); +}; + +#endif + diff --git a/libarmbox/pwrmngr.cpp b/libarmbox/pwrmngr.cpp new file mode 100644 index 0000000..b5ab30a --- /dev/null +++ b/libarmbox/pwrmngr.cpp @@ -0,0 +1,102 @@ +#include + +#include "pwrmngr.h" +#include "lt_debug.h" +#include +#include +#include +#include +#include + +#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_PWRMNGR, this, args) +void cCpuFreqManager::Up(void) { lt_debug("%s\n", __FUNCTION__); } +void cCpuFreqManager::Down(void) { lt_debug("%s\n", __FUNCTION__); } +void cCpuFreqManager::Reset(void) { lt_debug("%s\n", __FUNCTION__); } +/* those function dummies return true or "harmless" values */ +bool cCpuFreqManager::SetDelta(unsigned long) { lt_debug("%s\n", __FUNCTION__); return true; } +#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE +unsigned long cCpuFreqManager::GetCpuFreq(void) { + int freq = 0; + if (FILE *pll0 = fopen("/proc/cpu_frequ/pll0_ndiv_mdiv", "r")) { + char buffer[120]; + while(fgets(buffer, sizeof(buffer), pll0)) { + if (1 == sscanf(buffer, "SH4 = %d MHZ", &freq)) + break; + } + fclose(pll0); + return 1000 * 1000 * (unsigned long) freq; + } + return 0; +} +#else +unsigned long cCpuFreqManager::GetCpuFreq(void) { lt_debug("%s\n", __FUNCTION__); return 0; } +#endif +unsigned long cCpuFreqManager::GetDelta(void) { lt_debug("%s\n", __FUNCTION__); return 0; } +// +cCpuFreqManager::cCpuFreqManager(void) { lt_debug("%s\n", __FUNCTION__); } + +bool cPowerManager::SetState(PWR_STATE) { lt_debug("%s\n", __FUNCTION__); return true; } + +bool cPowerManager::Open(void) { lt_debug("%s\n", __FUNCTION__); return true; } +void cPowerManager::Close(void) { lt_debug("%s\n", __FUNCTION__); } +// +bool cPowerManager::SetStandby(bool Active, bool Passive) +{ + lt_debug("%s(%d, %d)\n", __FUNCTION__, Active, Passive); + return true; +} + +bool cCpuFreqManager::SetCpuFreq(unsigned long f) +{ +#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE + if (f) { + FILE *pll0 = fopen ("/proc/cpu_frequ/pll0_ndiv_mdiv", "w"); + if (pll0) { + f /= 1000000; + fprintf(pll0, "%lu\n", (f/10 << 8) | 3); + fclose (pll0); + return false; + } + } +#else + /* actually SetCpuFreq is used to determine if the system is in standby + this is an "elegant" hack, because: + * during a recording, cpu freq is kept "high", even if the box is sent to standby + * the "SetStandby" call is made even if a recording is running + On the TD, setting standby disables the frontend, so we must not do it + if a recording is running. + For now, the values in neutrino are hardcoded: + * f == 0 => max => not standby + * f == 50000000 => min => standby + */ + lt_debug("%s(%lu) => set standby = %s\n", __FUNCTION__, f, f?"true":"false"); +#if 0 + int fd = open("/dev/stb/tdsystem", O_RDONLY); + if (fd < 0) + { + perror("open tdsystem"); + return false; + } + if (f) + { + ioctl(fd, IOC_AVS_SET_VOLUME, 31); /* mute AVS to avoid ugly noise */ + ioctl(fd, IOC_AVS_STANDBY_ENTER); + } + else + { + ioctl(fd, IOC_AVS_SET_VOLUME, 31); /* mute AVS to avoid ugly noise */ + ioctl(fd, IOC_AVS_STANDBY_LEAVE); + /* unmute will be done by cAudio::do_mute(). Ugly, but prevents pops */ + // ioctl(fd, IOC_AVS_SET_VOLUME, 0); /* max gain */ + } + + close(fd); +#endif +#endif + return true; +} + +// +cPowerManager::cPowerManager(void) { lt_debug("%s\n", __FUNCTION__); } +cPowerManager::~cPowerManager() { lt_debug("%s\n", __FUNCTION__); } + diff --git a/libarmbox/pwrmngr.h b/libarmbox/pwrmngr.h new file mode 100644 index 0000000..55dc984 --- /dev/null +++ b/libarmbox/pwrmngr.h @@ -0,0 +1,53 @@ +#ifndef __PWRMNGR_H__ +#define __PWRMNGR_H__ + +// -- cCpuFreqManager ---------------------------------------------------------- + +class cCpuFreqManager { +private: + unsigned long startCpuFreq; + unsigned long delta; +public: + void Up(void); + void Down(void); + void Reset(void); + // + bool SetCpuFreq(unsigned long CpuFreq); + bool SetDelta(unsigned long Delta); + unsigned long GetCpuFreq(void); + unsigned long GetDelta(void); + // + cCpuFreqManager(void); + +}; + +// -- cPowerManageger ---------------------------------------------------------- + +typedef enum +{ + PWR_INIT = 1, + PWR_FULL_ACTIVE, /* all devices/clocks up */ + PWR_ACTIVE_STANDBY, + PWR_PASSIVE_STANDBY, + PWR_INVALID +} PWR_STATE; + +class cPowerManager { +private: + bool init; + bool opened; + PWR_STATE powerState; + // + static void ApplicationCallback(void *, void *, signed long, void *, void *) {} + bool SetState(PWR_STATE PowerState); +public: + bool Open(void); + void Close(void); + // + bool SetStandby(bool Active, bool Passive); + // + cPowerManager(void); + virtual ~cPowerManager(); +}; + +#endif // __PWRMNGR_H__ diff --git a/libarmbox/record.cpp b/libarmbox/record.cpp new file mode 100644 index 0000000..cae962b --- /dev/null +++ b/libarmbox/record.cpp @@ -0,0 +1,383 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "record_lib.h" +#include "lt_debug.h" +#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_RECORD, this, args) +#define lt_info(args...) _lt_info(TRIPLE_DEBUG_RECORD, this, args) + +/* helper functions to call the cpp thread loops */ +void *execute_record_thread(void *c) +{ + cRecord *obj = (cRecord *)c; + obj->RecordThread(); + return NULL; +} + +void *execute_writer_thread(void *c) +{ + cRecord *obj = (cRecord *)c; + obj->WriterThread(); + return NULL; +} + +cRecord::cRecord(int num, int bs_dmx, int bs) +{ + lt_info("%s %d\n", __func__, num); + dmx = NULL; + record_thread_running = false; + file_fd = -1; + exit_flag = RECORD_STOPPED; + dmx_num = num; + bufsize = bs; + bufsize_dmx = bs_dmx; + failureCallback = NULL; + failureData = NULL; +} + +cRecord::~cRecord() +{ + lt_info("%s: calling ::Stop()\n", __func__); + Stop(); + lt_info("%s: end\n", __func__); +} + +bool cRecord::Open(void) +{ + lt_info("%s\n", __func__); + exit_flag = RECORD_STOPPED; + return true; +} + +#if 0 +// unused +void cRecord::Close(void) +{ + lt_info("%s: \n", __func__); +} +#endif + +bool cRecord::Start(int fd, unsigned short vpid, unsigned short *apids, int numpids, uint64_t) +{ + lt_info("%s: fd %d, vpid 0x%03x\n", __func__, fd, vpid); + int i; + + if (!dmx) + dmx = new cDemux(dmx_num); + + dmx->Open(DMX_TP_CHANNEL, NULL, bufsize_dmx); + dmx->pesFilter(vpid); + + for (i = 0; i < numpids; i++) + dmx->addPid(apids[i]); + + file_fd = fd; + exit_flag = RECORD_RUNNING; + if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED)) + perror("posix_fadvise"); + + i = pthread_create(&record_thread, 0, execute_record_thread, this); + if (i != 0) + { + exit_flag = RECORD_FAILED_READ; + errno = i; + lt_info("%s: error creating thread! (%m)\n", __func__); + delete dmx; + dmx = NULL; + return false; + } + record_thread_running = true; + return true; +} + +bool cRecord::Stop(void) +{ + lt_info("%s\n", __func__); + + if (exit_flag != RECORD_RUNNING) + lt_info("%s: status not RUNNING? (%d)\n", __func__, exit_flag); + + exit_flag = RECORD_STOPPED; + if (record_thread_running) + pthread_join(record_thread, NULL); + record_thread_running = false; + + /* We should probably do that from the destructor... */ + if (!dmx) + lt_info("%s: dmx == NULL?\n", __func__); + else + delete dmx; + dmx = NULL; + + if (file_fd != -1) + close(file_fd); + else + lt_info("%s: file_fd not open??\n", __func__); + file_fd = -1; + return true; +} + +bool cRecord::ChangePids(unsigned short /*vpid*/, unsigned short *apids, int numapids) +{ + std::vector pids; + int j; + bool found; + unsigned short pid; + lt_info("%s\n", __func__); + if (!dmx) { + lt_info("%s: DMX = NULL\n", __func__); + return false; + } + pids = dmx->getPesPids(); + /* the first PID is the video pid, so start with the second PID... */ + for (std::vector::const_iterator i = pids.begin() + 1; i != pids.end(); ++i) { + found = false; + pid = (*i).pid; + for (j = 0; j < numapids; j++) { + if (pid == apids[j]) { + found = true; + break; + } + } + if (!found) + dmx->removePid(pid); + } + for (j = 0; j < numapids; j++) { + found = false; + for (std::vector::const_iterator i = pids.begin() + 1; i != pids.end(); ++i) { + if ((*i).pid == apids[j]) { + found = true; + break; + } + } + if (!found) + dmx->addPid(apids[j]); + } + return true; +} + +bool cRecord::AddPid(unsigned short pid) +{ + std::vector pids; + lt_info("%s: \n", __func__); + if (!dmx) { + lt_info("%s: DMX = NULL\n", __func__); + return false; + } + pids = dmx->getPesPids(); + for (std::vector::const_iterator i = pids.begin(); i != pids.end(); ++i) { + if ((*i).pid == pid) + return true; /* or is it an error to try to add the same PID twice? */ + } + return dmx->addPid(pid); +} + +void cRecord::WriterThread() +{ + char threadname[17]; + strncpy(threadname, "WriterThread", sizeof(threadname)); + threadname[16] = 0; + prctl (PR_SET_NAME, (unsigned long)&threadname); + unsigned int chunk = 0; + while (!sem_wait(&sem)) { + if (!io_len[chunk]) // empty, assume end of recording + return; + unsigned char *p_buf = io_buf[chunk]; + size_t p_len = io_len[chunk]; + while (p_len) { + ssize_t written = write(file_fd, p_buf, p_len); + if (written < 0) + break; + p_len -= written; + p_buf += written; + } + if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED)) + perror("posix_fadvise"); + chunk++; + chunk %= RECORD_WRITER_CHUNKS; + } +} + +void cRecord::RecordThread() +{ + lt_info("%s: begin\n", __func__); + char threadname[17]; + strncpy(threadname, "RecordThread", sizeof(threadname)); + threadname[16] = 0; + prctl (PR_SET_NAME, (unsigned long)&threadname); + int readsize = bufsize/16; + int buf_pos = 0; + int count = 0; + int queued = 0; + uint8_t *buf; + struct aiocb a; + + buf = (uint8_t *)malloc(bufsize); + lt_info("BUFSIZE=0x%x READSIZE=0x%x\n", bufsize, readsize); + if (!buf) + { + exit_flag = RECORD_FAILED_MEMORY; + lt_info("%s: unable to allocate buffer! (out of memory)\n", __func__); + if (failureCallback) + failureCallback(failureData); + lt_info("%s: end\n", __func__); + pthread_exit(NULL); + } + + int val = fcntl(file_fd, F_GETFL); + if (fcntl(file_fd, F_SETFL, val|O_APPEND)) + lt_info("%s: O_APPEND? (%m)\n", __func__); + + memset(&a, 0, sizeof(a)); + a.aio_fildes = file_fd; + a.aio_sigevent.sigev_notify = SIGEV_NONE; + + dmx->Start(); + int overflow_count = 0; + bool overflow = false; + int r = 0; + while (exit_flag == RECORD_RUNNING) + { + if (buf_pos < bufsize) + { + if (overflow_count) { + lt_info("%s: Overflow cleared after %d iterations\n", __func__, overflow_count); + overflow_count = 0; + } + int toread = bufsize - buf_pos; + if (toread > readsize) + toread = readsize; + ssize_t s = dmx->Read(buf + buf_pos, toread, 50); + lt_debug("%s: buf_pos %6d s %6d / %6d\n", __func__, buf_pos, (int)s, bufsize - buf_pos); + if (s < 0) + { + if (errno != EAGAIN && (errno != EOVERFLOW || !overflow)) + { + lt_info("%s: read failed: %m\n", __func__); + exit_flag = RECORD_FAILED_READ; + break; + } + } + else + { + overflow = false; + buf_pos += s; + if (count > 100) + { + if (buf_pos < bufsize / 2) + continue; + } + else + { + count += 1; + } + } + } + else + { + if (!overflow) + overflow_count = 0; + overflow = true; + if (!(overflow_count % 10)) + lt_info("%s: buffer full! Overflow? (%d)\n", __func__, ++overflow_count); + } + r = aio_error(&a); + if (r == EINPROGRESS) + { + lt_debug("%s: aio in progress, free: %d\n", __func__, bufsize - buf_pos); + continue; + } + // not calling aio_return causes a memory leak --martii + r = aio_return(&a); + if (r < 0) + { + exit_flag = RECORD_FAILED_FILE; + lt_debug("%s: aio_return = %d (%m)\n", __func__, r); + break; + } + else + lt_debug("%s: aio_return = %d, free: %d\n", __func__, r, bufsize - buf_pos); + if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED)) + perror("posix_fadvise"); + if (queued) + { + memmove(buf, buf + queued, buf_pos - queued); + buf_pos -= queued; + } + queued = buf_pos; + a.aio_buf = buf; + a.aio_nbytes = queued; + r = aio_write(&a); + if (r) + { + lt_info("%s: aio_write %d (%m)\n", __func__, r); + exit_flag = RECORD_FAILED_FILE; + break; + } + } + dmx->Stop(); + while (true) /* write out the unwritten buffer content */ + { + lt_debug("%s: run-out write, buf_pos %d\n", __func__, buf_pos); + r = aio_error(&a); + if (r == EINPROGRESS) + { + usleep(50000); + continue; + } + r = aio_return(&a); + if (r < 0) + { + exit_flag = RECORD_FAILED_FILE; + lt_info("%s: aio_result: %d (%m)\n", __func__, r); + break; + } + if (!queued) + break; + memmove(buf, buf + queued, buf_pos - queued); + buf_pos -= queued; + queued = buf_pos; + a.aio_buf = buf; + a.aio_nbytes = queued; + r = aio_write(&a); + } + free(buf); + +#if 0 + // TODO: do we need to notify neutrino about failing recording? + CEventServer eventServer; + eventServer.registerEvent2(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, "/tmp/neutrino.sock"); + stream2file_status2_t s; + s.status = exit_flag; + strncpy(s.filename,basename(myfilename),512); + s.filename[511] = '\0'; + strncpy(s.dir,dirname(myfilename),100); + s.dir[99] = '\0'; + eventServer.sendEvent(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, &s, sizeof(s)); + printf("[stream2file]: pthreads exit code: %i, dir: '%s', filename: '%s' myfilename: '%s'\n", exit_flag, s.dir, s.filename, myfilename); +#endif + + if ((exit_flag != RECORD_STOPPED) && failureCallback) + failureCallback(failureData); + lt_info("%s: end\n", __func__); + pthread_exit(NULL); +} + +int cRecord::GetStatus() +{ + return (exit_flag == RECORD_STOPPED) ? REC_STATUS_STOPPED : REC_STATUS_OK; +} + +void cRecord::ResetStatus() +{ + return; +} diff --git a/libarmbox/record_lib.h b/libarmbox/record_lib.h new file mode 100644 index 0000000..5ff453e --- /dev/null +++ b/libarmbox/record_lib.h @@ -0,0 +1,57 @@ +#ifndef __RECORD_TD_H +#define __RECORD_TD_H + +#include +#include +#include "dmx_lib.h" + +#define REC_STATUS_OK 0 +#define REC_STATUS_SLOW 1 +#define REC_STATUS_OVERFLOW 2 +#define REC_STATUS_STOPPED 4 + +typedef enum { + RECORD_RUNNING, + RECORD_STOPPED, + RECORD_FAILED_READ, /* failed to read from DMX */ + RECORD_FAILED_OVERFLOW, /* cannot write fast enough */ + RECORD_FAILED_FILE, /* cannot write to file */ + RECORD_FAILED_MEMORY /* out of memory */ +} record_state_t; + +class cRecord +{ + private: + int file_fd; + int dmx_num; + cDemux *dmx; + pthread_t record_thread; + bool record_thread_running; + record_state_t exit_flag; + int state; + int bufsize; + int bufsize_dmx; + void (*failureCallback)(void *); + void *failureData; + + sem_t sem; +#define RECORD_WRITER_CHUNKS 16 + unsigned char *io_buf[RECORD_WRITER_CHUNKS]; + size_t io_len[RECORD_WRITER_CHUNKS]; + public: + cRecord(int num = 0, int bs_dmx = 2048 * 1024, int bs = 4096 * 1024); + void setFailureCallback(void (*f)(void *), void *d) { failureCallback = f; failureData = d; } + ~cRecord(); + + bool Open(); + bool Start(int fd, unsigned short vpid, unsigned short *apids, int numapids, uint64_t ch = 0); + bool Stop(void); + bool AddPid(unsigned short pid); + int GetStatus(); + void ResetStatus(); + bool ChangePids(unsigned short vpid, unsigned short *apids, int numapids); + + void RecordThread(); + void WriterThread(); +}; +#endif diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp new file mode 100644 index 0000000..41855db --- /dev/null +++ b/libarmbox/video.cpp @@ -0,0 +1,1053 @@ +/* + * (C) 2002-2003 Andreas Oberritter + * (C) 2010-2013, 2015 Stefan Seyfried + * + * 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include "video_lib.h" +#include "lt_debug.h" +#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args) +#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args) +#define lt_debug_c(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, NULL, args) +#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_VIDEO, NULL, args) + +#define fop(cmd, args...) ({ \ + int _r; \ + if (fd >= 0) { \ + if ((_r = ::cmd(fd, args)) < 0) \ + lt_info(#cmd"(fd, "#args")\n"); \ + else \ + lt_debug(#cmd"(fd, "#args")\n");\ + } \ + else { _r = fd; } \ + _r; \ +}) + +cVideo * videoDecoder = NULL; +cVideo * pipDecoder = NULL; + +int system_rev = 0; + +static bool hdmi_enabled = true; +static bool stillpicture = false; + +static const char *VDEV[] = { + "/dev/dvb/adapter0/video0", + "/dev/dvb/adapter0/video1" +}; +static const char *VMPEG_aspect[] = { + "/proc/stb/vmpeg/0/aspect", + "/proc/stb/vmpeg/1/aspect" +}; + +static const char *VMPEG_xres[] = { + "/proc/stb/vmpeg/0/xres", + "/proc/stb/vmpeg/1/xres" +}; + +static const char *VMPEG_yres[] = { + "/proc/stb/vmpeg/0/yres", + "/proc/stb/vmpeg/1/yres" +}; + +static const char *VMPEG_dst_all[] = { + "/proc/stb/vmpeg/0/dst_all", + "/proc/stb/vmpeg/1/dst_all" +}; + +static const char *VMPEG_framerate[] = { + "/proc/stb/vmpeg/0/framerate", + "/proc/stb/vmpeg/1/framerate" +}; + + +#define VIDEO_STREAMTYPE_MPEG2 0 +#define VIDEO_STREAMTYPE_MPEG4_H264 1 +#define VIDEO_STREAMTYPE_VC1 3 +#define VIDEO_STREAMTYPE_MPEG4_Part2 4 +#define VIDEO_STREAMTYPE_VC1_SM 5 +#define VIDEO_STREAMTYPE_MPEG1 6 +#define VIDEO_STREAMTYPE_H265_HEVC 7 +#define VIDEO_STREAMTYPE_AVS 16 + + +static int proc_put(const char *path, const char *value, const int len) +{ + int ret, ret2; + int pfd = open(path, O_WRONLY); + if (pfd < 0) + return pfd; + ret = write(pfd, value, len); + ret2 = close(pfd); + if (ret2 < 0) + return ret2; + return ret; +} + +static int proc_get(const char *path, char *value, const int len) +{ + int ret, ret2; + int pfd = open(path, O_RDONLY); + if (pfd < 0) + return pfd; + ret = read(pfd, value, len); + value[len-1] = '\0'; /* make sure string is terminated */ + while (ret > 0 && isspace(value[ret-1])) + value[--ret] = '\0'; /* remove trailing whitespace */ + ret2 = close(pfd); + if (ret2 < 0) + return ret2; + return ret; +} + +static unsigned int proc_get_hex(const char *path) +{ + unsigned int n, ret = 0; + char buf[16]; + n = proc_get(path, buf, 16); + if (n > 0) + sscanf(buf, "%x", &ret); + return ret; +} + +static int hdmi_out(bool enable) +{ + int ret = -1; + return ret; +} + + +cVideo::cVideo(int, void *, void *, unsigned int unit) +{ + lt_debug("%s unit %u\n", __func__, unit); + + brightness = -1; + contrast = -1; + saturation = -1; + hue = -1; + + scartvoltage = -1; + video_standby = 0; + if (unit > 1) { + lt_info("%s: unit %d out of range, setting to 0\n", __func__, unit); + devnum = 0; + } else + devnum = unit; + fd = -1; + openDevice(); +} + +cVideo::~cVideo(void) +{ + closeDevice(); +} + +void cVideo::openDevice(void) +{ + int n = 0; + lt_debug("#%d: %s\n", devnum, __func__); + /* todo: this fd checking is racy, should be protected by a lock */ + if (fd != -1) /* already open */ + return; +retry: + if ((fd = open(VDEV[devnum], O_RDWR|O_CLOEXEC)) < 0) + { + if (errno == EBUSY) + { + /* sometimes we get busy quickly after close() */ + usleep(50000); + if (++n < 10) + goto retry; + } + lt_info("#%d: %s cannot open %s: %m, retries %d\n", devnum, __func__, VDEV[devnum], n); + } + playstate = VIDEO_STOPPED; +} + +void cVideo::closeDevice(void) +{ + lt_debug("%s\n", __func__); + /* looks like sometimes close is unhappy about non-empty buffers */ + Start(); + if (fd >= 0) + close(fd); + fd = -1; + playstate = VIDEO_STOPPED; +} + +int cVideo::setAspectRatio(int aspect, int mode) +{ + static const char *a[] = { "n/a", "4:3", "14:9", "16:9" }; + static const char *m[] = { "panscan", "letterbox", "bestfit", "nonlinear", "(unset)" }; + int n; + lt_debug("%s: a:%d m:%d %s\n", __func__, aspect, mode, m[(mode < 0||mode > 3) ? 4 : mode]); + + if (aspect > 3 || aspect == 0) + lt_info("%s: invalid aspect: %d\n", __func__, aspect); + else if (aspect > 0) /* -1 == don't set */ + { + lt_debug("%s: /proc/stb/video/aspect -> %s\n", __func__, a[aspect]); + n = proc_put("/proc/stb/video/aspect", a[aspect], strlen(a[aspect])); + if (n < 0) + lt_info("%s: proc_put /proc/stb/video/aspect (%m)\n", __func__); + } + + if (mode == -1) + return 0; + + lt_debug("%s: /proc/stb/video/policy -> %s\n", __func__, m[mode]); + n = proc_put("/proc/stb/video/policy", m[mode], strlen(m[mode])); + if (n < 0) + return 1; + return 0; +} + +int cVideo::getAspectRatio(void) +{ + video_size_t s; + if (fd == -1) + { + /* in movieplayer mode, fd is not opened -> fall back to procfs */ + int n = proc_get_hex(VMPEG_aspect[devnum]); + return n * 2 + 1; + } + if (fop(ioctl, VIDEO_GET_SIZE, &s) < 0) + { + lt_info("%s: VIDEO_GET_SIZE %m\n", __func__); + return -1; + } + lt_debug("#%d: %s: %d\n", devnum, __func__, s.aspect_ratio); + return s.aspect_ratio * 2 + 1; +} + +int cVideo::setCroppingMode(int /*vidDispMode_t format*/) +{ + return 0; +#if 0 + croppingMode = format; + const char *format_string[] = { "norm", "letterbox", "unknown", "mode_1_2", "mode_1_4", "mode_2x", "scale", "disexp" }; + const char *f; + if (format >= VID_DISPMODE_NORM && format <= VID_DISPMODE_DISEXP) + f = format_string[format]; + else + f = "ILLEGAL format!"; + lt_debug("%s(%d) => %s\n", __FUNCTION__, format, f); + return fop(ioctl, MPEG_VID_SET_DISPMODE, format); +#endif +} + +int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned short /*VideoPid*/, void * /*hChannel*/) +{ + lt_debug("#%d: %s playstate=%d\n", devnum, __func__, playstate); +#if 0 + if (playstate == VIDEO_PLAYING) + return 0; + if (playstate == VIDEO_FREEZED) /* in theory better, but not in practice :-) */ + fop(ioctl, MPEG_VID_CONTINUE); +#endif + playstate = VIDEO_PLAYING; + fop(ioctl, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); + int res = fop(ioctl, VIDEO_PLAY); + if (brightness > -1) { + SetControl(VIDEO_CONTROL_BRIGHTNESS, brightness); + brightness = -1; + } + if (contrast > -1) { + SetControl(VIDEO_CONTROL_CONTRAST, contrast); + contrast = -1; + } + if (saturation > -1) { + SetControl(VIDEO_CONTROL_SATURATION, saturation); + saturation = -1; + } + if (hue > -1) { + SetControl(VIDEO_CONTROL_HUE, hue); + hue = -1; + } + return res; +} + +int cVideo::Stop(bool blank) +{ + lt_debug("#%d: %s(%d)\n", devnum, __func__, blank); + if (stillpicture) + { + lt_debug("%s: stillpicture == true\n", __func__); + return -1; + } + playstate = blank ? VIDEO_STOPPED : VIDEO_FREEZED; + return fop(ioctl, VIDEO_STOP, blank ? 1 : 0); +} + +int cVideo::setBlank(int) +{ + fop(ioctl, VIDEO_PLAY); + fop(ioctl, VIDEO_CONTINUE); + video_still_picture sp = { NULL, 0 }; + fop(ioctl, VIDEO_STILLPICTURE, &sp); + return Stop(1); +} + +int cVideo::GetVideoSystem() +{ + lt_debug("%s\n", __func__); + char current[32]; + static const char *modes[] = { + "pal", // VIDEO_STD_NTSC + "pal", // VIDEO_STD_SECAM + "pal", // VIDEO_STD_PAL + "480p", // VIDEO_STD_480P + "576p50", // VIDEO_STD_576P + "720p60", // VIDEO_STD_720P60 + "1080i60", // VIDEO_STD_1080I60 + "720p50", // VIDEO_STD_720P50 + "1080i50", // VIDEO_STD_1080I50 + "1080p30", // VIDEO_STD_1080P30 + "1080p24", // VIDEO_STD_1080P24 + "1080p25", // VIDEO_STD_1080P25 + "1080p50", // VIDEO_STD_1080P50 + "1080p60", // VIDEO_STD_1080P60 + "1080p2397", // VIDEO_STD_1080P2397 + "1080p2997", // VIDEO_STD_1080P2997 + "720p50" // VIDEO_STD_AUTO + }; + + int ret = proc_get("/proc/stb/video/videomode", current, 32); + for (int i=0; i VIDEO_STD_MAX) + { + lt_info("%s: video_system (%d) > VIDEO_STD_MAX (%d)\n", __func__, video_system, VIDEO_STD_MAX); + return -1; + } + int ret = proc_get("/proc/stb/video/videomode", current, 32); + if (strcmp(current, modes[video_system]) == 0) + { + lt_info("%s: video_system %d (%s) already set, skipping\n", __func__, video_system, current); + return 0; + } + lt_info("%s: old: '%s' new: '%s'\n", __func__, current, modes[video_system]); + bool stopped = false; + if (playstate == VIDEO_PLAYING) + { + lt_info("%s: playstate == VIDEO_PLAYING, stopping video\n", __func__); + Stop(); + stopped = true; + } + hdmi_out(false); + ret = proc_put("/proc/stb/video/videomode", modes[video_system],strlen(modes[video_system])); + hdmi_out(true); + if (stopped) + Start(); + + return ret; +} + +int cVideo::getPlayState(void) +{ + return playstate; +} + +void cVideo::SetVideoMode(analog_mode_t mode) +{ + lt_debug("#%d: %s(%d)\n", devnum, __func__, mode); + if (!(mode & ANALOG_SCART_MASK)) + { + lt_debug("%s: non-SCART mode ignored\n", __func__); + return; + } + const char *m; + switch(mode) + { + case ANALOG_SD_YPRPB_SCART: + m = "yuv"; + break; + case ANALOG_SD_RGB_SCART: + m = "rgb"; + break; + default: + lt_info("%s unknown mode %d\n", __func__, mode); + m = "rgb"; + break; /* default to rgb */ + } + proc_put("/proc/stb/avs/0/colorformat", m, strlen(m)); +} + +void cVideo::ShowPicture(const char * fname, const char *_destname) +{ + lt_debug("%s(%s)\n", __func__, fname); + static const unsigned char pes_header[] = { 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x80, 0x00, 0x00 }; + static const unsigned char seq_end[] = { 0x00, 0x00, 0x01, 0xB7 }; + char destname[512]; + char cmd[512]; + char *p; + int mfd; + struct stat st, st2; + if (video_standby) + { + /* does not work and the driver does not seem to like it */ + lt_info("%s: video_standby == true\n", __func__); + return; + } + const char *lastDot = strrchr(fname, '.'); + if (lastDot && !strcasecmp(lastDot + 1, "m2v")) + strncpy(destname, fname, sizeof(destname)); + else { + if (_destname) + strncpy(destname, _destname, sizeof(destname)); + else { + strcpy(destname, "/tmp/cache"); + if (stat(fname, &st2)) + { + lt_info("%s: could not stat %s (%m)\n", __func__, fname); + return; + } + mkdir(destname, 0755); + /* the cache filename is (example for /share/tuxbox/neutrino/icons/radiomode.jpg): + /var/cache/share.tuxbox.neutrino.icons.radiomode.jpg.m2v + build that filename first... + TODO: this could cause name clashes, use a hashing function instead... */ + strcat(destname, fname); + p = &destname[strlen("/tmp/cache/")]; + while ((p = strchr(p, '/')) != NULL) + *p = '.'; + strcat(destname, ".m2v"); + } + /* ...then check if it exists already... */ + if (stat(destname, &st) || (st.st_mtime != st2.st_mtime) || (st.st_size == 0)) + { + struct utimbuf u; + u.actime = time(NULL); + u.modtime = st2.st_mtime; + /* it does not exist or has a different date, so call ffmpeg... */ + sprintf(cmd, "ffmpeg -y -f mjpeg -i '%s' -s 1280x720 -aspect 16:9 '%s' = 0) + { + stillpicture = true; + + if (ioctl(fd, VIDEO_SET_FORMAT, VIDEO_FORMAT_16_9) < 0) + lt_info("%s: VIDEO_SET_FORMAT failed (%m)\n", __func__); + bool seq_end_avail = false; + off_t pos=0; + unsigned char *iframe = (unsigned char *)malloc((st.st_size < 8192) ? 8192 : st.st_size); + if (! iframe) + { + lt_info("%s: malloc failed (%m)\n", __func__); + goto out; + } + read(mfd, iframe, st.st_size); + ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY); + ioctl(fd, VIDEO_PLAY); + ioctl(fd, VIDEO_CONTINUE); + ioctl(fd, VIDEO_CLEAR_BUFFER); + while (pos <= (st.st_size-4) && !(seq_end_avail = (!iframe[pos] && !iframe[pos+1] && iframe[pos+2] == 1 && iframe[pos+3] == 0xB7))) + ++pos; + + if ((iframe[3] >> 4) != 0xE) // no pes header + write(fd, pes_header, sizeof(pes_header)); + write(fd, iframe, st.st_size); + if (!seq_end_avail) + write(fd, seq_end, sizeof(seq_end)); + memset(iframe, 0, 8192); + write(fd, iframe, 8192); + ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); + free(iframe); + } + out: + close(mfd); + return; +} + +void cVideo::StopPicture() +{ + lt_debug("%s\n", __func__); + stillpicture = false; + Stop(1); +} + +void cVideo::Standby(unsigned int bOn) +{ + lt_debug("%s(%d)\n", __func__, bOn); + if (bOn) + { + closeDevice(); + hdmi_out(false); + } + else + { + /* only enable HDMI output when coming from standby, not on + * start. I have no idea why, but enabling it on startup leads + * to strange locking problems of the framebuffer driver :-( */ + if (!hdmi_enabled) + { + hdmi_out(true); + /* make sure the driver has time to settle. + * again - lame, but makes it work... */ + sleep(1); + } + openDevice(); + } + video_standby = bOn; +} + +int cVideo::getBlank(void) +{ + static unsigned int lastcount = 0; + unsigned int count = 0; + size_t n = 0; + ssize_t r; + char *line = NULL; + /* hack: the "mailbox" irq is not increasing if + * no audio or video is decoded... */ + FILE *f = fopen("/proc/interrupts", "r"); + if (! f) /* huh? */ + return 0; + while ((r = getline(&line, &n, f)) != -1) + { + if (r <= (ssize_t) strlen("mailbox")) /* should not happen... */ + continue; + line[r - 1] = 0; /* remove \n */ + if (!strcmp(&line[r - 1 - strlen("mailbox")], "mailbox")) + { + count = atoi(line + 5); + break; + } + } + free(line); + fclose(f); + int ret = (count == lastcount); /* no new decode -> return 1 */ + lt_debug("#%d: %s: %d (irq++: %d)\n", devnum, __func__, ret, count - lastcount); + lastcount = count; + return ret; +} + +/* this function is regularly called, checks if video parameters + changed and triggers appropriate actions */ +void cVideo::VideoParamWatchdog(void) +{ +#if 0 + static unsigned int _v_info = (unsigned int) -1; + unsigned int v_info; + if (fd == -1) + return; + ioctl(fd, MPEG_VID_GET_V_INFO_RAW, &v_info); + if (_v_info != v_info) + { + lt_debug("%s params changed. old: %08x new: %08x\n", __FUNCTION__, _v_info, v_info); + setAspectRatio(-1, -1); + } + _v_info = v_info; +#endif +} + +void cVideo::Pig(int x, int y, int w, int h, int osd_w, int osd_h, int startx, int starty, int endx, int endy) +{ + char buffer[64]; + int _x, _y, _w, _h; + /* the target "coordinates" seem to be in a PAL sized plane + * TODO: check this in the driver sources */ + int xres = 720; /* proc_get_hex("/proc/stb/vmpeg/0/xres") */ + int yres = 576; /* proc_get_hex("/proc/stb/vmpeg/0/yres") */ + lt_debug("#%d %s: x:%d y:%d w:%d h:%d ow:%d oh:%d\n", devnum, __func__, x, y, w, h, osd_w, osd_h); + if (x == -1 && y == -1 && w == -1 && h == -1) + { + _w = xres; + _h = yres; + _x = 0; + _y = 0; + } + else + { + // need to do some additional adjustments because osd border is handled by blitter + x += startx; + x *= endx - startx + 1; + y += starty; + y *= endy - starty + 1; + w *= endx - startx + 1; + h *= endy - starty + 1; + _x = x * xres / osd_w; + _w = w * xres / osd_w; + _y = y * yres / osd_h; + _h = h * yres / osd_h; + _x /= 1280; + _y /= 720; + _w /= 1280; + _h /= 720; + } + lt_debug("#%d %s: x:%d y:%d w:%d h:%d xr:%d yr:%d\n", devnum, __func__, _x, _y, _w, _h, xres, yres); + sprintf(buffer, "%x %x %x %x", _x, _y, _w, _h); + proc_put(VMPEG_dst_all[devnum], buffer, strlen(buffer)); +} + +static inline int rate2csapi(int rate) +{ + switch (rate) + { + case 23976: + return 0; + case 24000: + return 1; + case 25000: + return 2; + case 29976: + return 3; + case 30000: + return 4; + case 50000: + return 5; + case 50940: + return 6; + case 60000: + return 7; + default: + break; + } + return -1; +} + +void cVideo::getPictureInfo(int &width, int &height, int &rate) +{ + video_size_t s; + int r; + if (fd == -1) + { + /* in movieplayer mode, fd is not opened -> fall back to procfs */ + r = proc_get_hex(VMPEG_framerate[devnum]); + width = proc_get_hex(VMPEG_xres[devnum]); + height = proc_get_hex(VMPEG_yres[devnum]); + rate = rate2csapi(r); + return; + } + ioctl(fd, VIDEO_GET_SIZE, &s); + ioctl(fd, VIDEO_GET_FRAME_RATE, &r); + rate = rate2csapi(r); + height = s.h; + width = s.w; + lt_debug("#%d: %s: rate: %d, width: %d height: %d\n", devnum, __func__, rate, width, height); +} + +void cVideo::SetSyncMode(AVSYNC_TYPE mode) +{ + lt_debug("%s %d\n", __func__, mode); + /* + * { 0, LOCALE_OPTIONS_OFF }, + * { 1, LOCALE_OPTIONS_ON }, + * { 2, LOCALE_AUDIOMENU_AVSYNC_AM } + */ + const char *apply[] = { "disapply", "apply" }; + const char *clock[] = { "video", "audio" }; + const char *a = apply[mode > 0]; /* mode == 1 or mode == 2 -> "apply" */ + const char *c = clock[mode > 1]; /* mode == 2 -> "audio" */ + proc_put("/proc/stb/stream/policy/AV_SYNC", a, strlen(a)); + proc_put("/proc/stb/stream/policy/MASTER_CLOCK", c, strlen(c)); +}; + +int cVideo::SetStreamType(VIDEO_FORMAT type) +{ + static const char *VF[] = { + "VIDEO_FORMAT_MPEG2", + "VIDEO_FORMAT_MPEG4", + "VIDEO_FORMAT_VC1", + "VIDEO_FORMAT_JPEG", + "VIDEO_FORMAT_GIF", + "VIDEO_FORMAT_PNG" + }; + int t; + lt_debug("#%d: %s type=%s\n", devnum, __func__, VF[type]); + + switch (type) + { + case VIDEO_FORMAT_MPEG4_H264: + t = VIDEO_STREAMTYPE_MPEG4_H264; + break; + case VIDEO_FORMAT_MPEG4_H265: + t = VIDEO_STREAMTYPE_H265_HEVC; + break; + case VIDEO_FORMAT_AVS: + t = VIDEO_STREAMTYPE_AVS; + break; + case VIDEO_FORMAT_VC1: + t = VIDEO_STREAMTYPE_VC1; + break; + case VIDEO_FORMAT_MPEG2: + default: + t = VIDEO_STREAMTYPE_MPEG2; + break; + } + + if (ioctl(fd, VIDEO_SET_STREAMTYPE, t) < 0) + lt_info("%s VIDEO_SET_STREAMTYPE(%d) failed: %m\n", __func__, t); + return 0; +} + +int64_t cVideo::GetPTS(void) +{ + int64_t pts = 0; + if (ioctl(fd, VIDEO_GET_PTS, &pts) < 0) + lt_info("%s: GET_PTS failed (%m)\n", __func__); + return pts; +} + +void cVideo::SetDemux(cDemux *) +{ + lt_debug("#%d %s not implemented yet\n", devnum, __func__); +} + +void cVideo::SetControl(int control, int value) { + const char *p = NULL; + switch (control) { + case VIDEO_CONTROL_BRIGHTNESS: + brightness = value; + p = "/proc/stb/video/plane/psi_brightness"; + break; + case VIDEO_CONTROL_CONTRAST: + contrast = value; + p = "/proc/stb/video/plane/psi_contrast"; + break; + case VIDEO_CONTROL_SATURATION: + saturation = value; + p = "/proc/stb/video/plane/psi_saturation"; + break; + case VIDEO_CONTROL_HUE: + hue = value; + p = "/proc/stb/video/plane/psi_tint"; + break; + } + if (p) { + char buf[20]; + int len = snprintf(buf, sizeof(buf), "%d", value); + if (len < (int) sizeof(buf)) + proc_put(p, buf, len); + } +} + +void cVideo::SetColorFormat(COLOR_FORMAT color_format) { + const char *p = NULL; + switch(color_format) { + case COLORFORMAT_RGB: + p = "rgb"; + break; + case COLORFORMAT_YUV: + p = "yuv"; + break; + case COLORFORMAT_CVBS: + p = "cvbs"; + break; + case COLORFORMAT_SVIDEO: + p = "svideo"; + break; + case COLORFORMAT_HDMI_RGB: + p = "hdmi_rgb"; + break; + case COLORFORMAT_HDMI_YCBCR444: + p = "hdmi_yuv"; + break; + case COLORFORMAT_HDMI_YCBCR422: + p = "hdmi_422"; + break; + } + if (p) + proc_put("/proc/stb/avs/0/colorformat", p, strlen(p)); +} + +/* get an image of the video screen + * this code is inspired by dreambox AIO-grab, + * git://schwerkraft.elitedvb.net/aio-grab/aio-grab.git + * and the patches for STi support from + * https://github.com/Schischu/STLinux.BSP-Duckbox.git */ +/* static lookup tables for faster yuv2rgb conversion */ +static const uint32_t yuv2rgbtable_y[256] = { + 0xFFED5EA0, 0xFFEE88B6, 0xFFEFB2CC, 0xFFF0DCE2, 0xFFF206F8, 0xFFF3310E, 0xFFF45B24, 0xFFF5853A, + 0xFFF6AF50, 0xFFF7D966, 0xFFF9037C, 0xFFFA2D92, 0xFFFB57A8, 0xFFFC81BE, 0xFFFDABD4, 0xFFFED5EA, + 0x00000000, 0x00012A16, 0x0002542C, 0x00037E42, 0x0004A858, 0x0005D26E, 0x0006FC84, 0x0008269A, + 0x000950B0, 0x000A7AC6, 0x000BA4DC, 0x000CCEF2, 0x000DF908, 0x000F231E, 0x00104D34, 0x0011774A, + 0x0012A160, 0x0013CB76, 0x0014F58C, 0x00161FA2, 0x001749B8, 0x001873CE, 0x00199DE4, 0x001AC7FA, + 0x001BF210, 0x001D1C26, 0x001E463C, 0x001F7052, 0x00209A68, 0x0021C47E, 0x0022EE94, 0x002418AA, + 0x002542C0, 0x00266CD6, 0x002796EC, 0x0028C102, 0x0029EB18, 0x002B152E, 0x002C3F44, 0x002D695A, + 0x002E9370, 0x002FBD86, 0x0030E79C, 0x003211B2, 0x00333BC8, 0x003465DE, 0x00358FF4, 0x0036BA0A, + 0x0037E420, 0x00390E36, 0x003A384C, 0x003B6262, 0x003C8C78, 0x003DB68E, 0x003EE0A4, 0x00400ABA, + 0x004134D0, 0x00425EE6, 0x004388FC, 0x0044B312, 0x0045DD28, 0x0047073E, 0x00483154, 0x00495B6A, + 0x004A8580, 0x004BAF96, 0x004CD9AC, 0x004E03C2, 0x004F2DD8, 0x005057EE, 0x00518204, 0x0052AC1A, + 0x0053D630, 0x00550046, 0x00562A5C, 0x00575472, 0x00587E88, 0x0059A89E, 0x005AD2B4, 0x005BFCCA, + 0x005D26E0, 0x005E50F6, 0x005F7B0C, 0x0060A522, 0x0061CF38, 0x0062F94E, 0x00642364, 0x00654D7A, + 0x00667790, 0x0067A1A6, 0x0068CBBC, 0x0069F5D2, 0x006B1FE8, 0x006C49FE, 0x006D7414, 0x006E9E2A, + 0x006FC840, 0x0070F256, 0x00721C6C, 0x00734682, 0x00747098, 0x00759AAE, 0x0076C4C4, 0x0077EEDA, + 0x007918F0, 0x007A4306, 0x007B6D1C, 0x007C9732, 0x007DC148, 0x007EEB5E, 0x00801574, 0x00813F8A, + 0x008269A0, 0x008393B6, 0x0084BDCC, 0x0085E7E2, 0x008711F8, 0x00883C0E, 0x00896624, 0x008A903A, + 0x008BBA50, 0x008CE466, 0x008E0E7C, 0x008F3892, 0x009062A8, 0x00918CBE, 0x0092B6D4, 0x0093E0EA, + 0x00950B00, 0x00963516, 0x00975F2C, 0x00988942, 0x0099B358, 0x009ADD6E, 0x009C0784, 0x009D319A, + 0x009E5BB0, 0x009F85C6, 0x00A0AFDC, 0x00A1D9F2, 0x00A30408, 0x00A42E1E, 0x00A55834, 0x00A6824A, + 0x00A7AC60, 0x00A8D676, 0x00AA008C, 0x00AB2AA2, 0x00AC54B8, 0x00AD7ECE, 0x00AEA8E4, 0x00AFD2FA, + 0x00B0FD10, 0x00B22726, 0x00B3513C, 0x00B47B52, 0x00B5A568, 0x00B6CF7E, 0x00B7F994, 0x00B923AA, + 0x00BA4DC0, 0x00BB77D6, 0x00BCA1EC, 0x00BDCC02, 0x00BEF618, 0x00C0202E, 0x00C14A44, 0x00C2745A, + 0x00C39E70, 0x00C4C886, 0x00C5F29C, 0x00C71CB2, 0x00C846C8, 0x00C970DE, 0x00CA9AF4, 0x00CBC50A, + 0x00CCEF20, 0x00CE1936, 0x00CF434C, 0x00D06D62, 0x00D19778, 0x00D2C18E, 0x00D3EBA4, 0x00D515BA, + 0x00D63FD0, 0x00D769E6, 0x00D893FC, 0x00D9BE12, 0x00DAE828, 0x00DC123E, 0x00DD3C54, 0x00DE666A, + 0x00DF9080, 0x00E0BA96, 0x00E1E4AC, 0x00E30EC2, 0x00E438D8, 0x00E562EE, 0x00E68D04, 0x00E7B71A, + 0x00E8E130, 0x00EA0B46, 0x00EB355C, 0x00EC5F72, 0x00ED8988, 0x00EEB39E, 0x00EFDDB4, 0x00F107CA, + 0x00F231E0, 0x00F35BF6, 0x00F4860C, 0x00F5B022, 0x00F6DA38, 0x00F8044E, 0x00F92E64, 0x00FA587A, + 0x00FB8290, 0x00FCACA6, 0x00FDD6BC, 0x00FF00D2, 0x01002AE8, 0x010154FE, 0x01027F14, 0x0103A92A, + 0x0104D340, 0x0105FD56, 0x0107276C, 0x01085182, 0x01097B98, 0x010AA5AE, 0x010BCFC4, 0x010CF9DA, + 0x010E23F0, 0x010F4E06, 0x0110781C, 0x0111A232, 0x0112CC48, 0x0113F65E, 0x01152074, 0x01164A8A +}; +static const uint32_t yuv2rgbtable_ru[256] = { + 0xFEFDA500, 0xFEFFA9B6, 0xFF01AE6C, 0xFF03B322, 0xFF05B7D8, 0xFF07BC8E, 0xFF09C144, 0xFF0BC5FA, + 0xFF0DCAB0, 0xFF0FCF66, 0xFF11D41C, 0xFF13D8D2, 0xFF15DD88, 0xFF17E23E, 0xFF19E6F4, 0xFF1BEBAA, + 0xFF1DF060, 0xFF1FF516, 0xFF21F9CC, 0xFF23FE82, 0xFF260338, 0xFF2807EE, 0xFF2A0CA4, 0xFF2C115A, + 0xFF2E1610, 0xFF301AC6, 0xFF321F7C, 0xFF342432, 0xFF3628E8, 0xFF382D9E, 0xFF3A3254, 0xFF3C370A, + 0xFF3E3BC0, 0xFF404076, 0xFF42452C, 0xFF4449E2, 0xFF464E98, 0xFF48534E, 0xFF4A5804, 0xFF4C5CBA, + 0xFF4E6170, 0xFF506626, 0xFF526ADC, 0xFF546F92, 0xFF567448, 0xFF5878FE, 0xFF5A7DB4, 0xFF5C826A, + 0xFF5E8720, 0xFF608BD6, 0xFF62908C, 0xFF649542, 0xFF6699F8, 0xFF689EAE, 0xFF6AA364, 0xFF6CA81A, + 0xFF6EACD0, 0xFF70B186, 0xFF72B63C, 0xFF74BAF2, 0xFF76BFA8, 0xFF78C45E, 0xFF7AC914, 0xFF7CCDCA, + 0xFF7ED280, 0xFF80D736, 0xFF82DBEC, 0xFF84E0A2, 0xFF86E558, 0xFF88EA0E, 0xFF8AEEC4, 0xFF8CF37A, + 0xFF8EF830, 0xFF90FCE6, 0xFF93019C, 0xFF950652, 0xFF970B08, 0xFF990FBE, 0xFF9B1474, 0xFF9D192A, + 0xFF9F1DE0, 0xFFA12296, 0xFFA3274C, 0xFFA52C02, 0xFFA730B8, 0xFFA9356E, 0xFFAB3A24, 0xFFAD3EDA, + 0xFFAF4390, 0xFFB14846, 0xFFB34CFC, 0xFFB551B2, 0xFFB75668, 0xFFB95B1E, 0xFFBB5FD4, 0xFFBD648A, + 0xFFBF6940, 0xFFC16DF6, 0xFFC372AC, 0xFFC57762, 0xFFC77C18, 0xFFC980CE, 0xFFCB8584, 0xFFCD8A3A, + 0xFFCF8EF0, 0xFFD193A6, 0xFFD3985C, 0xFFD59D12, 0xFFD7A1C8, 0xFFD9A67E, 0xFFDBAB34, 0xFFDDAFEA, + 0xFFDFB4A0, 0xFFE1B956, 0xFFE3BE0C, 0xFFE5C2C2, 0xFFE7C778, 0xFFE9CC2E, 0xFFEBD0E4, 0xFFEDD59A, + 0xFFEFDA50, 0xFFF1DF06, 0xFFF3E3BC, 0xFFF5E872, 0xFFF7ED28, 0xFFF9F1DE, 0xFFFBF694, 0xFFFDFB4A, + 0x00000000, 0x000204B6, 0x0004096C, 0x00060E22, 0x000812D8, 0x000A178E, 0x000C1C44, 0x000E20FA, + 0x001025B0, 0x00122A66, 0x00142F1C, 0x001633D2, 0x00183888, 0x001A3D3E, 0x001C41F4, 0x001E46AA, + 0x00204B60, 0x00225016, 0x002454CC, 0x00265982, 0x00285E38, 0x002A62EE, 0x002C67A4, 0x002E6C5A, + 0x00307110, 0x003275C6, 0x00347A7C, 0x00367F32, 0x003883E8, 0x003A889E, 0x003C8D54, 0x003E920A, + 0x004096C0, 0x00429B76, 0x0044A02C, 0x0046A4E2, 0x0048A998, 0x004AAE4E, 0x004CB304, 0x004EB7BA, + 0x0050BC70, 0x0052C126, 0x0054C5DC, 0x0056CA92, 0x0058CF48, 0x005AD3FE, 0x005CD8B4, 0x005EDD6A, + 0x0060E220, 0x0062E6D6, 0x0064EB8C, 0x0066F042, 0x0068F4F8, 0x006AF9AE, 0x006CFE64, 0x006F031A, + 0x007107D0, 0x00730C86, 0x0075113C, 0x007715F2, 0x00791AA8, 0x007B1F5E, 0x007D2414, 0x007F28CA, + 0x00812D80, 0x00833236, 0x008536EC, 0x00873BA2, 0x00894058, 0x008B450E, 0x008D49C4, 0x008F4E7A, + 0x00915330, 0x009357E6, 0x00955C9C, 0x00976152, 0x00996608, 0x009B6ABE, 0x009D6F74, 0x009F742A, + 0x00A178E0, 0x00A37D96, 0x00A5824C, 0x00A78702, 0x00A98BB8, 0x00AB906E, 0x00AD9524, 0x00AF99DA, + 0x00B19E90, 0x00B3A346, 0x00B5A7FC, 0x00B7ACB2, 0x00B9B168, 0x00BBB61E, 0x00BDBAD4, 0x00BFBF8A, + 0x00C1C440, 0x00C3C8F6, 0x00C5CDAC, 0x00C7D262, 0x00C9D718, 0x00CBDBCE, 0x00CDE084, 0x00CFE53A, + 0x00D1E9F0, 0x00D3EEA6, 0x00D5F35C, 0x00D7F812, 0x00D9FCC8, 0x00DC017E, 0x00DE0634, 0x00E00AEA, + 0x00E20FA0, 0x00E41456, 0x00E6190C, 0x00E81DC2, 0x00EA2278, 0x00EC272E, 0x00EE2BE4, 0x00F0309A, + 0x00F23550, 0x00F43A06, 0x00F63EBC, 0x00F84372, 0x00FA4828, 0x00FC4CDE, 0x00FE5194, 0x00100564A +}; +static const uint32_t yuv2rgbtable_gu[256] = { + 0xFFCDD300, 0xFFCE375A, 0xFFCE9BB4, 0xFFCF000E, 0xFFCF6468, 0xFFCFC8C2, 0xFFD02D1C, 0xFFD09176, + 0xFFD0F5D0, 0xFFD15A2A, 0xFFD1BE84, 0xFFD222DE, 0xFFD28738, 0xFFD2EB92, 0xFFD34FEC, 0xFFD3B446, + 0xFFD418A0, 0xFFD47CFA, 0xFFD4E154, 0xFFD545AE, 0xFFD5AA08, 0xFFD60E62, 0xFFD672BC, 0xFFD6D716, + 0xFFD73B70, 0xFFD79FCA, 0xFFD80424, 0xFFD8687E, 0xFFD8CCD8, 0xFFD93132, 0xFFD9958C, 0xFFD9F9E6, + 0xFFDA5E40, 0xFFDAC29A, 0xFFDB26F4, 0xFFDB8B4E, 0xFFDBEFA8, 0xFFDC5402, 0xFFDCB85C, 0xFFDD1CB6, + 0xFFDD8110, 0xFFDDE56A, 0xFFDE49C4, 0xFFDEAE1E, 0xFFDF1278, 0xFFDF76D2, 0xFFDFDB2C, 0xFFE03F86, + 0xFFE0A3E0, 0xFFE1083A, 0xFFE16C94, 0xFFE1D0EE, 0xFFE23548, 0xFFE299A2, 0xFFE2FDFC, 0xFFE36256, + 0xFFE3C6B0, 0xFFE42B0A, 0xFFE48F64, 0xFFE4F3BE, 0xFFE55818, 0xFFE5BC72, 0xFFE620CC, 0xFFE68526, + 0xFFE6E980, 0xFFE74DDA, 0xFFE7B234, 0xFFE8168E, 0xFFE87AE8, 0xFFE8DF42, 0xFFE9439C, 0xFFE9A7F6, + 0xFFEA0C50, 0xFFEA70AA, 0xFFEAD504, 0xFFEB395E, 0xFFEB9DB8, 0xFFEC0212, 0xFFEC666C, 0xFFECCAC6, + 0xFFED2F20, 0xFFED937A, 0xFFEDF7D4, 0xFFEE5C2E, 0xFFEEC088, 0xFFEF24E2, 0xFFEF893C, 0xFFEFED96, + 0xFFF051F0, 0xFFF0B64A, 0xFFF11AA4, 0xFFF17EFE, 0xFFF1E358, 0xFFF247B2, 0xFFF2AC0C, 0xFFF31066, + 0xFFF374C0, 0xFFF3D91A, 0xFFF43D74, 0xFFF4A1CE, 0xFFF50628, 0xFFF56A82, 0xFFF5CEDC, 0xFFF63336, + 0xFFF69790, 0xFFF6FBEA, 0xFFF76044, 0xFFF7C49E, 0xFFF828F8, 0xFFF88D52, 0xFFF8F1AC, 0xFFF95606, + 0xFFF9BA60, 0xFFFA1EBA, 0xFFFA8314, 0xFFFAE76E, 0xFFFB4BC8, 0xFFFBB022, 0xFFFC147C, 0xFFFC78D6, + 0xFFFCDD30, 0xFFFD418A, 0xFFFDA5E4, 0xFFFE0A3E, 0xFFFE6E98, 0xFFFED2F2, 0xFFFF374C, 0xFFFF9BA6, + 0x00000000, 0x0000645A, 0x0000C8B4, 0x00012D0E, 0x00019168, 0x0001F5C2, 0x00025A1C, 0x0002BE76, + 0x000322D0, 0x0003872A, 0x0003EB84, 0x00044FDE, 0x0004B438, 0x00051892, 0x00057CEC, 0x0005E146, + 0x000645A0, 0x0006A9FA, 0x00070E54, 0x000772AE, 0x0007D708, 0x00083B62, 0x00089FBC, 0x00090416, + 0x00096870, 0x0009CCCA, 0x000A3124, 0x000A957E, 0x000AF9D8, 0x000B5E32, 0x000BC28C, 0x000C26E6, + 0x000C8B40, 0x000CEF9A, 0x000D53F4, 0x000DB84E, 0x000E1CA8, 0x000E8102, 0x000EE55C, 0x000F49B6, + 0x000FAE10, 0x0010126A, 0x001076C4, 0x0010DB1E, 0x00113F78, 0x0011A3D2, 0x0012082C, 0x00126C86, + 0x0012D0E0, 0x0013353A, 0x00139994, 0x0013FDEE, 0x00146248, 0x0014C6A2, 0x00152AFC, 0x00158F56, + 0x0015F3B0, 0x0016580A, 0x0016BC64, 0x001720BE, 0x00178518, 0x0017E972, 0x00184DCC, 0x0018B226, + 0x00191680, 0x00197ADA, 0x0019DF34, 0x001A438E, 0x001AA7E8, 0x001B0C42, 0x001B709C, 0x001BD4F6, + 0x001C3950, 0x001C9DAA, 0x001D0204, 0x001D665E, 0x001DCAB8, 0x001E2F12, 0x001E936C, 0x001EF7C6, + 0x001F5C20, 0x001FC07A, 0x002024D4, 0x0020892E, 0x0020ED88, 0x002151E2, 0x0021B63C, 0x00221A96, + 0x00227EF0, 0x0022E34A, 0x002347A4, 0x0023ABFE, 0x00241058, 0x002474B2, 0x0024D90C, 0x00253D66, + 0x0025A1C0, 0x0026061A, 0x00266A74, 0x0026CECE, 0x00273328, 0x00279782, 0x0027FBDC, 0x00286036, + 0x0028C490, 0x002928EA, 0x00298D44, 0x0029F19E, 0x002A55F8, 0x002ABA52, 0x002B1EAC, 0x002B8306, + 0x002BE760, 0x002C4BBA, 0x002CB014, 0x002D146E, 0x002D78C8, 0x002DDD22, 0x002E417C, 0x002EA5D6, + 0x002F0A30, 0x002F6E8A, 0x002FD2E4, 0x0030373E, 0x00309B98, 0x0030FFF2, 0x0031644C, 0x0031C8A6 +}; +static const uint32_t yuv2rgbtable_gv[256] = { + 0xFF97E900, 0xFF98B92E, 0xFF99895C, 0xFF9A598A, 0xFF9B29B8, 0xFF9BF9E6, 0xFF9CCA14, 0xFF9D9A42, + 0xFF9E6A70, 0xFF9F3A9E, 0xFFA00ACC, 0xFFA0DAFA, 0xFFA1AB28, 0xFFA27B56, 0xFFA34B84, 0xFFA41BB2, + 0xFFA4EBE0, 0xFFA5BC0E, 0xFFA68C3C, 0xFFA75C6A, 0xFFA82C98, 0xFFA8FCC6, 0xFFA9CCF4, 0xFFAA9D22, + 0xFFAB6D50, 0xFFAC3D7E, 0xFFAD0DAC, 0xFFADDDDA, 0xFFAEAE08, 0xFFAF7E36, 0xFFB04E64, 0xFFB11E92, + 0xFFB1EEC0, 0xFFB2BEEE, 0xFFB38F1C, 0xFFB45F4A, 0xFFB52F78, 0xFFB5FFA6, 0xFFB6CFD4, 0xFFB7A002, + 0xFFB87030, 0xFFB9405E, 0xFFBA108C, 0xFFBAE0BA, 0xFFBBB0E8, 0xFFBC8116, 0xFFBD5144, 0xFFBE2172, + 0xFFBEF1A0, 0xFFBFC1CE, 0xFFC091FC, 0xFFC1622A, 0xFFC23258, 0xFFC30286, 0xFFC3D2B4, 0xFFC4A2E2, + 0xFFC57310, 0xFFC6433E, 0xFFC7136C, 0xFFC7E39A, 0xFFC8B3C8, 0xFFC983F6, 0xFFCA5424, 0xFFCB2452, + 0xFFCBF480, 0xFFCCC4AE, 0xFFCD94DC, 0xFFCE650A, 0xFFCF3538, 0xFFD00566, 0xFFD0D594, 0xFFD1A5C2, + 0xFFD275F0, 0xFFD3461E, 0xFFD4164C, 0xFFD4E67A, 0xFFD5B6A8, 0xFFD686D6, 0xFFD75704, 0xFFD82732, + 0xFFD8F760, 0xFFD9C78E, 0xFFDA97BC, 0xFFDB67EA, 0xFFDC3818, 0xFFDD0846, 0xFFDDD874, 0xFFDEA8A2, + 0xFFDF78D0, 0xFFE048FE, 0xFFE1192C, 0xFFE1E95A, 0xFFE2B988, 0xFFE389B6, 0xFFE459E4, 0xFFE52A12, + 0xFFE5FA40, 0xFFE6CA6E, 0xFFE79A9C, 0xFFE86ACA, 0xFFE93AF8, 0xFFEA0B26, 0xFFEADB54, 0xFFEBAB82, + 0xFFEC7BB0, 0xFFED4BDE, 0xFFEE1C0C, 0xFFEEEC3A, 0xFFEFBC68, 0xFFF08C96, 0xFFF15CC4, 0xFFF22CF2, + 0xFFF2FD20, 0xFFF3CD4E, 0xFFF49D7C, 0xFFF56DAA, 0xFFF63DD8, 0xFFF70E06, 0xFFF7DE34, 0xFFF8AE62, + 0xFFF97E90, 0xFFFA4EBE, 0xFFFB1EEC, 0xFFFBEF1A, 0xFFFCBF48, 0xFFFD8F76, 0xFFFE5FA4, 0xFFFF2FD2, + 0x00000000, 0x0000D02E, 0x0001A05C, 0x0002708A, 0x000340B8, 0x000410E6, 0x0004E114, 0x0005B142, + 0x00068170, 0x0007519E, 0x000821CC, 0x0008F1FA, 0x0009C228, 0x000A9256, 0x000B6284, 0x000C32B2, + 0x000D02E0, 0x000DD30E, 0x000EA33C, 0x000F736A, 0x00104398, 0x001113C6, 0x0011E3F4, 0x0012B422, + 0x00138450, 0x0014547E, 0x001524AC, 0x0015F4DA, 0x0016C508, 0x00179536, 0x00186564, 0x00193592, + 0x001A05C0, 0x001AD5EE, 0x001BA61C, 0x001C764A, 0x001D4678, 0x001E16A6, 0x001EE6D4, 0x001FB702, + 0x00208730, 0x0021575E, 0x0022278C, 0x0022F7BA, 0x0023C7E8, 0x00249816, 0x00256844, 0x00263872, + 0x002708A0, 0x0027D8CE, 0x0028A8FC, 0x0029792A, 0x002A4958, 0x002B1986, 0x002BE9B4, 0x002CB9E2, + 0x002D8A10, 0x002E5A3E, 0x002F2A6C, 0x002FFA9A, 0x0030CAC8, 0x00319AF6, 0x00326B24, 0x00333B52, + 0x00340B80, 0x0034DBAE, 0x0035ABDC, 0x00367C0A, 0x00374C38, 0x00381C66, 0x0038EC94, 0x0039BCC2, + 0x003A8CF0, 0x003B5D1E, 0x003C2D4C, 0x003CFD7A, 0x003DCDA8, 0x003E9DD6, 0x003F6E04, 0x00403E32, + 0x00410E60, 0x0041DE8E, 0x0042AEBC, 0x00437EEA, 0x00444F18, 0x00451F46, 0x0045EF74, 0x0046BFA2, + 0x00478FD0, 0x00485FFE, 0x0049302C, 0x004A005A, 0x004AD088, 0x004BA0B6, 0x004C70E4, 0x004D4112, + 0x004E1140, 0x004EE16E, 0x004FB19C, 0x005081CA, 0x005151F8, 0x00522226, 0x0052F254, 0x0053C282, + 0x005492B0, 0x005562DE, 0x0056330C, 0x0057033A, 0x0057D368, 0x0058A396, 0x005973C4, 0x005A43F2, + 0x005B1420, 0x005BE44E, 0x005CB47C, 0x005D84AA, 0x005E54D8, 0x005F2506, 0x005FF534, 0x0060C562, + 0x00619590, 0x006265BE, 0x006335EC, 0x0064061A, 0x0064D648, 0x0065A676, 0x006676A4, 0x006746D2 +}; +static const uint32_t yuv2rgbtable_bv[256] = { + 0xFF33A280, 0xFF353B3B, 0xFF36D3F6, 0xFF386CB1, 0xFF3A056C, 0xFF3B9E27, 0xFF3D36E2, 0xFF3ECF9D, + 0xFF406858, 0xFF420113, 0xFF4399CE, 0xFF453289, 0xFF46CB44, 0xFF4863FF, 0xFF49FCBA, 0xFF4B9575, + 0xFF4D2E30, 0xFF4EC6EB, 0xFF505FA6, 0xFF51F861, 0xFF53911C, 0xFF5529D7, 0xFF56C292, 0xFF585B4D, + 0xFF59F408, 0xFF5B8CC3, 0xFF5D257E, 0xFF5EBE39, 0xFF6056F4, 0xFF61EFAF, 0xFF63886A, 0xFF652125, + 0xFF66B9E0, 0xFF68529B, 0xFF69EB56, 0xFF6B8411, 0xFF6D1CCC, 0xFF6EB587, 0xFF704E42, 0xFF71E6FD, + 0xFF737FB8, 0xFF751873, 0xFF76B12E, 0xFF7849E9, 0xFF79E2A4, 0xFF7B7B5F, 0xFF7D141A, 0xFF7EACD5, + 0xFF804590, 0xFF81DE4B, 0xFF837706, 0xFF850FC1, 0xFF86A87C, 0xFF884137, 0xFF89D9F2, 0xFF8B72AD, + 0xFF8D0B68, 0xFF8EA423, 0xFF903CDE, 0xFF91D599, 0xFF936E54, 0xFF95070F, 0xFF969FCA, 0xFF983885, + 0xFF99D140, 0xFF9B69FB, 0xFF9D02B6, 0xFF9E9B71, 0xFFA0342C, 0xFFA1CCE7, 0xFFA365A2, 0xFFA4FE5D, + 0xFFA69718, 0xFFA82FD3, 0xFFA9C88E, 0xFFAB6149, 0xFFACFA04, 0xFFAE92BF, 0xFFB02B7A, 0xFFB1C435, + 0xFFB35CF0, 0xFFB4F5AB, 0xFFB68E66, 0xFFB82721, 0xFFB9BFDC, 0xFFBB5897, 0xFFBCF152, 0xFFBE8A0D, + 0xFFC022C8, 0xFFC1BB83, 0xFFC3543E, 0xFFC4ECF9, 0xFFC685B4, 0xFFC81E6F, 0xFFC9B72A, 0xFFCB4FE5, + 0xFFCCE8A0, 0xFFCE815B, 0xFFD01A16, 0xFFD1B2D1, 0xFFD34B8C, 0xFFD4E447, 0xFFD67D02, 0xFFD815BD, + 0xFFD9AE78, 0xFFDB4733, 0xFFDCDFEE, 0xFFDE78A9, 0xFFE01164, 0xFFE1AA1F, 0xFFE342DA, 0xFFE4DB95, + 0xFFE67450, 0xFFE80D0B, 0xFFE9A5C6, 0xFFEB3E81, 0xFFECD73C, 0xFFEE6FF7, 0xFFF008B2, 0xFFF1A16D, + 0xFFF33A28, 0xFFF4D2E3, 0xFFF66B9E, 0xFFF80459, 0xFFF99D14, 0xFFFB35CF, 0xFFFCCE8A, 0xFFFE6745, + 0x00000000, 0x000198BB, 0x00033176, 0x0004CA31, 0x000662EC, 0x0007FBA7, 0x00099462, 0x000B2D1D, + 0x000CC5D8, 0x000E5E93, 0x000FF74E, 0x00119009, 0x001328C4, 0x0014C17F, 0x00165A3A, 0x0017F2F5, + 0x00198BB0, 0x001B246B, 0x001CBD26, 0x001E55E1, 0x001FEE9C, 0x00218757, 0x00232012, 0x0024B8CD, + 0x00265188, 0x0027EA43, 0x002982FE, 0x002B1BB9, 0x002CB474, 0x002E4D2F, 0x002FE5EA, 0x00317EA5, + 0x00331760, 0x0034B01B, 0x003648D6, 0x0037E191, 0x00397A4C, 0x003B1307, 0x003CABC2, 0x003E447D, + 0x003FDD38, 0x004175F3, 0x00430EAE, 0x0044A769, 0x00464024, 0x0047D8DF, 0x0049719A, 0x004B0A55, + 0x004CA310, 0x004E3BCB, 0x004FD486, 0x00516D41, 0x005305FC, 0x00549EB7, 0x00563772, 0x0057D02D, + 0x005968E8, 0x005B01A3, 0x005C9A5E, 0x005E3319, 0x005FCBD4, 0x0061648F, 0x0062FD4A, 0x00649605, + 0x00662EC0, 0x0067C77B, 0x00696036, 0x006AF8F1, 0x006C91AC, 0x006E2A67, 0x006FC322, 0x00715BDD, + 0x0072F498, 0x00748D53, 0x0076260E, 0x0077BEC9, 0x00795784, 0x007AF03F, 0x007C88FA, 0x007E21B5, + 0x007FBA70, 0x0081532B, 0x0082EBE6, 0x008484A1, 0x00861D5C, 0x0087B617, 0x00894ED2, 0x008AE78D, + 0x008C8048, 0x008E1903, 0x008FB1BE, 0x00914A79, 0x0092E334, 0x00947BEF, 0x009614AA, 0x0097AD65, + 0x00994620, 0x009ADEDB, 0x009C7796, 0x009E1051, 0x009FA90C, 0x00A141C7, 0x00A2DA82, 0x00A4733D, + 0x00A60BF8, 0x00A7A4B3, 0x00A93D6E, 0x00AAD629, 0x00AC6EE4, 0x00AE079F, 0x00AFA05A, 0x00B13915, + 0x00B2D1D0, 0x00B46A8B, 0x00B60346, 0x00B79C01, 0x00B934BC, 0x00BACD77, 0x00BC6632, 0x00BDFEED, + 0x00BF97A8, 0x00C13063, 0x00C2C91E, 0x00C461D9, 0x00C5FA94, 0x00C7934F, 0x00C92C0A, 0x00CAC4C5 +}; + +#define OUT(x) \ + out[OUTITER] = (uint8_t)*(decode_surface + x)&0xFF; \ + OUTITER += OUTINC; + +#define OUT4(x) \ + OUT(x + 0x03); \ + OUT(x + 0x02); \ + OUT(x + 0x01); \ + OUT(x + 0x00); + +#define OUT8(x) \ + OUT4(x + 0x04); \ + OUT4(x + 0x00); + +#define OUT_LU_16A(x) \ + OUT8(x); \ + OUT8(x + 0x40); + +#define OUT_CH_8A(x) \ + OUT4(x); \ + OUT4(x + 0x20); + +//pppppppppppppppp +//x: macroblock address +//l: line 0-15 +#define OUT_LU_16(x,l) \ + OUT_LU_16A(x + (l/4) * 0x10 + (l%2) * 0x80 + ((l/2)%2?0x00:0x08)); + +//pppppppp +//x: macroblock address +//l: line 0-7 +//b: 0=cr 1=cb +#define OUT_CH_8(x,l,b) \ + OUT_CH_8A(x + (l/4) * 0x10 + (l%2) * 0x40 + ((l/2)%2?0x00:0x08) + (b?0x04:0x00)); + +//---- +#define CLAMP(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x)) +#define SWAP(x,y) { x ^= y; y ^= x; x ^= y; } + +/* TODO: aspect ratio correction and PIP */ +bool cVideo::GetScreenImage(unsigned char * &video, int &xres, int &yres, bool get_video, bool get_osd, bool scale_to_video) +{ + lt_info("%s: get_video: %d get_osd: %d scale_to_video: %d\n", + __func__, get_video, get_osd, scale_to_video); + return true; +} diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h new file mode 100644 index 0000000..e172cb9 --- /dev/null +++ b/libarmbox/video_lib.h @@ -0,0 +1,218 @@ +#ifndef _VIDEO_TD_H +#define _VIDEO_TD_H + +#include +#include "../common/cs_types.h" +#include "dmx_lib.h" + +typedef enum { + ANALOG_SD_RGB_CINCH = 0x00, + ANALOG_SD_YPRPB_CINCH, + ANALOG_HD_RGB_CINCH, + ANALOG_HD_YPRPB_CINCH, + ANALOG_SD_RGB_SCART = 0x10, + ANALOG_SD_YPRPB_SCART, + ANALOG_HD_RGB_SCART, + ANALOG_HD_YPRPB_SCART, + ANALOG_SCART_MASK = 0x10 +} analog_mode_t; + +typedef enum { + COLORFORMAT_RGB = 0x10, // keep compatible with analog_mode_t + COLORFORMAT_YUV, + COLORFORMAT_CVBS, + COLORFORMAT_SVIDEO, + COLORFORMAT_HDMI_RGB, + COLORFORMAT_HDMI_YCBCR444, + COLORFORMAT_HDMI_YCBCR422 +} COLOR_FORMAT; + +typedef enum { + VIDEO_FORMAT_MPEG2 = 0, + VIDEO_FORMAT_MPEG4_H264, + VIDEO_FORMAT_VC1, + VIDEO_FORMAT_JPEG, + VIDEO_FORMAT_GIF, + VIDEO_FORMAT_PNG, + VIDEO_FORMAT_MPEG4_H265, + VIDEO_FORMAT_AVS = 16 +} VIDEO_FORMAT; + +typedef enum { + VIDEO_SD = 0, + VIDEO_HD, + VIDEO_120x60i, + VIDEO_320x240i, + VIDEO_1440x800i, + VIDEO_360x288i +} VIDEO_DEFINITION; + +typedef enum { + VIDEO_FRAME_RATE_23_976 = 0, + VIDEO_FRAME_RATE_24, + VIDEO_FRAME_RATE_25, + VIDEO_FRAME_RATE_29_97, + VIDEO_FRAME_RATE_30, + VIDEO_FRAME_RATE_50, + VIDEO_FRAME_RATE_59_94, + VIDEO_FRAME_RATE_60 +} VIDEO_FRAME_RATE; + +typedef enum { + DISPLAY_AR_1_1, + DISPLAY_AR_4_3, + DISPLAY_AR_14_9, + DISPLAY_AR_16_9, + DISPLAY_AR_20_9, + DISPLAY_AR_RAW +} DISPLAY_AR; + +typedef enum { + DISPLAY_AR_MODE_PANSCAN = 0, + DISPLAY_AR_MODE_LETTERBOX, + DISPLAY_AR_MODE_NONE, + DISPLAY_AR_MODE_PANSCAN2 +} DISPLAY_AR_MODE; + +typedef enum { + VIDEO_DB_DR_NEITHER = 0, + VIDEO_DB_ON, + VIDEO_DB_DR_BOTH +} VIDEO_DB_DR; + +typedef enum { + VIDEO_PLAY_STILL = 0, + VIDEO_PLAY_CLIP, + VIDEO_PLAY_TRICK, + VIDEO_PLAY_MOTION, + VIDEO_PLAY_MOTION_NO_SYNC +} VIDEO_PLAY_MODE; + +typedef enum { + VIDEO_STD_NTSC, + VIDEO_STD_SECAM, + VIDEO_STD_PAL, + VIDEO_STD_480P, + VIDEO_STD_576P, + VIDEO_STD_720P60, + VIDEO_STD_1080I60, + VIDEO_STD_720P50, + VIDEO_STD_1080I50, + VIDEO_STD_1080P30, + VIDEO_STD_1080P24, + VIDEO_STD_1080P25, + VIDEO_STD_1080P50, + VIDEO_STD_1080P60, + VIDEO_STD_1080P2397, + VIDEO_STD_1080P2997, + VIDEO_STD_AUTO, + VIDEO_STD_MAX = VIDEO_STD_AUTO +} VIDEO_STD; + +/* not used, for dummy functions */ +typedef enum { + VIDEO_HDMI_CEC_MODE_OFF = 0, + VIDEO_HDMI_CEC_MODE_TUNER, + VIDEO_HDMI_CEC_MODE_RECORDER +} VIDEO_HDMI_CEC_MODE; + +typedef enum +{ + VIDEO_CONTROL_BRIGHTNESS = 0, + VIDEO_CONTROL_CONTRAST, + VIDEO_CONTROL_SATURATION, + VIDEO_CONTROL_HUE, + VIDEO_CONTROL_SHARPNESS, + VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS +} VIDEO_CONTROL; + + +class cVideo +{ + friend class cDemux; + friend class cPlayback; + private: + /* video device */ + int fd; + unsigned int devnum; + /* apparently we cannot query the driver's state + => remember it */ + video_play_state_t playstate; + int /*vidDispMode_t*/ croppingMode; + int /*vidOutFmt_t*/ outputformat; + int scartvoltage; + + VIDEO_FORMAT StreamType; + VIDEO_DEFINITION VideoDefinition; + DISPLAY_AR DisplayAR; + VIDEO_PLAY_MODE SyncMode; + DISPLAY_AR_MODE ARMode; + VIDEO_DB_DR eDbDr; + DISPLAY_AR PictureAR; + VIDEO_FRAME_RATE FrameRate; + int video_standby; + int64_t GetPTS(void); + + int brightness, contrast, saturation, hue; + + void openDevice(void); + void closeDevice(void); + public: + /* constructor & destructor */ + cVideo(int mode, void *, void *, unsigned int unit = 0); + ~cVideo(void); + + void * GetTVEnc() { return NULL; }; + void * GetTVEncSD() { return NULL; }; + + /* aspect ratio */ + int getAspectRatio(void); + void getPictureInfo(int &width, int &height, int &rate); + int setAspectRatio(int aspect, int mode); + + /* cropping mode */ + int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/); + + /* get play state */ + int getPlayState(void); + + /* blank on freeze */ + int getBlank(void); + int setBlank(int enable); + + /* change video play state. Parameters are all unused. */ + int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL); + int Stop(bool blank = true); + bool Pause(void); + + /* get video system infos */ + int GetVideoSystem(); + + /* set video_system */ + int SetVideoSystem(int video_system, bool remember = true); + int SetStreamType(VIDEO_FORMAT type); + void SetSyncMode(AVSYNC_TYPE mode); + bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; }; + void SetCECAutoView(bool) { return; }; + void SetCECAutoStandby(bool) { return; }; + void ShowPicture(const char * fname, const char *_destname = NULL); + void StopPicture(); + void Standby(unsigned int bOn); + void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600, int startx = 0, int starty = 0, int endx = 1279, int endy = 719); + void SetControl(int, int); + void VideoParamWatchdog(void); + void setContrast(int val); + void SetVideoMode(analog_mode_t mode); + void SetDBDR(int) { return; }; + void SetAudioHandle(void *) { return; }; + void SetAutoModes(int [VIDEO_STD_MAX]) { return; }; + int OpenVBI(int) { return 0; }; + int CloseVBI(void) { return 0; }; + int StartVBI(unsigned short) { return 0; }; + int StopVBI(void) { return 0; }; + void SetDemux(cDemux *dmx); + void SetColorFormat(COLOR_FORMAT color_format); + bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false); +}; + +#endif From 33f05feccc63f7b1524c163f630a0c329b0a8c57 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Tue, 12 Sep 2017 17:12:00 +0200 Subject: [PATCH 09/73] fix armbox frontpanel --- libarmbox/hardware_caps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libarmbox/hardware_caps.c b/libarmbox/hardware_caps.c index 5dd7fd8..df23c3a 100644 --- a/libarmbox/hardware_caps.c +++ b/libarmbox/hardware_caps.c @@ -17,7 +17,7 @@ #include -#define FP_DEV "/dev/vfd" +#define FP_DEV "/dev/dbox/oled0" static int initialized = 0; static hw_caps_t caps; @@ -32,7 +32,7 @@ hw_caps_t *get_hwcaps(void) caps.has_CI = 0; caps.can_cec = 1; caps.can_shutdown = 1; - caps.display_type = HW_DISPLAY_LED_NUM; + caps.display_type = HW_DISPLAY_LINE_TEXT; caps.can_set_display_brightness = 0; caps.has_HDMI = 1; caps.display_xres = 4; From 7e4b69f3b98e52eb16445bfd03f801157f85c0c3 Mon Sep 17 00:00:00 2001 From: max_10 Date: Thu, 14 Sep 2017 23:33:45 +0200 Subject: [PATCH 10/73] acinclude: remove unused boxtypes --- acinclude.m4 | 80 +++++++++------------------------------------------- 1 file changed, 14 insertions(+), 66 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index f36f39a..f68f835 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -108,25 +108,25 @@ if test "$TARGET" = "cdk"; then fi TUXBOX_APPS_DIRECTORY_ONE(configdir,CONFIGDIR,localstatedir,/var,/tuxbox/config, - [--with-configdir=PATH ],[where to find the config files]) + [--with-configdir=PATH ],[where to find the config files]) TUXBOX_APPS_DIRECTORY_ONE(datadir,DATADIR,datadir,/share,/tuxbox, - [--with-datadir=PATH ],[where to find data]) + [--with-datadir=PATH ],[where to find data]) TUXBOX_APPS_DIRECTORY_ONE(fontdir,FONTDIR,datadir,/share,/fonts, - [--with-fontdir=PATH ],[where to find the fonts]) + [--with-fontdir=PATH ],[where to find the fonts]) TUXBOX_APPS_DIRECTORY_ONE(gamesdir,GAMESDIR,localstatedir,/var,/tuxbox/games, - [--with-gamesdir=PATH ],[where games data is stored]) + [--with-gamesdir=PATH ],[where games data is stored]) TUXBOX_APPS_DIRECTORY_ONE(libdir,LIBDIR,libdir,/lib,/tuxbox, - [--with-libdir=PATH ],[where to find the internal libs]) + [--with-libdir=PATH ],[where to find the internal libs]) TUXBOX_APPS_DIRECTORY_ONE(plugindir,PLUGINDIR,libdir,/lib,/tuxbox/plugins, - [--with-plugindir=PATH ],[where to find the plugins]) + [--with-plugindir=PATH ],[where to find the plugins]) TUXBOX_APPS_DIRECTORY_ONE(themesdir,THEMESDIR,datadir,/share,/tuxbox/neutrino/themes, - [--with-themesdir=PATH ],[where to find the themes (don't change)]) + [--with-themesdir=PATH ],[where to find the themes (don't change)]) ]) dnl automake <= 1.6 needs this specifications @@ -273,9 +273,9 @@ _TUXBOX_APPS_LIB_SYMBOL($1,$2,$3,WARN) AC_DEFUN([TUXBOX_BOXTYPE],[ AC_ARG_WITH(boxtype, - [ --with-boxtype valid values: dbox2,tripledragon,dreambox,ipbox,coolstream,spark,azbox,generic,duckbox,spark7162,armbox], + [ --with-boxtype valid values: tripledragon,spark,azbox,generic,duckbox,spark7162,armbox], [case "${withval}" in - dbox2|dreambox|ipbox|tripledragon|coolstream|azbox|generic) + tripledragon|azbox|generic) BOXTYPE="$withval" ;; spark|spark7162) @@ -339,26 +339,11 @@ AC_ARG_WITH(boxtype, esac], [BOXTYPE="generic"]) AC_ARG_WITH(boxmodel, - [ --with-boxmodel valid for dreambox: dm500, dm500plus, dm600pvr, dm56x0, dm7000, dm7020, dm7025 - valid for ipbox: ip200, ip250, ip350, ip400 + [ --with-boxmodel valid for generic: raspi valid for duckbox: ufs910, ufs912, ufs913, ufs922, atevio7500, fortis_hdbox, octagon1008, hs7110, hs7810a, hs7119, hs7819, dp7000, cuberevo, cuberevo_mini, cuberevo_mini2, cuberevo_250hd, cuberevo_2000hd, cuberevo_3000hd, ipbox9900, ipbox99, ipbox55, arivalink200, tf7700, hl101 valid for spark: spark, spark7162 valid for armbox: armbox], [case "${withval}" in - dm500|dm500plus|dm600pvr|dm56x0|dm7000|dm7020|dm7025) - if test "$BOXTYPE" = "dreambox"; then - BOXMODEL="$withval" - else - AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE]) - fi - ;; - ip200|ip250|ip350|ip400) - if test "$BOXTYPE" = "ipbox"; then - BOXMODEL="$withval" - else - AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE]) - fi - ;; ufs910|ufs912|ufs913|ufs922|atevio7500|fortis_hdbox|octagon1008|hs7110|hs7810a|hs7119|hs7819|dp7000|cuberevo|cuberevo_mini|cuberevo_mini2|cuberevo_250hd|cuberevo_2000hd|cuberevo_3000hd|ipbox9900|ipbox99|ipbox55|arivalink200|tf7700|hl101) if test "$BOXTYPE" = "duckbox"; then BOXMODEL="$withval" @@ -390,36 +375,18 @@ AC_ARG_WITH(boxmodel, *) AC_MSG_ERROR([unsupported value $withval for --with-boxmodel]) ;; - esac], - [if test "$BOXTYPE" = "dreambox" -o "$BOXTYPE" = "ipbox" && test -z "$BOXMODEL"; then - AC_MSG_ERROR([Dreambox/IPBox needs --with-boxmodel]) - fi]) + esac]) AC_SUBST(BOXTYPE) AC_SUBST(BOXMODEL) AM_CONDITIONAL(BOXTYPE_AZBOX, test "$BOXTYPE" = "azbox") -AM_CONDITIONAL(BOXTYPE_DBOX2, test "$BOXTYPE" = "dbox2") AM_CONDITIONAL(BOXTYPE_TRIPLE, test "$BOXTYPE" = "tripledragon") -AM_CONDITIONAL(BOXTYPE_DREAMBOX, test "$BOXTYPE" = "dreambox") -AM_CONDITIONAL(BOXTYPE_IPBOX, test "$BOXTYPE" = "ipbox") -AM_CONDITIONAL(BOXTYPE_COOL, test "$BOXTYPE" = "coolstream") AM_CONDITIONAL(BOXTYPE_SPARK, test "$BOXTYPE" = "spark") AM_CONDITIONAL(BOXTYPE_GENERIC, test "$BOXTYPE" = "generic") AM_CONDITIONAL(BOXTYPE_DUCKBOX, test "$BOXTYPE" = "duckbox") AM_CONDITIONAL(BOXTYPE_ARMBOX, test "$BOXTYPE" = "armbox") -AM_CONDITIONAL(BOXMODEL_DM500,test "$BOXMODEL" = "dm500") -AM_CONDITIONAL(BOXMODEL_DM500PLUS,test "$BOXMODEL" = "dm500plus") -AM_CONDITIONAL(BOXMODEL_DM600PVR,test "$BOXMODEL" = "dm600pvr") -AM_CONDITIONAL(BOXMODEL_DM56x0,test "$BOXMODEL" = "dm56x0") -AM_CONDITIONAL(BOXMODEL_DM7000,test "$BOXMODEL" = "dm7000" -o "$BOXMODEL" = "dm7020" -o "$BOXMODEL" = "dm7025") - -AM_CONDITIONAL(BOXMODEL_IP200,test "$BOXMODEL" = "ip200") -AM_CONDITIONAL(BOXMODEL_IP250,test "$BOXMODEL" = "ip250") -AM_CONDITIONAL(BOXMODEL_IP350,test "$BOXMODEL" = "ip350") -AM_CONDITIONAL(BOXMODEL_IP400,test "$BOXMODEL" = "ip400") - AM_CONDITIONAL(BOXMODEL_UFS910,test "$BOXMODEL" = "ufs910") AM_CONDITIONAL(BOXMODEL_UFS912,test "$BOXMODEL" = "ufs912") AM_CONDITIONAL(BOXMODEL_UFS913,test "$BOXMODEL" = "ufs913") @@ -434,7 +401,6 @@ AM_CONDITIONAL(BOXMODEL_HS7810A,test "$BOXMODEL" = "hs7810a") AM_CONDITIONAL(BOXMODEL_HS7119,test "$BOXMODEL" = "hs7119") AM_CONDITIONAL(BOXMODEL_HS7819,test "$BOXMODEL" = "hs7819") AM_CONDITIONAL(BOXMODEL_DP7000,test "$BOXMODEL" = "dp7000") - AM_CONDITIONAL(BOXMODEL_CUBEREVO,test "$BOXMODEL" = "cuberevo") AM_CONDITIONAL(BOXMODEL_CUBEREVO_MINI,test "$BOXMODEL" = "cuberevo_mini") AM_CONDITIONAL(BOXMODEL_CUBEREVO_MINI2,test "$BOXMODEL" = "cuberevo_mini2") @@ -452,18 +418,10 @@ AM_CONDITIONAL(BOXMODEL_RASPI,test "$BOXMODEL" = "raspi") AM_CONDITIONAL(BOXMODEL_ARMBOX,test "$BOXMODEL" = "armbox") -if test "$BOXTYPE" = "dbox2"; then - AC_DEFINE(HAVE_DBOX_HARDWARE, 1, [building for a dbox2]) -elif test "$BOXTYPE" = "azbox"; then +if test "$BOXTYPE" = "azbox"; then AC_DEFINE(HAVE_AZBOX_HARDWARE, 1, [building for an azbox]) elif test "$BOXTYPE" = "tripledragon"; then AC_DEFINE(HAVE_TRIPLEDRAGON, 1, [building for a tripledragon]) -elif test "$BOXTYPE" = "dreambox"; then - AC_DEFINE(HAVE_DREAMBOX_HARDWARE, 1, [building for a dreambox]) -elif test "$BOXTYPE" = "ipbox"; then - AC_DEFINE(HAVE_IPBOX_HARDWARE, 1, [building for an ipbox]) -elif test "$BOXTYPE" = "coolstream"; then - AC_DEFINE(HAVE_COOL_HARDWARE, 1, [building for a coolstream]) elif test "$BOXTYPE" = "spark"; then AC_DEFINE(HAVE_SPARK_HARDWARE, 1, [building for a goldenmedia 990 or edision pingulux]) elif test "$BOXTYPE" = "armbox"; then @@ -475,16 +433,8 @@ elif test "$BOXTYPE" = "duckbox"; then fi # TODO: do we need more defines? -if test "$BOXMODEL" = "dm500"; then - AC_DEFINE(BOXMODEL_DM500, 1, [dreambox 500]) -elif test "$BOXMODEL" = "ip200"; then - AC_DEFINE(BOXMODEL_IP200, 1, [ipbox 200]) -elif test "$BOXMODEL" = "ip250"; then - AC_DEFINE(BOXMODEL_IP250, 1, [ipbox 250]) -elif test "$BOXMODEL" = "ip350"; then - AC_DEFINE(BOXMODEL_IP350, 1, [ipbox 350]) -elif test "$BOXMODEL" = "ip400"; then - AC_DEFINE(BOXMODEL_IP400, 1, [ipbox 400]) +if test "$BOXMODEL" = "raspi"; then + AC_DEFINE(BOXMODEL_RASPI, 1, [Raspberry pi]) elif test "$BOXMODEL" = "ufs910"; then AC_DEFINE(BOXMODEL_UFS910, 1, [ufs910]) elif test "$BOXMODEL" = "ufs912"; then @@ -537,8 +487,6 @@ elif test "$BOXMODEL" = "tf7700"; then AC_DEFINE(BOXMODEL_TF7700, 1, [tf7700]) elif test "$BOXMODEL" = "hl101"; then AC_DEFINE(BOXMODEL_HL101, 1, [hl101]) -elif test "$BOXMODEL" = "raspi"; then - AC_DEFINE(BOXMODEL_RASPI, 1, [Raspberry pi]) elif test "$BOXMODEL" = "armbox"; then AC_DEFINE(BOXMODEL_ARMBOX, 1, [armbox]) fi From ab0c4a8d47eb3de827b06d1919781c20018405e8 Mon Sep 17 00:00:00 2001 From: max_10 Date: Thu, 14 Sep 2017 23:37:22 +0200 Subject: [PATCH 11/73] acinclude: remove unused TUXBOX_APPS_* stuff --- acinclude.m4 | 136 --------------------------------------------------- configure.ac | 5 +- 2 files changed, 3 insertions(+), 138 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index f68f835..17066d3 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -51,10 +51,6 @@ fi AC_CANONICAL_BUILD AC_CANONICAL_HOST -check_path () { - return $(perl -e "if(\"$1\"=~m#^/usr/(local/)?bin#){print \"0\"}else{print \"1\";}") -} - ]) dnl expand nested ${foo}/bar @@ -139,138 +135,6 @@ AC_SUBST(PLUGINDIR) AC_SUBST(THEMESDIR) dnl end workaround -AC_DEFUN([TUXBOX_APPS_ENDIAN],[ -AC_CHECK_HEADERS(endian.h) -AC_C_BIGENDIAN -]) - -AC_DEFUN([TUXBOX_APPS_DVB],[ -AC_ARG_WITH(dvbincludes, - [ --with-dvbincludes=PATH path for dvb includes [[NONE]]], - [DVBINCLUDES="$withval"],[DVBINCLUDES=""]) - -if test "$DVBINCLUDES"; then - CPPFLAGS="$CPPFLAGS -I$DVBINCLUDES" -fi - -if test -z "$DVB_API_VERSION"; then -AC_CHECK_HEADERS(linux/dvb/version.h,[ - AC_LANG_PREPROC_REQUIRE() - AC_REQUIRE([AC_PROG_EGREP]) - AC_LANG_CONFTEST([AC_LANG_SOURCE([[ -#include -version DVB_API_VERSION - ]])]) - DVB_API_VERSION=`(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | $EGREP "^version" | sed "s,version\ ,,"` - rm -f conftest* - - AC_MSG_NOTICE([found dvb version $DVB_API_VERSION]) -]) -fi - -if test "$DVB_API_VERSION"; then - AC_DEFINE(HAVE_DVB,1,[Define to 1 if you have the dvb includes]) - AC_DEFINE_UNQUOTED(HAVE_DVB_API_VERSION,$DVB_API_VERSION,[Define to the version of the dvb api]) -else - AC_MSG_ERROR([can't find dvb headers]) -fi -]) - -AC_DEFUN([_TUXBOX_APPS_LIB_CONFIG],[ -AC_PATH_PROG($1_CONFIG,$2,no) -if test "$$1_CONFIG" != "no"; then - if test "$TARGET" = "cdk" && check_path "$$1_CONFIG"; then - AC_MSG_$3([could not find a suitable version of $2]); - else - if test "$1" = "CURL"; then - $1_CFLAGS=$($$1_CONFIG --cflags) - $1_LIBS=$($$1_CONFIG --libs) - else - if test "$1" = "FREETYPE"; then - $1_CFLAGS=$($$1_CONFIG --cflags) - $1_LIBS=$($$1_CONFIG --libs) - else - $1_CFLAGS=$($$1_CONFIG --prefix=$targetprefix --cflags) - $1_LIBS=$($$1_CONFIG --prefix=$targetprefix --libs) - fi - fi - fi -fi - -AC_SUBST($1_CFLAGS) -AC_SUBST($1_LIBS) -]) - -AC_DEFUN([TUXBOX_APPS_LIB_CONFIG],[ -_TUXBOX_APPS_LIB_CONFIG($1,$2,ERROR) -if test "$$1_CONFIG" = "no"; then - AC_MSG_ERROR([could not find $2]); -fi -]) - -AC_DEFUN([TUXBOX_APPS_LIB_CONFIG_CHECK],[ -_TUXBOX_APPS_LIB_CONFIG($1,$2,WARN) -]) - -AC_DEFUN([TUXBOX_APPS_PKGCONFIG],[ -m4_pattern_forbid([^_?PKG_[A-Z_]+$]) -m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) -AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) -fi -if test x"$PKG_CONFIG" = x"" ; then - AC_MSG_ERROR([could not find pkg-config]); -fi -]) - -AC_DEFUN([_TUXBOX_APPS_LIB_PKGCONFIG],[ -AC_REQUIRE([TUXBOX_APPS_PKGCONFIG]) -AC_MSG_CHECKING(for package $2) -if $PKG_CONFIG --exists "$2" ; then - AC_MSG_RESULT(yes) - $1_CFLAGS=$($PKG_CONFIG --cflags "$2") - $1_LIBS=$($PKG_CONFIG --libs "$2") - $1_EXISTS=yes -else - AC_MSG_RESULT(no) -fi - -AC_SUBST($1_CFLAGS) -AC_SUBST($1_LIBS) -]) - -AC_DEFUN([TUXBOX_APPS_LIB_PKGCONFIG],[ -_TUXBOX_APPS_LIB_PKGCONFIG($1,$2) -if test x"$$1_EXISTS" != xyes; then - AC_MSG_ERROR([could not find package $2]); -fi -]) - -AC_DEFUN([TUXBOX_APPS_LIB_PKGCONFIG_CHECK],[ -_TUXBOX_APPS_LIB_PKGCONFIG($1,$2) -]) - -AC_DEFUN([_TUXBOX_APPS_LIB_SYMBOL],[ -AC_CHECK_LIB($2,$3,HAVE_$1="yes",HAVE_$1="no") -if test "$HAVE_$1" = "yes"; then - $1_LIBS=-l$2 -fi - -AC_SUBST($1_LIBS) -]) - -AC_DEFUN([TUXBOX_APPS_LIB_SYMBOL],[ -_TUXBOX_APPS_LIB_SYMBOL($1,$2,$3,ERROR) -if test "$HAVE_$1" = "no"; then - AC_MSG_ERROR([could not find $2]); -fi -]) - -AC_DEFUN([TUXBOX_APPS_LIB_CONFIG_SYMBOL],[ -_TUXBOX_APPS_LIB_SYMBOL($1,$2,$3,WARN) -]) - AC_DEFUN([TUXBOX_BOXTYPE],[ AC_ARG_WITH(boxtype, [ --with-boxtype valid values: tripledragon,spark,azbox,generic,duckbox,spark7162,armbox], diff --git a/configure.ac b/configure.ac index 6335ce9..9bdb071 100644 --- a/configure.ac +++ b/configure.ac @@ -6,11 +6,11 @@ AC_GNU_SOURCE TUXBOX_APPS TUXBOX_APPS_DIRECTORY -TUXBOX_APPS_PKGCONFIG TUXBOX_BOXTYPE AC_PROG_CC AC_PROG_CXX +PKG_PROG_PKG_CONFIG ## both disabled => libtool still defaults to static ## at least the libtool I tested with ;-) ## --enable-shared => build only shared @@ -21,7 +21,7 @@ AC_SYS_LARGEFILE AC_PROG_LIBTOOL if test x"$BOXTYPE" = x"tripledragon"; then - TUXBOX_APPS_LIB_PKGCONFIG(DIRECTFB, directfb) + PKG_CHECK_MODULES([DIRECTFB], [directfb]) fi AC_ARG_ENABLE(gstreamer_01, @@ -61,6 +61,7 @@ if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then PKG_CHECK_MODULES([SWSCALE], [libswscale]) PKG_CHECK_MODULES([SWRESAMPLE], [libswresample]) fi + AC_OUTPUT([ Makefile common/Makefile From f7786867c4f9bf10aacc690f2a532153b78d68f1 Mon Sep 17 00:00:00 2001 From: max_10 Date: Thu, 14 Sep 2017 23:42:04 +0200 Subject: [PATCH 12/73] acinclude: add arm boxtypes --- acinclude.m4 | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 17066d3..7f534c5 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -194,7 +194,11 @@ AC_ARG_WITH(boxtype, BOXTYPE="duckbox" BOXMODEL="$withval" ;; - armbox) + hd51) + BOXTYPE="armbox" + BOXMODEL="$withval" + ;; + vusolo4k) BOXTYPE="armbox" BOXMODEL="$withval" ;; @@ -206,7 +210,7 @@ AC_ARG_WITH(boxmodel, [ --with-boxmodel valid for generic: raspi valid for duckbox: ufs910, ufs912, ufs913, ufs922, atevio7500, fortis_hdbox, octagon1008, hs7110, hs7810a, hs7119, hs7819, dp7000, cuberevo, cuberevo_mini, cuberevo_mini2, cuberevo_250hd, cuberevo_2000hd, cuberevo_3000hd, ipbox9900, ipbox99, ipbox55, arivalink200, tf7700, hl101 valid for spark: spark, spark7162 - valid for armbox: armbox], + valid for armbox: hd51, vusolo4k], [case "${withval}" in ufs910|ufs912|ufs913|ufs922|atevio7500|fortis_hdbox|octagon1008|hs7110|hs7810a|hs7119|hs7819|dp7000|cuberevo|cuberevo_mini|cuberevo_mini2|cuberevo_250hd|cuberevo_2000hd|cuberevo_3000hd|ipbox9900|ipbox99|ipbox55|arivalink200|tf7700|hl101) if test "$BOXTYPE" = "duckbox"; then @@ -229,7 +233,14 @@ AC_ARG_WITH(boxmodel, AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE]) fi ;; - armbox) + hd51) + if test "$BOXTYPE" = "armbox"; then + BOXMODEL="$withval" + else + AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE]) + fi + ;; + vusolo4k) if test "$BOXTYPE" = "armbox"; then BOXMODEL="$withval" else @@ -278,9 +289,10 @@ AM_CONDITIONAL(BOXMODEL_ARIVALINK200,test "$BOXMODEL" = "arivalink200") AM_CONDITIONAL(BOXMODEL_TF7700,test "$BOXMODEL" = "tf7700") AM_CONDITIONAL(BOXMODEL_HL101,test "$BOXMODEL" = "hl101") -AM_CONDITIONAL(BOXMODEL_RASPI,test "$BOXMODEL" = "raspi") +AM_CONDITIONAL(BOXMODEL_HD51,test "$BOXMODEL" = "hd51") +AM_CONDITIONAL(BOXMODEL_VUSOLO4K,test "$BOXMODEL" = "vusolo4k") -AM_CONDITIONAL(BOXMODEL_ARMBOX,test "$BOXMODEL" = "armbox") +AM_CONDITIONAL(BOXMODEL_RASPI,test "$BOXMODEL" = "raspi") if test "$BOXTYPE" = "azbox"; then AC_DEFINE(HAVE_AZBOX_HARDWARE, 1, [building for an azbox]) @@ -288,12 +300,13 @@ elif test "$BOXTYPE" = "tripledragon"; then AC_DEFINE(HAVE_TRIPLEDRAGON, 1, [building for a tripledragon]) elif test "$BOXTYPE" = "spark"; then AC_DEFINE(HAVE_SPARK_HARDWARE, 1, [building for a goldenmedia 990 or edision pingulux]) -elif test "$BOXTYPE" = "armbox"; then - AC_DEFINE(HAVE_ARM_HARDWARE, 1, [building for a armbox]) elif test "$BOXTYPE" = "generic"; then AC_DEFINE(HAVE_GENERIC_HARDWARE, 1, [building for a generic device like a standard PC]) elif test "$BOXTYPE" = "duckbox"; then AC_DEFINE(HAVE_DUCKBOX_HARDWARE, 1, [building for a duckbox]) +elif test "$BOXTYPE" = "armbox"; then + AC_DEFINE(HAVE_ARM_HARDWARE, 1, [building for a armbox]) + fi # TODO: do we need more defines? @@ -351,8 +364,10 @@ elif test "$BOXMODEL" = "tf7700"; then AC_DEFINE(BOXMODEL_TF7700, 1, [tf7700]) elif test "$BOXMODEL" = "hl101"; then AC_DEFINE(BOXMODEL_HL101, 1, [hl101]) -elif test "$BOXMODEL" = "armbox"; then - AC_DEFINE(BOXMODEL_ARMBOX, 1, [armbox]) +elif test "$BOXMODEL" = "hd51"; then + AC_DEFINE(BOXMODEL_HD51, 1, [HD51 / AX51]) +elif test "$BOXMODEL" = "vusolo4k"; then + AC_DEFINE(BOXMODEL_VUSOLO4K, 1, [vusolo4k]) fi ]) From ee1ca3ff658bdb324f5befb7df4c6dd1f44eb4db Mon Sep 17 00:00:00 2001 From: max_10 Date: Fri, 15 Sep 2017 13:19:21 +0200 Subject: [PATCH 13/73] add video_cs.h header to reduce number of #ifdefs needed --- include/video_cs.h | 1 + 1 file changed, 1 insertion(+) create mode 100644 include/video_cs.h diff --git a/include/video_cs.h b/include/video_cs.h new file mode 100644 index 0000000..f1d48d4 --- /dev/null +++ b/include/video_cs.h @@ -0,0 +1 @@ +#include "video_hal.h" From 814f92096b2a4cfc51b38c2de2f6989164c26212 Mon Sep 17 00:00:00 2001 From: max_10 Date: Fri, 15 Sep 2017 14:29:29 +0200 Subject: [PATCH 14/73] cs_api.h: add missing cs_get_chip_type() dummy --- libarmbox/cs_api.h | 1 + libduckbox/cs_api.h | 1 + libspark/cs_api.h | 1 + libtriple/cs_api.h | 1 + 4 files changed, 4 insertions(+) diff --git a/libarmbox/cs_api.h b/libarmbox/cs_api.h index fb5d613..e4349dd 100644 --- a/libarmbox/cs_api.h +++ b/libarmbox/cs_api.h @@ -62,5 +62,6 @@ unsigned long long cs_get_serial(void); #endif /* compat... HD1 seems to be version 6. everything newer ist > 6... */ static inline unsigned int cs_get_revision(void) { return 1; }; +static inline unsigned int cs_get_chip_type(void) { return 0; }; extern int cnxt_debug; #endif //__CS_API_H_ diff --git a/libduckbox/cs_api.h b/libduckbox/cs_api.h index 8ac8d93..1082ab7 100644 --- a/libduckbox/cs_api.h +++ b/libduckbox/cs_api.h @@ -26,5 +26,6 @@ static inline void cs_deregister_messenger(void) { return; }; /* compat... HD1 seems to be version 6. everything newer ist > 6... */ static inline unsigned int cs_get_revision(void) { return 1; }; +static inline unsigned int cs_get_chip_type(void) { return 0; }; extern int cnxt_debug; #endif //__CS_API_H_ diff --git a/libspark/cs_api.h b/libspark/cs_api.h index fb5d613..e4349dd 100644 --- a/libspark/cs_api.h +++ b/libspark/cs_api.h @@ -62,5 +62,6 @@ unsigned long long cs_get_serial(void); #endif /* compat... HD1 seems to be version 6. everything newer ist > 6... */ static inline unsigned int cs_get_revision(void) { return 1; }; +static inline unsigned int cs_get_chip_type(void) { return 0; }; extern int cnxt_debug; #endif //__CS_API_H_ diff --git a/libtriple/cs_api.h b/libtriple/cs_api.h index 292430d..47890e0 100644 --- a/libtriple/cs_api.h +++ b/libtriple/cs_api.h @@ -62,5 +62,6 @@ unsigned long long cs_get_serial(void); #endif /* compat... HD1 seems to be version 6. everything newer ist > 6... */ static inline unsigned int cs_get_revision(void) { return 1; }; +static inline unsigned int cs_get_chip_type(void) { return 0; }; extern int cnxt_debug; #endif //__CS_API_H_ From 7e61b2a3ea5efdf864d1f98653686c34e5eaa7cd Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 17 Sep 2017 20:37:57 +0200 Subject: [PATCH 15/73] fix gst flags --- libarmbox/playback_gst.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index 53d9a5c..790b1c0 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -49,15 +49,18 @@ static const char * FILENAME = "[playback.cpp]"; typedef enum { - GST_PLAY_FLAG_VIDEO = 0x00000001, - GST_PLAY_FLAG_AUDIO = 0x00000002, - GST_PLAY_FLAG_TEXT = 0x00000004, - GST_PLAY_FLAG_VIS = 0x00000008, - GST_PLAY_FLAG_SOFT_VOLUME = 0x00000010, - GST_PLAY_FLAG_NATIVE_AUDIO = 0x00000020, - GST_PLAY_FLAG_NATIVE_VIDEO = 0x00000040, - GST_PLAY_FLAG_DOWNLOAD = 0x00000080, - GST_PLAY_FLAG_BUFFERING = 0x000000100 + GST_PLAY_FLAG_VIDEO = (1 << 0), + GST_PLAY_FLAG_AUDIO = (1 << 1), + GST_PLAY_FLAG_TEXT = (1 << 2), + GST_PLAY_FLAG_VIS = (1 << 3), + GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4), + GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5), + GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6), + GST_PLAY_FLAG_DOWNLOAD = (1 << 7), + GST_PLAY_FLAG_BUFFERING = (1 << 8), + GST_PLAY_FLAG_DEINTERLACE = (1 << 9), + GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10), + GST_PLAY_FLAG_FORCE_FILTERS = (1 << 11), } GstPlayFlags; @@ -389,6 +392,9 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, lt_info("%s:%s - filename=%s\n", FILENAME, __FUNCTION__, filename); + guint flags = GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | \ + GST_PLAY_FLAG_TEXT | GST_PLAY_FLAG_NATIVE_VIDEO; + // create gst pipeline m_gst_playbin = gst_element_factory_make ("playbin", "playbin"); @@ -396,13 +402,6 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, { lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__); - guint flags; - g_object_get(G_OBJECT (m_gst_playbin), "flags", &flags, NULL); - /* avoid video conversion, let the (hardware) sinks handle that */ - flags |= GST_PLAY_FLAG_NATIVE_VIDEO; - /* volume control is done by hardware */ - flags &= ~GST_PLAY_FLAG_SOFT_VOLUME; - g_object_set(G_OBJECT (m_gst_playbin), "uri", uri, NULL); g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL); From 17b3fefac81db905a522cd9fb83d41a0454ca98f Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 17 Sep 2017 20:53:57 +0200 Subject: [PATCH 16/73] armbox: fix PIG --- libarmbox/video.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 41855db..f62a525 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -85,6 +85,26 @@ static const char *VMPEG_dst_all[] = { "/proc/stb/vmpeg/1/dst_all" }; +static const char *VMPEG_dst_height[] = { + "/proc/stb/vmpeg/0/dst_height", + "/proc/stb/vmpeg/1/dst_height" +}; + +static const char *VMPEG_dst_width[] = { + "/proc/stb/vmpeg/0/dst_width", + "/proc/stb/vmpeg/1/dst_width" +}; + +static const char *VMPEG_dst_top[] = { + "/proc/stb/vmpeg/0/dst_top", + "/proc/stb/vmpeg/1/dst_top" +}; + +static const char *VMPEG_dst_left[] = { + "/proc/stb/vmpeg/0/dst_left", + "/proc/stb/vmpeg/1/dst_left" +}; + static const char *VMPEG_framerate[] = { "/proc/stb/vmpeg/0/framerate", "/proc/stb/vmpeg/1/framerate" @@ -653,8 +673,17 @@ void cVideo::Pig(int x, int y, int w, int h, int osd_w, int osd_h, int startx, i _h /= 720; } lt_debug("#%d %s: x:%d y:%d w:%d h:%d xr:%d yr:%d\n", devnum, __func__, _x, _y, _w, _h, xres, yres); - sprintf(buffer, "%x %x %x %x", _x, _y, _w, _h); - proc_put(VMPEG_dst_all[devnum], buffer, strlen(buffer)); + sprintf(buffer, "%x", _x); + proc_put(VMPEG_dst_left[devnum], buffer, strlen(buffer)); + + sprintf(buffer, "%x", _y); + proc_put(VMPEG_dst_top[devnum], buffer, strlen(buffer)); + + sprintf(buffer, "%x", _w); + proc_put(VMPEG_dst_width[devnum], buffer, strlen(buffer)); + + sprintf(buffer, "%x", _h); + proc_put(VMPEG_dst_height[devnum], buffer, strlen(buffer)); } static inline int rate2csapi(int rate) From 63cb1f936c825cc3de3a973aee1038737fc13827 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 17 Sep 2017 20:54:10 +0200 Subject: [PATCH 17/73] armbox: align to demuxes --- libarmbox/dmx.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libarmbox/dmx.cpp b/libarmbox/dmx.cpp index d3ba4e7..cb16b20 100644 --- a/libarmbox/dmx.cpp +++ b/libarmbox/dmx.cpp @@ -110,14 +110,19 @@ static const char *DMX_T[] = { static int dmx_source[NUM_DEMUX] = { 0, 0, 0, 0 }; /* map the device numbers. */ -#define NUM_DEMUXDEV 3 +#define NUM_DEMUXDEV 8 static const char *devname[NUM_DEMUXDEV] = { "/dev/dvb/adapter0/demux0", "/dev/dvb/adapter0/demux1", - "/dev/dvb/adapter0/demux2" + "/dev/dvb/adapter0/demux2", + "/dev/dvb/adapter0/demux3", + "/dev/dvb/adapter0/demux4", + "/dev/dvb/adapter0/demux5", + "/dev/dvb/adapter0/demux6", + "/dev/dvb/adapter0/demux7" }; /* did we already DMX_SET_SOURCE on that demux device? */ -static bool init[NUM_DEMUXDEV] = { false, false, false }; +static bool init[NUM_DEMUXDEV] = { false, false, false, false, false, false, false, false }; /* uuuugly */ static int dmx_tp_count = 0; From b55bbce62d211c0ea3913f02611d86510504a270 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Mon, 18 Sep 2017 19:57:12 +0200 Subject: [PATCH 18/73] fix armbox vfd --- libarmbox/hardware_caps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libarmbox/hardware_caps.c b/libarmbox/hardware_caps.c index df23c3a..3041216 100644 --- a/libarmbox/hardware_caps.c +++ b/libarmbox/hardware_caps.c @@ -32,10 +32,10 @@ hw_caps_t *get_hwcaps(void) caps.has_CI = 0; caps.can_cec = 1; caps.can_shutdown = 1; + caps.display_xres = 16; caps.display_type = HW_DISPLAY_LINE_TEXT; - caps.can_set_display_brightness = 0; + caps.can_set_display_brightness = 1; caps.has_HDMI = 1; - caps.display_xres = 4; strcpy(caps.boxvendor, "armbox"); strcpy(caps.boxname, "armbox"); strcpy(caps.boxarch,caps.boxname); From 1356d700be203d3107f32dafdf2c22e675898f09 Mon Sep 17 00:00:00 2001 From: max_10 Date: Tue, 19 Sep 2017 12:13:38 +0200 Subject: [PATCH 19/73] libeplayer3: switch off the teletext sub --- libeplayer3/input.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libeplayer3/input.cpp b/libeplayer3/input.cpp index 19af03e..f4621f9 100644 --- a/libeplayer3/input.cpp +++ b/libeplayer3/input.cpp @@ -80,7 +80,7 @@ extern void dvbsub_write(AVSubtitle *, int64_t); extern void dvbsub_ass_write(AVCodecContext *c, AVSubtitle *sub, int pid); extern void dvbsub_ass_clear(void); // from neutrino-mp/lib/lib/libtuxtxt/tuxtxt_common.h -extern void teletext_write(int pid, uint8_t *data, int size); +//extern void teletext_write(int pid, uint8_t *data, int size); static std::string lastlog_message; static unsigned int lastlog_repeats; @@ -253,10 +253,11 @@ bool Input::Play() } } } - } else if (_teletextTrack && (_teletextTrack->stream == stream)) { - if (packet.data && packet.size > 1) - teletext_write(_teletextTrack->pid, packet.data + 1, packet.size - 1); } +// else if (_teletextTrack && (_teletextTrack->stream == stream)) { +// if (packet.data && packet.size > 1) +// teletext_write(_teletextTrack->pid, packet.data + 1, packet.size - 1); +// } #if (LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR == 25) av_packet_unref(&packet); From 7cc65ef5332ca1b9d2ad49b955cb228334cc0d27 Mon Sep 17 00:00:00 2001 From: max_10 Date: Tue, 19 Sep 2017 17:47:21 +0200 Subject: [PATCH 20/73] duplicate entry removed --- generic-pc/playback.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/generic-pc/playback.cpp b/generic-pc/playback.cpp index 86b6b6f..9b6899f 100644 --- a/generic-pc/playback.cpp +++ b/generic-pc/playback.cpp @@ -131,11 +131,6 @@ void cPlayback::SetTitle(int /*title*/) { } -uint64_t cPlayback::GetReadCount() -{ - return 0; -} - cPlayback::cPlayback(int /*num*/) { printf("%s:%s\n", FILENAME, __func__); From 2054081eeb0ce73a28153172fb57b73334185e2f Mon Sep 17 00:00:00 2001 From: max_10 Date: Mon, 25 Sep 2017 14:49:38 +0200 Subject: [PATCH 21/73] libarmbox delete unnecessary code --- libarmbox/README.libtriple | 72 - libarmbox/dmx.cpp | 5 +- libarmbox/init.cpp | 273 --- libarmbox/irmp.c | 4284 ------------------------------------ libarmbox/irmp.h | 528 ----- libarmbox/irmpconfig.h | 191 -- libarmbox/lirmp_input.cpp | 445 ---- libarmbox/lirmp_input.h | 7 - libarmbox/video.cpp | 242 +- libarmbox/video_lib.h | 1 - 10 files changed, 6 insertions(+), 6042 deletions(-) delete mode 100644 libarmbox/README.libtriple delete mode 100644 libarmbox/irmp.c delete mode 100644 libarmbox/irmp.h delete mode 100644 libarmbox/irmpconfig.h delete mode 100644 libarmbox/lirmp_input.cpp delete mode 100644 libarmbox/lirmp_input.h diff --git a/libarmbox/README.libtriple b/libarmbox/README.libtriple deleted file mode 100644 index 89f65b7..0000000 --- a/libarmbox/README.libtriple +++ /dev/null @@ -1,72 +0,0 @@ -libtriple reimplements the interfaces of the libcoolstrem library for -the Tripledragon receiver. - -There are a few debugging or configuration helpers which affect the -way libtriple does some things. They are all configured by exporting -environment variables, which are described here: - -TRIPLE_NOSCART=1 - makes neutrino *not* do any voltage switching on - SCART pin 8, probably not useful for anyone but me - -TRIPLE_DEBUG=... - controls various debugging levels in libtriple - valid values for the different component: - audio 0x01 - video 0x02 - demux 0x04 - play 0x08 - power 0x10 - init 0x20 - ca 0x40 - record 0x80 - all 0xff - multiple levels are added / ORed together, so if you want to - debug record and playback code, do "export TRIPLE_DEBUG=0x88" - for audio & video use TRIPLE_DEBUG=0x3 - -DSP_DEVICE -MIX_DEVICE - alternative audio devices for the audioplayer and internet - radio. Those are used to output music to e.g. USB audio devices. - Here is what you need to do: - * look in /dev/sound which devices are already there. Probably - /dev/sound/dsp and /dev/sound/mixer, created by the tdoss driver - * make sure that the USB HC driver is loaded: - modprobe ohci-hcd - * load the USB audio driver: - modprobe audio - * plug in your USB audio device, check with "dmesg" that it is - recognised by the kernel - * look in /dev/sound which new devices are there. Probably it's - /dev/sound/dsp1 and /dev/sound/mixer1. If there are more - well - it's time to experiment ;) - * export DSP_DEVICE=/dev/sound/dsp1 and MIX_DEVICE=/dev/sound/mixer1 - (of course the devices you found in the last step) - * from the same shell you exported the variables, start neutrino - (make sure that an already running neutrino is stopped before you - do that) - * start the audioplayer, play a track. Look for log lines like - [LT:106b5788:audio ] PrepareClipPlay: dsp_dev /dev/sound/dsp1 mix_dev /dev/sound/mixer1 - * if it works - fine :-) - * if it does not work, look for: - PrepareClipPlay: DSP_DEVICE is set (/dev/sound/dsp1) but cannot be opened, fall back to /dev/sound/dsp - PrepareClipPlay: dsp_dev /dev/sound/dsp mix_dev /dev/sound/mixer1 - PrepareClipPlay: open mixer /dev/sound/mixer1 failed (No such file or directory) - * this basically means that the device is not there. Different errors - will get different messages - I cannot trigger those now, so you'll - need to find them out by yourself ;) - * another possible messag you may get is: - PrepareClipPlay: more than one mixer control: devmask 00000021 stereo 00000021 - This means that your device has more than one mixer. The set bit - numbers in the devmask are the different mixers, in this case - it would be number 0 and 5. To select one of those, export - MIX_NUMBER=5 or MIX_NUMBER=0 (this code is untested, there may - be bugs) - - So now I found out what devices to use, but how do I make that permanent? - That's easy: - * create or extend /etc/rcS.local with - modprobe ohci-hcd - modprobe audio - * create or extend /etc/profile.local with - export DSP_DEVICE=/dev/sound/dsp1 - export MIX_DEVICE=/dev/sound/mixer1 - * reboot. Enjoy. diff --git a/libarmbox/dmx.cpp b/libarmbox/dmx.cpp index cb16b20..70eeed1 100644 --- a/libarmbox/dmx.cpp +++ b/libarmbox/dmx.cpp @@ -90,7 +90,6 @@ extern cVideo *videoDecoder; cDemux *videoDemux = NULL; cDemux *audioDemux = NULL; -//cDemux *pcrDemux = NULL; static const char *DMX_T[] = { "DMX_INVALID", @@ -483,10 +482,10 @@ bool cDemux::pesFilter(const unsigned short pid) _open(); memset(&p_flt, 0, sizeof(p_flt)); - p_flt.pid = pid; + p_flt.pid = pid; p_flt.output = DMX_OUT_DECODER; p_flt.input = DMX_IN_FRONTEND; - p_flt.flags = DMX_IMMEDIATE_START; + p_flt.flags = 0; switch (dmx_type) { case DMX_PCR_ONLY_CHANNEL: diff --git a/libarmbox/init.cpp b/libarmbox/init.cpp index b52ecca..fc1129f 100644 --- a/libarmbox/init.cpp +++ b/libarmbox/init.cpp @@ -1,6 +1,3 @@ - -#include - #include #include "init_lib.h" @@ -12,254 +9,12 @@ #include #include -#include - #include "pwrmngr.h" #include "lt_debug.h" #define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args) #define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define VIRTUALINPUT "/sys/devices/virtual/input" -#define DEVINPUT "/dev/input" - -typedef struct { - const char *name; - const char *desc; - int fd; - unsigned int major; - unsigned int minor; - time_t next_discovery; -} input_device_t; - -static input_device_t input_device[] = { - { "/dev/input/nevis_ir", "lircd", -1, 0, 0, 0 }, - { "/dev/input/tdt_rc", "TDT RC event driver", -1, 0, 0, 0 }, - { "/dev/input/fulan_fp", "fulan front panel buttons", -1, 0, 0, 0 }, - { "/dev/input/event0", NULL, -1, 0, 0, 0 }, - { "/dev/input/event1", NULL, -1, 0, 0, 0 }, - { "/dev/input/event2", NULL, -1, 0, 0, 0 }, - { "/dev/input/event3", NULL, -1, 0, 0, 0 }, - { "/dev/input/event4", NULL, -1, 0, 0, 0 }, - { "/dev/input/event5", NULL, -1, 0, 0, 0 }, - { "/dev/input/event6", NULL, -1, 0, 0, 0 }, - { "/dev/input/event7", NULL, -1, 0, 0, 0 }, - { NULL, NULL, -1, 0, 0, 0 } -}; - -#define number_of_input_devices (sizeof(input_device)/sizeof(input_device_t) - 1) - -static void do_mknod(int i, char *d_name) { - char name[255]; - int dev = -1; - // I've no idea how the event device number is actually calculated. Just loop. --martii - - for (int j = 0; j < 99 && dev < 0; j++) { - snprintf(name, sizeof(name), VIRTUALINPUT "/%s/event%d/dev", d_name, j); - dev = open (name, O_RDONLY); - } - - if (dev > -1) { - char buf[255]; - int l = read(dev, buf, sizeof(buf) - 1); - close(dev); - if (l > -1) { - buf[l] = 0; - if (2 == sscanf(buf, "%d:%d", &input_device[i].major, &input_device[i].minor)) { - mknod(input_device[i].name, 0666 | S_IFCHR, - gnu_dev_makedev(input_device[i].major, input_device[i].minor)); - } - } - } -} - -static void create_input_devices (void) { - DIR *d = opendir (VIRTUALINPUT); - if (d) { - struct dirent *e; - while ((e = readdir(d))) { - char name[255]; - if (e->d_name[0] == '.') - continue; - snprintf(name, sizeof(name), VIRTUALINPUT "/%s/name", e->d_name); - int n = open(name, O_RDONLY); - if (n > -1) { - char buf[255]; - int l = read(n, buf, sizeof(buf) - 1); - close(n); - if (l > 1) { - do - buf[l--] = 0; - while (l > 1 && buf[l] == '\n'); - - for (unsigned int i = 0; i < number_of_input_devices; i++) - if (input_device[i].desc && !strcmp(buf, input_device[i].desc)) { - do_mknod(i, e->d_name); - break; - } - } - } - } - closedir(d); - } - // remove any event* files left that point to our "well-known" inputs - d = opendir (DEVINPUT); - if (d) { - struct dirent *e; - while ((e = readdir(d))) { - char name[255]; - if (strncmp(e->d_name, "event", 5)) - continue; - snprintf(name, sizeof(name), DEVINPUT "/%s", e->d_name); - struct stat st; - if (stat(name, &st)) - continue; - for (unsigned int i = 0; i < number_of_input_devices; i++) - if (input_device[i].major && - gnu_dev_major(st.st_rdev) == input_device[i].major && - gnu_dev_minor(st.st_rdev) == input_device[i].minor) - unlink(name); - } - closedir(d); - } -} - -static pthread_t inmux_task = 0; -static int inmux_thread_running = 0; - -static void open_input_devices(void) { - time_t now = time(NULL); - for (unsigned int i = 0; i < number_of_input_devices; i++) - if ((input_device[i].fd < 0) && (input_device[i].next_discovery <= now)) { - input_device[i].next_discovery = now + 60; - input_device[i].fd = open(input_device[i].name, O_RDWR | O_NONBLOCK); - } -} - -static void reopen_input_devices(void) { - create_input_devices(); - time_t now = time(NULL); - for (unsigned int i = 0; i < number_of_input_devices; i++) { - input_device[i].next_discovery = now + 60; - int fd = open(input_device[i].name, O_RDWR | O_NONBLOCK); - if (fd > -1) { - if (input_device[i].fd > -1) { - dup2(fd, input_device[i].fd); - close (fd); - } else { - input_device[i].fd = fd; - } - } else if (input_device[i].fd > -1) { - close (input_device[i].fd); - input_device[i].fd = -1; - } - } -} - -static void close_input_devices(void) { - for (unsigned int i = 0; i < number_of_input_devices; i++) - if (input_device[i].fd > -1) { - close(input_device[i].fd); - input_device[i].fd = -1; - } -} - -static void poll_input_devices(void) { - struct pollfd fds[number_of_input_devices]; - input_device_t *inputs[number_of_input_devices]; - int nfds = 0; - for (unsigned int i = 1; i < number_of_input_devices; i++) - if (input_device[i].fd > -1) { - fds[nfds].fd = input_device[i].fd; - fds[nfds].events = POLLIN | POLLHUP | POLLERR; - fds[nfds].revents = 0; - inputs[nfds] = &input_device[i]; - nfds++; - } - - if (nfds == 0) { - // Only a single input device, which happens to be our master. poll() to avoid looping too fast. - fds[0].fd = input_device[0].fd; - fds[0].events = POLLIN | POLLHUP | POLLERR; - fds[0].revents = 0; - poll(fds, 1, 60000 /* ms */); - return; - } - - int r = poll(fds, nfds, 60000 /* ms */); - if (r < 0) { - if (errno != EAGAIN) { - lt_info("%s: poll(): %m\n", __func__); - inmux_thread_running = 0; - } - return; - } - for (int i = 0; i < nfds && r > 0; i++) { - if (fds[i].revents & POLLIN) { -//fprintf(stderr, "### input from fd %d (%s)\n", fds[i].fd, inputs[i]->name); - struct input_event ev; - while (sizeof(ev) == read(fds[i].fd, &ev, sizeof(ev))) - write(input_device[0].fd, &ev, sizeof(ev)); - r--; - } else if (fds[i].revents & (POLLHUP | POLLERR | POLLNVAL)) { -//fprintf(stderr, "### error on %d (%s)\n", fds[i].fd, inputs[i]->name); - close (fds[i].fd); - inputs[i]->fd = -1; - r--; - } - } -} - -static void *inmux_thread(void *) -{ - char threadname[17]; - strncpy(threadname, __func__, sizeof(threadname)); - threadname[16] = 0; - prctl (PR_SET_NAME, (unsigned long)&threadname); - - inmux_thread_running = 1; - while (inmux_thread_running) { - open_input_devices(); - poll_input_devices(); - } - - return NULL; -} - -void start_inmux_thread(void) -{ - input_device[0].fd = open(input_device[0].name, O_RDWR | O_NONBLOCK); // nevis_ir. This is mandatory. - if (input_device[0].fd < 0){ - lt_info("%s: open(%s): %m\n", __func__, input_device[0].name); - return; - } - if (pthread_create(&inmux_task, 0, inmux_thread, NULL) != 0) - { - lt_info("%s: inmux thread pthread_create: %m\n", __func__); - inmux_thread_running = 0; - return; - } - pthread_detach(inmux_task); -} - -void stop_inmux_thread(void) -{ - inmux_thread_running = 0; -} - static bool initialized = false; void init_td_api() @@ -271,31 +26,7 @@ void init_td_api() { cCpuFreqManager f; f.SetCpuFreq(0); /* CPUFREQ == 0 is the trigger for leaving standby */ - create_input_devices(); - start_inmux_thread(); - -#if 0 - /* this is a strange hack: the drivers seem to only work correctly after - * demux0 has been used once. After that, we can use demux1,2,... */ - struct dmx_pes_filter_params p; - int dmx = open("/dev/dvb/adapter0/demux0", O_RDWR|O_CLOEXEC); - if (dmx < 0) - lt_info("%s: ERROR open /dev/dvb/adapter0/demux0 (%m)\n", __func__); - else - { - memset(&p, 0, sizeof(p)); - p.output = DMX_OUT_DECODER; - p.input = DMX_IN_FRONTEND; - p.flags = DMX_IMMEDIATE_START; - p.pes_type = DMX_PES_VIDEO; - ioctl(dmx, DMX_SET_PES_FILTER, &p); - ioctl(dmx, DMX_STOP); - close(dmx); - } -#endif } - else - reopen_input_devices(); initialized = true; lt_info("%s end\n", __FUNCTION__); } @@ -303,9 +34,5 @@ void init_td_api() void shutdown_td_api() { lt_info("%s, initialized = %d\n", __FUNCTION__, (int)initialized); - if (initialized) { - stop_inmux_thread(); - close_input_devices(); - } initialized = false; } diff --git a/libarmbox/irmp.c b/libarmbox/irmp.c deleted file mode 100644 index 68b82cc..0000000 --- a/libarmbox/irmp.c +++ /dev/null @@ -1,4284 +0,0 @@ -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * irmp.c - infrared multi-protocol decoder, supports several remote control protocols - * - * Copyright (c) 2009-2011 Frank Meyer - frank(at)fli4l.de - * - * $Id: irmp.c,v 1.115 2012/02/21 08:41:46 fm Exp $ - * - * ATMEGA88 @ 8 MHz - * - * Supported mikrocontrollers: - * - * ATtiny45, ATtiny85 - * ATtiny84 - * ATmega8, ATmega16, ATmega32 - * ATmega162 - * ATmega164, ATmega324, ATmega644, ATmega644P, ATmega1284 - * ATmega88, ATmega88P, ATmega168, ATmega168P, ATmega328P - * - * Typical manufacturers of remote controls: - * - * SIRCS - Sony - * NEC - NEC, Yamaha, Canon, Tevion, Harman/Kardon, Hitachi, JVC, Pioneer, Toshiba, Xoro, Orion, and many other Japanese manufacturers - * SAMSUNG - Samsung - * SAMSUNG32 - Samsung - * MATSUSHITA - Matsushita - * KASEIKYO - Panasonic, Denon & other Japanese manufacturers (members of "Japan's Association for Electric Home Application") - * RECS80 - Philips, Nokia, Thomson, Nordmende, Telefunken, Saba - * RC5 - Philips and other European manufacturers - * DENON - Denon, Sharp - * RC6 - Philips and other European manufacturers - * APPLE - Apple - * NUBERT - Nubert Subwoofer System - * B&O - Bang & Olufsen - * PANASONIC - Panasonic (older, yet not implemented) - * GRUNDIG - Grundig - * NOKIA - Nokia - * SIEMENS - Siemens, e.g. Gigaset M740AV - * FDC - FDC IR keyboard - * RCCAR - IR remote control for RC cars - * JVC - JVC - * THOMSON - Thomson - * NIKON - Nikon cameras - * RUWIDO - T-Home - * KATHREIN - Kathrein - * LEGO - Lego Power Functions RC - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * SIRCS - * ----- - * - * frame: 1 start bit + 12-20 data bits + no stop bit - * data: 7 command bits + 5 address bits + 0 to 8 additional bits - * - * start bit: data "0": data "1": stop bit: - * -----------------_________ ------_____ ------------______ - * 2400us 600us 600us 600us 1200us 600 us no stop bit - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * NEC + extended NEC - * ------------------------- - * - * frame: 1 start bit + 32 data bits + 1 stop bit - * data NEC: 8 address bits + 8 inverted address bits + 8 command bits + 8 inverted command bits - * data extended NEC: 16 address bits + 8 command bits + 8 inverted command bits - * - * start bit: data "0": data "1": stop bit: - * -----------------_________ ------______ ------________________ ------______.... - * 9000us 4500us 560us 560us 560us 1690 us 560us - * - * - * Repetition frame: - * - * -----------------_________------______ .... ~100ms Pause, then repeat - * 9000us 2250us 560us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * SAMSUNG - * ------- - * - * frame: 1 start bit + 16 data(1) bits + 1 sync bit + additional 20 data(2) bits + 1 stop bit - * data(1): 16 address bits - * data(2): 4 ID bits + 8 command bits + 8 inverted command bits - * - * start bit: data "0": data "1": sync bit: stop bit: - * ----------______________ ------______ ------________________ ------______________ ------______.... - * 4500us 4500us 550us 450us 550us 1450us 550us 4500us 550us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * SAMSUNG32 - * ---------- - * - * frame: 1 start bit + 32 data bits + 1 stop bit - * data: 16 address bits + 16 command bits - * - * start bit: data "0": data "1": stop bit: - * ----------______________ ------______ ------________________ ------______.... - * 4500us 4500us 550us 450us 550us 1450us 550us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * MATSUSHITA - * ---------- - * - * frame: 1 start bit + 24 data bits + 1 stop bit - * data: 6 custom bits + 6 command bits + 12 address bits - * - * start bit: data "0": data "1": stop bit: - * ----------_________ ------______ ------________________ ------______.... - * 3488us 3488us 872us 872us 872us 2616us 872us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * KASEIKYO - * -------- - * - * frame: 1 start bit + 48 data bits + 1 stop bit - * data: 16 manufacturer bits + 4 parity bits + 4 genre1 bits + 4 genre2 bits + 10 command bits + 2 id bits + 8 parity bits - * - * start bit: data "0": data "1": stop bit: - * ----------______ ------______ ------________________ ------______.... - * 3380us 1690us 423us 423us 423us 1269us 423us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * RECS80 - * ------ - * - * frame: 2 start bits + 10 data bits + 1 stop bit - * data: 1 toggle bit + 3 address bits + 6 command bits - * - * start bit: data "0": data "1": stop bit: - * -----_____________________ -----____________ -----______________ ------_______.... - * 158us 7432us 158us 4902us 158us 7432us 158us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * RECS80EXT - * --------- - * - * frame: 2 start bits + 11 data bits + 1 stop bit - * data: 1 toggle bit + 4 address bits + 6 command bits - * - * start bit: data "0": data "1": stop bit: - * -----_____________________ -----____________ -----______________ ------_______.... - * 158us 3637us 158us 4902us 158us 7432us 158us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * RC5 + RC5X - * ---------- - * - * RC5 frame: 2 start bits + 12 data bits + no stop bit - * RC5 data: 1 toggle bit + 5 address bits + 6 command bits - * RC5X frame: 1 start bit + 13 data bits + no stop bit - * RC5X data: 1 inverted command bit + 1 toggle bit + 5 address bits + 6 command bits - * - * start bit: data "0": data "1": - * ______----- ------______ ______------ - * 889us 889us 889us 889us 889us 889us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * DENON - * ----- - * - * frame: 0 start bits + 16 data bits + stop bit + 65ms pause + 16 inverted data bits + stop bit - * data: 5 address bits + 10 command bits - * - * Theory: - * - * data "0": data "1": - * ------________________ ------______________ - * 275us 775us 275us 1900us - * - * Practice: - * - * data "0": data "1": - * ------________________ ------______________ - * 310us 745us 310us 1780us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * RC6 - * --- - * - * RC6 frame: 1 start bit + 1 bit "1" + 3 mode bits + 1 toggle bit + 16 data bits + 2666 us pause - * RC6 data: 8 address bits + 8 command bits - * - * start bit toggle bit "0": toggle bit "1": data/mode "0": data/mode "1": - * ____________------- _______------- -------_______ _______------- -------_______ - * 2666us 889us 889us 889us 889us 889us 444us 444us 444us 444us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * APPLE - * ----- - * - * frame: 1 start bit + 32 data bits + 1 stop bit - * data: 16 address bits + 11100000 + 8 command bits - * - * start bit: data "0": data "1": stop bit: - * -----------------_________ ------______ ------________________ ------______.... - * 9000us 4500us 560us 560us 560us 1690 us 560us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * NUBERT (subwoofer system) - * ------------------------- - * - * frame: 1 start bit + 10 data bits + 1 stop bit - * data: 0 address bits + 10 command bits ? - * - * start bit: data "0": data "1": stop bit: - * ----------_____ ------______ ------________________ ------______.... - * 1340us 340us 500us 1300us 1340us 340us 500us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * BANG_OLUFSEN - * ------------ - * - * frame: 4 start bits + 16 data bits + 1 trailer bit + 1 stop bit - * data: 0 address bits + 16 command bits - * - * 1st start bit: 2nd start bit: 3rd start bit: 4th start bit: - * -----________ -----________ -----_____________ -----________ - * 210us 3000us 210us 3000us 210us 15000us 210us 3000us - * - * data "0": data "1": data "repeat bit": trailer bit: stop bit: - * -----________ -----_____________ -----___________ -----_____________ -----____... - * 210us 3000us 210us 9000us 210us 6000us 210us 12000us 210us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * GRUNDIG - * ------- - * - * packet: 1 start frame + 19,968ms pause + N info frames + 117,76ms pause + 1 stop frame - * frame: 1 pre bit + 1 start bit + 9 data bits + no stop bit - * pause between info frames: 117,76ms - * - * data of start frame: 9 x 1 - * data of info frame: 9 command bits - * data of stop frame: 9 x 1 - * - * pre bit: start bit data "0": data "1": - * ------____________ ------______ ______------ ------______ - * 528us 2639us 528us 528us 528us 528us 528us 528us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * NOKIA: - * ------ - * - * Timing similar to Grundig, but 16 data bits: - * frame: 1 pre bit + 1 start bit + 8 command bits + 8 address bits + no stop bit - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * SIEMENS or RUWIDO: - * ------------------ - * - * SIEMENS frame: 1 start bit + 22 data bits + no stop bit - * SIEMENS data: 13 address bits + 1 repeat bit + 7 data bits + 1 unknown bit - * - * start bit data "0": data "1": - * -------_______ _______------- -------_______ - * 250us 250us 250us 250us 250us 250us - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * PANASONIC (older protocol, yet not implemented, see also MATSUSHITA, timing very similar) - * ----------------------------------------------------------------------------------------- - * - * frame: 1 start bit + 22 data bits + 1 stop bit - * 22 data bits = 5 custom bits + 6 data bits + 5 inverted custom bits + 6 inverted data bits - * - * European version: T = 456us - * USA & Canada version: T = 422us - * - * start bit: data "0": data "1": stop bit: - * 8T 8T 2T 2T 2T 6T 2T - * -------------____________ ------_____ ------_____________ ------_______.... - * 3648us 3648us 912us 912us 912us 2736us 912us (Europe) - * 3376us 3376us 844us 844us 844us 2532us 844us (US) - * - *--------------------------------------------------------------------------------------------------------------------------------------------------- - * - * 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. - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ - -#if defined(__18CXX) -#define PIC_C18 // Microchip C18 Compiler -#endif - -#if defined(__PCM__) || defined(__PCB__) || defined(__PCH__) // CCS PIC Compiler instead of AVR -#define PIC_CCS_COMPILER -#endif - -#ifdef unix // test on linux/unix -#include -#include -#include -#include -#include - -/* for crazy lirc stuff... */ -#include -#include -#include -#include - -#define ANALYZE -#define PROGMEM -#define memcpy_P memcpy - -#else // not unix: - -#ifdef WIN32 -#include -#include -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -#define ANALYZE -#define PROGMEM -#define memcpy_P memcpy - -#else - -#if defined (PIC_CCS_COMPILER) || defined(PIC_C18) - -#include -#define PROGMEM -#define memcpy_P memcpy - -#if defined (PIC_CCS_COMPILER) -typedef unsigned int8 uint8_t; -typedef unsigned int16 uint16_t; -#endif - -#else // AVR: - -#include -#include -#include -#include -#include -#include - -#endif // PIC_CCS_COMPILER or PIC_C18 - -#endif // windows -#endif // unix - -#ifndef IRMP_USE_AS_LIB -#include "irmpconfig.h" -#endif -#include "irmp.h" - -#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRMP_SUPPORT_NOKIA_PROTOCOL == 1 || IRMP_SUPPORT_IR60_PROTOCOL == 1 -#define IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL 1 -#else -#define IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL 0 -#endif - -#if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 || IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 -#define IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL 1 -#else -#define IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL 0 -#endif - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 || \ - IRMP_SUPPORT_RC6_PROTOCOL == 1 || \ - IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 || \ - IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 || \ - IRMP_SUPPORT_GRUNDIG2_PROTOCOL == 1 || \ - IRMP_SUPPORT_IR60_PROTOCOL -#define IRMP_SUPPORT_MANCHESTER 1 -#else -#define IRMP_SUPPORT_MANCHESTER 0 -#endif - -#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 -#define IRMP_SUPPORT_SERIAL 1 -#else -#define IRMP_SUPPORT_SERIAL 0 -#endif - -#define IRMP_KEY_REPETITION_LEN (uint16_t)(F_INTERRUPTS * 150.0e-3 + 0.5) // autodetect key repetition within 150 msec - -#define MIN_TOLERANCE_00 1.0 // -0% -#define MAX_TOLERANCE_00 1.0 // +0% - -#define MIN_TOLERANCE_05 0.95 // -5% -#define MAX_TOLERANCE_05 1.05 // +5% - -#define MIN_TOLERANCE_10 0.9 // -10% -#define MAX_TOLERANCE_10 1.1 // +10% - -#define MIN_TOLERANCE_15 0.85 // -15% -#define MAX_TOLERANCE_15 1.15 // +15% - -#define MIN_TOLERANCE_20 0.8 // -20% -#define MAX_TOLERANCE_20 1.2 // +20% - -#define MIN_TOLERANCE_30 0.7 // -30% -#define MAX_TOLERANCE_30 1.3 // +30% - -#define MIN_TOLERANCE_40 0.6 // -40% -#define MAX_TOLERANCE_40 1.4 // +40% - -#define MIN_TOLERANCE_50 0.5 // -50% -#define MAX_TOLERANCE_50 1.5 // +50% - -#define MIN_TOLERANCE_60 0.4 // -60% -#define MAX_TOLERANCE_60 1.6 // +60% - -#define MIN_TOLERANCE_70 0.3 // -70% -#define MAX_TOLERANCE_70 1.7 // +70% - -#define SIRCS_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define SIRCS_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define SIRCS_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#if IRMP_SUPPORT_NETBOX_PROTOCOL // only 5% to avoid conflict with NETBOX: -#define SIRCS_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5)) -#else // only 5% + 1 to avoid conflict with RC6: -#define SIRCS_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) -#endif -#define SIRCS_1_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define SIRCS_1_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define SIRCS_0_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define SIRCS_0_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define SIRCS_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define SIRCS_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define NEC_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define NEC_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) -#define NEC_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define NEC_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) -#define NEC_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define NEC_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) -#define NEC_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define NEC_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) -#define NEC_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define NEC_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) -#define NEC_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define NEC_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) -// autodetect nec repetition frame within 50 msec: -// NEC seems to send the first repetition frame after 40ms, further repetition frames after 100 ms -#if 0 -#define NEC_FRAME_REPEAT_PAUSE_LEN_MAX (uint16_t)(F_INTERRUPTS * NEC_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) -#else -#define NEC_FRAME_REPEAT_PAUSE_LEN_MAX (uint16_t)(F_INTERRUPTS * 100.0e-3 * MAX_TOLERANCE_20 + 0.5) -#endif - -#define SAMSUNG_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define SAMSUNG_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define SAMSUNG_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define SAMSUNG_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define SAMSUNG_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define SAMSUNG_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) -#define SAMSUNG_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define SAMSUNG_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) -#define SAMSUNG_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define SAMSUNG_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) - -#define MATSUSHITA_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define MATSUSHITA_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define MATSUSHITA_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define MATSUSHITA_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define MATSUSHITA_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define MATSUSHITA_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) -#define MATSUSHITA_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define MATSUSHITA_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) -#define MATSUSHITA_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define MATSUSHITA_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) - -#define KASEIKYO_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define KASEIKYO_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define KASEIKYO_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define KASEIKYO_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define KASEIKYO_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME * MIN_TOLERANCE_50 + 0.5) - 1) -#define KASEIKYO_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME * MAX_TOLERANCE_50 + 0.5) + 1) -#define KASEIKYO_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define KASEIKYO_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) -#define KASEIKYO_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME * MIN_TOLERANCE_50 + 0.5) - 1) -#define KASEIKYO_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME * MAX_TOLERANCE_50 + 0.5) + 1) - -#define RECS80_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME * MIN_TOLERANCE_00 + 0.5) - 1) -#define RECS80_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RECS80_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RECS80_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RECS80_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RECS80_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RECS80_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RECS80_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RECS80_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RECS80_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define RC5_START_BIT_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RC5_START_BIT_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define RC5_BIT_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RC5_BIT_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define DENON_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * DENON_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define DENON_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * DENON_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define DENON_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define DENON_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 -#define DENON_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5)) // no -1, avoid conflict with RUWIDO -#else -#define DENON_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) // be more tolerant -#endif -#define DENON_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define THOMSON_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define THOMSON_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define THOMSON_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define THOMSON_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define THOMSON_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define THOMSON_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define RC6_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RC6_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RC6_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RC6_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RC6_TOGGLE_BIT_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RC6_TOGGLE_BIT_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RC6_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC6_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RC6_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC6_BIT_TIME * MAX_TOLERANCE_60 + 0.5) + 1) // pulses: 300 - 800 -#define RC6_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RC6_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RC6_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RC6_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1) // pauses: 300 - 600 - -#define RECS80EXT_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME * MIN_TOLERANCE_00 + 0.5) - 1) -#define RECS80EXT_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME * MAX_TOLERANCE_00 + 0.5) + 1) -#define RECS80EXT_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) -#define RECS80EXT_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) -#define RECS80EXT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RECS80EXT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RECS80EXT_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RECS80EXT_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RECS80EXT_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RECS80EXT_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define NUBERT_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NUBERT_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NUBERT_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NUBERT_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NUBERT_1_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NUBERT_1_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NUBERT_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NUBERT_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NUBERT_0_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NUBERT_0_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NUBERT_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NUBERT_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) - -#define BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX ((PAUSE_LEN)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) // value must be below IRMP_TIMEOUT -#define BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_R_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_R_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define IR60_TIMEOUT_LEN ((uint8_t)(F_INTERRUPTS * IR60_TIMEOUT_TIME * 0.5)) -#define GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define GRUNDIG_NOKIA_IR60_BIT_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define GRUNDIG_NOKIA_IR60_BIT_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) + 1) -#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) - -#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define GRUNDIG2_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG2_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define GRUNDIG2_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG2_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define GRUNDIG2_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG2_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define GRUNDIG2_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG2_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define GRUNDIG2_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG2_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define GRUNDIG2_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG2_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define GRUNDIG2_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * GRUNDIG2_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define GRUNDIG2_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * GRUNDIG2_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define FDC_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) // 5%: avoid conflict with NETBOX -#define FDC_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5)) -#define FDC_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) -#define FDC_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5)) -#define FDC_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * FDC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define FDC_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * FDC_PULSE_TIME * MAX_TOLERANCE_50 + 0.5) + 1) -#define FDC_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define FDC_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#if 0 -#define FDC_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) // could be negative: 255 -#else -#define FDC_0_PAUSE_LEN_MIN (1) // simply use 1 -#endif -#define FDC_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define RCCAR_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RCCAR_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RCCAR_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define RCCAR_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define RCCAR_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define RCCAR_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define RCCAR_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define RCCAR_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) -#define RCCAR_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) -#define RCCAR_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) - -#define JVC_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define JVC_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) -#define JVC_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * (JVC_FRAME_REPEAT_PAUSE_TIME - IRMP_TIMEOUT_TIME) * MIN_TOLERANCE_40 + 0.5) - 1) // HACK! -#define JVC_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * (JVC_FRAME_REPEAT_PAUSE_TIME - IRMP_TIMEOUT_TIME) * MAX_TOLERANCE_70 + 0.5) - 1) // HACK! -#define JVC_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * JVC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define JVC_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * JVC_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) -#define JVC_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define JVC_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) -#define JVC_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define JVC_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) -// autodetect JVC repetition frame within 50 msec: -#define JVC_FRAME_REPEAT_PAUSE_LEN_MAX (uint16_t)(F_INTERRUPTS * JVC_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) - -#define NIKON_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NIKON_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NIKON_START_BIT_PAUSE_LEN_MIN ((uint16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NIKON_START_BIT_PAUSE_LEN_MAX ((uint16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NIKON_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NIKON_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NIKON_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NIKON_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NIKON_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NIKON_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NIKON_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NIKON_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NIKON_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) -#define NIKON_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) -#define NIKON_FRAME_REPEAT_PAUSE_LEN_MAX (uint16_t)(F_INTERRUPTS * NIKON_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) - -#define KATHREIN_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define KATHREIN_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define KATHREIN_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define KATHREIN_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define KATHREIN_1_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define KATHREIN_1_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define KATHREIN_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define KATHREIN_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define KATHREIN_0_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define KATHREIN_0_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define KATHREIN_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define KATHREIN_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define KATHREIN_SYNC_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * KATHREIN_SYNC_BIT_PAUSE_LEN_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define KATHREIN_SYNC_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * KATHREIN_SYNC_BIT_PAUSE_LEN_TIME * MAX_TOLERANCE_10 + 0.5) + 1) - -#define NETBOX_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NETBOX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define NETBOX_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NETBOX_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define NETBOX_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * NETBOX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) -#define NETBOX_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * NETBOX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) -#define NETBOX_PULSE_LEN ((uint8_t)(F_INTERRUPTS * NETBOX_PULSE_TIME)) -#define NETBOX_PAUSE_LEN ((uint8_t)(F_INTERRUPTS * NETBOX_PAUSE_TIME)) -#define NETBOX_PULSE_REST_LEN ((uint8_t)(F_INTERRUPTS * NETBOX_PULSE_TIME / 4)) -#define NETBOX_PAUSE_REST_LEN ((uint8_t)(F_INTERRUPTS * NETBOX_PAUSE_TIME / 4)) - -#define LEGO_START_BIT_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define LEGO_START_BIT_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) -#define LEGO_START_BIT_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define LEGO_START_BIT_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) -#define LEGO_PULSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * LEGO_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define LEGO_PULSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * LEGO_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) -#define LEGO_1_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define LEGO_1_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) -#define LEGO_0_PAUSE_LEN_MIN ((uint8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) -#define LEGO_0_PAUSE_LEN_MAX ((uint8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) - -#define AUTO_FRAME_REPETITION_LEN (uint16_t)(F_INTERRUPTS * AUTO_FRAME_REPETITION_TIME + 0.5) // use uint16_t! - -#ifdef ANALYZE -#define ANALYZE_PUTCHAR(a) { if (! silent) { putchar (a); } } -#ifndef LIRC_IRMP -#define ANALYZE_ONLY_NORMAL_PUTCHAR(a) { if (! silent && !verbose) { putchar (a); } } -#else -#define ANALYZE_ONLY_NORMAL_PUTCHAR(a) -#endif -#define ANALYZE_PRINTF(...) { if (verbose) { printf (__VA_ARGS__); } } -#define ANALYZE_NEWLINE() { if (verbose) { putchar ('\n'); } } -static int silent = TRUE; -static int time_counter; -static int verbose; -#else -#define ANALYZE_PUTCHAR(a) -#define ANALYZE_ONLY_NORMAL_PUTCHAR(a) -#define ANALYZE_PRINTF(...) -#define ANALYZE_NEWLINE() -#endif - -#if IRMP_USE_CALLBACK == 1 -static void (*irmp_callback_ptr) (uint8_t); -#endif // IRMP_USE_CALLBACK == 1 - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * Protocol names - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#if IRMP_PROTOCOL_NAMES == 1 -char * -irmp_protocol_names[IRMP_N_PROTOCOLS + 1] = -{ - "UNKNOWN", - "SIRCS", - "NEC", - "SAMSUNG", - "MATSUSH", - "KASEIKYO", - "RECS80", - "RC5", - "DENON", - "RC6", - "SAMSG32", - "APPLE", - "RECS80EX", - "NUBERT", - "BANG OLU", - "GRUNDIG", - "NOKIA", - "SIEMENS", - "FDC", - "RCCAR", - "JVC", - "RC6A", - "NIKON", - "RUWIDO", - "IR60", - "KATHREIN", - "NETBOX", - "NEC16", - "NEC42", - "LEGO", - "THOMSON" -}; -#endif - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * Logging - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#if IRMP_LOGGING == 1 // logging via UART - -#if IRMP_EXT_LOGGING == 1 // use external logging -#include "irmpextlog.h" -#else // normal UART log (IRMP_EXT_LOGGING == 0) -#define BAUD 9600L -#include - -#ifdef UBRR0H - -#define UART0_UBRRH UBRR0H -#define UART0_UBRRL UBRR0L -#define UART0_UCSRA UCSR0A -#define UART0_UCSRB UCSR0B -#define UART0_UCSRC UCSR0C -#define UART0_UDRE_BIT_VALUE (1< ENDBITS) - { // if stop condition is true, output on uart - uint16_t i; - - for (i = 0; i < STARTCYCLES; i++) - { - irmp_uart_putc ('0'); // the ignored starting zeros - } - - for (i = 0; i < (buf_idx - ENDBITS + 20) / 8; i++) // transform bitset into uart chars - { - uint8_t d = buf[i]; - uint8_t j; - - for (j = 0; j < 8; j++) - { - irmp_uart_putc ((d & 1) + '0'); - d >>= 1; - } - } - - irmp_uart_putc ('\n'); - buf_idx = 0; - } - } - else - { - cnt = 0; - } - } - } -} - -#else -#define irmp_log(val) -#endif //IRMP_LOGGING - -typedef struct -{ - uint8_t protocol; // ir protocol - uint8_t pulse_1_len_min; // minimum length of pulse with bit value 1 - uint8_t pulse_1_len_max; // maximum length of pulse with bit value 1 - uint8_t pause_1_len_min; // minimum length of pause with bit value 1 - uint8_t pause_1_len_max; // maximum length of pause with bit value 1 - uint8_t pulse_0_len_min; // minimum length of pulse with bit value 0 - uint8_t pulse_0_len_max; // maximum length of pulse with bit value 0 - uint8_t pause_0_len_min; // minimum length of pause with bit value 0 - uint8_t pause_0_len_max; // maximum length of pause with bit value 0 - uint8_t address_offset; // address offset - uint8_t address_end; // end of address - uint8_t command_offset; // command offset - uint8_t command_end; // end of command - uint8_t complete_len; // complete length of frame - uint8_t stop_bit; // flag: frame has stop bit - uint8_t lsb_first; // flag: LSB first - uint8_t flags; // some flags -} IRMP_PARAMETER; - -#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER sircs_param = -{ - IRMP_SIRCS_PROTOCOL, // protocol: ir protocol - SIRCS_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - SIRCS_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - SIRCS_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - SIRCS_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - SIRCS_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - SIRCS_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - SIRCS_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - SIRCS_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - SIRCS_ADDRESS_OFFSET, // address_offset: address offset - SIRCS_ADDRESS_OFFSET + SIRCS_ADDRESS_LEN, // address_end: end of address - SIRCS_COMMAND_OFFSET, // command_offset: command offset - SIRCS_COMMAND_OFFSET + SIRCS_COMMAND_LEN, // command_end: end of command - SIRCS_COMPLETE_DATA_LEN, // complete_len: complete length of frame - SIRCS_STOP_BIT, // stop_bit: flag: frame has stop bit - SIRCS_LSB, // lsb_first: flag: LSB first - SIRCS_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_NEC_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER nec_param = -{ - IRMP_NEC_PROTOCOL, // protocol: ir protocol - NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - NEC_ADDRESS_OFFSET, // address_offset: address offset - NEC_ADDRESS_OFFSET + NEC_ADDRESS_LEN, // address_end: end of address - NEC_COMMAND_OFFSET, // command_offset: command offset - NEC_COMMAND_OFFSET + NEC_COMMAND_LEN, // command_end: end of command - NEC_COMPLETE_DATA_LEN, // complete_len: complete length of frame - NEC_STOP_BIT, // stop_bit: flag: frame has stop bit - NEC_LSB, // lsb_first: flag: LSB first - NEC_FLAGS // flags: some flags -}; - -static const PROGMEM IRMP_PARAMETER nec_rep_param = -{ - IRMP_NEC_PROTOCOL, // protocol: ir protocol - NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - 0, // address_offset: address offset - 0, // address_end: end of address - 0, // command_offset: command offset - 0, // command_end: end of command - 0, // complete_len: complete length of frame - NEC_STOP_BIT, // stop_bit: flag: frame has stop bit - NEC_LSB, // lsb_first: flag: LSB first - NEC_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER nec42_param = -{ - IRMP_NEC42_PROTOCOL, // protocol: ir protocol - NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - NEC42_ADDRESS_OFFSET, // address_offset: address offset - NEC42_ADDRESS_OFFSET + NEC42_ADDRESS_LEN, // address_end: end of address - NEC42_COMMAND_OFFSET, // command_offset: command offset - NEC42_COMMAND_OFFSET + NEC42_COMMAND_LEN, // command_end: end of command - NEC42_COMPLETE_DATA_LEN, // complete_len: complete length of frame - NEC_STOP_BIT, // stop_bit: flag: frame has stop bit - NEC_LSB, // lsb_first: flag: LSB first - NEC_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER samsung_param = -{ - IRMP_SAMSUNG_PROTOCOL, // protocol: ir protocol - SAMSUNG_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - SAMSUNG_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - SAMSUNG_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - SAMSUNG_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - SAMSUNG_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - SAMSUNG_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - SAMSUNG_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - SAMSUNG_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - SAMSUNG_ADDRESS_OFFSET, // address_offset: address offset - SAMSUNG_ADDRESS_OFFSET + SAMSUNG_ADDRESS_LEN, // address_end: end of address - SAMSUNG_COMMAND_OFFSET, // command_offset: command offset - SAMSUNG_COMMAND_OFFSET + SAMSUNG_COMMAND_LEN, // command_end: end of command - SAMSUNG_COMPLETE_DATA_LEN, // complete_len: complete length of frame - SAMSUNG_STOP_BIT, // stop_bit: flag: frame has stop bit - SAMSUNG_LSB, // lsb_first: flag: LSB first - SAMSUNG_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER matsushita_param = -{ - IRMP_MATSUSHITA_PROTOCOL, // protocol: ir protocol - MATSUSHITA_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - MATSUSHITA_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - MATSUSHITA_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - MATSUSHITA_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - MATSUSHITA_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - MATSUSHITA_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - MATSUSHITA_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - MATSUSHITA_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - MATSUSHITA_ADDRESS_OFFSET, // address_offset: address offset - MATSUSHITA_ADDRESS_OFFSET + MATSUSHITA_ADDRESS_LEN, // address_end: end of address - MATSUSHITA_COMMAND_OFFSET, // command_offset: command offset - MATSUSHITA_COMMAND_OFFSET + MATSUSHITA_COMMAND_LEN, // command_end: end of command - MATSUSHITA_COMPLETE_DATA_LEN, // complete_len: complete length of frame - MATSUSHITA_STOP_BIT, // stop_bit: flag: frame has stop bit - MATSUSHITA_LSB, // lsb_first: flag: LSB first - MATSUSHITA_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER kaseikyo_param = -{ - IRMP_KASEIKYO_PROTOCOL, // protocol: ir protocol - KASEIKYO_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - KASEIKYO_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - KASEIKYO_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - KASEIKYO_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - KASEIKYO_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - KASEIKYO_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - KASEIKYO_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - KASEIKYO_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - KASEIKYO_ADDRESS_OFFSET, // address_offset: address offset - KASEIKYO_ADDRESS_OFFSET + KASEIKYO_ADDRESS_LEN, // address_end: end of address - KASEIKYO_COMMAND_OFFSET, // command_offset: command offset - KASEIKYO_COMMAND_OFFSET + KASEIKYO_COMMAND_LEN, // command_end: end of command - KASEIKYO_COMPLETE_DATA_LEN, // complete_len: complete length of frame - KASEIKYO_STOP_BIT, // stop_bit: flag: frame has stop bit - KASEIKYO_LSB, // lsb_first: flag: LSB first - KASEIKYO_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_RECS80_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER recs80_param = -{ - IRMP_RECS80_PROTOCOL, // protocol: ir protocol - RECS80_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - RECS80_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - RECS80_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - RECS80_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - RECS80_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - RECS80_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - RECS80_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - RECS80_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - RECS80_ADDRESS_OFFSET, // address_offset: address offset - RECS80_ADDRESS_OFFSET + RECS80_ADDRESS_LEN, // address_end: end of address - RECS80_COMMAND_OFFSET, // command_offset: command offset - RECS80_COMMAND_OFFSET + RECS80_COMMAND_LEN, // command_end: end of command - RECS80_COMPLETE_DATA_LEN, // complete_len: complete length of frame - RECS80_STOP_BIT, // stop_bit: flag: frame has stop bit - RECS80_LSB, // lsb_first: flag: LSB first - RECS80_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER rc5_param = -{ - IRMP_RC5_PROTOCOL, // protocol: ir protocol - RC5_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse - RC5_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse - RC5_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause - RC5_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause - 0, // pulse_0_len_min: here: not used - 0, // pulse_0_len_max: here: not used - 0, // pause_0_len_min: here: not used - 0, // pause_0_len_max: here: not used - RC5_ADDRESS_OFFSET, // address_offset: address offset - RC5_ADDRESS_OFFSET + RC5_ADDRESS_LEN, // address_end: end of address - RC5_COMMAND_OFFSET, // command_offset: command offset - RC5_COMMAND_OFFSET + RC5_COMMAND_LEN, // command_end: end of command - RC5_COMPLETE_DATA_LEN, // complete_len: complete length of frame - RC5_STOP_BIT, // stop_bit: flag: frame has stop bit - RC5_LSB, // lsb_first: flag: LSB first - RC5_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_DENON_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER denon_param = -{ - IRMP_DENON_PROTOCOL, // protocol: ir protocol - DENON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - DENON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - DENON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - DENON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - DENON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - DENON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - DENON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - DENON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - DENON_ADDRESS_OFFSET, // address_offset: address offset - DENON_ADDRESS_OFFSET + DENON_ADDRESS_LEN, // address_end: end of address - DENON_COMMAND_OFFSET, // command_offset: command offset - DENON_COMMAND_OFFSET + DENON_COMMAND_LEN, // command_end: end of command - DENON_COMPLETE_DATA_LEN, // complete_len: complete length of frame - DENON_STOP_BIT, // stop_bit: flag: frame has stop bit - DENON_LSB, // lsb_first: flag: LSB first - DENON_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_RC6_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER rc6_param = -{ - IRMP_RC6_PROTOCOL, // protocol: ir protocol - - RC6_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse - RC6_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse - RC6_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause - RC6_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause - 0, // pulse_0_len_min: here: not used - 0, // pulse_0_len_max: here: not used - 0, // pause_0_len_min: here: not used - 0, // pause_0_len_max: here: not used - RC6_ADDRESS_OFFSET, // address_offset: address offset - RC6_ADDRESS_OFFSET + RC6_ADDRESS_LEN, // address_end: end of address - RC6_COMMAND_OFFSET, // command_offset: command offset - RC6_COMMAND_OFFSET + RC6_COMMAND_LEN, // command_end: end of command - RC6_COMPLETE_DATA_LEN_SHORT, // complete_len: complete length of frame - RC6_STOP_BIT, // stop_bit: flag: frame has stop bit - RC6_LSB, // lsb_first: flag: LSB first - RC6_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER recs80ext_param = -{ - IRMP_RECS80EXT_PROTOCOL, // protocol: ir protocol - RECS80EXT_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - RECS80EXT_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - RECS80EXT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - RECS80EXT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - RECS80EXT_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - RECS80EXT_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - RECS80EXT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - RECS80EXT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - RECS80EXT_ADDRESS_OFFSET, // address_offset: address offset - RECS80EXT_ADDRESS_OFFSET + RECS80EXT_ADDRESS_LEN, // address_end: end of address - RECS80EXT_COMMAND_OFFSET, // command_offset: command offset - RECS80EXT_COMMAND_OFFSET + RECS80EXT_COMMAND_LEN, // command_end: end of command - RECS80EXT_COMPLETE_DATA_LEN, // complete_len: complete length of frame - RECS80EXT_STOP_BIT, // stop_bit: flag: frame has stop bit - RECS80EXT_LSB, // lsb_first: flag: LSB first - RECS80EXT_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER nubert_param = -{ - IRMP_NUBERT_PROTOCOL, // protocol: ir protocol - NUBERT_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - NUBERT_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - NUBERT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - NUBERT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - NUBERT_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - NUBERT_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - NUBERT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - NUBERT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - NUBERT_ADDRESS_OFFSET, // address_offset: address offset - NUBERT_ADDRESS_OFFSET + NUBERT_ADDRESS_LEN, // address_end: end of address - NUBERT_COMMAND_OFFSET, // command_offset: command offset - NUBERT_COMMAND_OFFSET + NUBERT_COMMAND_LEN, // command_end: end of command - NUBERT_COMPLETE_DATA_LEN, // complete_len: complete length of frame - NUBERT_STOP_BIT, // stop_bit: flag: frame has stop bit - NUBERT_LSB, // lsb_first: flag: LSB first - NUBERT_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER bang_olufsen_param = -{ - IRMP_BANG_OLUFSEN_PROTOCOL, // protocol: ir protocol - BANG_OLUFSEN_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - BANG_OLUFSEN_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - BANG_OLUFSEN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - BANG_OLUFSEN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - BANG_OLUFSEN_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - BANG_OLUFSEN_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - BANG_OLUFSEN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - BANG_OLUFSEN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - BANG_OLUFSEN_ADDRESS_OFFSET, // address_offset: address offset - BANG_OLUFSEN_ADDRESS_OFFSET + BANG_OLUFSEN_ADDRESS_LEN, // address_end: end of address - BANG_OLUFSEN_COMMAND_OFFSET, // command_offset: command offset - BANG_OLUFSEN_COMMAND_OFFSET + BANG_OLUFSEN_COMMAND_LEN, // command_end: end of command - BANG_OLUFSEN_COMPLETE_DATA_LEN, // complete_len: complete length of frame - BANG_OLUFSEN_STOP_BIT, // stop_bit: flag: frame has stop bit - BANG_OLUFSEN_LSB, // lsb_first: flag: LSB first - BANG_OLUFSEN_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 - -static uint8_t first_bit; - -static const PROGMEM IRMP_PARAMETER grundig_param = -{ - IRMP_GRUNDIG_PROTOCOL, // protocol: ir protocol - - GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse - GRUNDIG_NOKIA_IR60_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse - GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause - GRUNDIG_NOKIA_IR60_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause - 0, // pulse_0_len_min: here: not used - 0, // pulse_0_len_max: here: not used - 0, // pause_0_len_min: here: not used - 0, // pause_0_len_max: here: not used - GRUNDIG_ADDRESS_OFFSET, // address_offset: address offset - GRUNDIG_ADDRESS_OFFSET + GRUNDIG_ADDRESS_LEN, // address_end: end of address - GRUNDIG_COMMAND_OFFSET, // command_offset: command offset - GRUNDIG_COMMAND_OFFSET + GRUNDIG_COMMAND_LEN + 1, // command_end: end of command (USE 1 bit MORE to STORE NOKIA DATA!) - NOKIA_COMPLETE_DATA_LEN, // complete_len: complete length of frame, here: NOKIA instead of GRUNDIG! - GRUNDIG_NOKIA_IR60_STOP_BIT, // stop_bit: flag: frame has stop bit - GRUNDIG_NOKIA_IR60_LSB, // lsb_first: flag: LSB first - GRUNDIG_NOKIA_IR60_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER ruwido_param = -{ - IRMP_RUWIDO_PROTOCOL, // protocol: ir protocol - SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse - SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse - SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause - SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause - 0, // pulse_0_len_min: here: not used - 0, // pulse_0_len_max: here: not used - 0, // pause_0_len_min: here: not used - 0, // pause_0_len_max: here: not used - RUWIDO_ADDRESS_OFFSET, // address_offset: address offset - RUWIDO_ADDRESS_OFFSET + RUWIDO_ADDRESS_LEN, // address_end: end of address - RUWIDO_COMMAND_OFFSET, // command_offset: command offset - RUWIDO_COMMAND_OFFSET + RUWIDO_COMMAND_LEN, // command_end: end of command - SIEMENS_COMPLETE_DATA_LEN, // complete_len: complete length of frame, here: SIEMENS instead of RUWIDO! - SIEMENS_OR_RUWIDO_STOP_BIT, // stop_bit: flag: frame has stop bit - SIEMENS_OR_RUWIDO_LSB, // lsb_first: flag: LSB first - SIEMENS_OR_RUWIDO_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_GRUNDIG2_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER grundig2_param = -{ - IRMP_GRUNDIG2_PROTOCOL, // protocol: ir protocol - GRUNDIG2_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse - GRUNDIG2_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse - GRUNDIG2_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause - GRUNDIG2_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause - 0, // pulse_0_len_min: here: not used - 0, // pulse_0_len_max: here: not used - 0, // pause_0_len_min: here: not used - 0, // pause_0_len_max: here: not used - GRUNDIG2_ADDRESS_OFFSET, // address_offset: address offset - GRUNDIG2_ADDRESS_OFFSET + GRUNDIG2_ADDRESS_LEN, // address_end: end of address - GRUNDIG2_COMMAND_OFFSET, // command_offset: command offset - GRUNDIG2_COMMAND_OFFSET + GRUNDIG2_COMMAND_LEN, // command_end: end of command - GRUNDIG2_COMPLETE_DATA_LEN, // complete_len: complete length of frame - GRUNDIG2_STOP_BIT, // stop_bit: flag: frame has stop bit - GRUNDIG2_LSB, // lsb_first: flag: LSB first - GRUNDIG2_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_FDC_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER fdc_param = -{ - IRMP_FDC_PROTOCOL, // protocol: ir protocol - FDC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - FDC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - FDC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - FDC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - FDC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - FDC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - FDC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - FDC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - FDC_ADDRESS_OFFSET, // address_offset: address offset - FDC_ADDRESS_OFFSET + FDC_ADDRESS_LEN, // address_end: end of address - FDC_COMMAND_OFFSET, // command_offset: command offset - FDC_COMMAND_OFFSET + FDC_COMMAND_LEN, // command_end: end of command - FDC_COMPLETE_DATA_LEN, // complete_len: complete length of frame - FDC_STOP_BIT, // stop_bit: flag: frame has stop bit - FDC_LSB, // lsb_first: flag: LSB first - FDC_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER rccar_param = -{ - IRMP_RCCAR_PROTOCOL, // protocol: ir protocol - RCCAR_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - RCCAR_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - RCCAR_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - RCCAR_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - RCCAR_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - RCCAR_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - RCCAR_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - RCCAR_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - RCCAR_ADDRESS_OFFSET, // address_offset: address offset - RCCAR_ADDRESS_OFFSET + RCCAR_ADDRESS_LEN, // address_end: end of address - RCCAR_COMMAND_OFFSET, // command_offset: command offset - RCCAR_COMMAND_OFFSET + RCCAR_COMMAND_LEN, // command_end: end of command - RCCAR_COMPLETE_DATA_LEN, // complete_len: complete length of frame - RCCAR_STOP_BIT, // stop_bit: flag: frame has stop bit - RCCAR_LSB, // lsb_first: flag: LSB first - RCCAR_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER nikon_param = -{ - IRMP_NIKON_PROTOCOL, // protocol: ir protocol - NIKON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - NIKON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - NIKON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - NIKON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - NIKON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - NIKON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - NIKON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - NIKON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - NIKON_ADDRESS_OFFSET, // address_offset: address offset - NIKON_ADDRESS_OFFSET + NIKON_ADDRESS_LEN, // address_end: end of address - NIKON_COMMAND_OFFSET, // command_offset: command offset - NIKON_COMMAND_OFFSET + NIKON_COMMAND_LEN, // command_end: end of command - NIKON_COMPLETE_DATA_LEN, // complete_len: complete length of frame - NIKON_STOP_BIT, // stop_bit: flag: frame has stop bit - NIKON_LSB, // lsb_first: flag: LSB first - NIKON_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER kathrein_param = -{ - IRMP_KATHREIN_PROTOCOL, // protocol: ir protocol - KATHREIN_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - KATHREIN_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - KATHREIN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - KATHREIN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - KATHREIN_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - KATHREIN_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - KATHREIN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - KATHREIN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - KATHREIN_ADDRESS_OFFSET, // address_offset: address offset - KATHREIN_ADDRESS_OFFSET + KATHREIN_ADDRESS_LEN, // address_end: end of address - KATHREIN_COMMAND_OFFSET, // command_offset: command offset - KATHREIN_COMMAND_OFFSET + KATHREIN_COMMAND_LEN, // command_end: end of command - KATHREIN_COMPLETE_DATA_LEN, // complete_len: complete length of frame - KATHREIN_STOP_BIT, // stop_bit: flag: frame has stop bit - KATHREIN_LSB, // lsb_first: flag: LSB first - KATHREIN_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER netbox_param = -{ - IRMP_NETBOX_PROTOCOL, // protocol: ir protocol - NETBOX_PULSE_LEN, // pulse_1_len_min: minimum length of pulse with bit value 1, here: exact value - NETBOX_PULSE_REST_LEN, // pulse_1_len_max: maximum length of pulse with bit value 1, here: rest value - NETBOX_PAUSE_LEN, // pause_1_len_min: minimum length of pause with bit value 1, here: exact value - NETBOX_PAUSE_REST_LEN, // pause_1_len_max: maximum length of pause with bit value 1, here: rest value - NETBOX_PULSE_LEN, // pulse_0_len_min: minimum length of pulse with bit value 0, here: exact value - NETBOX_PULSE_REST_LEN, // pulse_0_len_max: maximum length of pulse with bit value 0, here: rest value - NETBOX_PAUSE_LEN, // pause_0_len_min: minimum length of pause with bit value 0, here: exact value - NETBOX_PAUSE_REST_LEN, // pause_0_len_max: maximum length of pause with bit value 0, here: rest value - NETBOX_ADDRESS_OFFSET, // address_offset: address offset - NETBOX_ADDRESS_OFFSET + NETBOX_ADDRESS_LEN, // address_end: end of address - NETBOX_COMMAND_OFFSET, // command_offset: command offset - NETBOX_COMMAND_OFFSET + NETBOX_COMMAND_LEN, // command_end: end of command - NETBOX_COMPLETE_DATA_LEN, // complete_len: complete length of frame - NETBOX_STOP_BIT, // stop_bit: flag: frame has stop bit - NETBOX_LSB, // lsb_first: flag: LSB first - NETBOX_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER lego_param = -{ - IRMP_LEGO_PROTOCOL, // protocol: ir protocol - LEGO_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - LEGO_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - LEGO_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - LEGO_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - LEGO_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - LEGO_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - LEGO_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - LEGO_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - LEGO_ADDRESS_OFFSET, // address_offset: address offset - LEGO_ADDRESS_OFFSET + LEGO_ADDRESS_LEN, // address_end: end of address - LEGO_COMMAND_OFFSET, // command_offset: command offset - LEGO_COMMAND_OFFSET + LEGO_COMMAND_LEN, // command_end: end of command - LEGO_COMPLETE_DATA_LEN, // complete_len: complete length of frame - LEGO_STOP_BIT, // stop_bit: flag: frame has stop bit - LEGO_LSB, // lsb_first: flag: LSB first - LEGO_FLAGS // flags: some flags -}; - -#endif - -#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 - -static const PROGMEM IRMP_PARAMETER thomson_param = -{ - IRMP_THOMSON_PROTOCOL, // protocol: ir protocol - THOMSON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 - THOMSON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 - THOMSON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 - THOMSON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 - THOMSON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 - THOMSON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 - THOMSON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 - THOMSON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 - THOMSON_ADDRESS_OFFSET, // address_offset: address offset - THOMSON_ADDRESS_OFFSET + THOMSON_ADDRESS_LEN, // address_end: end of address - THOMSON_COMMAND_OFFSET, // command_offset: command offset - THOMSON_COMMAND_OFFSET + THOMSON_COMMAND_LEN, // command_end: end of command - THOMSON_COMPLETE_DATA_LEN, // complete_len: complete length of frame - THOMSON_STOP_BIT, // stop_bit: flag: frame has stop bit - THOMSON_LSB, // lsb_first: flag: LSB first - THOMSON_FLAGS // flags: some flags -}; - -#endif - -static uint8_t irmp_bit; // current bit position -static IRMP_PARAMETER irmp_param; - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) -static IRMP_PARAMETER irmp_param2; -#endif - -static volatile uint8_t irmp_ir_detected; -static volatile uint8_t irmp_protocol; -static volatile uint16_t irmp_address; -static volatile uint16_t irmp_command; -static volatile uint16_t irmp_id; // only used for SAMSUNG protocol -static volatile uint8_t irmp_flags; -// static volatile uint8_t irmp_busy_flag; - -#ifdef ANALYZE -static uint8_t IRMP_PIN; -#endif - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * Initialize IRMP decoder - * @details Configures IRMP input pin - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#ifndef ANALYZE -void -irmp_init (void) -{ -#ifndef ARDUINO -#if !defined(PIC_CCS_COMPILER) && !defined(PIC_C18) // only AVR - IRMP_PORT &= ~(1<> 8) == (~irmp_command & 0x00FF)) - { - irmp_command &= 0xff; - irmp_command |= irmp_id << 8; - rtc = TRUE; - } - break; -#endif -#if IRMP_SUPPORT_NEC_PROTOCOL == 1 - case IRMP_NEC_PROTOCOL: - if ((irmp_command >> 8) == (~irmp_command & 0x00FF)) - { - irmp_command &= 0xff; - rtc = TRUE; - } - else if (irmp_address == 0x87EE) - { - ANALYZE_PRINTF ("Switching to APPLE protocol\n"); - irmp_protocol = IRMP_APPLE_PROTOCOL; - irmp_address = (irmp_command & 0xFF00) >> 8; - irmp_command &= 0x00FF; - rtc = TRUE; - } - break; -#endif -#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 - case IRMP_SIEMENS_PROTOCOL: - case IRMP_RUWIDO_PROTOCOL: - if (((irmp_command >> 1) & 0x0001) == (~irmp_command & 0x0001)) - { - irmp_command >>= 1; - rtc = TRUE; - } - break; -#endif -#if IRMP_SUPPORT_GRUNDIG2_PROTOCOL == 1 - case IRMP_GRUNDIG2_PROTOCOL: - if (irmp_command & 0x0001) - { - irmp_command >>= 1; - rtc = TRUE; - } - break; -#endif -#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 - case IRMP_KATHREIN_PROTOCOL: - if (irmp_command != 0x0000) - { - rtc = TRUE; - } - break; -#endif -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 - case IRMP_RC5_PROTOCOL: - irmp_address &= ~0x20; // clear toggle bit - rtc = TRUE; - break; -#endif -#if IRMP_SUPPORT_IR60_PROTOCOL == 1 - case IRMP_IR60_PROTOCOL: - if (irmp_command != 0x007d) // 0x007d (== 62<<1 + 1) is start instruction frame - { - rtc = TRUE; - } - break; -#endif -#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 - case IRMP_RCCAR_PROTOCOL: - // frame in irmp_data: - // Bit 12 11 10 9 8 7 6 5 4 3 2 1 0 - // V D7 D6 D5 D4 D3 D2 D1 D0 A1 A0 C1 C0 // 10 9 8 7 6 5 4 3 2 1 0 - irmp_address = (irmp_command & 0x000C) >> 2; // addr: 0 0 0 0 0 0 0 0 0 A1 A0 - irmp_command = ((irmp_command & 0x1000) >> 2) | // V-Bit: V 0 0 0 0 0 0 0 0 0 0 - ((irmp_command & 0x0003) << 8) | // C-Bits: 0 C1 C0 0 0 0 0 0 0 0 0 - ((irmp_command & 0x0FF0) >> 4); // D-Bits: D7 D6 D5 D4 D3 D2 D1 D0 - rtc = TRUE; // Summe: V C1 C0 D7 D6 D5 D4 D3 D2 D1 D0 - break; -#endif - -#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 // squeeze code to 8 bit, upper bit indicates release-key - case IRMP_NETBOX_PROTOCOL: - if (irmp_command & 0x1000) // last bit set? - { - if ((irmp_command & 0x1f) == 0x15) // key pressed: 101 01 (LSB) - { - irmp_command >>= 5; - irmp_command &= 0x7F; - rtc = TRUE; - } - else if ((irmp_command & 0x1f) == 0x10) // key released: 000 01 (LSB) - { - irmp_command >>= 5; - irmp_command |= 0x80; - rtc = TRUE; - } - else - { - ANALYZE_PRINTF("error NETBOX: bit6/7 must be 0/1\n"); - } - } - else - { - ANALYZE_PRINTF("error NETBOX: last bit not set\n"); - } - break; -#endif -#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 - case IRMP_LEGO_PROTOCOL: - { - uint8_t crc = 0x0F ^ ((irmp_command & 0xF000) >> 12) ^ ((irmp_command & 0x0F00) >> 8) ^ ((irmp_command & 0x00F0) >> 4); - - if ((irmp_command & 0x000F) == crc) - { - irmp_command >>= 4; - rtc = TRUE; - } - else - { - ANALYZE_PRINTF ("CRC error in LEGO protocol\n"); - rtc = TRUE; - } - break; - } -#endif - default: - rtc = TRUE; - } - - if (rtc) - { - irmp_data_p->protocol = irmp_protocol; - irmp_data_p->address = irmp_address; - irmp_data_p->command = irmp_command; - irmp_data_p->flags = irmp_flags; - irmp_command = 0; - irmp_address = 0; - irmp_flags = 0; - } - - irmp_ir_detected = FALSE; - } - - return rtc; -} - -// uint8_t -// irmp_is_busy (void) -// { -// return irmp_busy_flag; -// } - -#if IRMP_USE_CALLBACK == 1 -void -irmp_set_callback_ptr (void (*cb)(uint8_t)) -{ - irmp_callback_ptr = cb; -} -#endif // IRMP_USE_CALLBACK == 1 - -// these statics must not be volatile, because they are only used by irmp_store_bit(), which is called by irmp_ISR() -static uint16_t irmp_tmp_address; // ir address -static uint16_t irmp_tmp_command; // ir command - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) || IRMP_SUPPORT_NEC42_PROTOCOL == 1 -static uint16_t irmp_tmp_address2; // ir address -static uint16_t irmp_tmp_command2; // ir command -#endif - -#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 -static uint16_t irmp_tmp_id; // ir id (only SAMSUNG) -#endif -#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 -static uint8_t xor_check[6]; // check kaseikyo "parity" bits -static uint8_t genre2; // save genre2 bits here, later copied to MSB in flags -#endif - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * store bit - * @details store bit in temp address or temp command - * @param value to store: 0 or 1 - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -// verhindert, dass irmp_store_bit() inline compiliert wird: -// static void irmp_store_bit (uint8_t) __attribute__ ((noinline)); - -static void -irmp_store_bit (uint8_t value) -{ -#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 - if (irmp_bit == 0 && irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL) - { - first_bit = value; - } - else -#endif - - if (irmp_bit >= irmp_param.address_offset && irmp_bit < irmp_param.address_end) - { - if (irmp_param.lsb_first) - { - irmp_tmp_address |= (((uint16_t) (value)) << (irmp_bit - irmp_param.address_offset)); // CV wants cast - } - else - { - irmp_tmp_address <<= 1; - irmp_tmp_address |= value; - } - } - else if (irmp_bit >= irmp_param.command_offset && irmp_bit < irmp_param.command_end) - { - if (irmp_param.lsb_first) - { - irmp_tmp_command |= (((uint16_t) (value)) << (irmp_bit - irmp_param.command_offset)); // CV wants cast - } - else - { - irmp_tmp_command <<= 1; - irmp_tmp_command |= value; - } - } - -#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 - else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit >= 13 && irmp_bit < 26) - { - irmp_tmp_address2 |= (((uint16_t) (value)) << (irmp_bit - 13)); // CV wants cast - } -#endif - -#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 - else if (irmp_param.protocol == IRMP_SAMSUNG_PROTOCOL && irmp_bit >= SAMSUNG_ID_OFFSET && irmp_bit < SAMSUNG_ID_OFFSET + SAMSUNG_ID_LEN) - { - irmp_tmp_id |= (((uint16_t) (value)) << (irmp_bit - SAMSUNG_ID_OFFSET)); // store with LSB first - } -#endif - -#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 - else if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL) - { - if (irmp_bit >= 20 && irmp_bit < 24) - { - irmp_tmp_command |= (((uint16_t) (value)) << (irmp_bit - 8)); // store 4 system bits (genre 1) in upper nibble with LSB first - } - else if (irmp_bit >= 24 && irmp_bit < 28) - { - genre2 |= (((uint8_t) (value)) << (irmp_bit - 20)); // store 4 system bits (genre 2) in upper nibble with LSB first - } - - if (irmp_bit < KASEIKYO_COMPLETE_DATA_LEN) - { - if (value) - { - xor_check[irmp_bit / 8] |= 1 << (irmp_bit % 8); - } - else - { - xor_check[irmp_bit / 8] &= ~(1 << (irmp_bit % 8)); - } - } - } -#endif - - irmp_bit++; -} - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * store bit - * @details store bit in temp address or temp command - * @param value to store: 0 or 1 - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) -static void -irmp_store_bit2 (uint8_t value) -{ - uint8_t irmp_bit2; - - if (irmp_param.protocol) - { - irmp_bit2 = irmp_bit - 2; - } - else - { - irmp_bit2 = irmp_bit - 1; - } - - if (irmp_bit2 >= irmp_param2.address_offset && irmp_bit2 < irmp_param2.address_end) - { - irmp_tmp_address2 |= (((uint16_t) (value)) << (irmp_bit2 - irmp_param2.address_offset)); // CV wants cast - } - else if (irmp_bit2 >= irmp_param2.command_offset && irmp_bit2 < irmp_param2.command_end) - { - irmp_tmp_command2 |= (((uint16_t) (value)) << (irmp_bit2 - irmp_param2.command_offset)); // CV wants cast - } -} -#endif // IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * ISR routine - * @details ISR routine, called 10000 times per second - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -uint8_t -irmp_ISR (uint8_t x42) -{ - static uint8_t irmp_start_bit_detected; // flag: start bit detected - static uint8_t wait_for_space; // flag: wait for data bit space - static uint8_t wait_for_start_space; // flag: wait for start bit space - static uint8_t irmp_pulse_time; // count bit time for pulse - static PAUSE_LEN irmp_pause_time; // count bit time for pause - static uint16_t last_irmp_address = 0xFFFF; // save last irmp address to recognize key repetition - static uint16_t last_irmp_command = 0xFFFF; // save last irmp command to recognize key repetition - static uint16_t repetition_len; // SIRCS repeats frame 2-5 times with 45 ms pause - static uint8_t repetition_frame_number; -#if IRMP_SUPPORT_DENON_PROTOCOL == 1 - static uint16_t last_irmp_denon_command; // save last irmp command to recognize DENON frame repetition -#endif -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 - static uint8_t rc5_cmd_bit6; // bit 6 of RC5 command is the inverted 2nd start bit -#endif -#if IRMP_SUPPORT_MANCHESTER == 1 - static PAUSE_LEN last_pause; // last pause value -#endif -#if IRMP_SUPPORT_MANCHESTER == 1 || IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 - static uint8_t last_value; // last bit value -#endif - uint8_t irmp_input; // input value - -#ifdef ANALYZE - time_counter++; -#endif - - irmp_input = input(x42); - -#if IRMP_USE_CALLBACK == 1 - if (irmp_callback_ptr) - { - static uint8_t last_inverted_input; - - if (last_inverted_input != !irmp_input) - { - (*irmp_callback_ptr) (! irmp_input); - last_inverted_input = !irmp_input; - } - } -#endif // IRMP_USE_CALLBACK == 1 - - irmp_log(irmp_input); // log ir signal, if IRMP_LOGGING defined - - if (! irmp_ir_detected) // ir code already detected? - { // no... - if (! irmp_start_bit_detected) // start bit detected? - { // no... - if (! irmp_input) // receiving burst? - { // yes... -// irmp_busy_flag = TRUE; -#ifdef ANALYZE - if (! irmp_pulse_time) - { - ANALYZE_PRINTF("%8.3fms [starting pulse]\n", (double) (time_counter * 1000) / F_INTERRUPTS); - } -#endif - irmp_pulse_time++; // increment counter - } - else - { // no... - if (irmp_pulse_time) // it's dark.... - { // set flags for counting the time of darkness... - irmp_start_bit_detected = 1; - wait_for_start_space = 1; - wait_for_space = 0; - irmp_tmp_command = 0; - irmp_tmp_address = 0; -#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 - genre2 = 0; -#endif - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) || IRMP_SUPPORT_NEC42_PROTOCOL == 1 - irmp_tmp_command2 = 0; - irmp_tmp_address2 = 0; -#endif - - irmp_bit = 0xff; - irmp_pause_time = 1; // 1st pause: set to 1, not to 0! -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 - rc5_cmd_bit6 = 0; // fm 2010-03-07: bugfix: reset it after incomplete RC5 frame! -#endif - } - else - { - if (repetition_len < 0xFFFF) // avoid overflow of counter - { - repetition_len++; - } - } - } - } - else - { - if (wait_for_start_space) // we have received start bit... - { // ...and are counting the time of darkness - if (irmp_input) // still dark? - { // yes - irmp_pause_time++; // increment counter - -#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 - if (((irmp_pulse_time < NIKON_START_BIT_PULSE_LEN_MIN || irmp_pulse_time > NIKON_START_BIT_PULSE_LEN_MAX) && irmp_pause_time > IRMP_TIMEOUT_LEN) || - irmp_pause_time > IRMP_TIMEOUT_NIKON_LEN) -#else - if (irmp_pause_time > IRMP_TIMEOUT_LEN) // timeout? -#endif - { // yes... -#if IRMP_SUPPORT_JVC_PROTOCOL == 1 - if (irmp_protocol == IRMP_JVC_PROTOCOL) // don't show eror if JVC protocol, irmp_pulse_time has been set below! - { - ; - } - else -#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 - { - ANALYZE_PRINTF ("%8.3fms error 1: pause after start bit pulse %d too long: %d\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_pulse_time, irmp_pause_time); - ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); - } -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // reset flags, let's wait for another start bit - irmp_pulse_time = 0; - irmp_pause_time = 0; - } - } - else - { // receiving first data pulse! - IRMP_PARAMETER * irmp_param_p = (IRMP_PARAMETER *) 0; - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) - irmp_param2.protocol = 0; -#endif - - ANALYZE_PRINTF ("%8.3fms [start-bit: pulse = %2d, pause = %2d]\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_pulse_time, irmp_pause_time); - -#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 - if (irmp_pulse_time >= SIRCS_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SIRCS_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= SIRCS_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SIRCS_START_BIT_PAUSE_LEN_MAX) - { // it's SIRCS - ANALYZE_PRINTF ("protocol = SIRCS, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - SIRCS_START_BIT_PULSE_LEN_MIN, SIRCS_START_BIT_PULSE_LEN_MAX, - SIRCS_START_BIT_PAUSE_LEN_MIN, SIRCS_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) (IRMP_PARAMETER *) &sircs_param; - } - else -#endif // IRMP_SUPPORT_SIRCS_PROTOCOL == 1 - -#if IRMP_SUPPORT_JVC_PROTOCOL == 1 - if (irmp_protocol == IRMP_JVC_PROTOCOL && // last protocol was JVC, awaiting repeat frame - irmp_pulse_time >= JVC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= JVC_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= JVC_REPEAT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= JVC_REPEAT_START_BIT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("protocol = NEC or JVC (type 1) repeat frame, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - JVC_START_BIT_PULSE_LEN_MIN, JVC_START_BIT_PULSE_LEN_MAX, - JVC_REPEAT_START_BIT_PAUSE_LEN_MIN, JVC_REPEAT_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &nec_param; - } - else -#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 - -#if IRMP_SUPPORT_NEC_PROTOCOL == 1 - if (irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= NEC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_START_BIT_PAUSE_LEN_MAX) - { -#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 - ANALYZE_PRINTF ("protocol = NEC42, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, - NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &nec42_param; -#else - ANALYZE_PRINTF ("protocol = NEC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, - NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &nec_param; -#endif - - } - else if (irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= NEC_REPEAT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_REPEAT_START_BIT_PAUSE_LEN_MAX) - { // it's NEC -#if IRMP_SUPPORT_JVC_PROTOCOL == 1 - if (irmp_protocol == IRMP_JVC_PROTOCOL) // last protocol was JVC, awaiting repeat frame - { // some jvc remote controls use nec repetition frame for jvc repetition frame - ANALYZE_PRINTF ("protocol = JVC repeat frame type 2, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, - NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &nec_param; - } - else -#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 - { - ANALYZE_PRINTF ("protocol = NEC (repetition frame), start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, - NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX); - - irmp_param_p = (IRMP_PARAMETER *) &nec_rep_param; - } - } - else - -#if IRMP_SUPPORT_JVC_PROTOCOL == 1 - if (irmp_protocol == IRMP_JVC_PROTOCOL && // last protocol was JVC, awaiting repeat frame - irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= NEC_0_PAUSE_LEN_MIN && irmp_pause_time <= NEC_0_PAUSE_LEN_MAX) - { // it's JVC repetition type 3 - ANALYZE_PRINTF ("protocol = JVC repeat frame type 3, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, - NEC_0_PAUSE_LEN_MIN, NEC_0_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &nec_param; - } - else -#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 - -#endif // IRMP_SUPPORT_NEC_PROTOCOL == 1 - -#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 - if (irmp_pulse_time >= NIKON_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NIKON_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= NIKON_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NIKON_START_BIT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("protocol = NIKON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - NIKON_START_BIT_PULSE_LEN_MIN, NIKON_START_BIT_PULSE_LEN_MAX, - NIKON_START_BIT_PAUSE_LEN_MIN, NIKON_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &nikon_param; - } - else -#endif // IRMP_SUPPORT_NIKON_PROTOCOL == 1 - -#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 - if (irmp_pulse_time >= SAMSUNG_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= SAMSUNG_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_START_BIT_PAUSE_LEN_MAX) - { // it's SAMSUNG - ANALYZE_PRINTF ("protocol = SAMSUNG, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - SAMSUNG_START_BIT_PULSE_LEN_MIN, SAMSUNG_START_BIT_PULSE_LEN_MAX, - SAMSUNG_START_BIT_PAUSE_LEN_MIN, SAMSUNG_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &samsung_param; - } - else -#endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 - -#if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 - if (irmp_pulse_time >= MATSUSHITA_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MATSUSHITA_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= MATSUSHITA_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MATSUSHITA_START_BIT_PAUSE_LEN_MAX) - { // it's MATSUSHITA - ANALYZE_PRINTF ("protocol = MATSUSHITA, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - MATSUSHITA_START_BIT_PULSE_LEN_MIN, MATSUSHITA_START_BIT_PULSE_LEN_MAX, - MATSUSHITA_START_BIT_PAUSE_LEN_MIN, MATSUSHITA_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &matsushita_param; - } - else -#endif // IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 - -#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 - if (irmp_pulse_time >= KASEIKYO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= KASEIKYO_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= KASEIKYO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KASEIKYO_START_BIT_PAUSE_LEN_MAX) - { // it's KASEIKYO - ANALYZE_PRINTF ("protocol = KASEIKYO, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - KASEIKYO_START_BIT_PULSE_LEN_MIN, KASEIKYO_START_BIT_PULSE_LEN_MAX, - KASEIKYO_START_BIT_PAUSE_LEN_MIN, KASEIKYO_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &kaseikyo_param; - } - else -#endif // IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 - -#if IRMP_SUPPORT_RECS80_PROTOCOL == 1 - if (irmp_pulse_time >= RECS80_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RECS80_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= RECS80_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RECS80_START_BIT_PAUSE_LEN_MAX) - { // it's RECS80 - ANALYZE_PRINTF ("protocol = RECS80, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - RECS80_START_BIT_PULSE_LEN_MIN, RECS80_START_BIT_PULSE_LEN_MAX, - RECS80_START_BIT_PAUSE_LEN_MIN, RECS80_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &recs80_param; - } - else -#endif // IRMP_SUPPORT_RECS80_PROTOCOL == 1 - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 - if (((irmp_pulse_time >= RC5_START_BIT_LEN_MIN && irmp_pulse_time <= RC5_START_BIT_LEN_MAX) || - (irmp_pulse_time >= 2 * RC5_START_BIT_LEN_MIN && irmp_pulse_time <= 2 * RC5_START_BIT_LEN_MAX)) && - ((irmp_pause_time >= RC5_START_BIT_LEN_MIN && irmp_pause_time <= RC5_START_BIT_LEN_MAX) || - (irmp_pause_time >= 2 * RC5_START_BIT_LEN_MIN && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX))) - { // it's RC5 -#if IRMP_SUPPORT_FDC_PROTOCOL == 1 - if (irmp_pulse_time >= FDC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FDC_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= FDC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FDC_START_BIT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("protocol = RC5 or FDC\n"); - ANALYZE_PRINTF ("FDC start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX, - FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX); - ANALYZE_PRINTF ("RC5 start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, - RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX); - memcpy_P (&irmp_param2, &fdc_param, sizeof (IRMP_PARAMETER)); - } - else -#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 - -#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 - if (irmp_pulse_time >= RCCAR_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= RCCAR_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_START_BIT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("protocol = RC5 or RCCAR\n"); - ANALYZE_PRINTF ("RCCAR start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX, - RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX); - ANALYZE_PRINTF ("RC5 start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, - RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX); - memcpy_P (&irmp_param2, &rccar_param, sizeof (IRMP_PARAMETER)); - } - else -#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 - { - ANALYZE_PRINTF ("protocol = RC5, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or pulse: %3d - %3d, pause: %3d - %3d\n", - RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, - 2 * RC5_START_BIT_LEN_MIN, 2 * RC5_START_BIT_LEN_MAX, - RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, - 2 * RC5_START_BIT_LEN_MIN, 2 * RC5_START_BIT_LEN_MAX); - } - - irmp_param_p = (IRMP_PARAMETER *) &rc5_param; - last_pause = irmp_pause_time; - - if ((irmp_pulse_time > RC5_START_BIT_LEN_MAX && irmp_pulse_time <= 2 * RC5_START_BIT_LEN_MAX) || - (irmp_pause_time > RC5_START_BIT_LEN_MAX && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX)) - { - last_value = 0; - rc5_cmd_bit6 = 1<<6; - } - else - { - last_value = 1; - } - } - else -#endif // IRMP_SUPPORT_RC5_PROTOCOL == 1 - -#if IRMP_SUPPORT_DENON_PROTOCOL == 1 - if ( (irmp_pulse_time >= DENON_PULSE_LEN_MIN && irmp_pulse_time <= DENON_PULSE_LEN_MAX) && - ((irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX) || - (irmp_pause_time >= DENON_0_PAUSE_LEN_MIN && irmp_pause_time <= DENON_0_PAUSE_LEN_MAX))) - { // it's DENON - ANALYZE_PRINTF ("protocol = DENON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or %3d - %3d\n", - DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX, - DENON_1_PAUSE_LEN_MIN, DENON_1_PAUSE_LEN_MAX, - DENON_0_PAUSE_LEN_MIN, DENON_0_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &denon_param; - } - else -#endif // IRMP_SUPPORT_DENON_PROTOCOL == 1 - -#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 - if ( (irmp_pulse_time >= THOMSON_PULSE_LEN_MIN && irmp_pulse_time <= THOMSON_PULSE_LEN_MAX) && - ((irmp_pause_time >= THOMSON_1_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_1_PAUSE_LEN_MAX) || - (irmp_pause_time >= THOMSON_0_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_0_PAUSE_LEN_MAX))) - { // it's THOMSON - ANALYZE_PRINTF ("protocol = THOMSON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or %3d - %3d\n", - THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX, - THOMSON_1_PAUSE_LEN_MIN, THOMSON_1_PAUSE_LEN_MAX, - THOMSON_0_PAUSE_LEN_MIN, THOMSON_0_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &thomson_param; - } - else -#endif // IRMP_SUPPORT_THOMSON_PROTOCOL == 1 - -#if IRMP_SUPPORT_RC6_PROTOCOL == 1 - if (irmp_pulse_time >= RC6_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RC6_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= RC6_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RC6_START_BIT_PAUSE_LEN_MAX) - { // it's RC6 - ANALYZE_PRINTF ("protocol = RC6, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - RC6_START_BIT_PULSE_LEN_MIN, RC6_START_BIT_PULSE_LEN_MAX, - RC6_START_BIT_PAUSE_LEN_MIN, RC6_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &rc6_param; - last_pause = 0; - last_value = 1; - } - else -#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 - -#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 - if (irmp_pulse_time >= RECS80EXT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RECS80EXT_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= RECS80EXT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RECS80EXT_START_BIT_PAUSE_LEN_MAX) - { // it's RECS80EXT - ANALYZE_PRINTF ("protocol = RECS80EXT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - RECS80EXT_START_BIT_PULSE_LEN_MIN, RECS80EXT_START_BIT_PULSE_LEN_MAX, - RECS80EXT_START_BIT_PAUSE_LEN_MIN, RECS80EXT_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &recs80ext_param; - } - else -#endif // IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 - -#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 - if (irmp_pulse_time >= NUBERT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NUBERT_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= NUBERT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NUBERT_START_BIT_PAUSE_LEN_MAX) - { // it's NUBERT - ANALYZE_PRINTF ("protocol = NUBERT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - NUBERT_START_BIT_PULSE_LEN_MIN, NUBERT_START_BIT_PULSE_LEN_MAX, - NUBERT_START_BIT_PAUSE_LEN_MIN, NUBERT_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &nubert_param; - } - else -#endif // IRMP_SUPPORT_NUBERT_PROTOCOL == 1 - -#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 - if (irmp_pulse_time >= BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN && irmp_pulse_time <= BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX && - irmp_pause_time >= BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX) - { // it's BANG_OLUFSEN - ANALYZE_PRINTF ("protocol = BANG_OLUFSEN\n"); - ANALYZE_PRINTF ("start bit 1 timings: pulse: %3d - %3d, pause: %3d - %3d\n", - BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX, - BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX); - ANALYZE_PRINTF ("start bit 2 timings: pulse: %3d - %3d, pause: %3d - %3d\n", - BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX, - BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX); - ANALYZE_PRINTF ("start bit 3 timings: pulse: %3d - %3d, pause: %3d - %3d\n", - BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX, - BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX); - ANALYZE_PRINTF ("start bit 4 timings: pulse: %3d - %3d, pause: %3d - %3d\n", - BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX, - BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &bang_olufsen_param; - last_value = 0; - } - else -#endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 - -#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 - if (irmp_pulse_time >= GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN && irmp_pulse_time <= GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX && - irmp_pause_time >= GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN && irmp_pause_time <= GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX) - { // it's GRUNDIG - ANALYZE_PRINTF ("protocol = GRUNDIG, pre bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN, GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX, - GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN, GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &grundig_param; - last_pause = irmp_pause_time; - last_value = 1; - } - else -#endif // IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 - -#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 - if (((irmp_pulse_time >= SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX) || - (irmp_pulse_time >= 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX)) && - ((irmp_pause_time >= SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX) || - (irmp_pause_time >= 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX))) - { // it's RUWIDO or SIEMENS - ANALYZE_PRINTF ("protocol = RUWIDO, start bit timings: pulse: %3d - %3d or %3d - %3d, pause: %3d - %3d or %3d - %3d\n", - SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX, - 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX, - SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX, - 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &ruwido_param; - last_pause = irmp_pause_time; - last_value = 1; - } - else -#endif // IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 - -#if IRMP_SUPPORT_GRUNDIG2_PROTOCOL == 1 - if ((irmp_pulse_time >= GRUNDIG2_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= GRUNDIG2_START_BIT_PULSE_LEN_MAX) && - (irmp_pause_time >= GRUNDIG2_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= GRUNDIG2_START_BIT_PAUSE_LEN_MAX)) - { // it's GRUNDIG2 - ANALYZE_PRINTF ("protocol = GRUNDIG2, start bit timings: pulse: %3d - %3d or %3d - %3d, pause: %3d - %3d or %3d - %3d\n", - GRUNDIG2_START_BIT_PULSE_LEN_MIN, GRUNDIG2_START_BIT_PULSE_LEN_MAX, - 2 * GRUNDIG2_START_BIT_PULSE_LEN_MIN, 2 * GRUNDIG2_START_BIT_PULSE_LEN_MAX, - GRUNDIG2_START_BIT_PAUSE_LEN_MIN, GRUNDIG2_START_BIT_PAUSE_LEN_MAX, - 2 * GRUNDIG2_START_BIT_PAUSE_LEN_MIN, 2 * GRUNDIG2_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &grundig2_param; - last_pause = irmp_pause_time; - last_value = 1; - } - else -#endif // IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 - -#if IRMP_SUPPORT_FDC_PROTOCOL == 1 - if (irmp_pulse_time >= FDC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FDC_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= FDC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FDC_START_BIT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("protocol = FDC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX, - FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &fdc_param; - } - else -#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 - -#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 - if (irmp_pulse_time >= RCCAR_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= RCCAR_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_START_BIT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("protocol = RCCAR, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX, - RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &rccar_param; - } - else -#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 - -#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 - if (irmp_pulse_time >= KATHREIN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= KATHREIN_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= KATHREIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_START_BIT_PAUSE_LEN_MAX) - { // it's KATHREIN - ANALYZE_PRINTF ("protocol = KATHREIN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - KATHREIN_START_BIT_PULSE_LEN_MIN, KATHREIN_START_BIT_PULSE_LEN_MAX, - KATHREIN_START_BIT_PAUSE_LEN_MIN, KATHREIN_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &kathrein_param; - } - else -#endif // IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 - -#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 - if (irmp_pulse_time >= NETBOX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NETBOX_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= NETBOX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NETBOX_START_BIT_PAUSE_LEN_MAX) - { // it's NETBOX - ANALYZE_PRINTF ("protocol = NETBOX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - NETBOX_START_BIT_PULSE_LEN_MIN, NETBOX_START_BIT_PULSE_LEN_MAX, - NETBOX_START_BIT_PAUSE_LEN_MIN, NETBOX_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &netbox_param; - } - else -#endif // IRMP_SUPPORT_NETBOX_PROTOCOL == 1 - -#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 - if (irmp_pulse_time >= LEGO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= LEGO_START_BIT_PULSE_LEN_MAX && - irmp_pause_time >= LEGO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= LEGO_START_BIT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("protocol = LEGO, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", - LEGO_START_BIT_PULSE_LEN_MIN, LEGO_START_BIT_PULSE_LEN_MAX, - LEGO_START_BIT_PAUSE_LEN_MIN, LEGO_START_BIT_PAUSE_LEN_MAX); - irmp_param_p = (IRMP_PARAMETER *) &lego_param; - } - else -#endif // IRMP_SUPPORT_LEGO_PROTOCOL == 1 - - { - ANALYZE_PRINTF ("protocol = UNKNOWN\n"); -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // wait for another start bit... - } - - if (irmp_start_bit_detected) - { - memcpy_P (&irmp_param, irmp_param_p, sizeof (IRMP_PARAMETER)); - -#ifdef ANALYZE - if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) - { - ANALYZE_PRINTF ("pulse_1: %3d - %3d\n", irmp_param.pulse_1_len_min, irmp_param.pulse_1_len_max); - ANALYZE_PRINTF ("pause_1: %3d - %3d\n", irmp_param.pause_1_len_min, irmp_param.pause_1_len_max); - } - else - { - ANALYZE_PRINTF ("pulse: %3d - %3d or %3d - %3d\n", irmp_param.pulse_1_len_min, irmp_param.pulse_1_len_max, - 2 * irmp_param.pulse_1_len_min, 2 * irmp_param.pulse_1_len_max); - ANALYZE_PRINTF ("pause: %3d - %3d or %3d - %3d\n", irmp_param.pause_1_len_min, irmp_param.pause_1_len_max, - 2 * irmp_param.pause_1_len_min, 2 * irmp_param.pause_1_len_max); - } - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) - if (irmp_param2.protocol) - { - ANALYZE_PRINTF ("pulse_0: %3d - %3d\n", irmp_param2.pulse_0_len_min, irmp_param2.pulse_0_len_max); - ANALYZE_PRINTF ("pause_0: %3d - %3d\n", irmp_param2.pause_0_len_min, irmp_param2.pause_0_len_max); - ANALYZE_PRINTF ("pulse_1: %3d - %3d\n", irmp_param2.pulse_1_len_min, irmp_param2.pulse_1_len_max); - ANALYZE_PRINTF ("pause_1: %3d - %3d\n", irmp_param2.pause_1_len_min, irmp_param2.pause_1_len_max); - } -#endif - - -#if IRMP_SUPPORT_RC6_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_RC6_PROTOCOL) - { - ANALYZE_PRINTF ("pulse_toggle: %3d - %3d\n", RC6_TOGGLE_BIT_LEN_MIN, RC6_TOGGLE_BIT_LEN_MAX); - } -#endif - - if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) - { - ANALYZE_PRINTF ("pulse_0: %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); - ANALYZE_PRINTF ("pause_0: %3d - %3d\n", irmp_param.pause_0_len_min, irmp_param.pause_0_len_max); - } - else - { - ANALYZE_PRINTF ("pulse: %3d - %3d or %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max, - 2 * irmp_param.pulse_0_len_min, 2 * irmp_param.pulse_0_len_max); - ANALYZE_PRINTF ("pause: %3d - %3d or %3d - %3d\n", irmp_param.pause_0_len_min, irmp_param.pause_0_len_max, - 2 * irmp_param.pause_0_len_min, 2 * irmp_param.pause_0_len_max); - } - -#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_BANG_OLUFSEN_PROTOCOL) - { - ANALYZE_PRINTF ("pulse_r: %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); - ANALYZE_PRINTF ("pause_r: %3d - %3d\n", BANG_OLUFSEN_R_PAUSE_LEN_MIN, BANG_OLUFSEN_R_PAUSE_LEN_MAX); - } -#endif - - ANALYZE_PRINTF ("command_offset: %2d\n", irmp_param.command_offset); - ANALYZE_PRINTF ("command_len: %3d\n", irmp_param.command_end - irmp_param.command_offset); - ANALYZE_PRINTF ("complete_len: %3d\n", irmp_param.complete_len); - ANALYZE_PRINTF ("stop_bit: %3d\n", irmp_param.stop_bit); -#endif // ANALYZE - } - - irmp_bit = 0; - -#if IRMP_SUPPORT_MANCHESTER == 1 - if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && - irmp_param.protocol != IRMP_RUWIDO_PROTOCOL && // Manchester, but not RUWIDO - irmp_param.protocol != IRMP_RC6_PROTOCOL) // Manchester, but not RC6 - { - if (irmp_pause_time > irmp_param.pulse_1_len_max && irmp_pause_time <= 2 * irmp_param.pulse_1_len_max) - { - ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); - ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '0' : '1'); - ANALYZE_NEWLINE (); - irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 0 : 1); - } - else if (! last_value) // && irmp_pause_time >= irmp_param.pause_1_len_min && irmp_pause_time <= irmp_param.pause_1_len_max) - { - ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); - - ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '1' : '0'); - ANALYZE_NEWLINE (); - irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0); - } - } - else -#endif // IRMP_SUPPORT_MANCHESTER == 1 - -#if IRMP_SUPPORT_SERIAL == 1 - if (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) - { - ; // do nothing - } - else -#endif // IRMP_SUPPORT_SERIAL == 1 - - -#if IRMP_SUPPORT_DENON_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_DENON_PROTOCOL) - { - ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); - - if (irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX) - { // pause timings correct for "1"? - ANALYZE_PUTCHAR ('1'); // yes, store 1 - ANALYZE_NEWLINE (); - irmp_store_bit (1); - } - else // if (irmp_pause_time >= DENON_0_PAUSE_LEN_MIN && irmp_pause_time <= DENON_0_PAUSE_LEN_MAX) - { // pause timings correct for "0"? - ANALYZE_PUTCHAR ('0'); // yes, store 0 - ANALYZE_NEWLINE (); - irmp_store_bit (0); - } - } - else -#endif // IRMP_SUPPORT_DENON_PROTOCOL == 1 -#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_THOMSON_PROTOCOL) - { - ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); - - if (irmp_pause_time >= THOMSON_1_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_1_PAUSE_LEN_MAX) - { // pause timings correct for "1"? - ANALYZE_PUTCHAR ('1'); // yes, store 1 - ANALYZE_NEWLINE (); - irmp_store_bit (1); - } - else // if (irmp_pause_time >= THOMSON_0_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_0_PAUSE_LEN_MAX) - { // pause timings correct for "0"? - ANALYZE_PUTCHAR ('0'); // yes, store 0 - ANALYZE_NEWLINE (); - irmp_store_bit (0); - } - } - else -#endif // IRMP_SUPPORT_THOMSON_PROTOCOL == 1 - { - ; // else do nothing - } - - irmp_pulse_time = 1; // set counter to 1, not 0 - irmp_pause_time = 0; - wait_for_start_space = 0; - } - } - else if (wait_for_space) // the data section.... - { // counting the time of darkness.... - uint8_t got_light = FALSE; - - if (irmp_input) // still dark? - { // yes... - if (irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 1) - { - if ( -#if IRMP_SUPPORT_MANCHESTER == 1 - (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) || -#endif -#if IRMP_SUPPORT_SERIAL == 1 - (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) || -#endif - (irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max)) - { -#ifdef ANALYZE - if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) - { - ANALYZE_PRINTF ("stop bit detected\n"); - } -#endif - irmp_param.stop_bit = 0; - } - else - { - ANALYZE_PRINTF ("error: stop bit timing wrong, irmp_bit = %d, irmp_pulse_time = %d, pulse_0_len_min = %d, pulse_0_len_max = %d\n", - irmp_bit, irmp_pulse_time, irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); - -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // wait for another start bit... - irmp_pulse_time = 0; - irmp_pause_time = 0; - } - } - else - { - irmp_pause_time++; // increment counter - -#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && // Sony has a variable number of bits: - irmp_pause_time > SIRCS_PAUSE_LEN_MAX && // minimum is 12 - irmp_bit >= 12 - 1) // pause too long? - { // yes, break and close this frame - irmp_param.complete_len = irmp_bit + 1; // set new complete length - got_light = TRUE; // this is a lie, but helps (generates stop bit) - irmp_tmp_address |= (irmp_bit - SIRCS_MINIMUM_DATA_LEN + 1) << 8; // new: store number of additional bits in upper byte of address! - irmp_param.command_end = irmp_param.command_offset + irmp_bit + 1; // correct command length - irmp_pause_time = SIRCS_PAUSE_LEN_MAX - 1; // correct pause length - } - else -#endif -#if IRMP_SUPPORT_SERIAL == 1 - // NETBOX generates no stop bit, here is the timeout condition: - if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) && irmp_param.protocol == IRMP_NETBOX_PROTOCOL && - irmp_pause_time >= NETBOX_PULSE_LEN * (NETBOX_COMPLETE_DATA_LEN - irmp_bit)) - { - got_light = TRUE; // this is a lie, but helps (generates stop bit) - } - else -#endif -#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && !irmp_param.stop_bit) - { - if (irmp_pause_time > IR60_TIMEOUT_LEN && irmp_bit == 6) - { - ANALYZE_PRINTF ("Switching to IR60 protocol\n"); - got_light = TRUE; // this is a lie, but generates a stop bit ;-) - irmp_param.stop_bit = TRUE; // set flag - - irmp_param.protocol = IRMP_IR60_PROTOCOL; // change protocol - irmp_param.complete_len = IR60_COMPLETE_DATA_LEN; // correct complete len - irmp_param.address_offset = IR60_ADDRESS_OFFSET; - irmp_param.address_end = IR60_ADDRESS_OFFSET + IR60_ADDRESS_LEN; - irmp_param.command_offset = IR60_COMMAND_OFFSET; - irmp_param.command_end = IR60_COMMAND_OFFSET + IR60_COMMAND_LEN; - - irmp_tmp_command <<= 1; - irmp_tmp_command |= first_bit; - } - else if (irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN - 2) - { // special manchester decoder - irmp_param.complete_len = GRUNDIG_COMPLETE_DATA_LEN; // correct complete len - got_light = TRUE; // this is a lie, but generates a stop bit ;-) - irmp_param.stop_bit = TRUE; // set flag - } - else if (irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN) - { - ANALYZE_PRINTF ("Switching to NOKIA protocol\n"); - irmp_param.protocol = IRMP_NOKIA_PROTOCOL; // change protocol - irmp_param.address_offset = NOKIA_ADDRESS_OFFSET; - irmp_param.address_end = NOKIA_ADDRESS_OFFSET + NOKIA_ADDRESS_LEN; - irmp_param.command_offset = NOKIA_COMMAND_OFFSET; - irmp_param.command_end = NOKIA_COMMAND_OFFSET + NOKIA_COMMAND_LEN; - - if (irmp_tmp_command & 0x300) - { - irmp_tmp_address = (irmp_tmp_command >> 8); - irmp_tmp_command &= 0xFF; - } - } - } - else -#endif -#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_RUWIDO_PROTOCOL && !irmp_param.stop_bit) - { - if (irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= RUWIDO_COMPLETE_DATA_LEN - 2) - { // special manchester decoder - irmp_param.complete_len = RUWIDO_COMPLETE_DATA_LEN; // correct complete len - got_light = TRUE; // this is a lie, but generates a stop bit ;-) - irmp_param.stop_bit = TRUE; // set flag - } - else if (irmp_bit >= RUWIDO_COMPLETE_DATA_LEN) - { - ANALYZE_PRINTF ("Switching to SIEMENS protocol\n"); - irmp_param.protocol = IRMP_SIEMENS_PROTOCOL; // change protocol - irmp_param.address_offset = SIEMENS_ADDRESS_OFFSET; - irmp_param.address_end = SIEMENS_ADDRESS_OFFSET + SIEMENS_ADDRESS_LEN; - irmp_param.command_offset = SIEMENS_COMMAND_OFFSET; - irmp_param.command_end = SIEMENS_COMMAND_OFFSET + SIEMENS_COMMAND_LEN; - - // 76543210 - // RUWIDO: AAAAAAAAACCCCCCCp - // SIEMENS: AAAAAAAAAAACCCCCCCCCCp - irmp_tmp_address <<= 2; - irmp_tmp_address |= (irmp_tmp_command >> 6); - irmp_tmp_command &= 0x003F; - irmp_tmp_command <<= 4; - irmp_tmp_command |= last_value; - } - } - else -#endif -#if IRMP_SUPPORT_MANCHESTER == 1 - if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && - irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= irmp_param.complete_len - 2 && !irmp_param.stop_bit) - { // special manchester decoder - got_light = TRUE; // this is a lie, but generates a stop bit ;-) - irmp_param.stop_bit = TRUE; // set flag - } - else -#endif // IRMP_SUPPORT_MANCHESTER == 1 - if (irmp_pause_time > IRMP_TIMEOUT_LEN) // timeout? - { // yes... - if (irmp_bit == irmp_param.complete_len - 1 && irmp_param.stop_bit == 0) - { - irmp_bit++; - } -#if IRMP_SUPPORT_JVC_PROTOCOL == 1 - else if (irmp_param.protocol == IRMP_NEC_PROTOCOL && (irmp_bit == 16 || irmp_bit == 17)) // it was a JVC stop bit - { - ANALYZE_PRINTF ("Switching to JVC protocol, irmp_bit = %d\n", irmp_bit); - irmp_param.stop_bit = TRUE; // set flag - irmp_param.protocol = IRMP_JVC_PROTOCOL; // switch protocol - irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 - irmp_tmp_command = (irmp_tmp_address >> 4); // set command: upper 12 bits are command bits - irmp_tmp_address = irmp_tmp_address & 0x000F; // lower 4 bits are address bits - irmp_start_bit_detected = 1; // tricky: don't wait for another start bit... - } -#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 - -#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 -#if IRMP_SUPPORT_NEC_PROTOCOL == 1 - else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit == 32) // it was a NEC stop bit - { - ANALYZE_PRINTF ("Switching to NEC protocol\n"); - irmp_param.stop_bit = TRUE; // set flag - irmp_param.protocol = IRMP_NEC_PROTOCOL; // switch protocol - irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 - - // 0123456789ABC0123456789ABC0123456701234567 - // NEC42: AAAAAAAAAAAAAaaaaaaaaaaaaaCCCCCCCCcccccccc - // NEC: AAAAAAAAaaaaaaaaCCCCCCCCcccccccc - irmp_tmp_address |= (irmp_tmp_address2 & 0x0007) << 13; // fm 2012-02-13: 12 -> 13 - irmp_tmp_command = (irmp_tmp_address2 >> 3) | (irmp_tmp_command << 10); - } -#endif // IRMP_SUPPORT_NEC_PROTOCOL == 1 -#if IRMP_SUPPORT_JVC_PROTOCOL == 1 - else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && (irmp_bit == 16 || irmp_bit == 17)) // it was a JVC stop bit - { - ANALYZE_PRINTF ("Switching to JVC protocol, irmp_bit = %d\n", irmp_bit); - irmp_param.stop_bit = TRUE; // set flag - irmp_param.protocol = IRMP_JVC_PROTOCOL; // switch protocol - irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 - - // 0123456789ABC0123456789ABC0123456701234567 - // NEC42: AAAAAAAAAAAAAaaaaaaaaaaaaaCCCCCCCCcccccccc - // JVC: AAAACCCCCCCCCCCC - irmp_tmp_command = (irmp_tmp_address >> 4) | (irmp_tmp_address2 << 9); // set command: upper 12 bits are command bits - irmp_tmp_address = irmp_tmp_address & 0x000F; // lower 4 bits are address bits - } -#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 -#endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1 - else - { - ANALYZE_PRINTF ("error 2: pause %d after data bit %d too long\n", irmp_pause_time, irmp_bit); - ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); - -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // wait for another start bit... - irmp_pulse_time = 0; - irmp_pause_time = 0; - } - } - } - } - else - { // got light now! - got_light = TRUE; - } - - if (got_light) - { - ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); - -#if IRMP_SUPPORT_MANCHESTER == 1 - if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) // Manchester - { -#if 1 - if (irmp_pulse_time > irmp_param.pulse_1_len_max /* && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max */) -#else // better, but some IR-RCs use asymmetric timings :-/ - if (irmp_pulse_time > irmp_param.pulse_1_len_max && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max && - irmp_pause_time <= 2 * irmp_param.pause_1_len_max) -#endif - { -#if IRMP_SUPPORT_RC6_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 4 && irmp_pulse_time > RC6_TOGGLE_BIT_LEN_MIN) // RC6 toggle bit - { - ANALYZE_PUTCHAR ('T'); - if (irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG) // RC6 mode 6A - { - irmp_store_bit (1); - last_value = 1; - } - else // RC6 mode 0 - { - irmp_store_bit (0); - last_value = 0; - } - ANALYZE_NEWLINE (); - } - else -#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 - { - ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '0' : '1'); - irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 0 : 1 ); - -#if IRMP_SUPPORT_RC6_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 4 && irmp_pulse_time > RC6_TOGGLE_BIT_LEN_MIN) // RC6 toggle bit - { - ANALYZE_PUTCHAR ('T'); - irmp_store_bit (1); - - if (irmp_pause_time > 2 * irmp_param.pause_1_len_max) - { - last_value = 0; - } - else - { - last_value = 1; - } - ANALYZE_NEWLINE (); - } - else -#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 - { - ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '1' : '0'); - irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0 ); -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) - if (! irmp_param2.protocol) -#endif - { - ANALYZE_NEWLINE (); - } - last_value = (irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0; - } - } - } - else if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max - /* && irmp_pause_time <= 2 * irmp_param.pause_1_len_max */) - { - uint8_t manchester_value; - - if (last_pause > irmp_param.pause_1_len_max && last_pause <= 2 * irmp_param.pause_1_len_max) - { - manchester_value = last_value ? 0 : 1; - last_value = manchester_value; - } - else - { - manchester_value = last_value; - } - - ANALYZE_PUTCHAR (manchester_value + '0'); - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) - if (! irmp_param2.protocol) -#endif - { - ANALYZE_NEWLINE (); - } - -#if IRMP_SUPPORT_RC6_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 1 && manchester_value == 1) // RC6 mode != 0 ??? - { - ANALYZE_PRINTF ("Switching to RC6A protocol\n"); - irmp_param.complete_len = RC6_COMPLETE_DATA_LEN_LONG; - irmp_param.address_offset = 5; - irmp_param.address_end = irmp_param.address_offset + 15; - irmp_param.command_offset = irmp_param.address_end + 1; // skip 1 system bit, changes like a toggle bit - irmp_param.command_end = irmp_param.command_offset + 16 - 1; - irmp_tmp_address = 0; - } -#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 - - irmp_store_bit (manchester_value); - } - else - { -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_FDC_PROTOCOL == 1 - if (irmp_param2.protocol == IRMP_FDC_PROTOCOL && - irmp_pulse_time >= FDC_PULSE_LEN_MIN && irmp_pulse_time <= FDC_PULSE_LEN_MAX && - ((irmp_pause_time >= FDC_1_PAUSE_LEN_MIN && irmp_pause_time <= FDC_1_PAUSE_LEN_MAX) || - (irmp_pause_time >= FDC_0_PAUSE_LEN_MIN && irmp_pause_time <= FDC_0_PAUSE_LEN_MAX))) - { - ANALYZE_PUTCHAR ('?'); - irmp_param.protocol = 0; // switch to FDC, see below - } - else -#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCCAR_PROTOCOL == 1 - if (irmp_param2.protocol == IRMP_RCCAR_PROTOCOL && - irmp_pulse_time >= RCCAR_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_PULSE_LEN_MAX && - ((irmp_pause_time >= RCCAR_1_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_1_PAUSE_LEN_MAX) || - (irmp_pause_time >= RCCAR_0_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_0_PAUSE_LEN_MAX))) - { - ANALYZE_PUTCHAR ('?'); - irmp_param.protocol = 0; // switch to RCCAR, see below - } - else -#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 - { - ANALYZE_PUTCHAR ('?'); - ANALYZE_NEWLINE (); - ANALYZE_PRINTF ("error 3 manchester: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); - ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // reset flags and wait for next start bit - irmp_pause_time = 0; - } - } - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_FDC_PROTOCOL == 1 - if (irmp_param2.protocol == IRMP_FDC_PROTOCOL && irmp_pulse_time >= FDC_PULSE_LEN_MIN && irmp_pulse_time <= FDC_PULSE_LEN_MAX) - { - if (irmp_pause_time >= FDC_1_PAUSE_LEN_MIN && irmp_pause_time <= FDC_1_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF (" 1 (FDC)\n"); - irmp_store_bit2 (1); - } - else if (irmp_pause_time >= FDC_0_PAUSE_LEN_MIN && irmp_pause_time <= FDC_0_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF (" 0 (FDC)\n"); - irmp_store_bit2 (0); - } - - if (! irmp_param.protocol) - { - ANALYZE_PRINTF ("Switching to FDC protocol\n"); - memcpy (&irmp_param, &irmp_param2, sizeof (IRMP_PARAMETER)); - irmp_param2.protocol = 0; - irmp_tmp_address = irmp_tmp_address2; - irmp_tmp_command = irmp_tmp_command2; - } - } -#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCCAR_PROTOCOL == 1 - if (irmp_param2.protocol == IRMP_RCCAR_PROTOCOL && irmp_pulse_time >= RCCAR_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_PULSE_LEN_MAX) - { - if (irmp_pause_time >= RCCAR_1_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_1_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF (" 1 (RCCAR)\n"); - irmp_store_bit2 (1); - } - else if (irmp_pause_time >= RCCAR_0_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_0_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF (" 0 (RCCAR)\n"); - irmp_store_bit2 (0); - } - - if (! irmp_param.protocol) - { - ANALYZE_PRINTF ("Switching to RCCAR protocol\n"); - memcpy (&irmp_param, &irmp_param2, sizeof (IRMP_PARAMETER)); - irmp_param2.protocol = 0; - irmp_tmp_address = irmp_tmp_address2; - irmp_tmp_command = irmp_tmp_command2; - } - } -#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 - - last_pause = irmp_pause_time; - wait_for_space = 0; - } - else -#endif // IRMP_SUPPORT_MANCHESTER == 1 - -#if IRMP_SUPPORT_SERIAL == 1 - if (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) - { - while (irmp_bit < irmp_param.complete_len && irmp_pulse_time > irmp_param.pulse_1_len_max) - { - ANALYZE_PUTCHAR ('1'); - irmp_store_bit (1); - - if (irmp_pulse_time >= irmp_param.pulse_1_len_min) - { - irmp_pulse_time -= irmp_param.pulse_1_len_min; - } - else - { - irmp_pulse_time = 0; - } - } - - while (irmp_bit < irmp_param.complete_len && irmp_pause_time > irmp_param.pause_1_len_max) - { - ANALYZE_PUTCHAR ('0'); - irmp_store_bit (0); - - if (irmp_pause_time >= irmp_param.pause_1_len_min) - { - irmp_pause_time -= irmp_param.pause_1_len_min; - } - else - { - irmp_pause_time = 0; - } - } - ANALYZE_NEWLINE (); - wait_for_space = 0; - } - else -#endif // IRMP_SUPPORT_SERIAL == 1 - -#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_SAMSUNG_PROTOCOL && irmp_bit == 16) // Samsung: 16th bit - { - if (irmp_pulse_time >= SAMSUNG_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_PULSE_LEN_MAX && - irmp_pause_time >= SAMSUNG_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_START_BIT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("SYNC\n"); - wait_for_space = 0; - irmp_tmp_id = 0; - irmp_bit++; - } - else if (irmp_pulse_time >= SAMSUNG_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_PULSE_LEN_MAX) - { - irmp_param.protocol = IRMP_SAMSUNG32_PROTOCOL; - irmp_param.command_offset = SAMSUNG32_COMMAND_OFFSET; - irmp_param.command_end = SAMSUNG32_COMMAND_OFFSET + SAMSUNG32_COMMAND_LEN; - irmp_param.complete_len = SAMSUNG32_COMPLETE_DATA_LEN; - - if (irmp_pause_time >= SAMSUNG_1_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_1_PAUSE_LEN_MAX) - { - ANALYZE_PUTCHAR ('1'); - ANALYZE_NEWLINE (); - irmp_store_bit (1); - wait_for_space = 0; - } - else - { - ANALYZE_PUTCHAR ('0'); - ANALYZE_NEWLINE (); - irmp_store_bit (0); - wait_for_space = 0; - } - - ANALYZE_PRINTF ("Switching to SAMSUNG32 protocol\n"); - } - else - { // timing incorrect! - ANALYZE_PRINTF ("error 3 Samsung: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); - ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // reset flags and wait for next start bit - irmp_pause_time = 0; - } - } - else -#endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL - -#if IRMP_SUPPORT_NEC16_PROTOCOL -#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && -#else // IRMP_SUPPORT_NEC_PROTOCOL instead - if (irmp_param.protocol == IRMP_NEC_PROTOCOL && -#endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1 - irmp_bit == 8 && irmp_pause_time >= NEC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_START_BIT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("Switching to NEC16 protocol\n"); - irmp_param.protocol = IRMP_NEC16_PROTOCOL; - irmp_param.address_offset = NEC16_ADDRESS_OFFSET; - irmp_param.address_end = NEC16_ADDRESS_OFFSET + NEC16_ADDRESS_LEN; - irmp_param.command_offset = NEC16_COMMAND_OFFSET; - irmp_param.command_end = NEC16_COMMAND_OFFSET + NEC16_COMMAND_LEN; - irmp_param.complete_len = NEC16_COMPLETE_DATA_LEN; - wait_for_space = 0; - } - else -#endif // IRMP_SUPPORT_NEC16_PROTOCOL - -#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_BANG_OLUFSEN_PROTOCOL) - { - if (irmp_pulse_time >= BANG_OLUFSEN_PULSE_LEN_MIN && irmp_pulse_time <= BANG_OLUFSEN_PULSE_LEN_MAX) - { - if (irmp_bit == 1) // Bang & Olufsen: 3rd bit - { - if (irmp_pause_time >= BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("3rd start bit\n"); - wait_for_space = 0; - irmp_bit++; - } - else - { // timing incorrect! - ANALYZE_PRINTF ("error 3a B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); - ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // reset flags and wait for next start bit - irmp_pause_time = 0; - } - } - else if (irmp_bit == 19) // Bang & Olufsen: trailer bit - { - if (irmp_pause_time >= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("trailer bit\n"); - wait_for_space = 0; - irmp_bit++; - } - else - { // timing incorrect! - ANALYZE_PRINTF ("error 3b B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); - ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // reset flags and wait for next start bit - irmp_pause_time = 0; - } - } - else - { - if (irmp_pause_time >= BANG_OLUFSEN_1_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_1_PAUSE_LEN_MAX) - { // pulse & pause timings correct for "1"? - ANALYZE_PUTCHAR ('1'); - ANALYZE_NEWLINE (); - irmp_store_bit (1); - last_value = 1; - wait_for_space = 0; - } - else if (irmp_pause_time >= BANG_OLUFSEN_0_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_0_PAUSE_LEN_MAX) - { // pulse & pause timings correct for "0"? - ANALYZE_PUTCHAR ('0'); - ANALYZE_NEWLINE (); - irmp_store_bit (0); - last_value = 0; - wait_for_space = 0; - } - else if (irmp_pause_time >= BANG_OLUFSEN_R_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_R_PAUSE_LEN_MAX) - { - ANALYZE_PUTCHAR (last_value + '0'); - ANALYZE_NEWLINE (); - irmp_store_bit (last_value); - wait_for_space = 0; - } - else - { // timing incorrect! - ANALYZE_PRINTF ("error 3c B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); - ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // reset flags and wait for next start bit - irmp_pause_time = 0; - } - } - } - else - { // timing incorrect! - ANALYZE_PRINTF ("error 3d B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); - ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // reset flags and wait for next start bit - irmp_pause_time = 0; - } - } - else -#endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL - - if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max && - irmp_pause_time >= irmp_param.pause_1_len_min && irmp_pause_time <= irmp_param.pause_1_len_max) - { // pulse & pause timings correct for "1"? - ANALYZE_PUTCHAR ('1'); - ANALYZE_NEWLINE (); - irmp_store_bit (1); - wait_for_space = 0; - } - else if (irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max && - irmp_pause_time >= irmp_param.pause_0_len_min && irmp_pause_time <= irmp_param.pause_0_len_max) - { // pulse & pause timings correct for "0"? - ANALYZE_PUTCHAR ('0'); - ANALYZE_NEWLINE (); - irmp_store_bit (0); - wait_for_space = 0; - } - else -#if IRMP_SUPPORT_KATHREIN_PROTOCOL - - if (irmp_param.protocol == IRMP_KATHREIN_PROTOCOL && - irmp_pulse_time >= KATHREIN_1_PULSE_LEN_MIN && irmp_pulse_time <= KATHREIN_1_PULSE_LEN_MAX && - (((irmp_bit == 8 || irmp_bit == 6) && - irmp_pause_time >= KATHREIN_SYNC_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_SYNC_BIT_PAUSE_LEN_MAX) || - (irmp_bit == 12 && - irmp_pause_time >= KATHREIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_START_BIT_PAUSE_LEN_MAX))) - - { - if (irmp_bit == 8) - { - irmp_bit++; - ANALYZE_PUTCHAR ('S'); - ANALYZE_NEWLINE (); - irmp_tmp_command <<= 1; - } - else - { - ANALYZE_PUTCHAR ('S'); - ANALYZE_NEWLINE (); - irmp_store_bit (1); - } - wait_for_space = 0; - } - else -#endif // IRMP_SUPPORT_KATHREIN_PROTOCOL - { // timing incorrect! - ANALYZE_PRINTF ("error 3: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); - ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // reset flags and wait for next start bit - irmp_pause_time = 0; - } - - irmp_pulse_time = 1; // set counter to 1, not 0 - } - } - else - { // counting the pulse length ... - if (! irmp_input) // still light? - { // yes... - irmp_pulse_time++; // increment counter - } - else - { // now it's dark! - wait_for_space = 1; // let's count the time (see above) - irmp_pause_time = 1; // set pause counter to 1, not 0 - } - } - - if (irmp_start_bit_detected && irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 0) // enough bits received? - { - if (last_irmp_command == irmp_tmp_command && repetition_len < AUTO_FRAME_REPETITION_LEN) - { - repetition_frame_number++; - } - else - { - repetition_frame_number = 0; - } - -#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 - // if SIRCS protocol and the code will be repeated within 50 ms, we will ignore 2nd and 3rd repetition frame - if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && (repetition_frame_number == 1 || repetition_frame_number == 2)) - { - ANALYZE_PRINTF ("code skipped: SIRCS auto repetition frame #%d, counter = %d, auto repetition len = %d\n", - repetition_frame_number + 1, repetition_len, AUTO_FRAME_REPETITION_LEN); - repetition_len = 0; - } - else -#endif - -#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 - // if KASEIKYO protocol and the code will be repeated within 50 ms, we will ignore 2nd repetition frame - if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL && repetition_frame_number == 1) - { - ANALYZE_PRINTF ("code skipped: KASEIKYO auto repetition frame #%d, counter = %d, auto repetition len = %d\n", - repetition_frame_number + 1, repetition_len, AUTO_FRAME_REPETITION_LEN); - repetition_len = 0; - } - else -#endif - -#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 - // if SAMSUNG32 protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame - if (irmp_param.protocol == IRMP_SAMSUNG32_PROTOCOL && (repetition_frame_number & 0x01)) - { - ANALYZE_PRINTF ("code skipped: SAMSUNG32 auto repetition frame #%d, counter = %d, auto repetition len = %d\n", - repetition_frame_number + 1, repetition_len, AUTO_FRAME_REPETITION_LEN); - repetition_len = 0; - } - else -#endif - -#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 - // if NUBERT protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame - if (irmp_param.protocol == IRMP_NUBERT_PROTOCOL && (repetition_frame_number & 0x01)) - { - ANALYZE_PRINTF ("code skipped: NUBERT auto repetition frame #%d, counter = %d, auto repetition len = %d\n", - repetition_frame_number + 1, repetition_len, AUTO_FRAME_REPETITION_LEN); - repetition_len = 0; - } - else -#endif - - { - ANALYZE_PRINTF ("%8.3fms code detected, length = %d\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit); - irmp_ir_detected = TRUE; - -#if IRMP_SUPPORT_DENON_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_DENON_PROTOCOL) - { // check for repetition frame - if ((~irmp_tmp_command & 0x3FF) == last_irmp_denon_command) // command bits must be inverted - { - irmp_tmp_command = last_irmp_denon_command; // use command received before! - - irmp_protocol = irmp_param.protocol; // store protocol - irmp_address = irmp_tmp_address; // store address - irmp_command = irmp_tmp_command ; // store command - } - else - { - ANALYZE_PRINTF ("waiting for inverted command repetition\n"); - irmp_ir_detected = FALSE; - last_irmp_denon_command = irmp_tmp_command; - } - } - else -#endif // IRMP_SUPPORT_DENON_PROTOCOL - -#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && irmp_tmp_command == 0x01ff) - { // Grundig start frame? - ANALYZE_PRINTF ("Detected GRUNDIG start frame, ignoring it\n"); - irmp_ir_detected = FALSE; - } - else -#endif // IRMP_SUPPORT_GRUNDIG_PROTOCOL - -#if IRMP_SUPPORT_NOKIA_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_NOKIA_PROTOCOL && irmp_tmp_address == 0x00ff && irmp_tmp_command == 0x00fe) - { // Nokia start frame? - ANALYZE_PRINTF ("Detected NOKIA start frame, ignoring it\n"); - irmp_ir_detected = FALSE; - } - else -#endif // IRMP_SUPPORT_NOKIA_PROTOCOL - { -#if IRMP_SUPPORT_NEC_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_NEC_PROTOCOL && irmp_bit == 0) // repetition frame - { - if (repetition_len < NEC_FRAME_REPEAT_PAUSE_LEN_MAX) - { - ANALYZE_PRINTF ("Detected NEC repetition frame, repetition_len = %d\n", repetition_len); - irmp_tmp_address = last_irmp_address; // address is last address - irmp_tmp_command = last_irmp_command; // command is last command - irmp_flags |= IRMP_FLAG_REPETITION; - repetition_len = 0; - } - else - { - ANALYZE_PRINTF ("Detected NEC repetition frame, ignoring it: timeout occured, repetition_len = %d > %d\n", - repetition_len, NEC_FRAME_REPEAT_PAUSE_LEN_MAX); - irmp_ir_detected = FALSE; - } - } -#endif // IRMP_SUPPORT_NEC_PROTOCOL - -#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL) - { - uint8_t xor; - // ANALYZE_PRINTF ("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", - // xor_check[0], xor_check[1], xor_check[2], xor_check[3], xor_check[4], xor_check[5]); - - xor = (xor_check[0] & 0x0F) ^ ((xor_check[0] & 0xF0) >> 4) ^ (xor_check[1] & 0x0F) ^ ((xor_check[1] & 0xF0) >> 4); - - if (xor != (xor_check[2] & 0x0F)) - { - ANALYZE_PRINTF ("error 4: wrong XOR check for customer id: 0x%1x 0x%1x\n", xor, xor_check[2] & 0x0F); - irmp_ir_detected = FALSE; - } - - xor = xor_check[2] ^ xor_check[3] ^ xor_check[4]; - - if (xor != xor_check[5]) - { - ANALYZE_PRINTF ("error 4: wrong XOR check for data bits: 0x%02x 0x%02x\n", xor, xor_check[5]); - irmp_ir_detected = FALSE; - } - - irmp_flags |= genre2; // write the genre2 bits into MSB of the flag byte - } -#endif // IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 - -#if IRMP_SUPPORT_RC6_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG) // RC6 mode = 6? - { - irmp_protocol = IRMP_RC6A_PROTOCOL; - } - else -#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 - - irmp_protocol = irmp_param.protocol; - -#if IRMP_SUPPORT_FDC_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_FDC_PROTOCOL) - { - if (irmp_tmp_command & 0x000F) // released key? - { - irmp_tmp_command = (irmp_tmp_command >> 4) | 0x80; // yes, set bit 7 - } - else - { - irmp_tmp_command >>= 4; // no, it's a pressed key - } - irmp_tmp_command |= (irmp_tmp_address << 2) & 0x0F00; // 000000CCCCAAAAAA -> 0000CCCC00000000 - irmp_tmp_address &= 0x003F; - } -#endif - - irmp_address = irmp_tmp_address; // store address -#if IRMP_SUPPORT_NEC_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_NEC_PROTOCOL) - { - last_irmp_address = irmp_tmp_address; // store as last address, too - } -#endif - -#if IRMP_SUPPORT_RC5_PROTOCOL == 1 - if (irmp_param.protocol == IRMP_RC5_PROTOCOL) - { - irmp_tmp_command |= rc5_cmd_bit6; // store bit 6 - } -#endif - irmp_command = irmp_tmp_command; // store command - -#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 - irmp_id = irmp_tmp_id; -#endif - } - } - - if (irmp_ir_detected) - { - if (last_irmp_command == irmp_tmp_command && - last_irmp_address == irmp_tmp_address && - repetition_len < IRMP_KEY_REPETITION_LEN) - { - irmp_flags |= IRMP_FLAG_REPETITION; - } - - last_irmp_address = irmp_tmp_address; // store as last address, too - last_irmp_command = irmp_tmp_command; // store as last command, too - - repetition_len = 0; - } - else - { - ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); - } - -// irmp_busy_flag = FALSE; - irmp_start_bit_detected = 0; // and wait for next start bit - irmp_tmp_command = 0; - irmp_pulse_time = 0; - irmp_pause_time = 0; - -#if IRMP_SUPPORT_JVC_PROTOCOL == 1 - if (irmp_protocol == IRMP_JVC_PROTOCOL) // the stop bit of JVC frame is also start bit of next frame - { // set pulse time here! - irmp_pulse_time = ((uint8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME)); - } -#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 - } - } - } - return (irmp_ir_detected); -} - -#ifdef ANALYZE - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * main functions - for Unix/Linux + Windows only! - * - * AVR: see main.c! - * - * Compile it under linux with: - * cc irmp.c -o irmp - * - * usage: ./irmp [-v|-s|-a|-l|-p] < file - * - * options: - * -v verbose - * -s silent - * -a analyze - * -l list pulse/pauses - * -p print timings - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ - -#ifndef IRMP_EMBED -static void -print_timings (void) -{ - printf ("IRMP_TIMEOUT_LEN: %d [%d byte(s)]\n", IRMP_TIMEOUT_LEN, sizeof (PAUSE_LEN)); - printf ("IRMP_KEY_REPETITION_LEN %d\n", IRMP_KEY_REPETITION_LEN); - puts (""); - printf ("PROTOCOL S S-PULSE S-PAUSE PULSE-0 PAUSE-0 PULSE-1 PAUSE-1\n"); - printf ("====================================================================================\n"); - printf ("SIRCS 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - SIRCS_START_BIT_PULSE_LEN_MIN, SIRCS_START_BIT_PULSE_LEN_MAX, SIRCS_START_BIT_PAUSE_LEN_MIN, SIRCS_START_BIT_PAUSE_LEN_MAX, - SIRCS_0_PULSE_LEN_MIN, SIRCS_0_PULSE_LEN_MAX, SIRCS_PAUSE_LEN_MIN, SIRCS_PAUSE_LEN_MAX, - SIRCS_1_PULSE_LEN_MIN, SIRCS_1_PULSE_LEN_MAX, SIRCS_PAUSE_LEN_MIN, SIRCS_PAUSE_LEN_MAX); - - printf ("NEC 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX, - NEC_PULSE_LEN_MIN, NEC_PULSE_LEN_MAX, NEC_0_PAUSE_LEN_MIN, NEC_0_PAUSE_LEN_MAX, - NEC_PULSE_LEN_MIN, NEC_PULSE_LEN_MAX, NEC_1_PAUSE_LEN_MIN, NEC_1_PAUSE_LEN_MAX); - - printf ("NEC (rep) 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX, - NEC_PULSE_LEN_MIN, NEC_PULSE_LEN_MAX, NEC_0_PAUSE_LEN_MIN, NEC_0_PAUSE_LEN_MAX, - NEC_PULSE_LEN_MIN, NEC_PULSE_LEN_MAX, NEC_1_PAUSE_LEN_MIN, NEC_1_PAUSE_LEN_MAX); - - printf ("SAMSUNG 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - SAMSUNG_START_BIT_PULSE_LEN_MIN, SAMSUNG_START_BIT_PULSE_LEN_MAX, SAMSUNG_START_BIT_PAUSE_LEN_MIN, SAMSUNG_START_BIT_PAUSE_LEN_MAX, - SAMSUNG_PULSE_LEN_MIN, SAMSUNG_PULSE_LEN_MAX, SAMSUNG_0_PAUSE_LEN_MIN, SAMSUNG_0_PAUSE_LEN_MAX, - SAMSUNG_PULSE_LEN_MIN, SAMSUNG_PULSE_LEN_MAX, SAMSUNG_1_PAUSE_LEN_MIN, SAMSUNG_1_PAUSE_LEN_MAX); - - printf ("MATSUSHITA 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - MATSUSHITA_START_BIT_PULSE_LEN_MIN, MATSUSHITA_START_BIT_PULSE_LEN_MAX, MATSUSHITA_START_BIT_PAUSE_LEN_MIN, MATSUSHITA_START_BIT_PAUSE_LEN_MAX, - MATSUSHITA_PULSE_LEN_MIN, MATSUSHITA_PULSE_LEN_MAX, MATSUSHITA_0_PAUSE_LEN_MIN, MATSUSHITA_0_PAUSE_LEN_MAX, - MATSUSHITA_PULSE_LEN_MIN, MATSUSHITA_PULSE_LEN_MAX, MATSUSHITA_1_PAUSE_LEN_MIN, MATSUSHITA_1_PAUSE_LEN_MAX); - - printf ("KASEIKYO 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - KASEIKYO_START_BIT_PULSE_LEN_MIN, KASEIKYO_START_BIT_PULSE_LEN_MAX, KASEIKYO_START_BIT_PAUSE_LEN_MIN, KASEIKYO_START_BIT_PAUSE_LEN_MAX, - KASEIKYO_PULSE_LEN_MIN, KASEIKYO_PULSE_LEN_MAX, KASEIKYO_0_PAUSE_LEN_MIN, KASEIKYO_0_PAUSE_LEN_MAX, - KASEIKYO_PULSE_LEN_MIN, KASEIKYO_PULSE_LEN_MAX, KASEIKYO_1_PAUSE_LEN_MIN, KASEIKYO_1_PAUSE_LEN_MAX); - - printf ("RECS80 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - RECS80_START_BIT_PULSE_LEN_MIN, RECS80_START_BIT_PULSE_LEN_MAX, RECS80_START_BIT_PAUSE_LEN_MIN, RECS80_START_BIT_PAUSE_LEN_MAX, - RECS80_PULSE_LEN_MIN, RECS80_PULSE_LEN_MAX, RECS80_0_PAUSE_LEN_MIN, RECS80_0_PAUSE_LEN_MAX, - RECS80_PULSE_LEN_MIN, RECS80_PULSE_LEN_MAX, RECS80_1_PAUSE_LEN_MIN, RECS80_1_PAUSE_LEN_MAX); - - printf ("RC5 1 %3d - %3d %3d - %3d %3d - %3d\n", - RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, - RC5_BIT_LEN_MIN, RC5_BIT_LEN_MAX); - - printf ("DENON 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX, - DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX, DENON_0_PAUSE_LEN_MIN, DENON_0_PAUSE_LEN_MAX, - DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX, DENON_1_PAUSE_LEN_MIN, DENON_1_PAUSE_LEN_MAX); - - printf ("THOMSON 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX, - THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX, THOMSON_0_PAUSE_LEN_MIN, THOMSON_0_PAUSE_LEN_MAX, - THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX, THOMSON_1_PAUSE_LEN_MIN, THOMSON_1_PAUSE_LEN_MAX); - - printf ("RC6 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - RC6_START_BIT_PULSE_LEN_MIN, RC6_START_BIT_PULSE_LEN_MAX, RC6_START_BIT_PAUSE_LEN_MIN, RC6_START_BIT_PAUSE_LEN_MAX, - RC6_BIT_PULSE_LEN_MIN, RC6_BIT_PULSE_LEN_MAX, RC6_BIT_PAUSE_LEN_MIN, RC6_BIT_PAUSE_LEN_MAX); - - printf ("RECS80EXT 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - RECS80EXT_START_BIT_PULSE_LEN_MIN, RECS80EXT_START_BIT_PULSE_LEN_MAX, RECS80EXT_START_BIT_PAUSE_LEN_MIN, RECS80EXT_START_BIT_PAUSE_LEN_MAX, - RECS80EXT_PULSE_LEN_MIN, RECS80EXT_PULSE_LEN_MAX, RECS80EXT_0_PAUSE_LEN_MIN, RECS80EXT_0_PAUSE_LEN_MAX, - RECS80EXT_PULSE_LEN_MIN, RECS80EXT_PULSE_LEN_MAX, RECS80EXT_1_PAUSE_LEN_MIN, RECS80EXT_1_PAUSE_LEN_MAX); - - printf ("NUBERT 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - NUBERT_START_BIT_PULSE_LEN_MIN, NUBERT_START_BIT_PULSE_LEN_MAX, NUBERT_START_BIT_PAUSE_LEN_MIN, NUBERT_START_BIT_PAUSE_LEN_MAX, - NUBERT_0_PULSE_LEN_MIN, NUBERT_0_PULSE_LEN_MAX, NUBERT_0_PAUSE_LEN_MIN, NUBERT_0_PAUSE_LEN_MAX, - NUBERT_1_PULSE_LEN_MIN, NUBERT_1_PULSE_LEN_MAX, NUBERT_1_PAUSE_LEN_MIN, NUBERT_1_PAUSE_LEN_MAX); - - printf ("BANG_OLUFSEN 1 %3d - %3d %3d - %3d\n", - BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX, - BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX); - - printf ("BANG_OLUFSEN 2 %3d - %3d %3d - %3d\n", - BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX, - BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX); - - printf ("BANG_OLUFSEN 3 %3d - %3d %3d - %3d\n", - BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX, - BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX); - - printf ("BANG_OLUFSEN 4 %3d - %3d %3d - %3d\n", - BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX, - BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX); - - printf ("BANG_OLUFSEN - %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - BANG_OLUFSEN_PULSE_LEN_MIN, BANG_OLUFSEN_PULSE_LEN_MAX, BANG_OLUFSEN_0_PAUSE_LEN_MIN, BANG_OLUFSEN_0_PAUSE_LEN_MAX, - BANG_OLUFSEN_PULSE_LEN_MIN, BANG_OLUFSEN_PULSE_LEN_MAX, BANG_OLUFSEN_1_PAUSE_LEN_MIN, BANG_OLUFSEN_1_PAUSE_LEN_MAX); - - printf ("GRUNDIG/NOKIA 1 %3d - %3d %3d - %3d %3d - %3d\n", - GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN, GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX, - GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN, GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX, - GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, GRUNDIG_NOKIA_IR60_BIT_LEN_MAX); - - printf ("SIEMENS/RUWIDO 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX, - SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX, - SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN, SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX, - SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN, SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX, - 2 * SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX, - 2 * SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX); - - printf ("GRUNDIG2 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - GRUNDIG2_START_BIT_PULSE_LEN_MIN, GRUNDIG2_START_BIT_PULSE_LEN_MAX, - GRUNDIG2_START_BIT_PAUSE_LEN_MIN, GRUNDIG2_START_BIT_PAUSE_LEN_MAX, - GRUNDIG2_BIT_PULSE_LEN_MIN, GRUNDIG2_BIT_PULSE_LEN_MAX, - GRUNDIG2_BIT_PAUSE_LEN_MIN, GRUNDIG2_BIT_PAUSE_LEN_MAX, - 2 * GRUNDIG2_BIT_PULSE_LEN_MIN, 2 * GRUNDIG2_BIT_PULSE_LEN_MAX, - 2 * GRUNDIG2_BIT_PAUSE_LEN_MIN, 2 * GRUNDIG2_BIT_PAUSE_LEN_MAX); - - printf ("FDC 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX, FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX, - FDC_PULSE_LEN_MIN, FDC_PULSE_LEN_MAX, FDC_0_PAUSE_LEN_MIN, FDC_0_PAUSE_LEN_MAX, - FDC_PULSE_LEN_MIN, FDC_PULSE_LEN_MAX, FDC_1_PAUSE_LEN_MIN, FDC_1_PAUSE_LEN_MAX); - - printf ("RCCAR 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX, RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX, - RCCAR_PULSE_LEN_MIN, RCCAR_PULSE_LEN_MAX, RCCAR_0_PAUSE_LEN_MIN, RCCAR_0_PAUSE_LEN_MAX, - RCCAR_PULSE_LEN_MIN, RCCAR_PULSE_LEN_MAX, RCCAR_1_PAUSE_LEN_MIN, RCCAR_1_PAUSE_LEN_MAX); - - printf ("NIKON 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - NIKON_START_BIT_PULSE_LEN_MIN, NIKON_START_BIT_PULSE_LEN_MAX, NIKON_START_BIT_PAUSE_LEN_MIN, NIKON_START_BIT_PAUSE_LEN_MAX, - NIKON_PULSE_LEN_MIN, NIKON_PULSE_LEN_MAX, NIKON_0_PAUSE_LEN_MIN, NIKON_0_PAUSE_LEN_MAX, - NIKON_PULSE_LEN_MIN, NIKON_PULSE_LEN_MAX, NIKON_1_PAUSE_LEN_MIN, NIKON_1_PAUSE_LEN_MAX); - - printf ("LEGO 1 %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d %3d - %3d\n", - LEGO_START_BIT_PULSE_LEN_MIN, LEGO_START_BIT_PULSE_LEN_MAX, LEGO_START_BIT_PAUSE_LEN_MIN, LEGO_START_BIT_PAUSE_LEN_MAX, - LEGO_PULSE_LEN_MIN, LEGO_PULSE_LEN_MAX, LEGO_0_PAUSE_LEN_MIN, LEGO_0_PAUSE_LEN_MAX, - LEGO_PULSE_LEN_MIN, LEGO_PULSE_LEN_MAX, LEGO_1_PAUSE_LEN_MIN, LEGO_1_PAUSE_LEN_MAX); - -} - -void -print_spectrum (char * text, int * buf, int is_pulse) -{ - int i; - int j; - int min; - int max; - int max_value = 0; - int value; - int sum = 0; - int counter = 0; - double average = 0; - double tolerance; - - puts ("-------------------------------------------------------------------------------"); - printf ("%s:\n", text); - - for (i = 0; i < 256; i++) - { - if (buf[i] > max_value) - { - max_value = buf[i]; - } - } - - for (i = 1; i < 100; i++) - { - if (buf[i] > 0) - { - printf ("%3d ", i); - value = (buf[i] * 60) / max_value; - - for (j = 0; j < value; j++) - { - putchar ('o'); - } - printf (" %d\n", buf[i]); - - sum += i * buf[i]; - counter += buf[i]; - } - else - { - max = i - 1; - - if (counter > 0) - { - average = (float) sum / (float) counter; - - if (is_pulse) - { - printf ("pulse "); - } - else - { - printf ("pause "); - } - - printf ("avg: %4.1f=%6.1f us, ", average, (1000000. * average) / (float) F_INTERRUPTS); - printf ("min: %2d=%6.1f us, ", min, (1000000. * min) / (float) F_INTERRUPTS); - printf ("max: %2d=%6.1f us, ", max, (1000000. * max) / (float) F_INTERRUPTS); - - tolerance = (max - average); - - if (average - min > tolerance) - { - tolerance = average - min; - } - - tolerance = tolerance * 100 / average; - printf ("tol: %4.1f%%\n", tolerance); - } - - counter = 0; - sum = 0; - min = i + 1; - } - } -} -#endif - -#define STATE_LEFT_SHIFT 0x01 -#define STATE_RIGHT_SHIFT 0x02 -#define STATE_LEFT_CTRL 0x04 -#define STATE_LEFT_ALT 0x08 -#define STATE_RIGHT_ALT 0x10 - -#define KEY_ESCAPE 0x1B // keycode = 0x006e -#define KEY_MENUE 0x80 // keycode = 0x0070 -#define KEY_BACK 0x81 // keycode = 0x0071 -#define KEY_FORWARD 0x82 // keycode = 0x0072 -#define KEY_ADDRESS 0x83 // keycode = 0x0073 -#define KEY_WINDOW 0x84 // keycode = 0x0074 -#define KEY_1ST_PAGE 0x85 // keycode = 0x0075 -#define KEY_STOP 0x86 // keycode = 0x0076 -#define KEY_MAIL 0x87 // keycode = 0x0077 -#define KEY_FAVORITES 0x88 // keycode = 0x0078 -#define KEY_NEW_PAGE 0x89 // keycode = 0x0079 -#define KEY_SETUP 0x8A // keycode = 0x007a -#define KEY_FONT 0x8B // keycode = 0x007b -#define KEY_PRINT 0x8C // keycode = 0x007c -#define KEY_ON_OFF 0x8E // keycode = 0x007c - -#define KEY_INSERT 0x90 // keycode = 0x004b -#define KEY_DELETE 0x91 // keycode = 0x004c -#define KEY_LEFT 0x92 // keycode = 0x004f -#define KEY_HOME 0x93 // keycode = 0x0050 -#define KEY_END 0x94 // keycode = 0x0051 -#define KEY_UP 0x95 // keycode = 0x0053 -#define KEY_DOWN 0x96 // keycode = 0x0054 -#define KEY_PAGE_UP 0x97 // keycode = 0x0055 -#define KEY_PAGE_DOWN 0x98 // keycode = 0x0056 -#define KEY_RIGHT 0x99 // keycode = 0x0059 -#define KEY_MOUSE_1 0x9E // keycode = 0x0400 -#define KEY_MOUSE_2 0x9F // keycode = 0x0800 - -#ifndef LIRC_IRMP -static uint8_t -get_fdc_key (uint16_t cmd) -{ - static uint8_t key_table[128] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, '^', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'ß', '´', 0, '\b', - '\t','q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 'ü', '+', 0, 0, 'a', - 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä', '#', '\r', 0, '<', 'y', 'x', - 'c', 'v', 'b', 'n', 'm', ',', '.', '-', 0, 0, 0, 0, 0, ' ', 0, 0, - - 0, '°', '!', '"', '§', '$', '%', '&', '/', '(', ')', '=', '?', '`', 0, '\b', - '\t','Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 'Ü', '*', 0, 0, 'A', - 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Ö', 'Ä', '\'','\r', 0, '>', 'Y', 'X', - 'C', 'V', 'B', 'N', 'M', ';', ':', '_', 0, 0, 0, 0, 0, ' ', 0, 0 - }; - static uint8_t state; - - uint8_t key = 0; - - switch (cmd) - { - case 0x002C: state |= STATE_LEFT_SHIFT; break; // pressed left shift - case 0x00AC: state &= ~STATE_LEFT_SHIFT; break; // released left shift - case 0x0039: state |= STATE_RIGHT_SHIFT; break; // pressed right shift - case 0x00B9: state &= ~STATE_RIGHT_SHIFT; break; // released right shift - case 0x003A: state |= STATE_LEFT_CTRL; break; // pressed left ctrl - case 0x00BA: state &= ~STATE_LEFT_CTRL; break; // released left ctrl - case 0x003C: state |= STATE_LEFT_ALT; break; // pressed left alt - case 0x00BC: state &= ~STATE_LEFT_ALT; break; // released left alt - case 0x003E: state |= STATE_RIGHT_ALT; break; // pressed left alt - case 0x00BE: state &= ~STATE_RIGHT_ALT; break; // released left alt - - case 0x006e: key = KEY_ESCAPE; break; - case 0x004b: key = KEY_INSERT; break; - case 0x004c: key = KEY_DELETE; break; - case 0x004f: key = KEY_LEFT; break; - case 0x0050: key = KEY_HOME; break; - case 0x0051: key = KEY_END; break; - case 0x0053: key = KEY_UP; break; - case 0x0054: key = KEY_DOWN; break; - case 0x0055: key = KEY_PAGE_UP; break; - case 0x0056: key = KEY_PAGE_DOWN; break; - case 0x0059: key = KEY_RIGHT; break; - case 0x0400: key = KEY_MOUSE_1; break; - case 0x0800: key = KEY_MOUSE_2; break; - - default: - { - if (!(cmd & 0x80)) // pressed key - { - if (cmd >= 0x70 && cmd <= 0x7F) // function keys - { - key = cmd + 0x10; // 7x -> 8x - } - else if (cmd < 64) // key listed in key_table - { - if (state & (STATE_LEFT_ALT | STATE_RIGHT_ALT)) - { - switch (cmd) - { - case 0x0003: key = '²'; break; - case 0x0008: key = '{'; break; - case 0x0009: key = '['; break; - case 0x000A: key = ']'; break; - case 0x000B: key = '}'; break; - case 0x000C: key = '\\'; break; - case 0x001C: key = '~'; break; - case 0x002D: key = '|'; break; - case 0x0034: key = 0xB5; break; // Mu - } - } - else if (state & (STATE_LEFT_CTRL)) - { - if (key_table[cmd] >= 'a' && key_table[cmd] <= 'z') - { - key = key_table[cmd] - 'a' + 1; - } - else - { - key = key_table[cmd]; - } - } - else - { - int idx = cmd + ((state & (STATE_LEFT_SHIFT | STATE_RIGHT_SHIFT)) ? 64 : 0); - - if (key_table[idx]) - { - key = key_table[idx]; - } - } - } - } - break; - } - } - - return (key); -} - -static int analyze = FALSE; -static int list = FALSE; -static IRMP_DATA irmp_data; - -static void -next_tick (void) -{ - if (! analyze && ! list) - { - (void) irmp_ISR (); - - if (irmp_get_data (&irmp_data)) - { - uint8_t key; - - ANALYZE_ONLY_NORMAL_PUTCHAR (' '); - - if (verbose) - { - printf ("%8.3fms ", (double) (time_counter * 1000) / F_INTERRUPTS); - } - - if (irmp_data.protocol == IRMP_FDC_PROTOCOL && (key = get_fdc_key (irmp_data.command)) != 0) - { - if ((key >= 0x20 && key < 0x7F) || key >= 0xA0) - { - printf ("p = %2d, a = 0x%04x, c = 0x%04x, f = 0x%02x, asc = 0x%02x, key = '%c'\n", - irmp_data.protocol, irmp_data.address, irmp_data.command, irmp_data.flags, key, key); - } - else if (key == '\r' || key == '\t' || key == KEY_ESCAPE || (key >= 0x80 && key <= 0x9F)) // function keys - { - char * p = (char *) NULL; - - switch (key) - { - case '\t' : p = "TAB"; break; - case '\r' : p = "CR"; break; - case KEY_ESCAPE : p = "ESCAPE"; break; - case KEY_MENUE : p = "MENUE"; break; - case KEY_BACK : p = "BACK"; break; - case KEY_FORWARD : p = "FORWARD"; break; - case KEY_ADDRESS : p = "ADDRESS"; break; - case KEY_WINDOW : p = "WINDOW"; break; - case KEY_1ST_PAGE : p = "1ST_PAGE"; break; - case KEY_STOP : p = "STOP"; break; - case KEY_MAIL : p = "MAIL"; break; - case KEY_FAVORITES : p = "FAVORITES"; break; - case KEY_NEW_PAGE : p = "NEW_PAGE"; break; - case KEY_SETUP : p = "SETUP"; break; - case KEY_FONT : p = "FONT"; break; - case KEY_PRINT : p = "PRINT"; break; - case KEY_ON_OFF : p = "ON_OFF"; break; - - case KEY_INSERT : p = "INSERT"; break; - case KEY_DELETE : p = "DELETE"; break; - case KEY_LEFT : p = "LEFT"; break; - case KEY_HOME : p = "HOME"; break; - case KEY_END : p = "END"; break; - case KEY_UP : p = "UP"; break; - case KEY_DOWN : p = "DOWN"; break; - case KEY_PAGE_UP : p = "PAGE_UP"; break; - case KEY_PAGE_DOWN : p = "PAGE_DOWN"; break; - case KEY_RIGHT : p = "RIGHT"; break; - case KEY_MOUSE_1 : p = "KEY_MOUSE_1"; break; - case KEY_MOUSE_2 : p = "KEY_MOUSE_2"; break; - default : p = ""; break; - } - - printf ("p = %2d, a = 0x%04x, c = 0x%04x, f = 0x%02x, asc = 0x%02x, key = %s\n", - irmp_data.protocol, irmp_data.address, irmp_data.command, irmp_data.flags, key, p); - } - else - { - printf ("p = %2d, a = 0x%04x, c = 0x%04x, f = 0x%02x, asc = 0x%02x\n", - irmp_data.protocol, irmp_data.address, irmp_data.command, irmp_data.flags, key); - } - } - else - { - printf ("p = %2d, a = 0x%04x, c = 0x%04x, f = 0x%02x\n", - irmp_data.protocol, irmp_data.address, irmp_data.command, irmp_data.flags); - } - } - } -} -#endif - -#ifndef LIRC_IRMP -int -main (int argc, char ** argv) -{ - int i; - int ch; - int last_ch = 0; - int pulse = 0; - int pause = 0; - - int start_pulses[256]; - int start_pauses[256]; - int pulses[256]; - int pauses[256]; - - int first_pulse = TRUE; - int first_pause = TRUE; - - if (argc == 2) - { - if (! strcmp (argv[1], "-v")) - { - verbose = TRUE; - } - else if (! strcmp (argv[1], "-l")) - { - list = TRUE; - } - else if (! strcmp (argv[1], "-a")) - { - analyze = TRUE; - } - else if (! strcmp (argv[1], "-s")) - { - silent = TRUE; - } - else if (! strcmp (argv[1], "-p")) - { - print_timings (); - return (0); - } - } - - for (i = 0; i < 256; i++) - { - start_pulses[i] = 0; - start_pauses[i] = 0; - pulses[i] = 0; - pauses[i] = 0; - } - - IRMP_PIN = 0xFF; - - while ((ch = getchar ()) != EOF) - { - if (ch == '_' || ch == '0') - { - if (last_ch != ch) - { - if (pause > 0) - { - if (list) - { - printf ("pause: %d\n", pause); - } - - if (analyze) - { - if (first_pause) - { - if (pause < 256) - { - start_pauses[pause]++; - } - first_pause = FALSE; - } - else - { - if (pause < 256) - { - pauses[pause]++; - } - } - } - } - pause = 0; - } - pulse++; - IRMP_PIN = 0x00; - } - else if (ch == 0xaf || ch == '-' || ch == '1') - { - if (last_ch != ch) - { - if (list) - { - printf ("pulse: %d ", pulse); - } - - if (analyze) - { - if (first_pulse) - { - if (pulse < 256) - { - start_pulses[pulse]++; - } - first_pulse = FALSE; - } - else - { - if (pulse < 256) - { - pulses[pulse]++; - } - } - } - pulse = 0; - } - - pause++; - IRMP_PIN = 0xff; - } - else if (ch == '\n') - { - IRMP_PIN = 0xff; - - if (list && pause > 0) - { - printf ("pause: %d\n", pause); - } - pause = 0; - - if (! analyze) - { - for (i = 0; i < (int) ((8000.0 * F_INTERRUPTS) / 10000); i++) // newline: long pause of 800 msec - { - next_tick (); - } - } - first_pulse = TRUE; - first_pause = TRUE; - } - else if (ch == '#') - { - if (analyze) - { - while ((ch = getchar()) != '\n' && ch != EOF) - { - ; - } - } - else - { - puts ("-------------------------------------------------------------------"); - putchar (ch); - - while ((ch = getchar()) != '\n' && ch != EOF) - { - if (ch != '\r') // ignore CR in DOS/Windows files - { - putchar (ch); - } - } - putchar ('\n'); - } - - } - - last_ch = ch; - - next_tick (); - } - - if (analyze) - { - print_spectrum ("START PULSES", start_pulses, TRUE); - print_spectrum ("START PAUSES", start_pauses, FALSE); - print_spectrum ("PULSES", pulses, TRUE); - print_spectrum ("PAUSES", pauses, FALSE); - puts ("-------------------------------------------------------------------------------"); - } - return 0; -} -#else -#ifndef IRMP_EMBED -/* 50 ms. This should be longer than the longest light pulse */ -#define POLL_MS (50 * 1000) -#define LIRC_PULSE 0x01000000 -#define LIRC_PULSE_MASK 0x00FFFFFF - -int main (int argc, char ** argv) -{ - int fd; - int pulse; - int last_pulse = 1; - uint32_t lircdata; /* lirc_t to be correct... */ - unsigned int count = 0; /* how many timeouts? */ - IRMP_DATA d; - - silent = TRUE; - - if (argc == 2) - { - if (! strcmp (argv[1], "-v")) - { - verbose = TRUE; - silent = FALSE; - } - else if (! strcmp (argv[1], "-p")) - { - print_timings (); - return (0); - } - } - - IRMP_PIN = 0xFF; - fd = open("/dev/lirc", O_RDONLY); - if (fd < 0) - { - perror ("open /dev/lirc"); - return 1; - } - /* TODO: ioctl to find out if we have a compatible LIRC_MODE2 device */ - - while(1) - { - fd_set fds; - struct timeval tv; - int ret; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - tv.tv_sec = 0; - tv.tv_usec = POLL_MS; - /* any singal can interrupt select. we rely on the linux-only feature - * that the timeout is automatcally recalculated in this case! */ - do { - ret = select(fd + 1, &fds, NULL, NULL, &tv); - } while (ret == -1 && errno == EINTR); - - if (ret == -1) { - /* errno != EINTR... */ - perror("lirmp: select"); - break; - } - - if (ret == 0) - { - count++; - lircdata = POLL_MS; /* timeout */ - pulse = !last_pulse; /* lirc sends data on signal change */ - } - else - { - if (read(fd, &lircdata, sizeof(lircdata)) != sizeof(lircdata)) - { - perror("read"); - break; - } - pulse = (lircdata & LIRC_PULSE); /* we got light... */ - last_pulse = pulse; - lircdata &= LIRC_PULSE_MASK; /* how long the pulse was in microseconds */ - } - - if (ret && count) - { - if (count * POLL_MS > lircdata) - lircdata = 0; - else - lircdata -= count * POLL_MS; - count = 0; - } - //printf("lircdata: ret:%d c:%d %d\n", ret, ch - '0', lircdata); - lircdata /= (1000000 / F_INTERRUPTS); - - if (pulse) - IRMP_PIN = 0x00; - else - IRMP_PIN = 0xff; - - do { - (void) irmp_ISR (); - if (irmp_get_data (&d)) - { - printf("protocol: %2d address: 0x%04x command: 0x%04x flags: %d\n", - d.protocol, d.address, d.command, d.flags); - - /* do something else here... */ - - /* todo: do we need to complete the loop if we already - * detected the singal in this pulse? */ - } - } while (lircdata-- > 0); - } - return 0; -} -#endif // IRMP_EMBED -#endif // LIRC_IRMP -#endif // ANALYZE diff --git a/libarmbox/irmp.h b/libarmbox/irmp.h deleted file mode 100644 index 1e3852b..0000000 --- a/libarmbox/irmp.h +++ /dev/null @@ -1,528 +0,0 @@ -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * irmp.h - * - * Copyright (c) 2009-2011 Frank Meyer - frank(at)fli4l.de - * - * $Id: irmp.h,v 1.70 2012/02/21 08:41:46 fm Exp $ - * - * ATMEGA88 @ 8 MHz - * - * 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. - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ - -#ifndef _WC_IRMP_H_ -#define _WC_IRMP_H_ - -#if defined(__18CXX) // Microchip C18 declaration of missing typedef -typedef unsigned char uint8_t; -typedef unsigned int uint16_t; -#endif //Microchip C18 - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * timing constants: - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -// fm 22.09.2011: may not be more than 16000L, otherwise some JVC codes will not be accepted -#define IRMP_TIMEOUT_TIME 15500.0e-6 // timeout after 15.5 ms darkness -#define IRMP_TIMEOUT_TIME_MS 15500L // timeout after 15.5 ms darkness - -#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 -#define IRMP_TIMEOUT_NIKON_TIME 29500.0e-6 // 2nd timeout after 29.5 ms darkness (only for NIKON!) -#define IRMP_TIMEOUT_NIKON_TIME_MS 29500L // 2nd timeout after 29.5 ms darkness -typedef uint16_t PAUSE_LEN; -#define IRMP_TIMEOUT_NIKON_LEN (PAUSE_LEN)(F_INTERRUPTS * IRMP_TIMEOUT_NIKON_TIME + 0.5) -#else -#if (F_INTERRUPTS * IRMP_TIMEOUT_TIME_MS) / 1000000 >= 254 -typedef uint16_t PAUSE_LEN; -#else -typedef uint8_t PAUSE_LEN; -#endif -#endif - -#define IRMP_TIMEOUT_LEN (PAUSE_LEN)(F_INTERRUPTS * IRMP_TIMEOUT_TIME + 0.5) - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * IR protocols - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#define IRMP_SIRCS_PROTOCOL 1 // Sony -#define IRMP_NEC_PROTOCOL 2 // NEC, Pioneer, JVC, Toshiba, NoName etc. -#define IRMP_SAMSUNG_PROTOCOL 3 // Samsung -#define IRMP_MATSUSHITA_PROTOCOL 4 // Matsushita -#define IRMP_KASEIKYO_PROTOCOL 5 // Kaseikyo (Panasonic etc) -#define IRMP_RECS80_PROTOCOL 6 // Philips, Thomson, Nordmende, Telefunken, Saba -#define IRMP_RC5_PROTOCOL 7 // Philips etc -#define IRMP_DENON_PROTOCOL 8 // Denon, Sharp -#define IRMP_RC6_PROTOCOL 9 // Philips etc -#define IRMP_SAMSUNG32_PROTOCOL 10 // Samsung32: no sync pulse at bit 16, length 32 instead of 37 -#define IRMP_APPLE_PROTOCOL 11 // Apple, very similar to NEC -#define IRMP_RECS80EXT_PROTOCOL 12 // Philips, Technisat, Thomson, Nordmende, Telefunken, Saba -#define IRMP_NUBERT_PROTOCOL 13 // Nubert -#define IRMP_BANG_OLUFSEN_PROTOCOL 14 // Bang & Olufsen -#define IRMP_GRUNDIG_PROTOCOL 15 // Grundig -#define IRMP_NOKIA_PROTOCOL 16 // Nokia -#define IRMP_SIEMENS_PROTOCOL 17 // Siemens, e.g. Gigaset -#define IRMP_FDC_PROTOCOL 18 // FDC keyboard -#define IRMP_RCCAR_PROTOCOL 19 // RC Car -#define IRMP_JVC_PROTOCOL 20 // JVC (NEC with 16 bits) -#define IRMP_RC6A_PROTOCOL 21 // RC6A, e.g. Kathrein, XBOX -#define IRMP_NIKON_PROTOCOL 22 // Nikon -#define IRMP_RUWIDO_PROTOCOL 23 // Ruwido, e.g. T-Home Mediareceiver -#define IRMP_IR60_PROTOCOL 24 // IR60 (SAB2008) -#define IRMP_KATHREIN_PROTOCOL 25 // Kathrein -#define IRMP_NETBOX_PROTOCOL 26 // Netbox keyboard (bitserial) -#define IRMP_NEC16_PROTOCOL 27 // NEC with 16 bits (incl. sync) -#define IRMP_NEC42_PROTOCOL 28 // NEC with 42 bits -#define IRMP_LEGO_PROTOCOL 29 // LEGO Power Functions RC -#define IRMP_THOMSON_PROTOCOL 30 // Thomson -#define IRMP_GRUNDIG2_PROTOCOL 31 // Grundig, e.g. TP400 - -#define IRMP_N_PROTOCOLS 31 // number of supported protocols - -// some flags of struct IRMP_PARAMETER: -#define IRMP_PARAM_FLAG_IS_MANCHESTER 0x01 -#define IRMP_PARAM_FLAG_1ST_PULSE_IS_1 0x02 -#define IRMP_PARAM_FLAG_IS_SERIAL 0x04 - -#define SIRCS_START_BIT_PULSE_TIME 2400.0e-6 // 2400 usec pulse -#define SIRCS_START_BIT_PAUSE_TIME 600.0e-6 // 600 usec pause -#define SIRCS_1_PULSE_TIME 1200.0e-6 // 1200 usec pulse -#define SIRCS_0_PULSE_TIME 600.0e-6 // 600 usec pulse -#define SIRCS_PAUSE_TIME 600.0e-6 // 600 usec pause -#define SIRCS_FRAMES 3 // SIRCS sends each frame 3 times -#define SIRCS_AUTO_REPETITION_PAUSE_TIME 25.0e-3 // auto repetition after 25ms -#define SIRCS_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms -#define SIRCS_ADDRESS_OFFSET 15 // skip 15 bits -#define SIRCS_ADDRESS_LEN 5 // read up to 5 address bits -#define SIRCS_COMMAND_OFFSET 0 // skip 0 bits -#define SIRCS_COMMAND_LEN 15 // read 12-15 command bits -#define SIRCS_MINIMUM_DATA_LEN 12 // minimum data length -#define SIRCS_COMPLETE_DATA_LEN 20 // complete length - may be up to 20 -#define SIRCS_STOP_BIT 0 // has no stop bit -#define SIRCS_LSB 1 // LSB...MSB -#define SIRCS_FLAGS 0 // flags - -#define NEC_START_BIT_PULSE_TIME 9000.0e-6 // 9000 usec pulse -#define NEC_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause -#define NEC_REPEAT_START_BIT_PAUSE_TIME 2250.0e-6 // 2250 usec pause -#define NEC_PULSE_TIME 560.0e-6 // 560 usec pulse -#define NEC_1_PAUSE_TIME 1690.0e-6 // 1690 usec pause -#define NEC_0_PAUSE_TIME 560.0e-6 // 560 usec pause -#define NEC_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms -#define NEC_ADDRESS_OFFSET 0 // skip 0 bits -#define NEC_ADDRESS_LEN 16 // read 16 address bits -#define NEC_COMMAND_OFFSET 16 // skip 16 bits (8 address + 8 /address) -#define NEC_COMMAND_LEN 16 // read 16 bits (8 command + 8 /command) -#define NEC_COMPLETE_DATA_LEN 32 // complete length -#define NEC_STOP_BIT 1 // has stop bit -#define NEC_LSB 1 // LSB...MSB -#define NEC_FLAGS 0 // flags - -#define NEC42_ADDRESS_OFFSET 0 // skip 0 bits -#define NEC42_ADDRESS_LEN 13 // read 13 address bits -#define NEC42_COMMAND_OFFSET 26 // skip 26 bits (2 x 13 address bits) -#define NEC42_COMMAND_LEN 8 // read 8 command bits -#define NEC42_COMPLETE_DATA_LEN 42 // complete length (2 x 13 + 2 x 8) - -#define NEC16_ADDRESS_OFFSET 0 // skip 0 bits -#define NEC16_ADDRESS_LEN 8 // read 8 address bits -#define NEC16_COMMAND_OFFSET 8 // skip 8 bits (8 address) -#define NEC16_COMMAND_LEN 8 // read 8 bits (8 command) -#define NEC16_COMPLETE_DATA_LEN 16 // complete length - -#define SAMSUNG_START_BIT_PULSE_TIME 4500.0e-6 // 4500 usec pulse -#define SAMSUNG_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause -#define SAMSUNG_PULSE_TIME 550.0e-6 // 550 usec pulse -#define SAMSUNG_1_PAUSE_TIME 1650.0e-6 // 1650 usec pause -#define SAMSUNG_0_PAUSE_TIME 550.0e-6 // 550 usec pause - -#define SAMSUNG_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms -#define SAMSUNG_ADDRESS_OFFSET 0 // skip 0 bits -#define SAMSUNG_ADDRESS_LEN 16 // read 16 address bits -#define SAMSUNG_ID_OFFSET 17 // skip 16 + 1 sync bit -#define SAMSUNG_ID_LEN 4 // read 4 id bits -#define SAMSUNG_COMMAND_OFFSET 21 // skip 16 + 1 sync + 4 data bits -#define SAMSUNG_COMMAND_LEN 16 // read 16 command bits -#define SAMSUNG_COMPLETE_DATA_LEN 37 // complete length -#define SAMSUNG_STOP_BIT 1 // has stop bit -#define SAMSUNG_LSB 1 // LSB...MSB? -#define SAMSUNG_FLAGS 0 // flags - -#define SAMSUNG32_COMMAND_OFFSET 16 // skip 16 bits -#define SAMSUNG32_COMMAND_LEN 16 // read 16 command bits -#define SAMSUNG32_COMPLETE_DATA_LEN 32 // complete length -#define SAMSUNG32_FRAMES 1 // SAMSUNG32 sends each frame 1 times -#define SAMSUNG32_AUTO_REPETITION_PAUSE_TIME 47.0e-3 // repetition after 47 ms -#define SAMSUNG32_FRAME_REPEAT_PAUSE_TIME 47.0e-3 // frame repeat after 47ms - -#define MATSUSHITA_START_BIT_PULSE_TIME 3488.0e-6 // 3488 usec pulse -#define MATSUSHITA_START_BIT_PAUSE_TIME 3488.0e-6 // 3488 usec pause -#define MATSUSHITA_PULSE_TIME 872.0e-6 // 872 usec pulse -#define MATSUSHITA_1_PAUSE_TIME 2616.0e-6 // 2616 usec pause -#define MATSUSHITA_0_PAUSE_TIME 872.0e-6 // 872 usec pause -#define MATSUSHITA_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms -#define MATSUSHITA_ADDRESS_OFFSET 12 // skip 12 bits -#define MATSUSHITA_ADDRESS_LEN 12 // read 12 address bits -#define MATSUSHITA_COMMAND_OFFSET 0 // skip 0 bits -#define MATSUSHITA_COMMAND_LEN 12 // read 12 bits (6 custom + 6 command) -#define MATSUSHITA_COMPLETE_DATA_LEN 24 // complete length -#define MATSUSHITA_STOP_BIT 1 // has stop bit -#define MATSUSHITA_LSB 1 // LSB...MSB? -#define MATSUSHITA_FLAGS 0 // flags - -#define KASEIKYO_START_BIT_PULSE_TIME 3380.0e-6 // 3380 usec pulse -#define KASEIKYO_START_BIT_PAUSE_TIME 1690.0e-6 // 1690 usec pause -#define KASEIKYO_PULSE_TIME 423.0e-6 // 525 usec pulse -#define KASEIKYO_1_PAUSE_TIME 1269.0e-6 // 525 usec pause -#define KASEIKYO_0_PAUSE_TIME 423.0e-6 // 1690 usec pause -#define KASEIKYO_AUTO_REPETITION_PAUSE_TIME 74.0e-3 // repetition after 74 ms -#define KASEIKYO_FRAME_REPEAT_PAUSE_TIME 74.0e-3 // frame repeat after 74 ms -#define KASEIKYO_ADDRESS_OFFSET 0 // skip 0 bits -#define KASEIKYO_ADDRESS_LEN 16 // read 16 address bits -#define KASEIKYO_COMMAND_OFFSET 28 // skip 28 bits (16 manufacturer & 4 parity & 8 genre) -#define KASEIKYO_COMMAND_LEN 12 // read 12 command bits (10 real command & 2 id) -#define KASEIKYO_COMPLETE_DATA_LEN 48 // complete length -#define KASEIKYO_STOP_BIT 1 // has stop bit -#define KASEIKYO_LSB 1 // LSB...MSB? -#define KASEIKYO_FRAMES 2 // KASEIKYO sends 1st frame 2 times -#define KASEIKYO_FLAGS 0 // flags - -#define RECS80_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse -#define RECS80_START_BIT_PAUSE_TIME 7432.0e-6 // 7432 usec pause -#define RECS80_PULSE_TIME 158.0e-6 // 158 usec pulse -#define RECS80_1_PAUSE_TIME 7432.0e-6 // 7432 usec pause -#define RECS80_0_PAUSE_TIME 4902.0e-6 // 4902 usec pause -#define RECS80_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms -#define RECS80_ADDRESS_OFFSET 1 // skip 1 bit (toggle bit) -#define RECS80_ADDRESS_LEN 3 // read 3 address bits -#define RECS80_COMMAND_OFFSET 4 // skip 4 bits (1 toggle + 3 address) -#define RECS80_COMMAND_LEN 6 // read 6 command bits -#define RECS80_COMPLETE_DATA_LEN 10 // complete length -#define RECS80_STOP_BIT 1 // has stop bit -#define RECS80_LSB 0 // MSB...LSB -#define RECS80_FLAGS 0 // flags - -#define RC5_BIT_TIME 889.0e-6 // 889 usec pulse/pause -#define RC5_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms - -#define RC5_ADDRESS_OFFSET 1 // skip 1 bit (2nd start) -#define RC5_ADDRESS_LEN 6 // read 1 toggle bit (for key repetition detection) + 5 address bits -#define RC5_COMMAND_OFFSET 7 // skip 5 bits (2nd start + 1 toggle + 5 address) -#define RC5_COMMAND_LEN 6 // read 6 command bits -#define RC5_COMPLETE_DATA_LEN 13 // complete length -#define RC5_STOP_BIT 0 // has no stop bit -#define RC5_LSB 0 // MSB...LSB -#define RC5_FLAGS IRMP_PARAM_FLAG_IS_MANCHESTER // flags - -#define DENON_PULSE_TIME 310.0e-6 // 310 usec pulse in practice, 275 in theory -#define DENON_1_PAUSE_TIME 1780.0e-6 // 1780 usec pause in practice, 1900 in theory -#define DENON_0_PAUSE_TIME 745.0e-6 // 745 usec pause in practice, 775 in theory -#define DENON_FRAMES 2 // DENON sends each frame 2 times -#define DENON_AUTO_REPETITION_PAUSE_TIME 65.0e-3 // inverted repetition after 65ms -#define DENON_FRAME_REPEAT_PAUSE_TIME 65.0e-3 // frame repeat after 65ms -#define DENON_ADDRESS_OFFSET 0 // skip 0 bits -#define DENON_ADDRESS_LEN 5 // read 5 address bits -#define DENON_COMMAND_OFFSET 5 // skip 5 -#define DENON_COMMAND_LEN 10 // read 10 command bits -#define DENON_COMPLETE_DATA_LEN 15 // complete length -#define DENON_STOP_BIT 1 // has stop bit -#define DENON_LSB 0 // MSB...LSB -#define DENON_FLAGS 0 // flags - -#define RC6_START_BIT_PULSE_TIME 2666.0e-6 // 2.666 msec pulse -#define RC6_START_BIT_PAUSE_TIME 889.0e-6 // 889 usec pause -#define RC6_TOGGLE_BIT_TIME 889.0e-6 // 889 msec pulse/pause -#define RC6_BIT_TIME 444.0e-6 // 889 usec pulse/pause -#define RC6_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms -#define RC6_ADDRESS_OFFSET 5 // skip "1" + 3 mode bits + 1 toggle bit -#define RC6_ADDRESS_LEN 8 // read 8 address bits -#define RC6_COMMAND_OFFSET 13 // skip 12 bits ("1" + 3 mode + 1 toggle + 8 address) -#define RC6_COMMAND_LEN 8 // read 8 command bits -#define RC6_COMPLETE_DATA_LEN_SHORT 21 // complete length -#define RC6_COMPLETE_DATA_LEN_LONG 36 // complete length -#define RC6_STOP_BIT 0 // has no stop bit -#define RC6_LSB 0 // MSB...LSB -#define RC6_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags - -#define RECS80EXT_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse -#define RECS80EXT_START_BIT_PAUSE_TIME 3637.0e-6 // 3637 usec pause -#define RECS80EXT_PULSE_TIME 158.0e-6 // 158 usec pulse -#define RECS80EXT_1_PAUSE_TIME 7432.0e-6 // 7432 usec pause -#define RECS80EXT_0_PAUSE_TIME 4902.0e-6 // 4902 usec pause -#define RECS80EXT_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms -#define RECS80EXT_ADDRESS_OFFSET 2 // skip 2 bits (2nd start + 1 toggle) -#define RECS80EXT_ADDRESS_LEN 4 // read 4 address bits -#define RECS80EXT_COMMAND_OFFSET 6 // skip 6 bits (2nd start + 1 toggle + 4 address) -#define RECS80EXT_COMMAND_LEN 6 // read 6 command bits -#define RECS80EXT_COMPLETE_DATA_LEN 12 // complete length -#define RECS80EXT_STOP_BIT 1 // has stop bit -#define RECS80EXT_LSB 0 // MSB...LSB -#define RECS80EXT_FLAGS 0 // flags - -#define NUBERT_START_BIT_PULSE_TIME 1340.0e-6 // 1340 usec pulse -#define NUBERT_START_BIT_PAUSE_TIME 340.0e-6 // 340 usec pause -#define NUBERT_1_PULSE_TIME 1340.0e-6 // 1340 usec pulse -#define NUBERT_1_PAUSE_TIME 340.0e-6 // 340 usec pause -#define NUBERT_0_PULSE_TIME 500.0e-6 // 500 usec pulse -#define NUBERT_0_PAUSE_TIME 1300.0e-6 // 1300 usec pause -#define NUBERT_FRAMES 2 // Nubert sends 2 frames -#define NUBERT_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms -#define NUBERT_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 45ms -#define NUBERT_ADDRESS_OFFSET 0 // skip 0 bits -#define NUBERT_ADDRESS_LEN 0 // read 0 address bits -#define NUBERT_COMMAND_OFFSET 0 // skip 0 bits -#define NUBERT_COMMAND_LEN 10 // read 10 bits -#define NUBERT_COMPLETE_DATA_LEN 10 // complete length -#define NUBERT_STOP_BIT 1 // has stop bit -#define NUBERT_LSB 0 // MSB? -#define NUBERT_FLAGS 0 // flags - -#define BANG_OLUFSEN_START_BIT1_PULSE_TIME 200.0e-6 // 200 usec pulse -#define BANG_OLUFSEN_START_BIT1_PAUSE_TIME 3125.0e-6 // 3125 usec pause -#define BANG_OLUFSEN_START_BIT2_PULSE_TIME 200.0e-6 // 200 usec pulse -#define BANG_OLUFSEN_START_BIT2_PAUSE_TIME 3125.0e-6 // 3125 usec pause -#define BANG_OLUFSEN_START_BIT3_PULSE_TIME 200.0e-6 // 200 usec pulse -#define BANG_OLUFSEN_START_BIT3_PAUSE_TIME 15625.0e-6 // 15625 usec pause -#define BANG_OLUFSEN_START_BIT4_PULSE_TIME 200.0e-6 // 200 usec pulse -#define BANG_OLUFSEN_START_BIT4_PAUSE_TIME 3125.0e-6 // 3125 usec pause -#define BANG_OLUFSEN_PULSE_TIME 200.0e-6 // 200 usec pulse -#define BANG_OLUFSEN_1_PAUSE_TIME 9375.0e-6 // 9375 usec pause -#define BANG_OLUFSEN_0_PAUSE_TIME 3125.0e-6 // 3125 usec pause -#define BANG_OLUFSEN_R_PAUSE_TIME 6250.0e-6 // 6250 usec pause (repeat last bit) -#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME 12500.0e-6 // 12500 usec pause (trailer bit) -#define BANG_OLUFSEN_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms -#define BANG_OLUFSEN_ADDRESS_OFFSET 0 // no address bits -#define BANG_OLUFSEN_ADDRESS_LEN 0 // no address bits -#define BANG_OLUFSEN_COMMAND_OFFSET 3 // skip startbits 2, 3, 4 -#define BANG_OLUFSEN_COMMAND_LEN 16 // read 16 command bits -#define BANG_OLUFSEN_COMPLETE_DATA_LEN 20 // complete length: startbits 2, 3, 4 + 16 data bits + trailer bit -#define BANG_OLUFSEN_STOP_BIT 1 // has stop bit -#define BANG_OLUFSEN_LSB 0 // MSB...LSB -#define BANG_OLUFSEN_FLAGS 0 // flags - -#define GRUNDIG_NOKIA_IR60_BIT_TIME 528.0e-6 // 528 usec pulse/pause -#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME 2639.0e-6 // 2639 usec pause after pre bit -#define GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_TIME 117.76e-3 // info frame repeat after 117.76 ms -#define GRUNDIG_NOKIA_IR60_STOP_BIT 0 // has no stop bit -#define GRUNDIG_NOKIA_IR60_LSB 1 // MSB...LSB -#define GRUNDIG_NOKIA_IR60_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags - -#define GRUNDIG_FRAMES 2 // GRUNDIG sends each frame 1+1 times -#define GRUNDIG_AUTO_REPETITION_PAUSE_TIME 20.0e-3 // repetition after 20ms -#define GRUNDIG_ADDRESS_OFFSET 0 // no address -#define GRUNDIG_ADDRESS_LEN 0 // no address -#define GRUNDIG_COMMAND_OFFSET 1 // skip 1 start bit -#define GRUNDIG_COMMAND_LEN 9 // read 9 command bits -#define GRUNDIG_COMPLETE_DATA_LEN 10 // complete length: 1 start bit + 9 data bits - -#define NOKIA_FRAMES 3 // NOKIA sends each frame 1 + 1 + 1 times -#define NOKIA_AUTO_REPETITION_PAUSE_TIME 20.0e-3 // repetition after 20ms -#define NOKIA_ADDRESS_OFFSET 9 // skip 9 bits (1 start bit + 8 data bits) -#define NOKIA_ADDRESS_LEN 8 // 7 address bits -#define NOKIA_COMMAND_OFFSET 1 // skip 1 bit (1 start bit) -#define NOKIA_COMMAND_LEN 8 // read 8 command bits -#define NOKIA_COMPLETE_DATA_LEN 17 // complete length: 1 start bit + 8 address bits + 8 command bits - -#define IR60_TIMEOUT_TIME 5000.0e-6 // timeout grundig frame, switch to IR60 -#define IR60_ADDRESS_OFFSET 0 // skip 1 bits -#define IR60_ADDRESS_LEN 0 // read 0 address bits -#define IR60_COMMAND_OFFSET 0 // skip 1 bit (start bit after pre bit, always 1) -#define IR60_COMMAND_LEN 7 // read 6 command bits -#define IR60_COMPLETE_DATA_LEN 7 // complete length - -#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME 275.0e-6 // 275 usec pulse -#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME 550.0e-6 // 550 usec pause -#define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME 275.0e-6 // 275 usec short pulse -#define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME_2 550.0e-6 // 550 usec long pulse -#define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME 275.0e-6 // 275 usec short pause -#define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME_2 550.0e-6 // 550 usec long pause -#define SIEMENS_OR_RUWIDO_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms -#define SIEMENS_OR_RUWIDO_STOP_BIT 0 // has no stop bit -#define SIEMENS_OR_RUWIDO_LSB 0 // MSB...LSB -#define SIEMENS_OR_RUWIDO_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags - -#define RUWIDO_ADDRESS_OFFSET 0 // skip 0 bits -#define RUWIDO_ADDRESS_LEN 9 // read 9 address bits -#define RUWIDO_COMMAND_OFFSET 9 // skip 9 bits -#define RUWIDO_COMMAND_LEN 8 // read 7 + 1 command bits, last bit is only check bit -#define RUWIDO_COMPLETE_DATA_LEN 17 // complete length - -#define SIEMENS_ADDRESS_OFFSET 0 // skip 0 bits -#define SIEMENS_ADDRESS_LEN 11 // read 11 bits -#define SIEMENS_COMMAND_OFFSET 11 // skip 11 bits -#define SIEMENS_COMMAND_LEN 11 // read 10 + 1 command bits, last bit is only check bit -#define SIEMENS_COMPLETE_DATA_LEN 22 // complete length - -#define FDC_START_BIT_PULSE_TIME 2085.0e-6 // 2085 usec pulse -#define FDC_START_BIT_PAUSE_TIME 966.0e-6 // 966 usec pause -#define FDC_PULSE_TIME 300.0e-6 // 300 usec pulse -#define FDC_1_PAUSE_TIME 715.0e-6 // 715 usec pause -#define FDC_0_PAUSE_TIME 220.0e-6 // 220 usec pause -#define FDC_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms -#define FDC_ADDRESS_OFFSET 0 // skip 0 bits -#define FDC_ADDRESS_LEN 14 // read 14 address bits, but use only 6, shift 8 into command -#define FDC_COMMAND_OFFSET 20 // skip 20 bits -#define FDC_COMMAND_LEN 12 // read 12 bits -#define FDC_COMPLETE_DATA_LEN 40 // complete length -#define FDC_STOP_BIT 1 // has stop bit -#define FDC_LSB 1 // LSB...MSB -#define FDC_FLAGS 0 // flags - -#define RCCAR_START_BIT_PULSE_TIME 2000.0e-6 // 2000 usec pulse -#define RCCAR_START_BIT_PAUSE_TIME 2000.0e-6 // 2000 usec pause -#define RCCAR_PULSE_TIME 600.0e-6 // 360 usec pulse -#define RCCAR_1_PAUSE_TIME 450.0e-6 // 650 usec pause -#define RCCAR_0_PAUSE_TIME 900.0e-6 // 180 usec pause -#define RCCAR_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms -#define RCCAR_ADDRESS_OFFSET 0 // skip 0 bits -#define RCCAR_ADDRESS_LEN 0 // read 0 address bits -#define RCCAR_COMMAND_OFFSET 0 // skip 0 bits -#define RCCAR_COMMAND_LEN 13 // read 13 bits -#define RCCAR_COMPLETE_DATA_LEN 13 // complete length -#define RCCAR_STOP_BIT 1 // has stop bit -#define RCCAR_LSB 1 // LSB...MSB -#define RCCAR_FLAGS 0 // flags - -#define JVC_START_BIT_PULSE_TIME 9000.0e-6 // 9000 usec pulse -#define JVC_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause -#define JVC_PULSE_TIME 560.0e-6 // 560 usec pulse -#define JVC_1_PAUSE_TIME 1690.0e-6 // 1690 usec pause -#define JVC_0_PAUSE_TIME 560.0e-6 // 560 usec pause -#define JVC_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after 22ms -#define JVC_ADDRESS_OFFSET 0 // skip 0 bits -#define JVC_ADDRESS_LEN 4 // read 4 address bits -#define JVC_COMMAND_OFFSET 4 // skip 4 bits -#define JVC_COMMAND_LEN 12 // read 12 bits -#define JVC_COMPLETE_DATA_LEN 16 // complete length -#define JVC_STOP_BIT 1 // has stop bit -#define JVC_LSB 1 // LSB...MSB -#define JVC_FLAGS 0 // flags - -#define NIKON_START_BIT_PULSE_TIME 2200.0e-6 // 2200 usec pulse -#define NIKON_START_BIT_PAUSE_TIME 27100.0e-6 // 27100 usec pause -#define NIKON_PULSE_TIME 500.0e-6 // 500 usec pulse -#define NIKON_1_PAUSE_TIME 3500.0e-6 // 3500 usec pause -#define NIKON_0_PAUSE_TIME 1500.0e-6 // 1500 usec pause -#define NIKON_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms -#define NIKON_ADDRESS_OFFSET 0 // skip 0 bits -#define NIKON_ADDRESS_LEN 0 // read 0 address bits -#define NIKON_COMMAND_OFFSET 0 // skip 0 bits -#define NIKON_COMMAND_LEN 2 // read 2 bits -#define NIKON_COMPLETE_DATA_LEN 2 // complete length -#define NIKON_STOP_BIT 1 // has stop bit -#define NIKON_LSB 0 // LSB...MSB -#define NIKON_FLAGS 0 // flags - -#define KATHREIN_START_BIT_PULSE_TIME 210.0e-6 // 1340 usec pulse -#define KATHREIN_START_BIT_PAUSE_TIME 6218.0e-6 // 340 usec pause -#define KATHREIN_1_PULSE_TIME 210.0e-6 // 1340 usec pulse -#define KATHREIN_1_PAUSE_TIME 3000.0e-6 // 340 usec pause -#define KATHREIN_0_PULSE_TIME 210.0e-6 // 500 usec pulse -#define KATHREIN_0_PAUSE_TIME 1400.0e-6 // 1300 usec pause -#define KATHREIN_SYNC_BIT_PAUSE_LEN_TIME 4600.0e-6 // 4600 usec sync (on 6th and/or 8th bit) -#define KATHREIN_FRAMES 1 // Kathrein sends 1 frame -#define KATHREIN_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms -#define KATHREIN_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms -#define KATHREIN_ADDRESS_OFFSET 1 // skip 1 bits -#define KATHREIN_ADDRESS_LEN 4 // read 4 address bits -#define KATHREIN_COMMAND_OFFSET 5 // skip 5 bits -#define KATHREIN_COMMAND_LEN 7 // read 7 bits -#define KATHREIN_COMPLETE_DATA_LEN 13 // complete length -#define KATHREIN_STOP_BIT 1 // has stop bit -#define KATHREIN_LSB 0 // MSB -#define KATHREIN_FLAGS 0 // flags - -#define NETBOX_START_BIT_PULSE_TIME 2400.0e-6 // 2400 usec pulse -#define NETBOX_START_BIT_PAUSE_TIME 800.0e-6 // 800 usec pause -#define NETBOX_PULSE_TIME 800.0e-6 // 800 usec pulse -#define NETBOX_PAUSE_TIME 800.0e-6 // 800 usec pause -#define NETBOX_FRAMES 1 // Netbox sends 1 frame -#define NETBOX_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms -#define NETBOX_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms -#define NETBOX_ADDRESS_OFFSET 0 // skip 0 bits -#define NETBOX_ADDRESS_LEN 3 // read 3 address bits -#define NETBOX_COMMAND_OFFSET 3 // skip 3 bits -#define NETBOX_COMMAND_LEN 13 // read 13 bits -#define NETBOX_COMPLETE_DATA_LEN 16 // complete length -#define NETBOX_STOP_BIT 0 // has no stop bit -#define NETBOX_LSB 1 // LSB -#define NETBOX_FLAGS IRMP_PARAM_FLAG_IS_SERIAL // flags - -#define LEGO_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse ( 6 x 1/38kHz) -#define LEGO_START_BIT_PAUSE_TIME 1026.0e-6 // 1026 usec pause (39 x 1/38kHz) -#define LEGO_PULSE_TIME 158.0e-6 // 158 usec pulse ( 6 x 1/38kHz) -#define LEGO_1_PAUSE_TIME 553.0e-6 // 553 usec pause (21 x 1/38kHz) -#define LEGO_0_PAUSE_TIME 263.0e-6 // 263 usec pause (10 x 1/38kHz) -#define LEGO_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms -#define LEGO_ADDRESS_OFFSET 0 // skip 0 bits -#define LEGO_ADDRESS_LEN 0 // read 0 address bits -#define LEGO_COMMAND_OFFSET 0 // skip 0 bits -#define LEGO_COMMAND_LEN 16 // read 16 bits (12 command + 4 CRC) -#define LEGO_COMPLETE_DATA_LEN 16 // complete length -#define LEGO_STOP_BIT 1 // has stop bit -#define LEGO_LSB 0 // MSB...LSB -#define LEGO_FLAGS 0 // flags - -#define THOMSON_PULSE_TIME 550.0e-6 // 550 usec pulse -#define THOMSON_1_PAUSE_TIME 4500.0e-6 // 4500 usec pause -#define THOMSON_0_PAUSE_TIME 2000.0e-6 // 2000 usec pause -#define THOMSON_FRAMES 1 // THOMSON sends 1 frame -#define THOMSON_AUTO_REPETITION_PAUSE_TIME 65.0e-3 // repetition after 65ms -#define THOMSON_FRAME_REPEAT_PAUSE_TIME 65.0e-3 // frame repeat after 65ms -#define THOMSON_ADDRESS_OFFSET 0 // skip 0 bits -#define THOMSON_ADDRESS_LEN 4 // read 4 address bits -#define THOMSON_COMMAND_OFFSET 5 // skip 4 address bits + 1 toggle bit -#define THOMSON_COMMAND_LEN 7 // read 7 command bits -#define THOMSON_COMPLETE_DATA_LEN 12 // complete length -#define THOMSON_STOP_BIT 1 // has stop bit -#define THOMSON_LSB 0 // MSB...LSB -#define THOMSON_FLAGS 0 // flags - -#define GRUNDIG2_START_BIT_PULSE_TIME 550.0e-6 // 550 usec pulse -#define GRUNDIG2_START_BIT_PAUSE_TIME 2700.0e-6 // 2700 usec pause -#define GRUNDIG2_BIT_PULSE_TIME 550.0e-6 // 550 usec short pulse -#define GRUNDIG2_BIT_PAUSE_TIME 550.0e-6 // 550 usec short pause -#define GRUNDIG2_FRAME_REPEAT_PAUSE_TIME 100.0e-3 // frame repeat after 100ms -#define GRUNDIG2_STOP_BIT 0 // has no stop bit -#define GRUNDIG2_LSB 1 // MSB...LSB -#define GRUNDIG2_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags -#define GRUNDIG2_ADDRESS_OFFSET 0 // skip 0 bits -#define GRUNDIG2_ADDRESS_LEN 0 // read 0 bits -#define GRUNDIG2_COMMAND_OFFSET 0 // skip 0 bits -#define GRUNDIG2_COMMAND_LEN 7 // read 6 + 1 command bits, last bit is always 1 -#define GRUNDIG2_COMPLETE_DATA_LEN 7 // complete length - -#define AUTO_FRAME_REPETITION_TIME 80.0e-3 // SIRCS/SAMSUNG32/NUBERT: automatic repetition after 25-50ms - // KASEIKYO: automatic repetition after 75ms - -#define TRUE 1 -#define FALSE 0 - -#define IRMP_FLAG_REPETITION 0x01 - -typedef struct -{ - uint8_t protocol; // protocol, i.e. NEC_PROTOCOL - uint16_t address; // address - uint16_t command; // command - uint8_t flags; // flags, e.g. repetition -} IRMP_DATA; - -extern void irmp_init (void); -extern uint8_t irmp_get_data (IRMP_DATA *); -extern uint8_t irmp_is_busy (void); -extern uint8_t irmp_ISR (uint8_t); - -#if IRMP_PROTOCOL_NAMES == 1 -extern char * irmp_protocol_names[IRMP_N_PROTOCOLS + 1]; -#endif - -#if IRMP_USE_CALLBACK == 1 -extern void irmp_set_callback_ptr (void (*cb)(uint8_t)); -#endif // IRSND_USE_CALLBACK == 1 - -#endif /* _WC_IRMP_H_ */ diff --git a/libarmbox/irmpconfig.h b/libarmbox/irmpconfig.h deleted file mode 100644 index 10b34b7..0000000 --- a/libarmbox/irmpconfig.h +++ /dev/null @@ -1,191 +0,0 @@ -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * irmpconfig.h - * - * Copyright (c) 2009-2011 Frank Meyer - frank(at)fli4l.de - * - * $Id: irmpconfig.h,v 1.80 2012/02/21 08:41:46 fm Exp $ - * - * ATMEGA88 @ 8 MHz - * - * 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. - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ - -#ifndef _IRMPCONFIG_H_ -#define _IRMPCONFIG_H_ - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * Change F_INTERRUPTS if you change the number of interrupts per second, - * Normally, F_INTERRUPTS should be in the range from 10000 to 15000, typical is 15000 - * A value above 15000 costs additional program space, absolute maximum value is 20000. - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#ifndef F_INTERRUPTS -#define F_INTERRUPTS 15000 // interrupts per second, min: 10000, max: 20000, typ: 15000 -#endif - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * Change settings from 1 to 0 if you want to disable one or more decoders. - * This saves program space. - * - * 1 enable decoder - * 0 disable decoder - * - * The standard decoders are enabled per default. - * Less common protocols are disabled here, you need to enable them manually. - * - * If you want to use FDC or RCCAR simultaneous with RC5 protocol, additional program space is required. - * If you don't need RC5 when using FDC/RCCAR, you should disable RC5. - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ - -// typical protocols, disable here! Enable Remarks F_INTERRUPTS Program Space -#define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~150 bytes -#define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE >= 10000 ~300 bytes -#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsung32 >= 10000 ~300 bytes -#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~50 bytes -#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~250 bytes -#define IRMP_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~250 bytes - -// more protocols, enable here! Enable Remarks F_INTERRUPTS Program Space -#define IRMP_SUPPORT_RC5_PROTOCOL 0 // RC5 >= 10000 ~250 bytes -#define IRMP_SUPPORT_RC6_PROTOCOL 0 // RC6 & RC6A >= 10000 ~250 bytes -#define IRMP_SUPPORT_JVC_PROTOCOL 0 // JVC >= 10000 ~150 bytes -#define IRMP_SUPPORT_NEC16_PROTOCOL 0 // NEC16 >= 10000 ~100 bytes -#define IRMP_SUPPORT_NEC42_PROTOCOL 0 // NEC42 >= 10000 ~300 bytes -#define IRMP_SUPPORT_IR60_PROTOCOL 0 // IR60 (SAB2008) >= 10000 ~300 bytes -#define IRMP_SUPPORT_GRUNDIG_PROTOCOL 0 // Grundig >= 10000 ~300 bytes -#define IRMP_SUPPORT_SIEMENS_PROTOCOL 0 // Siemens Gigaset >= 15000 ~550 bytes -#define IRMP_SUPPORT_NOKIA_PROTOCOL 0 // Nokia >= 10000 ~300 bytes - -// exotic protocols, enable here! Enable Remarks F_INTERRUPTS Program Space -#define IRMP_SUPPORT_GRUNDIG2_PROTOCOL 0 // Grundig TP400 >= 10000 ~300 bytes -#define IRMP_SUPPORT_KATHREIN_PROTOCOL 0 // Kathrein >= 10000 ~200 bytes -#define IRMP_SUPPORT_NUBERT_PROTOCOL 0 // NUBERT >= 10000 ~50 bytes -#define IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL 0 // Bang & Olufsen >= 10000 ~200 bytes -#define IRMP_SUPPORT_RECS80_PROTOCOL 0 // RECS80 (SAA3004) >= 15000 ~50 bytes -#define IRMP_SUPPORT_RECS80EXT_PROTOCOL 0 // RECS80EXT (SAA3008) >= 15000 ~50 bytes -#define IRMP_SUPPORT_THOMSON_PROTOCOL 0 // Thomson >= 10000 ~250 bytes -#define IRMP_SUPPORT_NIKON_PROTOCOL 0 // NIKON camera >= 10000 ~250 bytes -#define IRMP_SUPPORT_NETBOX_PROTOCOL 0 // Netbox keyboard >= 10000 ~400 bytes (PROTOTYPE!) -#define IRMP_SUPPORT_FDC_PROTOCOL 0 // FDC3402 keyboard >= 10000 (better 15000) ~150 bytes (~400 in combination with RC5) -#define IRMP_SUPPORT_RCCAR_PROTOCOL 0 // RC Car >= 10000 (better 15000) ~150 bytes (~500 in combination with RC5) -#define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 // RUWIDO, T-Home >= 15000 ~550 bytes -#define IRMP_SUPPORT_LEGO_PROTOCOL 0 // LEGO Power RC >= 20000 ~150 bytes - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * Change hardware pin here: - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#if defined (PIC_C18) // Microchip C18 Compiler -#include // main PIC18 h file -#define IRMP_PIN PORTBbits.RB4 // use RB4 as IR input on PIC -#define input(x) (x) - -#elif defined (PIC_CCS_COMPILER) // PIC CCS Compiler: -#define IRMP_PIN PIN_B4 // use PB4 as IR input on PIC - -#else // AVR: - -#ifndef ARDUINO -#define IRMP_PORT PORTB -#define IRMP_DDR DDRB -#define IRMP_PIN PINB -#define IRMP_BIT 6 // use PB6 as IR input on AVR -#else // ARDUINO -#define IRMP_PIN PIND // use digital pin 2 as IR input -#define IRMP_BIT 2 // on arduino -#endif // ARDUINO - -#define input(x) ((x) & (1 << IRMP_BIT)) -#endif - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * Set IRMP_LOGGING to 1 if want to log data to UART with 9600Bd - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#ifndef IRMP_LOGGING -#define IRMP_LOGGING 0 // 1: log IR signal (scan), 0: do not (default) -#endif - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * Use external logging routines - * If you enable external logging, you have also to enable IRMP_LOGGING above - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#ifndef IRMP_EXT_LOGGING -#define IRMP_EXT_LOGGING 0 // 1:log, 0: do not log ; -#endif - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * Set IRMP_PROTOCOL_NAMES to 1 if want to access protocol names (for logging etc), costs ~300 bytes RAM! - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#define IRMP_PROTOCOL_NAMES 0 // 1: access protocol names, 0: do not (default), - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * Use Callbacks to indicate input signal - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#define IRMP_USE_CALLBACK 0 // flag: 0 = don't use callbacks, 1 = use callbacks, default is 0 - -/*--------------------------------------------------------------------------------------------------------------------------------------------------- - * DO NOT CHANGE THE FOLLOWING LINES ! - *--------------------------------------------------------------------------------------------------------------------------------------------------- - */ -#if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 && F_INTERRUPTS < 15000 -# warning F_INTERRUPTS too low, SIEMENS protocol disabled (should be at least 15000) -# undef IRMP_SUPPORT_SIEMENS_PROTOCOL -# define IRMP_SUPPORT_SIEMENS_PROTOCOL 0 -#endif - -#if IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 && F_INTERRUPTS < 15000 -# warning F_INTERRUPTS too low, RUWIDO protocol disabled (should be at least 15000) -# undef IRMP_SUPPORT_RUWIDO_PROTOCOL -# define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 -#endif - -#if IRMP_SUPPORT_RECS80_PROTOCOL == 1 && F_INTERRUPTS < 15000 -# warning F_INTERRUPTS too low, RECS80 protocol disabled (should be at least 15000) -# undef IRMP_SUPPORT_RECS80_PROTOCOL -# define IRMP_SUPPORT_RECS80_PROTOCOL 0 -#endif - -#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 && F_INTERRUPTS < 15000 -# warning F_INTERRUPTS too low, RECS80EXT protocol disabled (should be at least 15000) -# undef IRMP_SUPPORT_RECS80EXT_PROTOCOL -# define IRMP_SUPPORT_RECS80EXT_PROTOCOL 0 -#endif - -#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 && F_INTERRUPTS < 20000 -# warning F_INTERRUPTS too low, LEGO protocol disabled (should be at least 20000) -# undef IRMP_SUPPORT_LEGO_PROTOCOL -# define IRMP_SUPPORT_LEGO_PROTOCOL 0 -#endif - -#if IRMP_SUPPORT_JVC_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 -# warning JVC protocol needs also NEC protocol, NEC protocol enabled -# undef IRMP_SUPPORT_NEC_PROTOCOL -# define IRMP_SUPPORT_NEC_PROTOCOL 1 -#endif - -#if IRMP_SUPPORT_NEC16_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 -# warning NEC16 protocol needs also NEC protocol, NEC protocol enabled -# undef IRMP_SUPPORT_NEC_PROTOCOL -# define IRMP_SUPPORT_NEC_PROTOCOL 1 -#endif - -#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 -# warning NEC42 protocol needs also NEC protocol, NEC protocol enabled -# undef IRMP_SUPPORT_NEC_PROTOCOL -# define IRMP_SUPPORT_NEC_PROTOCOL 1 -#endif - -#if F_INTERRUPTS > 20000 -#error F_INTERRUPTS too high (should be not greater than 20000) -#endif - -#endif /* _WC_IRMPCONFIG_H_ */ diff --git a/libarmbox/lirmp_input.cpp b/libarmbox/lirmp_input.cpp deleted file mode 100644 index 73dcc06..0000000 --- a/libarmbox/lirmp_input.cpp +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Simulate a linux input device via uinput - * Get lirc remote events, decode with IRMP and inject them via uinput - * - * (C) 2012 Stefan Seyfried - * - * 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, see . - */ - -/* the C++ compiler did not like this code, so let's put it into a - * separate file and compile with gcc insead of g++... - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "lirmp_input.h" -extern "C" { -#include "irmp.h" -} -static uint8_t IRMP_PIN; - -#include -#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args) -#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args) - -/* same defines as in neutrino's rcinput.h */ -#define KEY_TTTV KEY_FN_1 -#define KEY_TTZOOM KEY_FN_2 -#define KEY_REVEAL KEY_FN_D -/* only defined in newer kernels / headers... */ -#ifndef KEY_ZOOMIN -#define KEY_ZOOMIN KEY_FN_E -#endif -#ifndef KEY_ZOOMOUT -#define KEY_ZOOMOUT KEY_FN_F -#endif - -typedef struct { - uint16_t ir; /* IR command */ - int code; /* input key code */ -} key_map_t; - -static const key_map_t key_map[] = { - { 0x13, KEY_0 }, - { 0x1a, KEY_1 }, - { 0x1f, KEY_2 }, - { 0x58, KEY_3 }, - { 0x16, KEY_4 }, - { 0x1b, KEY_5 }, - { 0x54, KEY_6 }, - { 0x12, KEY_7 }, - { 0x17, KEY_8 }, - { 0x50, KEY_9 }, - { 0x5f, KEY_OK }, - { 0x59, KEY_TIME }, - { 0x43, KEY_FAVORITES }, - { 0x4f, KEY_SAT }, - { 0x0f, KEY_NEXT }, /* V.Format */ - { 0x1e, KEY_POWER }, - { 0x5a, KEY_MUTE }, - { 0x1c, KEY_MENU }, - { 0x5d, KEY_EPG }, - { 0x07, KEY_INFO }, - { 0x60, KEY_EXIT }, - { 0x48, KEY_PAGEUP }, - { 0x44, KEY_PAGEDOWN }, - { 0x02, KEY_LEFT }, - { 0x40, KEY_RIGHT }, - { 0x03, KEY_UP }, - { 0x5e, KEY_DOWN }, - { 0x0a, KEY_VOLUMEUP }, - { 0x06, KEY_VOLUMEDOWN }, - { 0x49, KEY_RED }, - { 0x4e, KEY_GREEN }, - { 0x11, KEY_YELLOW }, - { 0x4a, KEY_BLUE }, - { 0x4c, KEY_TV }, /* TV/Radio */ - { 0x5c, KEY_VIDEO }, /* FIND */ - { 0x19, KEY_AUDIO }, /* FOLDER */ -/* KEY_AUX, - KEY_TEXT, - KEY_TTTV, - KEY_TTZOOM, - KEY_REVEAL, -*/ - { 0x01, KEY_REWIND }, - { 0x53, KEY_FORWARD }, - { 0x22, KEY_STOP }, - { 0x4d, KEY_PAUSE }, - { 0x15, KEY_PLAY }, - { 0x20, KEY_PREVIOUS }, - { 0x23, KEY_NEXT }, -// KEY_EJECTCD, - { 0x10, KEY_RECORD } -}; - -static const int key_list[] = { - KEY_0, - KEY_1, - KEY_2, - KEY_3, - KEY_4, - KEY_5, - KEY_6, - KEY_7, - KEY_8, - KEY_9, - KEY_OK, - KEY_TIME, - KEY_FAVORITES, - KEY_SAT, - KEY_ZOOMOUT, - KEY_ZOOMIN, - KEY_NEXT, - KEY_POWER, - KEY_MUTE, - KEY_MENU, - KEY_EPG, - KEY_INFO, - KEY_EXIT, - KEY_PAGEUP, - KEY_PAGEDOWN, - KEY_LEFT, - KEY_RIGHT, - KEY_UP, - KEY_DOWN, - KEY_VOLUMEUP, - KEY_VOLUMEDOWN, - KEY_RED, - KEY_GREEN, - KEY_YELLOW, - KEY_BLUE, - KEY_TV, - KEY_VIDEO, - KEY_AUDIO, -// KEY_AUX, -// KEY_TEXT, -// KEY_TTTV, -// KEY_TTZOOM, -// KEY_REVEAL, - KEY_REWIND, - KEY_STOP, - KEY_PAUSE, - KEY_PLAY, - KEY_FORWARD, - KEY_PREVIOUS, - KEY_NEXT, -// KEY_EJECTCD, - KEY_RECORD, - -1 -}; - -static pthread_t thread; -static int thread_running; - -static void *input_thread(void *) -{ - int uinput; - struct input_event u; - struct uinput_user_dev ud; - FILE *f; - int lircfd; - int pulse; - int i = 0; - int last_pulse = 1; - int last_code = -1; - uint32_t lircdata; /* lirc_t to be correct... */ - unsigned int count = 0; /* how many timeouts? */ - unsigned int nodec = 0; /* how many timeouts since last decoded? */ - int aotom_fd = -1; - IRMP_DATA d; - - lt_info("LIRC/IRMP input converter thread starting...\n"); - - /* modprobe does not complain if the module is already loaded... */ - system("/sbin/modprobe uinput"); - do { - usleep(100000); /* mdev needs some time to create the device? */ - uinput = open("/dev/uinput", O_WRONLY|O_NDELAY); - } while (uinput < 0 && ++count < 100); - - if (uinput < 0) - { - lt_info("LIRC/IRMP input thread: unable to open /dev/uinput (%m)\n"); - thread_running = 2; - return NULL; - } - - fcntl(uinput, F_SETFD, FD_CLOEXEC); - ioctl(uinput, UI_SET_EVBIT, EV_KEY); - /* do not use kernel repeat EV_REP since neutrino will be confused by the - * generated SYN_REPORT events... - ioctl(uinput, UI_SET_EVBIT, EV_REP); - */ - /* register keys */ - for (i = 0; key_list[i] != -1; i++) - ioctl(uinput, UI_SET_KEYBIT, key_list[i]); - - /* configure the device */ - memset(&ud, 0, sizeof(ud)); - strncpy(ud.name, "Neutrino LIRC/IRMP to Input Device converter", UINPUT_MAX_NAME_SIZE); - ud.id.version = 0x42; - ud.id.vendor = 0x1234; - ud.id.product = 0x5678; - ud.id.bustype = BUS_I2C; /* ?? */ - write(uinput, &ud, sizeof(ud)); - - if (ioctl(uinput, UI_DEV_CREATE)) - { - lt_info("LIRC/IRMP input thread UI_DEV_CREATE: %m\n"); - close(uinput); - return NULL; - } - - /* this is ugly: parse the new input device from /proc/...devices - * and symlink it to /dev/input/nevis_ir... */ -#define DEVLINE "I: Bus=0018 Vendor=1234 Product=5678 Version=0042" - f = fopen("/proc/bus/input/devices", "r"); - if (f) - { - int found = 0; - int evdev = -1; - size_t n = 0; - char *line = NULL; - char *p; - char newdev[20]; - while (getline(&line, &n, f) != -1) - { - switch(line[0]) - { - case 'I': - if (strncmp(line, DEVLINE, strlen(DEVLINE)) == 0) - found = 1; - break; - case 'H': - if (! found) - break; - p = strstr(line, " event"); - if (! p) - { - evdev = -1; - break; - } - evdev = atoi(p + 6); - sprintf(newdev, "event%d", evdev); - lt_info("LIRC/IRMP input thread: symlink /dev/input/nevis_ir to %s\n", newdev); - unlink("/dev/input/nevis_ir"); - symlink(newdev, "/dev/input/nevis_ir"); - break; - default: - break; - } - if (evdev != -1) - break; - } - fclose(f); - free(line); - } - - u.type = EV_KEY; - u.value = 0; /* initialize: first event wil be a key press */ - - lircfd = open("/dev/lirc", O_RDONLY); - if (lircfd < 0) - { - lt_info("%s: open /dev/lirc: %m\n", __func__); - goto out; - } - IRMP_PIN = 0xFF; - -/* 50 ms. This should be longer than the longest light pulse */ -#define POLL_MS (100 * 1000) -#define LIRC_PULSE 0x01000000 -#define LIRC_PULSE_MASK 0x00FFFFFF - lt_info("LIRC/IRMP input converter going into main loop...\n"); - - aotom_fd = open("/dev/vfd", O_RDONLY); - - /* TODO: ioctl to find out if we have a compatible LIRC_MODE2 device */ - thread_running = 1; - while (thread_running) - { - fd_set fds; - struct timeval tv; - int ret; - - FD_ZERO(&fds); - FD_SET(lircfd, &fds); - tv.tv_sec = 0; - tv.tv_usec = POLL_MS; - /* any singal can interrupt select. we rely on the linux-only feature - * that the timeout is automatcally recalculated in this case! */ - do { - ret = select(lircfd + 1, &fds, NULL, NULL, &tv); - } while (ret == -1 && errno == EINTR); - - if (ret == -1) { - /* errno != EINTR... */ - lt_info("%s: lirmp: lircfd select: %m\n", __func__); - break; - } - - if (ret == 0) - { - count++; - nodec++; - lircdata = POLL_MS; /* timeout */ - pulse = !last_pulse; /* lirc sends data on signal change */ - if (last_code != -1 && nodec > 1) - { - // fprintf(stderr, "timeout!\n"); - u.code = last_code; - u.value = 0; /* release */ - write(uinput, &u, sizeof(u)); - last_code = -1; - } - } - else - { - if (read(lircfd, &lircdata, sizeof(lircdata)) != sizeof(lircdata)) - { - perror("read"); - break; - } - pulse = (lircdata & LIRC_PULSE); /* we got light... */ - last_pulse = pulse; - lircdata &= LIRC_PULSE_MASK; /* how long the pulse was in microseconds */ - } - - if (ret && count) - { - if (count * POLL_MS > lircdata) - lircdata = 0; - else - lircdata -= count * POLL_MS; - count = 0; - } - //printf("lircdata: ret:%d c:%d %d\n", ret, ch - '0', lircdata); - lircdata /= (1000000 / F_INTERRUPTS); - - if (pulse) - IRMP_PIN = 0x00; - else - IRMP_PIN = 0xff; - - do { - (void) irmp_ISR (IRMP_PIN); - if (irmp_get_data (&d)) - { - nodec = 0; - lt_debug("irmp_get_data proto: %2d addr: 0x%04x cmd: 0x%04x fl: %d\n", - d.protocol, d.address, d.command, d.flags); - - /* todo: do we need to complete the loop if we already - * detected the singal in this pulse? */ - if (d.protocol == IRMP_NEC_PROTOCOL && d.address == 0xba45) - { - for (i = 0; i < (int)(sizeof(key_map)/sizeof(key_map_t)); i++) - { - if (key_map[i].ir == d.command) - { - if (last_code != -1 && last_code != key_map[i].code) - { - u.code = last_code; - u.value = 0; - write(uinput, &u, sizeof(u)); - } - u.code = key_map[i].code; - u.value = (d.flags & 0x1) + 1; - //lt_debug("uinput write: value: %d code: %d\n", u.value, u.code); - last_code = u.code; - write(uinput, &u, sizeof(u)); - if (aotom_fd > -1) { - struct aotom_ioctl_data vfd_data; - vfd_data.u.led.led_nr = 1; - vfd_data.u.led.on = 10; - ioctl(aotom_fd, VFDSETLED, &vfd_data); - } - break; - } - } - } - } - } while (lircdata-- > 0); - } - /* clean up */ - close (lircfd); - - if (aotom_fd > -1) - close(aotom_fd); - - out: - ioctl(uinput, UI_DEV_DESTROY); - return NULL; -} - -void start_input_thread(void) -{ - if (pthread_create(&thread, 0, input_thread, NULL) != 0) - { - lt_info("%s: LIRC/IRMP input thread pthread_create: %m\n", __func__); - thread_running = 0; - return; - } - /* wait until the device is created before continuing */ - while (! thread_running) - usleep(1000); - if (thread_running == 2) /* failed... :-( */ - thread_running = 0; -} - -void stop_input_thread(void) -{ - if (! thread_running) - return; - thread_running = 0; - pthread_join(thread, NULL); -} diff --git a/libarmbox/lirmp_input.h b/libarmbox/lirmp_input.h deleted file mode 100644 index c277dda..0000000 --- a/libarmbox/lirmp_input.h +++ /dev/null @@ -1,7 +0,0 @@ -/* functions from lirmp_input.cpp */ - -#ifndef __LIRMP_INPUT_H_ -#define __LIRMP_INPUT_H_ -void start_input_thread(void); -void stop_input_thread(void); -#endif diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index f62a525..d87e69c 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -403,7 +403,7 @@ int cVideo::SetVideoSystem(int video_system, bool remember) return -1; } int ret = proc_get("/proc/stb/video/videomode", current, 32); - if (strcmp(current, modes[video_system]) == 0) + if (strcmp(current, modes[video_system]) == 0) { lt_info("%s: video_system %d (%s) already set, skipping\n", __func__, video_system, current); return 0; @@ -619,25 +619,6 @@ int cVideo::getBlank(void) return ret; } -/* this function is regularly called, checks if video parameters - changed and triggers appropriate actions */ -void cVideo::VideoParamWatchdog(void) -{ -#if 0 - static unsigned int _v_info = (unsigned int) -1; - unsigned int v_info; - if (fd == -1) - return; - ioctl(fd, MPEG_VID_GET_V_INFO_RAW, &v_info); - if (_v_info != v_info) - { - lt_debug("%s params changed. old: %08x new: %08x\n", __FUNCTION__, _v_info, v_info); - setAspectRatio(-1, -1); - } - _v_info = v_info; -#endif -} - void cVideo::Pig(int x, int y, int w, int h, int osd_w, int osd_h, int startx, int starty, int endx, int endy) { char buffer[64]; @@ -857,226 +838,11 @@ void cVideo::SetColorFormat(COLOR_FORMAT color_format) { proc_put("/proc/stb/avs/0/colorformat", p, strlen(p)); } -/* get an image of the video screen - * this code is inspired by dreambox AIO-grab, - * git://schwerkraft.elitedvb.net/aio-grab/aio-grab.git - * and the patches for STi support from - * https://github.com/Schischu/STLinux.BSP-Duckbox.git */ -/* static lookup tables for faster yuv2rgb conversion */ -static const uint32_t yuv2rgbtable_y[256] = { - 0xFFED5EA0, 0xFFEE88B6, 0xFFEFB2CC, 0xFFF0DCE2, 0xFFF206F8, 0xFFF3310E, 0xFFF45B24, 0xFFF5853A, - 0xFFF6AF50, 0xFFF7D966, 0xFFF9037C, 0xFFFA2D92, 0xFFFB57A8, 0xFFFC81BE, 0xFFFDABD4, 0xFFFED5EA, - 0x00000000, 0x00012A16, 0x0002542C, 0x00037E42, 0x0004A858, 0x0005D26E, 0x0006FC84, 0x0008269A, - 0x000950B0, 0x000A7AC6, 0x000BA4DC, 0x000CCEF2, 0x000DF908, 0x000F231E, 0x00104D34, 0x0011774A, - 0x0012A160, 0x0013CB76, 0x0014F58C, 0x00161FA2, 0x001749B8, 0x001873CE, 0x00199DE4, 0x001AC7FA, - 0x001BF210, 0x001D1C26, 0x001E463C, 0x001F7052, 0x00209A68, 0x0021C47E, 0x0022EE94, 0x002418AA, - 0x002542C0, 0x00266CD6, 0x002796EC, 0x0028C102, 0x0029EB18, 0x002B152E, 0x002C3F44, 0x002D695A, - 0x002E9370, 0x002FBD86, 0x0030E79C, 0x003211B2, 0x00333BC8, 0x003465DE, 0x00358FF4, 0x0036BA0A, - 0x0037E420, 0x00390E36, 0x003A384C, 0x003B6262, 0x003C8C78, 0x003DB68E, 0x003EE0A4, 0x00400ABA, - 0x004134D0, 0x00425EE6, 0x004388FC, 0x0044B312, 0x0045DD28, 0x0047073E, 0x00483154, 0x00495B6A, - 0x004A8580, 0x004BAF96, 0x004CD9AC, 0x004E03C2, 0x004F2DD8, 0x005057EE, 0x00518204, 0x0052AC1A, - 0x0053D630, 0x00550046, 0x00562A5C, 0x00575472, 0x00587E88, 0x0059A89E, 0x005AD2B4, 0x005BFCCA, - 0x005D26E0, 0x005E50F6, 0x005F7B0C, 0x0060A522, 0x0061CF38, 0x0062F94E, 0x00642364, 0x00654D7A, - 0x00667790, 0x0067A1A6, 0x0068CBBC, 0x0069F5D2, 0x006B1FE8, 0x006C49FE, 0x006D7414, 0x006E9E2A, - 0x006FC840, 0x0070F256, 0x00721C6C, 0x00734682, 0x00747098, 0x00759AAE, 0x0076C4C4, 0x0077EEDA, - 0x007918F0, 0x007A4306, 0x007B6D1C, 0x007C9732, 0x007DC148, 0x007EEB5E, 0x00801574, 0x00813F8A, - 0x008269A0, 0x008393B6, 0x0084BDCC, 0x0085E7E2, 0x008711F8, 0x00883C0E, 0x00896624, 0x008A903A, - 0x008BBA50, 0x008CE466, 0x008E0E7C, 0x008F3892, 0x009062A8, 0x00918CBE, 0x0092B6D4, 0x0093E0EA, - 0x00950B00, 0x00963516, 0x00975F2C, 0x00988942, 0x0099B358, 0x009ADD6E, 0x009C0784, 0x009D319A, - 0x009E5BB0, 0x009F85C6, 0x00A0AFDC, 0x00A1D9F2, 0x00A30408, 0x00A42E1E, 0x00A55834, 0x00A6824A, - 0x00A7AC60, 0x00A8D676, 0x00AA008C, 0x00AB2AA2, 0x00AC54B8, 0x00AD7ECE, 0x00AEA8E4, 0x00AFD2FA, - 0x00B0FD10, 0x00B22726, 0x00B3513C, 0x00B47B52, 0x00B5A568, 0x00B6CF7E, 0x00B7F994, 0x00B923AA, - 0x00BA4DC0, 0x00BB77D6, 0x00BCA1EC, 0x00BDCC02, 0x00BEF618, 0x00C0202E, 0x00C14A44, 0x00C2745A, - 0x00C39E70, 0x00C4C886, 0x00C5F29C, 0x00C71CB2, 0x00C846C8, 0x00C970DE, 0x00CA9AF4, 0x00CBC50A, - 0x00CCEF20, 0x00CE1936, 0x00CF434C, 0x00D06D62, 0x00D19778, 0x00D2C18E, 0x00D3EBA4, 0x00D515BA, - 0x00D63FD0, 0x00D769E6, 0x00D893FC, 0x00D9BE12, 0x00DAE828, 0x00DC123E, 0x00DD3C54, 0x00DE666A, - 0x00DF9080, 0x00E0BA96, 0x00E1E4AC, 0x00E30EC2, 0x00E438D8, 0x00E562EE, 0x00E68D04, 0x00E7B71A, - 0x00E8E130, 0x00EA0B46, 0x00EB355C, 0x00EC5F72, 0x00ED8988, 0x00EEB39E, 0x00EFDDB4, 0x00F107CA, - 0x00F231E0, 0x00F35BF6, 0x00F4860C, 0x00F5B022, 0x00F6DA38, 0x00F8044E, 0x00F92E64, 0x00FA587A, - 0x00FB8290, 0x00FCACA6, 0x00FDD6BC, 0x00FF00D2, 0x01002AE8, 0x010154FE, 0x01027F14, 0x0103A92A, - 0x0104D340, 0x0105FD56, 0x0107276C, 0x01085182, 0x01097B98, 0x010AA5AE, 0x010BCFC4, 0x010CF9DA, - 0x010E23F0, 0x010F4E06, 0x0110781C, 0x0111A232, 0x0112CC48, 0x0113F65E, 0x01152074, 0x01164A8A -}; -static const uint32_t yuv2rgbtable_ru[256] = { - 0xFEFDA500, 0xFEFFA9B6, 0xFF01AE6C, 0xFF03B322, 0xFF05B7D8, 0xFF07BC8E, 0xFF09C144, 0xFF0BC5FA, - 0xFF0DCAB0, 0xFF0FCF66, 0xFF11D41C, 0xFF13D8D2, 0xFF15DD88, 0xFF17E23E, 0xFF19E6F4, 0xFF1BEBAA, - 0xFF1DF060, 0xFF1FF516, 0xFF21F9CC, 0xFF23FE82, 0xFF260338, 0xFF2807EE, 0xFF2A0CA4, 0xFF2C115A, - 0xFF2E1610, 0xFF301AC6, 0xFF321F7C, 0xFF342432, 0xFF3628E8, 0xFF382D9E, 0xFF3A3254, 0xFF3C370A, - 0xFF3E3BC0, 0xFF404076, 0xFF42452C, 0xFF4449E2, 0xFF464E98, 0xFF48534E, 0xFF4A5804, 0xFF4C5CBA, - 0xFF4E6170, 0xFF506626, 0xFF526ADC, 0xFF546F92, 0xFF567448, 0xFF5878FE, 0xFF5A7DB4, 0xFF5C826A, - 0xFF5E8720, 0xFF608BD6, 0xFF62908C, 0xFF649542, 0xFF6699F8, 0xFF689EAE, 0xFF6AA364, 0xFF6CA81A, - 0xFF6EACD0, 0xFF70B186, 0xFF72B63C, 0xFF74BAF2, 0xFF76BFA8, 0xFF78C45E, 0xFF7AC914, 0xFF7CCDCA, - 0xFF7ED280, 0xFF80D736, 0xFF82DBEC, 0xFF84E0A2, 0xFF86E558, 0xFF88EA0E, 0xFF8AEEC4, 0xFF8CF37A, - 0xFF8EF830, 0xFF90FCE6, 0xFF93019C, 0xFF950652, 0xFF970B08, 0xFF990FBE, 0xFF9B1474, 0xFF9D192A, - 0xFF9F1DE0, 0xFFA12296, 0xFFA3274C, 0xFFA52C02, 0xFFA730B8, 0xFFA9356E, 0xFFAB3A24, 0xFFAD3EDA, - 0xFFAF4390, 0xFFB14846, 0xFFB34CFC, 0xFFB551B2, 0xFFB75668, 0xFFB95B1E, 0xFFBB5FD4, 0xFFBD648A, - 0xFFBF6940, 0xFFC16DF6, 0xFFC372AC, 0xFFC57762, 0xFFC77C18, 0xFFC980CE, 0xFFCB8584, 0xFFCD8A3A, - 0xFFCF8EF0, 0xFFD193A6, 0xFFD3985C, 0xFFD59D12, 0xFFD7A1C8, 0xFFD9A67E, 0xFFDBAB34, 0xFFDDAFEA, - 0xFFDFB4A0, 0xFFE1B956, 0xFFE3BE0C, 0xFFE5C2C2, 0xFFE7C778, 0xFFE9CC2E, 0xFFEBD0E4, 0xFFEDD59A, - 0xFFEFDA50, 0xFFF1DF06, 0xFFF3E3BC, 0xFFF5E872, 0xFFF7ED28, 0xFFF9F1DE, 0xFFFBF694, 0xFFFDFB4A, - 0x00000000, 0x000204B6, 0x0004096C, 0x00060E22, 0x000812D8, 0x000A178E, 0x000C1C44, 0x000E20FA, - 0x001025B0, 0x00122A66, 0x00142F1C, 0x001633D2, 0x00183888, 0x001A3D3E, 0x001C41F4, 0x001E46AA, - 0x00204B60, 0x00225016, 0x002454CC, 0x00265982, 0x00285E38, 0x002A62EE, 0x002C67A4, 0x002E6C5A, - 0x00307110, 0x003275C6, 0x00347A7C, 0x00367F32, 0x003883E8, 0x003A889E, 0x003C8D54, 0x003E920A, - 0x004096C0, 0x00429B76, 0x0044A02C, 0x0046A4E2, 0x0048A998, 0x004AAE4E, 0x004CB304, 0x004EB7BA, - 0x0050BC70, 0x0052C126, 0x0054C5DC, 0x0056CA92, 0x0058CF48, 0x005AD3FE, 0x005CD8B4, 0x005EDD6A, - 0x0060E220, 0x0062E6D6, 0x0064EB8C, 0x0066F042, 0x0068F4F8, 0x006AF9AE, 0x006CFE64, 0x006F031A, - 0x007107D0, 0x00730C86, 0x0075113C, 0x007715F2, 0x00791AA8, 0x007B1F5E, 0x007D2414, 0x007F28CA, - 0x00812D80, 0x00833236, 0x008536EC, 0x00873BA2, 0x00894058, 0x008B450E, 0x008D49C4, 0x008F4E7A, - 0x00915330, 0x009357E6, 0x00955C9C, 0x00976152, 0x00996608, 0x009B6ABE, 0x009D6F74, 0x009F742A, - 0x00A178E0, 0x00A37D96, 0x00A5824C, 0x00A78702, 0x00A98BB8, 0x00AB906E, 0x00AD9524, 0x00AF99DA, - 0x00B19E90, 0x00B3A346, 0x00B5A7FC, 0x00B7ACB2, 0x00B9B168, 0x00BBB61E, 0x00BDBAD4, 0x00BFBF8A, - 0x00C1C440, 0x00C3C8F6, 0x00C5CDAC, 0x00C7D262, 0x00C9D718, 0x00CBDBCE, 0x00CDE084, 0x00CFE53A, - 0x00D1E9F0, 0x00D3EEA6, 0x00D5F35C, 0x00D7F812, 0x00D9FCC8, 0x00DC017E, 0x00DE0634, 0x00E00AEA, - 0x00E20FA0, 0x00E41456, 0x00E6190C, 0x00E81DC2, 0x00EA2278, 0x00EC272E, 0x00EE2BE4, 0x00F0309A, - 0x00F23550, 0x00F43A06, 0x00F63EBC, 0x00F84372, 0x00FA4828, 0x00FC4CDE, 0x00FE5194, 0x00100564A -}; -static const uint32_t yuv2rgbtable_gu[256] = { - 0xFFCDD300, 0xFFCE375A, 0xFFCE9BB4, 0xFFCF000E, 0xFFCF6468, 0xFFCFC8C2, 0xFFD02D1C, 0xFFD09176, - 0xFFD0F5D0, 0xFFD15A2A, 0xFFD1BE84, 0xFFD222DE, 0xFFD28738, 0xFFD2EB92, 0xFFD34FEC, 0xFFD3B446, - 0xFFD418A0, 0xFFD47CFA, 0xFFD4E154, 0xFFD545AE, 0xFFD5AA08, 0xFFD60E62, 0xFFD672BC, 0xFFD6D716, - 0xFFD73B70, 0xFFD79FCA, 0xFFD80424, 0xFFD8687E, 0xFFD8CCD8, 0xFFD93132, 0xFFD9958C, 0xFFD9F9E6, - 0xFFDA5E40, 0xFFDAC29A, 0xFFDB26F4, 0xFFDB8B4E, 0xFFDBEFA8, 0xFFDC5402, 0xFFDCB85C, 0xFFDD1CB6, - 0xFFDD8110, 0xFFDDE56A, 0xFFDE49C4, 0xFFDEAE1E, 0xFFDF1278, 0xFFDF76D2, 0xFFDFDB2C, 0xFFE03F86, - 0xFFE0A3E0, 0xFFE1083A, 0xFFE16C94, 0xFFE1D0EE, 0xFFE23548, 0xFFE299A2, 0xFFE2FDFC, 0xFFE36256, - 0xFFE3C6B0, 0xFFE42B0A, 0xFFE48F64, 0xFFE4F3BE, 0xFFE55818, 0xFFE5BC72, 0xFFE620CC, 0xFFE68526, - 0xFFE6E980, 0xFFE74DDA, 0xFFE7B234, 0xFFE8168E, 0xFFE87AE8, 0xFFE8DF42, 0xFFE9439C, 0xFFE9A7F6, - 0xFFEA0C50, 0xFFEA70AA, 0xFFEAD504, 0xFFEB395E, 0xFFEB9DB8, 0xFFEC0212, 0xFFEC666C, 0xFFECCAC6, - 0xFFED2F20, 0xFFED937A, 0xFFEDF7D4, 0xFFEE5C2E, 0xFFEEC088, 0xFFEF24E2, 0xFFEF893C, 0xFFEFED96, - 0xFFF051F0, 0xFFF0B64A, 0xFFF11AA4, 0xFFF17EFE, 0xFFF1E358, 0xFFF247B2, 0xFFF2AC0C, 0xFFF31066, - 0xFFF374C0, 0xFFF3D91A, 0xFFF43D74, 0xFFF4A1CE, 0xFFF50628, 0xFFF56A82, 0xFFF5CEDC, 0xFFF63336, - 0xFFF69790, 0xFFF6FBEA, 0xFFF76044, 0xFFF7C49E, 0xFFF828F8, 0xFFF88D52, 0xFFF8F1AC, 0xFFF95606, - 0xFFF9BA60, 0xFFFA1EBA, 0xFFFA8314, 0xFFFAE76E, 0xFFFB4BC8, 0xFFFBB022, 0xFFFC147C, 0xFFFC78D6, - 0xFFFCDD30, 0xFFFD418A, 0xFFFDA5E4, 0xFFFE0A3E, 0xFFFE6E98, 0xFFFED2F2, 0xFFFF374C, 0xFFFF9BA6, - 0x00000000, 0x0000645A, 0x0000C8B4, 0x00012D0E, 0x00019168, 0x0001F5C2, 0x00025A1C, 0x0002BE76, - 0x000322D0, 0x0003872A, 0x0003EB84, 0x00044FDE, 0x0004B438, 0x00051892, 0x00057CEC, 0x0005E146, - 0x000645A0, 0x0006A9FA, 0x00070E54, 0x000772AE, 0x0007D708, 0x00083B62, 0x00089FBC, 0x00090416, - 0x00096870, 0x0009CCCA, 0x000A3124, 0x000A957E, 0x000AF9D8, 0x000B5E32, 0x000BC28C, 0x000C26E6, - 0x000C8B40, 0x000CEF9A, 0x000D53F4, 0x000DB84E, 0x000E1CA8, 0x000E8102, 0x000EE55C, 0x000F49B6, - 0x000FAE10, 0x0010126A, 0x001076C4, 0x0010DB1E, 0x00113F78, 0x0011A3D2, 0x0012082C, 0x00126C86, - 0x0012D0E0, 0x0013353A, 0x00139994, 0x0013FDEE, 0x00146248, 0x0014C6A2, 0x00152AFC, 0x00158F56, - 0x0015F3B0, 0x0016580A, 0x0016BC64, 0x001720BE, 0x00178518, 0x0017E972, 0x00184DCC, 0x0018B226, - 0x00191680, 0x00197ADA, 0x0019DF34, 0x001A438E, 0x001AA7E8, 0x001B0C42, 0x001B709C, 0x001BD4F6, - 0x001C3950, 0x001C9DAA, 0x001D0204, 0x001D665E, 0x001DCAB8, 0x001E2F12, 0x001E936C, 0x001EF7C6, - 0x001F5C20, 0x001FC07A, 0x002024D4, 0x0020892E, 0x0020ED88, 0x002151E2, 0x0021B63C, 0x00221A96, - 0x00227EF0, 0x0022E34A, 0x002347A4, 0x0023ABFE, 0x00241058, 0x002474B2, 0x0024D90C, 0x00253D66, - 0x0025A1C0, 0x0026061A, 0x00266A74, 0x0026CECE, 0x00273328, 0x00279782, 0x0027FBDC, 0x00286036, - 0x0028C490, 0x002928EA, 0x00298D44, 0x0029F19E, 0x002A55F8, 0x002ABA52, 0x002B1EAC, 0x002B8306, - 0x002BE760, 0x002C4BBA, 0x002CB014, 0x002D146E, 0x002D78C8, 0x002DDD22, 0x002E417C, 0x002EA5D6, - 0x002F0A30, 0x002F6E8A, 0x002FD2E4, 0x0030373E, 0x00309B98, 0x0030FFF2, 0x0031644C, 0x0031C8A6 -}; -static const uint32_t yuv2rgbtable_gv[256] = { - 0xFF97E900, 0xFF98B92E, 0xFF99895C, 0xFF9A598A, 0xFF9B29B8, 0xFF9BF9E6, 0xFF9CCA14, 0xFF9D9A42, - 0xFF9E6A70, 0xFF9F3A9E, 0xFFA00ACC, 0xFFA0DAFA, 0xFFA1AB28, 0xFFA27B56, 0xFFA34B84, 0xFFA41BB2, - 0xFFA4EBE0, 0xFFA5BC0E, 0xFFA68C3C, 0xFFA75C6A, 0xFFA82C98, 0xFFA8FCC6, 0xFFA9CCF4, 0xFFAA9D22, - 0xFFAB6D50, 0xFFAC3D7E, 0xFFAD0DAC, 0xFFADDDDA, 0xFFAEAE08, 0xFFAF7E36, 0xFFB04E64, 0xFFB11E92, - 0xFFB1EEC0, 0xFFB2BEEE, 0xFFB38F1C, 0xFFB45F4A, 0xFFB52F78, 0xFFB5FFA6, 0xFFB6CFD4, 0xFFB7A002, - 0xFFB87030, 0xFFB9405E, 0xFFBA108C, 0xFFBAE0BA, 0xFFBBB0E8, 0xFFBC8116, 0xFFBD5144, 0xFFBE2172, - 0xFFBEF1A0, 0xFFBFC1CE, 0xFFC091FC, 0xFFC1622A, 0xFFC23258, 0xFFC30286, 0xFFC3D2B4, 0xFFC4A2E2, - 0xFFC57310, 0xFFC6433E, 0xFFC7136C, 0xFFC7E39A, 0xFFC8B3C8, 0xFFC983F6, 0xFFCA5424, 0xFFCB2452, - 0xFFCBF480, 0xFFCCC4AE, 0xFFCD94DC, 0xFFCE650A, 0xFFCF3538, 0xFFD00566, 0xFFD0D594, 0xFFD1A5C2, - 0xFFD275F0, 0xFFD3461E, 0xFFD4164C, 0xFFD4E67A, 0xFFD5B6A8, 0xFFD686D6, 0xFFD75704, 0xFFD82732, - 0xFFD8F760, 0xFFD9C78E, 0xFFDA97BC, 0xFFDB67EA, 0xFFDC3818, 0xFFDD0846, 0xFFDDD874, 0xFFDEA8A2, - 0xFFDF78D0, 0xFFE048FE, 0xFFE1192C, 0xFFE1E95A, 0xFFE2B988, 0xFFE389B6, 0xFFE459E4, 0xFFE52A12, - 0xFFE5FA40, 0xFFE6CA6E, 0xFFE79A9C, 0xFFE86ACA, 0xFFE93AF8, 0xFFEA0B26, 0xFFEADB54, 0xFFEBAB82, - 0xFFEC7BB0, 0xFFED4BDE, 0xFFEE1C0C, 0xFFEEEC3A, 0xFFEFBC68, 0xFFF08C96, 0xFFF15CC4, 0xFFF22CF2, - 0xFFF2FD20, 0xFFF3CD4E, 0xFFF49D7C, 0xFFF56DAA, 0xFFF63DD8, 0xFFF70E06, 0xFFF7DE34, 0xFFF8AE62, - 0xFFF97E90, 0xFFFA4EBE, 0xFFFB1EEC, 0xFFFBEF1A, 0xFFFCBF48, 0xFFFD8F76, 0xFFFE5FA4, 0xFFFF2FD2, - 0x00000000, 0x0000D02E, 0x0001A05C, 0x0002708A, 0x000340B8, 0x000410E6, 0x0004E114, 0x0005B142, - 0x00068170, 0x0007519E, 0x000821CC, 0x0008F1FA, 0x0009C228, 0x000A9256, 0x000B6284, 0x000C32B2, - 0x000D02E0, 0x000DD30E, 0x000EA33C, 0x000F736A, 0x00104398, 0x001113C6, 0x0011E3F4, 0x0012B422, - 0x00138450, 0x0014547E, 0x001524AC, 0x0015F4DA, 0x0016C508, 0x00179536, 0x00186564, 0x00193592, - 0x001A05C0, 0x001AD5EE, 0x001BA61C, 0x001C764A, 0x001D4678, 0x001E16A6, 0x001EE6D4, 0x001FB702, - 0x00208730, 0x0021575E, 0x0022278C, 0x0022F7BA, 0x0023C7E8, 0x00249816, 0x00256844, 0x00263872, - 0x002708A0, 0x0027D8CE, 0x0028A8FC, 0x0029792A, 0x002A4958, 0x002B1986, 0x002BE9B4, 0x002CB9E2, - 0x002D8A10, 0x002E5A3E, 0x002F2A6C, 0x002FFA9A, 0x0030CAC8, 0x00319AF6, 0x00326B24, 0x00333B52, - 0x00340B80, 0x0034DBAE, 0x0035ABDC, 0x00367C0A, 0x00374C38, 0x00381C66, 0x0038EC94, 0x0039BCC2, - 0x003A8CF0, 0x003B5D1E, 0x003C2D4C, 0x003CFD7A, 0x003DCDA8, 0x003E9DD6, 0x003F6E04, 0x00403E32, - 0x00410E60, 0x0041DE8E, 0x0042AEBC, 0x00437EEA, 0x00444F18, 0x00451F46, 0x0045EF74, 0x0046BFA2, - 0x00478FD0, 0x00485FFE, 0x0049302C, 0x004A005A, 0x004AD088, 0x004BA0B6, 0x004C70E4, 0x004D4112, - 0x004E1140, 0x004EE16E, 0x004FB19C, 0x005081CA, 0x005151F8, 0x00522226, 0x0052F254, 0x0053C282, - 0x005492B0, 0x005562DE, 0x0056330C, 0x0057033A, 0x0057D368, 0x0058A396, 0x005973C4, 0x005A43F2, - 0x005B1420, 0x005BE44E, 0x005CB47C, 0x005D84AA, 0x005E54D8, 0x005F2506, 0x005FF534, 0x0060C562, - 0x00619590, 0x006265BE, 0x006335EC, 0x0064061A, 0x0064D648, 0x0065A676, 0x006676A4, 0x006746D2 -}; -static const uint32_t yuv2rgbtable_bv[256] = { - 0xFF33A280, 0xFF353B3B, 0xFF36D3F6, 0xFF386CB1, 0xFF3A056C, 0xFF3B9E27, 0xFF3D36E2, 0xFF3ECF9D, - 0xFF406858, 0xFF420113, 0xFF4399CE, 0xFF453289, 0xFF46CB44, 0xFF4863FF, 0xFF49FCBA, 0xFF4B9575, - 0xFF4D2E30, 0xFF4EC6EB, 0xFF505FA6, 0xFF51F861, 0xFF53911C, 0xFF5529D7, 0xFF56C292, 0xFF585B4D, - 0xFF59F408, 0xFF5B8CC3, 0xFF5D257E, 0xFF5EBE39, 0xFF6056F4, 0xFF61EFAF, 0xFF63886A, 0xFF652125, - 0xFF66B9E0, 0xFF68529B, 0xFF69EB56, 0xFF6B8411, 0xFF6D1CCC, 0xFF6EB587, 0xFF704E42, 0xFF71E6FD, - 0xFF737FB8, 0xFF751873, 0xFF76B12E, 0xFF7849E9, 0xFF79E2A4, 0xFF7B7B5F, 0xFF7D141A, 0xFF7EACD5, - 0xFF804590, 0xFF81DE4B, 0xFF837706, 0xFF850FC1, 0xFF86A87C, 0xFF884137, 0xFF89D9F2, 0xFF8B72AD, - 0xFF8D0B68, 0xFF8EA423, 0xFF903CDE, 0xFF91D599, 0xFF936E54, 0xFF95070F, 0xFF969FCA, 0xFF983885, - 0xFF99D140, 0xFF9B69FB, 0xFF9D02B6, 0xFF9E9B71, 0xFFA0342C, 0xFFA1CCE7, 0xFFA365A2, 0xFFA4FE5D, - 0xFFA69718, 0xFFA82FD3, 0xFFA9C88E, 0xFFAB6149, 0xFFACFA04, 0xFFAE92BF, 0xFFB02B7A, 0xFFB1C435, - 0xFFB35CF0, 0xFFB4F5AB, 0xFFB68E66, 0xFFB82721, 0xFFB9BFDC, 0xFFBB5897, 0xFFBCF152, 0xFFBE8A0D, - 0xFFC022C8, 0xFFC1BB83, 0xFFC3543E, 0xFFC4ECF9, 0xFFC685B4, 0xFFC81E6F, 0xFFC9B72A, 0xFFCB4FE5, - 0xFFCCE8A0, 0xFFCE815B, 0xFFD01A16, 0xFFD1B2D1, 0xFFD34B8C, 0xFFD4E447, 0xFFD67D02, 0xFFD815BD, - 0xFFD9AE78, 0xFFDB4733, 0xFFDCDFEE, 0xFFDE78A9, 0xFFE01164, 0xFFE1AA1F, 0xFFE342DA, 0xFFE4DB95, - 0xFFE67450, 0xFFE80D0B, 0xFFE9A5C6, 0xFFEB3E81, 0xFFECD73C, 0xFFEE6FF7, 0xFFF008B2, 0xFFF1A16D, - 0xFFF33A28, 0xFFF4D2E3, 0xFFF66B9E, 0xFFF80459, 0xFFF99D14, 0xFFFB35CF, 0xFFFCCE8A, 0xFFFE6745, - 0x00000000, 0x000198BB, 0x00033176, 0x0004CA31, 0x000662EC, 0x0007FBA7, 0x00099462, 0x000B2D1D, - 0x000CC5D8, 0x000E5E93, 0x000FF74E, 0x00119009, 0x001328C4, 0x0014C17F, 0x00165A3A, 0x0017F2F5, - 0x00198BB0, 0x001B246B, 0x001CBD26, 0x001E55E1, 0x001FEE9C, 0x00218757, 0x00232012, 0x0024B8CD, - 0x00265188, 0x0027EA43, 0x002982FE, 0x002B1BB9, 0x002CB474, 0x002E4D2F, 0x002FE5EA, 0x00317EA5, - 0x00331760, 0x0034B01B, 0x003648D6, 0x0037E191, 0x00397A4C, 0x003B1307, 0x003CABC2, 0x003E447D, - 0x003FDD38, 0x004175F3, 0x00430EAE, 0x0044A769, 0x00464024, 0x0047D8DF, 0x0049719A, 0x004B0A55, - 0x004CA310, 0x004E3BCB, 0x004FD486, 0x00516D41, 0x005305FC, 0x00549EB7, 0x00563772, 0x0057D02D, - 0x005968E8, 0x005B01A3, 0x005C9A5E, 0x005E3319, 0x005FCBD4, 0x0061648F, 0x0062FD4A, 0x00649605, - 0x00662EC0, 0x0067C77B, 0x00696036, 0x006AF8F1, 0x006C91AC, 0x006E2A67, 0x006FC322, 0x00715BDD, - 0x0072F498, 0x00748D53, 0x0076260E, 0x0077BEC9, 0x00795784, 0x007AF03F, 0x007C88FA, 0x007E21B5, - 0x007FBA70, 0x0081532B, 0x0082EBE6, 0x008484A1, 0x00861D5C, 0x0087B617, 0x00894ED2, 0x008AE78D, - 0x008C8048, 0x008E1903, 0x008FB1BE, 0x00914A79, 0x0092E334, 0x00947BEF, 0x009614AA, 0x0097AD65, - 0x00994620, 0x009ADEDB, 0x009C7796, 0x009E1051, 0x009FA90C, 0x00A141C7, 0x00A2DA82, 0x00A4733D, - 0x00A60BF8, 0x00A7A4B3, 0x00A93D6E, 0x00AAD629, 0x00AC6EE4, 0x00AE079F, 0x00AFA05A, 0x00B13915, - 0x00B2D1D0, 0x00B46A8B, 0x00B60346, 0x00B79C01, 0x00B934BC, 0x00BACD77, 0x00BC6632, 0x00BDFEED, - 0x00BF97A8, 0x00C13063, 0x00C2C91E, 0x00C461D9, 0x00C5FA94, 0x00C7934F, 0x00C92C0A, 0x00CAC4C5 -}; - -#define OUT(x) \ - out[OUTITER] = (uint8_t)*(decode_surface + x)&0xFF; \ - OUTITER += OUTINC; - -#define OUT4(x) \ - OUT(x + 0x03); \ - OUT(x + 0x02); \ - OUT(x + 0x01); \ - OUT(x + 0x00); - -#define OUT8(x) \ - OUT4(x + 0x04); \ - OUT4(x + 0x00); - -#define OUT_LU_16A(x) \ - OUT8(x); \ - OUT8(x + 0x40); - -#define OUT_CH_8A(x) \ - OUT4(x); \ - OUT4(x + 0x20); - -//pppppppppppppppp -//x: macroblock address -//l: line 0-15 -#define OUT_LU_16(x,l) \ - OUT_LU_16A(x + (l/4) * 0x10 + (l%2) * 0x80 + ((l/2)%2?0x00:0x08)); - -//pppppppp -//x: macroblock address -//l: line 0-7 -//b: 0=cr 1=cb -#define OUT_CH_8(x,l,b) \ - OUT_CH_8A(x + (l/4) * 0x10 + (l%2) * 0x40 + ((l/2)%2?0x00:0x08) + (b?0x04:0x00)); - -//---- -#define CLAMP(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x)) -#define SWAP(x,y) { x ^= y; y ^= x; x ^= y; } - /* TODO: aspect ratio correction and PIP */ bool cVideo::GetScreenImage(unsigned char * &video, int &xres, int &yres, bool get_video, bool get_osd, bool scale_to_video) { - lt_info("%s: get_video: %d get_osd: %d scale_to_video: %d\n", - __func__, get_video, get_osd, scale_to_video); + lt_info("%s: video 0x%p xres %d yres %d vid %d osd %d scale %d\n", + __func__, video, xres, yres, get_video, get_osd, scale_to_video); + return true; } diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index e172cb9..536ee15 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -200,7 +200,6 @@ class cVideo void Standby(unsigned int bOn); void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600, int startx = 0, int starty = 0, int endx = 1279, int endy = 719); void SetControl(int, int); - void VideoParamWatchdog(void); void setContrast(int val); void SetVideoMode(analog_mode_t mode); void SetDBDR(int) { return; }; From baf540d79fde5410020fe01c3f4a80367ec5ab6d Mon Sep 17 00:00:00 2001 From: max_10 Date: Tue, 26 Sep 2017 14:15:14 +0200 Subject: [PATCH 22/73] libarmbox: del libass LDFLAGS --- libarmbox/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libarmbox/Makefile.am b/libarmbox/Makefile.am index e3218f7..fb81b20 100644 --- a/libarmbox/Makefile.am +++ b/libarmbox/Makefile.am @@ -13,7 +13,7 @@ AM_LDFLAGS = \ @AVUTIL_LIBS@ \ @AVCODEC_LIBS@ \ @SWRESAMPLE_LIBS@ \ - -lpthread -lasound -lass -lrt \ + -lpthread -lasound -lrt \ -lgstreamer-1.0 libarmbox_la_SOURCES = \ From b21afd56b186def21161462bb8115c7bda32ff08 Mon Sep 17 00:00:00 2001 From: max_10 Date: Tue, 26 Sep 2017 14:16:42 +0200 Subject: [PATCH 23/73] libarmbox: adjustments --- libarmbox/video.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index d87e69c..e17d01c 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -786,19 +786,19 @@ void cVideo::SetControl(int control, int value) { switch (control) { case VIDEO_CONTROL_BRIGHTNESS: brightness = value; - p = "/proc/stb/video/plane/psi_brightness"; + p = "/proc/stb/vmpeg/0/pep_brightness"; break; case VIDEO_CONTROL_CONTRAST: contrast = value; - p = "/proc/stb/video/plane/psi_contrast"; + p = "/proc/stb/vmpeg/0/pep_contrast"; break; case VIDEO_CONTROL_SATURATION: saturation = value; - p = "/proc/stb/video/plane/psi_saturation"; + p = "/proc/stb/vmpeg/0/pep_saturation"; break; case VIDEO_CONTROL_HUE: hue = value; - p = "/proc/stb/video/plane/psi_tint"; + p = "/proc/stb/vmpeg/0/pep_hue"; break; } if (p) { @@ -835,7 +835,7 @@ void cVideo::SetColorFormat(COLOR_FORMAT color_format) { break; } if (p) - proc_put("/proc/stb/avs/0/colorformat", p, strlen(p)); + proc_put("/proc/stb/video/hdmi_colorspace", p, strlen(p)); } /* TODO: aspect ratio correction and PIP */ From 57ae0340c839ce142f68f0109602a9abaa6488cd Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 1 Oct 2017 11:56:28 +0200 Subject: [PATCH 24/73] adding 4k video settings for armbox --- libarmbox/video.cpp | 4 ++++ libarmbox/video_lib.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index f62a525..b5bfe38 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -394,6 +394,10 @@ int cVideo::SetVideoSystem(int video_system, bool remember) "1080p60", // VIDEO_STD_1080P60 "1080p2397", // VIDEO_STD_1080P2397 "1080p2997", // VIDEO_STD_1080P2997 + "2160p24", //VIDEO_STD_2160P24 + "2160p25", // VIDEO_STD_2160P25 + "2160p30", // VIDEO_STD_2160P30 + "2160p50", // VIDEO_STD_2160P50 "720p50" // VIDEO_STD_AUTO }; diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index e172cb9..7c40cb1 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -105,6 +105,10 @@ typedef enum { VIDEO_STD_1080P60, VIDEO_STD_1080P2397, VIDEO_STD_1080P2997, + VIDEO_STD_2160P24, + VIDEO_STD_2160P25, + VIDEO_STD_2160P30, + VIDEO_STD_2160P50, VIDEO_STD_AUTO, VIDEO_STD_MAX = VIDEO_STD_AUTO } VIDEO_STD; From e5547c17ed834a80124061f59d40ba7792c06084 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 1 Oct 2017 12:00:48 +0200 Subject: [PATCH 25/73] fix generic compile --- generic-pc/playback.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/generic-pc/playback.cpp b/generic-pc/playback.cpp index 86b6b6f..87dfbee 100644 --- a/generic-pc/playback.cpp +++ b/generic-pc/playback.cpp @@ -145,8 +145,3 @@ cPlayback::~cPlayback() { printf("%s:%s\n", FILENAME, __func__); } - -uint64_t cPlayback::GetReadCount() -{ - return 0; -} From 3ece63839e3cafd5234fde0f81935e27a786c0d5 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 1 Oct 2017 11:56:28 +0200 Subject: [PATCH 26/73] adding 4k video settings for armbox --- libarmbox/video.cpp | 4 ++++ libarmbox/video_lib.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index e17d01c..9ee3c0e 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -394,6 +394,10 @@ int cVideo::SetVideoSystem(int video_system, bool remember) "1080p60", // VIDEO_STD_1080P60 "1080p2397", // VIDEO_STD_1080P2397 "1080p2997", // VIDEO_STD_1080P2997 + "2160p24", //VIDEO_STD_2160P24 + "2160p25", // VIDEO_STD_2160P25 + "2160p30", // VIDEO_STD_2160P30 + "2160p50", // VIDEO_STD_2160P50 "720p50" // VIDEO_STD_AUTO }; diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index 536ee15..6f9af5f 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -105,6 +105,10 @@ typedef enum { VIDEO_STD_1080P60, VIDEO_STD_1080P2397, VIDEO_STD_1080P2997, + VIDEO_STD_2160P24, + VIDEO_STD_2160P25, + VIDEO_STD_2160P30, + VIDEO_STD_2160P50, VIDEO_STD_AUTO, VIDEO_STD_MAX = VIDEO_STD_AUTO } VIDEO_STD; From 63c02d0f24f96f47df18687333603a921efc3c47 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Thu, 5 Oct 2017 15:23:39 +0200 Subject: [PATCH 27/73] fix armbox realname --- libarmbox/hardware_caps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libarmbox/hardware_caps.c b/libarmbox/hardware_caps.c index 3041216..5ce19c4 100644 --- a/libarmbox/hardware_caps.c +++ b/libarmbox/hardware_caps.c @@ -36,8 +36,8 @@ hw_caps_t *get_hwcaps(void) caps.display_type = HW_DISPLAY_LINE_TEXT; caps.can_set_display_brightness = 1; caps.has_HDMI = 1; - strcpy(caps.boxvendor, "armbox"); - strcpy(caps.boxname, "armbox"); - strcpy(caps.boxarch,caps.boxname); + strcpy(caps.boxvendor, "AX-Technologies"); + strcpy(caps.boxname, "HD51"); + strcpy(caps.boxarch, "BCM7251S"); return ∩︀ } From cb74eae85bf4fa313605facd501db4018cc3101c Mon Sep 17 00:00:00 2001 From: TangoCash Date: Thu, 5 Oct 2017 15:26:25 +0200 Subject: [PATCH 28/73] fix audio/video devices --- libarmbox/audio.cpp | 12 +++++------- libarmbox/video.cpp | 6 +++++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/libarmbox/audio.cpp b/libarmbox/audio.cpp index 7a55814..9e5960b 100644 --- a/libarmbox/audio.cpp +++ b/libarmbox/audio.cpp @@ -58,7 +58,7 @@ void cAudio::openDevice(void) if (fd < 0) { - if ((fd = open(AUDIO_DEVICE, O_RDWR)) < 0) + if ((fd = open(AUDIO_DEVICE, O_RDWR | O_NONBLOCK)) < 0) lt_info("openDevice: open failed (%m)\n"); fcntl(fd, F_SETFD, FD_CLOEXEC); do_mute(true, false); @@ -397,9 +397,7 @@ void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int void cAudio::SetHdmiDD(bool enable) { - const char *opt[] = { "pcm", "spdif" }; - lt_debug("%s %d\n", __func__, enable); - proc_put("/proc/stb/hdmi/audio_source", opt[enable], strlen(opt[enable])); + lt_debug("%s\n", __FUNCTION__); } void cAudio::SetSpdifDD(bool enable) @@ -422,9 +420,9 @@ void cAudio::EnableAnalogOut(bool enable) #define AUDIO_BYPASS_OFF 1 void cAudio::setBypassMode(bool disable) { - const char *opt[] = { "passthrough", "downmix" }; - lt_debug("%s %d\n", __func__, disable); - proc_put("/proc/stb/audio/ac3", opt[disable], strlen(opt[disable])); + int mode = disable ? AUDIO_BYPASS_OFF : AUDIO_BYPASS_ON; + if (ioctl(fd, AUDIO_SET_BYPASS_MODE, mode) < 0) + lt_info("%s AUDIO_SET_BYPASS_MODE %d: %m\n", __func__, mode); } void cAudio::openMixers(void) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index b5bfe38..a9a84bf 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -200,7 +200,7 @@ void cVideo::openDevice(void) if (fd != -1) /* already open */ return; retry: - if ((fd = open(VDEV[devnum], O_RDWR|O_CLOEXEC)) < 0) + if ((fd = open(VDEV[devnum], O_RDWR|O_CLOEXEC|O_NONBLOCK)) < 0) { if (errno == EBUSY) { @@ -359,6 +359,10 @@ int cVideo::GetVideoSystem() "1080p60", // VIDEO_STD_1080P60 "1080p2397", // VIDEO_STD_1080P2397 "1080p2997", // VIDEO_STD_1080P2997 + "2160p24", //VIDEO_STD_2160P24 + "2160p25", // VIDEO_STD_2160P25 + "2160p30", // VIDEO_STD_2160P30 + "2160p50", // VIDEO_STD_2160P50 "720p50" // VIDEO_STD_AUTO }; From 36e2ff6d68173c75697f44b7e2be13b1a6d1629e Mon Sep 17 00:00:00 2001 From: TangoCash Date: Thu, 5 Oct 2017 15:27:01 +0200 Subject: [PATCH 29/73] re-arrange gstreamer code --- libarmbox/playback_gst.cpp | 48 ++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index 790b1c0..5e34d5c 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -196,6 +196,8 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) case GST_STATE_CHANGE_READY_TO_PAUSED: { GstIterator *children; + GValue r = { 0, }; + if (audioSink) { gst_object_unref(GST_OBJECT(audioSink)); @@ -208,13 +210,23 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) videoSink = NULL; } children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); - GValue r = G_VALUE_INIT; - gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink"); - audioSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); - g_value_unset (&r); - gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink"); - videoSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); - g_value_unset (&r); + + if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink")) + { + audioSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); + g_value_unset (&r); + lt_info_c( "%s %s - audio sink created\n", FILENAME, __FUNCTION__); + } + + gst_iterator_free(children); + children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); + + if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink")) + { + videoSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); + g_value_unset (&r); + lt_info_c( "%s %s - video sink created\n", FILENAME, __FUNCTION__); + } gst_iterator_free(children); } break; @@ -395,6 +407,9 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, guint flags = GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | \ GST_PLAY_FLAG_TEXT | GST_PLAY_FLAG_NATIVE_VIDEO; + /* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */ + int m_buffer_size = 5*1024*1024; + // create gst pipeline m_gst_playbin = gst_element_factory_make ("playbin", "playbin"); @@ -402,8 +417,17 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, { lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__); - g_object_set(G_OBJECT (m_gst_playbin), "uri", uri, NULL); + if(isHTTP) + { + // set buffer size + g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL); + g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL); + flags |= GST_PLAY_FLAG_BUFFERING; + } + g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL); + + g_object_set(G_OBJECT (m_gst_playbin), "uri", uri, NULL); //gstbus handler GstBus * bus = gst_pipeline_get_bus( GST_PIPELINE(m_gst_playbin) ); @@ -411,7 +435,7 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, gst_object_unref(bus); // state playing - gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING); playing = true; playstate = STATE_PLAY; @@ -425,12 +449,6 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, } g_free(uri); - - // set buffer size - /* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */ - int m_buffer_size = 5*1024*1024; - //g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL); - g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL); return true; } From 6367dfc13fdc7dba1e7fed4aabec96f731acea40 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Fri, 6 Oct 2017 21:57:04 +0200 Subject: [PATCH 30/73] armbox: make open/close device public --- libarmbox/audio_lib.h | 6 +++--- libarmbox/video_lib.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libarmbox/audio_lib.h b/libarmbox/audio_lib.h index b2b78d6..8a71732 100644 --- a/libarmbox/audio_lib.h +++ b/libarmbox/audio_lib.h @@ -54,9 +54,6 @@ class cAudio int volume; - void openDevice(void); - void closeDevice(void); - int do_mute(bool enable, bool remember); void setBypassMode(bool disable); @@ -69,6 +66,9 @@ class cAudio cAudio(void *, void *, void *); ~cAudio(void); + void openDevice(void); + void closeDevice(void); + void *GetHandle() { return NULL; }; /* shut up */ int mute(bool remember = true) { return do_mute(true, remember); }; diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index 7c40cb1..9837571 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -158,14 +158,14 @@ class cVideo int64_t GetPTS(void); int brightness, contrast, saturation, hue; - - void openDevice(void); - void closeDevice(void); public: /* constructor & destructor */ cVideo(int mode, void *, void *, unsigned int unit = 0); ~cVideo(void); + void openDevice(void); + void closeDevice(void); + void * GetTVEnc() { return NULL; }; void * GetTVEncSD() { return NULL; }; From 0d30ab013eb38ec520706621e73e1ece7f319686 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 2 Nov 2013 20:24:56 +0100 Subject: [PATCH 31/73] spark: use proc_tools --- libspark/audio.cpp | 24 ++++++------------------ libspark/video.cpp | 43 +++---------------------------------------- 2 files changed, 9 insertions(+), 58 deletions(-) diff --git a/libspark/audio.cpp b/libspark/audio.cpp index 7a55814..268377a 100644 --- a/libspark/audio.cpp +++ b/libspark/audio.cpp @@ -7,6 +7,8 @@ #include #include + +#include #include "audio_lib.h" #include "audio_mixer.h" #include "lt_debug.h" @@ -19,19 +21,6 @@ cAudio * audioDecoder = NULL; -static int proc_put(const char *path, const char *value, const int len) -{ - int ret, ret2; - int pfd = open(path, O_WRONLY); - if (pfd < 0) - return pfd; - ret = write(pfd, value, len); - ret2 = close(pfd); - if (ret2 < 0) - return ret2; - return ret; -} - cAudio::cAudio(void *, void *, void *) { fd = -1; @@ -117,7 +106,6 @@ int map_volume(const int volume) return vol; } - int cAudio::setVolume(unsigned int left, unsigned int right) { lt_debug("%s(%d, %d)\n", __func__, left, right); @@ -281,7 +269,7 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian) usable = devmask & stereo; if (usable == 0) { lt_info("%s: devmask: %08x stereo: %08x, no usable dev :-(\n", - __func__, devmask, stereo); + __func__, devmask, stereo); close(mixer_fd); mixer_fd = -1; return 0; /* TODO: should we treat this as error? */ @@ -290,13 +278,13 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian) if (__builtin_popcount (usable) != 1) { /* TODO: this code is not yet tested as I have only single-mixer devices... */ lt_info("%s: more than one mixer control: devmask %08x stereo %08x\n" - "%s: querying MIX_NUMBER environment variable...\n", - __func__, devmask, stereo, __func__); + "%s: querying MIX_NUMBER environment variable...\n", + __func__, devmask, stereo, __func__); const char *tmp = getenv("MIX_NUMBER"); if (tmp) mixer_num = atoi(tmp); lt_info("%s: mixer_num is %d -> device %08x\n", - __func__, mixer_num, (mixer_num >= 0) ? (1 << mixer_num) : 0); + __func__, mixer_num, (mixer_num >= 0) ? (1 << mixer_num) : 0); /* no error checking, you'd better know what you are doing... */ } else { mixer_num = 0; diff --git a/libspark/video.cpp b/libspark/video.cpp index cb734c1..a0f0e87 100644 --- a/libspark/video.cpp +++ b/libspark/video.cpp @@ -38,6 +38,9 @@ #include #include "video_lib.h" #include "lt_debug.h" + +#include + #define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args) #define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args) #define lt_debug_c(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, NULL, args) @@ -102,46 +105,6 @@ static const char *VMPEG_framerate[] = { #define VIDEO_STREAMTYPE_H265_HEVC 7 #define VIDEO_STREAMTYPE_AVS 16 - -static int proc_put(const char *path, const char *value, const int len) -{ - int ret, ret2; - int pfd = open(path, O_WRONLY); - if (pfd < 0) - return pfd; - ret = write(pfd, value, len); - ret2 = close(pfd); - if (ret2 < 0) - return ret2; - return ret; -} - -static int proc_get(const char *path, char *value, const int len) -{ - int ret, ret2; - int pfd = open(path, O_RDONLY); - if (pfd < 0) - return pfd; - ret = read(pfd, value, len); - value[len-1] = '\0'; /* make sure string is terminated */ - while (ret > 0 && isspace(value[ret-1])) - value[--ret] = '\0'; /* remove trailing whitespace */ - ret2 = close(pfd); - if (ret2 < 0) - return ret2; - return ret; -} - -static unsigned int proc_get_hex(const char *path) -{ - unsigned int n, ret = 0; - char buf[16]; - n = proc_get(path, buf, 16); - if (n > 0) - sscanf(buf, "%x", &ret); - return ret; -} - static int hdmi_out(bool enable) { struct stmfbio_output_configuration out; From ba7a351f59c04dabae9572901acec38c60ed6735 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Fri, 25 Dec 2015 19:08:31 +0100 Subject: [PATCH 32/73] spark/video: implicitly do StopPicture() on CVideo::Start() This seems to be what the coolstream code does. TODO: look out for side effects (in radio mode etc...) --- libspark/video.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libspark/video.cpp b/libspark/video.cpp index a0f0e87..71b2351 100644 --- a/libspark/video.cpp +++ b/libspark/video.cpp @@ -268,6 +268,12 @@ int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned sho if (playstate == VIDEO_FREEZED) /* in theory better, but not in practice :-) */ fop(ioctl, MPEG_VID_CONTINUE); #endif + /* implicitly do StopPicture() on video->Start() */ + if (stillpicture) { + lt_info("%s: stillpicture == true, doing implicit StopPicture()\n", __func__); + stillpicture = false; + Stop(1); + } playstate = VIDEO_PLAYING; fop(ioctl, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); int res = fop(ioctl, VIDEO_PLAY); From d57ac2cbdd9525187cc2438eb6debcc251de444d Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 19 Feb 2017 17:54:56 +0100 Subject: [PATCH 33/73] spark/video: add missing O_CLOEXEC to memory fd --- libspark/video.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libspark/video.cpp b/libspark/video.cpp index 71b2351..a83a351 100644 --- a/libspark/video.cpp +++ b/libspark/video.cpp @@ -1190,7 +1190,7 @@ bool cVideo::GetScreenImage(unsigned char * &video, int &xres, int &yres, bool g lt_info("%s: primary display pane not found in /proc/bpa2\n", __func__); } - mfd = open("/dev/mem", O_RDWR); + mfd = open("/dev/mem", O_RDWR | O_CLOEXEC); if (mfd < 0) { lt_info("%s: cannot open open /dev/mem (%m)\n", __func__); goto error_cleanup; From 18f3fbd8b905be0b4464237bf010f179a2a45618 Mon Sep 17 00:00:00 2001 From: max_10 Date: Sat, 7 Oct 2017 20:22:40 +0200 Subject: [PATCH 34/73] Revert "align videomodes" This reverts commit 7f9a31d29c903df9913ec5d656c65be424867a17. --- libspark/video_lib.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libspark/video_lib.h b/libspark/video_lib.h index e172cb9..3f8a7c2 100644 --- a/libspark/video_lib.h +++ b/libspark/video_lib.h @@ -101,12 +101,9 @@ typedef enum { VIDEO_STD_1080P30, VIDEO_STD_1080P24, VIDEO_STD_1080P25, - VIDEO_STD_1080P50, - VIDEO_STD_1080P60, - VIDEO_STD_1080P2397, - VIDEO_STD_1080P2997, VIDEO_STD_AUTO, - VIDEO_STD_MAX = VIDEO_STD_AUTO + VIDEO_STD_1080P50, /* SPARK only */ + VIDEO_STD_MAX } VIDEO_STD; /* not used, for dummy functions */ From 5ce57d6f57fa9e94f2327c67b022f0615929745a Mon Sep 17 00:00:00 2001 From: max_10 Date: Sat, 7 Oct 2017 20:23:15 +0200 Subject: [PATCH 35/73] Revert "align videomodes" This reverts commit b66a63553b50b3b0acb79898854e54ab63c7ab21. --- libspark/video.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libspark/video.cpp b/libspark/video.cpp index a83a351..f1e0dbe 100644 --- a/libspark/video.cpp +++ b/libspark/video.cpp @@ -337,8 +337,7 @@ int cVideo::GetVideoSystem() "1080p50", // VIDEO_STD_1080P50 "1080p60", // VIDEO_STD_1080P60 "1080p2397", // VIDEO_STD_1080P2397 - "1080p2997", // VIDEO_STD_1080P2997 - "720p50" // VIDEO_STD_AUTO + "1080p2997" // VIDEO_STD_1080P2997 }; int ret = proc_get("/proc/stb/video/videomode", current, 32); @@ -369,11 +368,8 @@ int cVideo::SetVideoSystem(int video_system, bool remember) "1080p30", // VIDEO_STD_1080P30 "1080p24", // VIDEO_STD_1080P24 "1080p25", // VIDEO_STD_1080P25 - "1080p50", // VIDEO_STD_1080P50 - "1080p60", // VIDEO_STD_1080P60 - "1080p2397", // VIDEO_STD_1080P2397 - "1080p2997", // VIDEO_STD_1080P2997 - "720p50" // VIDEO_STD_AUTO + "720p50", // VIDEO_STD_AUTO -> not implemented + "1080p50" // VIDEO_STD_1080P50 -> SPARK only }; if (video_system > VIDEO_STD_MAX) From 6b2e3594fa1a92347532c71f38ea9d320e130330 Mon Sep 17 00:00:00 2001 From: max_10 Date: Sat, 7 Oct 2017 20:23:32 +0200 Subject: [PATCH 36/73] Revert "implement GetVideoSystem" This reverts commit 23afdef65c2442eeabb4760c274372d86fd065ed. --- libspark/video.cpp | 34 ---------------------------------- libspark/video_lib.h | 3 --- 2 files changed, 37 deletions(-) diff --git a/libspark/video.cpp b/libspark/video.cpp index f1e0dbe..37ea57d 100644 --- a/libspark/video.cpp +++ b/libspark/video.cpp @@ -317,40 +317,6 @@ int cVideo::setBlank(int) return Stop(1); } -int cVideo::GetVideoSystem() -{ - lt_debug("%s\n", __func__); - char current[32]; - static const char *modes[] = { - "pal", // VIDEO_STD_NTSC - "pal", // VIDEO_STD_SECAM - "pal", // VIDEO_STD_PAL - "480p", // VIDEO_STD_480P - "576p50", // VIDEO_STD_576P - "720p60", // VIDEO_STD_720P60 - "1080i60", // VIDEO_STD_1080I60 - "720p50", // VIDEO_STD_720P50 - "1080i50", // VIDEO_STD_1080I50 - "1080p30", // VIDEO_STD_1080P30 - "1080p24", // VIDEO_STD_1080P24 - "1080p25", // VIDEO_STD_1080P25 - "1080p50", // VIDEO_STD_1080P50 - "1080p60", // VIDEO_STD_1080P60 - "1080p2397", // VIDEO_STD_1080P2397 - "1080p2997" // VIDEO_STD_1080P2997 - }; - - int ret = proc_get("/proc/stb/video/videomode", current, 32); - for (int i=0; i Date: Sat, 26 Aug 2017 12:56:32 +0200 Subject: [PATCH 37/73] libspark: implement cVideo::GetVideoSystem() --- libspark/video.cpp | 52 +++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/libspark/video.cpp b/libspark/video.cpp index 37ea57d..5692d47 100644 --- a/libspark/video.cpp +++ b/libspark/video.cpp @@ -95,6 +95,23 @@ static const char *VMPEG_framerate[] = { "/proc/stb/vmpeg/1/framerate" }; +static const char *vid_modes[] = { + "pal", // VIDEO_STD_NTSC + "pal", // VIDEO_STD_SECAM + "pal", // VIDEO_STD_PAL + "480p", // VIDEO_STD_480P + "576p50", // VIDEO_STD_576P + "720p60", // VIDEO_STD_720P60 + "1080i60", // VIDEO_STD_1080I60 + "720p50", // VIDEO_STD_720P50 + "1080i50", // VIDEO_STD_1080I50 + "1080p30", // VIDEO_STD_1080P30 + "1080p24", // VIDEO_STD_1080P24 + "1080p25", // VIDEO_STD_1080P25 + "720p50", // VIDEO_STD_AUTO -> not implemented + "1080p50", // VIDEO_STD_1080P50 -> SPARK only + NULL +}; #define VIDEO_STREAMTYPE_MPEG2 0 #define VIDEO_STREAMTYPE_MPEG4_H264 1 @@ -321,22 +338,6 @@ int cVideo::SetVideoSystem(int video_system, bool remember) { lt_debug("%s(%d, %d)\n", __func__, video_system, remember); char current[32]; - static const char *modes[] = { - "pal", // VIDEO_STD_NTSC - "pal", // VIDEO_STD_SECAM - "pal", // VIDEO_STD_PAL - "480p", // VIDEO_STD_480P - "576p50", // VIDEO_STD_576P - "720p60", // VIDEO_STD_720P60 - "1080i60", // VIDEO_STD_1080I60 - "720p50", // VIDEO_STD_720P50 - "1080i50", // VIDEO_STD_1080I50 - "1080p30", // VIDEO_STD_1080P30 - "1080p24", // VIDEO_STD_1080P24 - "1080p25", // VIDEO_STD_1080P25 - "720p50", // VIDEO_STD_AUTO -> not implemented - "1080p50" // VIDEO_STD_1080P50 -> SPARK only - }; if (video_system > VIDEO_STD_MAX) { @@ -344,12 +345,12 @@ int cVideo::SetVideoSystem(int video_system, bool remember) return -1; } int ret = proc_get("/proc/stb/video/videomode", current, 32); - if (strcmp(current, modes[video_system]) == 0) + if (strcmp(current, vid_modes[video_system]) == 0) { lt_info("%s: video_system %d (%s) already set, skipping\n", __func__, video_system, current); return 0; } - lt_info("%s: old: '%s' new: '%s'\n", __func__, current, modes[video_system]); + lt_info("%s: old: '%s' new: '%s'\n", __func__, current, vid_modes[video_system]); bool stopped = false; if (playstate == VIDEO_PLAYING) { @@ -358,7 +359,7 @@ int cVideo::SetVideoSystem(int video_system, bool remember) stopped = true; } hdmi_out(false); - ret = proc_put("/proc/stb/video/videomode", modes[video_system],strlen(modes[video_system])); + ret = proc_put("/proc/stb/video/videomode", vid_modes[video_system],strlen(vid_modes[video_system])); hdmi_out(true); if (stopped) Start(); @@ -366,6 +367,19 @@ int cVideo::SetVideoSystem(int video_system, bool remember) return ret; } +int cVideo::GetVideoSystem(void) +{ + char current[32]; + proc_get("/proc/stb/video/videomode", current, 32); + for (int i = 2; vid_modes[i]; i++) /* 0,1,2 are all "pal" */ + { + if (strcmp(current, vid_modes[i]) == 0) + return i; + } + lt_info("%s: could not find '%s' mode, returning VIDEO_STD_720P50\n", __func__, current); + return VIDEO_STD_720P50; +} + int cVideo::getPlayState(void) { return playstate; From 4285d9449def37b9ecafa9f50227f07294bd6582 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 26 Aug 2017 12:57:40 +0200 Subject: [PATCH 38/73] libspark: implement cVideo::GetVideoSystemFormatName() --- include/video_hal.h | 222 +++++++++++++++++++++++++++++++++++++++++++ libspark/video.cpp | 11 +++ libspark/video_lib.h | 14 ++- 3 files changed, 245 insertions(+), 2 deletions(-) diff --git a/include/video_hal.h b/include/video_hal.h index db01265..1729929 100644 --- a/include/video_hal.h +++ b/include/video_hal.h @@ -1,3 +1,4 @@ +<<<<<<< HEAD #include #if HAVE_TRIPLEDRAGON #include "../libtriple/video_td.h" @@ -18,6 +19,227 @@ #else #error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined #endif +======= +/* + Copyright 2010-2013 Stefan Seyfried + + 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, see . +*/ + + +#ifndef _VIDEO_LIB_H +#define _VIDEO_LIB_H + +#include +#include + +typedef struct cs_vs_format_t +{ + char format[16]; +} cs_vs_format_struct_t; + +typedef enum { + ANALOG_SD_RGB_CINCH = 0x00, + ANALOG_SD_YPRPB_CINCH, + ANALOG_HD_RGB_CINCH, + ANALOG_HD_YPRPB_CINCH, + ANALOG_SD_RGB_SCART = 0x10, + ANALOG_SD_YPRPB_SCART, + ANALOG_HD_RGB_SCART, + ANALOG_HD_YPRPB_SCART, + ANALOG_SCART_MASK = 0x10 +} analog_mode_t; + + +typedef enum { + VIDEO_FORMAT_MPEG2 = 0, + VIDEO_FORMAT_MPEG4, /* H264 */ + VIDEO_FORMAT_VC1, + VIDEO_FORMAT_JPEG, + VIDEO_FORMAT_GIF, + VIDEO_FORMAT_PNG, + VIDEO_FORMAT_DIVX,/* DIVX 3.11 */ + VIDEO_FORMAT_MPEG4PART2,/* MPEG4 SVH, MPEG4 SP, MPEG4 ASP, DIVX4,5,6 */ + VIDEO_FORMAT_REALVIDEO8, + VIDEO_FORMAT_REALVIDEO9, + VIDEO_FORMAT_ON2_VP6, + VIDEO_FORMAT_ON2_VP8, + VIDEO_FORMAT_SORENSON_SPARK, + VIDEO_FORMAT_H263, + VIDEO_FORMAT_H263_ENCODER, + VIDEO_FORMAT_H264_ENCODER, + VIDEO_FORMAT_MPEG4PART2_ENCODER, + VIDEO_FORMAT_AVS, + VIDEO_FORMAT_VIP656, + VIDEO_FORMAT_UNSUPPORTED +} VIDEO_FORMAT; + +typedef enum { + VIDEO_SD = 0, + VIDEO_HD, + VIDEO_120x60i, + VIDEO_320x240i, + VIDEO_1440x800i, + VIDEO_360x288i +} VIDEO_DEFINITION; + +typedef enum { + VIDEO_FRAME_RATE_23_976 = 0, + VIDEO_FRAME_RATE_24, + VIDEO_FRAME_RATE_25, + VIDEO_FRAME_RATE_29_97, + VIDEO_FRAME_RATE_30, + VIDEO_FRAME_RATE_50, + VIDEO_FRAME_RATE_59_94, + VIDEO_FRAME_RATE_60 +} VIDEO_FRAME_RATE; + +typedef enum { + DISPLAY_AR_1_1, + DISPLAY_AR_4_3, + DISPLAY_AR_14_9, + DISPLAY_AR_16_9, + DISPLAY_AR_20_9, + DISPLAY_AR_RAW, +} DISPLAY_AR; + +typedef enum { + DISPLAY_AR_MODE_PANSCAN = 0, + DISPLAY_AR_MODE_LETTERBOX, + DISPLAY_AR_MODE_NONE, + DISPLAY_AR_MODE_PANSCAN2 +} DISPLAY_AR_MODE; + +typedef enum { + VIDEO_DB_DR_NEITHER = 0, + VIDEO_DB_ON, + VIDEO_DB_DR_BOTH +} VIDEO_DB_DR; + +typedef enum { + VIDEO_PLAY_STILL = 0, + VIDEO_PLAY_CLIP, + VIDEO_PLAY_TRICK, + VIDEO_PLAY_MOTION, + VIDEO_PLAY_MOTION_NO_SYNC +} VIDEO_PLAY_MODE; + +typedef enum { + VIDEO_STD_NTSC, + VIDEO_STD_SECAM, + VIDEO_STD_PAL, + VIDEO_STD_480P, + VIDEO_STD_576P, + VIDEO_STD_720P60, + VIDEO_STD_1080I60, + VIDEO_STD_720P50, + VIDEO_STD_1080I50, + VIDEO_STD_1080P30, + VIDEO_STD_1080P24, + VIDEO_STD_1080P25, + VIDEO_STD_1080P50, + VIDEO_STD_1080P60, + VIDEO_STD_AUTO, + VIDEO_STD_MAX +} VIDEO_STD; + +/* not used, for dummy functions */ +typedef enum { + VIDEO_HDMI_CEC_MODE_OFF = 0, + VIDEO_HDMI_CEC_MODE_TUNER, + VIDEO_HDMI_CEC_MODE_RECORDER +} VIDEO_HDMI_CEC_MODE; + +typedef enum +{ + VIDEO_CONTROL_BRIGHTNESS = 0, + VIDEO_CONTROL_CONTRAST, + VIDEO_CONTROL_SATURATION, + VIDEO_CONTROL_HUE, + VIDEO_CONTROL_SHARPNESS, + VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS +} VIDEO_CONTROL; + +class cDemux; +class cPlayback; +class VDec; + +class cVideo +{ + friend class cPlayback; + friend class cDemux; + public: + /* constructor & destructor */ + cVideo(int mode, void *, void *, unsigned int unit = 0); + ~cVideo(void); + + void * GetTVEnc() { return NULL; }; + void * GetTVEncSD() { return NULL; }; + + /* aspect ratio */ + int getAspectRatio(void); + void getPictureInfo(int &width, int &height, int &rate); + int setAspectRatio(int aspect, int mode); + + /* cropping mode */ + int setCroppingMode(void); + + /* get play state */ + int getPlayState(void); + + /* blank on freeze */ + int getBlank(void); + int setBlank(int enable); + + /* change video play state. Parameters are all unused. */ + int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL); + int Stop(bool blank = true); + bool Pause(void); + + /* get video system infos */ + int GetVideoSystem(void); + /* when system = -1 then use current video system */ + void GetVideoSystemFormatName(cs_vs_format_t* format, int system = -1); + + /* set video_system */ + int SetVideoSystem(int video_system, bool remember = true); + int SetStreamType(VIDEO_FORMAT type); + void SetSyncMode(AVSYNC_TYPE mode); + bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; }; + void SetCECAutoView(bool) { return; }; + void SetCECAutoStandby(bool) { return; }; + void ShowPicture(const char * fname); + void StopPicture(); + void Standby(unsigned int bOn); + void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600); + void SetControl(int, int) { return; }; + void setContrast(int val); + void SetVideoMode(analog_mode_t mode); + void SetDBDR(int) { return; }; + void SetAudioHandle(void *) { return; }; + void SetAutoModes(int [VIDEO_STD_MAX]) { return; }; + int OpenVBI(int) { return 0; }; + int CloseVBI(void) { return 0; }; + int StartVBI(unsigned short) { return 0; }; + int StopVBI(void) { return 0; }; + void SetDemux(cDemux *dmx); + bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false); + private: + VDec *vdec; + void *pdata; +}; +>>>>>>> 6e3b116... libspark: implement cVideo::GetVideoSystemFormatName() #if STB_HAL_VIDEO_HAS_GETSCREENIMAGE #define SCREENSHOT 1 diff --git a/libspark/video.cpp b/libspark/video.cpp index 5692d47..16f0477 100644 --- a/libspark/video.cpp +++ b/libspark/video.cpp @@ -380,6 +380,17 @@ int cVideo::GetVideoSystem(void) return VIDEO_STD_720P50; } +void cVideo::GetVideoSystemFormatName(cs_vs_format_t *format, int system) +{ + if (system == -1) + system = GetVideoSystem(); + if (system < 0 || system > VIDEO_STD_1080P50) { + lt_info("%s: invalid system %d\n", __func__, system); + strcpy(format->format, "invalid"); + } else + strcpy(format->format, vid_modes[system]); +} + int cVideo::getPlayState(void) { return playstate; diff --git a/libspark/video_lib.h b/libspark/video_lib.h index 139333d..d4bb5f7 100644 --- a/libspark/video_lib.h +++ b/libspark/video_lib.h @@ -5,6 +5,11 @@ #include "../common/cs_types.h" #include "dmx_lib.h" +typedef struct cs_vs_format_t +{ + char format[16]; +} cs_vs_format_struct_t; + typedef enum { ANALOG_SD_RGB_CINCH = 0x00, ANALOG_SD_YPRPB_CINCH, @@ -108,7 +113,7 @@ typedef enum { /* not used, for dummy functions */ typedef enum { - VIDEO_HDMI_CEC_MODE_OFF = 0, + VIDEO_HDMI_CEC_MODE_OFF = 0, VIDEO_HDMI_CEC_MODE_TUNER, VIDEO_HDMI_CEC_MODE_RECORDER } VIDEO_HDMI_CEC_MODE; @@ -126,8 +131,8 @@ typedef enum class cVideo { - friend class cDemux; friend class cPlayback; + friend class cDemux; private: /* video device */ int fd; @@ -182,6 +187,11 @@ class cVideo int Stop(bool blank = true); bool Pause(void); + /* get video system infos */ + int GetVideoSystem(void); + /* when system = -1 then use current video system */ + void GetVideoSystemFormatName(cs_vs_format_t* format, int system = -1); + /* set video_system */ int SetVideoSystem(int video_system, bool remember = true); int SetStreamType(VIDEO_FORMAT type); From 70d7730f8228d1b7efe78338fa0edd6af976c3e2 Mon Sep 17 00:00:00 2001 From: max_10 Date: Sat, 7 Oct 2017 17:49:09 +0200 Subject: [PATCH 39/73] fix cherry-pick --- include/video_hal.h | 222 -------------------------------------------- 1 file changed, 222 deletions(-) diff --git a/include/video_hal.h b/include/video_hal.h index 1729929..db01265 100644 --- a/include/video_hal.h +++ b/include/video_hal.h @@ -1,4 +1,3 @@ -<<<<<<< HEAD #include #if HAVE_TRIPLEDRAGON #include "../libtriple/video_td.h" @@ -19,227 +18,6 @@ #else #error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined #endif -======= -/* - Copyright 2010-2013 Stefan Seyfried - - 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, see . -*/ - - -#ifndef _VIDEO_LIB_H -#define _VIDEO_LIB_H - -#include -#include - -typedef struct cs_vs_format_t -{ - char format[16]; -} cs_vs_format_struct_t; - -typedef enum { - ANALOG_SD_RGB_CINCH = 0x00, - ANALOG_SD_YPRPB_CINCH, - ANALOG_HD_RGB_CINCH, - ANALOG_HD_YPRPB_CINCH, - ANALOG_SD_RGB_SCART = 0x10, - ANALOG_SD_YPRPB_SCART, - ANALOG_HD_RGB_SCART, - ANALOG_HD_YPRPB_SCART, - ANALOG_SCART_MASK = 0x10 -} analog_mode_t; - - -typedef enum { - VIDEO_FORMAT_MPEG2 = 0, - VIDEO_FORMAT_MPEG4, /* H264 */ - VIDEO_FORMAT_VC1, - VIDEO_FORMAT_JPEG, - VIDEO_FORMAT_GIF, - VIDEO_FORMAT_PNG, - VIDEO_FORMAT_DIVX,/* DIVX 3.11 */ - VIDEO_FORMAT_MPEG4PART2,/* MPEG4 SVH, MPEG4 SP, MPEG4 ASP, DIVX4,5,6 */ - VIDEO_FORMAT_REALVIDEO8, - VIDEO_FORMAT_REALVIDEO9, - VIDEO_FORMAT_ON2_VP6, - VIDEO_FORMAT_ON2_VP8, - VIDEO_FORMAT_SORENSON_SPARK, - VIDEO_FORMAT_H263, - VIDEO_FORMAT_H263_ENCODER, - VIDEO_FORMAT_H264_ENCODER, - VIDEO_FORMAT_MPEG4PART2_ENCODER, - VIDEO_FORMAT_AVS, - VIDEO_FORMAT_VIP656, - VIDEO_FORMAT_UNSUPPORTED -} VIDEO_FORMAT; - -typedef enum { - VIDEO_SD = 0, - VIDEO_HD, - VIDEO_120x60i, - VIDEO_320x240i, - VIDEO_1440x800i, - VIDEO_360x288i -} VIDEO_DEFINITION; - -typedef enum { - VIDEO_FRAME_RATE_23_976 = 0, - VIDEO_FRAME_RATE_24, - VIDEO_FRAME_RATE_25, - VIDEO_FRAME_RATE_29_97, - VIDEO_FRAME_RATE_30, - VIDEO_FRAME_RATE_50, - VIDEO_FRAME_RATE_59_94, - VIDEO_FRAME_RATE_60 -} VIDEO_FRAME_RATE; - -typedef enum { - DISPLAY_AR_1_1, - DISPLAY_AR_4_3, - DISPLAY_AR_14_9, - DISPLAY_AR_16_9, - DISPLAY_AR_20_9, - DISPLAY_AR_RAW, -} DISPLAY_AR; - -typedef enum { - DISPLAY_AR_MODE_PANSCAN = 0, - DISPLAY_AR_MODE_LETTERBOX, - DISPLAY_AR_MODE_NONE, - DISPLAY_AR_MODE_PANSCAN2 -} DISPLAY_AR_MODE; - -typedef enum { - VIDEO_DB_DR_NEITHER = 0, - VIDEO_DB_ON, - VIDEO_DB_DR_BOTH -} VIDEO_DB_DR; - -typedef enum { - VIDEO_PLAY_STILL = 0, - VIDEO_PLAY_CLIP, - VIDEO_PLAY_TRICK, - VIDEO_PLAY_MOTION, - VIDEO_PLAY_MOTION_NO_SYNC -} VIDEO_PLAY_MODE; - -typedef enum { - VIDEO_STD_NTSC, - VIDEO_STD_SECAM, - VIDEO_STD_PAL, - VIDEO_STD_480P, - VIDEO_STD_576P, - VIDEO_STD_720P60, - VIDEO_STD_1080I60, - VIDEO_STD_720P50, - VIDEO_STD_1080I50, - VIDEO_STD_1080P30, - VIDEO_STD_1080P24, - VIDEO_STD_1080P25, - VIDEO_STD_1080P50, - VIDEO_STD_1080P60, - VIDEO_STD_AUTO, - VIDEO_STD_MAX -} VIDEO_STD; - -/* not used, for dummy functions */ -typedef enum { - VIDEO_HDMI_CEC_MODE_OFF = 0, - VIDEO_HDMI_CEC_MODE_TUNER, - VIDEO_HDMI_CEC_MODE_RECORDER -} VIDEO_HDMI_CEC_MODE; - -typedef enum -{ - VIDEO_CONTROL_BRIGHTNESS = 0, - VIDEO_CONTROL_CONTRAST, - VIDEO_CONTROL_SATURATION, - VIDEO_CONTROL_HUE, - VIDEO_CONTROL_SHARPNESS, - VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS -} VIDEO_CONTROL; - -class cDemux; -class cPlayback; -class VDec; - -class cVideo -{ - friend class cPlayback; - friend class cDemux; - public: - /* constructor & destructor */ - cVideo(int mode, void *, void *, unsigned int unit = 0); - ~cVideo(void); - - void * GetTVEnc() { return NULL; }; - void * GetTVEncSD() { return NULL; }; - - /* aspect ratio */ - int getAspectRatio(void); - void getPictureInfo(int &width, int &height, int &rate); - int setAspectRatio(int aspect, int mode); - - /* cropping mode */ - int setCroppingMode(void); - - /* get play state */ - int getPlayState(void); - - /* blank on freeze */ - int getBlank(void); - int setBlank(int enable); - - /* change video play state. Parameters are all unused. */ - int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL); - int Stop(bool blank = true); - bool Pause(void); - - /* get video system infos */ - int GetVideoSystem(void); - /* when system = -1 then use current video system */ - void GetVideoSystemFormatName(cs_vs_format_t* format, int system = -1); - - /* set video_system */ - int SetVideoSystem(int video_system, bool remember = true); - int SetStreamType(VIDEO_FORMAT type); - void SetSyncMode(AVSYNC_TYPE mode); - bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; }; - void SetCECAutoView(bool) { return; }; - void SetCECAutoStandby(bool) { return; }; - void ShowPicture(const char * fname); - void StopPicture(); - void Standby(unsigned int bOn); - void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600); - void SetControl(int, int) { return; }; - void setContrast(int val); - void SetVideoMode(analog_mode_t mode); - void SetDBDR(int) { return; }; - void SetAudioHandle(void *) { return; }; - void SetAutoModes(int [VIDEO_STD_MAX]) { return; }; - int OpenVBI(int) { return 0; }; - int CloseVBI(void) { return 0; }; - int StartVBI(unsigned short) { return 0; }; - int StopVBI(void) { return 0; }; - void SetDemux(cDemux *dmx); - bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false); - private: - VDec *vdec; - void *pdata; -}; ->>>>>>> 6e3b116... libspark: implement cVideo::GetVideoSystemFormatName() #if STB_HAL_VIDEO_HAS_GETSCREENIMAGE #define SCREENSHOT 1 From b67a0a7e44cfe4d3c7692bfa92b5db7cc3e37bfe Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Fri, 20 Feb 2015 09:30:19 +0100 Subject: [PATCH 40/73] spark: fix race condition in cDemux cDemux destructor was racing with Read() which did lead to all sorts of nasty crashes because after poll returned, the dmx object could be gone and its memory replaced with totally different things. --- libspark/dmx.cpp | 38 ++++++++++++++++++++++++++++++++++---- libspark/dmx_lib.h | 1 + 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/libspark/dmx.cpp b/libspark/dmx.cpp index d3ba4e7..6f8a969 100644 --- a/libspark/dmx.cpp +++ b/libspark/dmx.cpp @@ -66,11 +66,13 @@ #include #include #include +#include +#include #include "dmx_lib.h" #include "lt_debug.h" -/* Ugh... see comment in destructor for details... */ #include "video_lib.h" +/* needed for getSTC... */ extern cVideo *videoDecoder; #define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args) @@ -119,9 +121,11 @@ static const char *devname[NUM_DEMUXDEV] = { /* did we already DMX_SET_SOURCE on that demux device? */ static bool init[NUM_DEMUXDEV] = { false, false, false }; -/* uuuugly */ -static int dmx_tp_count = 0; -#define MAX_TS_COUNT 1 +typedef struct dmx_pdata { + int last_source; + OpenThreads::Mutex *mutex; +} dmx_pdata; +#define P ((dmx_pdata *)pdata) cDemux::cDemux(int n) { @@ -137,6 +141,11 @@ cDemux::cDemux(int n) last_measure = 0; last_data = 0; last_source = -1; + + pdata = (void *)calloc(1, sizeof(dmx_pdata)); + P->last_source = -1; + P->mutex = new OpenThreads::Mutex; + dmx_type = DMX_INVALID; } cDemux::~cDemux() @@ -155,6 +164,12 @@ cDemux::~cDemux() */ if (dmx_type == DMX_VIDEO_CHANNEL) videoDecoder = NULL; + /* wait until Read() has released the mutex */ + (*P->mutex).lock(); + (*P->mutex).unlock(); + free(P->mutex); + free(pdata); + pdata = NULL; } bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize) @@ -250,6 +265,7 @@ void cDemux::Close(void) bool cDemux::Start(bool) { + lt_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]); if (fd < 0) { lt_info("%s #%d: not open!\n", __FUNCTION__, num); @@ -261,6 +277,7 @@ bool cDemux::Start(bool) bool cDemux::Stop(void) { + lt_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]); if (fd < 0) { lt_info("%s #%d: not open!\n", __FUNCTION__, num); @@ -282,6 +299,8 @@ int cDemux::Read(unsigned char *buff, int len, int timeout) lt_info("%s #%d: not open!\n", __func__, num); return -1; } + /* avoid race in destructor: ~cDemux needs to wait until Read() returns */ + OpenThreads::ScopedLock m_lock(*P->mutex); int rc; int to = timeout; struct pollfd ufds; @@ -299,6 +318,12 @@ int cDemux::Read(unsigned char *buff, int len, int timeout) { retry: rc = ::poll(&ufds, 1, to); + if (ufds.fd != fd) + { + /* Close() will set fd to -1, this is normal. Everything else is not. */ + lt_info("%s:1 ========== fd has changed, %d->%d ==========\n", __func__, ufds.fd, fd); + return -1; + } if (!rc) { if (timeout == 0) /* we took the emergency exit */ @@ -336,6 +361,11 @@ int cDemux::Read(unsigned char *buff, int len, int timeout) return 0; } } + if (ufds.fd != fd) /* does this ever happen? and if, is it harmful? */ + { /* read(-1,...) will just return EBADF anyway... */ + lt_info("%s:2 ========== fd has changed, %d->%d ==========\n", __func__, ufds.fd, fd); + return -1; + } rc = ::read(fd, buff, len); //fprintf(stderr, "fd %d ret: %d\n", fd, rc); diff --git a/libspark/dmx_lib.h b/libspark/dmx_lib.h index af87a02..056cb71 100644 --- a/libspark/dmx_lib.h +++ b/libspark/dmx_lib.h @@ -42,6 +42,7 @@ class cDemux struct dmx_pes_filter_params p_flt; int last_source; bool _open(void); + void *pdata; public: bool Open(DMX_CHANNEL_TYPE pes_type, void * unused = NULL, int bufsize = 0); From 9f1c5a6c59ba7e69f24944ef1d7369d0c2854999 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 21 Feb 2015 22:14:47 +0100 Subject: [PATCH 41/73] spark: remove videodecoder hack from dmx destructor --- libspark/dmx.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/libspark/dmx.cpp b/libspark/dmx.cpp index 6f8a969..caa4fc9 100644 --- a/libspark/dmx.cpp +++ b/libspark/dmx.cpp @@ -152,18 +152,6 @@ cDemux::~cDemux() { lt_debug("%s #%d fd: %d\n", __FUNCTION__, num, fd); Close(); - /* in zapit.cpp, videoDemux is deleted after videoDecoder - * in the video watchdog, we access videoDecoder - * the thread still runs after videoDecoder has been deleted - * => set videoDecoder to NULL here to make the check in the - * watchdog thread pick this up. - * This is ugly, but it saves me from changing neutrino - * - * if the delete order in neutrino will ever be changed, this - * will blow up badly :-( - */ - if (dmx_type == DMX_VIDEO_CHANNEL) - videoDecoder = NULL; /* wait until Read() has released the mutex */ (*P->mutex).lock(); (*P->mutex).unlock(); From 3f6cee32f46b378db3404b5ba30af7a74f861deb Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 21 Feb 2015 22:25:29 +0100 Subject: [PATCH 42/73] spark: remove dead code from cDemux --- libspark/dmx.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libspark/dmx.cpp b/libspark/dmx.cpp index caa4fc9..ec81e9a 100644 --- a/libspark/dmx.cpp +++ b/libspark/dmx.cpp @@ -240,15 +240,6 @@ void cDemux::Close(void) fd = -1; if (measure) return; - if (dmx_type == DMX_TP_CHANNEL) - { - dmx_tp_count--; - if (dmx_tp_count < 0) - { - lt_info("%s dmx_tp_count < 0!!\n", __func__); - dmx_tp_count = 0; - } - } } bool cDemux::Start(bool) From be07c1a1b7e0e76dfa33aaf737903f521b9ea86a Mon Sep 17 00:00:00 2001 From: max_10 Date: Sat, 7 Oct 2017 20:55:48 +0200 Subject: [PATCH 43/73] armbox: use proc_tools --- libarmbox/audio.cpp | 24 ++++++------------------ libarmbox/video.cpp | 43 +++---------------------------------------- 2 files changed, 9 insertions(+), 58 deletions(-) diff --git a/libarmbox/audio.cpp b/libarmbox/audio.cpp index 9e5960b..3eb0a97 100644 --- a/libarmbox/audio.cpp +++ b/libarmbox/audio.cpp @@ -7,6 +7,8 @@ #include #include + +#include #include "audio_lib.h" #include "audio_mixer.h" #include "lt_debug.h" @@ -19,19 +21,6 @@ cAudio * audioDecoder = NULL; -static int proc_put(const char *path, const char *value, const int len) -{ - int ret, ret2; - int pfd = open(path, O_WRONLY); - if (pfd < 0) - return pfd; - ret = write(pfd, value, len); - ret2 = close(pfd); - if (ret2 < 0) - return ret2; - return ret; -} - cAudio::cAudio(void *, void *, void *) { fd = -1; @@ -117,7 +106,6 @@ int map_volume(const int volume) return vol; } - int cAudio::setVolume(unsigned int left, unsigned int right) { lt_debug("%s(%d, %d)\n", __func__, left, right); @@ -281,7 +269,7 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian) usable = devmask & stereo; if (usable == 0) { lt_info("%s: devmask: %08x stereo: %08x, no usable dev :-(\n", - __func__, devmask, stereo); + __func__, devmask, stereo); close(mixer_fd); mixer_fd = -1; return 0; /* TODO: should we treat this as error? */ @@ -290,13 +278,13 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian) if (__builtin_popcount (usable) != 1) { /* TODO: this code is not yet tested as I have only single-mixer devices... */ lt_info("%s: more than one mixer control: devmask %08x stereo %08x\n" - "%s: querying MIX_NUMBER environment variable...\n", - __func__, devmask, stereo, __func__); + "%s: querying MIX_NUMBER environment variable...\n", + __func__, devmask, stereo, __func__); const char *tmp = getenv("MIX_NUMBER"); if (tmp) mixer_num = atoi(tmp); lt_info("%s: mixer_num is %d -> device %08x\n", - __func__, mixer_num, (mixer_num >= 0) ? (1 << mixer_num) : 0); + __func__, mixer_num, (mixer_num >= 0) ? (1 << mixer_num) : 0); /* no error checking, you'd better know what you are doing... */ } else { mixer_num = 0; diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 90cdce4..8a521ce 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -36,6 +36,9 @@ #include #include "video_lib.h" #include "lt_debug.h" + +#include + #define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args) #define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args) #define lt_debug_c(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, NULL, args) @@ -120,46 +123,6 @@ static const char *VMPEG_framerate[] = { #define VIDEO_STREAMTYPE_H265_HEVC 7 #define VIDEO_STREAMTYPE_AVS 16 - -static int proc_put(const char *path, const char *value, const int len) -{ - int ret, ret2; - int pfd = open(path, O_WRONLY); - if (pfd < 0) - return pfd; - ret = write(pfd, value, len); - ret2 = close(pfd); - if (ret2 < 0) - return ret2; - return ret; -} - -static int proc_get(const char *path, char *value, const int len) -{ - int ret, ret2; - int pfd = open(path, O_RDONLY); - if (pfd < 0) - return pfd; - ret = read(pfd, value, len); - value[len-1] = '\0'; /* make sure string is terminated */ - while (ret > 0 && isspace(value[ret-1])) - value[--ret] = '\0'; /* remove trailing whitespace */ - ret2 = close(pfd); - if (ret2 < 0) - return ret2; - return ret; -} - -static unsigned int proc_get_hex(const char *path) -{ - unsigned int n, ret = 0; - char buf[16]; - n = proc_get(path, buf, 16); - if (n > 0) - sscanf(buf, "%x", &ret); - return ret; -} - static int hdmi_out(bool enable) { int ret = -1; From a5ee425996b6508f0d3d45d003d8ed87c2d2af52 Mon Sep 17 00:00:00 2001 From: max_10 Date: Sat, 7 Oct 2017 21:02:27 +0200 Subject: [PATCH 44/73] armbox: remove videodecoder hack from dmx destructor --- libarmbox/dmx.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/libarmbox/dmx.cpp b/libarmbox/dmx.cpp index 70eeed1..59b4172 100644 --- a/libarmbox/dmx.cpp +++ b/libarmbox/dmx.cpp @@ -147,18 +147,6 @@ cDemux::~cDemux() { lt_debug("%s #%d fd: %d\n", __FUNCTION__, num, fd); Close(); - /* in zapit.cpp, videoDemux is deleted after videoDecoder - * in the video watchdog, we access videoDecoder - * the thread still runs after videoDecoder has been deleted - * => set videoDecoder to NULL here to make the check in the - * watchdog thread pick this up. - * This is ugly, but it saves me from changing neutrino - * - * if the delete order in neutrino will ever be changed, this - * will blow up badly :-( - */ - if (dmx_type == DMX_VIDEO_CHANNEL) - videoDecoder = NULL; } bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize) From 86244ea9529be1bddf9f28aecfe37615fa6d8bde Mon Sep 17 00:00:00 2001 From: max_10 Date: Sat, 7 Oct 2017 21:04:31 +0200 Subject: [PATCH 45/73] armbox: remove dead code from cDemux --- libarmbox/dmx.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/libarmbox/dmx.cpp b/libarmbox/dmx.cpp index 59b4172..687f3b8 100644 --- a/libarmbox/dmx.cpp +++ b/libarmbox/dmx.cpp @@ -69,8 +69,8 @@ #include "dmx_lib.h" #include "lt_debug.h" -/* Ugh... see comment in destructor for details... */ #include "video_lib.h" +/* needed for getSTC... */ extern cVideo *videoDecoder; #define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args) @@ -123,10 +123,6 @@ static const char *devname[NUM_DEMUXDEV] = { /* did we already DMX_SET_SOURCE on that demux device? */ static bool init[NUM_DEMUXDEV] = { false, false, false, false, false, false, false, false }; -/* uuuugly */ -static int dmx_tp_count = 0; -#define MAX_TS_COUNT 1 - cDemux::cDemux(int n) { if (n < 0 || n >= NUM_DEMUX) @@ -229,15 +225,6 @@ void cDemux::Close(void) fd = -1; if (measure) return; - if (dmx_type == DMX_TP_CHANNEL) - { - dmx_tp_count--; - if (dmx_tp_count < 0) - { - lt_info("%s dmx_tp_count < 0!!\n", __func__); - dmx_tp_count = 0; - } - } } bool cDemux::Start(bool) From 5c0741a8e364caf2ff6885fccda668cecb06267d Mon Sep 17 00:00:00 2001 From: max_10 Date: Sat, 7 Oct 2017 21:53:16 +0200 Subject: [PATCH 46/73] armbox: delete parts of sh4 code --- libarmbox/video.cpp | 29 ----------------------------- libarmbox/video_lib.h | 9 +++++++-- 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 8a521ce..74f07b0 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -61,7 +61,6 @@ cVideo * pipDecoder = NULL; int system_rev = 0; -static bool hdmi_enabled = true; static bool stillpicture = false; static const char *VDEV[] = { @@ -123,13 +122,6 @@ static const char *VMPEG_framerate[] = { #define VIDEO_STREAMTYPE_H265_HEVC 7 #define VIDEO_STREAMTYPE_AVS 16 -static int hdmi_out(bool enable) -{ - int ret = -1; - return ret; -} - - cVideo::cVideo(int, void *, void *, unsigned int unit) { lt_debug("%s unit %u\n", __func__, unit); @@ -138,8 +130,6 @@ cVideo::cVideo(int, void *, void *, unsigned int unit) contrast = -1; saturation = -1; hue = -1; - - scartvoltage = -1; video_standby = 0; if (unit > 1) { lt_info("%s: unit %d out of range, setting to 0\n", __func__, unit); @@ -387,9 +377,7 @@ int cVideo::SetVideoSystem(int video_system, bool remember) Stop(); stopped = true; } - hdmi_out(false); ret = proc_put("/proc/stb/video/videomode", modes[video_system],strlen(modes[video_system])); - hdmi_out(true); if (stopped) Start(); @@ -540,20 +528,9 @@ void cVideo::Standby(unsigned int bOn) if (bOn) { closeDevice(); - hdmi_out(false); } else { - /* only enable HDMI output when coming from standby, not on - * start. I have no idea why, but enabling it on startup leads - * to strange locking problems of the framebuffer driver :-( */ - if (!hdmi_enabled) - { - hdmi_out(true); - /* make sure the driver has time to settle. - * again - lame, but makes it work... */ - sleep(1); - } openDevice(); } video_standby = bOn; @@ -693,12 +670,6 @@ void cVideo::SetSyncMode(AVSYNC_TYPE mode) * { 1, LOCALE_OPTIONS_ON }, * { 2, LOCALE_AUDIOMENU_AVSYNC_AM } */ - const char *apply[] = { "disapply", "apply" }; - const char *clock[] = { "video", "audio" }; - const char *a = apply[mode > 0]; /* mode == 1 or mode == 2 -> "apply" */ - const char *c = clock[mode > 1]; /* mode == 2 -> "audio" */ - proc_put("/proc/stb/stream/policy/AV_SYNC", a, strlen(a)); - proc_put("/proc/stb/stream/policy/MASTER_CLOCK", c, strlen(c)); }; int cVideo::SetStreamType(VIDEO_FORMAT type) diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index a539419..3dae3eb 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -144,7 +144,6 @@ class cVideo video_play_state_t playstate; int /*vidDispMode_t*/ croppingMode; int /*vidOutFmt_t*/ outputformat; - int scartvoltage; VIDEO_FORMAT StreamType; VIDEO_DEFINITION VideoDefinition; @@ -155,14 +154,20 @@ class cVideo DISPLAY_AR PictureAR; VIDEO_FRAME_RATE FrameRate; int video_standby; + int brightness; + int contrast; + int saturation; + int hue; + + /* used internally by dmx */ int64_t GetPTS(void); - int brightness, contrast, saturation, hue; public: /* constructor & destructor */ cVideo(int mode, void *, void *, unsigned int unit = 0); ~cVideo(void); + /* used internally by playback */ void openDevice(void); void closeDevice(void); From 0fc12438dbf4f108e36b4912c86cfa429ad6be2b Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sat, 7 Oct 2017 23:02:24 +0200 Subject: [PATCH 47/73] armbox: remove audiomixers --- libarmbox/Makefile.am | 1 - libarmbox/audio.cpp | 14 +++++++++----- libarmbox/audio_lib.h | 2 ++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libarmbox/Makefile.am b/libarmbox/Makefile.am index e3218f7..f39cd65 100644 --- a/libarmbox/Makefile.am +++ b/libarmbox/Makefile.am @@ -21,7 +21,6 @@ libarmbox_la_SOURCES = \ dmx.cpp \ video.cpp \ audio.cpp \ - audio_mixer.cpp \ init.cpp \ playback_gst.cpp \ pwrmngr.cpp \ diff --git a/libarmbox/audio.cpp b/libarmbox/audio.cpp index 9e5960b..3713be4 100644 --- a/libarmbox/audio.cpp +++ b/libarmbox/audio.cpp @@ -8,7 +8,7 @@ #include #include "audio_lib.h" -#include "audio_mixer.h" +//#include "audio_mixer.h" #include "lt_debug.h" #define AUDIO_DEVICE "/dev/dvb/adapter0/audio0" @@ -38,9 +38,11 @@ cAudio::cAudio(void *, void *, void *) clipfd = -1; mixer_fd = -1; +/* mixerAnalog = mixerHDMI = mixerSPDIF = NULL; volumeAnalog = volumeHDMI = volumeSPDIF = 0; - mixersMuted = false; + mixersMuted = false +*/ openDevice(); Muted = false; @@ -48,13 +50,13 @@ cAudio::cAudio(void *, void *, void *) cAudio::~cAudio(void) { - closeMixers(); + //closeMixers(); closeDevice(); } void cAudio::openDevice(void) { - openMixers(); + //openMixers(); if (fd < 0) { @@ -69,7 +71,7 @@ void cAudio::openDevice(void) void cAudio::closeDevice(void) { - closeMixers(); + //closeMixers(); if (fd > -1) { close(fd); @@ -425,6 +427,7 @@ void cAudio::setBypassMode(bool disable) lt_info("%s AUDIO_SET_BYPASS_MODE %d: %m\n", __func__, mode); } +#if 0 void cAudio::openMixers(void) { if (!mixerAnalog) @@ -476,3 +479,4 @@ void cAudio::muteMixers(bool m) setMixerVolume("SPDIF", volumeSPDIF, false); } } +#endif diff --git a/libarmbox/audio_lib.h b/libarmbox/audio_lib.h index 8a71732..5fb3e9c 100644 --- a/libarmbox/audio_lib.h +++ b/libarmbox/audio_lib.h @@ -100,10 +100,12 @@ class cAudio void ScheduleMute(bool On); void EnableAnalogOut(bool enable); +#if 0 void openMixers(void); void closeMixers(void); void setMixerVolume(const char *name, long value, bool remember = true); void muteMixers(bool m = true); +#endif }; #endif From c4d16f29c7512eacf028081c0cbbf584077c3e20 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sat, 7 Oct 2017 23:20:07 +0200 Subject: [PATCH 48/73] HMDI ac3 passthrough/downmix --- libarmbox/audio.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libarmbox/audio.cpp b/libarmbox/audio.cpp index 3713be4..bd3f71f 100644 --- a/libarmbox/audio.cpp +++ b/libarmbox/audio.cpp @@ -399,7 +399,9 @@ void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int void cAudio::SetHdmiDD(bool enable) { - lt_debug("%s\n", __FUNCTION__); + const char *opt[] = { "downmix", "passthrough" }; + lt_debug("%s %d\n", __func__, enable); + proc_put("/proc/stb/audio/ac3", opt[enable], strlen(opt[enable])); } void cAudio::SetSpdifDD(bool enable) From b0f09fd723a1d423546e3d5e68a095a2b390d6ae Mon Sep 17 00:00:00 2001 From: max_10 Date: Sun, 8 Oct 2017 01:08:53 +0200 Subject: [PATCH 49/73] armbox: modification GetVideoSystem --- libarmbox/video.cpp | 103 ++++++++++++++++++------------------------ libarmbox/video_lib.h | 9 +++- 2 files changed, 52 insertions(+), 60 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 74f07b0..a0412f1 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -112,6 +112,29 @@ static const char *VMPEG_framerate[] = { "/proc/stb/vmpeg/1/framerate" }; +static const char *vid_modes[] = { + "pal", // VIDEO_STD_NTSC + "pal", // VIDEO_STD_SECAM + "pal", // VIDEO_STD_PAL + "480p", // VIDEO_STD_480P + "576p50", // VIDEO_STD_576P + "720p60", // VIDEO_STD_720P60 + "1080i60", // VIDEO_STD_1080I60 + "720p50", // VIDEO_STD_720P50 + "1080i50", // VIDEO_STD_1080I50 + "1080p30", // VIDEO_STD_1080P30 + "1080p24", // VIDEO_STD_1080P24 + "1080p25", // VIDEO_STD_1080P25 + "1080p50", // VIDEO_STD_1080P50 + "1080p60", // VIDEO_STD_1080P60 + "1080p2397", // VIDEO_STD_1080P2397 + "1080p2997", // VIDEO_STD_1080P2997 + "2160p24", // VIDEO_STD_2160P24 + "2160p25", // VIDEO_STD_2160P25 + "2160p30", // VIDEO_STD_2160P30 + "2160p50", // VIDEO_STD_2160P50 + "720p50" // VIDEO_STD_AUTO +}; #define VIDEO_STREAMTYPE_MPEG2 0 #define VIDEO_STREAMTYPE_MPEG4_H264 1 @@ -291,72 +314,34 @@ int cVideo::setBlank(int) return Stop(1); } -int cVideo::GetVideoSystem() +int cVideo::GetVideoSystem(void) { - lt_debug("%s\n", __func__); char current[32]; - static const char *modes[] = { - "pal", // VIDEO_STD_NTSC - "pal", // VIDEO_STD_SECAM - "pal", // VIDEO_STD_PAL - "480p", // VIDEO_STD_480P - "576p50", // VIDEO_STD_576P - "720p60", // VIDEO_STD_720P60 - "1080i60", // VIDEO_STD_1080I60 - "720p50", // VIDEO_STD_720P50 - "1080i50", // VIDEO_STD_1080I50 - "1080p30", // VIDEO_STD_1080P30 - "1080p24", // VIDEO_STD_1080P24 - "1080p25", // VIDEO_STD_1080P25 - "1080p50", // VIDEO_STD_1080P50 - "1080p60", // VIDEO_STD_1080P60 - "1080p2397", // VIDEO_STD_1080P2397 - "1080p2997", // VIDEO_STD_1080P2997 - "2160p24", //VIDEO_STD_2160P24 - "2160p25", // VIDEO_STD_2160P25 - "2160p30", // VIDEO_STD_2160P30 - "2160p50", // VIDEO_STD_2160P50 - "720p50" // VIDEO_STD_AUTO - }; - - int ret = proc_get("/proc/stb/video/videomode", current, 32); - for (int i=0; i VIDEO_STD_1080P50) { + lt_info("%s: invalid system %d\n", __func__, system); + strcpy(format->format, "invalid"); + } else + strcpy(format->format, vid_modes[system]); } int cVideo::SetVideoSystem(int video_system, bool remember) { lt_debug("%s(%d, %d)\n", __func__, video_system, remember); char current[32]; - static const char *modes[] = { - "pal", // VIDEO_STD_NTSC - "pal", // VIDEO_STD_SECAM - "pal", // VIDEO_STD_PAL - "480p", // VIDEO_STD_480P - "576p50", // VIDEO_STD_576P - "720p60", // VIDEO_STD_720P60 - "1080i60", // VIDEO_STD_1080I60 - "720p50", // VIDEO_STD_720P50 - "1080i50", // VIDEO_STD_1080I50 - "1080p30", // VIDEO_STD_1080P30 - "1080p24", // VIDEO_STD_1080P24 - "1080p25", // VIDEO_STD_1080P25 - "1080p50", // VIDEO_STD_1080P50 - "1080p60", // VIDEO_STD_1080P60 - "1080p2397", // VIDEO_STD_1080P2397 - "1080p2997", // VIDEO_STD_1080P2997 - "2160p24", //VIDEO_STD_2160P24 - "2160p25", // VIDEO_STD_2160P25 - "2160p30", // VIDEO_STD_2160P30 - "2160p50", // VIDEO_STD_2160P50 - "720p50" // VIDEO_STD_AUTO - }; if (video_system > VIDEO_STD_MAX) { @@ -364,12 +349,12 @@ int cVideo::SetVideoSystem(int video_system, bool remember) return -1; } int ret = proc_get("/proc/stb/video/videomode", current, 32); - if (strcmp(current, modes[video_system]) == 0) + if (strcmp(current, vid_modes[video_system]) == 0) { lt_info("%s: video_system %d (%s) already set, skipping\n", __func__, video_system, current); return 0; } - lt_info("%s: old: '%s' new: '%s'\n", __func__, current, modes[video_system]); + lt_info("%s: old: '%s' new: '%s'\n", __func__, current, vid_modes[video_system]); bool stopped = false; if (playstate == VIDEO_PLAYING) { @@ -377,7 +362,7 @@ int cVideo::SetVideoSystem(int video_system, bool remember) Stop(); stopped = true; } - ret = proc_put("/proc/stb/video/videomode", modes[video_system],strlen(modes[video_system])); + ret = proc_put("/proc/stb/video/videomode", vid_modes[video_system],strlen(vid_modes[video_system])); if (stopped) Start(); diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index 3dae3eb..b2e579b 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -5,6 +5,11 @@ #include "../common/cs_types.h" #include "dmx_lib.h" +typedef struct cs_vs_format_t +{ + char format[16]; +} cs_vs_format_struct_t; + typedef enum { ANALOG_SD_RGB_CINCH = 0x00, ANALOG_SD_YPRPB_CINCH, @@ -195,7 +200,9 @@ class cVideo bool Pause(void); /* get video system infos */ - int GetVideoSystem(); + int GetVideoSystem(void); + /* when system = -1 then use current video system */ + void GetVideoSystemFormatName(cs_vs_format_t* format, int system); /* set video_system */ int SetVideoSystem(int video_system, bool remember = true); From a2fc1d51ee2bd5d66263aecdbf2936cf26e91f17 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 8 Oct 2017 13:14:30 +0200 Subject: [PATCH 50/73] Revert "libeplayer3: switch off the teletext sub" This reverts commit 1356d700be203d3107f32dafdf2c22e675898f09. --- libeplayer3/input.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libeplayer3/input.cpp b/libeplayer3/input.cpp index f4621f9..19af03e 100644 --- a/libeplayer3/input.cpp +++ b/libeplayer3/input.cpp @@ -80,7 +80,7 @@ extern void dvbsub_write(AVSubtitle *, int64_t); extern void dvbsub_ass_write(AVCodecContext *c, AVSubtitle *sub, int pid); extern void dvbsub_ass_clear(void); // from neutrino-mp/lib/lib/libtuxtxt/tuxtxt_common.h -//extern void teletext_write(int pid, uint8_t *data, int size); +extern void teletext_write(int pid, uint8_t *data, int size); static std::string lastlog_message; static unsigned int lastlog_repeats; @@ -253,11 +253,10 @@ bool Input::Play() } } } + } else if (_teletextTrack && (_teletextTrack->stream == stream)) { + if (packet.data && packet.size > 1) + teletext_write(_teletextTrack->pid, packet.data + 1, packet.size - 1); } -// else if (_teletextTrack && (_teletextTrack->stream == stream)) { -// if (packet.data && packet.size > 1) -// teletext_write(_teletextTrack->pid, packet.data + 1, packet.size - 1); -// } #if (LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR == 25) av_packet_unref(&packet); From efc486301f318e2066ab5fefe76827b5d2033c72 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Wed, 11 Oct 2017 20:42:05 +0200 Subject: [PATCH 51/73] armbox: enable DTS passthrough --- libarmbox/audio.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libarmbox/audio.cpp b/libarmbox/audio.cpp index 909b019..dc4238e 100644 --- a/libarmbox/audio.cpp +++ b/libarmbox/audio.cpp @@ -394,8 +394,10 @@ void cAudio::SetHdmiDD(bool enable) void cAudio::SetSpdifDD(bool enable) { + //using this function for dts passthrough + const char *opt[] = { "downmix", "passthrough" }; lt_debug("%s %d\n", __func__, enable); - setBypassMode(!enable); + proc_put("/proc/stb/audio/dts", opt[enable], strlen(opt[enable])); } void cAudio::ScheduleMute(bool On) From ba0766f0c010d37f8b372f40c8b3cb2864d6aba7 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 15 Oct 2017 12:23:46 +0200 Subject: [PATCH 52/73] fix gst playback --- libarmbox/playback_gst.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index 5e34d5c..079074e 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -77,6 +77,35 @@ gint match_sinktype(const GValue *velement, const gchar *type) return strcmp(g_type_name(G_OBJECT_TYPE(element)), type); } +void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer /*user_data*/) +{ + GstElement *source = NULL; + g_object_get(object, "source", &source, NULL); + + if (source) + { + if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "timeout") != 0) + { + GstElementFactory *factory = gst_element_get_factory(source); + if (factory) + { + const gchar *sourcename = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory)); + if (!strcmp(sourcename, "souphttpsrc")) + { + g_object_set(G_OBJECT(source), "timeout", HTTP_TIMEOUT, NULL); + } + } + } + + if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "ssl-strict") != 0) + { + g_object_set(G_OBJECT(source), "ssl-strict", FALSE, NULL); + } + + gst_object_unref(source); + } +} + GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) { gchar * sourceName; @@ -419,6 +448,8 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, if(isHTTP) { + g_signal_connect (G_OBJECT (m_gst_playbin), "notify::source", G_CALLBACK (playbinNotifySource), NULL); + // set buffer size g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL); g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL); From 8ad83136ce366d05117b8857549573226cdb7e86 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 15 Oct 2017 12:25:20 +0200 Subject: [PATCH 53/73] fix last commit --- libarmbox/playback_gst.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index 079074e..4108a39 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -401,6 +401,10 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, { isHTTP = true; } + else if(!strncmp("https://", filename, 8)) + { + isHTTP = true; + } else if(!strncmp("file://", filename, 7)) { isHTTP = false; From baf59692c62dabfd81465eb323276cc0a87ea6b4 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 15 Oct 2017 12:26:54 +0200 Subject: [PATCH 54/73] fix last commit --- libarmbox/playback_gst.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index 4108a39..7322b9c 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -70,6 +70,7 @@ GstElement * videoSink = NULL; gchar * uri = NULL; GstTagList * m_stream_tags = 0; static int end_eof = 0; +#define HTTP_TIMEOUT 30 gint match_sinktype(const GValue *velement, const gchar *type) { From 6dcf797dba895e42331fab03401216312b375fb4 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 15 Oct 2017 15:10:18 +0200 Subject: [PATCH 55/73] armbox: fix gst seeking --- libarmbox/playback_gst.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index 7322b9c..daebed9 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -555,7 +555,7 @@ void cPlayback::trickSeek(int ratio) if( GetPosition(position, duration) ) { validposition = true; - pos = position; + pos = position*1000000; } gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); @@ -693,10 +693,14 @@ bool cPlayback::SetPosition(int position, bool absolute) if(m_gst_playbin) { - gst_element_query_position(m_gst_playbin, fmt, &pos); - time_nanoseconds = pos + (position * 1000000.0); - if(time_nanoseconds < 0) - time_nanoseconds = 0; + if (!absolute) { + gst_element_query_position(m_gst_playbin, fmt, &pos); + time_nanoseconds = pos + (position * 1000000.0); + if(time_nanoseconds < 0) + time_nanoseconds = 0; + } else { + time_nanoseconds = position * 1000000.0; + } gst_element_seek(m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); } @@ -867,7 +871,7 @@ uint64_t cPlayback::GetReadCount() int cPlayback::GetAPid(void) { lt_info("%s\n", __func__); - return 0; + return mAudioStream; } int cPlayback::GetVPid(void) From fec61c7e1c0c143ca6fb9afbd672b7215d548394 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 15 Oct 2017 16:06:48 +0200 Subject: [PATCH 56/73] armbox: gst-playback reformat code --- libarmbox/playback_gst.cpp | 547 +++++++++++++++++++------------------ libarmbox/playback_gst.h | 92 ++++--- 2 files changed, 323 insertions(+), 316 deletions(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index daebed9..1fb77dc 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -110,184 +110,186 @@ void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer /*user_da GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) { gchar * sourceName; - + // source GstObject * source; source = GST_MESSAGE_SRC(msg); - + if (!GST_IS_OBJECT(source)) return GST_BUS_DROP; - + sourceName = gst_object_get_name(source); - switch (GST_MESSAGE_TYPE(msg)) + switch (GST_MESSAGE_TYPE(msg)) { - case GST_MESSAGE_EOS: - { - g_message("End-of-stream"); - end_eof = 1; - break; - } - - case GST_MESSAGE_ERROR: - { - gchar * debug; - GError *err; - gst_message_parse_error(msg, &err, &debug); - g_free (debug); - lt_info_c( "%s:%s - GST_MESSAGE_ERROR: %s (%i) from %s\n", FILENAME, __FUNCTION__, err->message, err->code, sourceName ); - if ( err->domain == GST_STREAM_ERROR ) - { - if ( err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND ) - { - if ( g_strrstr(sourceName, "videosink") ) - lt_info_c( "%s:%s - GST_MESSAGE_ERROR: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? - else if ( g_strrstr(sourceName, "audiosink") ) - lt_info_c( "%s:%s - GST_MESSAGE_ERROR: audioSink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? - } - } - g_error_free(err); + case GST_MESSAGE_EOS: + { + g_message("End-of-stream"); + end_eof = 1; + break; + } - end_eof = 1; // NOTE: just to exit - - break; - } - - case GST_MESSAGE_INFO: + case GST_MESSAGE_ERROR: + { + gchar * debug; + GError *err; + gst_message_parse_error(msg, &err, &debug); + g_free (debug); + lt_info_c( "%s:%s - GST_MESSAGE_ERROR: %s (%i) from %s\n", FILENAME, __FUNCTION__, err->message, err->code, sourceName ); + if ( err->domain == GST_STREAM_ERROR ) { - gchar *debug; - GError *inf; - - gst_message_parse_info (msg, &inf, &debug); - g_free (debug); - if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE ) + if ( err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND ) { if ( g_strrstr(sourceName, "videosink") ) - lt_info_c( "%s:%s - GST_MESSAGE_INFO: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? + lt_info_c( "%s:%s - GST_MESSAGE_ERROR: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? + else if ( g_strrstr(sourceName, "audiosink") ) + lt_info_c( "%s:%s - GST_MESSAGE_ERROR: audioSink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? } - g_error_free(inf); - break; } - - case GST_MESSAGE_TAG: + g_error_free(err); + + end_eof = 1; // NOTE: just to exit + + break; + } + + case GST_MESSAGE_INFO: + { + gchar *debug; + GError *inf; + + gst_message_parse_info (msg, &inf, &debug); + g_free (debug); + if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE ) { - GstTagList *tags, *result; - gst_message_parse_tag(msg, &tags); - - result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE); - if (result) - { - if (m_stream_tags) - gst_tag_list_free(m_stream_tags); - m_stream_tags = result; - } - - const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0); - if ( gv_image ) - { - GstBuffer *buf_image; - buf_image = gst_value_get_buffer (gv_image); - int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644); - if(fd >= 0) - { - GstMapInfo Info; - gst_buffer_map(buf_image, &Info,(GstMapFlags)( GST_MAP_READ)); - int ret = write(fd, Info.data, Info.size); - close(fd); - gst_buffer_unmap(buf_image, &Info); - lt_info_c( "%s:%s - GST_MESSAGE_INFO: cPlayback::state /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__ , ret); - } - //FIXME: how shall playback handle this event??? - } - gst_tag_list_free(tags); - lt_debug_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event??? - break; + if ( g_strrstr(sourceName, "videosink") ) + lt_info_c( "%s:%s - GST_MESSAGE_INFO: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? } - - case GST_MESSAGE_STATE_CHANGED: + g_error_free(inf); + break; + } + + case GST_MESSAGE_TAG: + { + GstTagList *tags, *result; + gst_message_parse_tag(msg, &tags); + + result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE); + if (result) { - if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) - break; + if (m_stream_tags) + gst_tag_list_free(m_stream_tags); + m_stream_tags = result; + } - GstState old_state, new_state; - gst_message_parse_state_changed(msg, &old_state, &new_state, NULL); - - if(old_state == new_state) - break; - lt_info_c( "%s:%s - GST_MESSAGE_STATE_CHANGED: state transition %s -> %s\n", FILENAME, __FUNCTION__, gst_element_state_get_name(old_state), gst_element_state_get_name(new_state)); - - GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state); - - switch(transition) + const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0); + if ( gv_image ) + { + GstBuffer *buf_image; + buf_image = gst_value_get_buffer (gv_image); + int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644); + if(fd >= 0) { - case GST_STATE_CHANGE_NULL_TO_READY: - { - } break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - { - GstIterator *children; - GValue r = { 0, }; - - if (audioSink) - { - gst_object_unref(GST_OBJECT(audioSink)); - audioSink = NULL; - } - - if (videoSink) - { - gst_object_unref(GST_OBJECT(videoSink)); - videoSink = NULL; - } - children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); - - if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink")) - { - audioSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); - g_value_unset (&r); - lt_info_c( "%s %s - audio sink created\n", FILENAME, __FUNCTION__); - } - - gst_iterator_free(children); - children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); - - if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink")) - { - videoSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); - g_value_unset (&r); - lt_info_c( "%s %s - video sink created\n", FILENAME, __FUNCTION__); - } - gst_iterator_free(children); - - } break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - { - } break; - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - { - } break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - { - if (audioSink) - { - gst_object_unref(GST_OBJECT(audioSink)); - audioSink = NULL; - } - if (videoSink) - { - gst_object_unref(GST_OBJECT(videoSink)); - videoSink = NULL; - } - } break; - case GST_STATE_CHANGE_READY_TO_NULL: - { - } break; + GstMapInfo Info; + gst_buffer_map(buf_image, &Info,(GstMapFlags)( GST_MAP_READ)); + int ret = write(fd, Info.data, Info.size); + close(fd); + gst_buffer_unmap(buf_image, &Info); + lt_info_c( "%s:%s - GST_MESSAGE_INFO: cPlayback::state /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__, ret); } + //FIXME: how shall playback handle this event??? + } + gst_tag_list_free(tags); + lt_debug_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event??? + break; + } + + case GST_MESSAGE_STATE_CHANGED: + { + if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) break; + + GstState old_state, new_state; + gst_message_parse_state_changed(msg, &old_state, &new_state, NULL); + + if(old_state == new_state) + break; + lt_info_c( "%s:%s - GST_MESSAGE_STATE_CHANGED: state transition %s -> %s\n", FILENAME, __FUNCTION__, gst_element_state_get_name(old_state), gst_element_state_get_name(new_state)); + + GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state); + + switch(transition) + { + case GST_STATE_CHANGE_NULL_TO_READY: + { + } break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + { + GstIterator *children; + GValue r = { 0, }; + + if (audioSink) + { + gst_object_unref(GST_OBJECT(audioSink)); + audioSink = NULL; + } + + if (videoSink) + { + gst_object_unref(GST_OBJECT(videoSink)); + videoSink = NULL; + } + children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); + + if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink")) + { + audioSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); + g_value_unset (&r); + lt_info_c( "%s %s - audio sink created\n", FILENAME, __FUNCTION__); + } + + gst_iterator_free(children); + children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); + + if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink")) + { + videoSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); + g_value_unset (&r); + lt_info_c( "%s %s - video sink created\n", FILENAME, __FUNCTION__); + } + gst_iterator_free(children); + } break; - default: - break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + { + } break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + { + } break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + { + if (audioSink) + { + gst_object_unref(GST_OBJECT(audioSink)); + audioSink = NULL; + } + if (videoSink) + { + gst_object_unref(GST_OBJECT(videoSink)); + videoSink = NULL; + } + } + break; + case GST_STATE_CHANGE_READY_TO_NULL: + { + } break; + } + break; + } + break; + default: + break; } return GST_BUS_DROP; @@ -295,25 +297,25 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) cPlayback::cPlayback(int num) -{ +{ lt_info( "%s:%s\n", FILENAME, __FUNCTION__); - const gchar *nano_str; - guint major, minor, micro, nano; + const gchar *nano_str; + guint major, minor, micro, nano; gst_init(NULL, NULL); gst_version (&major, &minor, µ, &nano); - if (nano == 1) - nano_str = "(CVS)"; - else if (nano == 2) - nano_str = "(Prerelease)"; + if (nano == 1) + nano_str = "(CVS)"; + else if (nano == 2) + nano_str = "(Prerelease)"; else - nano_str = ""; + nano_str = ""; - lt_info( "%s:%s - This program is linked against GStreamer %d.%d.%d %s\n", - FILENAME, __FUNCTION__, - major, minor, micro, nano_str); + lt_info( "%s:%s - This program is linked against GStreamer %d.%d.%d %s\n", + FILENAME, __FUNCTION__, + major, minor, micro, nano_str); mAudioStream = 0; mSpeed = 0; @@ -323,7 +325,7 @@ cPlayback::cPlayback(int num) } cPlayback::~cPlayback() -{ +{ lt_info( "%s:%s\n", FILENAME, __FUNCTION__); //FIXME: all deleting stuff is done in Close() } @@ -337,11 +339,11 @@ bool cPlayback::Open(playmode_t PlayMode) // used by movieplay void cPlayback::Close(void) -{ +{ lt_info( "%s:%s\n", FILENAME, __FUNCTION__); Stop(); - + // disconnect bus handler if (m_gst_playbin) { @@ -351,7 +353,7 @@ void cPlayback::Close(void) gst_object_unref(bus); lt_info( "%s:%s - GST bus handler closed\n", FILENAME, __FUNCTION__); } - + if (m_stream_tags) gst_tag_list_free(m_stream_tags); @@ -362,22 +364,22 @@ void cPlayback::Close(void) { gst_object_unref(GST_OBJECT(audioSink)); audioSink = NULL; - + lt_info( "%s:%s - GST audio Sink closed\n", FILENAME, __FUNCTION__); } - + if (videoSink) { gst_object_unref(GST_OBJECT(videoSink)); videoSink = NULL; - + lt_info( "%s:%s - GST video Sink closed\n", FILENAME, __FUNCTION__); } - + // unref m_gst_playbin gst_object_unref (GST_OBJECT (m_gst_playbin)); lt_info( "%s:%s - GST playbin closed\n", FILENAME, __FUNCTION__); - + m_gst_playbin = NULL; } } @@ -393,7 +395,7 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, lt_info( "%s:%s\n", FILENAME, __FUNCTION__); mAudioStream = 0; - + //create playback path char file[400] = {""}; bool isHTTP = false; @@ -427,19 +429,19 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, isHTTP = true; } else - strcat(file, "file://"); - + strcat(file, "file://"); + strcat(file, filename); - + if (isHTTP) uri = g_uri_escape_string(filename, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS, true); else uri = g_filename_to_uri(filename, NULL, NULL); - + lt_info("%s:%s - filename=%s\n", FILENAME, __FUNCTION__, filename); guint flags = GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | \ - GST_PLAY_FLAG_TEXT | GST_PLAY_FLAG_NATIVE_VIDEO; + GST_PLAY_FLAG_TEXT | GST_PLAY_FLAG_NATIVE_VIDEO; /* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */ int m_buffer_size = 5*1024*1024; @@ -451,28 +453,28 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, { lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__); - if(isHTTP) + if(isHTTP) { g_signal_connect (G_OBJECT (m_gst_playbin), "notify::source", G_CALLBACK (playbinNotifySource), NULL); - // set buffer size - g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL); - g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL); - flags |= GST_PLAY_FLAG_BUFFERING; - } + // set buffer size + g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL); + g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL); + flags |= GST_PLAY_FLAG_BUFFERING; + } - g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL); + g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL); g_object_set(G_OBJECT (m_gst_playbin), "uri", uri, NULL); - + //gstbus handler GstBus * bus = gst_pipeline_get_bus( GST_PIPELINE(m_gst_playbin) ); gst_bus_set_sync_handler(bus, Gst_bus_call, NULL, NULL); - gst_object_unref(bus); - + gst_object_unref(bus); + // state playing gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING); - + playing = true; playstate = STATE_PLAY; } @@ -480,26 +482,26 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, { lt_info("%s:%s - failed to create GStreamer pipeline!, sorry we can not play\n", FILENAME, __FUNCTION__); playing = false; - + return false; } - - g_free(uri); - + + g_free(uri); + return true; } bool cPlayback::Play(void) { - lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); - if(playing == true) + if(playing == true) return true; - + if(m_gst_playbin) { gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING); - + playing = true; playstate = STATE_PLAY; } @@ -509,11 +511,11 @@ bool cPlayback::Play(void) } bool cPlayback::Stop(void) -{ - if(playing == false) +{ + if(playing == false) return false; lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); - + // stop if(m_gst_playbin) { @@ -521,20 +523,20 @@ bool cPlayback::Stop(void) } playing = false; - + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); - + playstate = STATE_STOP; return true; } -bool cPlayback::SetAPid(int pid , bool /*ac3*/) +bool cPlayback::SetAPid(int pid, bool /*ac3*/) { lt_info("%s: pid %i\n", __func__, pid); - + int current_audio; - + if(pid != mAudioStream) { g_object_set (G_OBJECT (m_gst_playbin), "current-audio", pid, NULL); @@ -551,7 +553,7 @@ void cPlayback::trickSeek(int ratio) gint64 pos = 0; int position; int duration; - + if( GetPosition(position, duration) ) { validposition = true; @@ -559,7 +561,7 @@ void cPlayback::trickSeek(int ratio) } gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); - + if (validposition) { if(ratio >= 0.0) @@ -570,14 +572,14 @@ void cPlayback::trickSeek(int ratio) } bool cPlayback::SetSpeed(int speed) -{ - lt_info( "%s:%s speed %d\n", FILENAME, __FUNCTION__, speed); +{ + lt_info( "%s:%s speed %d\n", FILENAME, __FUNCTION__, speed); - if(playing == false) + if(playing == false) return false; if(m_gst_playbin) - { + { // pause if(speed == 0) { @@ -615,10 +617,10 @@ bool cPlayback::SetSpeed(int speed) } bool cPlayback::SetSlow(int slow) -{ - lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); +{ + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); - if(playing == false) + if(playing == false) return false; if(m_gst_playbin) @@ -643,8 +645,8 @@ bool cPlayback::GetSpeed(int &speed) const // in milliseconds bool cPlayback::GetPosition(int &position, int &duration) { - if(playing == false) - return false; + if(playing == false) + return false; //EOF if(end_eof) @@ -652,18 +654,18 @@ bool cPlayback::GetPosition(int &position, int &duration) end_eof = 0; return false; } - + if(m_gst_playbin) { //position GstFormat fmt = GST_FORMAT_TIME; //Returns time in nanosecs - + gint64 pts = 0; unsigned long long int sec = 0; - + gst_element_query_position(m_gst_playbin, fmt, &pts); position = pts / 1000000.0; - + // duration GstFormat fmt_d = GST_FORMAT_TIME; //Returns time in nanosecs double length = 0; @@ -671,37 +673,40 @@ bool cPlayback::GetPosition(int &position, int &duration) gst_element_query_duration(m_gst_playbin, fmt_d, &len); length = len / 1000000.0; - if(length < 0) + if(length < 0) length = 0; - + duration = (int)(length); } - + return true; } bool cPlayback::SetPosition(int position, bool absolute) { lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing); - - if(playing == false) + + if(playing == false) return false; - + gint64 time_nanoseconds; gint64 pos; GstFormat fmt = GST_FORMAT_TIME; - + if(m_gst_playbin) { - if (!absolute) { + if (!absolute) + { gst_element_query_position(m_gst_playbin, fmt, &pos); time_nanoseconds = pos + (position * 1000000.0); - if(time_nanoseconds < 0) + if(time_nanoseconds < 0) time_nanoseconds = 0; - } else { + } + else + { time_nanoseconds = position * 1000000.0; } - + gst_element_seek(m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); } @@ -709,72 +714,72 @@ bool cPlayback::SetPosition(int position, bool absolute) } void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string * language) -{ +{ lt_info( "%s:%s\n", FILENAME, __FUNCTION__); if(m_gst_playbin) { gint i, n_audio = 0; //GstStructure * structure = NULL; - + // get audio g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL); printf("%s: %d audio\n", __FUNCTION__, n_audio); - + if(n_audio == 0) return; - + for (i = 0; i < n_audio; i++) { // apids apids[i]=i; - + GstPad * pad = 0; g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad); GstCaps * caps = gst_pad_get_current_caps(pad); if (!caps) continue; - + GstStructure * structure = gst_caps_get_structure(caps, 0); //const gchar *g_type = gst_structure_get_name(structure); - + //if (!structure) - //return atUnknown; + //return atUnknown; //ac3flags[0] = 0; // ac3flags if ( gst_structure_has_name (structure, "audio/mpeg")) { gint mpegversion, layer = -1; - + if (!gst_structure_get_int (structure, "mpegversion", &mpegversion)) //return atUnknown; ac3flags[i] = 0; - switch (mpegversion) + switch (mpegversion) { - case 1: - /* - { - gst_structure_get_int (structure, "layer", &layer); - if ( layer == 3 ) - return atMP3; - else - return atMPEG; - ac3flags[0] = 4; - break; - } - */ - ac3flags[i] = 4; - case 2: - //return atAAC; - ac3flags[i] = 5; - case 4: - //return atAAC; - ac3flags[i] = 5; - default: - //return atUnknown; - ac3flags[i] = 0; + case 1: + /* + { + gst_structure_get_int (structure, "layer", &layer); + if ( layer == 3 ) + return atMP3; + else + return atMPEG; + ac3flags[0] = 4; + break; + } + */ + ac3flags[i] = 4; + case 2: + //return atAAC; + ac3flags[i] = 5; + case 4: + //return atAAC; + ac3flags[i] = 5; + default: + //return atUnknown; + ac3flags[i] = 0; } } else if ( gst_structure_has_name (structure, "audio/x-ac3") || gst_structure_has_name (structure, "audio/ac3") ) @@ -786,10 +791,10 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu else if ( gst_structure_has_name (structure, "audio/x-raw-int") ) //return atPCM; ac3flags[i] = 0; - + gst_caps_unref(caps); } - + // numpids *numpida=i; } @@ -797,15 +802,15 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu void cPlayback::getMeta() { - if(playing) + if(playing) return; } bool cPlayback::SyncAV(void) { - lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); + lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing); - if(playing == false ) + if(playing == false ) return false; return true; diff --git a/libarmbox/playback_gst.h b/libarmbox/playback_gst.h index 25331bd..8b2d554 100644 --- a/libarmbox/playback_gst.h +++ b/libarmbox/playback_gst.h @@ -26,7 +26,8 @@ #include -typedef enum { +typedef enum +{ STATE_STOP, STATE_PLAY, STATE_PAUSE, @@ -35,7 +36,8 @@ typedef enum { STATE_SLOW } playstate_t; -typedef enum { +typedef enum +{ PLAYMODE_TS = 0, PLAYMODE_FILE, } playmode_t; @@ -44,53 +46,53 @@ struct AVFormatContext; class cPlayback { - private: - bool playing; +private: + bool playing; - int mSpeed; - int mAudioStream; + int mSpeed; + int mAudioStream; - public: - playstate_t playstate; - - cPlayback(int); - bool Open(playmode_t PlayMode); - void Close(void); - bool Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = ""); - bool Start(std::string filename, std::string headers = ""); - bool Play(void); - bool SyncAV(void); - - bool Stop(void); - bool SetAPid(int pid, bool ac3); - bool SetSubtitlePid(int pid); - bool SetTeletextPid(int pid); +public: + playstate_t playstate; - void trickSeek(int ratio); - bool SetSpeed(int speed); - bool SetSlow(int slow); - bool GetSpeed(int &speed) const; - bool GetPosition(int &position, int &duration); - void GetPts(uint64_t &pts); - int GetAPid(void); - int GetVPid(void); - int GetSubtitlePid(void); - bool SetPosition(int position, bool absolute = false); - void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language); - void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language); - void FindAllTeletextsubtitlePids(int *pids, unsigned int *numpidt, std::string *tlanguage, int *mags, int *pages); - void RequestAbort(void); - void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language); - bool SelectSubtitles(int pid); - uint64_t GetReadCount(void); - void GetChapters(std::vector &positions, std::vector &titles); - void GetMetadata(std::vector &keys, std::vector &values); - AVFormatContext *GetAVFormatContext(); - void ReleaseAVFormatContext(); + cPlayback(int); + bool Open(playmode_t PlayMode); + void Close(void); + bool Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = ""); + bool Start(std::string filename, std::string headers = ""); + bool Play(void); + bool SyncAV(void); - // - ~cPlayback(); - void getMeta(); + bool Stop(void); + bool SetAPid(int pid, bool ac3); + bool SetSubtitlePid(int pid); + bool SetTeletextPid(int pid); + + void trickSeek(int ratio); + bool SetSpeed(int speed); + bool SetSlow(int slow); + bool GetSpeed(int &speed) const; + bool GetPosition(int &position, int &duration); + void GetPts(uint64_t &pts); + int GetAPid(void); + int GetVPid(void); + int GetSubtitlePid(void); + bool SetPosition(int position, bool absolute = false); + void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language); + void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language); + void FindAllTeletextsubtitlePids(int *pids, unsigned int *numpidt, std::string *tlanguage, int *mags, int *pages); + void RequestAbort(void); + void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language); + bool SelectSubtitles(int pid); + uint64_t GetReadCount(void); + void GetChapters(std::vector &positions, std::vector &titles); + void GetMetadata(std::vector &keys, std::vector &values); + AVFormatContext *GetAVFormatContext(); + void ReleaseAVFormatContext(); + + // + ~cPlayback(); + void getMeta(); }; #endif From 73a12abdb86956aad77826ca16ae9cd13973ec1d Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 15 Oct 2017 16:55:19 +0200 Subject: [PATCH 57/73] armbox: adding header and user_agent to gst playback --- libarmbox/playback_gst.cpp | 62 +++++++++++++++++++++++++++++++++++--- libarmbox/playback_gst.h | 2 ++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index 1fb77dc..70ee4ef 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -78,9 +78,10 @@ gint match_sinktype(const GValue *velement, const gchar *type) return strcmp(g_type_name(G_OBJECT_TYPE(element)), type); } -void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer /*user_data*/) +void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer user_data) { GstElement *source = NULL; + cPlayback *_this = (cPlayback*)user_data; g_object_get(object, "source", &source, NULL); if (source) @@ -97,12 +98,60 @@ void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer /*user_da } } } - if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "ssl-strict") != 0) { g_object_set(G_OBJECT(source), "ssl-strict", FALSE, NULL); } - + if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "user-agent") != 0 && !_this->user_agent.empty()) + { + g_object_set(G_OBJECT(source), "user-agent", _this->user_agent.c_str(), NULL); + } + if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "extra-headers") != 0 && !_this->extra_headers.empty()) + { + GstStructure *extras = gst_structure_new_empty("extras"); + size_t pos = 0; + while (pos != std::string::npos) + { + std::string name, value; + size_t start = pos; + size_t len = std::string::npos; + pos = _this->extra_headers.find('=', pos); + if (pos != std::string::npos) + { + len = pos - start; + pos++; + name = _this->extra_headers.substr(start, len); + start = pos; + len = std::string::npos; + pos = _this->extra_headers.find('&', pos); + if (pos != std::string::npos) + { + len = pos - start; + pos++; + } + value = _this->extra_headers.substr(start, len); + } + if (!name.empty() && !value.empty()) + { + GValue header; + lt_info_c( "%s:%s setting extra-header '%s:%s'\n", FILENAME, __FUNCTION__, name.c_str(), value.c_str()); + memset(&header, 0, sizeof(GValue)); + g_value_init(&header, G_TYPE_STRING); + g_value_set_string(&header, value.c_str()); + gst_structure_set_value(extras, name.c_str(), &header); + } + else + { + lt_info_c( "%s:%s Invalid header format %s\n", FILENAME, __FUNCTION__, _this->extra_headers.c_str()); + break; + } + } + if (gst_structure_n_fields(extras) > 0) + { + g_object_set(G_OBJECT(source), "extra-headers", extras, NULL); + } + gst_structure_free(extras); + } gst_object_unref(source); } } @@ -394,6 +443,11 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, { lt_info( "%s:%s\n", FILENAME, __FUNCTION__); + if (!headers.empty()) + extra_headers = headers; + else + extra_headers.clear(); + mAudioStream = 0; //create playback path @@ -455,7 +509,7 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, if(isHTTP) { - g_signal_connect (G_OBJECT (m_gst_playbin), "notify::source", G_CALLBACK (playbinNotifySource), NULL); + g_signal_connect (G_OBJECT (m_gst_playbin), "notify::source", G_CALLBACK (playbinNotifySource), this); // set buffer size g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL); diff --git a/libarmbox/playback_gst.h b/libarmbox/playback_gst.h index 8b2d554..5dfcbfc 100644 --- a/libarmbox/playback_gst.h +++ b/libarmbox/playback_gst.h @@ -89,6 +89,8 @@ public: void GetMetadata(std::vector &keys, std::vector &values); AVFormatContext *GetAVFormatContext(); void ReleaseAVFormatContext(); + std::string extra_headers; + std::string user_agent; // ~cPlayback(); From ec61bd0a3e05330359dc15f8c3ed874851236128 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 15 Oct 2017 17:25:04 +0200 Subject: [PATCH 58/73] armbox: let gst playback handle devices --- libarmbox/playback_gst.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index 70ee4ef..0956eee 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -43,6 +43,10 @@ #define lt_info_c(args...) _lt_info(HAL_DEBUG_PLAYBACK, NULL, args) static const char * FILENAME = "[playback.cpp]"; +extern cVideo * videoDecoder; +extern cAudio * audioDecoder; +extern cDemux * audioDemux; +extern cDemux * videoDemux; #include #include @@ -430,7 +434,14 @@ void cPlayback::Close(void) lt_info( "%s:%s - GST playbin closed\n", FILENAME, __FUNCTION__); m_gst_playbin = NULL; + + videoDecoder->openDevice(); + audioDecoder->openDevice(); + + videoDemux->Start(); + audioDemux->Start(); } + } // start @@ -505,6 +516,13 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, if(m_gst_playbin) { + + videoDemux->Stop(); + audioDemux->Stop(); + + videoDecoder->closeDevice(); + audioDecoder->closeDevice(); + lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__); if(isHTTP) From 6268ebdb1b55bcead5bc85491215fd93299380d6 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 15 Oct 2017 18:06:43 +0200 Subject: [PATCH 59/73] partly revert last commit --- libarmbox/playback_gst.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index 0956eee..84baf20 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -438,8 +438,8 @@ void cPlayback::Close(void) videoDecoder->openDevice(); audioDecoder->openDevice(); - videoDemux->Start(); - audioDemux->Start(); + //videoDemux->Start(); + //audioDemux->Start(); } } @@ -517,8 +517,8 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, if(m_gst_playbin) { - videoDemux->Stop(); - audioDemux->Stop(); + //videoDemux->Stop(); + //audioDemux->Stop(); videoDecoder->closeDevice(); audioDecoder->closeDevice(); From a3ecb31bc9dced1980edeb67a155b36c3b6af795 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Tue, 17 Oct 2017 18:00:36 +0200 Subject: [PATCH 60/73] armbox: start implementing cec support --- libarmbox/video.cpp | 192 ++++++++++++++++++++++++++++++++++++++++++ libarmbox/video_lib.h | 27 +++++- 2 files changed, 216 insertions(+), 3 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index a0412f1..0afd139 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -36,6 +36,7 @@ #include #include "video_lib.h" #include "lt_debug.h" +#include "linux-uapi-cec.h" #include @@ -160,6 +161,7 @@ cVideo::cVideo(int, void *, void *, unsigned int unit) } else devnum = unit; fd = -1; + standby_cec_activ = autoview_cec_activ = false; openDevice(); } @@ -519,6 +521,7 @@ void cVideo::Standby(unsigned int bOn) openDevice(); } video_standby = bOn; + SetCECState(video_standby); } int cVideo::getBlank(void) @@ -773,3 +776,192 @@ bool cVideo::GetScreenImage(unsigned char * &video, int &xres, int &yres, bool g return true; } + +bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) +{ + physicalAddress[0] = 0x10; + physicalAddress[1] = 0x00; + logicalAddress = 1; + deviceType = 1; /* default: recorder */ + + hdmiFd = open("/dev/cec0", O_RDWR | O_CLOEXEC); + if (hdmiFd >= 0) + { + __u32 monitor = CEC_MODE_INITIATOR | CEC_MODE_FOLLOWER; + struct cec_caps caps = {}; + + if (ioctl(hdmiFd, CEC_ADAP_G_CAPS, &caps) < 0) + lt_info("%s: CEC get caps failed (%m)\n", __func__); + + if (caps.capabilities & CEC_CAP_LOG_ADDRS) + { + struct cec_log_addrs laddrs = {}; + + if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0) + lt_info("%s: CEC reset log addr failed (%m)\n", __func__); + + memset(&laddrs, 0, sizeof(laddrs)); + + /* + * NOTE: cec_version, osd_name and deviceType should be made configurable, + * CEC_ADAP_S_LOG_ADDRS delayed till the desired values are available + * (saves us some startup speed as well, polling for a free logical address + * takes some time) + */ + laddrs.cec_version = CEC_OP_CEC_VERSION_2_0; + strcpy(laddrs.osd_name, "neutrino"); + laddrs.vendor_id = CEC_VENDOR_ID_NONE; + + switch (deviceType) + { + case CEC_LOG_ADDR_TV: + laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TV; + laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TV; + laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TV; + break; + case CEC_LOG_ADDR_RECORD_1: + laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_RECORD; + laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_RECORD; + laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_RECORD; + break; + case CEC_LOG_ADDR_TUNER_1: + laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TUNER; + laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TUNER; + laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TUNER; + break; + case CEC_LOG_ADDR_PLAYBACK_1: + laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_PLAYBACK; + laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_PLAYBACK; + laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_PLAYBACK; + break; + case CEC_LOG_ADDR_AUDIOSYSTEM: + laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM; + laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM; + laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM; + break; + default: + laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_UNREGISTERED; + laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_SWITCH; + laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_SWITCH; + break; + } + laddrs.num_log_addrs++; + + if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0) + lt_info("%s: CEC set log addr failed (%m)\n", __func__); + } + + if (ioctl(hdmiFd, CEC_S_MODE, &monitor) < 0) + lt_info("%s: CEC monitor failed (%m)\n", __func__); + + } + + getCECAddressInfo(); + +} + +void cVideo::getCECAddressInfo() +{ + if (hdmiFd >= 0) + { + bool hasdata = false; + struct addressinfo addressinfo; + + __u16 phys_addr; + struct cec_log_addrs laddrs = {}; + + ::ioctl(hdmiFd, CEC_ADAP_G_PHYS_ADDR, &phys_addr); + addressinfo.physical[0] = (phys_addr >> 8) & 0xff; + addressinfo.physical[1] = phys_addr & 0xff; + + ::ioctl(hdmiFd, CEC_ADAP_G_LOG_ADDRS, &laddrs); + addressinfo.logical = laddrs.log_addr[0]; + + switch (laddrs.log_addr_type[0]) + { + case CEC_LOG_ADDR_TYPE_TV: + addressinfo.type = CEC_LOG_ADDR_TV; + break; + case CEC_LOG_ADDR_TYPE_RECORD: + addressinfo.type = CEC_LOG_ADDR_RECORD_1; + break; + case CEC_LOG_ADDR_TYPE_TUNER: + addressinfo.type = CEC_LOG_ADDR_TUNER_1; + break; + case CEC_LOG_ADDR_TYPE_PLAYBACK: + addressinfo.type = CEC_LOG_ADDR_PLAYBACK_1; + break; + case CEC_LOG_ADDR_TYPE_AUDIOSYSTEM: + addressinfo.type = CEC_LOG_ADDR_AUDIOSYSTEM; + break; + case CEC_LOG_ADDR_TYPE_UNREGISTERED: + default: + addressinfo.type = CEC_LOG_ADDR_UNREGISTERED; + break; + } + hasdata = true; + + if (hasdata) + { + deviceType = addressinfo.type; + logicalAddress = addressinfo.logical; + if (!fixedAddress) + { + if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress))) + { + lt_info("%s: detected physical address change: %02X%02X --> %02X%02X", __func__, physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]); + memcpy(physicalAddress, addressinfo.physical, sizeof(physicalAddress)); + //reportPhysicalAddress(); + // addressChanged((physicalAddress[0] << 8) | physicalAddress[1]); + } + } + } + } +} + +void cVideo::sendCECMessage(struct cec_message &message) +{ + if (hdmiFd >= 0) + { + lt_info("[CEC] send message"); + for (int i = 0; i < message.length; i++) + { + lt_info(" %02X", message.data[i]); + } + lt_info("\n"); + struct cec_msg msg; + cec_msg_init(&msg, logicalAddress, message.address); + memcpy(&msg.msg[1], message.data, message.length); + msg.len = message.length + 1; + ioctl(hdmiFd, CEC_TRANSMIT, &msg); + } +} + +void cVideo::SetCECAutoStandby(bool state) +{ + standby_cec_activ = state; +} + +void cVideo::SetCECAutoView(bool state) +{ + autoview_cec_activ = state; +} + +void cVideo::SetCECState(bool state) +{ + struct cec_message message; + message.address = 0x0f; + message.length = 2; + + if ((standby_cec_activ) && state){ + message.data[0] = CEC_MSG_STANDBY; + message.data[1] = 1; + } + + if ((autoview_cec_activ) && !state){ + message.data[0] = CEC_MSG_IMAGE_VIEW_ON; + message.data[1] = 1; + } + + sendCECMessage(message); +} diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index b2e579b..2d2e787 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -135,6 +135,19 @@ typedef enum VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS } VIDEO_CONTROL; +struct cec_message +{ + unsigned char address; + unsigned char length; + unsigned char data[256]; +}__attribute__((packed)); +#define cec_rx_message cec_message +struct addressinfo +{ + unsigned char logical; + unsigned char physical[2]; + unsigned char type; +}; class cVideo { @@ -167,6 +180,11 @@ class cVideo /* used internally by dmx */ int64_t GetPTS(void); + unsigned char physicalAddress[2]; + bool fixedAddress,standby_cec_activ,autoview_cec_activ; + unsigned char deviceType, logicalAddress; + int hdmiFd; + public: /* constructor & destructor */ cVideo(int mode, void *, void *, unsigned int unit = 0); @@ -208,9 +226,12 @@ class cVideo int SetVideoSystem(int video_system, bool remember = true); int SetStreamType(VIDEO_FORMAT type); void SetSyncMode(AVSYNC_TYPE mode); - bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; }; - void SetCECAutoView(bool) { return; }; - void SetCECAutoStandby(bool) { return; }; + bool SetCECMode(VIDEO_HDMI_CEC_MODE); + void SetCECAutoView(bool); + void SetCECAutoStandby(bool); + void getCECAddressInfo(); + void sendCECMessage(struct cec_message &message); + void SetCECState(bool state); void ShowPicture(const char * fname, const char *_destname = NULL); void StopPicture(); void Standby(unsigned int bOn); From 07b59f07dddb32968f42c8ec7692ff90ae22f5b5 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Tue, 17 Oct 2017 18:39:10 +0200 Subject: [PATCH 61/73] armbox add missing header file --- libarmbox/linux-uapi-cec.h | 1014 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1014 insertions(+) create mode 100644 libarmbox/linux-uapi-cec.h diff --git a/libarmbox/linux-uapi-cec.h b/libarmbox/linux-uapi-cec.h new file mode 100644 index 0000000..851968e --- /dev/null +++ b/libarmbox/linux-uapi-cec.h @@ -0,0 +1,1014 @@ +/* + * cec - HDMI Consumer Electronics Control public header + * + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * Alternatively you can redistribute this file under the terms of the + * BSD license as stated below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. The names of its contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * Note: this framework is still in staging and it is likely the API + * will change before it goes out of staging. + * + * Once it is moved out of staging this header will move to uapi. + */ +#ifndef _CEC_UAPI_H +#define _CEC_UAPI_H + +#include + +#define CEC_MAX_MSG_SIZE 16 + +/** + * struct cec_msg - CEC message structure. + * @tx_ts: Timestamp in nanoseconds using CLOCK_MONOTONIC. Set by the + * driver when the message transmission has finished. + * @rx_ts: Timestamp in nanoseconds using CLOCK_MONOTONIC. Set by the + * driver when the message was received. + * @len: Length in bytes of the message. + * @timeout: The timeout (in ms) that is used to timeout CEC_RECEIVE. + * Set to 0 if you want to wait forever. This timeout can also be + * used with CEC_TRANSMIT as the timeout for waiting for a reply. + * If 0, then it will use a 1 second timeout instead of waiting + * forever as is done with CEC_RECEIVE. + * @sequence: The framework assigns a sequence number to messages that are + * sent. This can be used to track replies to previously sent + * messages. + * @flags: Set to 0. + * @msg: The message payload. + * @reply: This field is ignored with CEC_RECEIVE and is only used by + * CEC_TRANSMIT. If non-zero, then wait for a reply with this + * opcode. Set to CEC_MSG_FEATURE_ABORT if you want to wait for + * a possible ABORT reply. If there was an error when sending the + * msg or FeatureAbort was returned, then reply is set to 0. + * If reply is non-zero upon return, then len/msg are set to + * the received message. + * If reply is zero upon return and status has the + * CEC_TX_STATUS_FEATURE_ABORT bit set, then len/msg are set to + * the received feature abort message. + * If reply is zero upon return and status has the + * CEC_TX_STATUS_MAX_RETRIES bit set, then no reply was seen at + * all. If reply is non-zero for CEC_TRANSMIT and the message is a + * broadcast, then -EINVAL is returned. + * if reply is non-zero, then timeout is set to 1000 (the required + * maximum response time). + * @rx_status: The message receive status bits. Set by the driver. + * @tx_status: The message transmit status bits. Set by the driver. + * @tx_arb_lost_cnt: The number of 'Arbitration Lost' events. Set by the driver. + * @tx_nack_cnt: The number of 'Not Acknowledged' events. Set by the driver. + * @tx_low_drive_cnt: The number of 'Low Drive Detected' events. Set by the + * driver. + * @tx_error_cnt: The number of 'Error' events. Set by the driver. + */ +struct cec_msg { + __u64 tx_ts; + __u64 rx_ts; + __u32 len; + __u32 timeout; + __u32 sequence; + __u32 flags; + __u8 msg[CEC_MAX_MSG_SIZE]; + __u8 reply; + __u8 rx_status; + __u8 tx_status; + __u8 tx_arb_lost_cnt; + __u8 tx_nack_cnt; + __u8 tx_low_drive_cnt; + __u8 tx_error_cnt; +}; + +/** + * cec_msg_initiator - return the initiator's logical address. + * @msg: the message structure + */ +static inline __u8 cec_msg_initiator(const struct cec_msg *msg) +{ + return msg->msg[0] >> 4; +} + +/** + * cec_msg_destination - return the destination's logical address. + * @msg: the message structure + */ +static inline __u8 cec_msg_destination(const struct cec_msg *msg) +{ + return msg->msg[0] & 0xf; +} + +/** + * cec_msg_opcode - return the opcode of the message, -1 for poll + * @msg: the message structure + */ +static inline int cec_msg_opcode(const struct cec_msg *msg) +{ + return msg->len > 1 ? msg->msg[1] : -1; +} + +/** + * cec_msg_is_broadcast - return true if this is a broadcast message. + * @msg: the message structure + */ +static inline bool cec_msg_is_broadcast(const struct cec_msg *msg) +{ + return (msg->msg[0] & 0xf) == 0xf; +} + +/** + * cec_msg_init - initialize the message structure. + * @msg: the message structure + * @initiator: the logical address of the initiator + * @destination:the logical address of the destination (0xf for broadcast) + * + * The whole structure is zeroed, the len field is set to 1 (i.e. a poll + * message) and the initiator and destination are filled in. + */ +static inline void cec_msg_init(struct cec_msg *msg, + __u8 initiator, __u8 destination) +{ + memset(msg, 0, sizeof(*msg)); + msg->msg[0] = (initiator << 4) | destination; + msg->len = 1; +} + +/** + * cec_msg_set_reply_to - fill in destination/initiator in a reply message. + * @msg: the message structure for the reply + * @orig: the original message structure + * + * Set the msg destination to the orig initiator and the msg initiator to the + * orig destination. Note that msg and orig may be the same pointer, in which + * case the change is done in place. + */ +static inline void cec_msg_set_reply_to(struct cec_msg *msg, + struct cec_msg *orig) +{ + /* The destination becomes the initiator and vice versa */ + msg->msg[0] = (cec_msg_destination(orig) << 4) | + cec_msg_initiator(orig); + msg->reply = msg->timeout = 0; +} + +/* cec status field */ +#define CEC_TX_STATUS_OK (1 << 0) +#define CEC_TX_STATUS_ARB_LOST (1 << 1) +#define CEC_TX_STATUS_NACK (1 << 2) +#define CEC_TX_STATUS_LOW_DRIVE (1 << 3) +#define CEC_TX_STATUS_ERROR (1 << 4) +#define CEC_TX_STATUS_MAX_RETRIES (1 << 5) + +#define CEC_RX_STATUS_OK (1 << 0) +#define CEC_RX_STATUS_TIMEOUT (1 << 1) +#define CEC_RX_STATUS_FEATURE_ABORT (1 << 2) + +static inline bool cec_msg_status_is_ok(const struct cec_msg *msg) +{ + if (msg->tx_status && !(msg->tx_status & CEC_TX_STATUS_OK)) + return false; + if (msg->rx_status && !(msg->rx_status & CEC_RX_STATUS_OK)) + return false; + if (!msg->tx_status && !msg->rx_status) + return false; + return !(msg->rx_status & CEC_RX_STATUS_FEATURE_ABORT); +} + +#define CEC_LOG_ADDR_INVALID 0xff +#define CEC_PHYS_ADDR_INVALID 0xffff + +/* + * The maximum number of logical addresses one device can be assigned to. + * The CEC 2.0 spec allows for only 2 logical addresses at the moment. The + * Analog Devices CEC hardware supports 3. So let's go wild and go for 4. + */ +#define CEC_MAX_LOG_ADDRS 4 + +/* The logical addresses defined by CEC 2.0 */ +#define CEC_LOG_ADDR_TV 0 +#define CEC_LOG_ADDR_RECORD_1 1 +#define CEC_LOG_ADDR_RECORD_2 2 +#define CEC_LOG_ADDR_TUNER_1 3 +#define CEC_LOG_ADDR_PLAYBACK_1 4 +#define CEC_LOG_ADDR_AUDIOSYSTEM 5 +#define CEC_LOG_ADDR_TUNER_2 6 +#define CEC_LOG_ADDR_TUNER_3 7 +#define CEC_LOG_ADDR_PLAYBACK_2 8 +#define CEC_LOG_ADDR_RECORD_3 9 +#define CEC_LOG_ADDR_TUNER_4 10 +#define CEC_LOG_ADDR_PLAYBACK_3 11 +#define CEC_LOG_ADDR_BACKUP_1 12 +#define CEC_LOG_ADDR_BACKUP_2 13 +#define CEC_LOG_ADDR_SPECIFIC 14 +#define CEC_LOG_ADDR_UNREGISTERED 15 /* as initiator address */ +#define CEC_LOG_ADDR_BROADCAST 15 /* ad destination address */ + +/* The logical address types that the CEC device wants to claim */ +#define CEC_LOG_ADDR_TYPE_TV 0 +#define CEC_LOG_ADDR_TYPE_RECORD 1 +#define CEC_LOG_ADDR_TYPE_TUNER 2 +#define CEC_LOG_ADDR_TYPE_PLAYBACK 3 +#define CEC_LOG_ADDR_TYPE_AUDIOSYSTEM 4 +#define CEC_LOG_ADDR_TYPE_SPECIFIC 5 +#define CEC_LOG_ADDR_TYPE_UNREGISTERED 6 +/* + * Switches should use UNREGISTERED. + * Processors should use SPECIFIC. + */ + +#define CEC_LOG_ADDR_MASK_TV (1 << CEC_LOG_ADDR_TV) +#define CEC_LOG_ADDR_MASK_RECORD ((1 << CEC_LOG_ADDR_RECORD_1) | \ + (1 << CEC_LOG_ADDR_RECORD_2) | \ + (1 << CEC_LOG_ADDR_RECORD_3)) +#define CEC_LOG_ADDR_MASK_TUNER ((1 << CEC_LOG_ADDR_TUNER_1) | \ + (1 << CEC_LOG_ADDR_TUNER_2) | \ + (1 << CEC_LOG_ADDR_TUNER_3) | \ + (1 << CEC_LOG_ADDR_TUNER_4)) +#define CEC_LOG_ADDR_MASK_PLAYBACK ((1 << CEC_LOG_ADDR_PLAYBACK_1) | \ + (1 << CEC_LOG_ADDR_PLAYBACK_2) | \ + (1 << CEC_LOG_ADDR_PLAYBACK_3)) +#define CEC_LOG_ADDR_MASK_AUDIOSYSTEM (1 << CEC_LOG_ADDR_AUDIOSYSTEM) +#define CEC_LOG_ADDR_MASK_BACKUP ((1 << CEC_LOG_ADDR_BACKUP_1) | \ + (1 << CEC_LOG_ADDR_BACKUP_2)) +#define CEC_LOG_ADDR_MASK_SPECIFIC (1 << CEC_LOG_ADDR_SPECIFIC) +#define CEC_LOG_ADDR_MASK_UNREGISTERED (1 << CEC_LOG_ADDR_UNREGISTERED) + +static inline bool cec_has_tv(__u16 log_addr_mask) +{ + return log_addr_mask & CEC_LOG_ADDR_MASK_TV; +} + +static inline bool cec_has_record(__u16 log_addr_mask) +{ + return log_addr_mask & CEC_LOG_ADDR_MASK_RECORD; +} + +static inline bool cec_has_tuner(__u16 log_addr_mask) +{ + return log_addr_mask & CEC_LOG_ADDR_MASK_TUNER; +} + +static inline bool cec_has_playback(__u16 log_addr_mask) +{ + return log_addr_mask & CEC_LOG_ADDR_MASK_PLAYBACK; +} + +static inline bool cec_has_audiosystem(__u16 log_addr_mask) +{ + return log_addr_mask & CEC_LOG_ADDR_MASK_AUDIOSYSTEM; +} + +static inline bool cec_has_backup(__u16 log_addr_mask) +{ + return log_addr_mask & CEC_LOG_ADDR_MASK_BACKUP; +} + +static inline bool cec_has_specific(__u16 log_addr_mask) +{ + return log_addr_mask & CEC_LOG_ADDR_MASK_SPECIFIC; +} + +static inline bool cec_is_unregistered(__u16 log_addr_mask) +{ + return log_addr_mask & CEC_LOG_ADDR_MASK_UNREGISTERED; +} + +static inline bool cec_is_unconfigured(__u16 log_addr_mask) +{ + return log_addr_mask == 0; +} + +/* + * Use this if there is no vendor ID (CEC_G_VENDOR_ID) or if the vendor ID + * should be disabled (CEC_S_VENDOR_ID) + */ +#define CEC_VENDOR_ID_NONE 0xffffffff + +/* The message handling modes */ +/* Modes for initiator */ +#define CEC_MODE_NO_INITIATOR (0x0 << 0) +#define CEC_MODE_INITIATOR (0x1 << 0) +#define CEC_MODE_EXCL_INITIATOR (0x2 << 0) +#define CEC_MODE_INITIATOR_MSK 0x0f + +/* Modes for follower */ +#define CEC_MODE_NO_FOLLOWER (0x0 << 4) +#define CEC_MODE_FOLLOWER (0x1 << 4) +#define CEC_MODE_EXCL_FOLLOWER (0x2 << 4) +#define CEC_MODE_EXCL_FOLLOWER_PASSTHRU (0x3 << 4) +#define CEC_MODE_MONITOR (0xe << 4) +#define CEC_MODE_MONITOR_ALL (0xf << 4) +#define CEC_MODE_FOLLOWER_MSK 0xf0 + +/* Userspace has to configure the physical address */ +#define CEC_CAP_PHYS_ADDR (1 << 0) +/* Userspace has to configure the logical addresses */ +#define CEC_CAP_LOG_ADDRS (1 << 1) +/* Userspace can transmit messages (and thus become follower as well) */ +#define CEC_CAP_TRANSMIT (1 << 2) +/* + * Passthrough all messages instead of processing them. + */ +#define CEC_CAP_PASSTHROUGH (1 << 3) +/* Supports remote control */ +#define CEC_CAP_RC (1 << 4) +/* Hardware can monitor all messages, not just directed and broadcast. */ +#define CEC_CAP_MONITOR_ALL (1 << 5) + +/** + * struct cec_caps - CEC capabilities structure. + * @driver: name of the CEC device driver. + * @name: name of the CEC device. @driver + @name must be unique. + * @available_log_addrs: number of available logical addresses. + * @capabilities: capabilities of the CEC adapter. + * @version: version of the CEC adapter framework. + */ +struct cec_caps { + char driver[32]; + char name[32]; + __u32 available_log_addrs; + __u32 capabilities; + __u32 version; +}; + +/** + * struct cec_log_addrs - CEC logical addresses structure. + * @log_addr: the claimed logical addresses. Set by the driver. + * @log_addr_mask: current logical address mask. Set by the driver. + * @cec_version: the CEC version that the adapter should implement. Set by the + * caller. + * @num_log_addrs: how many logical addresses should be claimed. Set by the + * caller. + * @vendor_id: the vendor ID of the device. Set by the caller. + * @flags: flags. + * @osd_name: the OSD name of the device. Set by the caller. + * @primary_device_type: the primary device type for each logical address. + * Set by the caller. + * @log_addr_type: the logical address types. Set by the caller. + * @all_device_types: CEC 2.0: all device types represented by the logical + * address. Set by the caller. + * @features: CEC 2.0: The logical address features. Set by the caller. + */ +struct cec_log_addrs { + __u8 log_addr[CEC_MAX_LOG_ADDRS]; + __u16 log_addr_mask; + __u8 cec_version; + __u8 num_log_addrs; + __u32 vendor_id; + __u32 flags; + char osd_name[15]; + __u8 primary_device_type[CEC_MAX_LOG_ADDRS]; + __u8 log_addr_type[CEC_MAX_LOG_ADDRS]; + + /* CEC 2.0 */ + __u8 all_device_types[CEC_MAX_LOG_ADDRS]; + __u8 features[CEC_MAX_LOG_ADDRS][12]; +}; + +/* Allow a fallback to unregistered */ +#define CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK (1 << 0) + +/* Events */ + +/* Event that occurs when the adapter state changes */ +#define CEC_EVENT_STATE_CHANGE 1 +/* + * This event is sent when messages are lost because the application + * didn't empty the message queue in time + */ +#define CEC_EVENT_LOST_MSGS 2 + +#define CEC_EVENT_FL_INITIAL_STATE (1 << 0) + +/** + * struct cec_event_state_change - used when the CEC adapter changes state. + * @phys_addr: the current physical address + * @log_addr_mask: the current logical address mask + */ +struct cec_event_state_change { + __u16 phys_addr; + __u16 log_addr_mask; +}; + +/** + * struct cec_event_lost_msgs - tells you how many messages were lost due. + * @lost_msgs: how many messages were lost. + */ +struct cec_event_lost_msgs { + __u32 lost_msgs; +}; + +/** + * struct cec_event - CEC event structure + * @ts: the timestamp of when the event was sent. + * @event: the event. + * array. + * @state_change: the event payload for CEC_EVENT_STATE_CHANGE. + * @lost_msgs: the event payload for CEC_EVENT_LOST_MSGS. + * @raw: array to pad the union. + */ +struct cec_event { + __u64 ts; + __u32 event; + __u32 flags; + union { + struct cec_event_state_change state_change; + struct cec_event_lost_msgs lost_msgs; + __u32 raw[16]; + }; +}; + +/* ioctls */ + +/* Adapter capabilities */ +#define CEC_ADAP_G_CAPS _IOWR('a', 0, struct cec_caps) + +/* + * phys_addr is either 0 (if this is the CEC root device) + * or a valid physical address obtained from the sink's EDID + * as read by this CEC device (if this is a source device) + * or a physical address obtained and modified from a sink + * EDID and used for a sink CEC device. + * If nothing is connected, then phys_addr is 0xffff. + * See HDMI 1.4b, section 8.7 (Physical Address). + * + * The CEC_ADAP_S_PHYS_ADDR ioctl may not be available if that is handled + * internally. + */ +#define CEC_ADAP_G_PHYS_ADDR _IOR('a', 1, __u16) +#define CEC_ADAP_S_PHYS_ADDR _IOW('a', 2, __u16) + +/* + * Configure the CEC adapter. It sets the device type and which + * logical types it will try to claim. It will return which + * logical addresses it could actually claim. + * An error is returned if the adapter is disabled or if there + * is no physical address assigned. + */ + +#define CEC_ADAP_G_LOG_ADDRS _IOR('a', 3, struct cec_log_addrs) +#define CEC_ADAP_S_LOG_ADDRS _IOWR('a', 4, struct cec_log_addrs) + +/* Transmit/receive a CEC command */ +#define CEC_TRANSMIT _IOWR('a', 5, struct cec_msg) +#define CEC_RECEIVE _IOWR('a', 6, struct cec_msg) + +/* Dequeue CEC events */ +#define CEC_DQEVENT _IOWR('a', 7, struct cec_event) + +/* + * Get and set the message handling mode for this filehandle. + */ +#define CEC_G_MODE _IOR('a', 8, __u32) +#define CEC_S_MODE _IOW('a', 9, __u32) + +/* + * The remainder of this header defines all CEC messages and operands. + * The format matters since it the cec-ctl utility parses it to generate + * code for implementing all these messages. + * + * Comments ending with 'Feature' group messages for each feature. + * If messages are part of multiple features, then the "Has also" + * comment is used to list the previously defined messages that are + * supported by the feature. + * + * Before operands are defined a comment is added that gives the + * name of the operand and in brackets the variable name of the + * corresponding argument in the cec-funcs.h function. + */ + +/* Messages */ + +/* One Touch Play Feature */ +#define CEC_MSG_ACTIVE_SOURCE 0x82 +#define CEC_MSG_IMAGE_VIEW_ON 0x04 +#define CEC_MSG_TEXT_VIEW_ON 0x0d + + +/* Routing Control Feature */ + +/* + * Has also: + * CEC_MSG_ACTIVE_SOURCE + */ + +#define CEC_MSG_INACTIVE_SOURCE 0x9d +#define CEC_MSG_REQUEST_ACTIVE_SOURCE 0x85 +#define CEC_MSG_ROUTING_CHANGE 0x80 +#define CEC_MSG_ROUTING_INFORMATION 0x81 +#define CEC_MSG_SET_STREAM_PATH 0x86 + + +/* Standby Feature */ +#define CEC_MSG_STANDBY 0x36 + + +/* One Touch Record Feature */ +#define CEC_MSG_RECORD_OFF 0x0b +#define CEC_MSG_RECORD_ON 0x09 +/* Record Source Type Operand (rec_src_type) */ +#define CEC_OP_RECORD_SRC_OWN 1 +#define CEC_OP_RECORD_SRC_DIGITAL 2 +#define CEC_OP_RECORD_SRC_ANALOG 3 +#define CEC_OP_RECORD_SRC_EXT_PLUG 4 +#define CEC_OP_RECORD_SRC_EXT_PHYS_ADDR 5 +/* Service Identification Method Operand (service_id_method) */ +#define CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID 0 +#define CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL 1 +/* Digital Service Broadcast System Operand (dig_bcast_system) */ +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_GEN 0x00 +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN 0x01 +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_GEN 0x02 +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS 0x08 +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_CS 0x09 +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T 0x0a +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE 0x10 +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT 0x11 +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T 0x12 +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_C 0x18 +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S 0x19 +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2 0x1a +#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T 0x1b +/* Analogue Broadcast Type Operand (ana_bcast_type) */ +#define CEC_OP_ANA_BCAST_TYPE_CABLE 0 +#define CEC_OP_ANA_BCAST_TYPE_SATELLITE 1 +#define CEC_OP_ANA_BCAST_TYPE_TERRESTRIAL 2 +/* Broadcast System Operand (bcast_system) */ +#define CEC_OP_BCAST_SYSTEM_PAL_BG 0x00 +#define CEC_OP_BCAST_SYSTEM_SECAM_LQ 0x01 /* SECAM L' */ +#define CEC_OP_BCAST_SYSTEM_PAL_M 0x02 +#define CEC_OP_BCAST_SYSTEM_NTSC_M 0x03 +#define CEC_OP_BCAST_SYSTEM_PAL_I 0x04 +#define CEC_OP_BCAST_SYSTEM_SECAM_DK 0x05 +#define CEC_OP_BCAST_SYSTEM_SECAM_BG 0x06 +#define CEC_OP_BCAST_SYSTEM_SECAM_L 0x07 +#define CEC_OP_BCAST_SYSTEM_PAL_DK 0x08 +#define CEC_OP_BCAST_SYSTEM_OTHER 0x1f +/* Channel Number Format Operand (channel_number_fmt) */ +#define CEC_OP_CHANNEL_NUMBER_FMT_1_PART 0x01 +#define CEC_OP_CHANNEL_NUMBER_FMT_2_PART 0x02 + +#define CEC_MSG_RECORD_STATUS 0x0a +/* Record Status Operand (rec_status) */ +#define CEC_OP_RECORD_STATUS_CUR_SRC 0x01 +#define CEC_OP_RECORD_STATUS_DIG_SERVICE 0x02 +#define CEC_OP_RECORD_STATUS_ANA_SERVICE 0x03 +#define CEC_OP_RECORD_STATUS_EXT_INPUT 0x04 +#define CEC_OP_RECORD_STATUS_NO_DIG_SERVICE 0x05 +#define CEC_OP_RECORD_STATUS_NO_ANA_SERVICE 0x06 +#define CEC_OP_RECORD_STATUS_NO_SERVICE 0x07 +#define CEC_OP_RECORD_STATUS_INVALID_EXT_PLUG 0x09 +#define CEC_OP_RECORD_STATUS_INVALID_EXT_PHYS_ADDR 0x0a +#define CEC_OP_RECORD_STATUS_UNSUP_CA 0x0b +#define CEC_OP_RECORD_STATUS_NO_CA_ENTITLEMENTS 0x0c +#define CEC_OP_RECORD_STATUS_CANT_COPY_SRC 0x0d +#define CEC_OP_RECORD_STATUS_NO_MORE_COPIES 0x0e +#define CEC_OP_RECORD_STATUS_NO_MEDIA 0x10 +#define CEC_OP_RECORD_STATUS_PLAYING 0x11 +#define CEC_OP_RECORD_STATUS_ALREADY_RECORDING 0x12 +#define CEC_OP_RECORD_STATUS_MEDIA_PROT 0x13 +#define CEC_OP_RECORD_STATUS_NO_SIGNAL 0x14 +#define CEC_OP_RECORD_STATUS_MEDIA_PROBLEM 0x15 +#define CEC_OP_RECORD_STATUS_NO_SPACE 0x16 +#define CEC_OP_RECORD_STATUS_PARENTAL_LOCK 0x17 +#define CEC_OP_RECORD_STATUS_TERMINATED_OK 0x1a +#define CEC_OP_RECORD_STATUS_ALREADY_TERM 0x1b +#define CEC_OP_RECORD_STATUS_OTHER 0x1f + +#define CEC_MSG_RECORD_TV_SCREEN 0x0f + + +/* Timer Programming Feature */ +#define CEC_MSG_CLEAR_ANALOGUE_TIMER 0x33 +/* Recording Sequence Operand (recording_seq) */ +#define CEC_OP_REC_SEQ_SUNDAY 0x01 +#define CEC_OP_REC_SEQ_MONDAY 0x02 +#define CEC_OP_REC_SEQ_TUESDAY 0x04 +#define CEC_OP_REC_SEQ_WEDNESDAY 0x08 +#define CEC_OP_REC_SEQ_THURSDAY 0x10 +#define CEC_OP_REC_SEQ_FRIDAY 0x20 +#define CEC_OP_REC_SEQ_SATERDAY 0x40 +#define CEC_OP_REC_SEQ_ONCE_ONLY 0x00 + +#define CEC_MSG_CLEAR_DIGITAL_TIMER 0x99 + +#define CEC_MSG_CLEAR_EXT_TIMER 0xa1 +/* External Source Specifier Operand (ext_src_spec) */ +#define CEC_OP_EXT_SRC_PLUG 0x04 +#define CEC_OP_EXT_SRC_PHYS_ADDR 0x05 + +#define CEC_MSG_SET_ANALOGUE_TIMER 0x34 +#define CEC_MSG_SET_DIGITAL_TIMER 0x97 +#define CEC_MSG_SET_EXT_TIMER 0xa2 + +#define CEC_MSG_SET_TIMER_PROGRAM_TITLE 0x67 +#define CEC_MSG_TIMER_CLEARED_STATUS 0x43 +/* Timer Cleared Status Data Operand (timer_cleared_status) */ +#define CEC_OP_TIMER_CLR_STAT_RECORDING 0x00 +#define CEC_OP_TIMER_CLR_STAT_NO_MATCHING 0x01 +#define CEC_OP_TIMER_CLR_STAT_NO_INFO 0x02 +#define CEC_OP_TIMER_CLR_STAT_CLEARED 0x80 + +#define CEC_MSG_TIMER_STATUS 0x35 +/* Timer Overlap Warning Operand (timer_overlap_warning) */ +#define CEC_OP_TIMER_OVERLAP_WARNING_NO_OVERLAP 0 +#define CEC_OP_TIMER_OVERLAP_WARNING_OVERLAP 1 +/* Media Info Operand (media_info) */ +#define CEC_OP_MEDIA_INFO_UNPROT_MEDIA 0 +#define CEC_OP_MEDIA_INFO_PROT_MEDIA 1 +#define CEC_OP_MEDIA_INFO_NO_MEDIA 2 +/* Programmed Indicator Operand (prog_indicator) */ +#define CEC_OP_PROG_IND_NOT_PROGRAMMED 0 +#define CEC_OP_PROG_IND_PROGRAMMED 1 +/* Programmed Info Operand (prog_info) */ +#define CEC_OP_PROG_INFO_ENOUGH_SPACE 0x08 +#define CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE 0x09 +#define CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE 0x0b +#define CEC_OP_PROG_INFO_NONE_AVAILABLE 0x0a +/* Not Programmed Error Info Operand (prog_error) */ +#define CEC_OP_PROG_ERROR_NO_FREE_TIMER 0x01 +#define CEC_OP_PROG_ERROR_DATE_OUT_OF_RANGE 0x02 +#define CEC_OP_PROG_ERROR_REC_SEQ_ERROR 0x03 +#define CEC_OP_PROG_ERROR_INV_EXT_PLUG 0x04 +#define CEC_OP_PROG_ERROR_INV_EXT_PHYS_ADDR 0x05 +#define CEC_OP_PROG_ERROR_CA_UNSUPP 0x06 +#define CEC_OP_PROG_ERROR_INSUF_CA_ENTITLEMENTS 0x07 +#define CEC_OP_PROG_ERROR_RESOLUTION_UNSUPP 0x08 +#define CEC_OP_PROG_ERROR_PARENTAL_LOCK 0x09 +#define CEC_OP_PROG_ERROR_CLOCK_FAILURE 0x0a +#define CEC_OP_PROG_ERROR_DUPLICATE 0x0e + + +/* System Information Feature */ +#define CEC_MSG_CEC_VERSION 0x9e +/* CEC Version Operand (cec_version) */ +#define CEC_OP_CEC_VERSION_1_3A 4 +#define CEC_OP_CEC_VERSION_1_4 5 +#define CEC_OP_CEC_VERSION_2_0 6 + +#define CEC_MSG_GET_CEC_VERSION 0x9f +#define CEC_MSG_GIVE_PHYSICAL_ADDR 0x83 +#define CEC_MSG_GET_MENU_LANGUAGE 0x91 +#define CEC_MSG_REPORT_PHYSICAL_ADDR 0x84 +/* Primary Device Type Operand (prim_devtype) */ +#define CEC_OP_PRIM_DEVTYPE_TV 0 +#define CEC_OP_PRIM_DEVTYPE_RECORD 1 +#define CEC_OP_PRIM_DEVTYPE_TUNER 3 +#define CEC_OP_PRIM_DEVTYPE_PLAYBACK 4 +#define CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM 5 +#define CEC_OP_PRIM_DEVTYPE_SWITCH 6 +#define CEC_OP_PRIM_DEVTYPE_PROCESSOR 7 + +#define CEC_MSG_SET_MENU_LANGUAGE 0x32 +#define CEC_MSG_REPORT_FEATURES 0xa6 /* HDMI 2.0 */ +/* All Device Types Operand (all_device_types) */ +#define CEC_OP_ALL_DEVTYPE_TV 0x80 +#define CEC_OP_ALL_DEVTYPE_RECORD 0x40 +#define CEC_OP_ALL_DEVTYPE_TUNER 0x20 +#define CEC_OP_ALL_DEVTYPE_PLAYBACK 0x10 +#define CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM 0x08 +#define CEC_OP_ALL_DEVTYPE_SWITCH 0x04 +/* + * And if you wondering what happened to PROCESSOR devices: those should + * be mapped to a SWITCH. + */ + +/* Valid for RC Profile and Device Feature operands */ +#define CEC_OP_FEAT_EXT 0x80 /* Extension bit */ +/* RC Profile Operand (rc_profile) */ +#define CEC_OP_FEAT_RC_TV_PROFILE_NONE 0x00 +#define CEC_OP_FEAT_RC_TV_PROFILE_1 0x02 +#define CEC_OP_FEAT_RC_TV_PROFILE_2 0x06 +#define CEC_OP_FEAT_RC_TV_PROFILE_3 0x0a +#define CEC_OP_FEAT_RC_TV_PROFILE_4 0x0e +#define CEC_OP_FEAT_RC_SRC_HAS_DEV_ROOT_MENU 0x50 +#define CEC_OP_FEAT_RC_SRC_HAS_DEV_SETUP_MENU 0x48 +#define CEC_OP_FEAT_RC_SRC_HAS_CONTENTS_MENU 0x44 +#define CEC_OP_FEAT_RC_SRC_HAS_MEDIA_TOP_MENU 0x42 +#define CEC_OP_FEAT_RC_SRC_HAS_MEDIA_CONTEXT_MENU 0x41 +/* Device Feature Operand (dev_features) */ +#define CEC_OP_FEAT_DEV_HAS_RECORD_TV_SCREEN 0x40 +#define CEC_OP_FEAT_DEV_HAS_SET_OSD_STRING 0x20 +#define CEC_OP_FEAT_DEV_HAS_DECK_CONTROL 0x10 +#define CEC_OP_FEAT_DEV_HAS_SET_AUDIO_RATE 0x08 +#define CEC_OP_FEAT_DEV_SINK_HAS_ARC_TX 0x04 +#define CEC_OP_FEAT_DEV_SOURCE_HAS_ARC_RX 0x02 + +#define CEC_MSG_GIVE_FEATURES 0xa5 /* HDMI 2.0 */ + + +/* Deck Control Feature */ +#define CEC_MSG_DECK_CONTROL 0x42 +/* Deck Control Mode Operand (deck_control_mode) */ +#define CEC_OP_DECK_CTL_MODE_SKIP_FWD 1 +#define CEC_OP_DECK_CTL_MODE_SKIP_REV 2 +#define CEC_OP_DECK_CTL_MODE_STOP 3 +#define CEC_OP_DECK_CTL_MODE_EJECT 4 + +#define CEC_MSG_DECK_STATUS 0x1b +/* Deck Info Operand (deck_info) */ +#define CEC_OP_DECK_INFO_PLAY 0x11 +#define CEC_OP_DECK_INFO_RECORD 0x12 +#define CEC_OP_DECK_INFO_PLAY_REV 0x13 +#define CEC_OP_DECK_INFO_STILL 0x14 +#define CEC_OP_DECK_INFO_SLOW 0x15 +#define CEC_OP_DECK_INFO_SLOW_REV 0x16 +#define CEC_OP_DECK_INFO_FAST_FWD 0x17 +#define CEC_OP_DECK_INFO_FAST_REV 0x18 +#define CEC_OP_DECK_INFO_NO_MEDIA 0x19 +#define CEC_OP_DECK_INFO_STOP 0x1a +#define CEC_OP_DECK_INFO_SKIP_FWD 0x1b +#define CEC_OP_DECK_INFO_SKIP_REV 0x1c +#define CEC_OP_DECK_INFO_INDEX_SEARCH_FWD 0x1d +#define CEC_OP_DECK_INFO_INDEX_SEARCH_REV 0x1e +#define CEC_OP_DECK_INFO_OTHER 0x1f + +#define CEC_MSG_GIVE_DECK_STATUS 0x1a +/* Status Request Operand (status_req) */ +#define CEC_OP_STATUS_REQ_ON 1 +#define CEC_OP_STATUS_REQ_OFF 2 +#define CEC_OP_STATUS_REQ_ONCE 3 + +#define CEC_MSG_PLAY 0x41 +/* Play Mode Operand (play_mode) */ +#define CEC_OP_PLAY_MODE_PLAY_FWD 0x24 +#define CEC_OP_PLAY_MODE_PLAY_REV 0x20 +#define CEC_OP_PLAY_MODE_PLAY_STILL 0x25 +#define CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MIN 0x05 +#define CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MED 0x06 +#define CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MAX 0x07 +#define CEC_OP_PLAY_MODE_PLAY_FAST_REV_MIN 0x09 +#define CEC_OP_PLAY_MODE_PLAY_FAST_REV_MED 0x0a +#define CEC_OP_PLAY_MODE_PLAY_FAST_REV_MAX 0x0b +#define CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MIN 0x15 +#define CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MED 0x16 +#define CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MAX 0x17 +#define CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MIN 0x19 +#define CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MED 0x1a +#define CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MAX 0x1b + + +/* Tuner Control Feature */ +#define CEC_MSG_GIVE_TUNER_DEVICE_STATUS 0x08 +#define CEC_MSG_SELECT_ANALOGUE_SERVICE 0x92 +#define CEC_MSG_SELECT_DIGITAL_SERVICE 0x93 +#define CEC_MSG_TUNER_DEVICE_STATUS 0x07 +/* Recording Flag Operand (rec_flag) */ +#define CEC_OP_REC_FLAG_USED 0 +#define CEC_OP_REC_FLAG_NOT_USED 1 +/* Tuner Display Info Operand (tuner_display_info) */ +#define CEC_OP_TUNER_DISPLAY_INFO_DIGITAL 0 +#define CEC_OP_TUNER_DISPLAY_INFO_NONE 1 +#define CEC_OP_TUNER_DISPLAY_INFO_ANALOGUE 2 + +#define CEC_MSG_TUNER_STEP_DECREMENT 0x06 +#define CEC_MSG_TUNER_STEP_INCREMENT 0x05 + + +/* Vendor Specific Commands Feature */ + +/* + * Has also: + * CEC_MSG_CEC_VERSION + * CEC_MSG_GET_CEC_VERSION + */ +#define CEC_MSG_DEVICE_VENDOR_ID 0x87 +#define CEC_MSG_GIVE_DEVICE_VENDOR_ID 0x8c +#define CEC_MSG_VENDOR_COMMAND 0x89 +#define CEC_MSG_VENDOR_COMMAND_WITH_ID 0xa0 +#define CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN 0x8a +#define CEC_MSG_VENDOR_REMOTE_BUTTON_UP 0x8b + + +/* OSD Display Feature */ +#define CEC_MSG_SET_OSD_STRING 0x64 +/* Display Control Operand (disp_ctl) */ +#define CEC_OP_DISP_CTL_DEFAULT 0x00 +#define CEC_OP_DISP_CTL_UNTIL_CLEARED 0x40 +#define CEC_OP_DISP_CTL_CLEAR 0x80 + + +/* Device OSD Transfer Feature */ +#define CEC_MSG_GIVE_OSD_NAME 0x46 +#define CEC_MSG_SET_OSD_NAME 0x47 + + +/* Device Menu Control Feature */ +#define CEC_MSG_MENU_REQUEST 0x8d +/* Menu Request Type Operand (menu_req) */ +#define CEC_OP_MENU_REQUEST_ACTIVATE 0x00 +#define CEC_OP_MENU_REQUEST_DEACTIVATE 0x01 +#define CEC_OP_MENU_REQUEST_QUERY 0x02 + +#define CEC_MSG_MENU_STATUS 0x8e +/* Menu State Operand (menu_state) */ +#define CEC_OP_MENU_STATE_ACTIVATED 0x00 +#define CEC_OP_MENU_STATE_DEACTIVATED 0x01 + +#define CEC_MSG_USER_CONTROL_PRESSED 0x44 +/* UI Broadcast Type Operand (ui_bcast_type) */ +#define CEC_OP_UI_BCAST_TYPE_TOGGLE_ALL 0x00 +#define CEC_OP_UI_BCAST_TYPE_TOGGLE_DIG_ANA 0x01 +#define CEC_OP_UI_BCAST_TYPE_ANALOGUE 0x10 +#define CEC_OP_UI_BCAST_TYPE_ANALOGUE_T 0x20 +#define CEC_OP_UI_BCAST_TYPE_ANALOGUE_CABLE 0x30 +#define CEC_OP_UI_BCAST_TYPE_ANALOGUE_SAT 0x40 +#define CEC_OP_UI_BCAST_TYPE_DIGITAL 0x50 +#define CEC_OP_UI_BCAST_TYPE_DIGITAL_T 0x60 +#define CEC_OP_UI_BCAST_TYPE_DIGITAL_CABLE 0x70 +#define CEC_OP_UI_BCAST_TYPE_DIGITAL_SAT 0x80 +#define CEC_OP_UI_BCAST_TYPE_DIGITAL_COM_SAT 0x90 +#define CEC_OP_UI_BCAST_TYPE_DIGITAL_COM_SAT2 0x91 +#define CEC_OP_UI_BCAST_TYPE_IP 0xa0 +/* UI Sound Presentation Control Operand (ui_snd_pres_ctl) */ +#define CEC_OP_UI_SND_PRES_CTL_DUAL_MONO 0x10 +#define CEC_OP_UI_SND_PRES_CTL_KARAOKE 0x20 +#define CEC_OP_UI_SND_PRES_CTL_DOWNMIX 0x80 +#define CEC_OP_UI_SND_PRES_CTL_REVERB 0x90 +#define CEC_OP_UI_SND_PRES_CTL_EQUALIZER 0xa0 +#define CEC_OP_UI_SND_PRES_CTL_BASS_UP 0xb1 +#define CEC_OP_UI_SND_PRES_CTL_BASS_NEUTRAL 0xb2 +#define CEC_OP_UI_SND_PRES_CTL_BASS_DOWN 0xb3 +#define CEC_OP_UI_SND_PRES_CTL_TREBLE_UP 0xc1 +#define CEC_OP_UI_SND_PRES_CTL_TREBLE_NEUTRAL 0xc2 +#define CEC_OP_UI_SND_PRES_CTL_TREBLE_DOWN 0xc3 + +#define CEC_MSG_USER_CONTROL_RELEASED 0x45 + + +/* Remote Control Passthrough Feature */ + +/* + * Has also: + * CEC_MSG_USER_CONTROL_PRESSED + * CEC_MSG_USER_CONTROL_RELEASED + */ + + +/* Power Status Feature */ +#define CEC_MSG_GIVE_DEVICE_POWER_STATUS 0x8f +#define CEC_MSG_REPORT_POWER_STATUS 0x90 +/* Power Status Operand (pwr_state) */ +#define CEC_OP_POWER_STATUS_ON 0 +#define CEC_OP_POWER_STATUS_STANDBY 1 +#define CEC_OP_POWER_STATUS_TO_ON 2 +#define CEC_OP_POWER_STATUS_TO_STANDBY 3 + + +/* General Protocol Messages */ +#define CEC_MSG_FEATURE_ABORT 0x00 +/* Abort Reason Operand (reason) */ +#define CEC_OP_ABORT_UNRECOGNIZED_OP 0 +#define CEC_OP_ABORT_INCORRECT_MODE 1 +#define CEC_OP_ABORT_NO_SOURCE 2 +#define CEC_OP_ABORT_INVALID_OP 3 +#define CEC_OP_ABORT_REFUSED 4 +#define CEC_OP_ABORT_UNDETERMINED 5 + +#define CEC_MSG_ABORT 0xff + + +/* System Audio Control Feature */ + +/* + * Has also: + * CEC_MSG_USER_CONTROL_PRESSED + * CEC_MSG_USER_CONTROL_RELEASED + */ +#define CEC_MSG_GIVE_AUDIO_STATUS 0x71 +#define CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS 0x7d +#define CEC_MSG_REPORT_AUDIO_STATUS 0x7a +/* Audio Mute Status Operand (aud_mute_status) */ +#define CEC_OP_AUD_MUTE_STATUS_OFF 0 +#define CEC_OP_AUD_MUTE_STATUS_ON 1 + +#define CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR 0xa3 +#define CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR 0xa4 +#define CEC_MSG_SET_SYSTEM_AUDIO_MODE 0x72 +/* System Audio Status Operand (sys_aud_status) */ +#define CEC_OP_SYS_AUD_STATUS_OFF 0 +#define CEC_OP_SYS_AUD_STATUS_ON 1 + +#define CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST 0x70 +#define CEC_MSG_SYSTEM_AUDIO_MODE_STATUS 0x7e +/* Audio Format ID Operand (audio_format_id) */ +#define CEC_OP_AUD_FMT_ID_CEA861 0 +#define CEC_OP_AUD_FMT_ID_CEA861_CXT 1 + + +/* Audio Rate Control Feature */ +#define CEC_MSG_SET_AUDIO_RATE 0x9a +/* Audio Rate Operand (audio_rate) */ +#define CEC_OP_AUD_RATE_OFF 0 +#define CEC_OP_AUD_RATE_WIDE_STD 1 +#define CEC_OP_AUD_RATE_WIDE_FAST 2 +#define CEC_OP_AUD_RATE_WIDE_SLOW 3 +#define CEC_OP_AUD_RATE_NARROW_STD 4 +#define CEC_OP_AUD_RATE_NARROW_FAST 5 +#define CEC_OP_AUD_RATE_NARROW_SLOW 6 + + +/* Audio Return Channel Control Feature */ +#define CEC_MSG_INITIATE_ARC 0xc0 +#define CEC_MSG_REPORT_ARC_INITIATED 0xc1 +#define CEC_MSG_REPORT_ARC_TERMINATED 0xc2 +#define CEC_MSG_REQUEST_ARC_INITIATION 0xc3 +#define CEC_MSG_REQUEST_ARC_TERMINATION 0xc4 +#define CEC_MSG_TERMINATE_ARC 0xc5 + + +/* Dynamic Audio Lipsync Feature */ +/* Only for CEC 2.0 and up */ +#define CEC_MSG_REQUEST_CURRENT_LATENCY 0xa7 +#define CEC_MSG_REPORT_CURRENT_LATENCY 0xa8 +/* Low Latency Mode Operand (low_latency_mode) */ +#define CEC_OP_LOW_LATENCY_MODE_OFF 0 +#define CEC_OP_LOW_LATENCY_MODE_ON 1 +/* Audio Output Compensated Operand (audio_out_compensated) */ +#define CEC_OP_AUD_OUT_COMPENSATED_NA 0 +#define CEC_OP_AUD_OUT_COMPENSATED_DELAY 1 +#define CEC_OP_AUD_OUT_COMPENSATED_NO_DELAY 2 +#define CEC_OP_AUD_OUT_COMPENSATED_PARTIAL_DELAY 3 + + +/* Capability Discovery and Control Feature */ +#define CEC_MSG_CDC_MESSAGE 0xf8 +/* Ethernet-over-HDMI: nobody ever does this... */ +#define CEC_MSG_CDC_HEC_INQUIRE_STATE 0x00 +#define CEC_MSG_CDC_HEC_REPORT_STATE 0x01 +/* HEC Functionality State Operand (hec_func_state) */ +#define CEC_OP_HEC_FUNC_STATE_NOT_SUPPORTED 0 +#define CEC_OP_HEC_FUNC_STATE_INACTIVE 1 +#define CEC_OP_HEC_FUNC_STATE_ACTIVE 2 +#define CEC_OP_HEC_FUNC_STATE_ACTIVATION_FIELD 3 +/* Host Functionality State Operand (host_func_state) */ +#define CEC_OP_HOST_FUNC_STATE_NOT_SUPPORTED 0 +#define CEC_OP_HOST_FUNC_STATE_INACTIVE 1 +#define CEC_OP_HOST_FUNC_STATE_ACTIVE 2 +/* ENC Functionality State Operand (enc_func_state) */ +#define CEC_OP_ENC_FUNC_STATE_EXT_CON_NOT_SUPPORTED 0 +#define CEC_OP_ENC_FUNC_STATE_EXT_CON_INACTIVE 1 +#define CEC_OP_ENC_FUNC_STATE_EXT_CON_ACTIVE 2 +/* CDC Error Code Operand (cdc_errcode) */ +#define CEC_OP_CDC_ERROR_CODE_NONE 0 +#define CEC_OP_CDC_ERROR_CODE_CAP_UNSUPPORTED 1 +#define CEC_OP_CDC_ERROR_CODE_WRONG_STATE 2 +#define CEC_OP_CDC_ERROR_CODE_OTHER 3 +/* HEC Support Operand (hec_support) */ +#define CEC_OP_HEC_SUPPORT_NO 0 +#define CEC_OP_HEC_SUPPORT_YES 1 +/* HEC Activation Operand (hec_activation) */ +#define CEC_OP_HEC_ACTIVATION_ON 0 +#define CEC_OP_HEC_ACTIVATION_OFF 1 + +#define CEC_MSG_CDC_HEC_SET_STATE_ADJACENT 0x02 +#define CEC_MSG_CDC_HEC_SET_STATE 0x03 +/* HEC Set State Operand (hec_set_state) */ +#define CEC_OP_HEC_SET_STATE_DEACTIVATE 0 +#define CEC_OP_HEC_SET_STATE_ACTIVATE 1 + +#define CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION 0x04 +#define CEC_MSG_CDC_HEC_NOTIFY_ALIVE 0x05 +#define CEC_MSG_CDC_HEC_DISCOVER 0x06 +/* Hotplug Detect messages */ +#define CEC_MSG_CDC_HPD_SET_STATE 0x10 +/* HPD State Operand (hpd_state) */ +#define CEC_OP_HPD_STATE_CP_EDID_DISABLE 0 +#define CEC_OP_HPD_STATE_CP_EDID_ENABLE 1 +#define CEC_OP_HPD_STATE_CP_EDID_DISABLE_ENABLE 2 +#define CEC_OP_HPD_STATE_EDID_DISABLE 3 +#define CEC_OP_HPD_STATE_EDID_ENABLE 4 +#define CEC_OP_HPD_STATE_EDID_DISABLE_ENABLE 5 +#define CEC_MSG_CDC_HPD_REPORT_STATE 0x11 +/* HPD Error Code Operand (hpd_error) */ +#define CEC_OP_HPD_ERROR_NONE 0 +#define CEC_OP_HPD_ERROR_INITIATOR_NOT_CAPABLE 1 +#define CEC_OP_HPD_ERROR_INITIATOR_WRONG_STATE 2 +#define CEC_OP_HPD_ERROR_OTHER 3 +#define CEC_OP_HPD_ERROR_NONE_NO_VIDEO 4 + +#endif From 18d6e271e259b07883ca36679471890ce7b4063f Mon Sep 17 00:00:00 2001 From: TangoCash Date: Tue, 17 Oct 2017 18:39:21 +0200 Subject: [PATCH 62/73] armbox: fix devices --- libarmbox/audio.cpp | 2 +- libarmbox/video.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libarmbox/audio.cpp b/libarmbox/audio.cpp index dc4238e..36498e4 100644 --- a/libarmbox/audio.cpp +++ b/libarmbox/audio.cpp @@ -49,7 +49,7 @@ void cAudio::openDevice(void) if (fd < 0) { - if ((fd = open(AUDIO_DEVICE, O_RDWR | O_NONBLOCK)) < 0) + if ((fd = open(AUDIO_DEVICE, O_RDWR)) < 0) lt_info("openDevice: open failed (%m)\n"); fcntl(fd, F_SETFD, FD_CLOEXEC); do_mute(true, false); diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 0afd139..61c7f6f 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -178,7 +178,7 @@ void cVideo::openDevice(void) if (fd != -1) /* already open */ return; retry: - if ((fd = open(VDEV[devnum], O_RDWR|O_CLOEXEC|O_NONBLOCK)) < 0) + if ((fd = open(VDEV[devnum], O_RDWR|O_CLOEXEC)) < 0) { if (errno == EBUSY) { From 4ccbffeb312cf48e8be8199da3bfd7d6fb86994f Mon Sep 17 00:00:00 2001 From: TangoCash Date: Tue, 17 Oct 2017 19:53:02 +0200 Subject: [PATCH 63/73] armbox: fix still image --- libarmbox/video.cpp | 48 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 61c7f6f..6979df9 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -401,10 +401,32 @@ void cVideo::SetVideoMode(analog_mode_t mode) proc_put("/proc/stb/avs/0/colorformat", m, strlen(m)); } +ssize_t write_all(int fd, const void *buf, size_t count) +{ + int retval; + char *ptr = (char*)buf; + size_t handledcount = 0; + while (handledcount < count) + { + retval = write(fd, &ptr[handledcount], count - handledcount); + if (retval == 0) + return -1; + if (retval < 0) + { + if (errno == EINTR) + continue; + return retval; + } + handledcount += retval; + } + return handledcount; +} + void cVideo::ShowPicture(const char * fname, const char *_destname) { lt_debug("%s(%s)\n", __func__, fname); - static const unsigned char pes_header[] = { 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x80, 0x00, 0x00 }; + //static const unsigned char pes_header[] = { 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x80, 0x00, 0x00 }; + static const unsigned char pes_header[] = {0x0, 0x0, 0x1, 0xe0, 0x00, 0x00, 0x80, 0x80, 0x5, 0x21, 0x0, 0x1, 0x0, 0x1}; static const unsigned char seq_end[] = { 0x00, 0x00, 0x01, 0xB7 }; char destname[512]; char cmd[512]; @@ -448,7 +470,7 @@ void cVideo::ShowPicture(const char * fname, const char *_destname) u.actime = time(NULL); u.modtime = st2.st_mtime; /* it does not exist or has a different date, so call ffmpeg... */ - sprintf(cmd, "ffmpeg -y -f mjpeg -i '%s' -s 1280x720 -aspect 16:9 '%s' /dev/null", fname, destname); system(cmd); /* TODO: use libavcodec to directly convert it */ utime(destname, &u); @@ -469,17 +491,19 @@ void cVideo::ShowPicture(const char * fname, const char *_destname) { stillpicture = true; - if (ioctl(fd, VIDEO_SET_FORMAT, VIDEO_FORMAT_16_9) < 0) - lt_info("%s: VIDEO_SET_FORMAT failed (%m)\n", __func__); bool seq_end_avail = false; off_t pos=0; - unsigned char *iframe = (unsigned char *)malloc((st.st_size < 8192) ? 8192 : st.st_size); + unsigned char iframe[st.st_size]; if (! iframe) { lt_info("%s: malloc failed (%m)\n", __func__); goto out; } read(mfd, iframe, st.st_size); + if(iframe[0] == 0x00 && iframe[1] == 0x00 && iframe[2] == 0x00 && iframe[3] == 0x01 && (iframe[4] & 0x0f) == 0x07) + ioctl(fd, VIDEO_SET_STREAMTYPE, 1); // set to mpeg4 + else + ioctl(fd, VIDEO_SET_STREAMTYPE, 0); // set to mpeg2 ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY); ioctl(fd, VIDEO_PLAY); ioctl(fd, VIDEO_CONTINUE); @@ -488,14 +512,17 @@ void cVideo::ShowPicture(const char * fname, const char *_destname) ++pos; if ((iframe[3] >> 4) != 0xE) // no pes header - write(fd, pes_header, sizeof(pes_header)); - write(fd, iframe, st.st_size); + write_all(fd, pes_header, sizeof(pes_header)); + else + iframe[4] = iframe[5] = 0x00; + write_all(fd, iframe, st.st_size); if (!seq_end_avail) write(fd, seq_end, sizeof(seq_end)); memset(iframe, 0, 8192); - write(fd, iframe, 8192); + write_all(fd, iframe, 8192); + usleep(150000); + ioctl(fd, VIDEO_STOP, 0); ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); - free(iframe); } out: close(mfd); @@ -956,12 +983,13 @@ void cVideo::SetCECState(bool state) if ((standby_cec_activ) && state){ message.data[0] = CEC_MSG_STANDBY; message.data[1] = 1; + sendCECMessage(message); } if ((autoview_cec_activ) && !state){ message.data[0] = CEC_MSG_IMAGE_VIEW_ON; message.data[1] = 1; + sendCECMessage(message); } - sendCECMessage(message); } From 0dd25ef8fb040533d038372046ee1ce7020b9043 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Wed, 18 Oct 2017 12:50:34 +0200 Subject: [PATCH 64/73] ca_ci: in some situations missing scambled flag (thx dbo) --- common/ca_ci.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/common/ca_ci.cpp b/common/ca_ci.cpp index 72772f6..9f8cd3c 100644 --- a/common/ca_ci.cpp +++ b/common/ca_ci.cpp @@ -692,14 +692,20 @@ SlotIt cCA::FindFreeSlot(u64 TP, u8 source, u16 SID, ca_map_t camap, unsigned ch for (int j = 0; j < CI_MAX_MULTI; j++) { if ((*it)->TP == TP && (*it)->SID[j] == SID && (*it)->source == source) + { + (*it)->scrambled = scrambled; return it; + } } } for (it = slot_data.begin(); it != slot_data.end(); ++it) { if ((*it)->multi && (*it)->TP == TP && (*it)->source == source && (*it)->ci_use_count < CI_MAX_MULTI) - return it; + { + (*it)->scrambled = scrambled; + return it; + } } for (it = slot_data.begin(); it != slot_data.end(); ++it) From 99eb4a3c7f1c94c589e62cb3b1764f72e0e2f601 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Wed, 18 Oct 2017 21:05:28 +0200 Subject: [PATCH 65/73] armbox: tryfix lost of video device after playing something with gst --- libarmbox/video.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 6979df9..c55df3a 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -189,6 +189,8 @@ retry: } lt_info("#%d: %s cannot open %s: %m, retries %d\n", devnum, __func__, VDEV[devnum], n); } + ioctl(fd, VIDEO_STOP, 0); + ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); playstate = VIDEO_STOPPED; } @@ -197,6 +199,10 @@ void cVideo::closeDevice(void) lt_debug("%s\n", __func__); /* looks like sometimes close is unhappy about non-empty buffers */ Start(); + ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY); + ioctl(fd, VIDEO_PLAY); + ioctl(fd, VIDEO_CONTINUE); + ioctl(fd, VIDEO_CLEAR_BUFFER); if (fd >= 0) close(fd); fd = -1; From 9bdcb65a616d138f32ef0ca43e56f0bd51a4b066 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Thu, 19 Oct 2017 21:12:05 +0200 Subject: [PATCH 66/73] armbox: tryfix cec --- libarmbox/video.cpp | 58 ++++++++++++++++++++++++++----------------- libarmbox/video_lib.h | 7 +++--- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index c55df3a..f5f0964 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -889,11 +889,11 @@ bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) } - getCECAddressInfo(); + GetCECAddressInfo(); } -void cVideo::getCECAddressInfo() +void cVideo::GetCECAddressInfo() { if (hdmiFd >= 0) { @@ -932,27 +932,32 @@ void cVideo::getCECAddressInfo() addressinfo.type = CEC_LOG_ADDR_UNREGISTERED; break; } - hasdata = true; - if (hasdata) + deviceType = addressinfo.type; + logicalAddress = addressinfo.logical; + if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress))) { - deviceType = addressinfo.type; - logicalAddress = addressinfo.logical; - if (!fixedAddress) - { - if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress))) - { - lt_info("%s: detected physical address change: %02X%02X --> %02X%02X", __func__, physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]); - memcpy(physicalAddress, addressinfo.physical, sizeof(physicalAddress)); - //reportPhysicalAddress(); - // addressChanged((physicalAddress[0] << 8) | physicalAddress[1]); - } - } + lt_info("%s: detected physical address change: %02X%02X --> %02X%02X", __func__, physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]); + memcpy(physicalAddress, addressinfo.physical, sizeof(physicalAddress)); + ReportPhysicalAddress(); + // addressChanged((physicalAddress[0] << 8) | physicalAddress[1]); } } } -void cVideo::sendCECMessage(struct cec_message &message) +void cVideo::ReportPhysicalAddress() +{ + struct cec_message txmessage; + txmessage.address = 0x0f; /* broadcast */ + txmessage.data[0] = CEC_MSG_REPORT_PHYSICAL_ADDR; + txmessage.data[1] = physicalAddress[0]; + txmessage.data[2] = physicalAddress[1]; + txmessage.data[3] = deviceType; + txmessage.length = 4; + SendCECMessage(txmessage); +} + +void cVideo::SendCECMessage(struct cec_message &message) { if (hdmiFd >= 0) { @@ -983,19 +988,26 @@ void cVideo::SetCECAutoView(bool state) void cVideo::SetCECState(bool state) { struct cec_message message; - message.address = 0x0f; - message.length = 2; if ((standby_cec_activ) && state){ + message.address = CEC_OP_PRIM_DEVTYPE_TV; message.data[0] = CEC_MSG_STANDBY; - message.data[1] = 1; - sendCECMessage(message); + message.length = 1; + SendCECMessage(message); } if ((autoview_cec_activ) && !state){ + message.address = CEC_OP_PRIM_DEVTYPE_TV; message.data[0] = CEC_MSG_IMAGE_VIEW_ON; - message.data[1] = 1; - sendCECMessage(message); + message.length = 1; + SendCECMessage(message); + usleep(10000); + message.address = 0x0f; /* broadcast */ + message.data[0] = CEC_MSG_ACTIVE_SOURCE; + message.data[1] = ((((int)physicalAddress >> 12) & 0xf) << 4) + (((int)physicalAddress >> 8) & 0xf); + message.data[2] = ((((int)physicalAddress >> 4) & 0xf) << 4) + (((int)physicalAddress >> 0) & 0xf); + message.length = 3; + SendCECMessage(message); } } diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index 2d2e787..2090ab5 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -181,7 +181,7 @@ class cVideo int64_t GetPTS(void); unsigned char physicalAddress[2]; - bool fixedAddress,standby_cec_activ,autoview_cec_activ; + bool standby_cec_activ,autoview_cec_activ; unsigned char deviceType, logicalAddress; int hdmiFd; @@ -229,9 +229,10 @@ class cVideo bool SetCECMode(VIDEO_HDMI_CEC_MODE); void SetCECAutoView(bool); void SetCECAutoStandby(bool); - void getCECAddressInfo(); - void sendCECMessage(struct cec_message &message); + void GetCECAddressInfo(); + void SendCECMessage(struct cec_message &message); void SetCECState(bool state); + void ReportPhysicalAddress(); void ShowPicture(const char * fname, const char *_destname = NULL); void StopPicture(); void Standby(unsigned int bOn); From 0b69bc17f90f165c148a2613a3fe1f0ab4f93bae Mon Sep 17 00:00:00 2001 From: TangoCash Date: Thu, 19 Oct 2017 21:39:55 +0200 Subject: [PATCH 67/73] armbox: improve cec --- libarmbox/video.cpp | 18 ++++++++++++++++-- libarmbox/video_lib.h | 5 ++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index f5f0964..7e62f5b 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -161,6 +161,7 @@ cVideo::cVideo(int, void *, void *, unsigned int unit) } else devnum = unit; fd = -1; + hdmiFd = -1; standby_cec_activ = autoview_cec_activ = false; openDevice(); } @@ -815,9 +816,21 @@ bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) physicalAddress[0] = 0x10; physicalAddress[1] = 0x00; logicalAddress = 1; - deviceType = 1; /* default: recorder */ + + if (_deviceType == VIDEO_HDMI_CEC_MODE_OFF) + { + if (hdmiFd >= 0) { + close hdmiFd; + hdmiFd = -1; + } + return false; + } + else + deviceType = _deviceType; + + if (hdmiFd == -1) + hdmiFd = open("/dev/cec0", O_RDWR | O_CLOEXEC); - hdmiFd = open("/dev/cec0", O_RDWR | O_CLOEXEC); if (hdmiFd >= 0) { __u32 monitor = CEC_MODE_INITIATOR | CEC_MODE_FOLLOWER; @@ -891,6 +904,7 @@ bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) GetCECAddressInfo(); + return true; } void cVideo::GetCECAddressInfo() diff --git a/libarmbox/video_lib.h b/libarmbox/video_lib.h index 2090ab5..15224bc 100644 --- a/libarmbox/video_lib.h +++ b/libarmbox/video_lib.h @@ -118,11 +118,10 @@ typedef enum { VIDEO_STD_MAX = VIDEO_STD_AUTO } VIDEO_STD; -/* not used, for dummy functions */ typedef enum { VIDEO_HDMI_CEC_MODE_OFF = 0, - VIDEO_HDMI_CEC_MODE_TUNER, - VIDEO_HDMI_CEC_MODE_RECORDER + VIDEO_HDMI_CEC_MODE_TUNER = 3, + VIDEO_HDMI_CEC_MODE_RECORDER = 1 } VIDEO_HDMI_CEC_MODE; typedef enum From 36cc88ad7e37e332cf517f2a0b3bbb1b8d10ae39 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Thu, 19 Oct 2017 21:42:11 +0200 Subject: [PATCH 68/73] fix typo --- libarmbox/video.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 7e62f5b..ed5b3a1 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -820,7 +820,7 @@ bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) if (_deviceType == VIDEO_HDMI_CEC_MODE_OFF) { if (hdmiFd >= 0) { - close hdmiFd; + close(hdmiFd); hdmiFd = -1; } return false; From 5ae1ba0530c1db3994eecb297c918fdcb9854817 Mon Sep 17 00:00:00 2001 From: Jacek Jendrzej Date: Fri, 20 Oct 2017 19:21:41 +0200 Subject: [PATCH 69/73] rmove unused code --- libarmbox/playback_gst.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index 84baf20..b8cd307 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -462,7 +462,6 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, mAudioStream = 0; //create playback path - char file[400] = {""}; bool isHTTP = false; if(!strncmp("http://", filename, 7)) @@ -493,10 +492,6 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, { isHTTP = true; } - else - strcat(file, "file://"); - - strcat(file, filename); if (isHTTP) uri = g_uri_escape_string(filename, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS, true); From 6f261730ffee08395743eb1b97665f42696a1289 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sat, 21 Oct 2017 18:28:57 +0200 Subject: [PATCH 70/73] armbox: gstreamer - fix init jump, cleanup --- libarmbox/playback_gst.cpp | 66 ++++++++++++++++++++++++++++---------- libarmbox/playback_gst.h | 2 ++ libarmbox/video.cpp | 12 +++---- 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index b8cd307..dcb5d36 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -375,6 +375,7 @@ cPlayback::cPlayback(int num) playing = false; playstate = STATE_STOP; + decoders_closed = false; } cPlayback::~cPlayback() @@ -387,6 +388,15 @@ cPlayback::~cPlayback() bool cPlayback::Open(playmode_t PlayMode) { lt_info("%s: PlayMode %d\n", __func__, PlayMode); + + if (PlayMode != PLAYMODE_TS) + { + audioDecoder->closeDevice(); + videoDecoder->closeDevice(); + decoders_closed = true; + } + + init_jump = -1; return true; } @@ -435,11 +445,12 @@ void cPlayback::Close(void) m_gst_playbin = NULL; - videoDecoder->openDevice(); - audioDecoder->openDevice(); - - //videoDemux->Start(); - //audioDemux->Start(); + if (decoders_closed) + { + audioDecoder->openDevice(); + videoDecoder->openDevice(); + decoders_closed = false; + } } } @@ -460,6 +471,7 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, extra_headers.clear(); mAudioStream = 0; + init_jump = -1; //create playback path bool isHTTP = false; @@ -511,13 +523,6 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, if(m_gst_playbin) { - - //videoDemux->Stop(); - //audioDemux->Stop(); - - videoDecoder->closeDevice(); - audioDecoder->closeDevice(); - lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__); if(isHTTP) @@ -540,10 +545,18 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, gst_object_unref(bus); // state playing - gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING); + if(isHTTP) + { + gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING); + playstate = STATE_PLAY; + } + else + { + gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PAUSED); + playstate = STATE_PAUSE; + } playing = true; - playstate = STATE_PLAY; } else { @@ -642,6 +655,14 @@ bool cPlayback::SetSpeed(int speed) { lt_info( "%s:%s speed %d\n", FILENAME, __FUNCTION__, speed); + if (!decoders_closed) + { + audioDecoder->closeDevice(); + videoDecoder->closeDevice(); + decoders_closed = true; + usleep(500000); + } + if(playing == false) return false; @@ -676,6 +697,12 @@ bool cPlayback::SetSpeed(int speed) // playstate = STATE_REW; } + + if (init_jump > -1) + { + SetPosition(init_jump,true); + init_jump = -1; + } } mSpeed = speed; @@ -753,15 +780,20 @@ bool cPlayback::SetPosition(int position, bool absolute) { lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing); - if(playing == false) - return false; - gint64 time_nanoseconds; gint64 pos; GstFormat fmt = GST_FORMAT_TIME; + GstState state; if(m_gst_playbin) { + gst_element_get_state(m_gst_playbin, &state, NULL, GST_CLOCK_TIME_NONE); + + if ( state == GST_STATE_PAUSED ) + { + init_jump = position; + return false; + } if (!absolute) { gst_element_query_position(m_gst_playbin, fmt, &pos); diff --git a/libarmbox/playback_gst.h b/libarmbox/playback_gst.h index 5dfcbfc..396989e 100644 --- a/libarmbox/playback_gst.h +++ b/libarmbox/playback_gst.h @@ -48,9 +48,11 @@ class cPlayback { private: bool playing; + bool decoders_closed; int mSpeed; int mAudioStream; + int init_jump; public: playstate_t playstate; diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index ed5b3a1..5269187 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -190,8 +190,6 @@ retry: } lt_info("#%d: %s cannot open %s: %m, retries %d\n", devnum, __func__, VDEV[devnum], n); } - ioctl(fd, VIDEO_STOP, 0); - ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); playstate = VIDEO_STOPPED; } @@ -200,10 +198,6 @@ void cVideo::closeDevice(void) lt_debug("%s\n", __func__); /* looks like sometimes close is unhappy about non-empty buffers */ Start(); - ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY); - ioctl(fd, VIDEO_PLAY); - ioctl(fd, VIDEO_CONTINUE); - ioctl(fd, VIDEO_CLEAR_BUFFER); if (fd >= 0) close(fd); fd = -1; @@ -280,6 +274,12 @@ int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned sho if (playstate == VIDEO_FREEZED) /* in theory better, but not in practice :-) */ fop(ioctl, MPEG_VID_CONTINUE); #endif + /* implicitly do StopPicture() on video->Start() */ + if (stillpicture) { + lt_info("%s: stillpicture == true, doing implicit StopPicture()\n", __func__); + stillpicture = false; + Stop(1); + } playstate = VIDEO_PLAYING; fop(ioctl, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); int res = fop(ioctl, VIDEO_PLAY); From 07d9206a5640aeaa2217748a90183e90c7742c0c Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 22 Oct 2017 10:46:57 +0200 Subject: [PATCH 71/73] armbox: fix gst playback --- libarmbox/playback_gst.cpp | 22 +++++++++------------- libarmbox/playback_gst.h | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index dcb5d36..ec16ddd 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -376,6 +376,7 @@ cPlayback::cPlayback(int num) playing = false; playstate = STATE_STOP; decoders_closed = false; + first = false; } cPlayback::~cPlayback() @@ -544,6 +545,8 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, gst_bus_set_sync_handler(bus, Gst_bus_call, NULL, NULL); gst_object_unref(bus); + first = true; + // state playing if(isHTTP) { @@ -629,25 +632,17 @@ bool cPlayback::SetAPid(int pid, bool /*ac3*/) void cPlayback::trickSeek(int ratio) { - bool validposition = false; + GstFormat fmt = GST_FORMAT_TIME; gint64 pos = 0; - int position; - int duration; - - if( GetPosition(position, duration) ) - { - validposition = true; - pos = position*1000000; - } gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); - if (validposition) + if (gst_element_query_position(m_gst_playbin, fmt, &pos)) { if(ratio >= 0.0) - gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1); + gst_element_seek(m_gst_playbin, ratio, fmt, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP | GST_SEEK_FLAG_ACCURATE), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1); else - gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos); + gst_element_seek(m_gst_playbin, ratio, fmt, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP | GST_SEEK_FLAG_ACCURATE), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos); } } @@ -789,9 +784,10 @@ bool cPlayback::SetPosition(int position, bool absolute) { gst_element_get_state(m_gst_playbin, &state, NULL, GST_CLOCK_TIME_NONE); - if ( state == GST_STATE_PAUSED ) + if ( (state == GST_STATE_PAUSED) && first) { init_jump = position; + first = false; return false; } if (!absolute) diff --git a/libarmbox/playback_gst.h b/libarmbox/playback_gst.h index 396989e..a58de78 100644 --- a/libarmbox/playback_gst.h +++ b/libarmbox/playback_gst.h @@ -47,7 +47,7 @@ struct AVFormatContext; class cPlayback { private: - bool playing; + bool playing, first; bool decoders_closed; int mSpeed; From e4fca206a2cb4687a7f81f42ca008dc09dbb1aa5 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Sun, 22 Oct 2017 11:03:04 +0200 Subject: [PATCH 72/73] partly revert last commit --- libarmbox/playback_gst.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index ec16ddd..f240748 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -640,9 +640,9 @@ void cPlayback::trickSeek(int ratio) if (gst_element_query_position(m_gst_playbin, fmt, &pos)) { if(ratio >= 0.0) - gst_element_seek(m_gst_playbin, ratio, fmt, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP | GST_SEEK_FLAG_ACCURATE), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1); + gst_element_seek(m_gst_playbin, ratio, fmt, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1); else - gst_element_seek(m_gst_playbin, ratio, fmt, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP | GST_SEEK_FLAG_ACCURATE), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos); + gst_element_seek(m_gst_playbin, ratio, fmt, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos); } } From 3ec44df06f9b85ce096d999ee96948c28ac384fc Mon Sep 17 00:00:00 2001 From: Jacek Jendrzej Date: Mon, 23 Oct 2017 11:51:10 +0200 Subject: [PATCH 73/73] fix uri for http --- libarmbox/playback_gst.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libarmbox/playback_gst.cpp b/libarmbox/playback_gst.cpp index f240748..548d22f 100644 --- a/libarmbox/playback_gst.cpp +++ b/libarmbox/playback_gst.cpp @@ -507,7 +507,7 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, } if (isHTTP) - uri = g_uri_escape_string(filename, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS, true); + uri = g_strdup_printf ("%s", filename); else uri = g_filename_to_uri(filename, NULL, NULL);