Add wasm tacle-bench targets

This commit is contained in:
2026-06-12 20:06:22 +02:00
parent 30daa8a00c
commit 08c2e9c13d
1122 changed files with 520422 additions and 0 deletions

View File

@ -0,0 +1,120 @@
#include <arch/io.h>
#include <arch/signal.h>
#include <arch/interrupt.h>
#include "std.h"
#include "ad7714.h"
#include "spi.h"
/* unipolar, 16 bits, current boost, filter 4000 */
//#define AD_HIGH_FILTER_CFG 0xAF
//#define AD_LOW_FILTER_CFG 0xA0
/* filter 2000 */
#define AD_HIGH_FILTER_CFG 0xA7
#define AD_LOW_FILTER_CFG 0xD0
/* filter 19 */
//const uint8_t AD_HIGH_FILTER_CFG = 0xA0;
//const uint8_t AD_LOW_FILTER_CFG = 0x13;
struct AdMsg {
uint8_t len;
const uint8_t *data;
};
#define AD7714_SETUP_LEN 6
const uint8_t ad7714_setup_data[ AD7714_SETUP_LEN ] = {
AD_F_HIGH_REG + AD_FD0, /* select high filter register */
AD_HIGH_FILTER_CFG,
AD_F_LOW_REG + AD_FD0, /* select low filter register */
AD_LOW_FILTER_CFG,
AD_MODE_REG + AD_FD0, /* select com register */
AD_SELFCAL_MOD + AD_GAIN_128,
};
const struct AdMsg ad7714_setup = {AD7714_SETUP_LEN, ad7714_setup_data};
#define AD7714_READ_LEN 3
const uint8_t ad7714_read_data[ ] = {
AD_DATA_REG + AD_WR + AD_FD0, /* transmit read request */
0x00, /* transmit a dumb value just to get the result */
0xAA /* transmit a dumb value just to get the result */
};
const struct AdMsg ad7714_read = {AD7714_READ_LEN, ad7714_read_data};
#define AD7714_SELECT_CHANNEL_LEN 2
const uint8_t ad7714_select_channel_data[ AD7714_SELECT_CHANNEL_LEN ] = {
AD_MODE_REG + AD_FD0,
// AD_BG_CAL_MOD + AD_GAIN_128
AD_NOR_MOD + AD_GAIN_128
};
const struct AdMsg ad7714_select_channel = {AD7714_SELECT_CHANNEL_LEN, ad7714_select_channel_data};
static struct AdMsg *msg;
static uint8_t idx;
uint16_t ad7714_sample;
uint8_t ad7714_sample_read;
void ad7714_start_transmitting ( const struct AdMsg *amsg )
{
/* Enable SPI, Master, MSB first, clock idle high, sample on trailing edge, clock rate fck/128 */
SPI_START( _BV( SPE ) | _BV( MSTR ) | _BV( SPR1 ) | _BV( CPOL ) | _BV(
CPHA ) | _BV( SPR0 ) ); //| _BV(SPR0)
SPI_SELECT_SLAVE1();
msg = ( struct AdMsg * )amsg;
SPDR = msg->data[ 0 ];
idx = 0;
}
void ad7714_on_spi_it( void )
{
uint8_t spi_read = SPDR;
if ( msg == &ad7714_read ) {
if ( idx == 1 )
ad7714_sample = spi_read << 8;
else
if ( idx == 2 ) {
ad7714_sample += spi_read;
ad7714_sample_read = TRUE;
}
}
idx++;
if ( idx < msg->len )
SPI_SEND( msg->data[ idx ] );
else {
SPI_UNSELECT_SLAVE1();
SPI_STOP();
}
}
uint8_t ad7714_status = 0;
void ad7714_on_it( void )
{
if ( ad7714_status == 0 )
ad7714_start_transmitting( &ad7714_setup );
else
if ( ad7714_status == 1 )
ad7714_start_transmitting( &ad7714_select_channel );
else
ad7714_start_transmitting( &ad7714_read );
ad7714_status++;
}
void ad7714_init( void )
{
/* setupt interrupt on falling edge */
cbi( EICRB, ISC60 );
sbi( EICRB, ISC61 );
/* clear interrupt flag */
// if (bit_is_set(EIFR, INTF6))
// EIFR != _BV(INTF6);
Ad7714_Enable_It();
}
SIGNAL( SIG_INTERRUPT6 )
{
ad7714_on_it();
}

View File

@ -0,0 +1,56 @@
#ifndef AD_7714_H
#define AD_7714_H
#include <inttypes.h>
/* AD7714 COM register */
#define AD_COM_REG (0<<4)
#define AD_MODE_REG (1<<4)
#define AD_F_HIGH_REG (2<<4)
#define AD_F_LOW_REG (3<<4)
#define AD_TEST_REG (4<<4)
#define AD_DATA_REG (5<<4)
#define AD_ZS_CAL_REG (6<<4)
#define AD_FS_CAL_REG (7<<4)
#define AD_WR (1<<3)
#define AD_FD0 (4<<0)
#define AD_FD1 (5<<0)
#define AD_FD2 (6<<0)
/* AD7714 MODE register */
#define AD_NOR_MOD (0<<5)
#define AD_SELFCAL_MOD (1<<5)
#define AD_ZS_SYSCAL_MOD (2<<5)
#define AD_FS_SYSCAL_MOD (3<<5)
#define AD_SYSOFFCAL_MOD (4<<5)
#define AD_BG_CAL_MOD (5<<5)
#define AD_ZS_SELFCAL_MOD (6<<5)
#define AD_FS_SELFCAL_MOD (7<<5)
#define AD_GAIN_1 (0<<2)
#define AD_GAIN_2 (1<<2)
#define AD_GAIN_4 (2<<2)
#define AD_GAIN_8 (3<<2)
#define AD_GAIN_16 (4<<2)
#define AD_GAIN_32 (5<<2)
#define AD_GAIN_64 (6<<2)
#define AD_GAIN_128 (7<<2)
#define AD_BO (1<<1)
#define AD_FSYNC (1<<0)
#define Ad7714_Disable_It() { cbi(EIMSK, INT6); }
#define Ad7714_Enable_It() { sbi(EIMSK, INT6); }
#define Ad7714_Ready() (bit_is_clear(EIFR, INTF6))
extern uint16_t ad7714_sample;
extern uint8_t ad7714_sample_read;
void ad7714_init( void );
void ad7714_on_spi_it( void );
void ad7714_on_it( void );
#endif /* AD_7714_H */

View File

@ -0,0 +1,130 @@
/*
Paparazzi mcu0 adc functions
Copied from autopilot (autopilot.sf.net) thanx alot Trammell
Copyright (C) 2002 Trammell Hudson <hudson@rotomotion.com>
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <arch/signal.h>
#include <arch/interrupt.h>
#include <arch/io.h>
#include "airframe.h"
#include "std.h"
#include "adc.h"
/*************************************************************************
Analog to digital conversion code.
We allow interrupts during the 2048 usec windows. If we run the
ADC clock faster than Clk/64 we have too much overhead servicing
the interrupts from it and end up with servo jitter.
For now we've slowed the clock to Clk/128 because it lets us
be lazy in the interrupt routine.
*/
#define VOLTAGE_TIME 0x07
#define ANALOG_PORT PORTF
#define ANALOG_PORT_DIR DDRF
#ifdef CTL_BRD_V1_1
#define ANALOG_VREF 0
#endif
#if defined CTL_BRD_V1_2 || defined CTL_BRD_V1_2_1
#define ANALOG_VREF _BV(REFS0)
#endif
uint16_t adc_samples[ NB_ADC ];
static struct adc_buf *buffers[ NB_ADC ];
void adc_buf_channel( uint8_t adc_channel, struct adc_buf *s )
{
buffers[ adc_channel ] = s;
}
void
adc_init( void )
{
uint8_t i;
/* Ensure that our port is for input with no pull-ups */
ANALOG_PORT = 0x00;
ANALOG_PORT_DIR = 0x00;
/* Select our external voltage ref, which is tied to Vcc */
ADMUX = ANALOG_VREF;
/* Turn off the analog comparator */
sbi( ACSR, ACD );
/* Select out clock, turn on the ADC interrupt and start conversion */
ADCSR = 0
| VOLTAGE_TIME
| ( 1 << ADEN )
| ( 1 << ADIE )
| ( 1 << ADSC );
/* Init to 0 (usefull ?) */
_Pragma( "loopbound min 8 max 8" )
for ( i = 0; i < NB_ADC; i++ )
buffers[ i ] = ( struct adc_buf * )0;
}
/**
Called when the voltage conversion is finished
8.913kHz on mega128@16MHz 1kHz/channel ??
*/
SIGNAL( SIG_ADC )
{
uint8_t adc_input = ADMUX & 0x7;
struct adc_buf *buf = buffers[ adc_input ];
uint16_t adc_value = ADCW;
/* Store result */
adc_samples[ adc_input ] = adc_value;
if ( buf ) {
uint8_t new_head = buf->head + 1;
if ( new_head >= AV_NB_SAMPLE ) new_head = 0;
buf->sum -= buf->values[ new_head ];
buf->values[ new_head ] = adc_value;
buf->sum += adc_value;
buf->head = new_head;
}
/* Find the next input */
adc_input++;
if ( adc_input >= 8 )
adc_input = 0;
/* Select it */
ADMUX = adc_input | ANALOG_VREF;
/* Restart the conversion */
sbi( ADCSR, ADSC );
}

View File

@ -0,0 +1,53 @@
/*
Paparazzi mcu0 adc functions
Copied from autopilot (autopilot.sf.net) thanx alot Trammell
Copyright (C) 2002 Trammell Hudson <hudson@rotomotion.com>
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _ADC_H_
#define _ADC_H_
#include <inttypes.h>
#define NB_ADC 8
/* Array containing the last measured value */
extern uint16_t adc_samples[ NB_ADC ];
void adc_init( void );
#define AV_NB_SAMPLE 0x20
struct adc_buf {
uint16_t sum;
uint16_t values[ AV_NB_SAMPLE ];
uint8_t head;
};
/* Facility to store last values in a circular buffer for a specific
channel: allocate a (struct adc_buf) and register it with the following
function */
void adc_buf_channel( uint8_t adc_channel, struct adc_buf *s );
#endif

View File

@ -0,0 +1,123 @@
/*
$Id: autopilot.h,v 1.1 2011-01-18 12:48:38 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef AUTOPILOT_H
#define AUTOPILOT_H
#include "link_autopilot.h"
#define TRESHOLD1 TRESHOLD_MANUAL_PPRZ
#define TRESHOLD2 200 * CLOCK
#define PPRZ_MODE_MANUAL 0
#define PPRZ_MODE_AUTO1 1
#define PPRZ_MODE_AUTO2 2
#define PPRZ_MODE_HOME 3
#define PPRZ_MODE_NB 4
#define PPRZ_MODE_OF_PULSE(pprz, mega8_status) \
(pprz > TRESHOLD2 ? PPRZ_MODE_AUTO2 : \
(pprz > TRESHOLD1 ? PPRZ_MODE_AUTO1 : PPRZ_MODE_MANUAL))
extern uint8_t pprz_mode;
#define VERTICAL_MODE_MANUAL 0
#define VERTICAL_MODE_AUTO_GAZ 1
#define VERTICAL_MODE_AUTO_CLIMB 2
#define VERTICAL_MODE_AUTO_ALT 3
#define VERTICAL_MODE_NB 4
#define LATERAL_MODE_MANUAL 0
#define LATERAL_MODE_ROLL_RATE 1
#define LATERAL_MODE_ROLL 2
#define LATERAL_MODE_COURSE 3
#define LATERAL_MODE_NB 4
#define VERTICAL_MODE_OF_PULSE(pprz) (pprz < TRESHOLD2 ? VERTICAL_MODE_MANUAL: \
VERTICAL_MODE_AUTO_ALT)
#define IR_ESTIM_MODE_OFF 0
#define IR_ESTIM_MODE_ON 1
#define IR_ESTIM_MODE_OF_PULSE(pprz) (pprz < TRESHOLD2 ? IR_ESTIM_MODE_OFF: \
IR_ESTIM_MODE_ON)
extern uint8_t ir_estim_mode;
#define STICK_PUSHED(pprz) (pprz < TRESHOLD1 || pprz > TRESHOLD2)
#define TRIM_PPRZ(pprz) (pprz < MIN_PPRZ ? MIN_PPRZ : \
(pprz > MAX_PPRZ ? MAX_PPRZ : \
pprz))
#define TRIM_UPPRZ(pprz) (pprz < 0 ? 0 : \
(pprz > MAX_PPRZ ? MAX_PPRZ : \
pprz))
#define FLOAT_OF_PPRZ(pprz, center, travel) ((float)pprz / (float)MAX_PPRZ * travel + center)
extern uint8_t fatal_error_nb;
#define GAZ_THRESHOLD_TAKEOFF (pprz_t)(MAX_PPRZ * 0.9)
extern uint8_t inflight_calib_mode;
//extern uint16_t flight_time;
extern uint8_t vertical_mode;
extern bool_t auto_pitch;
extern uint8_t lateral_mode;
extern uint8_t vsupply;
extern bool_t rc_event_1, rc_event_2;
extern float slider_1_val, slider_2_val;
extern bool_t launch;
#define ModeUpdate(_mode, _value) { \
uint8_t new_mode = _value; \
if (_mode != new_mode) { _mode = new_mode; return TRUE; } \
return FALSE; \
}
#define CheckEvent(_event) (_event ? _event = FALSE, TRUE : FALSE)
#ifdef CTL_BRD_V1_1
extern struct adc_buf buf_bat;
#endif
void periodic_task( void );
void use_gps_pos( void );
void radio_control_task( void );
/*receive_gps_data_task */
void send_gps_pos( void );
void send_radIR( void );
void send_takeOff( void );
/*end receive_gps_data_task*/
void stabilisation_task( void );
#endif /* AUTOPILOT_H */

View File

@ -0,0 +1,35 @@
/*
Paparazzi mcu0 $Id: downlink.h,v 1.1 2011-01-18 12:48:38 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef DOWNLINK_H
#define DOWNLINK_H
#include "modem.h"
#define STX 0x05
#define ETX 0x06
#include "messages.h"
#endif /* DOWNLINK_H */

View File

@ -0,0 +1,202 @@
/*
Paparazzi autopilot $Id: estimator.c,v 1.2 2011-01-21 11:52:44 moellmer Exp $
Copyright (C) 2004 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <inttypes.h>
#include <math.h>
#include "estimator.h"
#include "gps.h"
#include "pid.h"
#include "infrared.h"
#include "autopilot.h"
/* position in meters */
float estimator_x;
float estimator_y;
float estimator_z;
/* attitude in radian */
float estimator_phi;
float estimator_psi;
float estimator_theta;
/* speed in meters per second */
float estimator_x_dot;
float estimator_y_dot;
float estimator_z_dot;
/* rotational speed in radians per second */
float estimator_phi_dot;
float estimator_psi_dot;
float estimator_theta_dot;
/* flight time in seconds */
uint16_t estimator_flight_time;
/* flight time in seconds */
float estimator_t;
/* horizontal speed in module and dir */
float estimator_hspeed_mod;
float estimator_hspeed_dir;
float estimator_rad_of_ir, estimator_ir, estimator_rad;
#define EstimatorSetPos(x, y, z) { estimator_x = x; estimator_y = y; estimator_z = z; }
#define EstimatorSetAtt(phi, psi, theta) { estimator_phi = phi; estimator_psi = psi; estimator_theta = theta; }
// FIXME maybe vz = -climb for NED??
#define EstimatorSetSpeedCart(vx, vy, vz) { \
estimator_vx = vx; \
estimator_vy = vy; \
estimator_vz = vz; \
}
// estimator_hspeed_mod = sqrt( estimator_vx * estimator_vx + estimator_vy * estimator_vy);
// estimator_hspeed_dir = atan2(estimator_vy, estimator_vx);
#define EstimatorSetSpeedPol(vhmod, vhdir, vz) { \
estimator_hspeed_mod = vhmod; \
estimator_hspeed_dir = vhdir; \
estimator_z_dot = vz; \
}
//FIXME is this true ?? estimator_vx = estimator_hspeed_mod * cos(estimator_hspeed_dir);
//FIXME is this true ?? estimator_vy = estimator_hspeed_mod * sin(estimator_hspeed_dir);
#define EstimatorSetRotSpeed(phi_dot, psi_dot, theta_dot) { \
estimator_phi_dot = phi_dot; \
estimator_psi_dot = psi_dot; \
estimator_theta_dot = theta_dot; \
}
inline void estimator_update_lls( void );
void estimator_init( void )
{
EstimatorSetPos ( 0., 0., 0. );
EstimatorSetAtt ( 0., 0., 0 );
EstimatorSetSpeedPol ( 0., 0., 0. );
EstimatorSetRotSpeed ( 0., 0., 0. );
estimator_flight_time = 0;
estimator_rad_of_ir = ir_rad_of_ir;
}
#define EstimatorIrGainIsCorrect() (TRUE)
void estimator_update_state_infrared( void )
{
float rad_of_ir = ( ir_estim_mode == IR_ESTIM_MODE_ON &&
EstimatorIrGainIsCorrect() ) ?
estimator_rad_of_ir : ir_rad_of_ir;
estimator_phi = rad_of_ir * ir_roll;
estimator_theta = rad_of_ir * ir_pitch;
}
#define INIT_WEIGHT 100. /* The number of times the initial value has to be taken */
#define RHO 0.999 /* The higher, the slower the estimation is changing */
#define g 9.81
void estimator_update_ir_estim( void )
{
static float last_hspeed_dir;
static float last_t;
static bool_t initialized = FALSE;
static float sum_xy, sum_xx;
float absphi;
float init_ir2;
if ( initialized ) {
float dt = gps_ftow - last_t;
if ( dt > 0.1 ) { // Against division by zero
float phi = ( estimator_hspeed_dir - last_hspeed_dir );
//NORM_RAD_ANGLE(phi);
_Pragma( "loopbounds min 0 max 1" )
while ( phi > M_PI ) phi -= 2 * M_PI;
_Pragma( "loopbounds min 0 max 1" )
while ( phi < -M_PI ) phi += 2 * M_PI;
phi = phi / dt * NOMINAL_AIRSPEED / g; /* tan linearized */
//NORM_RAD_ANGLE(phi);
_Pragma( "loopbounds min 0 max 1" )
while ( phi > M_PI ) phi -= 2 * M_PI;
_Pragma( "loopbounds min 0 max 1" )
while ( phi < -M_PI ) phi += 2 * M_PI;
estimator_ir = ( float )ir_roll;
estimator_rad = phi;
absphi = fabs( phi );
if ( absphi < 1.0 && absphi > 0.05 && ( - ir_contrast / 2 < ir_roll &&
ir_roll < ir_contrast / 2 ) ) {
sum_xy = estimator_rad * estimator_ir + RHO * sum_xy;
sum_xx = estimator_ir * estimator_ir + RHO * sum_xx;
#if defined IR_RAD_OF_IR_MIN_VALUE & defined IR_RAD_OF_IR_MAX_VALUE
float result = sum_xy / sum_xx;
if ( result < IR_RAD_OF_IR_MIN_VALUE )
estimator_rad_of_ir = IR_RAD_OF_IR_MIN_VALUE;
else
if ( result > IR_RAD_OF_IR_MAX_VALUE )
estimator_rad_of_ir = IR_RAD_OF_IR_MAX_VALUE;
else
estimator_rad_of_ir = result;
#else
estimator_rad_of_ir = sum_xy / sum_xx;
#endif
}
}
} else {
initialized = TRUE;
init_ir2 = ir_contrast;
init_ir2 = init_ir2 * init_ir2;
sum_xy = INIT_WEIGHT * estimator_rad_of_ir * init_ir2;
sum_xx = INIT_WEIGHT * init_ir2;
}
last_hspeed_dir = estimator_hspeed_dir;
last_t = gps_ftow;
}
void estimator_update_state_gps( void )
{
if ( GPS_FIX_VALID( gps_mode ) ) {
EstimatorSetPos( gps_east, gps_north, gps_falt );
EstimatorSetSpeedPol( gps_fspeed, gps_fcourse, gps_fclimb );
if ( estimator_flight_time )
estimator_update_ir_estim();
}
}
void estimator_propagate_state( void )
{
}

