2014-01-09 06:20:26 -08:00
|
|
|
/*
|
|
|
|
Copyright 2012-2014 Benjamin Vedder benjamin@vedder.se
|
|
|
|
|
|
|
|
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 3 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* servo_dec.c
|
|
|
|
*
|
|
|
|
* Created on: 20 jan 2013
|
|
|
|
* Author: benjamin
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "servo_dec.h"
|
|
|
|
#include "stm32f4xx_conf.h"
|
|
|
|
#include "ch.h"
|
|
|
|
#include "hal.h"
|
2014-09-19 18:22:38 -07:00
|
|
|
#include "hw.h"
|
2014-01-09 06:20:26 -08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Settings
|
|
|
|
*/
|
2014-04-02 11:23:27 -07:00
|
|
|
#define SERVO_NUM 1
|
2014-01-09 06:20:26 -08:00
|
|
|
#define TIMER_FREQ 1000000
|
|
|
|
|
2014-04-03 00:19:25 -07:00
|
|
|
// Private variables
|
2014-09-19 18:22:38 -07:00
|
|
|
static volatile systime_t last_update_time;
|
|
|
|
static volatile float servo_pos[SERVO_NUM];
|
|
|
|
static volatile float pulse_start = 1.0;
|
|
|
|
static volatile float pulse_width = 1.0;
|
2014-04-03 00:19:25 -07:00
|
|
|
|
|
|
|
// Function pointers
|
|
|
|
static void(*done_func)(void) = 0;
|
|
|
|
|
2014-09-19 18:22:38 -07:00
|
|
|
static void icuwidthcb(ICUDriver *icup) {
|
|
|
|
float len = ((float)icuGetWidth(icup) / ((float)TIMER_FREQ / 1000.0)) - pulse_start;
|
|
|
|
|
|
|
|
if (len > pulse_width) {
|
|
|
|
if (len < pulse_width * 1.2) {
|
|
|
|
len = pulse_width;
|
|
|
|
} else {
|
|
|
|
// Too long pulse. Most likely something is wrong.
|
|
|
|
len = -1.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len > 0.0) {
|
|
|
|
servo_pos[0] = (len * 2.0 - pulse_width) / pulse_width;
|
|
|
|
last_update_time = chTimeNow();
|
|
|
|
|
|
|
|
if (done_func) {
|
|
|
|
done_func();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void icuperiodcb(ICUDriver *icup) {
|
|
|
|
(void)icup;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ICUConfig icucfg = {
|
|
|
|
ICU_INPUT_ACTIVE_HIGH,
|
|
|
|
TIMER_FREQ,
|
|
|
|
icuwidthcb,
|
|
|
|
icuperiodcb,
|
|
|
|
NULL,
|
|
|
|
HW_ICU_CHANNEL,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2014-04-03 00:19:25 -07:00
|
|
|
/**
|
|
|
|
* Initialize the serve decoding driver.
|
|
|
|
*
|
|
|
|
* @param d_func
|
|
|
|
* A function that should be called every time the servo signals have been
|
|
|
|
* decoded. Can be NULL.
|
|
|
|
*/
|
|
|
|
void servodec_init(void (*d_func)(void)) {
|
2014-09-19 18:22:38 -07:00
|
|
|
icuStart(&ICUD3, &icucfg);
|
|
|
|
palSetPadMode(HW_ICU_GPIO, HW_ICU_PIN, PAL_MODE_ALTERNATE(HW_ICU_GPIO_AF));
|
|
|
|
icuEnable(&ICUD3);
|
2014-01-09 06:20:26 -08:00
|
|
|
|
2014-04-03 00:19:25 -07:00
|
|
|
// Set our function pointer
|
|
|
|
done_func = d_func;
|
|
|
|
}
|
2014-04-02 11:23:27 -07:00
|
|
|
|
2014-04-03 00:19:25 -07:00
|
|
|
/**
|
2014-09-19 18:22:38 -07:00
|
|
|
* Change the limits of how the servo pulses should be decoded.
|
2014-04-03 00:19:25 -07:00
|
|
|
*
|
2014-09-19 18:22:38 -07:00
|
|
|
* @param start
|
|
|
|
* The amount of milliseconds the pulse starts at (default is 1.0)
|
2014-04-03 00:19:25 -07:00
|
|
|
*
|
2014-09-19 18:22:38 -07:00
|
|
|
* @param width
|
|
|
|
* The width of the pulse in milliseconds (default is 1.0)
|
2014-04-03 00:19:25 -07:00
|
|
|
*/
|
2014-09-19 18:22:38 -07:00
|
|
|
void servodec_set_pulse_options(float start, float width) {
|
|
|
|
pulse_start = start;
|
|
|
|
pulse_width = width;
|
2014-01-09 06:20:26 -08:00
|
|
|
}
|
|
|
|
|
2014-04-03 00:19:25 -07:00
|
|
|
/**
|
2014-09-19 18:22:38 -07:00
|
|
|
* Get a decoded servo value.
|
2014-04-03 00:19:25 -07:00
|
|
|
*
|
|
|
|
* @param servo_num
|
2014-09-19 18:22:38 -07:00
|
|
|
* The servo index. If it is out of range, 0.0 will be returned.
|
2014-04-03 00:19:25 -07:00
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* The servo value in the range [-1.0 1.0].
|
|
|
|
*/
|
2014-09-19 18:22:38 -07:00
|
|
|
float servodec_get_servo(int servo_num) {
|
|
|
|
if (servo_num < SERVO_NUM) {
|
|
|
|
return servo_pos[servo_num];
|
|
|
|
} else {
|
|
|
|
return 0.0;
|
|
|
|
}
|
2014-04-03 00:19:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-01-09 06:20:26 -08:00
|
|
|
* Get the amount of milliseconds that has passed since
|
2014-04-03 00:19:25 -07:00
|
|
|
* the last time servo positions were received.
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* The amount of milliseconds that have passed since an update.
|
2014-01-09 06:20:26 -08:00
|
|
|
*/
|
|
|
|
uint32_t servodec_get_time_since_update(void) {
|
2014-09-19 18:22:38 -07:00
|
|
|
return chTimeElapsedSince(last_update_time) / (CH_FREQUENCY / 1000);
|
2014-01-09 06:20:26 -08:00
|
|
|
}
|