From patchwork Tue Mar 31 17:48:07 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?QW50dGkgU2VwcMOkbMOk?= X-Patchwork-Id: 6133181 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 39511BF4A6 for ; Tue, 31 Mar 2015 17:49:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6685F201BB for ; Tue, 31 Mar 2015 17:49:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B361A201C0 for ; Tue, 31 Mar 2015 17:49:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752570AbbCaRs6 (ORCPT ); Tue, 31 Mar 2015 13:48:58 -0400 Received: from mail-lb0-f182.google.com ([209.85.217.182]:36451 "EHLO mail-lb0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752285AbbCaRs5 (ORCPT ); Tue, 31 Mar 2015 13:48:57 -0400 Received: by lbbug6 with SMTP id ug6so18245085lbb.3 for ; Tue, 31 Mar 2015 10:48:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=k/hvC59sQpK7LlHDgFc6mh4OXOAEmg2WdQi8DL/1bFY=; b=WNd3Tqv6FAln+NTUfd0CYKAzsYAe77v2mKJ97oA1YBCyqA0YaOeBi8c4b6JInGjlBn 55v8Tt/P3NF6PRJ9Jg8F2ZQJzrSQBQ6LQVTN45x+jNzy8dBltsjAOsYCOq2EmhvZOgTp QbNNE5f5T9ScNDeYODTQfuqzgfrfHgp6dL4Xj5X3GQfLnntQC5Nr1doauVVtR6880iZu k90K9wYHah0JOymX1Jxa3OjD9YDSfaGR+EoGnWjgRjrBjSh2ly+ErBLROovBAFZmr4km 7hi7IUz8kPLZwdLTYc0HNXzPyO2imgBDJ/4s6IPP69OrQ1BMsaqsiplhp3SaF2aIikaV DvpQ== X-Received: by 10.112.118.73 with SMTP id kk9mr7127850lbb.3.1427824135574; Tue, 31 Mar 2015 10:48:55 -0700 (PDT) Received: from pixie.elisa-laajakaista.fi (a91-154-178-36.elisa-laajakaista.fi. [91.154.178.36]) by mx.google.com with ESMTPSA id qw1sm2771382lbb.21.2015.03.31.10.48.54 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 31 Mar 2015 10:48:54 -0700 (PDT) From: =?UTF-8?q?Antti=20Sepp=C3=A4l=C3=A4?= To: linux-media@vger.kernel.org Cc: Mauro Carvalho Chehab , =?UTF-8?q?Antti=20Sepp=C3=A4l=C3=A4?= , James Hogan , =?UTF-8?q?David=20H=C3=A4rdeman?= Subject: [PATCH v3 2/7] rc: rc-ir-raw: Add Manchester encoder (phase encoder) helper Date: Tue, 31 Mar 2015 20:48:07 +0300 Message-Id: <1427824092-23163-3-git-send-email-a.seppala@gmail.com> X-Mailer: git-send-email 2.0.5 In-Reply-To: <1427824092-23163-1-git-send-email-a.seppala@gmail.com> References: <1427824092-23163-1-git-send-email-a.seppala@gmail.com> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Adding a simple Manchester encoder to rc-core. Manchester coding is used by at least RC-5 and RC-6 protocols and their variants. Signed-off-by: Antti Seppälä Signed-off-by: James Hogan Cc: David Härdeman --- Notes: Changes in v3: - Ported to apply against latest media-tree - Enhanced to support rc-6 encoding - Checkpatch.pl fixes Changes in v2 (James Hogan): - Alter encode API to return -ENOBUFS when there isn't enough buffer space. When this occurs all buffer contents must have been written with the partial encoding of the scancode. This is to allow drivers such as nuvoton-cir to provide a shorter buffer and still get a useful partial encoding for the wakeup pattern. - Add kerneldoc comment. - Add individual buffer full checks, in order to support -ENOBUFS properly. - Make i unsigned to theoretically support all 32bits of data. - Increment *ev at end so caller can calculate correct number of events (during the loop *ev points to the last written event to allow it to be extended in length). - Make start/leader pulse optional, continuing from (*ev)[-1] if disabled. This helps support rc-5x which has a space in the middle of the bits. drivers/media/rc/rc-core-priv.h | 33 ++++++++++++++++ drivers/media/rc/rc-ir-raw.c | 85 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 122c25f..5266ecc7 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -152,6 +152,39 @@ static inline bool is_timing_event(struct ir_raw_event ev) #define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000) #define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") +/* functions for IR encoders */ + +static inline void init_ir_raw_event_duration(struct ir_raw_event *ev, + unsigned int pulse, + u32 duration) +{ + init_ir_raw_event(ev); + ev->duration = duration; + ev->pulse = pulse; +} + +/** + * struct ir_raw_timings_manchester - Manchester coding timings + * @leader: duration of leader pulse (if any) 0 if continuing + * existing signal (see @pulse_space_start) + * @pulse_space_start: 1 for starting with pulse (0 for starting with space) + * @clock: duration of each pulse/space in ns + * @invert: if set clock logic is inverted + * (0 = space + pulse, 1 = pulse + space) + * @trailer_space: duration of trailer space in ns + */ +struct ir_raw_timings_manchester { + unsigned int leader; + unsigned int pulse_space_start:1; + unsigned int clock; + unsigned int invert:1; + unsigned int trailer_space; +}; + +int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max, + const struct ir_raw_timings_manchester *timings, + unsigned int n, unsigned int data); + /* * Routines from rc-raw.c to be used internally and by decoders */ diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index dd47fe5..6c9580e 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -247,6 +247,91 @@ static int change_protocol(struct rc_dev *dev, u64 *rc_type) } /** + * ir_raw_gen_manchester() - Encode data with Manchester (bi-phase) modulation. + * @ev: Pointer to pointer to next free event. *@ev is incremented for + * each raw event filled. + * @max: Maximum number of raw events to fill. + * @timings: Manchester modulation timings. + * @n: Number of bits of data. + * @data: Data bits to encode. + * + * Encodes the @n least significant bits of @data using Manchester (bi-phase) + * modulation with the timing characteristics described by @timings, writing up + * to @max raw IR events using the *@ev pointer. + * + * Returns: 0 on success. + * -ENOBUFS if there isn't enough space in the array to fit the + * full encoded data. In this case all @max events will have been + * written. + */ +int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max, + const struct ir_raw_timings_manchester *timings, + unsigned int n, unsigned int data) +{ + bool need_pulse; + unsigned int i; + int ret = -ENOBUFS; + + i = 1 << (n - 1); + + if (timings->leader) { + if (!max--) + return ret; + if (timings->pulse_space_start) { + init_ir_raw_event_duration((*ev)++, 1, timings->leader); + + if (!max--) + return ret; + init_ir_raw_event_duration((*ev), 0, timings->leader); + } else { + init_ir_raw_event_duration((*ev), 1, timings->leader); + } + i >>= 1; + } else { + /* continue existing signal */ + --(*ev); + } + /* from here on *ev will point to the last event rather than the next */ + + while (n && i > 0) { + need_pulse = !(data & i); + if (timings->invert) + need_pulse = !need_pulse; + if (need_pulse == !!(*ev)->pulse) { + (*ev)->duration += timings->clock; + } else { + if (!max--) + goto nobufs; + init_ir_raw_event_duration(++(*ev), need_pulse, + timings->clock); + } + + if (!max--) + goto nobufs; + init_ir_raw_event_duration(++(*ev), !need_pulse, + timings->clock); + i >>= 1; + } + + if (timings->trailer_space) { + if (!(*ev)->pulse) + (*ev)->duration += timings->trailer_space; + else if (!max--) + goto nobufs; + else + init_ir_raw_event_duration(++(*ev), 0, + timings->trailer_space); + } + + ret = 0; +nobufs: + /* point to the next event rather than last event before returning */ + ++(*ev); + return ret; +} +EXPORT_SYMBOL(ir_raw_gen_manchester); + +/** * ir_raw_encode_scancode() - Encode a scancode as raw events * * @protocols: permitted protocols