View File

@ -0,0 +1,67 @@
/*
$Id: estimator.h,v 1.1 2011-01-18 12:48:38 moellmer Exp $
Copyright (C) 2004 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef ESTIMATOR_H
#define ESTIMATOR_H
#include <inttypes.h>
/* position in meters */
extern float estimator_x;
extern float estimator_y;
extern float estimator_z;
/* attitude in radians */
extern float estimator_phi;
extern float estimator_psi;
extern float estimator_theta;
/* speed in meters per second */
extern float estimator_x_dot;
extern float estimator_y_dot;
extern float estimator_z_dot;
/* rotational speed in radians per second */
extern float estimator_phi_dot;
extern float estimator_psi_dot;
extern float estimator_teta_dot;
/* flight time in seconds */
extern uint16_t estimator_flight_time;
extern float estimator_t;
/* horizontal speed in module and dir (m/s, rad) */
extern float estimator_hspeed_mod;
extern float estimator_hspeed_dir;
void estimator_init( void );
void estimator_update_state_infrared( void );
void estimator_update_state_gps( void );
void estimator_propagate_state( void );
extern float estimator_rad_of_ir, estimator_ir, estimator_rad;
#endif /* ESTIMATOR_H */

View File

@ -0,0 +1,58 @@
/*
Paparazzi mcu0 $Id: gps.h,v 1.1 2011-01-18 12:48:38 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/*
Parse SIRF protocol from ublox SAM module
*/
#ifndef GPS_H
#define GPS_H
#include "std.h"
extern uint8_t gps_mode;
extern float gps_ftow; /* ms */
extern float gps_falt; /* m */
extern float gps_fspeed; /* m/s */
extern float gps_fclimb; /* m/s */
extern float gps_fcourse; /* rad */
extern int32_t gps_utm_east, gps_utm_north;
extern float gps_east, gps_north; /* m */
void gps_init( void );
void parse_gps_msg( void );
extern volatile uint8_t gps_msg_received;
extern bool_t gps_pos_available;
extern uint8_t gps_nb_ovrn;
#ifdef UBX
#include "ubx.h"
#else
#include "sirf.h"
#endif
#endif /* GPS_H */

View File

@ -0,0 +1,318 @@
/*
Paparazzi mcu0 $Id: gps_sirf.c,v 1.2 2011-01-25 09:40:36 plazar Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <inttypes.h>
#include <arch/io.h>
#include <arch/signal.h>
#include <arch/interrupt.h>
#include <string.h>
#include "math_papabench.h"
#include "uart.h"
#include "gps.h"
float gps_falt;
float gps_fspeed;
float gps_fclimb;
float gps_fcourse;
uint8_t gps_mode;
volatile bool_t gps_msg_received;
bool_t gps_pos_available;
#define SIRF_MAX_PAYLOAD 255
uint8_t sirf_msg_buf[ SIRF_MAX_PAYLOAD ];
#define READ_INT32_AT_OFFSET(offset, dest) \
{ \
dest[ 0 ] = sirf_msg_buf[ offset+3 ]; \
dest[ 1 ] = sirf_msg_buf[ offset+2 ]; \
dest[ 2 ] = sirf_msg_buf[ offset+1 ]; \
dest[ 3 ] = sirf_msg_buf[ offset ]; \
} \
/* ext nav type = 0x62
offset len
type 0 1
lat 1 4
lon 5 4
alt 9 4
speed 13 4
climb 17 4
course 21 4
mode 25 1
*/
void parse_gps_msg( void )
{
static int32_t tmp_int32;
uint8_t *tmp = ( uint8_t * )&tmp_int32;
READ_INT32_AT_OFFSET( 1, tmp );
gps_lat = tmp_int32;
READ_INT32_AT_OFFSET( 5, tmp );
gps_lon = tmp_int32;
READ_INT32_AT_OFFSET( 9, tmp );
gps_falt = ( float )tmp_int32 / 1e3;
READ_INT32_AT_OFFSET( 13, tmp );
gps_fspeed = ( float )tmp_int32 / 1e3;
READ_INT32_AT_OFFSET( 17, tmp );
gps_fclimb = ( float )tmp_int32 / 1e3;
READ_INT32_AT_OFFSET( 21, tmp );
gps_fcourse = ( float )tmp_int32 / 1e8;
gps_mode = sirf_msg_buf[ 25 ];
gps_pos_available = TRUE;
}
void gps_init( void )
{
/* Enable uart */
#ifdef SIMUL
uart0_init();
#else
uart1_init();
#endif
}
#define SIRF_START1 0xA0
#define SIRF_START2 0xA2
#define SIRF_END1 0xB0
#define SIRF_END2 0xB3
#ifdef SIMUL
#define IR_START 0xA1 /* simulator/mc.ml */
volatile int16_t simul_ir_roll;
volatile int16_t simul_ir_pitch;
#endif
#define SIRF_TYP_NAV 0x02
#define SIRF_TYP_EXT_NAV 0x62
#define UNINIT 0
#define GOT_START1 1
#define GOT_START2 2
#define GOT_LEN1 3
#define GOT_LEN2 4
#define GOT_PAYLOAD 5
#define GOT_CHECKSUM1 6
#define GOT_CHECKSUM2 7
#define GOT_END1 8
#ifdef SIMUL
#define GOT_IR_START 9
#define GOT_IR1 10
#define GOT_IR2 11
#define GOT_IR3 12
#endif
static uint8_t sirf_status;
static uint16_t sirf_len;
static uint16_t sirf_checksum;
static uint8_t sirf_type;
static uint8_t sirf_msg_idx;
static inline void parse_sirf( uint8_t c )
{
/*#ifdef WITH_SWITCH
switch (sirf_status) {
case UNINIT:
if (c == SIRF_START1)
sirf_status++;
#ifdef SIMUL
if (c == IR_START)
sirf_status = GOT_IR_START;
#endif
break;
case GOT_START1:
if (c != SIRF_START2)
goto error;
sirf_status++;
break;
case GOT_START2:
sirf_len = (c<<8) & 0xFF00;
sirf_status++;
break;
case GOT_LEN1:
sirf_len += (c & 0x00FF);
if (sirf_len > SIRF_MAX_PAYLOAD)
goto error;
sirf_msg_idx = 0;
sirf_status++;
break;
case GOT_LEN2:
if (sirf_msg_idx==0) {
sirf_type = c;
}
if (sirf_type == SIRF_TYP_EXT_NAV)
sirf_msg_buf[ sirf_msg_idx ] = c;
sirf_msg_idx++;
if (sirf_msg_idx >= sirf_len) {
sirf_status++;
}
break;
case GOT_PAYLOAD:
sirf_checksum = (c<<8) & 0xFF00;
sirf_status++;
break;
case GOT_CHECKSUM1:
sirf_checksum += (c & 0x00FF);
// fixme: check correct
sirf_status++;
break;
case GOT_CHECKSUM2:
if (c != SIRF_END1)
goto error;
sirf_status++;
break;
case GOT_END1:
if (c != SIRF_END2)
goto error;
if (sirf_type == SIRF_TYP_EXT_NAV)
gps_msg_received = TRUE;
goto restart;
break;
#ifdef SIMUL
case GOT_IR_START:
simul_ir_roll = c << 8;
sirf_status++;
break;
case GOT_IR1:
simul_ir_roll |= c;
sirf_status++;
break;
case GOT_IR2:
simul_ir_pitch = c << 8;
sirf_status++;
break;
case GOT_IR3:
simul_ir_pitch |= c;
goto restart;
break;
#endif
}
#else*/
if ( sirf_status == UNINIT ) {
if ( c == SIRF_START1 )
sirf_status++;
#ifdef SIMUL
if ( c == IR_START )
sirf_status = GOT_IR_START;
#endif
} else
if ( sirf_status == GOT_START1 ) {
if ( c != SIRF_START2 )
goto error;
sirf_status++;
} else
if ( sirf_status == GOT_START2 ) {
sirf_len = ( c << 8 ) & 0xFF00;
sirf_status++;
} else
if ( sirf_status == GOT_LEN1 ) {
sirf_len += ( c & 0x00FF );
if ( sirf_len > SIRF_MAX_PAYLOAD )
goto error;
sirf_msg_idx = 0;
sirf_status++;
} else
if ( sirf_status == GOT_LEN2 ) {
if ( sirf_msg_idx == 0 )
sirf_type = c;
if ( sirf_type == SIRF_TYP_EXT_NAV )
sirf_msg_buf[ sirf_msg_idx ] = c;
sirf_msg_idx++;
if ( sirf_msg_idx >= sirf_len )
sirf_status++;
} else
if ( sirf_status == GOT_PAYLOAD ) {
sirf_checksum = ( c << 8 ) & 0xFF00;
sirf_status++;
} else
if ( sirf_status == GOT_CHECKSUM1 ) {
sirf_checksum += ( c & 0x00FF );
/* fixme: check correct */
sirf_status++;
} else
if ( sirf_status == GOT_CHECKSUM2 ) {
if ( c != SIRF_END1 )
goto error;
sirf_status++;
} else
if ( sirf_status == GOT_END1 ) {
if ( c != SIRF_END2 )
goto error;
if ( sirf_type == SIRF_TYP_EXT_NAV )
gps_msg_received = TRUE;
goto restart;
}
#ifdef SIMUL
else
if ( sirf_status == GOT_IR_START ) {
simul_ir_roll = c << 8;
sirf_status++;
} else
if ( sirf_status == GOT_IR1 ) {
simul_ir_roll |= c;
sirf_status++;
} else
if ( sirf_status == GOT_IR2 ) {
simul_ir_pitch = c << 8;
sirf_status++;
} else
if ( sirf_status == GOT_IR3 ) {
simul_ir_pitch |= c;
goto restart;
}
#endif
else {}
//#endif
return;
error:
// modem_putc('r');
restart:
// modem_putc('\n');
sirf_status = UNINIT;
sirf_checksum = 0;
return;
}
#ifdef SIMUL
ReceiveUart0( parse_sirf );
#else
ReceiveUart1( parse_sirf );
#endif

View File

@ -0,0 +1,265 @@
/*
Paparazzi mcu0 $Id: gps_ubx.c,v 1.4 2011-01-25 09:40:36 plazar Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <inttypes.h>
#include <arch/io.h>
#include <arch/signal.h>
#include <arch/interrupt.h>
//#include <string.h>
#include <math.h>
#include "flight_plan.h"
#include "uart.h"
#include "gps.h"
#include "ubx_protocol.h"
#include "flight_plan.h"
float gps_ftow;
float gps_falt;
float gps_fspeed;
float gps_fclimb;
float gps_fcourse;
int32_t gps_utm_east, gps_utm_north;
float gps_east, gps_north;
uint8_t gps_mode;
volatile bool_t gps_msg_received;
bool_t gps_pos_available;
const int32_t utm_east0 = NAV_UTM_EAST0;
const int32_t utm_north0 = NAV_UTM_NORTH0;
#define UBX_MAX_PAYLOAD 255
static uint8_t ubx_msg_buf[ UBX_MAX_PAYLOAD ];
#define RadianOfDeg(d) ((d)/180.*3.1415927)
#ifdef SIMUL
#include "infrared.h"
#define IR_START 0xA1 /* simulator/mc.ml */
volatile int16_t simul_ir_roll;
volatile int16_t simul_ir_pitch;
#endif
#define UNINIT 0
#define GOT_SYNC1 1
#define GOT_SYNC2 2
#define GOT_CLASS 3
#define GOT_ID 4
#define GOT_LEN1 5
#define GOT_LEN2 6
#define GOT_PAYLOAD 7
#define GOT_CHECKSUM1 8
#ifdef SIMUL
#define GOT_IR_START 20
#define GOT_IR1 21
#define GOT_IR2 22
#define GOT_IR3 23
#endif
static uint8_t ubx_status;
static uint16_t ubx_len;
static uint8_t ubx_msg_idx;
// was static
uint8_t ck_a, ck_b, ubx_id, ubx_class;
void gps_init( void )
{
/* Enable uart */
#ifdef SIMUL
uart0_init();
simul_ir_roll = ir_roll_neutral;
simul_ir_pitch = ir_pitch_neutral;
#else
uart1_init();
#endif
ubx_status = UNINIT;
}
void parse_gps_msg( void )
{
if ( ubx_class == UBX_NAV_ID ) {
if ( ubx_id == UBX_NAV_POSUTM_ID ) {
gps_utm_east = UBX_NAV_POSUTM_EAST( ubx_msg_buf );
gps_utm_north = UBX_NAV_POSUTM_NORTH( ubx_msg_buf );
gps_falt = ( float )UBX_NAV_POSUTM_ALT( ubx_msg_buf ) / 100.;
} else
if ( ubx_id == UBX_NAV_STATUS_ID )
gps_mode = UBX_NAV_STATUS_GPSfix( ubx_msg_buf );
else
if ( ubx_id == UBX_NAV_VELNED_ID ) {
gps_fspeed = ( ( float )UBX_NAV_VELNED_GSpeed( ubx_msg_buf ) ) / 1e2;
gps_fclimb = ( ( float )UBX_NAV_VELNED_VEL_D( ubx_msg_buf ) ) / -1e2;
gps_fcourse = RadianOfDeg( ( ( float )UBX_NAV_VELNED_Heading(
ubx_msg_buf ) ) / 1e5 );
gps_ftow = ( ( float )UBX_NAV_VELNED_ITOW( ubx_msg_buf ) ) / 1e3;
gps_east = gps_utm_east / 100 - NAV_UTM_EAST0;
gps_north = gps_utm_north / 100 - NAV_UTM_NORTH0;
gps_pos_available = TRUE; /* The 3 UBX messages are sent in one rafale */
}
}
#ifdef SIMUL
if ( ubx_class == UBX_USR_ID ) {
if ( ubx_id == UBX_USR_IRSIM_ID ) {
simul_ir_roll = UBX_USR_IRSIM_ROLL( ubx_msg_buf );
simul_ir_pitch = UBX_USR_IRSIM_PITCH( ubx_msg_buf );
}
}
#endif
}
uint8_t gps_nb_ovrn;
static void parse_ubx( uint8_t c )
{
if ( ubx_status < GOT_PAYLOAD ) {
ck_a += c;
ck_b += ck_a;
}
/*#ifdef WITH_SWITCH
switch (ubx_status) {
case UNINIT:
if (c == UBX_SYNC1)
ubx_status++;
break;
case GOT_SYNC1:
if (c != UBX_SYNC2)
goto error;
ck_a = 0;
ck_b = 0;
ubx_status++;
break;
case GOT_SYNC2:
if (gps_msg_received) {
// Previous message has not yet been parsed: discard this one
gps_nb_ovrn++;
goto error;
}
ubx_class = c;
ubx_status++;
break;
case GOT_CLASS:
ubx_id = c;
ubx_status++;
break;
case GOT_ID:
ubx_len = c;
ubx_status++;
break;
case GOT_LEN1:
ubx_len |= (c<<8);
if (ubx_len > UBX_MAX_PAYLOAD)
goto error;
ubx_msg_idx = 0;
ubx_status++;
break;
case GOT_LEN2:
ubx_msg_buf[ ubx_msg_idx ] = c;
ubx_msg_idx++;
if (ubx_msg_idx >= ubx_len) {
ubx_status++;
}
break;
case GOT_PAYLOAD:
if (c != ck_a)
goto error;
ubx_status++;
break;
case GOT_CHECKSUM1:
if (c != ck_b)
goto error;
gps_msg_received = TRUE;
goto restart;
break;
}
#else */
if ( ubx_status == UNINIT ) {
if ( c == UBX_SYNC1 )
ubx_status++;
} else
if ( ubx_status == GOT_SYNC1 ) {
if ( c != UBX_SYNC2 )
goto error;
ck_a = 0;
ck_b = 0;
ubx_status++;
} else
if ( ubx_status == GOT_SYNC2 ) {
if ( gps_msg_received ) {
/* Previous message has not yet been parsed: discard this one */
gps_nb_ovrn++;
goto error;
}
ubx_class = c;
ubx_status++;
} else
if ( ubx_status == GOT_CLASS ) {
ubx_id = c;
ubx_status++;
} else
if ( ubx_status == GOT_ID ) {
ubx_len = c;
ubx_status++;
} else
if ( ubx_status == GOT_LEN1 ) {
ubx_len |= ( c << 8 );
if ( ubx_len > UBX_MAX_PAYLOAD )
goto error;
ubx_msg_idx = 0;
ubx_status++;
} else
if ( ubx_status == GOT_LEN2 ) {
ubx_msg_buf[ ubx_msg_idx ] = c;
ubx_msg_idx++;
if ( ubx_msg_idx >= ubx_len )
ubx_status++;
} else
if ( ubx_status == GOT_PAYLOAD ) {
if ( c != ck_a )
goto error;
ubx_status++;
} else
if ( ubx_status == GOT_CHECKSUM1 ) {
if ( c != ck_b )
goto error;
gps_msg_received = TRUE;
goto restart;
} else {}
//#endif
return;
error:
restart:
ubx_status = UNINIT;
return;
}
#ifdef SIMUL
ReceiveUart0( parse_ubx )
#else
ReceiveUart1( parse_ubx )
#endif

