PX4 Firmware
PX4 Autopilot Software http://px4.io
pwm_input.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2015 Andrew Tridgell. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file pwm_input.cpp
36  *
37  * PWM input driver based on earlier driver from Evan Slatyer,
38  * which in turn was based on drv_hrt.c
39  *
40  * @author: Andrew Tridgell
41  * @author: Ban Siesta <bansiesta@gmail.com>
42  */
43 
44 #include <px4_platform_common/px4_config.h>
45 #include <px4_platform_common/time.h>
46 #include <nuttx/arch.h>
47 #include <nuttx/irq.h>
48 
49 #include <sys/types.h>
50 #include <stdbool.h>
51 
52 #include <assert.h>
53 #include <debug.h>
54 #include <time.h>
55 #include <queue.h>
56 #include <errno.h>
57 #include <string.h>
58 #include <math.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61 
62 #include <board_config.h>
63 #include <drivers/drv_pwm_input.h>
64 #include <drivers/drv_hrt.h>
66 
67 #include "chip.h"
68 #include "up_internal.h"
69 #include "up_arch.h"
70 
71 #include "stm32_gpio.h"
72 #include "stm32_tim.h"
73 #include <systemlib/err.h>
74 
75 #include <uORB/uORB.h>
76 #include <uORB/topics/pwm_input.h>
77 
78 #include <drivers/drv_device.h>
79 #include <drivers/device/device.h>
81 
82 #include <sys/types.h>
83 #include <sys/stat.h>
84 #include <fcntl.h>
85 
86 /* Reset pin define */
87 #define GPIO_VDD_RANGEFINDER_EN GPIO_GPIO5_OUTPUT
88 
89 #if HRT_TIMER == PWMIN_TIMER
90 #error cannot share timer between HRT and PWMIN
91 #endif
92 
93 #if !defined(GPIO_PWM_IN) || !defined(PWMIN_TIMER) || !defined(PWMIN_TIMER_CHANNEL)
94 #error PWMIN defines are needed in board_config.h for this board
95 #endif
96 
97 /* Get the timer defines */
98 #define INPUT_TIMER PWMIN_TIMER
99 #include "timer_registers.h"
100 #define PWMIN_TIMER_BASE TIMER_BASE
101 #define PWMIN_TIMER_CLOCK TIMER_CLOCK
102 #define PWMIN_TIMER_POWER_REG TIMER_CLOCK_POWER_REG
103 #define PWMIN_TIMER_POWER_BIT TIMER_CLOCK_POWER_BIT
104 #define PWMIN_TIMER_VECTOR TIMER_IRQ_REG
105 
106 /*
107  * HRT clock must be at least 1MHz
108  */
109 #if PWMIN_TIMER_CLOCK <= 1000000
110 # error PWMIN_TIMER_CLOCK must be greater than 1MHz
111 #endif
112 
113 /*
114  * Timer register accessors
115  */
116 #define REG(_reg) (*(volatile uint32_t *)(PWMIN_TIMER_BASE + _reg))
117 
118 #define rCR1 REG(STM32_GTIM_CR1_OFFSET)
119 #define rCR2 REG(STM32_GTIM_CR2_OFFSET)
120 #define rSMCR REG(STM32_GTIM_SMCR_OFFSET)
121 #define rDIER REG(STM32_GTIM_DIER_OFFSET)
122 #define rSR REG(STM32_GTIM_SR_OFFSET)
123 #define rEGR REG(STM32_GTIM_EGR_OFFSET)
124 #define rCCMR1 REG(STM32_GTIM_CCMR1_OFFSET)
125 #define rCCMR2 REG(STM32_GTIM_CCMR2_OFFSET)
126 #define rCCER REG(STM32_GTIM_CCER_OFFSET)
127 #define rCNT REG(STM32_GTIM_CNT_OFFSET)
128 #define rPSC REG(STM32_GTIM_PSC_OFFSET)
129 #define rARR REG(STM32_GTIM_ARR_OFFSET)
130 #define rCCR1 REG(STM32_GTIM_CCR1_OFFSET)
131 #define rCCR2 REG(STM32_GTIM_CCR2_OFFSET)
132 #define rCCR3 REG(STM32_GTIM_CCR3_OFFSET)
133 #define rCCR4 REG(STM32_GTIM_CCR4_OFFSET)
134 #define rDCR REG(STM32_GTIM_DCR_OFFSET)
135 #define rDMAR REG(STM32_GTIM_DMAR_OFFSET)
136 
137 /*
138  * Specific registers and bits used by HRT sub-functions
139  */
140 #if PWMIN_TIMER_CHANNEL == 1
141 #define rCCR_PWMIN_A rCCR1 /* compare register for PWMIN */
142 #define DIER_PWMIN_A (GTIM_DIER_CC1IE) /* interrupt enable for PWMIN */
143 #define SR_INT_PWMIN_A GTIM_SR_CC1IF /* interrupt status for PWMIN */
144 #define rCCR_PWMIN_B rCCR2 /* compare register for PWMIN */
145 #define SR_INT_PWMIN_B GTIM_SR_CC2IF /* interrupt status for PWMIN */
146 #define CCMR1_PWMIN ((0x02 << GTIM_CCMR1_CC2S_SHIFT) | (0x01 << GTIM_CCMR1_CC1S_SHIFT))
147 #define CCMR2_PWMIN 0
148 #define CCER_PWMIN (GTIM_CCER_CC2P | GTIM_CCER_CC1E | GTIM_CCER_CC2E)
149 #define SR_OVF_PWMIN (GTIM_SR_CC1OF | GTIM_SR_CC2OF)
150 #define SMCR_PWMIN_1 (0x05 << GTIM_SMCR_TS_SHIFT)
151 #define SMCR_PWMIN_2 ((0x04 << GTIM_SMCR_SMS_SHIFT) | SMCR_PWMIN_1)
152 #elif PWMIN_TIMER_CHANNEL == 2
153 #define rCCR_PWMIN_A rCCR2 /* compare register for PWMIN */
154 #define DIER_PWMIN_A (GTIM_DIER_CC2IE) /* interrupt enable for PWMIN */
155 #define SR_INT_PWMIN_A GTIM_SR_CC2IF /* interrupt status for PWMIN */
156 #define rCCR_PWMIN_B rCCR1 /* compare register for PWMIN */
157 #define DIER_PWMIN_B GTIM_DIER_CC1IE /* interrupt enable for PWMIN */
158 #define SR_INT_PWMIN_B GTIM_SR_CC1IF /* interrupt status for PWMIN */
159 #define CCMR1_PWMIN ((0x01 << GTIM_CCMR1_CC2S_SHIFT) | (0x02 << GTIM_CCMR1_CC1S_SHIFT))
160 #define CCMR2_PWMIN 0
161 #define CCER_PWMIN (GTIM_CCER_CC1P | GTIM_CCER_CC1E | GTIM_CCER_CC2E)
162 #define SR_OVF_PWMIN (GTIM_SR_CC1OF | GTIM_SR_CC2OF)
163 #define SMCR_PWMIN_1 (0x06 << GTIM_SMCR_TS_SHIFT)
164 #define SMCR_PWMIN_2 ((0x04 << GTIM_SMCR_SMS_SHIFT) | SMCR_PWMIN_1)
165 #else
166 #error PWMIN_TIMER_CHANNEL must be either 1 and 2.
167 #endif
168 
169 // XXX refactor this out of this driver
170 #define TIMEOUT_POLL 300000 /* reset after no response over this time in microseconds [0.3s] */
171 #define TIMEOUT_READ 200000 /* don't reset if the last read is back more than this time in microseconds [0.2s] */
172 
174 {
175 public:
176  PWMIN();
177  virtual ~PWMIN();
178 
179  virtual int init();
180  virtual int open(struct file *filp);
181  virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
182  virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
183 
184  void publish(uint16_t status, uint32_t period, uint32_t pulse_width);
185  void print_info(void);
186  void hard_reset();
187 
188 private:
189  uint32_t _error_count;
191  uint32_t _last_period;
192  uint32_t _last_width;
195  ringbuffer::RingBuffer *_reports;
197 
198  hrt_call _hard_reset_call; /* HRT callout for note completion */
199  hrt_call _freeze_test_call; /* HRT callout for note completion */
200 
201  void _timer_init(void);
202 
203  void _turn_on();
204  void _turn_off();
205  void _freeze_test();
206 
207 };
208 
209 static int pwmin_tim_isr(int irq, void *context, void *arg);
210 static void pwmin_start();
211 static void pwmin_info(void);
212 static void pwmin_test(void);
213 static void pwmin_reset(void);
214 static void pwmin_usage(void);
215 
216 static PWMIN *g_dev;
217 
220  _error_count(0),
221  _pulses_captured(0),
222  _last_period(0),
223  _last_width(0),
224  _reports(nullptr),
225  _timer_started(false)
226 {
227 }
228 
230 {
231  if (_reports != nullptr) {
232  delete _reports;
233  }
234 }
235 
236 /*
237  * initialise the driver. This doesn't actually start the timer (that
238  * is done on open). We don't start the timer to allow for this driver
239  * to be started in init scripts when the user may be using the input
240  * pin as PWM output
241  */
242 int
244 {
245  /* we just register the device in /dev, and only actually
246  * activate the timer when requested to when the device is opened */
247  CDev::init();
248 
249  _reports = new ringbuffer::RingBuffer(2, sizeof(struct pwm_input_s));
250 
251  if (_reports == nullptr) {
252  return -ENOMEM;
253  }
254 
255  /* Schedule freeze check to invoke periodically */
256  hrt_call_every(&_freeze_test_call, 0, TIMEOUT_POLL, reinterpret_cast<hrt_callout>(&PWMIN::_freeze_test), this);
257 
258  return OK;
259 }
260 
261 /*
262  * Initialise the timer we are going to use.
263  */
265 {
266  /* run with interrupts disabled in case the timer is already
267  * setup. We don't want it firing while we are doing the setup */
268  irqstate_t flags = px4_enter_critical_section();
269 
270  /* configure input pin */
271  px4_arch_configgpio(GPIO_PWM_IN);
272 
273  // XXX refactor this out of this driver
274  /* configure reset pin */
275  px4_arch_configgpio(GPIO_VDD_RANGEFINDER_EN);
276 
277  /* claim our interrupt vector */
278  irq_attach(PWMIN_TIMER_VECTOR, pwmin_tim_isr, NULL);
279 
280  /* Clear no bits, set timer enable bit.*/
282 
283  /* disable and configure the timer */
284  rCR1 = 0;
285  rCR2 = 0;
286  rSMCR = 0;
287  rDIER = DIER_PWMIN_A;
288  rCCER = 0; /* unlock CCMR* registers */
289  rCCMR1 = CCMR1_PWMIN;
290  rCCMR2 = CCMR2_PWMIN;
291  rSMCR = SMCR_PWMIN_1; /* Set up mode */
292  rSMCR = SMCR_PWMIN_2; /* Enable slave mode controller */
293  rCCER = CCER_PWMIN;
294  rDCR = 0;
295 
296  /* for simplicity scale by the clock in MHz. This gives us
297  * readings in microseconds which is typically what is needed
298  * for a PWM input driver */
299  uint32_t prescaler = PWMIN_TIMER_CLOCK / 1000000UL;
300 
301  /*
302  * define the clock speed. We want the highest possible clock
303  * speed that avoids overflows.
304  */
305  rPSC = prescaler - 1;
306 
307  /* run the full span of the counter. All timers can handle
308  * uint16 */
309  rARR = UINT16_MAX;
310 
311  /* generate an update event; reloads the counter, all registers */
312  rEGR = GTIM_EGR_UG;
313 
314  /* enable the timer */
315  rCR1 = GTIM_CR1_CEN;
316 
317  /* enable interrupts */
318  up_enable_irq(PWMIN_TIMER_VECTOR);
319 
320  px4_leave_critical_section(flags);
321 
322  _timer_started = true;
323 }
324 
325 // XXX refactor this out of this driver
326 void
328 {
329  /* reset if last poll time was way back and a read was recently requested */
331  hard_reset();
332  }
333 }
334 
335 // XXX refactor this out of this driver
336 void
338 {
339  px4_arch_gpiowrite(GPIO_VDD_RANGEFINDER_EN, 1);
340 }
341 
342 // XXX refactor this out of this driver
343 void
345 {
346  px4_arch_gpiowrite(GPIO_VDD_RANGEFINDER_EN, 0);
347 }
348 
349 // XXX refactor this out of this driver
350 void
352 {
353  _turn_off();
354  hrt_call_after(&_hard_reset_call, 9000, reinterpret_cast<hrt_callout>(&PWMIN::_turn_on), this);
355 }
356 
357 /*
358  * hook for open of the driver. We start the timer at this point, then
359  * leave it running
360  */
361 int
362 PWMIN::open(struct file *filp)
363 {
364  if (g_dev == nullptr) {
365  return -EIO;
366  }
367 
368  int ret = CDev::open(filp);
369 
370  if (ret == OK && !_timer_started) {
371  g_dev->_timer_init();
372  }
373 
374  return ret;
375 }
376 
377 
378 /*
379  * handle ioctl requests
380  */
381 int
382 PWMIN::ioctl(struct file *filp, int cmd, unsigned long arg)
383 {
384  switch (cmd) {
385  case SENSORIOCRESET:
386  /* user has asked for the timer to be reset. This may
387  * be needed if the pin was used for a different
388  * purpose (such as PWM output) */
389  _timer_init();
390  /* also reset the sensor */
391  hard_reset();
392  return OK;
393 
394  default:
395  /* give it to the superclass */
396  return CDev::ioctl(filp, cmd, arg);
397  }
398 }
399 
400 
401 /*
402  * read some samples from the device
403  */
404 ssize_t
405 PWMIN::read(struct file *filp, char *buffer, size_t buflen)
406 {
408 
409  unsigned count = buflen / sizeof(struct pwm_input_s);
410  struct pwm_input_s *buf = reinterpret_cast<struct pwm_input_s *>(buffer);
411  int ret = 0;
412 
413  /* buffer must be large enough */
414  if (count < 1) {
415  return -ENOSPC;
416  }
417 
418  while (count--) {
419  if (_reports->get(buf)) {
420  ret += sizeof(struct pwm_input_s);
421  buf++;
422  }
423  }
424 
425  /* if there was no data, warn the caller */
426  return ret ? ret : -EAGAIN;
427 }
428 
429 /*
430  * publish some data from the ISR in the ring buffer
431  */
432 void PWMIN::publish(uint16_t status, uint32_t period, uint32_t pulse_width)
433 {
434  /* if we missed an edge, we have to give up */
435  if (status & SR_OVF_PWMIN) {
436  _error_count++;
437  return;
438  }
439 
441 
442  struct pwm_input_s pwmin_report;
443  pwmin_report.timestamp = _last_poll_time;
444  pwmin_report.error_count = _error_count;
445  pwmin_report.period = period;
446  pwmin_report.pulse_width = pulse_width;
447 
448  _reports->force(&pwmin_report);
449 }
450 
451 /*
452  * print information on the last captured
453  */
455 {
456  if (!_timer_started) {
457  printf("timer not started - try the 'test' command\n");
458 
459  } else {
460  printf("count=%u period=%u width=%u\n",
461  (unsigned)_pulses_captured,
462  (unsigned)_last_period,
463  (unsigned)_last_width);
464  }
465 }
466 
467 
468 /*
469  * Handle the interrupt, gathering pulse data
470  */
471 static int pwmin_tim_isr(int irq, void *context, void *arg)
472 {
473  uint16_t status = rSR;
474  uint32_t period = rCCR_PWMIN_A;
475  uint32_t pulse_width = rCCR_PWMIN_B;
476 
477  /* ack the interrupts we just read */
478  rSR = 0;
479 
480  if (g_dev != nullptr) {
481  g_dev->publish(status, period, pulse_width);
482  }
483 
484  return OK;
485 }
486 
487 /*
488  * start the driver
489  */
490 static void pwmin_start()
491 {
492  if (g_dev != nullptr) {
493  errx(1, "driver already started");
494  }
495 
496  g_dev = new PWMIN();
497 
498  if (g_dev == nullptr) {
499  errx(1, "driver allocation failed");
500  }
501 
502  if (g_dev->init() != OK) {
503  errx(1, "driver init failed");
504  }
505 
506  exit(0);
507 }
508 
509 /*
510  * test the driver
511  */
512 static void pwmin_test(void)
513 {
514  int fd = open(PWMIN0_DEVICE_PATH, O_RDONLY);
515 
516  if (fd == -1) {
517  errx(1, "Failed to open device");
518  }
519 
520  uint64_t start_time = hrt_absolute_time();
521 
522  printf("Showing samples for 5 seconds\n");
523 
524  while (hrt_absolute_time() < start_time + 5U * 1000UL * 1000UL) {
525  struct pwm_input_s buf;
526 
527  if (::read(fd, &buf, sizeof(buf)) == sizeof(buf)) {
528  printf("period=%u width=%u error_count=%u\n",
529  (unsigned)buf.period,
530  (unsigned)buf.pulse_width,
531  (unsigned)buf.error_count);
532 
533  } else {
534  /* no data, retry in 2 ms */
535  px4_usleep(2000);
536  }
537  }
538 
539  close(fd);
540  exit(0);
541 }
542 
543 /*
544  * reset the timer
545  */
546 static void pwmin_reset(void)
547 {
548  g_dev->hard_reset();
549  int fd = open(PWMIN0_DEVICE_PATH, O_RDONLY);
550 
551  if (fd == -1) {
552  errx(1, "Failed to open device");
553  }
554 
555  if (ioctl(fd, SENSORIOCRESET, 0) != OK) {
556  errx(1, "reset failed");
557  }
558 
559  close(fd);
560  exit(0);
561 }
562 
563 /*
564  * show some information on the driver
565  */
566 static void pwmin_info(void)
567 {
568  if (g_dev == nullptr) {
569  printf("driver not started\n");
570  exit(1);
571  }
572 
573  g_dev->print_info();
574  exit(0);
575 }
576 
577 static void pwmin_usage()
578 {
579  PX4_ERR("unrecognized command, try 'start', 'info', 'reset' or 'test'");
580 }
581 
582 /*
583  * driver entry point
584  */
585 int pwm_input_main(int argc, char *argv[])
586 {
587  if (argc < 2) {
588  pwmin_usage();
589  return -1;
590  }
591 
592  const char *verb = argv[1];
593 
594  /*
595  * Start/load the driver.
596  */
597  if (!strcmp(verb, "start")) {
598  pwmin_start();
599  }
600 
601  /*
602  * Print driver information.
603  */
604  if (!strcmp(verb, "info")) {
605  pwmin_info();
606  }
607 
608  /*
609  * print test results
610  */
611  if (!strcmp(verb, "test")) {
612  pwmin_test();
613  }
614 
615  /*
616  * reset the timer
617  */
618  if (!strcmp(verb, "reset")) {
619  pwmin_reset();
620  }
621 
622  pwmin_usage();
623  return -1;
624 }
#define rCCMR1
Definition: pwm_input.cpp:124
static void pwmin_reset(void)
Definition: pwm_input.cpp:546
static int pwmin_tim_isr(int irq, void *context, void *arg)
Definition: pwm_input.cpp:471
uint32_t period
Definition: pwm_input.h:56
static struct vehicle_status_s status
Definition: Commander.cpp:138
bool _timer_started
Definition: pwm_input.cpp:196
#define rDIER
Definition: pwm_input.cpp:121
API for the uORB lightweight object broker.
#define TIMEOUT_READ
Definition: pwm_input.cpp:171
static void pwmin_info(void)
Definition: pwm_input.cpp:566
virtual ssize_t read(struct file *filp, char *buffer, size_t buflen)
Definition: pwm_input.cpp:405
uint32_t _last_width
Definition: pwm_input.cpp:192
void print_info(void)
Definition: pwm_input.cpp:454
#define rCR2
Definition: pwm_input.cpp:119
uint32_t _error_count
Definition: pwm_input.cpp:189
uint32_t _last_period
Definition: pwm_input.cpp:191
hrt_call _hard_reset_call
Definition: pwm_input.cpp:198
virtual ~PWMIN()
Definition: pwm_input.cpp:229
#define rSMCR
Definition: pwm_input.cpp:120
#define rPSC
Definition: pwm_input.cpp:128
hrt_abstime _last_read_time
Definition: pwm_input.cpp:194
High-resolution timer with callouts and timekeeping.
#define rDCR
Definition: pwm_input.cpp:134
void _turn_off()
Definition: pwm_input.cpp:344
virtual int close(file_t *filep)
Handle a close of the device.
Definition: CDev.cpp:166
static void pwmin_start()
Definition: pwm_input.cpp:490
#define PWMIN_TIMER_VECTOR
Definition: pwm_input.cpp:104
uint64_t timestamp
Definition: pwm_input.h:53
virtual int open(struct file *filp)
Definition: pwm_input.cpp:362
hrt_call _freeze_test_call
Definition: pwm_input.cpp:199
#define rEGR
Definition: pwm_input.cpp:123
Generic device / sensor interface.
void _freeze_test()
Definition: pwm_input.cpp:327
__EXPORT void hrt_call_after(struct hrt_call *entry, hrt_abstime delay, hrt_callout callout, void *arg)
Call callout(arg) after delay has elapsed.
Abstract class for any character device.
Definition: CDev.hpp:58
uint64_t error_count
Definition: pwm_input.h:54
#define TIMEOUT_POLL
Definition: pwm_input.cpp:170
#define PWMIN0_DEVICE_PATH
Definition: drv_pwm_input.h:42
uint32_t pulse_width
Definition: pwm_input.h:55
void init()
Activates/configures the hardware registers.
#define PWMIN_TIMER_POWER_REG
Definition: pwm_input.cpp:102
#define rCCER
Definition: pwm_input.cpp:126
#define rCR1
Definition: pwm_input.cpp:118
static hrt_abstime hrt_elapsed_time(const hrt_abstime *then)
Compute the delta between a timestamp taken in the past and now.
Definition: drv_hrt.h:102
#define PWMIN_TIMER_CLOCK
Definition: pwm_input.cpp:101
Simple error/warning functions, heavily inspired by the BSD functions of the same names...
void hard_reset()
Definition: pwm_input.cpp:351
__EXPORT void hrt_call_every(struct hrt_call *entry, hrt_abstime delay, hrt_abstime interval, hrt_callout callout, void *arg)
Call callout(arg) after delay, and then after every interval.
#define rSR
Definition: pwm_input.cpp:122
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
int fd
Definition: dataman.cpp:146
uint32_t _pulses_captured
Definition: pwm_input.cpp:190
#define PWMIN_TIMER_POWER_BIT
Definition: pwm_input.cpp:103
static void pwmin_test(void)
Definition: pwm_input.cpp:512
#define GPIO_VDD_RANGEFINDER_EN
Definition: pwm_input.cpp:87
ringbuffer::RingBuffer * _reports
Definition: pwm_input.cpp:195
hrt_abstime _last_poll_time
Definition: pwm_input.cpp:193
virtual int ioctl(struct file *filp, int cmd, unsigned long arg)
Definition: pwm_input.cpp:382
static void pwmin_usage(void)
Definition: pwm_input.cpp:577
struct @83::@85::@87 file
void _timer_init(void)
Definition: pwm_input.cpp:264
#define SENSORIOCRESET
Reset the sensor to its default configuration.
Definition: drv_sensor.h:141
#define errx(eval,...)
Definition: err.h:89
#define rARR
Definition: pwm_input.cpp:129
CDev(const char *devname)
Constructor.
Definition: CDev.cpp:50
Callout record.
Definition: drv_hrt.h:72
int pwm_input_main(int argc, char *argv[])
Definition: pwm_input.cpp:585
void publish(uint16_t status, uint32_t period, uint32_t pulse_width)
Definition: pwm_input.cpp:432
virtual int init()
Definition: pwm_input.cpp:243
#define OK
Definition: uavcan_main.cpp:71
static PWMIN * g_dev
Definition: pwm_input.cpp:216
void _turn_on()
Definition: pwm_input.cpp:337
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
Get architecture-specific timer register defines.
#define rCCMR2
Definition: pwm_input.cpp:125