* drivers/timers/fake_capture.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/kmalloc.h>
#include <nuttx/spinlock.h>
#include <nuttx/wdog.h>
#include <nuttx/timers/capture.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <debug.h>
* Pre-processor Definitions
****************************************************************************/
#define CAPTURE_DUTY_DEFAULT 50
#define CAPTURE_FREQ_DEFAULT 10
* Private Types
****************************************************************************/
struct fake_capture_s
{
struct cap_lowerhalf_s lower;
spinlock_t lock;
struct wdog_s wdog;
bool high;
capture_notify_t cb;
FAR void *priv;
enum cap_type_e type;
};
* Private Function Prototypes
****************************************************************************/
static int fake_capture_start(FAR struct cap_lowerhalf_s *lower);
static int fake_capture_stop(FAR struct cap_lowerhalf_s *lower);
static int fake_capture_getduty(FAR struct cap_lowerhalf_s *lower,
FAR uint8_t *duty);
static int fake_capture_getfreq(FAR struct cap_lowerhalf_s *lower,
FAR uint32_t *freq);
static int fake_capture_getedges(FAR struct cap_lowerhalf_s *lower,
FAR uint32_t *edges);
static int fake_capture_bind(FAR struct cap_lowerhalf_s *lower,
enum cap_type_e type, capture_notify_t cb,
FAR void *priv);
static int fake_capture_unbind(FAR struct cap_lowerhalf_s *lower);
* Private Data
****************************************************************************/
static const struct cap_ops_s g_fake_cap_ops =
{
.start = fake_capture_start,
.stop = fake_capture_stop,
.getduty = fake_capture_getduty,
.getfreq = fake_capture_getfreq,
.getedges = fake_capture_getedges,
.bind = fake_capture_bind,
.unbind = fake_capture_unbind,
};
* Private Functions
****************************************************************************/
static void fake_capture_isr(wdparm_t arg)
{
FAR struct fake_capture_s *capture = (FAR struct fake_capture_s *)arg;
irqstate_t flags;
bool last;
flags = spin_lock_irqsave(&capture->lock);
last = capture->high;
capture->high = !capture->high;
if (capture->cb != NULL &&
(capture->type == CAP_TYPE_BOTH ||
(capture->type == CAP_TYPE_RISING && !last) ||
(capture->type == CAP_TYPE_FALLING && last)))
{
capture->cb(&capture->lower, capture->priv);
}
spin_unlock_irqrestore(&capture->lock, flags);
wd_start_next(&capture->wdog, MSEC2TICK(1000 / CAPTURE_FREQ_DEFAULT),
fake_capture_isr, (wdparm_t)capture);
}
* Name: fake_capture_start
*
* Description:
* This function is a requirement of the upper-half driver. When called,
* enables the capture channel, interruption routine, sets the positive
* edge to trigger this interrupt and resets the frequency and duty
* values. The positive edge is always the first expected.
*
* Input Parameters:
* lower - Pointer to the capture channel lower-half data structure.
*
* Returned Value:
* Returns OK on success.
*
****************************************************************************/
static int fake_capture_start(FAR struct cap_lowerhalf_s *lower)
{
FAR struct fake_capture_s *capture = (FAR struct fake_capture_s *)lower;
wd_start(&capture->wdog, MSEC2TICK(1000 / CAPTURE_FREQ_DEFAULT),
fake_capture_isr, (wdparm_t)capture);
return OK;
}
* Name: fake_capture_stop
*
* Description:
* This function is a requirement of the upper-half driver. When called,
* disables the capture channel and the interrupt routine associated.
*
* Input Parameters:
* lower - Pointer to the capture channel lower-half data structure.
*
* Returned Value:
* Returns OK on success.
*
****************************************************************************/
static int fake_capture_stop(FAR struct cap_lowerhalf_s *lower)
{
FAR struct fake_capture_s *capture = (FAR struct fake_capture_s *)lower;
wd_cancel(&capture->wdog);
return OK;
}
* Name: fake_capture_getduty
*
* Description:
* This function is a requirement of the upper-half driver. Returns
* the last calculated duty cycle value.
*
* Input Parameters:
* lower - Pointer to the capture channel lower-half data structure.
* duty - uint8_t pointer where the duty cycle value is written.
*
* Returned Value:
* Returns OK on success.
*
****************************************************************************/
static int fake_capture_getduty(FAR struct cap_lowerhalf_s *lower,
FAR uint8_t *duty)
{
*duty = CAPTURE_DUTY_DEFAULT;
return OK;
}
* Name: fake_capture_getfreq
*
* Description:
* This function is a requirement of the upper-half driver. Returns
* the last calculated frequency value.
*
* Input Parameters:
* lower - Pointer to the capture channel lower-half data structure.
* duty - uint8_t pointer where the frequency value is written.
*
* Returned Value:
* Returns OK on success.
*
****************************************************************************/
static int fake_capture_getfreq(FAR struct cap_lowerhalf_s *lower,
FAR uint32_t *freq)
{
*freq = CAPTURE_FREQ_DEFAULT;
return OK;
}
* Name: fake_capture_getedges
*
* Description:
* This function is a requirement of the upper-half driver. Returns
* the current edge type configured for the capture channel.
*
* Input Parameters:
* lower - Pointer to the capture channel lower-half data structure.
* type - Pointer to the edge type variable to be updated.
*
* Returned Value:
* Returns OK on success.
*
****************************************************************************/
static int fake_capture_getedges(FAR struct cap_lowerhalf_s *lower,
FAR uint32_t *edges)
{
FAR struct fake_capture_s *capture = (FAR struct fake_capture_s *)lower;
irqstate_t flags = spin_lock_irqsave(&capture->lock);
*edges = capture->high;
spin_unlock_irqrestore(&capture->lock, flags);
return OK;
}
* Name: fake_capture_bind
*
* Description:
* This function is used to bind a upper-half provided callback that will
* be invoked upon capture edge events.
*
* Input Parameters:
* lower - Pointer to the capture channel lower-half data structure.
* cb - The callback function pointer.
* priv - The private argument to be passed to the callback function.
* edge - The edge type that will trigger the callback.
*
* Returned Value:
* Returns OK on success.
*
****************************************************************************/
static int fake_capture_bind(FAR struct cap_lowerhalf_s *lower,
enum cap_type_e type, capture_notify_t cb,
FAR void *priv)
{
FAR struct fake_capture_s *capture = (FAR struct fake_capture_s *)lower;
irqstate_t flags = spin_lock_irqsave(&capture->lock);
capture->cb = cb;
capture->priv = priv;
capture->type = type;
spin_unlock_irqrestore(&capture->lock, flags);
return 0;
}
* Name: fake_capture_unbind
*
* Description:
* This function is used to un-bind a previously bound upper-half provided
* callback that was to be invoked upon capture edge events.
*
* Input Parameters:
* lower - Pointer to the capture channel lower-half data structure.
*
* Returned Value:
* Returns OK on success.
*
****************************************************************************/
static int fake_capture_unbind(FAR struct cap_lowerhalf_s *lower)
{
FAR struct fake_capture_s *capture = (FAR struct fake_capture_s *)lower;
irqstate_t flags = spin_lock_irqsave(&capture->lock);
capture->cb = NULL;
capture->priv = NULL;
spin_unlock_irqrestore(&capture->lock, flags);
return 0;
}
* Public Functions
****************************************************************************/
* Name: fake_capture_initialize
*
* Description:
* This function is called by board-specific logic to initialize
* fake capture.
*
* Input Parameters:
* channel - The capture channel number to initialize.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure. The following
* possible error values may be returned (most are returned by
* register_driver()):
*
****************************************************************************/
int fake_capture_initialize(int channels)
{
char path[32];
int ret = 0;
int i;
for (i = 0; i < channels; i++)
{
FAR struct fake_capture_s *priv;
priv = kmm_zalloc(sizeof(*priv));
DEBUGASSERT(priv);
spin_lock_init(&priv->lock);
priv->lower.ops = &g_fake_cap_ops;
snprintf(path, sizeof(path), "/dev/fake_capture%d", i);
ret = cap_register(path, &priv->lower);
if (ret < 0)
{
cperr("Failed to register capture:%d\n", ret);
kmm_free(priv);
break;
}
}
return ret;
}