View File

@ -0,0 +1,94 @@
/*
$Id: if_calib.c,v 1.1 2011-01-18 12:48:38 moellmer Exp $
Flight-time calibration facility
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <inttypes.h>
#include "radio.h"
#include "autopilot.h"
#include "if_calib.h"
#include "infrared.h"
#include "pid.h"
#include "nav.h"
#define ParamValInt16(param_init_val, param_travel, cur_pulse, init_pulse) \
(param_init_val + (int16_t)(((float)(cur_pulse - init_pulse)) * param_travel / (float)MAX_PPRZ))
#define ParamValFloat(param_init_val, param_travel, cur_pulse, init_pulse) \
(param_init_val + ((float)(cur_pulse - init_pulse)) * param_travel / (float)MAX_PPRZ)
uint8_t inflight_calib_mode = IF_CALIB_MODE_NONE;
static int16_t slider1_init, slider2_init;
#include "inflight_calib.h"
/***
inline uint8_t inflight_calib(void) {
static int16_t slider1_init, slider2_init;
//static float ir_gain_init;
//static float roll_pgain_init;
static float course_pgain_init;
static int16_t roll_neutral_init;
static float pitch_pgain_init;
static int16_t pitch_neutral_init;
int8_t mode_changed = inflight_calib_mode_update();
if (inflight_calib_mode == IF_CALIB_MODE_NEUTRAL) {
if (mode_changed) {
pitch_neutral_init = ir_pitch_neutral;
roll_neutral_init = ir_roll_neutral;
slider1_init = from_fbw.channels[ RADIO_GAIN1 ];
slider2_init = from_fbw.channels[ RADIO_GAIN2 ];
}
ir_pitch_neutral = PARAM_VAL_INT16( pitch_neutral_init, -60., from_fbw.channels[ RADIO_GAIN1 ], slider1_init);
ir_roll_neutral = PARAM_VAL_INT16( roll_neutral_init, 60., from_fbw.channels[ RADIO_GAIN2 ], slider2_init);
}
else if (inflight_calib_mode == IF_CALIB_MODE_GAIN) {
if (mode_changed) {
// ir_gain_init = ir_gain;
course_pgain_init = course_pgain;
// roll_pgain_init = roll_pgain;
pitch_pgain_init = pitch_pgain;
slider1_init = from_fbw.channels[ RADIO_GAIN1 ];
slider2_init = from_fbw.channels[ RADIO_GAIN2 ];
}
course_pgain = PARAM_VAL_FLOAT( course_pgain_init, -0.1, from_fbw.channels[ RADIO_GAIN1 ], slider1_init);
// ir_gain = PARAM_VAL_FLOAT( ir_gain_init, 0.0015, from_fbw.channels[ RADIO_GAIN2 ], slider2_init);
// roll_pgain = PARAM_VAL_FLOAT( roll_pgain_init, -5000., from_fbw.channels[ RADIO_GAIN2 ], slider1_init);
pitch_pgain = PARAM_VAL_FLOAT( pitch_pgain_init, -5000., from_fbw.channels[ RADIO_GAIN1 ], slider1_init);
}
return (mode_changed);
}
***/

View File

@ -0,0 +1,22 @@
#ifndef IF_CALIB_H
#include "link_fbw.h"
extern uint8_t inflight_calib_mode;
void inflight_calib( bool_t calib_mode_changed );
#define IF_CALIB_MODE_NONE 0
#define IF_CALIB_MODE_DOWN 1
#define IF_CALIB_MODE_UP 2
#ifdef ANTON_T7
#define IF_CALIB_MODE_OF_PULSE(pprz) (pprz < TRESHOLD1 ? IF_CALIB_MODE_UP : \
IF_CALIB_MODE_NONE)
#else
#define IF_CALIB_MODE_OF_PULSE(pprz) (pprz < TRESHOLD1 ? IF_CALIB_MODE_UP : \
(pprz < TRESHOLD2 ? IF_CALIB_MODE_NONE : \
IF_CALIB_MODE_DOWN))
#endif /* ANTON_T7 */
#endif // IF_CALIB_H

View File

@ -0,0 +1,76 @@
/*
Paparazzi mcu0 $Id: infrared.c,v 1.2 2011-01-18 14:55:52 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "adc.h"
#include "infrared.h"
#include "autopilot.h"
#include "estimator.h"
int16_t ir_roll;
int16_t ir_pitch;
int16_t ir_contrast = IR_DEFAULT_CONTRAST;
int16_t ir_roll_neutral = IR_ROLL_NEUTRAL_DEFAULT;
int16_t ir_pitch_neutral = IR_PITCH_NEUTRAL_DEFAULT;
#define RadOfIrFromConstrast(c) ir_rad_of_ir = IR_RAD_OF_IR_CONTRAST / c;
//float ir_rad_of_ir = IR_RAD_OF_IR_CONTRAST / IR_DEFAULT_CONTRAST;
float ir_rad_of_ir = 0.00375;
static struct adc_buf buf_ir1;
static struct adc_buf buf_ir2;
void ir_init( void )
{
RadOfIrFromConstrast( IR_DEFAULT_CONTRAST );
adc_buf_channel( ADC_CHANNEL_IR1, &buf_ir1 );
adc_buf_channel( ADC_CHANNEL_IR2, &buf_ir2 );
}
void ir_update( void )
{
#ifndef SIMUL
int16_t x1_mean = buf_ir1.sum / AV_NB_SAMPLE;
int16_t x2_mean = buf_ir2.sum / AV_NB_SAMPLE;
ir_roll = IR_RollOfIrs( x1_mean, x2_mean ) - ir_roll_neutral;
ir_pitch = IR_PitchOfIrs( x1_mean, x2_mean ) - ir_pitch_neutral;
#else
extern volatile int16_t simul_ir_roll, simul_ir_pitch;
ir_roll = simul_ir_roll - ir_roll_neutral;
ir_pitch = simul_ir_pitch - ir_pitch_neutral;
#endif
}
/*
Contrast measurement
*/
void ir_gain_calib( void ) // Plane nose down
{
/* plane nose down -> negativ value */
ir_contrast = - ir_pitch;
RadOfIrFromConstrast( ir_contrast );
}

View File

@ -0,0 +1,42 @@
/*
Paparazzi mcu0 $Id: infrared.h,v 1.2 2011-01-18 14:55:52 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef INFRARED_H
#define INFRARED_H
extern int16_t ir_roll; /* averaged roll adc */
extern int16_t ir_pitch; /* averaged pitch adc */
extern float ir_rad_of_ir;
extern int16_t ir_contrast;
extern int16_t ir_roll_neutral;
extern int16_t ir_pitch_neutral;
void ir_init( void );
void ir_update( void );
void ir_gain_calib( void );
#endif /* INFRARED_H */

View File

@ -0,0 +1,125 @@
/*
$Id: link_fbw.c,v 1.3 2011-01-25 09:40:37 plazar Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <arch/io.h>
#include <arch/signal.h>
#include <arch/interrupt.h>
#include "link_fbw.h"
#include "spi.h"
struct inter_mcu_msg from_fbw;
struct inter_mcu_msg to_fbw;
volatile uint8_t link_fbw_receive_complete = TRUE;
volatile uint8_t link_fbw_receive_valid = FALSE;
volatile uint8_t link_fbw_nb_err;
uint8_t link_fbw_fbw_nb_err;
static uint8_t idx_buf;
static uint8_t xor_in, xor_out;
void link_fbw_init( void )
{
link_fbw_nb_err;
link_fbw_receive_complete = FALSE;
}
void _Pragma( "entrypoint" ) link_fbw_send( void )
{
if ( spi_cur_slave != SPI_NONE ) {
spi_nb_ovrn++;
return;
}
/* Enable SPI, Master, set clock rate fck/16 */
SPI_START( _BV( SPE ) | _BV( MSTR ) | _BV( SPR0 ) ); // | _BV(SPR1);
SPI_SELECT_SLAVE0();
idx_buf = 0;
xor_in = 0;
xor_out = ( ( uint8_t * )&to_fbw )[ idx_buf ];
SPDR = xor_out;
link_fbw_receive_valid = FALSE;
// Other bytes will follow SIG_SPI interrupts
}
void link_fbw_on_spi_it( void )
{
/* setup OCR1A to pop in 200 clock cycles */
/* this leaves time for the slave (fbw) */
/* to process the byte we've sent and to */
/* prepare a new one to be sent */
OCR1A = TCNT1 + 200;
/* clear interrupt flag */
sbi( TIFR, OCF1A );
/* enable OC1A interrupt */
sbi( TIMSK, OCIE1A );
}
/* send the next byte */
SIGNAL( SIG_OUTPUT_COMPARE1A )
{
uint8_t tmp;
/* disable OC1A interrupt */
cbi( TIMSK, OCIE1A );
idx_buf++;
/* we have sent/received a complete frame */
if ( idx_buf == FRAME_LENGTH ) {
/* read checksum from receive register */
tmp = SPDR;
/* notify valid frame */
if ( tmp == xor_in ) {
link_fbw_receive_valid = TRUE;
link_fbw_fbw_nb_err = from_fbw.nb_err;
} else
link_fbw_nb_err++;
link_fbw_receive_complete = TRUE;
/* unselect slave0 */
SPI_UNSELECT_SLAVE0();
SPI_STOP();
return;
}
/* we are sending/receiving payload */
if ( idx_buf < FRAME_LENGTH - 1 ) {
/* place new payload byte in send register */
tmp = ( ( uint8_t * )&to_fbw )[ idx_buf ];
SPI_SEND( tmp );
xor_out ^= tmp;
}
/* we are done sending the payload */
else { // idx_buf == FRAME_LENGTH - 1
/* place checksum in send register */
SPI_SEND( xor_out );
}
/* read the byte from receive register */
tmp = SPDR;
( ( uint8_t * )&from_fbw )[ idx_buf - 1 ] = tmp;
xor_in ^= tmp;
}

View File

@ -0,0 +1,44 @@
/*
$Id: link_fbw.h,v 1.1 2011-01-18 12:48:38 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef LINK_FBW_H
#define LINK_FBW_H
#include <inttypes.h>
#include "link_autopilot.h"
void link_fbw_init( void );
void link_fbw_send( void );
void link_fbw_on_spi_it( void );
extern volatile uint8_t link_fbw_nb_err;
extern uint8_t link_fbw_fbw_nb_err;
extern struct inter_mcu_msg from_fbw;
extern struct inter_mcu_msg to_fbw;
extern volatile uint8_t link_fbw_receive_complete;
extern volatile uint8_t link_fbw_receive_valid;
#endif /* LINK_FBW_H */

View File

@ -0,0 +1,677 @@
/*
$Id: main.c,v 1.2 2011-01-18 14:55:52 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/** \file main.c
\brief Regroup main functions
*/
#include <inttypes.h>
#include <math.h>
#include "link_autopilot.h"
#include "timer.h"
#include "adc.h"
#include "pid.h"
#include "gps.h"
#include "infrared.h"
#include "downlink.h"
#include "nav.h"
#include "autopilot.h"
#include "estimator.h"
#include "if_calib.h"
//
//
// FIXME estimator_flight_time should not be manipuled here anymore
//
/** Define minimal speed for takeoff in m/s */
#define MIN_SPEED_FOR_TAKEOFF 5.
uint8_t fatal_error_nb = 0;
static const uint16_t version = 1;
/** in seconds */
static uint16_t cputime = 0;
uint8_t pprz_mode = PPRZ_MODE_MANUAL;
uint8_t vertical_mode = VERTICAL_MODE_MANUAL;
uint8_t lateral_mode = LATERAL_MODE_MANUAL;
uint8_t ir_estim_mode = IR_ESTIM_MODE_ON;
bool_t auto_pitch = FALSE;
bool_t rc_event_1, rc_event_2;
uint8_t vsupply;
static uint8_t mcu1_status, mcu1_ppm_cpt;
static bool_t low_battery = FALSE;
float slider_1_val, slider_2_val;
bool_t launch = FALSE;
static uint8_t boot = TRUE;
static uint8_t count;
//#define Min(x, y) (x < y ? x : y)
//#define Max(x, y) (x > y ? x : y)
#define NO_CALIB 0 /**< \enum No calibration state */
#define WAITING_CALIB_CONTRAST 1 /**< \enum Waiting calibration contrast state */
#define CALIB_DONE 2 /**< \enum Calibration done state */
/** Maximal delay for calibration */
#define MAX_DELAY_FOR_CALIBRATION 10
/** \fn inline void ground_calibrate( void )
\brief Calibrate contrast if paparazzi mode is
set to auto1 before MAX_DELAY_FOR_CALIBRATION secondes */
/**User must put verticaly the uav (nose bottom) and push
radio roll stick to get new calibration
If not, the default calibration is used.
*/
inline void ground_calibrate( void )
{
static uint8_t calib_status = NO_CALIB;
/*#ifdef WITH_SWITCH
switch (calib_status) {
case NO_CALIB:
if (cputime < MAX_DELAY_FOR_CALIBRATION && pprz_mode == PPRZ_MODE_AUTO1 ) {
calib_status = WAITING_CALIB_CONTRAST;
DOWNLINK_SEND_CALIB_START();
}
break;
case WAITING_CALIB_CONTRAST:
if (STICK_PUSHED(from_fbw.channels[ RADIO_ROLL ])) {
ir_gain_calib();
estimator_rad_of_ir = ir_rad_of_ir;
DOWNLINK_SEND_RAD_OF_IR(&estimator_ir, &estimator_rad, &estimator_rad_of_ir, &ir_roll_neutral, &ir_pitch_neutral);
calib_status = CALIB_DONE;
DOWNLINK_SEND_CALIB_CONTRAST(&ir_contrast);
}
break;
case CALIB_DONE:
break;
}
#else*/
if ( calib_status == NO_CALIB ) {
if ( cputime < MAX_DELAY_FOR_CALIBRATION && pprz_mode == PPRZ_MODE_AUTO1 ) {
calib_status = WAITING_CALIB_CONTRAST;
DOWNLINK_SEND_CALIB_START();
}
} else
if ( calib_status == WAITING_CALIB_CONTRAST ) {
if ( STICK_PUSHED( from_fbw.channels[ RADIO_ROLL ] ) ) {
ir_gain_calib();
estimator_rad_of_ir = ir_rad_of_ir;
DOWNLINK_SEND_RAD_OF_IR( &estimator_ir, &estimator_rad, &estimator_rad_of_ir,
&ir_roll_neutral, &ir_pitch_neutral );
calib_status = CALIB_DONE;
DOWNLINK_SEND_CALIB_CONTRAST( &ir_contrast );
}
} else {}
//#endif
}
/** \fn inline uint8_t pprz_mode_update( void )
\brief Update paparazzi mode
*/
inline uint8_t pprz_mode_update( void )
{
/** We remain in home mode until explicit reset from the RC */
if ( pprz_mode != PPRZ_MODE_HOME || CheckEvent( rc_event_1 ) )
ModeUpdate( pprz_mode, PPRZ_MODE_OF_PULSE( from_fbw.channels[ RADIO_MODE ],
from_fbw.status ) );
else
return FALSE;
}
#ifdef RADIO_LLS
/** \fn inline uint8_t ir_estim_mode_update( void )
\brief update ir estimation if RADIO_LLS is true \n
*/
inline uint8_t ir_estim_mode_update( void )
{
ModeUpdate( ir_estim_mode,
IR_ESTIM_MODE_OF_PULSE( from_fbw.channels[ RADIO_LLS ] ) );
}
#endif
/** \fn inline uint8_t mcu1_status_update( void )
\brief @@@@@ A FIXER @@@@@
*/
inline uint8_t mcu1_status_update( void )
{
uint8_t new_mode = from_fbw.status;
if ( mcu1_status != new_mode ) {
bool_t changed = ( ( mcu1_status & MASK_FBW_CHANGED ) !=
( new_mode & MASK_FBW_CHANGED ) );
mcu1_status = new_mode;
return changed;
}
return FALSE;
}
/** Delay between @@@@@ A FIXER @@@@@ */
#define EVENT_DELAY 20
/** \def EventUpdate(_cpt, _cond, _event)
@@@@@ A FIXER @@@@@
*/
#define EventUpdate(_cpt, _cond, _event) \
if (_cond) { \
if (_cpt < EVENT_DELAY) { \
_cpt++; \
if (_cpt == EVENT_DELAY) \
_event = TRUE; \
} \
} else { \
_cpt = 0; \
_event = FALSE; \
}
/** \def EventPos(_cpt, _channel, _event)
@@@@@ A FIXER @@@@@
*/
#define EventPos(_cpt, _channel, _event) \
EventUpdate(_cpt, (inflight_calib_mode==IF_CALIB_MODE_NONE && from_fbw.channels[ _channel ]>(int)(0.75*MAX_PPRZ)), _event)
/** \def EventNeg(_cpt, _channel, _event)
@@@@@ A FIXER @@@@@
*/
#define EventNeg(_cpt, _channel, _event) \
EventUpdate(_cpt, (inflight_calib_mode==IF_CALIB_MODE_NONE && from_fbw.channels[ _channel ]<(int)(-0.75*MAX_PPRZ)), _event)
/** \fn static inline void events_update( void )
@@@@@ A FIXER @@@@@
*/
static inline void events_update( void )
{
static uint16_t event1_cpt = 0;
static uint16_t event2_cpt = 0;
EventPos( event1_cpt, RADIO_GAIN1, rc_event_1 );
EventNeg( event2_cpt, RADIO_GAIN1, rc_event_2 );
}
/** \fn inline void copy_from_to_fbw ( void )
\brief Send back uncontrolled channels (only rudder)
*/
inline void copy_from_to_fbw ( void )
{
to_fbw.channels[ RADIO_YAW ] = from_fbw.channels[ RADIO_YAW ];
#ifdef ANTON_T7
to_fbw.channels[ RADIO_PITCH ] = from_fbw.channels[ RADIO_PITCH ];
#endif
to_fbw.status = 0;
}
#ifdef EST_TEST
float est_pos_x;
float est_pos_y;
float est_fcourse;
uint8_t ticks_last_est; // 20Hz
#endif /* EST_TEST */
/*
called at 20Hz.
sends a serie of initialisation messages followed by a stream of periodic ones
*/
/** Define number of message at initialisation */
#define INIT_MSG_NB 2
/** @@@@@ A FIXER @@@@ */
#define HI_FREQ_PHASE_NB 5
//static char signature[ 16 ] = MESSAGES_MD5SUM;
/** \def PERIODIC_SEND_BAT()
@@@@@ A FIXER @@@@@
*/
#define PERIODIC_SEND_BAT() DOWNLINK_SEND_BAT(&vsupply, &estimator_flight_time, &low_battery, &block_time, &stage_time)
/** \def EventPos(_cpt, _channel, _event)
@@@@@ A FIXER @@@@@
*/
#define PERIODIC_SEND_DEBUG() DOWNLINK_SEND_DEBUG(&link_fbw_nb_err, &link_fbw_fbw_nb_err, &modem_nb_ovrn, &gps_nb_ovrn, &mcu1_ppm_cpt);
/** \def EventPos(_cpt, _channel, _event)
@@@@@ A FIXER @@@@@
*/
#define PERIODIC_SEND_ATTITUDE() DOWNLINK_SEND_ATTITUDE(&estimator_phi, &estimator_psi, &estimator_theta);
/** \def EventPos(_cpt, _channel, _event)
@@@@@ A FIXER @@@@@
*/
#define PERIODIC_SEND_ADC() DOWNLINK_SEND_ADC(&ir_roll, &ir_pitch);
/** \def EventPos(_cpt, _channel, _event)
@@@@@ A FIXER @@@@@
*/
#define PERIODIC_SEND_STABILISATION() DOWNLINK_SEND_STABILISATION(&roll_pgain, &pitch_pgain);
#define PERIODIC_SEND_CLIMB_PID() DOWNLINK_SEND_CLIMB_PID(&desired_gaz, &desired_climb, &climb_sum_err, &climb_pgain);
#define PERIODIC_SEND_PPRZ_MODE() DOWNLINK_SEND_PPRZ_MODE(&pprz_mode, &vertical_mode, &inflight_calib_mode, &mcu1_status, &ir_estim_mode);
#define PERIODIC_SEND_DESIRED() DOWNLINK_SEND_DESIRED(&desired_roll, &desired_pitch, &desired_x, &desired_y, &desired_altitude);
#define PERIODIC_SEND_PITCH() DOWNLINK_SEND_PITCH(&ir_pitch, &ir_pitch_neutral, &ir_gain);
#define PERIODIC_SEND_NAVIGATION_REF() DOWNLINK_SEND_NAVIGATION_REF(&utm_east0, &utm_north0);
#ifdef RADIO_CALIB
#define PERIODIC_SEND_SETTINGS() if (inflight_calib_mode != IF_CALIB_MODE_NONE) DOWNLINK_SEND_SETTINGS(&inflight_calib_mode, &slider_1_val, &slider_2_val);
#else
#define PERIODIC_SEND_SETTINGS()
#endif
/** \fn inline void reporting_task( void )
\brief Send a serie of initialisation messages followed by a stream of periodic ones\n
Called at 20Hz.
*/
void send_boot( void )
{
/** initialisation phase during boot */
if ( boot ) {
DOWNLINK_SEND_BOOT( &version );
DOWNLINK_SEND_RAD_OF_IR( &estimator_ir, &estimator_rad, &estimator_rad_of_ir,
&ir_roll_neutral, &ir_pitch_neutral );
boot = FALSE;
}
}
void send_attitude( void ) //500ms
{
if ( !boot ) {
count++;
if ( count == 250 ) count = 0;
if ( count % 5 == 0 )
PERIODIC_SEND_ATTITUDE();
}
}
void send_adc( void ) //500ms
{
if ( !boot ) {
if ( count % 5 == 1 ) PERIODIC_SEND_ADC();
}
}
void send_settings( void ) //500ms
{
if ( !boot ) {
if ( count % 5 == 2 ) PERIODIC_SEND_SETTINGS();
}
}
void send_desired( void ) //1000ms
{
if ( !boot ) {
if ( count % 10 == 3 ) PERIODIC_SEND_DESIRED();
}
}
void send_bat( void ) //2000ms
{
if ( !boot ) {
if ( count % 20 == 8 ) PERIODIC_SEND_BAT();
}
}
void send_climb( void ) //2000ms
{
if ( !boot ) {
if ( count % 20 == 18 ) PERIODIC_SEND_CLIMB_PID();
}
}
void send_mode( void ) //5000ms
{
if ( !boot ) {
if ( count % 50 == 9 ) PERIODIC_SEND_PPRZ_MODE();
}
}
void send_debug( void ) //5000ms
{
if ( !boot ) {
if ( count % 50 == 29 ) PERIODIC_SEND_DEBUG();
}
}
void send_nav_ref( void ) //10000ms
{
if ( !boot ) {
if ( count % 100 == 49 ) PERIODIC_SEND_NAVIGATION_REF();
}
}
/** \fn inline uint8_t inflight_calib_mode_update ( void )
\brief @@@@@ A FIXER @@@@@
*/
inline uint8_t inflight_calib_mode_update ( void )
{
ModeUpdate( inflight_calib_mode,
IF_CALIB_MODE_OF_PULSE( from_fbw.channels[ RADIO_CALIB ] ) );
}
/** \fn inline void radio_control_task( void )
\brief @@@@@ A FIXER @@@@@
*/
void _Pragma( "entrypoint" ) radio_control_task( void )
{
bool_t calib_mode_changed;
if ( link_fbw_receive_valid ) {
uint8_t mode_changed = FALSE;
copy_from_to_fbw();
if ( ( bit_is_set( from_fbw.status, RADIO_REALLY_LOST ) &&
( pprz_mode == PPRZ_MODE_AUTO1 || pprz_mode == PPRZ_MODE_MANUAL ) ) ||
too_far_from_home ) {
pprz_mode = PPRZ_MODE_HOME;
mode_changed = TRUE;
}
if ( bit_is_set( from_fbw.status, AVERAGED_CHANNELS_SENT ) ) {
bool_t pprz_mode_changed = pprz_mode_update();
mode_changed |= pprz_mode_changed;
#ifdef RADIO_LLS
mode_changed |= ir_estim_mode_update();
#endif
#ifdef RADIO_CALIB
calib_mode_changed = inflight_calib_mode_update();
inflight_calib( calib_mode_changed || pprz_mode_changed );
mode_changed |= calib_mode_changed;
#endif
}
mode_changed |= mcu1_status_update();
if ( mode_changed )
DOWNLINK_SEND_PPRZ_MODE( &pprz_mode, &vertical_mode, &inflight_calib_mode,
&mcu1_status, &ir_estim_mode );
if ( pprz_mode == PPRZ_MODE_AUTO1 ) {
desired_roll = FLOAT_OF_PPRZ( from_fbw.channels[ RADIO_ROLL ], 0., -0.6 );
desired_pitch = FLOAT_OF_PPRZ( from_fbw.channels[ RADIO_PITCH ], 0., 0.5 );
} // else asynchronously set by course_pid_run()
if ( pprz_mode == PPRZ_MODE_MANUAL || pprz_mode == PPRZ_MODE_AUTO1 ) {
desired_gaz = from_fbw.channels[ RADIO_THROTTLE ];
#ifdef ANTON_MAGICAL_MISTERY_GAINS
roll_pgain = ROLL_PGAIN * ( 1 - 5. / 7. * from_fbw.channels[ RADIO_THROTTLE ] /
MAX_PPRZ );
pitch_pgain = PITCH_PGAIN * ( 1 - 1. / 3. * from_fbw.channels[ RADIO_THROTTLE ] /
MAX_PPRZ );
#endif /* ANTON_MAGICAL_MISTERY_GAINS */
}
// else asynchronously set by climb_pid_run();
mcu1_ppm_cpt = from_fbw.ppm_cpt;
vsupply = from_fbw.vsupply;
events_update();
if ( !estimator_flight_time ) {
ground_calibrate();
if ( pprz_mode == PPRZ_MODE_AUTO2 &&
from_fbw.channels[ RADIO_THROTTLE ] > GAZ_THRESHOLD_TAKEOFF )
launch = TRUE;
}
}
}
/** \fn void navigation_task( void )
\brief Compute desired_course
*/
void navigation_update( void )
{
/* Default to keep compatibility with previous behaviour */
lateral_mode = LATERAL_MODE_COURSE;
if ( pprz_mode == PPRZ_MODE_HOME )
nav_home();
else
nav_update();
}
void send_nav_values( void )
{
DOWNLINK_SEND_NAVIGATION( &nav_block, &nav_stage, &estimator_x, &estimator_y,
&desired_course, &dist2_to_wp, &course_pgain, &dist2_to_home );
}
void course_run( void )
{
if ( pprz_mode == PPRZ_MODE_AUTO2 || pprz_mode == PPRZ_MODE_HOME ) {
if ( lateral_mode >= LATERAL_MODE_COURSE )
course_pid_run(); /* aka compute nav_desired_roll */
desired_roll = nav_desired_roll;
}
}
void _Pragma( "entrypoint" ) altitude_control_task( void )
{
if ( pprz_mode == PPRZ_MODE_AUTO2 || pprz_mode == PPRZ_MODE_HOME ) {
if ( vertical_mode == VERTICAL_MODE_AUTO_ALT )
altitude_pid_run();
}
}
void _Pragma( "entrypoint" ) climb_control_task( void )
{
if ( pprz_mode == PPRZ_MODE_AUTO2 || pprz_mode == PPRZ_MODE_HOME ) {
if ( vertical_mode >= VERTICAL_MODE_AUTO_CLIMB )
climb_pid_run();
if ( vertical_mode == VERTICAL_MODE_AUTO_GAZ )
desired_gaz = nav_desired_gaz;
if ( low_battery || ( !estimator_flight_time && !launch ) )
desired_gaz = 0.;
}
}
#define PERIOD (256. * 1024. / CLOCK / 1000000.)
/** Maximum time allowed for low battery level */
#define LOW_BATTERY_DELAY 5
/** \fn inline void periodic_task( void )
\brief Do periodic tasks at 61 Hz
*/
/**There are four @@@@@ boucles @@@@@:
- 20 Hz:
- lets use \a reporting_task at 10 Hz
- updates ir with \a ir_update
- updates estimator of ir with \a estimator_update_state_infrared
- set \a desired_aileron and \a desired_elevator with \a roll_pitch_pid_run
- sends to \a fbw \a desired_gaz, \a desired_aileron and
\a desired_elevator \note \a desired_gaz is set upon GPS
message reception
- 10 Hz: to get a \a stage_time_ds
- 4 Hz:
- calls \a estimator_propagate_state
- do navigation with \a navigation_task
*/
#ifdef PAPABENCH_SINGLE
uint8_t _20Hz = 0;
uint8_t _1Hz = 0;
#else
static uint8_t _20Hz = 0;
static uint8_t _1Hz = 0;
#endif
void periodic_task( void )
{
static uint8_t _10Hz = 0;
static uint8_t _4Hz = 0;
static uint8_t t = 0;
estimator_t += PERIOD;
_20Hz++;
if ( _20Hz >= 3 ) _20Hz = 0;
_10Hz++;
if ( _10Hz >= 6 ) _10Hz = 0;
_4Hz++;
if ( _4Hz >= 15 ) _4Hz = 0;
_1Hz++;
if ( _1Hz >= 61 ) _1Hz = 0;
if ( !_10Hz )
stage_time_ds = stage_time_ds + .1;
if ( !_1Hz ) {
if ( estimator_flight_time ) estimator_flight_time++;
cputime++;
stage_time_ds = ( int16_t )( stage_time_ds + .5 );
stage_time++;
block_time++;
if ( vsupply < LOW_BATTERY ) t++;
else t = 0;
low_battery |= ( t >= LOW_BATTERY_DELAY );
}
/*#ifdef WITH_SWITCH
switch(_4Hz) {
case 0:
estimator_propagate_state();
navigation_task();
altitude_control_task();//added 4-05-06
climb_control_task();//added 04-05-06
break;
// default:
}
switch (_20Hz) {
case 0:
break;
case 1: {
static uint8_t odd;
odd++;
if (odd & 0x01)
reporting_task();
break;
}
case 2:
stabilisation_task();
link_fbw_send();
break;
default:
fatal_error_nb++;
}
#else */
if ( _4Hz == 0 ) {
estimator_propagate_state();
/*navigation_task */
navigation_update();
send_nav_values();
course_run();
/*end navigation*/
altitude_control_task();
climb_control_task();
}
if ( _20Hz == 0 )
{}
else
if ( _20Hz == 1 ) {
static uint8_t odd;
odd++;
if ( odd & 0x01 ) {
/*reporting_task()*/
send_boot();
send_attitude();
send_adc();
send_settings();
send_desired();
send_bat();
send_climb();
send_mode();
send_debug();
send_nav_ref();
}
} else
if ( _20Hz == 2 ) {
stabilisation_task();
link_fbw_send();
} else
fatal_error_nb++;
//#endif
}
void _Pragma( "entrypoint" ) stabilisation_task( void )
{
ir_update();
estimator_update_state_infrared();
roll_pitch_pid_run(); // Set desired_aileron & desired_elevator
to_fbw.channels[ RADIO_THROTTLE ] =
desired_gaz; // desired_gaz is set upon GPS message reception
to_fbw.channels[ RADIO_ROLL ] = desired_aileron;
#ifndef ANTON_T7
to_fbw.channels[ RADIO_PITCH ] = desired_elevator;
#endif
// Code for camera stabilization, FIXME put that elsewhere
to_fbw.channels[ RADIO_GAIN1 ] = TRIM_PPRZ( MAX_PPRZ / 0.75 *
( -estimator_phi ) );
}
/*void receive_gps_data_task(void)
{
parse_gps_msg();
gps_msg_received = FALSE;
if (gps_pos_available)
{
use_gps_pos();
gps_pos_available = FALSE;
}
}*/
/** \fn void use_gps_pos( void )
\brief use GPS
*/
/**Send by downlink the GPS and rad_of_ir messages with \a DOWNLINK_SEND_GPS
and \a DOWNLINK_SEND_RAD_OF_IR \n
If \a estimator_flight_time is null and \a estimator_hspeed_mod is greater
than \a MIN_SPEED_FOR_TAKEOFF, set the \a estimator_flight_time to 1 and \a
launch to true (which is not set in non auto launch. Then call
\a DOWNLINK_SEND_TAKEOFF
*/
void send_gps_pos( void )
{
gps_msg_received = FALSE;
if ( gps_pos_available ) {
DOWNLINK_SEND_GPS( &gps_mode, &gps_utm_east, &gps_utm_north, &gps_fcourse,
&gps_falt, &gps_fspeed, &gps_fclimb, &gps_ftow );
estimator_update_state_gps();
}
}
void send_radIR( void )
{
if ( gps_pos_available )
DOWNLINK_SEND_RAD_OF_IR( &estimator_ir, &estimator_rad, &estimator_rad_of_ir,
&ir_roll_neutral, &ir_pitch_neutral );
}
void send_takeOff( void )
{
if ( gps_pos_available ) {
if ( !estimator_flight_time &&
( estimator_hspeed_mod > MIN_SPEED_FOR_TAKEOFF ) ) {
estimator_flight_time = 1;
launch = TRUE; /* Not set in non auto launch */
DOWNLINK_SEND_TAKEOFF( &cputime );
}
gps_pos_available = FALSE;
}
}

View File

@ -0,0 +1,101 @@
/*
$Id: mainloop.c,v 1.3 2011-01-25 09:40:37 plazar Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <arch/interrupt.h>
#include "std.h"
#include "timer.h"
#include "modem.h"
#include "adc.h"
#include "airframe.h"
#include "autopilot.h"
#include "spi.h"
#include "link_fbw.h"
#include "gps.h"
#include "nav.h"
#include "infrared.h"
#include "estimator.h"
#include "downlink.h"
#ifndef PAPABENCH_SINGLE
void fbw_init( void );
void fbw_schedule( void );
#endif
int main( void )
{
uint8_t init_cpt;
/* init peripherals */
timer_init();
modem_init();
adc_init();
#ifdef CTL_BRD_V1_1
adc_buf_channel( ADC_CHANNEL_BAT, &buf_bat );
#endif
spi_init();
link_fbw_init();
gps_init();
nav_init();
ir_init();
estimator_init();
# ifdef PAPABENCH_SINGLE
fbw_init();
# endif
/* start interrupt task */
//sei(); /*Fadia*/
/* Wait 0.5s (for modem init ?) */
init_cpt = 30;
_Pragma( "loopbound min 31 max 31" )
while ( init_cpt ) {
if ( timer_periodic() )
init_cpt--;
}
/* enter mainloop */
#ifndef NO_MAINLOOP
while ( 1 ) {
#endif
if ( timer_periodic() ) {
periodic_task();
# if PAPABENCH_SINGLE
fbw_schedule();
# endif
}
if ( gps_msg_received ) {
/*receive_gps_data_task()*/
parse_gps_msg();
send_gps_pos();
send_radIR();
send_takeOff();
}
if ( link_fbw_receive_complete ) {
link_fbw_receive_complete = FALSE;
radio_control_task();
}
#ifndef NO_MAINLOOP
}
#endif
return 0;
}

View File

@ -0,0 +1,95 @@
/*
Paparazzi mcu0 cmx469 modem functions
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <inttypes.h>
#include <arch/io.h>
#include <arch/signal.h>
#include <arch/interrupt.h>
//#include <stdlib.h>
#include "modem.h"
#include "std.h"
uint8_t modem_nb_ovrn;
uint8_t tx_head;
volatile uint8_t tx_tail;
uint8_t tx_buf[ TX_BUF_SIZE ];
uint8_t tx_byte;
uint8_t tx_byte_idx;
uint8_t ck_a, ck_b;
void modem_init( void )
{
/*
on >= V1.2 boards, 4MHz modem clock is generated
by one PWM module.
*/
#if defined CTL_BRD_V1_2 || defined CTL_BRD_V1_2_1
MODEM_OSC_DDR |= _BV( MODEM_OSC );
OCR0 = 1; /* 4MhZ */
TCCR0 = _BV( WGM01 ) | _BV( COM00 ) | _BV( CS00 );
#endif
/* setup TX_EN and TX_DATA pin as output */
MODEM_TX_DDR |= _BV( MODEM_TX_EN ) | _BV( MODEM_TX_DATA );
/* data idles hight */
sbi( MODEM_TX_PORT, MODEM_TX_DATA );
/* enable transmitter */
cbi( MODEM_TX_PORT, MODEM_TX_EN );
/* set interrupt on failing edge of clock */
MODEM_CLK_INT_REG |= MODEM_CLK_INT_CFG;
}
SIGNAL( MODEM_CLK_INT_SIG )
{
/* start bit */
if ( tx_byte_idx == 0 )
cbi( MODEM_TX_PORT, MODEM_TX_DATA );
/* 8 data bits */
else
if ( tx_byte_idx < 9 ) {
if ( tx_byte & 0x01 )
sbi( MODEM_TX_PORT, MODEM_TX_DATA );
else
cbi( MODEM_TX_PORT, MODEM_TX_DATA );
tx_byte >>= 1;
}
/* stop_bit */
else
sbi( MODEM_TX_PORT, MODEM_TX_DATA );
tx_byte_idx++;
/* next byte */
if ( tx_byte_idx >= 10 ) {
/* if we have nothing left to transmit */
if ( tx_head == tx_tail ) {
/* disable clock interrupt */
cbi( EIMSK, MODEM_CLK_INT );
} else {
/* else load next byte */
MODEM_LOAD_NEXT_BYTE();
}
}
}

View File

@ -0,0 +1,140 @@
/*
Paparazzi mcu0 cmx469 modem functions
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef MODEM_H
#define MODEM_H
#include "airframe.h"
void modem_init( void );
extern uint8_t modem_nb_ovrn;
#define TX_BUF_SIZE 255
extern uint8_t tx_head;
extern volatile uint8_t tx_tail;
extern uint8_t tx_buf[ TX_BUF_SIZE ];
extern uint8_t tx_byte;
extern uint8_t tx_byte_idx;
extern uint8_t ck_a, ck_b;
#define ModemStartMessage(id) \
{ MODEM_PUT_1_BYTE(STX); MODEM_PUT_1_BYTE(id); ck_a = id; ck_b = id; }
#define ModemEndMessage() \
{ MODEM_PUT_1_BYTE(ck_a); MODEM_PUT_1_BYTE(ck_b); MODEM_CHECK_RUNNING(); }
#define MODEM_TX_PORT PORTD
#define MODEM_TX_DDR DDRD
#define MODEM_TX_EN 7
#define MODEM_TX_DATA 6
#ifdef CTL_BRD_V1_1
#define MODEM_CLK_DDR DDRD
#define MODEM_CLK_PORT PORTD
#define MODEM_CLK 0
#define MODEM_CLK_INT INT0
#define MODEM_CLK_INT_REG EICRA
#define MODEM_CLK_INT_CFG _BV(ISC01)
#define MODEM_CLK_INT_SIG SIG_INTERRUPT0
#endif /* CTL_BRD_V1_1 */
#ifdef CTL_BRD_V1_2
#define MODEM_CLK_DDR DDRD
#define MODEM_CLK_PORT PORTD
#define MODEM_CLK 0
#define MODEM_CLK_INT INT0
#define MODEM_CLK_INT_REG EICRA
#define MODEM_CLK_INT_CFG _BV(ISC01)
#define MODEM_CLK_INT_SIG SIG_INTERRUPT0
#define MODEM_OSC_DDR DDRB
#define MODEM_OSC_PORT PORTB
#define MODEM_OSC 4
#endif /* CTL_BRD_V1_2 */
#ifdef CTL_BRD_V1_2_1
#define MODEM_CLK_DDR DDRE
#define MODEM_CLK_PORT PORTE
#define MODEM_CLK 4
#define MODEM_CLK_INT INT4
#define MODEM_CLK_INT_REG EICRB
#define MODEM_CLK_INT_CFG _BV(ISC41)
#define MODEM_CLK_INT_SIG SIG_INTERRUPT4
#define MODEM_OSC_DDR DDRB
#define MODEM_OSC_PORT PORTB
#define MODEM_OSC 4
#endif /* CTL_BRD_V1_2_1 */
#define MODEM_CHECK_FREE_SPACE(_space) (tx_head>=tx_tail? _space < (TX_BUF_SIZE - (tx_head - tx_tail)) : _space < (tx_tail - tx_head))
#define MODEM_PUT_1_BYTE(_byte) { \
tx_buf[tx_head] = _byte; \
tx_head++; \
if (tx_head >= TX_BUF_SIZE) tx_head = 0; \
}
#define MODEM_PUT_1_BYTE_BY_ADDR(_byte) { \
tx_buf[tx_head] = *(_byte); \
ck_a += *(_byte); \
ck_b += ck_a; \
tx_head++; \
if (tx_head >= TX_BUF_SIZE) tx_head = 0; \
}
#define MODEM_PUT_2_BYTE_BY_ADDR(_byte) { \
MODEM_PUT_1_BYTE_BY_ADDR(_byte); \
MODEM_PUT_1_BYTE_BY_ADDR(_byte+1); \
}
#define MODEM_PUT_4_BYTE_BY_ADDR(_byte) { \
MODEM_PUT_1_BYTE_BY_ADDR(_byte); \
MODEM_PUT_1_BYTE_BY_ADDR(_byte+1); \
MODEM_PUT_1_BYTE_BY_ADDR(_byte+2); \
MODEM_PUT_1_BYTE_BY_ADDR(_byte+3); \
}
#define MODEM_LOAD_NEXT_BYTE() { \
tx_byte = tx_buf[tx_tail]; \
tx_byte_idx = 0; \
tx_tail++; \
if( tx_tail >= TX_BUF_SIZE ) \
tx_tail = 0; \
}
#define MODEM_CHECK_RUNNING() { \
if (!(EIMSK & _BV(MODEM_CLK_INT))) { \
MODEM_LOAD_NEXT_BYTE() \
sbi(EIFR, INTF0); \
sbi(EIMSK, MODEM_CLK_INT); \
} \
}
#endif /* MODEM_H */

View File

@ -0,0 +1,216 @@
/*
$Id: nav.c,v 1.3 2011-01-21 11:52:44 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#define NAV_C
#include "math.h"
#include "nav.h"
#include "estimator.h"
#include "pid.h"
#include "autopilot.h"
#include "link_fbw.h"
#include "airframe.h"
uint8_t nav_stage, nav_block;
uint8_t excpt_stage; /*To save the current stage when an exception is raised */
static float last_x, last_y;
static uint8_t last_wp;
float rc_pitch;
uint16_t stage_time, block_time;
float stage_time_ds;
#define RcRoll(travel) (from_fbw.channels[ RADIO_ROLL ]* (float)travel /(float)MAX_PPRZ)
#define RcEvent1() CheckEvent(rc_event_1)
#define RcEvent2() CheckEvent(rc_event_2)
#define Block(x) case x: nav_block=x;
#define InitBlock() { nav_stage = 0; block_time = 0; InitStage(); }
#define NextBlock() { nav_block++; InitBlock(); }
#define GotoBlock(b) { nav_block=b; InitBlock(); }
#define Stage(s) case s: nav_stage=s;
#define InitStage() { last_x = estimator_x; last_y = estimator_y; stage_time = 0; stage_time_ds = 0.0; return; }
#define NextStage() { nav_stage++; InitStage() }
#define NextStageFrom(wp) { last_wp = wp; NextStage() }
#define GotoStage(s) { nav_stage = s; InitStage() }
#define Label(x) label_ ## x:
#define Goto(x) { goto label_ ## x; }
#define Exception(x) { excpt_stage = nav_stage; goto label_ ## x; }
#define ReturnFromException(_) { GotoStage(excpt_stage) }
static bool_t approaching( uint8_t );
static inline void fly_to_xy( float x, float y );
static void fly_to( uint8_t wp );
static void route_to( uint8_t last_wp, uint8_t wp );
//static void glide_to(uint8_t last_wp, uint8_t wp);
#define MIN_DX ((int16_t)(MAX_PPRZ * 0.05))
#define DegOfRad(x) ((x) / M_PI * 180.)
#define RadOfDeg(x) ((x)/180. * M_PI)
#define NormCourse(x) { _Pragma("loopbound min 0 max 0") while (x < 0) x += 360; _Pragma("loopbound min 0 max 0") while (x >= 360) x -= 360;}
static float qdr; /* Degrees from 0 to 360 */
#define CircleXY(x,y,radius) { float alpha = atan2(estimator_y - y, estimator_x - x);float alpha_carrot = alpha + CARROT / (-radius * estimator_hspeed_mod); fly_to_xy(x+cos(alpha_carrot)*fabs(radius),y+sin(alpha_carrot)*fabs(radius)); qdr = DegOfRad(M_PI/2 - alpha_carrot); NormCourse(qdr);}
#define MAX_DIST_CARROT 250.
#define MIN_HEIGHT_CARROT 50.
#define MAX_HEIGHT_CARROT 150.
#define Goto3D(radius) { static float carrot_x, carrot_y; int16_t pitch; int16_t roll; if (pprz_mode == PPRZ_MODE_AUTO2) { int16_t yaw = from_fbw.channels[ RADIO_YAW ]; if (yaw > MIN_DX || yaw < -MIN_DX) { carrot_x += FLOAT_OF_PPRZ(yaw, 0, -20.);carrot_x = Min(carrot_x, MAX_DIST_CARROT); carrot_x = Max(carrot_x, -MAX_DIST_CARROT); } pitch = from_fbw.channels[ RADIO_PITCH ]; if (pitch > MIN_DX || pitch < -MIN_DX) { carrot_y += FLOAT_OF_PPRZ(pitch, 0, -20.); carrot_y = Min(carrot_y, MAX_DIST_CARROT); carrot_y = Max(carrot_y, -MAX_DIST_CARROT);} vertical_mode = VERTICAL_MODE_AUTO_ALT; roll = from_fbw.channels[ RADIO_ROLL ]; if (roll > MIN_DX || roll < -MIN_DX) { desired_altitude += FLOAT_OF_PPRZ(roll, 0, -1.0); desired_altitude = Max(desired_altitude, MIN_HEIGHT_CARROT+GROUND_ALT); desired_altitude = Min(desired_altitude, MAX_HEIGHT_CARROT+GROUND_ALT); } } CircleXY(carrot_x, carrot_y, radius); }
#define Circle(wp, radius) CircleXY(waypoints[ wp ].x, waypoints[ wp ].y, radius)
#define And(x, y) ((x) && (y))
#define Or(x, y) ((x) || (y))
//#define Min(x,y) (x < y ? x : y)
//#define Max(x,y) (x > y ? x : y)
#define Qdr(x) (Min(x, 350) < qdr && qdr < x+10)
#include "flight_plan.h"
#define MIN_DIST2_WP (15.*15.)
#define DISTANCE2(p1_x, p1_y, p2) ((p1_x-p2.x)*(p1_x-p2.x)+(p1_y-p2.y)*(p1_y-p2.y))
const int32_t nav_east0 = NAV_UTM_EAST0;
const int32_t nav_north0 = NAV_UTM_NORTH0;
float desired_altitude = GROUND_ALT + MIN_HEIGHT_CARROT;
float desired_x, desired_y;
uint16_t nav_desired_gaz;
float nav_pitch = NAV_PITCH;
float nav_desired_roll;
float dist2_to_wp, dist2_to_home;
bool_t too_far_from_home;
const uint8_t nb_waypoint = NB_WAYPOINT;
struct point waypoints[ NB_WAYPOINT + 1 ] = WAYPOINTS
static float carrot;
static bool_t approaching( uint8_t wp )
{
float pw_x = waypoints[ wp ].x - estimator_x;
float pw_y = waypoints[ wp ].y - estimator_y;
float scal_prod;//changes for PowerPc Fev-06
dist2_to_wp = pw_x * pw_x + pw_y * pw_y;
carrot = CARROT * estimator_hspeed_mod;
carrot = ( carrot < 40 ? 40 : carrot );
if ( dist2_to_wp < carrot * carrot )
return TRUE;
scal_prod = ( waypoints[ wp ].x - last_x ) * pw_x + ( waypoints[ wp ].y - last_y ) *
pw_y;
return ( scal_prod < 0 );
}
static inline void fly_to_xy( float x, float y )
{
desired_x = x;
desired_y = y;
desired_course = M_PI / 2. - atan2( y - estimator_y, x - estimator_x );
}
static void fly_to( uint8_t wp )
{
fly_to_xy( waypoints[ wp ].x, waypoints[ wp ].y );
}
static float alpha, leg;
static void route_to( uint8_t _last_wp, uint8_t wp )
{
float last_wp_x = waypoints[ _last_wp ].x;
float last_wp_y = waypoints[ _last_wp ].y;
float leg_x = waypoints[ wp ].x - last_wp_x;
float leg_y = waypoints[ wp ].y - last_wp_y;
float leg2 = leg_x * leg_x + leg_y * leg_y;
alpha = ( ( estimator_x - last_wp_x ) * leg_x + ( estimator_y - last_wp_y ) *
leg_y ) / leg2;
alpha = Max( alpha, 0. );
leg = sqrt( leg2 );
alpha += Max( carrot / leg, 0. ); /* carrot computed in approaching() */
alpha = Min( 1., alpha );
fly_to_xy( last_wp_x + alpha * leg_x, last_wp_y + alpha * leg_y );
}
/*static void glide_to(uint8_t _last_wp, uint8_t wp) {
float last_alt = waypoints[ _last_wp ].a;
desired_altitude = last_alt + alpha * (waypoints[ wp ].a - last_alt);
pre_climb = NOMINAL_AIRSPEED * (waypoints[ wp ].a - last_alt) / leg;
}*/
static inline void compute_dist2_to_home( void )
{
float ph_x = waypoints[ WP_HOME ].x - estimator_x;
float ph_y = waypoints[ WP_HOME ].y - estimator_y;
dist2_to_home = ph_x * ph_x + ph_y * ph_y;
too_far_from_home = dist2_to_home > ( MAX_DIST_FROM_HOME * MAX_DIST_FROM_HOME );
}
void nav_home( void )
{
//Circle(WP_HOME, 50); /* FIXME: radius should be defined elsewhere */
{
float alpha = atan2( estimator_y - waypoints[ WP_HOME ].y,
estimator_x - waypoints[ WP_HOME ].x );
float alpha_carrot = alpha + CARROT / ( -50 * estimator_hspeed_mod );
fly_to_xy( waypoints[ WP_HOME ].x + cos( alpha_carrot )*fabs( 50 ),
waypoints[ WP_HOME ].y + sin( alpha_carrot )*fabs( 50 ) );
qdr = DegOfRad( M_PI / 2 - alpha_carrot );
{
_Pragma( "loopbounds min 0 max 2" )
while ( qdr < 0 ) qdr += 360;
_Pragma( "loopbounds min 0 max 2" )
while ( qdr >= 360 ) qdr -= 360;
}
}
nav_pitch = 0.; /* Nominal speed */
vertical_mode = VERTICAL_MODE_AUTO_ALT;
desired_altitude = GROUND_ALT + 50;
compute_dist2_to_home();
dist2_to_wp = dist2_to_home;
}
void nav_update( void )
{
compute_dist2_to_home();
auto_nav();
}
void nav_init( void )
{
nav_block = 0;
nav_stage = 0;
}

View File

@ -0,0 +1,58 @@
/*
Paparazzi mcu0 $Id: nav.h,v 1.1 2011-01-18 12:48:39 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef NAV_H
#define NAV_H
#include <std.h>
struct point {
float x;
float y;
float a;
};
extern float cur_pos_x;
extern float cur_pos_y;
extern uint8_t nav_stage, nav_block;
extern float dist2_to_wp, dist2_to_home;
extern const int32_t nav_east0;
extern const int32_t nav_north0;
extern const uint8_t nb_waypoint;
extern struct point waypoints[];
extern float desired_altitude, desired_x, desired_y;
extern uint16_t nav_desired_gaz;
extern float nav_pitch, rc_pitch;
extern bool_t too_far_from_home;
extern uint16_t stage_time, block_time; /* s */
extern float stage_time_ds; /* s */
extern float nav_desired_roll;
void nav_update( void );
void nav_home( void );
void nav_init( void );
#endif /* NAV_H */

View File

@ -0,0 +1,139 @@
/*
$Id: pid.c,v 1.2 2011-01-21 11:52:44 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/** \file pid.c
\brief PID controllers (roll, pitch, climb, altitude, course).
*/
//#include <stdlib.h>
#include <math.h>
#include "pid.h"
#include "autopilot.h"
#include "infrared.h"
#include "estimator.h"
#include "nav.h"
float desired_roll = 0.;
float desired_pitch = 0.;
int16_t desired_gaz, desired_aileron, desired_elevator;
float roll_pgain = ROLL_PGAIN;
float pitch_pgain = PITCH_PGAIN;
float pitch_of_roll = PITCH_OF_ROLL;
float pitch_of_vz_pgain = CLIMB_PITCH_OF_VZ_PGAIN;
float pitch_of_vz = 0.;
/** \brief Computes ::desired_aileron and ::desired_elevator from attitude estimation and expected attitude. */
void roll_pitch_pid_run( void )
{
float err = estimator_phi - desired_roll;
desired_aileron = TRIM_PPRZ( roll_pgain * err );
if ( pitch_of_roll < 0. )
pitch_of_roll = 0.;
err = -( estimator_theta - desired_pitch - pitch_of_roll * fabs(
estimator_phi ) );
desired_elevator = TRIM_PPRZ( pitch_pgain * err );
}
float course_pgain = COURSE_PGAIN;
float desired_course = 0.;
float max_roll = MAX_ROLL;
void course_pid_run( void )
{
float err = estimator_hspeed_dir - desired_course;
//NORM_RAD_ANGLE(err);
_Pragma( "loopbound min 0 max 1" )
while ( err > M_PI ) err -= 2 * M_PI;
_Pragma( "loopbound min 0 max 1" )
while ( err < -M_PI ) err += 2 * M_PI;
nav_desired_roll = course_pgain * err; // * fspeed / AIR_SPEED;
if ( nav_desired_roll > max_roll )
nav_desired_roll = max_roll;
else
if ( nav_desired_roll < -max_roll )
nav_desired_roll = -max_roll;
}
const float climb_pgain = CLIMB_PGAIN;
const float climb_igain = CLIMB_IGAIN;
float desired_climb = 0., pre_climb = 0.;
static const float level_gaz = CLIMB_LEVEL_GAZ;
float climb_sum_err = 0;
float climb_pitch_pgain = CLIMB_PITCH_PGAIN;
float climb_pitch_igain = CLIMB_PITCH_IGAIN;
float climb_pitch_sum_err = 0.;
float max_pitch = MAX_PITCH;
float min_pitch = MIN_PITCH;
#define MAX_CLIMB_SUM_ERR 100
#define MAX_PITCH_CLIMB_SUM_ERR 100
/** \brief Computes desired_gaz and desired_pitch from desired_climb */
void climb_pid_run ( void )
{
float err = estimator_z_dot - desired_climb;
float fgaz;
if ( auto_pitch ) { /* gaz constant */
desired_gaz = nav_desired_gaz;
desired_pitch = climb_pitch_pgain * ( err + climb_pitch_igain *
climb_pitch_sum_err );
if ( desired_pitch > max_pitch )
desired_pitch = max_pitch;
if ( desired_pitch < min_pitch )
desired_pitch = min_pitch;
climb_pitch_sum_err += err;
if ( climb_pitch_sum_err > MAX_PITCH_CLIMB_SUM_ERR )
climb_pitch_sum_err = MAX_PITCH_CLIMB_SUM_ERR;
if ( climb_pitch_sum_err < - MAX_PITCH_CLIMB_SUM_ERR )
climb_pitch_sum_err = - MAX_PITCH_CLIMB_SUM_ERR;
} else { /* pitch almost constant */
/* pitch offset for climb */
pitch_of_vz = ( desired_climb > 0 ) ? desired_climb * pitch_of_vz_pgain : 0.;
fgaz = climb_pgain * ( err + climb_igain * climb_sum_err ) + CLIMB_LEVEL_GAZ +
CLIMB_GAZ_OF_CLIMB * desired_climb;
climb_sum_err += err;
if ( climb_sum_err > MAX_CLIMB_SUM_ERR ) climb_sum_err = MAX_CLIMB_SUM_ERR;
if ( climb_sum_err < - MAX_CLIMB_SUM_ERR ) climb_sum_err = - MAX_CLIMB_SUM_ERR;
desired_gaz = TRIM_UPPRZ( fgaz * MAX_PPRZ );
desired_pitch = nav_pitch + pitch_of_vz;
}
}
float altitude_pgain = ALTITUDE_PGAIN;
void altitude_pid_run( void )
{
float err = estimator_z - desired_altitude;
desired_climb = pre_climb + altitude_pgain * err;
if ( desired_climb < -CLIMB_MAX ) desired_climb = -CLIMB_MAX;
if ( desired_climb > CLIMB_MAX ) desired_climb = CLIMB_MAX;
}

View File

@ -0,0 +1,61 @@
/*
Paparazzi mcu0 $Id: pid.h,v 1.1 2011-01-18 12:48:39 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef PID_H
#define PID_H
#include <inttypes.h>
#define NORM_RAD_ANGLE(x) { \
while (x > M_PI) x -= 2 * M_PI; \
while (x < -M_PI) x += 2 * M_PI; \
}
extern float desired_roll;
extern float max_roll;
extern float desired_pitch;
extern float roll_pgain;
extern float pitch_pgain;
extern float pitch_of_roll;
void roll_pitch_pid_run( void );
extern float course_pgain;
extern float desired_course;
void course_pid_run( void );
extern const float climb_pgain;
extern const float climb_igain;
extern float climb_sum_err;
extern float desired_climb, pre_climb;
extern int16_t desired_gaz, desired_aileron, desired_elevator;
extern float pitch_of_vz_pgain;
extern float pitch_of_vz;
void climb_pid_run( void );
void altitude_pid_run( void );
#endif /* PID_H */

View File

@ -0,0 +1,36 @@
/*
Paparazzi autopilot $Id: sirf.h,v 1.1 2011-01-18 12:48:39 moellmer Exp $
Copyright (C) 2004 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/*
SIRF protocol specific code
*/
#ifndef SIRF_H
#define SIRF_H
#define GPS_FIX_VALID(gps_mode) (gps_mode & 1<<5)
#endif /* SIRF_H */

View File

@ -0,0 +1,43 @@
#include <inttypes.h>
#include <arch/io.h>
#include <arch/signal.h>
#include <arch/interrupt.h>
#include "spi.h"
#include "autopilot.h"
#include "link_fbw.h"
#include "ad7714.h"
volatile uint8_t spi_cur_slave;
uint8_t spi_nb_ovrn;
void spi_init( void )
{
/* Set MOSI and SCK output, all others input */
SPI_DDR |= _BV( SPI_MOSI_PIN ) | _BV( SPI_SCK_PIN );
/* enable pull up for miso */
// SPI_PORT |= _BV(SPI_MISO_PIN);
/* Set SS0 output */
sbi( SPI_SS0_DDR, SPI_SS0_PIN );
/* SS0 idles high (don't select slave yet)*/
SPI_UNSELECT_SLAVE0();
/* Set SS1 output */
sbi( SPI_SS1_DDR, SPI_SS1_PIN );
/* SS1 idles high (don't select slave yet)*/
SPI_UNSELECT_SLAVE1();
spi_cur_slave = SPI_NONE;
}
SIGNAL( SIG_SPI )
{
if ( spi_cur_slave == SPI_SLAVE0 )
link_fbw_on_spi_it();
else
fatal_error_nb++;
}

View File

@ -0,0 +1,74 @@
#ifndef SPI_H
#define SPI_H
//#include "link_autopilot.h"
#define SPI_SS0_PIN 0
#define SPI_SS0_PORT PORTB
#define SPI_SS0_DDR DDRB
#define SPI_IT0_PIN 1
#define SPI_IT0_PORT PORTD
#define SPI_IT0_DDR DDRD
#define SPI_SS1_PIN 7
#define SPI_SS1_PORT PORTE
#define SPI_SS1_DDR DDRE
#define SPI_IT1_PIN 6
#define SPI_IT1_PORT PORTE
#define SPI_IT1_DDR DDRE
#define SPI_SCK_PIN 1
#define SPI_MOSI_PIN 2
#define SPI_MISO_PIN 3
#define SPI_PORT PORTB
#define SPI_DDR DDRB
#define SPI_NONE 0
#define SPI_SLAVE0 1
#define SPI_SLAVE1 2
extern volatile uint8_t spi_cur_slave;
extern uint8_t spi_nb_ovrn;
void spi_init( void );
#define SPI_START(_SPCR_VAL) { \
uint8_t foo; \
SPCR = _SPCR_VAL; \
if (bit_is_set(SPSR, SPIF)) \
foo = SPDR; \
SPCR |= _BV(SPIE); \
}
#define SPI_SELECT_SLAVE0() { \
spi_cur_slave = SPI_SLAVE0; \
cbi( SPI_SS0_PORT, SPI_SS0_PIN );\
}
#define SPI_UNSELECT_SLAVE0() { \
spi_cur_slave = SPI_NONE; \
sbi( SPI_SS0_PORT, SPI_SS0_PIN );\
}
#define SPI_SELECT_SLAVE1() { \
spi_cur_slave = SPI_SLAVE1; \
cbi( SPI_SS1_PORT, SPI_SS1_PIN );\
}
#define SPI_UNSELECT_SLAVE1() { \
spi_cur_slave = SPI_NONE; \
sbi( SPI_SS1_PORT, SPI_SS1_PIN );\
}
#define SPI_SEND(data) { \
SPDR = data; \
}
#define SPI_STOP() { \
cbi(SPCR,SPIE); \
cbi(SPCR, SPE); \
}
#endif /* SPI_H */

View File

@ -0,0 +1,92 @@
/*
Paparazzi mcu0 timer functions
Copied from autopilot (autopilot.sf.net) thanx alot Trammell
Copyright (C) 2002 Trammell Hudson <hudson@rotomotion.com>
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef TIMER_H
#define TIMER_H
#include "std.h"
#include <arch/signal.h>
#include <arch/io.h>
/*
Enable Timer1 (16-bit) running at Clk/1 for the global system
clock. This will be used for computing the servo pulse widths,
PPM decoding, etc.
Low frequency periodic tasks will be signaled by timer 0
running at Clk/1024. For 16 Mhz clock, this will be every
262144 microseconds, or 61 Hz.
*/
static inline void timer_init( void )
{
/* Timer0: Modem clock is started in modem.h in ctc mode*/
/* Timer1 @ Clk/1: System clock, ppm and servos */
TCCR1A = 0x00;
TCCR1B = 0x01;
/* Timer2 @ Clk/1024: Periodic clock */
TCCR2 = 0x05;
}
/*
Retrieve the current time from the global clock in Timer1,
disabling interrupts to avoid stomping on the TEMP register.
If interrupts are already off, the non_atomic form can be used.
*/
static inline uint16_t
timer_now( void )
{
return TCNT1;
}
static inline uint16_t
timer_now_non_atomic( void )
{
return TCNT1L;
}
/*
Periodic tasks occur when Timer2 overflows. Check and unset
the overflow bit. We cycle through four possible periodic states,
so each state occurs every 30 Hz.
*/
static inline bool_t
timer_periodic( void )
{
if ( !bit_is_set( TIFR, TOV2 ) )
return FALSE;
TIFR = 1 << TOV2;
return TRUE;
}
#endif

View File

@ -0,0 +1,149 @@
/*
Paparazzi $Id: uart.c,v 1.3 2011-01-25 09:40:37 plazar Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <arch/signal.h>
#include <arch/interrupt.h>
#include <arch/io.h>
#include "uart.h"
#include "std.h"
#define TX_BUF_SIZE 256
static uint8_t tx_head0; /* next free in buf */
static volatile uint8_t tx_tail0; /* next char to send */
static uint8_t tx_buf0[ TX_BUF_SIZE ];
static uint8_t tx_head1; /* next free in buf */
static volatile uint8_t tx_tail1; /* next char to send */
static uint8_t tx_buf1[ TX_BUF_SIZE ];
void uart0_transmit( const unsigned char data )
{
if ( UCSR0B & _BV( TXCIE ) ) {
/* we are waiting for the last char to be sent : buffering */
if ( tx_tail0 == tx_head0 + 1 ) { /* BUF_SIZE = 256 */
/* Buffer is full (almost, but tx_head = tx_tail means "empty" */
return;
}
tx_buf0[ tx_head0 ] = data;
tx_head0++; /* BUF_SIZE = 256 */
} else { /* Channel is free: just send */
UDR0 = data;
sbi( UCSR0B, TXCIE );
}
}
void uart1_transmit( const unsigned char data )
{
if ( UCSR1B & _BV( TXCIE ) ) {
/* we are waiting for the last char to be sent : buffering */
if ( tx_tail1 == tx_head1 + 1 ) { /* BUF_SIZE = 256 */
/* Buffer is full (almost, but tx_head = tx_tail means "empty" */
return;
}
tx_buf1[ tx_head1 ] = data;
tx_head1++; /* BUF_SIZE = 256 */
} else { /* Channel is free: just send */
UDR1 = data;
sbi( UCSR1B, TXCIE );
}
}
void uart0_print_string( const uint8_t *s )
{
uint8_t i = 0;
_Pragma( "loopbound min 0 max 0" )
while ( s[ i ] ) {
uart0_transmit( s[ i ] );
i++;
}
}
void uart0_print_hex( const uint8_t c )
{
const uint8_t hex[ 16 ] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
uint8_t high = ( c & 0xF0 ) >> 4;
uint8_t low = c & 0x0F;
uart0_transmit( hex[ high ] );
uart0_transmit( hex[ low ] );
}
SIGNAL( SIG_UART0_TRANS )
{
if ( tx_head0 == tx_tail0 ) {
/* Nothing more to send */
cbi( UCSR0B, TXCIE ); /* disable interrupt */
} else {
UDR0 = tx_buf0[ tx_tail0 ];
tx_tail0++; /* warning tx_buf_len is 256 */
}
}
SIGNAL( SIG_UART1_TRANS )
{
if ( tx_head1 == tx_tail1 ) {
/* Nothing more to send */
cbi( UCSR1B, TXCIE ); /* disable interrupt */
} else {
UDR1 = tx_buf1[ tx_tail1 ];
tx_tail1++; /* warning tx_buf_len is 256 */
}
}
void uart0_init( void )
{
/* Baudrate is 38.4k */
UBRR0H = 0;
UBRR0L = 25; // 38.4
// UBRR0L = 103; //9600
/* single speed */
UCSR0A = 0;
/* Enable receiver and transmitter */
UCSR0B = _BV( RXEN ) | _BV( TXEN );
/* Set frame format: 8data, 1stop bit */
UCSR0C = _BV( UCSZ1 ) | _BV( UCSZ0 );
/* Enable uart receive interrupt */
sbi( UCSR0B, RXCIE );
}
void uart1_init( void )
{
/* Baudrate is 38.4k */
UBRR1H = 0;
UBRR1L = 25; // 38.4
// UBRR1L = 103; //9600
/* single speed */
UCSR1A = 0;
/* Enable receiver and transmitter */
UCSR1B = _BV( RXEN ) | _BV( TXEN );
/* Set frame format: 8data, 1stop bit */
UCSR1C = _BV( UCSZ1 ) | _BV( UCSZ0 );
/* Enable uart receive interrupt */
sbi( UCSR1B, RXCIE );
}

View File

@ -0,0 +1,48 @@
/*
Paparazzi $Id: uart.h,v 1.2 2011-01-18 14:55:52 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _UART_H_
#define _UART_H_
#include <inttypes.h>
extern void uart0_init( void );
extern void uart1_init( void );
extern void uart0_print_string( const uint8_t * );
extern void uart0_print_hex( const uint8_t );
void uart0_transmit( const uint8_t );
void uart1_transmit( const uint8_t );
#define ReceiveUart0(cb) \
SIGNAL( SIG_UART0_RECV ) { \
uint8_t c = UDR0; \
cb(c); \
}
#define ReceiveUart1(cb) \
SIGNAL( SIG_UART1_RECV ) { \
uint8_t c = UDR1; \
cb(c); \
}
#endif

View File

@ -0,0 +1,38 @@
/*
Paparazzi autopilot $Id: ubx.h,v 1.1 2011-01-18 12:48:39 moellmer Exp $
Copyright (C) 2004 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/*
UBX protocol specific code
*/
#ifndef UBX_H
#define UBX_H
#define GPS_FIX_VALID(gps_mode) (gps_mode == 3)
extern const int32_t utm_east0;
extern const int32_t utm_north0;
#endif /* UBX_H */

View File

@ -0,0 +1,121 @@
/*
Paparazzi fly by wire adc functions
Copied from autopilot (autopilot.sf.net) thanx alot Trammell
Copyright (C) 2002 Trammell Hudson <hudson@rotomotion.com>
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
//// ADC3 MVSUP
//// ADC6 MVSERVO
#include <arch/signal.h>
#include <arch/interrupt.h>
#include <arch/io.h>
#include "adc_fbw.h"
#include "std.h"
#if defined CTL_BRD_V1_2 || defined CTL_BRD_V1_2_1
#define VOLTAGE_TIME 0x07
#define ANALOG_PORT PORTC
#define ANALOG_PORT_DIR DDRC
//
#define ANALOG_VREF _BV(REFS0) | _BV(REFS1)
uint16_t adc_samples[ NB_ADC ];
static struct adc_buf *buffers[ NB_ADC ];
void fbw_adc_buf_channel( uint8_t adc_channel, struct adc_buf *s )
{
buffers[ adc_channel ] = s;
}
void
fbw_adc_init( void )
{
uint8_t i;
/* Ensure that our port is for input with no pull-ups */
ANALOG_PORT = 0x00;
ANALOG_PORT_DIR = 0x00;
/* Select our external voltage ref */
ADMUX = ANALOG_VREF;
/* Select out clock, turn on the ADC interrupt and start conversion */
ADCSRA = 0
| VOLTAGE_TIME
| _BV( ADEN )
| _BV( ADIE )
| _BV( ADSC );
/* Init to 0 (usefull ?) */
_Pragma( "loopbound min 8 max 8" )
for ( i = 0; i < NB_ADC; i++ )
buffers[ i ] = ( struct adc_buf * )0;
}
/**
Called when the voltage conversion is finished
8.913kHz on mega128@16MHz 1kHz/channel ??
*/
SIGNAL( SIG_ADC )
{
uint8_t adc_input = ADMUX & 0x7;
struct adc_buf *buf = buffers[ adc_input ];
uint16_t adc_value = ADCW;
/* Store result */
adc_samples[ adc_input ] = adc_value;
if ( buf ) {
uint8_t new_head = buf->head + 1;
if ( new_head >= AV_NB_SAMPLE ) new_head = 0;
buf->sum -= buf->values[ new_head ];
buf->values[ new_head ] = adc_value;
buf->sum += adc_value;
buf->head = new_head;
}
/* Find the next input */
adc_input++;
if ( adc_input == 4 )
adc_input = 6; // ADC 4 and 5 for i2c
if ( adc_input >= 8 ) {
adc_input = 0;
#ifdef CTL_BRD_V1_2
adc_input = 1; // WARNING ADC0 is for rservo driver reset on v1.2.0
#endif /* CTL_BRD_V1_2 */
}
/* Select it */
ADMUX = adc_input | ANALOG_VREF;
/* Restart the conversion */
sbi( ADCSR, ADSC );
}
#endif /* CTL_BRD_V1_2 || CTL_BRD_V1_2_1 */

View File

@ -0,0 +1,62 @@
/*
Paparazzi fly by wire adc functions
Copied from autopilot (autopilot.sf.net) thanx alot Trammell
Copyright (C) 2002 Trammell Hudson <hudson@rotomotion.com>
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _ADC_H_
#define _ADC_H_
#include "airframe.h"
#if defined CTL_BRD_V1_2 || defined CTL_BRD_V1_2_1
#include <inttypes.h>
#define NB_ADC 8
/* Array containing the last measured value */
extern uint16_t adc_samples[ NB_ADC ];
void adc_init( void );
#define AV_NB_SAMPLE 0x20
struct adc_buf {
uint16_t sum;
uint16_t values[ AV_NB_SAMPLE ];
uint8_t head;
};
/* Facility to store last values in a circular buffer for a specific
channel: allocate a (struct adc_buf) and register it with the following
function */
void adc_buf_channel( uint8_t adc_channel, struct adc_buf *s );
void fbw_adc_init( void );
void fbw_adc_buf_channel( uint8_t adc_channel, struct adc_buf *s );
#endif /* CTL_BRD_V1_2 || CTL_BRD_V1_2 */
#endif /* _ADC_H_ */

View File

@ -0,0 +1,69 @@
/* $Id: link_autopilot.h,v 1.1 2011-01-18 12:42:42 moellmer Exp $
(c) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef LINK_AUTOPILOT_H
#define LINK_AUTOPILOT_H
#include <inttypes.h>
#include "std.h"
#include "radio.h"
#include "airframe.h"
/*
System clock in MHz.
*/
#define CLOCK 16
typedef int16_t pprz_t; // type of commands
/* !!!!!!!!!!!!!!!!!!! Value used in gen_airframe.ml !!!!!!!!!!!!!!!!! */
#define MAX_PPRZ (600 * CLOCK)
#define MIN_PPRZ -MAX_PPRZ
struct inter_mcu_msg {
int16_t channels[ RADIO_CTL_NB ];
uint8_t ppm_cpt;
uint8_t status;
uint8_t nb_err;
uint8_t vsupply; /* 1e-1 V */
};
// Status bits from FBW to AUTOPILOT
#define STATUS_RADIO_OK 0
#define RADIO_REALLY_LOST 1
#define AVERAGED_CHANNELS_SENT 2
#define MASK_FBW_CHANGED 0x3
// Statut bits from AUTOPILOT to FBW
#define STATUS_AUTO_OK 0
#define FRAME_LENGTH (sizeof(struct inter_mcu_msg)+1)
#define TRESHOLD_MANUAL_PPRZ (MIN_PPRZ / 2)
void test_ppm_task( void );
void check_mega128_values_task( void );
void send_data_to_autopilot_task( void );
void check_failsafe_task( void );
#endif // LINK_AUTOPILOT_H

View File

@ -0,0 +1,219 @@
/*
Paparazzi $Id: main.c,v 1.4 2011-01-25 10:42:14 plazar Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <inttypes.h>
#include <io.h>
#include <signal.h>
#include <interrupt.h>
#include "timer.h"
#include "servo.h"
#include "ppm.h"
#include "spi.h"
#include "link_autopilot.h"
#include "radio.h"
#include "uart.h"
#ifndef CTL_BRD_V1_1
#include "adc_fbw.h"
struct adc_buf vsupply_adc_buf;
struct adc_buf vservos_adc_buf;
#endif
uint8_t mode;
static uint8_t time_since_last_mega128;
static uint16_t time_since_last_ppm;
bool_t radio_ok, mega128_ok, radio_really_lost;
static const pprz_t failsafe[ ] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
static uint8_t ppm_cpt, last_ppm_cpt;
#define STALLED_TIME 30 // 500ms with a 60Hz timer
#define REALLY_STALLED_TIME 300 // 5s with a 60Hz timer
/* static inline void status_transmit( void ) { */
/* uint8_t i; */
/* uart_transmit(7); */
/* uart_transmit(7); */
/* for (i=0; i<sizeof(struct inter_mcu_msg); i++) */
/* uart_transmit(((uint8_t*)&to_mega128)[ i ]); */
/* uart_transmit('\n'); */
/* uart_transmit(7); */
/* uart_transmit(7); */
/* uint8_t i; */
/* for(i = 0; i < RADIO_CTL_NB; i++) { */
/* extern uint16_t ppm_pulses[ ]; */
/* uart_transmit(ppm_pulses[ i ]>>8); */
/* uart_transmit(ppm_pulses[ i ] & 0xff); */
/* } */
/* uart_transmit('\n'); */
/* } */
/* Prepare data to be sent to mcu0 */
static void to_autopilot_from_last_radio ( void )
{
uint8_t i;
_Pragma( "loopbound min 9 max 9" )
for ( i = 0; i < RADIO_CTL_NB; i++ )
to_mega128.channels[ i ] = last_radio[ i ];
to_mega128.status = ( radio_ok ? _BV( STATUS_RADIO_OK ) : 0 );
to_mega128.status |= ( radio_really_lost ? _BV( RADIO_REALLY_LOST ) : 0 );
if ( last_radio_contains_avg_channels ) {
to_mega128.status |= _BV( AVERAGED_CHANNELS_SENT );
last_radio_contains_avg_channels = FALSE;
}
to_mega128.ppm_cpt = last_ppm_cpt;
#ifndef CTL_BRD_V1_1
to_mega128.vsupply = VoltageOfAdc( vsupply_adc_buf.sum / AV_NB_SAMPLE ) * 10;
#else
to_mega128.vsupply = 0;
#endif
}
void _Pragma( "entrypoint" ) send_data_to_autopilot_task( void )
{
#ifndef WCET_ANALYSIS
if ( !SpiIsSelected() && spi_was_interrupted ) {
spi_was_interrupted = FALSE;
to_autopilot_from_last_radio();
spi_reset();
}
#endif
}
#ifdef PAPABENCH_SINGLE
extern uint8_t _1Hz;
extern uint8_t _20Hz;
#else
static uint8_t _1Hz;
static uint8_t _20Hz;
#endif
void fbw_init( void )
{
uart_init_tx();
uart_print_string( "FBW Booting $Id: main.c,v 1.4 2011-01-25 10:42:14 plazar Exp $\n" );
#ifndef CTL_BRD_V1_1
fbw_adc_init();
fbw_adc_buf_channel( 3, &vsupply_adc_buf );
fbw_adc_buf_channel( 6, &vservos_adc_buf );
#endif
timer_init();
servo_init();
ppm_init();
fbw_spi_init();
//sei(); //FN
}
void fbw_schedule( void )
{
if ( time_since_last_mega128 < STALLED_TIME )
time_since_last_mega128++;
if ( time_since_last_ppm < REALLY_STALLED_TIME )
time_since_last_ppm++;
if ( _1Hz == 0 ) {
last_ppm_cpt = ppm_cpt;
ppm_cpt = 0;
}
test_ppm_task();
check_mega128_values_task();
send_data_to_autopilot_task();
check_failsafe_task();
if ( _20Hz >= 3 )
servo_transmit();
}
#ifndef PAPABENCH_SINGLE
int main( void )
{
fbw_init();
#ifndef NO_MAINLOOP
while ( 1 ) {
#endif
fbw_schedule();
if ( timer_periodic() ) {
_1Hz++;
_20Hz++;
if ( _1Hz >= 60 )
_1Hz = 0;
if ( _20Hz >= 3 )
_20Hz = 0;
}
#ifndef NO_MAINLOOP
}
#endif
return 0;
}
#endif
void _Pragma( "entrypoint" ) test_ppm_task( void )
{
if ( ppm_valid ) {
ppm_valid = FALSE;
ppm_cpt++;
radio_ok = TRUE;
radio_really_lost = FALSE;
time_since_last_ppm = 0;
last_radio_from_ppm();
if ( last_radio_contains_avg_channels )
mode = MODE_OF_PPRZ( last_radio[ RADIO_MODE ] );
if ( mode == MODE_MANUAL )
servo_set( last_radio );
} else
if ( mode == MODE_MANUAL && radio_really_lost )
mode = MODE_AUTO;
if ( time_since_last_ppm >= STALLED_TIME )
radio_ok = FALSE;
if ( time_since_last_ppm >= REALLY_STALLED_TIME )
radio_really_lost = TRUE;
}
void _Pragma( "entrypoint" ) check_failsafe_task( void )
{
if ( ( mode == MODE_MANUAL && !radio_ok ) ||
( mode == MODE_AUTO && !mega128_ok ) )
servo_set( failsafe );
}
void _Pragma( "entrypoint" ) check_mega128_values_task( void )
{
#ifndef WCET_ANALYSIS
if ( !SpiIsSelected() && spi_was_interrupted ) {
if ( mega128_receive_valid ) {
time_since_last_mega128 = 0;
mega128_ok = TRUE;
if ( mode == MODE_AUTO )
servo_set( from_mega128.channels );
}
}
if ( time_since_last_mega128 == STALLED_TIME )
mega128_ok = FALSE;
#endif
}

View File

@ -0,0 +1,107 @@
/* $Id: ppm.c,v 1.1 2011-01-18 12:42:42 moellmer Exp $
Copied from autopilot (autopilot.sf.net) thanx alot Trammell
(c) 2003 Trammell Hudson <hudson@rotomotion.com>
(c) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "radio.h"
#include "ppm.h"
#define AVERAGING_PERIOD (PPM_FREQ/4)
/*
Pulse width is computed as the difference between now and the
previous pulse. If no pulse has been received between then and
now, the time of the last pulse will be equal to the last pulse
we measured. Unfortunately, the Input Capture Flag (ICF1) will
not be set since the interrupt routine disables it.
Sync pulses are timed with Timer2, which runs at Clk/1024. This
is slow enough at both 4 and 8 Mhz to measure the lengthy (10ms
or longer) pulse.
Otherwise, compute the pulse width with the 16-bit timer1,
push the pulse width onto the stack and increment the
pulse counter until we have received eight pulses.
*/
uint16_t ppm_pulses[ PPM_NB_PULSES ];
pprz_t last_radio[ PPM_NB_PULSES ];
pprz_t avg_last_radio[ PPM_NB_PULSES ];
bool_t last_radio_contains_avg_channels = FALSE;
volatile bool_t ppm_valid;
/* MC3030, Trame PPM7: 25ms, 10.4 au neutre,
sync pulse = 16.2ms with low value on every channels */
#define RestartPpmCycle() { state = 0; sync_start = TCNT2; return; }
#ifdef PAPABENCH_SINGLE
SIGNAL( SIG_SPM_READY )
#else
SIGNAL( SIG_INPUT_CAPTURE1 )
#endif
{
static uint16_t last;
uint16_t this;
uint16_t width;
static uint8_t state;
static uint8_t sync_start;
this = ICR1;
width = this - last;
last = this;
if ( state == 0 ) {
uint8_t end = TCNT2;
uint8_t diff = ( end - sync_start );
sync_start = end;
/* The frame period of the mc3030 seems to be 25ms.
One pulse lasts from 1.05ms to 2.150ms.
Sync pulse is at least 7ms : (7000*CLOCK)/1024 = 109
*/
if ( diff > ( uint8_t )( ( ( uint32_t )( 7000ul * CLOCK ) ) / 1024ul ) )
state = 1;
} else {
/* Read a data pulses */
if ( width < 700ul * CLOCK || width > 2300ul * CLOCK )
RestartPpmCycle();
ppm_pulses[ state - 1 ] = width;
if ( state >= PPM_NB_PULSES ) {
ppm_valid = 1;
RestartPpmCycle();
} else
state++;
}
return;
}
/* Copy from the ppm receiving buffer to the buffer sent to mcu0 */
void last_radio_from_ppm()
{
LastRadioFromPpm()
}

View File

@ -0,0 +1,102 @@
/* $Id: ppm.h,v 1.2 2011-01-18 14:55:53 moellmer Exp $
Decoder for the trainer ports or hacked receivers for both
Futaba and JR formats. The ppm_valid flag is set whenever
a valid frame is received.
Pulse widths are stored as unscaled 16-bit values in ppm_pulses[ ].
If you require actual microsecond values, divide by CLOCK.
For an 8 Mhz clock and typical servo values, these will range
from 0x1F00 to 0x4000.
Copied from autopilot (autopilot.sf.net) thanx alot Trammell
(c) 2002 Trammell Hudson <hudson@rotomotion.com>
(c) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef PPM_H
#define PPM_H
/**
Receiver types
*/
#define RXFUTABA 0
#define RXJR 1
#define PPM_RX_TYPE RXFUTABA
#define PPM_FREQ 40 // 25ms
#include <inttypes.h>
#include <signal.h>
#include "timer.h"
#include "link_autopilot.h"
#define PpmOfUs(x) ((x)*CLOCK)
#define PPM_DDR DDRB
#define PPM_PORT PORTB
#define PPM_PIN PB0
/*
PPM pulses are falling edge clocked on the ICP, which records
the state of the global clock. We do not use any noise
canceling features.
JR might be rising edge clocked; set that as an option
*/
static inline void
ppm_init( void )
{
#if PPM_RX_TYPE == RXFUTABA
cbi( TCCR1B, ICES1 );
#elif PPM_RX_TYPE == RXJR
sbi( TCCR1B, ICES1 );
#else
# error "ppm.h: Unknown receiver type in PPM_RX_TYPE"
#endif
/* No noise cancelation */
sbi( TCCR1B, ICNC1 );
/* Set ICP to input, no internal pull up */
cbi( PPM_DDR, PPM_PIN );
/* Enable interrupt on input capture */
sbi( TIMSK, TICIE1 );
}
#define PPM_NB_PULSES RADIO_CTL_NB
extern volatile bool_t ppm_valid;
extern pprz_t last_radio[ PPM_NB_PULSES ];
extern bool_t last_radio_contains_avg_channels;
#define MODE_MANUAL 0
#define MODE_AUTO 1
#define MODE_OF_PPRZ(mode) ((mode) < TRESHOLD_MANUAL_PPRZ ? MODE_MANUAL : MODE_AUTO)
extern void last_radio_from_ppm( void );
#endif

View File

@ -0,0 +1,200 @@
/* $Id: servo.c,v 1.4 2011-01-25 10:05:41 plazar Exp $
Copied from autopilot (autopilot.sf.net) thanx alot Trammell
(c) 2002 Trammell Hudson <hudson@rotomotion.com>
(c) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <arch/io.h>
#include <arch/signal.h>
#include "servo.h"
#include "link_autopilot.h"
#include "airframe.h"
#include "uart.h"
/*
Paparazzi boards have one 4017 servo driver.
It is driven by OCR1A (PB1) with reset on PORTD5.
*/
#define _4017_NB_CHANNELS 10
#ifdef CTL_BRD_V1_1
#define _4017_RESET_PORT PORTD
#define _4017_RESET_DDR DDRD
#define _4017_RESET_PIN 5
#endif /* CTL_BRD_V1_1 */
#ifdef CTL_BRD_V1_2
#define _4017_RESET_PORT PORTC
#define _4017_RESET_DDR DDRC
#define _4017_RESET_PIN 0
#endif /* CTL_BRD_V1_2 */
#ifdef CTL_BRD_V1_2_1
#define _4017_RESET_PORT PORTD
#define _4017_RESET_DDR DDRD
#define _4017_RESET_PIN 7
#endif /* CTL_BRD_V1_2 */
#define _4017_CLOCK_PORT PORTB
#define _4017_CLOCK_DDR DDRB
#define _4017_CLOCK_PIN PB1
#define SERVO_OCR OCR1A
#define SERVO_ENABLE OCIE1A
#define SERVO_FLAG OCF1A
#define SERVO_FORCE FOC1A
#define SERVO_COM0 COM1A0
#define SERVO_COM1 COM1A1
/* Following macro is required since the compiler does not solve at
compile-time indexation in a known array with a known index */
#define SERVO_NEUTRAL_(i) SERVOS_NEUTRALS_ ## i
#define SERVO_NEUTRAL(i) (SERVO_NEUTRAL_(i)*CLOCK)
#define SERVO_NEUTRAL_I(i) (((int[ ])SERVOS_NEUTRALS[ i ])*CLOCK)
#define SERVO_MIN_I(i) (((int[ ])SERVOS_MINS[ i ])*CLOCK)
#define SERVO_MIN (SERVO_MIN_US*CLOCK)
#define SERVO_MAX (SERVO_MAX_US*CLOCK)
#define ChopServo(x) ((x) < SERVO_MIN ? SERVO_MIN : ((x) > SERVO_MAX ? SERVO_MAX : (x)))
/* holds the servo pulses width in clock ticks */
static uint16_t servo_widths[ _4017_NB_CHANNELS ];
/*
We use the output compare registers to generate our servo pulses.
These should be connected to a decade counter that routes the
pulses to the appropriate servo.
Initialization involves:
- Reseting the decade counters
- Writing the first pulse width to the counters
- Setting output compare to set the clock line by calling servo_enable()
- Bringing down the reset lines
Ideally, you can use two decade counters to drive 20 servos.
*/
void
servo_init( void )
{
uint8_t i;
/* Configure the reset and clock lines */
_4017_RESET_DDR |= _BV( _4017_RESET_PIN );
_4017_CLOCK_DDR |= _BV( _4017_CLOCK_PIN );
/* Reset the decade counter */
sbi( _4017_RESET_PORT, _4017_RESET_PIN );
/* Lower the regular servo line */
cbi( _4017_CLOCK_PORT, _4017_CLOCK_PIN );
/* Set all servos at their midpoints */
_Pragma( "loopbound min 10 max 10" )
for ( i = 0 ; i < _4017_NB_CHANNELS ; i++ )
// servo_widths[ i ] = SERVO_MIN;
servo_widths[ i ] = ( SERVO_MIN + SERVO_MAX ) / 2;
/* Set servos to go off some long time from now */
SERVO_OCR = 32768ul;
/*
Configure output compare to toggle the output bits.
*/
TCCR1A |= _BV( SERVO_COM0 );
/* Clear the interrupt flags in case they are set */
TIFR = _BV( SERVO_FLAG );
/* Unassert the decade counter reset to start it running */
cbi( _4017_RESET_PORT, _4017_RESET_PIN );
/* Enable our output compare interrupts */
TIMSK |= _BV( SERVO_ENABLE );
}
/*
Interrupt routine
write the next pulse width to OCR register and
assert the servo signal. It will be cleared by
the following compare match.
*/
SIGNAL( SIG_OUTPUT_COMPARE1A )
{
static uint8_t servo = 0;
uint16_t width;
if ( servo >= _4017_NB_CHANNELS ) {
sbi( _4017_RESET_PORT, _4017_RESET_PIN );
servo = 0;
// FIXME: 500 ns required by 4017 reset ???? why does it work without!
// asm( "nop; nop; nop; nop;nop; nop; nop; nop;nop; nop; nop; nop;nop; nop; nop; nop;" );
cbi( _4017_RESET_PORT, _4017_RESET_PIN );
}
width = servo_widths[ servo ];
SERVO_OCR += width;
TCCR1A |= _BV( SERVO_FORCE );
servo++;
}
void servo_set_one( uint8_t servo, uint16_t value_us )
{
servo_widths[ servo ] = ChopServo( CLOCK * value_us );
}
void
_Pragma( "entrypoint" ) servo_transmit( void )
{
uint8_t servo;
uart_transmit( ( uint8_t )0 );
uart_transmit( ( uint8_t )0 );
_Pragma( "loopbound min 10 max 10" )
for ( servo = 0; servo < _4017_NB_CHANNELS; servo++ ) {
uart_transmit( ( uint8_t )( servo_widths[ servo ] >> 8 ) );
uart_transmit( ( uint8_t )( servo_widths[ servo ] & 0xff ) );
}
uart_transmit( ( uint8_t )'\n' );
}
/*
defines how servos react to radio control or autopilot channels
*/
void servo_set( const pprz_t values[ ] )
{
ServoSet( values ); /*Generated from airframe.xml */
}

View File

@ -0,0 +1,61 @@
/* $Id: servo.h,v 1.1 2011-01-18 12:48:40 moellmer Exp $
Copied from autopilot (autopilot.sf.net) thanx alot Trammell
(c) 2002 Trammell Hudson <hudson@rotomotion.com>
(c) 2003 Pascal Brisset, Antoine Drouin
This is the new decade counter based servo driving code. It uses
one 16-bit output compare registers to determine when the regular
servo clock line should be toggled, causing the output to move to the
next servo. The other 16-bit output compare is used to drive a
JR or Futaba compatible high-speed digital servo.
User visibile routines:
- servo_init();
Call once at the start of the program to bring the servos online
and start the external decade counters. This will also start the
high speed servo.
- servo_make_pulse_width( length );
Converts a position value between 0 and 65536 to actual pulsewidth. 0 is
all the way left (1.0 ms pulse) and 65536 is all the way right (2.0 ms
pulse). Use it like this:
servo_widths[ i ] = servo_make_pulse_width( val )
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef SERVO_H
#define SERVO_H
#include <inttypes.h>
#include "timer.h"
extern void servo_init( void );
extern void servo_set( const pprz_t values[ ] );
extern void servo_set_one( uint8_t servo, uint16_t value_us );
extern void servo_transmit( void );
#endif /* SERVO_H */

View File

@ -0,0 +1,115 @@
/*
$Id: spi.c,v 1.2 2011-01-25 10:05:41 plazar Exp $
Paparazzi mcu1 spi functions
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <inttypes.h>
#include <arch/io.h>
#include <arch/signal.h>
#include <arch/interrupt.h>
#include "spi.h"
#define IT_PORT PORTD
#define IT_DDR DDRD
#define IT_PIN 7
#define SPI_DDR DDRB
#define SPI_MOSI_PIN 3
#define SPI_MISO_PIN 4
#define SPI_SCK_PIN 5
struct inter_mcu_msg from_mega128;
struct inter_mcu_msg to_mega128;
volatile bool_t mega128_receive_valid = FALSE;
volatile bool_t spi_was_interrupted = FALSE;
static volatile uint8_t idx_buf = 0;
static volatile uint8_t xor_in, xor_out;
void spi_reset( void )
{
idx_buf = 0;
xor_in = 0;
xor_out = ( ( uint8_t * )&to_mega128 )[ idx_buf ];
SPDR = xor_out;
mega128_receive_valid = FALSE;
}
void fbw_spi_init( void )
{
to_mega128.status = 0;
to_mega128.nb_err = 0;
/* set it pin output */
// IT_DDR |= _BV(IT_PIN);
/* set MISO pin output */
SPI_DDR |= _BV( SPI_MISO_PIN );
/* enable SPI, slave, MSB first, sck idle low */
SPCR = _BV( SPE );
/* enable interrupt */
SPCR |= _BV( SPIE );
}
SIGNAL( SIG_SPI )
{
static uint8_t tmp;
idx_buf++;
spi_was_interrupted = TRUE;
if ( idx_buf > FRAME_LENGTH )
return;
/* we have sent/received a complete frame */
if ( idx_buf == FRAME_LENGTH ) {
/* read checksum from receive register */
tmp = SPDR;
/* notify valid frame */
if ( tmp == xor_in )
mega128_receive_valid = TRUE;
else
to_mega128.nb_err++;
return;
}
/* we are sending/receiving payload */
if ( idx_buf < FRAME_LENGTH - 1 ) {
/* place new payload byte in send register */
tmp = ( ( uint8_t * )&to_mega128 )[ idx_buf ];
SPDR = tmp;
xor_out = xor_out ^ tmp;
}
/* we are done sending the payload */
else { // idx_buf == FRAME_LENGTH - 1
/* place checksum in send register */
SPDR = xor_out;
}
/* read the byte from receive register */
tmp = SPDR;
( ( uint8_t * )&from_mega128 )[ idx_buf - 1 ] = tmp;
xor_in = xor_in ^ tmp;
}

View File

@ -0,0 +1,48 @@
/* $Id: spi.h,v 1.1 2011-01-18 12:42:42 moellmer Exp $
Paparazzi fbw spi functions
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef SPI_H
#define SPI_H
#include "link_autopilot.h"
#define SPI_PORT PORTB
#define SPI_PIN PINB
#define SPI_SS_PIN 2
#define SpiIsSelected() (bit_is_clear(SPI_PIN, SPI_SS_PIN))
extern struct inter_mcu_msg from_mega128;
extern struct inter_mcu_msg to_mega128;
extern volatile bool_t mega128_receive_valid;
extern volatile bool_t spi_was_interrupted;
void spi_init( void );
void spi_reset( void );
#endif /* SPI_H */

View File

@ -0,0 +1,92 @@
/* $Id: timer.h,v 1.2 2011-01-18 14:55:53 moellmer Exp $
Paparazzi fbw timer functions
Copied from autopilot (autopilot.sf.net) thanx alot Trammell
Copyright (C) 2002 Trammell Hudson <hudson@rotomotion.com>
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef TIMER_H
#define TIMER_H
#include <inttypes.h>
#include <signal.h>
#include <io.h>
#include "link_autopilot.h"
/*
Enable Timer1 (16-bit) running at Clk/1 for the global system
clock. This will be used for computing the servo pulse widths,
PPM decoding, etc.
Low frequency periodic tasks will be signaled by timer 2
running at Clk/1024. For 16 Mhz clock, this will be every
16384 microseconds, or 61 Hz.
*/
static inline void
timer_init( void )
{
/* Timer1 @ Clk/1: System clock, ppm and servos pulses */
TCCR1A = 0x00;
TCCR1B = 0x01;
/* Timer2 @ Clk/1024: Periodic clock */
TCCR2 = 0x07;
}
/*
Retrieve the current time from the global clock in Timer1,
disabling interrupts to avoid stomping on the TEMP register.
If interrupts are already off, the non_atomic form can be used.
*/
static inline uint16_t
timer_now( void )
{
return TCNT1;
}
static inline uint16_t
timer_now_non_atomic( void )
{
return TCNT1L;
}
/*
Periodic tasks occur when Timer2 overflows. Check and unset
the overflow bit. We cycle through four possible periodic states,
so each state occurs every 60 Hz.
*/
static inline bool_t
timer_periodic( void )
{
if ( !bit_is_set( TIFR, TOV2 ) )
return FALSE;
TIFR = 1 << TOV2;
return TRUE;
}
#endif

View File

@ -0,0 +1,133 @@
/*
Paparazzi $Id: uart.c,v 1.4 2011-01-25 10:17:46 plazar Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <arch/signal.h>
#include <arch/interrupt.h>
#include <arch/io.h>
#include "std.h"
#include "uart.h"
#define TX_BUF_SIZE 256
static uint8_t tx_head; /* next free in buf */
static volatile uint8_t tx_tail; /* next char to send */
static uint8_t tx_buf[ TX_BUF_SIZE ];
/*
UART Baud rate generation settings:
With 16.0 MHz clock,UBRR=25 => 38400 baud
*/
void uart_init_tx( void )
{
#ifndef WCET_ANALYSIS
/* Baudrate is 38.4k */
UBRRH = 0;
UBRRL = 25;
/* single speed */
UCSRA = 0;
/* Enable transmitter */
UCSRB = _BV( TXEN );
/* Set frame format: 8data, 1stop bit */
UCSRC = _BV( URSEL ) | _BV( UCSZ1 ) | _BV( UCSZ0 );
#endif
}
void uart_init_rx()
{
#ifndef WCET_ANALYSIS
/* Enable receiver */
UCSRB |= _BV( RXEN );
/* Enable uart receive interrupt */
sbi( UCSRB, RXCIE );
#endif
}
void uart_transmit( unsigned char data )
{
#ifndef WCET_ANALYSIS
if ( UCSRB & _BV( TXCIE ) ) {
/* we are waiting for the last char to be sent : buffering */
if ( tx_tail == tx_head + 1 ) { /* BUF_SIZE = 256 */
/* Buffer is full (almost, but tx_head = tx_tail means "empty" */
return;
}
tx_buf[ tx_head ] = data;
tx_head++; /* BUF_SIZE = 256 */
} else { /* Channel is free: just send */
UDR = data;
sbi( UCSRB, TXCIE );
}
#endif
}
void uart_print_hex ( uint8_t c )
{
#ifndef WCET_ANALYSIS
const uint8_t hex[ 16 ] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
uint8_t high = ( c & 0xF0 ) >> 4;
uint8_t low = c & 0x0F;
uart_transmit( hex[ high ] );
uart_transmit( hex[ low ] );
#endif
}
void uart_print_hex16 ( uint16_t c )
{
#ifndef WCET_ANALYSIS
uint8_t high = ( uint8_t )( c >> 8 );
uint8_t low = ( uint8_t )( c );
uart_print_hex( high );
uart_print_hex( low );
#endif
}
void uart_print_string( const uint8_t *s )
{
#ifndef WCET_ANALYSIS
uint8_t i = 0;
_Pragma( "loopbound min 100 max 100" )
while ( s[ i ] ) {
uart_transmit( s[ i ] );
i++;
}
#endif
}
SIGNAL( SIG_UART_TRANS )
{
#ifndef WCET_ANALYSIS
if ( tx_head == tx_tail ) {
/* Nothing more to send */
cbi( UCSRB, TXCIE ); /* disable interrupt */
} else {
UDR = tx_buf[ tx_tail ];
tx_tail++; /* warning tx_buf_len is 256 */
}
#endif
}

View File

@ -0,0 +1,39 @@
/*
Paparazzi $Id: uart.h,v 1.1 2011-01-18 12:42:42 moellmer Exp $
Copyright (C) 2003 Pascal Brisset, Antoine Drouin
This file is part of paparazzi.
paparazzi 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, or (at your option)
any later version.
paparazzi 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 paparazzi; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _UART_H_
#define _UART_H_
#include <inttypes.h>
void uart_init_tx( void );
void uart_init_rx( void );
void uart_transmit( unsigned char data );
void uart_print_hex ( uint8_t c );
void uart_print_hex16 ( uint16_t c );
void uart_print_string( const uint8_t *s );
void uart_print_float( const float *f );
#endif